{"id":610,"date":"2026-03-21T22:52:56","date_gmt":"2026-03-21T14:52:56","guid":{"rendered":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/gateway-openshell\/"},"modified":"2026-03-21T23:28:48","modified_gmt":"2026-03-21T15:28:48","slug":"gateway-openshell","status":"publish","type":"post","link":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/gateway-openshell\/","title":{"rendered":"OpenShell"},"content":{"rendered":"<h1>OpenShell<\/h1>\n<p>OpenShell is a managed sandbox backend for OpenClaw. Instead of running Docker<br \/>\ncontainers locally, OpenClaw delegates sandbox lifecycle to the <code>openshell<\/code> CLI,<br \/>\nwhich provisions remote environments with SSH-based command execution.<\/p>\n<p>The OpenShell plugin reuses the same core SSH transport and remote filesystem<br \/>\nbridge as the generic <a href=\"\/\u7f51\u5173\/sandboxing#ssh-backend\">SSH backend<\/a>. It adds<br \/>\nOpenShell-specific lifecycle (<code>sandbox create\/get\/delete<\/code>, <code>sandbox ssh-config<\/code>)<br \/>\nand an optional <code>mirror<\/code> workspace mode.<\/p>\n<h2>Prerequisites<\/h2>\n<ul>\n<li>The <code>openshell<\/code> CLI installed and on <code>PATH<\/code> (or set a custom path via<br \/>\n  <code>plugins.entries.openshell.config.command<\/code>)<\/li>\n<li>An OpenShell account with sandbox access<\/li>\n<li>OpenClaw Gateway \u7f51\u5173 running on the host<\/li>\n<\/ul>\n<h2>\u5feb\u901f\u5f00\u59cb<\/h2>\n<ol>\n<li>Enable the plugin and set the sandbox backend:<\/li>\n<\/ol>\n<p>&#8220;`json5  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  agents: {<br \/>\n    defaults: {<br \/>\n      sandbox: {<br \/>\n        mode: &#8220;all&#8221;,<br \/>\n        backend: &#8220;openshell&#8221;,<br \/>\n        scope: &#8220;session&#8221;,<br \/>\n        workspaceAccess: &#8220;rw&#8221;,<br \/>\n      },<br \/>\n    },<br \/>\n  },<br \/>\n  plugins: {<br \/>\n    entries: {<br \/>\n      openshell: {<br \/>\n        enabled: true,<br \/>\n        config: {<br \/>\n          from: &#8220;openclaw&#8221;,<br \/>\n          mode: &#8220;remote&#8221;,<br \/>\n        },<br \/>\n      },<br \/>\n    },<br \/>\n  },<br \/>\n}<\/p>\n<pre><code>\n2. Restart the Gateway. On the next agent turn, OpenClaw creates an OpenShell\n   sandbox and routes tool execution through it.\n\n3. Verify:\n\n```bash  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nopenclaw sandbox list\nopenclaw sandbox explain\n<\/code><\/pre>\n<h2>Workspace modes<\/h2>\n<p>This is the most important decision when using OpenShell.<\/p>\n<h3><code>mirror<\/code><\/h3>\n<p>Use <code>plugins.entries.openshell.config.mode: \"mirror\"<\/code> when you want the <strong>local<br \/>\nworkspace to stay canonical<\/strong>.<\/p>\n<p>Behavior:<\/p>\n<ul>\n<li>Before <code>exec<\/code>, OpenClaw syncs the local workspace into the OpenShell sandbox.<\/li>\n<li>After <code>exec<\/code>, OpenClaw syncs the remote workspace back to the local workspace.<\/li>\n<li>File tools still operate through the sandbox bridge, but the local workspace<br \/>\n  remains the source of truth between turns.<\/li>\n<\/ul>\n<p>Best for:<\/p>\n<ul>\n<li>You edit files locally outside OpenClaw and want those changes visible in the<br \/>\n  sandbox automatically.<\/li>\n<li>You want the OpenShell sandbox to behave as much like the Docker backend as<br \/>\n  possible.<\/li>\n<li>You want the host workspace to reflect sandbox writes after each exec turn.<\/li>\n<\/ul>\n<p>Tradeoff: extra sync cost before and after each exec.<\/p>\n<h3><code>remote<\/code><\/h3>\n<p>Use <code>plugins.entries.openshell.config.mode: \"remote\"<\/code> when you want the<br \/>\n<strong>OpenShell workspace to become canonical<\/strong>.<\/p>\n<p>Behavior:<\/p>\n<ul>\n<li>When the sandbox is first created, OpenClaw seeds the remote workspace from<br \/>\n  the local workspace once.<\/li>\n<li>After that, <code>exec<\/code>, <code>read<\/code>, <code>write<\/code>, <code>edit<\/code>, and <code>apply_patch<\/code> operate<br \/>\n  directly against the remote OpenShell workspace.<\/li>\n<li>OpenClaw does <strong>not<\/strong> sync remote changes back into the local workspace.<\/li>\n<li>Prompt-time media reads still work because file and media tools read through<br \/>\n  the sandbox bridge.<\/li>\n<\/ul>\n<p>Best for:<\/p>\n<ul>\n<li>The sandbox should live primarily on the remote side.<\/li>\n<li>You want lower per-turn sync overhead.<\/li>\n<li>You do not want host-local edits to silently overwrite remote sandbox state.<\/li>\n<\/ul>\n<p>\u91cd\u8981\u8bf4\u660e: if you edit files on the host outside OpenClaw after the initial seed,<br \/>\nthe remote sandbox does <strong>not<\/strong> see those changes. Use<br \/>\n<code>openclaw sandbox recreate<\/code> to re-seed.<\/p>\n<h3>Choosing a mode<\/h3>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th><code>mirror<\/code><\/th>\n<th><code>remote<\/code><\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>Canonical workspace<\/strong><\/td>\n<td>Local host<\/td>\n<td>Remote OpenShell<\/td>\n<\/tr>\n<tr>\n<td><strong>Sync direction<\/strong><\/td>\n<td>Bidirectional (each exec)<\/td>\n<td>One-time seed<\/td>\n<\/tr>\n<tr>\n<td><strong>Per-turn overhead<\/strong><\/td>\n<td>Higher (upload + download)<\/td>\n<td>Lower (direct remote ops)<\/td>\n<\/tr>\n<tr>\n<td><strong>Local edits visible?<\/strong><\/td>\n<td>Yes, on next exec<\/td>\n<td>No, until recreate<\/td>\n<\/tr>\n<tr>\n<td><strong>Best for<\/strong><\/td>\n<td>Development workflows<\/td>\n<td>Long-running agents, CI<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>\u914d\u7f6e\u8bf4\u660e reference<\/h2>\n<p>All OpenShell config lives under <code>plugins.entries.openshell.config<\/code>:<\/p>\n<table>\n<thead>\n<tr>\n<th>Key<\/th>\n<th>Type<\/th>\n<th>Default<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>mode<\/code><\/td>\n<td><code>\"mirror\"<\/code> or <code>\"remote\"<\/code><\/td>\n<td><code>\"mirror\"<\/code><\/td>\n<td>Workspace sync mode<\/td>\n<\/tr>\n<tr>\n<td><code>command<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td><code>\"openshell\"<\/code><\/td>\n<td>Path or name of the <code>openshell<\/code> CLI<\/td>\n<\/tr>\n<tr>\n<td><code>from<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td><code>\"openclaw\"<\/code><\/td>\n<td>Sandbox source for first-time create<\/td>\n<\/tr>\n<tr>\n<td><code>gateway<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td>\u2014<\/td>\n<td>OpenShell \u7f51\u5173 name (<code>--gateway<\/code>)<\/td>\n<\/tr>\n<tr>\n<td><code>gatewayEndpoint<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td>\u2014<\/td>\n<td>OpenShell \u7f51\u5173 endpoint URL (<code>--gateway-endpoint<\/code>)<\/td>\n<\/tr>\n<tr>\n<td><code>policy<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td>\u2014<\/td>\n<td>OpenShell policy ID for sandbox creation<\/td>\n<\/tr>\n<tr>\n<td><code>providers<\/code><\/td>\n<td><code>string[]<\/code><\/td>\n<td><code>[]<\/code><\/td>\n<td>Provider names to attach when sandbox is created<\/td>\n<\/tr>\n<tr>\n<td><code>gpu<\/code><\/td>\n<td><code>boolean<\/code><\/td>\n<td><code>false<\/code><\/td>\n<td>Request GPU resources<\/td>\n<\/tr>\n<tr>\n<td><code>autoProviders<\/code><\/td>\n<td><code>boolean<\/code><\/td>\n<td><code>true<\/code><\/td>\n<td>Pass <code>--auto-providers<\/code> during sandbox create<\/td>\n<\/tr>\n<tr>\n<td><code>remoteWorkspaceDir<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td><code>\"\/sandbox\"<\/code><\/td>\n<td>Primary writable workspace inside the sandbox<\/td>\n<\/tr>\n<tr>\n<td><code>remoteAgentWorkspaceDir<\/code><\/td>\n<td><code>string<\/code><\/td>\n<td><code>\"\/agent\"<\/code><\/td>\n<td>Agent workspace mount path (for read-only access)<\/td>\n<\/tr>\n<tr>\n<td><code>timeoutSeconds<\/code><\/td>\n<td><code>number<\/code><\/td>\n<td><code>120<\/code><\/td>\n<td>Timeout for <code>openshell<\/code> CLI operations<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Sandbox-level settings (<code>mode<\/code>, <code>scope<\/code>, <code>workspaceAccess<\/code>) are configured under<br \/>\n<code>agents.defaults.sandbox<\/code> as with any backend. See<br \/>\n<a href=\"https:\/\/pa.yingzhi8.cn\/?p=140\">Sandboxing<\/a> for the full matrix.<\/p>\n<h2>Examples<\/h2>\n<h3>Minimal remote setup<\/h3>\n<p>&#8220;`json5  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  agents: {<br \/>\n    defaults: {<br \/>\n      sandbox: {<br \/>\n        mode: &#8220;all&#8221;,<br \/>\n        backend: &#8220;openshell&#8221;,<br \/>\n      },<br \/>\n    },<br \/>\n  },<br \/>\n  plugins: {<br \/>\n    entries: {<br \/>\n      openshell: {<br \/>\n        enabled: true,<br \/>\n        config: {<br \/>\n          from: &#8220;openclaw&#8221;,<br \/>\n          mode: &#8220;remote&#8221;,<br \/>\n        },<br \/>\n      },<br \/>\n    },<br \/>\n  },<br \/>\n}<\/p>\n<pre><code>\n### Mirror mode with GPU\n\n```json5  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\n{\n  agents: {\n    defaults: {\n      sandbox: {\n        mode: &quot;all&quot;,\n        backend: &quot;openshell&quot;,\n        scope: &quot;agent&quot;,\n        workspaceAccess: &quot;rw&quot;,\n      },\n    },\n  },\n  plugins: {\n    entries: {\n      openshell: {\n        enabled: true,\n        config: {\n          from: &quot;openclaw&quot;,\n          mode: &quot;mirror&quot;,\n          gpu: true,\n          providers: [&quot;openai&quot;],\n          timeoutSeconds: 180,\n        },\n      },\n    },\n  },\n}\n<\/code><\/pre>\n<h3>Per-agent OpenShell with custom \u7f51\u5173<\/h3>\n<p>&#8220;`json5  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  agents: {<br \/>\n    defaults: {<br \/>\n      sandbox: { mode: &#8220;off&#8221; },<br \/>\n    },<br \/>\n    list: [<br \/>\n      {<br \/>\n        id: &#8220;researcher&#8221;,<br \/>\n        sandbox: {<br \/>\n          mode: &#8220;all&#8221;,<br \/>\n          backend: &#8220;openshell&#8221;,<br \/>\n          scope: &#8220;agent&#8221;,<br \/>\n          workspaceAccess: &#8220;rw&#8221;,<br \/>\n        },<br \/>\n      },<br \/>\n    ],<br \/>\n  },<br \/>\n  plugins: {<br \/>\n    entries: {<br \/>\n      openshell: {<br \/>\n        enabled: true,<br \/>\n        config: {<br \/>\n          from: &#8220;openclaw&#8221;,<br \/>\n          mode: &#8220;remote&#8221;,<br \/>\n          \u7f51\u5173: &#8220;lab&#8221;,<br \/>\n          \u7f51\u5173Endpoint: &#8220;https:\/\/lab.example&#8221;,<br \/>\n          policy: &#8220;strict&#8221;,<br \/>\n        },<br \/>\n      },<br \/>\n    },<br \/>\n  },<br \/>\n}<\/p>\n<pre><code>\n## Lifecycle management\n\nOpenShell sandboxes are managed through the normal sandbox CLI:\n\n```bash  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\n# List all sandbox runtimes (Docker + OpenShell)\nopenclaw sandbox list\n\n# Inspect effective policy\nopenclaw sandbox explain\n\n# Recreate (deletes remote workspace, re-seeds on next use)\nopenclaw sandbox recreate --all\n<\/code><\/pre>\n<p>For <code>remote<\/code> mode, <strong>recreate is especially important<\/strong>: it deletes the canonical<br \/>\nremote workspace for that scope. The next use seeds a fresh remote workspace from<br \/>\nthe local workspace.<\/p>\n<p>For <code>mirror<\/code> mode, recreate mainly resets the remote execution environment because<br \/>\nthe local workspace remains canonical.<\/p>\n<h3>When to recreate<\/h3>\n<p>Recreate after changing any of these:<\/p>\n<ul>\n<li><code>agents.defaults.sandbox.backend<\/code><\/li>\n<li><code>plugins.entries.openshell.config.from<\/code><\/li>\n<li><code>plugins.entries.openshell.config.mode<\/code><\/li>\n<li><code>plugins.entries.openshell.config.policy<\/code><\/li>\n<\/ul>\n<p><code>bash  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}<br \/>\nopenclaw sandbox recreate --all<\/code><\/p>\n<h2>Current limitations<\/h2>\n<ul>\n<li>Sandbox browser is not supported on the OpenShell backend.<\/li>\n<li><code>sandbox.docker.binds<\/code> does not apply to OpenShell.<\/li>\n<li>Docker-specific runtime knobs under <code>sandbox.docker.*<\/code> apply only to the Docker<br \/>\n  backend.<\/li>\n<\/ul>\n<h2>How it works<\/h2>\n<ol>\n<li>OpenClaw calls <code>openshell sandbox create<\/code> (with <code>--from<\/code>, <code>--gateway<\/code>,<br \/>\n   <code>--policy<\/code>, <code>--providers<\/code>, <code>--gpu<\/code> flags as configured).<\/li>\n<li>OpenClaw calls <code>openshell sandbox ssh-config &lt;name&gt;<\/code> to get SSH connection<br \/>\n   details for the sandbox.<\/li>\n<li>Core writes the SSH config to a temp file and opens an SSH session using the<br \/>\n   same remote filesystem bridge as the generic SSH backend.<\/li>\n<li>In <code>mirror<\/code> mode: sync local to remote before exec, run, sync back after exec.<\/li>\n<li>In <code>remote<\/code> mode: seed once on create, then operate directly on the remote<br \/>\n   workspace.<\/li>\n<\/ol>\n<h2>See also<\/h2>\n<ul>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=140\">Sandboxing<\/a> &#8212; modes, scopes, and backend comparison<\/li>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=139\">Sandbox vs Tool Policy vs Elevated<\/a> &#8212; debugging blocked tools<\/li>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=288\">Multi-Agent Sandbox and Tools<\/a> &#8212; per-agent overrides<\/li>\n<li><a href=\"https:\/\/pa.yingzhi8.cn\/?p=73\">Sandbox CLI<\/a> &#8212; <code>openclaw sandbox<\/code> commands<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>OpenShell OpenShell is a managed sandbox backend for Op [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-610","post","type-post","status-publish","format-standard","hentry","category-docs"],"_links":{"self":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/610","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/comments?post=610"}],"version-history":[{"count":3,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/610\/revisions"}],"predecessor-version":[{"id":811,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/610\/revisions\/811"}],"wp:attachment":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/media?parent=610"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/categories?post=610"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/tags?post=610"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}