Files
adolf/docs/gateway/openshell.md
alvis bedb527145
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Vendor OpenClaw source as Adolf fork baseline
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11),
free to diverge. Tree copied sans upstream .git; upstream remote added for
future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19.
Preserves docs/ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
2026-07-05 09:36:54 +00:00

299 lines
10 KiB
Markdown

---
summary: "Use OpenShell as a managed sandbox backend for OpenClaw agents"
title: OpenShell
read_when:
- You want cloud-managed sandboxes instead of local Docker
- You are setting up the OpenShell plugin
- You need to choose between mirror and remote workspace modes
---
OpenShell is a managed sandbox backend: instead of running Docker containers
locally, OpenClaw delegates sandbox lifecycle to the `openshell` CLI, which
provisions remote environments and executes commands over SSH.
The plugin reuses the same SSH transport and remote filesystem bridge as the
generic [SSH backend](/gateway/sandboxing#ssh-backend), and adds OpenShell
lifecycle (`sandbox create/get/delete/ssh-config`) plus an optional `mirror`
workspace sync mode.
## Prerequisites
- OpenShell plugin installed (`openclaw plugins install @openclaw/openshell-sandbox`)
- `openshell` CLI on `PATH` (or a custom path via
`plugins.entries.openshell.config.command`)
- An OpenShell account with sandbox access
- OpenClaw Gateway running on the host
## Quick start
```bash
openclaw plugins install @openclaw/openshell-sandbox
```
```json5
{
agents: {
defaults: {
sandbox: {
mode: "all",
backend: "openshell",
scope: "session",
workspaceAccess: "rw",
},
},
},
plugins: {
entries: {
openshell: {
enabled: true,
config: {
from: "openclaw",
mode: "remote",
},
},
},
},
}
```
Restart the Gateway. On the next agent turn OpenClaw creates an OpenShell
sandbox and routes tool execution through it. Verify with:
```bash
openclaw sandbox list
openclaw sandbox explain
```
## Workspace modes
This is the most important OpenShell decision.
### mirror (default)
`plugins.entries.openshell.config.mode: "mirror"` keeps the **local workspace
canonical**:
- Before `exec`, OpenClaw syncs the local workspace into the sandbox.
- After `exec`, OpenClaw syncs the remote workspace back to local.
- File tools go through the sandbox bridge, but local stays source of truth
between turns.
Best for development workflows: local edits outside OpenClaw show up on the
next exec, and the sandbox behaves close to the Docker backend.
Tradeoff: upload + download cost on every exec turn.
### remote
`mode: "remote"` makes the **OpenShell workspace canonical**:
- On first sandbox creation, OpenClaw seeds the remote workspace from local
once.
- After that, `exec`, `read`, `write`, `edit`, and `apply_patch` operate
directly on the remote workspace. OpenClaw does **not** sync remote changes
back to local.
- Prompt-time media reads still work (file/media tools read through the
sandbox bridge).
Best for long-running agents and CI: lower per-turn overhead, and host-local
edits cannot silently clobber remote state.
<Warning>
Editing files on the host outside OpenClaw after the initial seed is invisible to the remote sandbox. Run `openclaw sandbox recreate` to re-seed.
</Warning>
### Choosing a mode
| | `mirror` | `remote` |
| ------------------------ | -------------------------- | ------------------------- |
| **Canonical workspace** | Local host | Remote OpenShell |
| **Sync direction** | Bidirectional (every exec) | One-time seed |
| **Per-turn overhead** | Higher (upload + download) | Lower (direct remote ops) |
| **Local edits visible?** | Yes, on next exec | No, until recreate |
| **Best for** | Development workflows | Long-running agents, CI |
## Configuration reference
All OpenShell config lives under `plugins.entries.openshell.config`:
| Key | Type | Default | Description |
| ------------------------- | ------------------------ | ------------- | -------------------------------------------------------------------------------------- |
| `mode` | `"mirror"` or `"remote"` | `"mirror"` | Workspace sync mode |
| `command` | `string` | `"openshell"` | Path or name of the `openshell` CLI |
| `from` | `string` | `"openclaw"` | Sandbox source for first-time create |
| `gateway` | `string` | unset | OpenShell gateway name (top-level `--gateway`) |
| `gatewayEndpoint` | `string` | unset | OpenShell gateway endpoint (top-level `--gateway-endpoint`) |
| `policy` | `string` | unset | OpenShell policy ID for sandbox creation |
| `providers` | `string[]` | `[]` | Provider names attached at sandbox creation (deduped, one `--provider` flag per entry) |
| `gpu` | `boolean` | `false` | Request GPU resources (`--gpu`) |
| `autoProviders` | `boolean` | `true` | Pass `--auto-providers` (or `--no-auto-providers` when false) during create |
| `remoteWorkspaceDir` | `string` | `"/sandbox"` | Primary writable workspace inside the sandbox |
| `remoteAgentWorkspaceDir` | `string` | `"/agent"` | Agent workspace mount path (read-only when workspace access is not `rw`) |
| `timeoutSeconds` | `number` | `120` | Timeout for `openshell` CLI operations |
`remoteWorkspaceDir` and `remoteAgentWorkspaceDir` must be absolute paths and
stay under the managed roots `/sandbox` or `/agent`; other absolute paths are
rejected.
Sandbox-level settings (`mode`, `scope`, `workspaceAccess`) live under
`agents.defaults.sandbox` like any backend. See
[Sandboxing](/gateway/sandboxing) for the full matrix.
## Examples
### Minimal remote setup
```json5
{
agents: {
defaults: {
sandbox: {
mode: "all",
backend: "openshell",
},
},
},
plugins: {
entries: {
openshell: {
enabled: true,
config: {
from: "openclaw",
mode: "remote",
},
},
},
},
}
```
### Mirror mode with GPU
```json5
{
agents: {
defaults: {
sandbox: {
mode: "all",
backend: "openshell",
scope: "agent",
workspaceAccess: "rw",
},
},
},
plugins: {
entries: {
openshell: {
enabled: true,
config: {
from: "openclaw",
mode: "mirror",
gpu: true,
providers: ["openai"],
timeoutSeconds: 180,
},
},
},
},
}
```
### Per-agent OpenShell with custom gateway
```json5
{
agents: {
defaults: {
sandbox: { mode: "off" },
},
list: [
{
id: "researcher",
sandbox: {
mode: "all",
backend: "openshell",
scope: "agent",
workspaceAccess: "rw",
},
},
],
},
plugins: {
entries: {
openshell: {
enabled: true,
config: {
from: "openclaw",
mode: "remote",
gateway: "lab",
gatewayEndpoint: "https://lab.example",
policy: "strict",
},
},
},
},
}
```
## Lifecycle management
```bash
# List all sandbox runtimes (Docker + OpenShell)
openclaw sandbox list
# Inspect effective policy
openclaw sandbox explain
# Recreate (deletes remote workspace, re-seeds on next use)
openclaw sandbox recreate --all
```
For `remote` mode, recreate is especially important: it deletes the canonical
remote workspace for that scope, and the next use seeds a fresh one from
local. For `mirror` mode, recreate mainly resets the remote execution
environment since local stays canonical.
Recreate after changing any of:
- `agents.defaults.sandbox.backend`
- `plugins.entries.openshell.config.from`
- `plugins.entries.openshell.config.mode`
- `plugins.entries.openshell.config.policy`
## Security hardening
The mirror-mode filesystem bridge pins the local workspace root and rechecks
canonical paths (via realpath) before every read, write, mkdir, remove, and
rename, rejecting mid-path symlinks. A symlink swap or remounted workspace
cannot redirect file access outside the mirrored tree.
## Current limitations
- Sandbox browser is not supported on the OpenShell backend.
- `sandbox.docker.binds` does not apply to OpenShell; sandbox creation fails
if binds are configured.
- Docker-specific runtime knobs under `sandbox.docker.*` (other than `env`)
apply only to the Docker backend.
## How it works
1. OpenClaw runs `sandbox get` for the sandbox name (with any configured
`--gateway`/`--gateway-endpoint`); if that fails it creates one with
`sandbox create`, passing `--name`, `--from`, `--policy` when set, `--gpu`
when enabled, `--auto-providers`/`--no-auto-providers`, and one
`--provider` flag per configured provider.
2. OpenClaw runs `sandbox ssh-config` for the sandbox name to fetch SSH
connection details.
3. Core writes the SSH config to a temp file and opens an SSH session through
the same remote filesystem bridge as the generic SSH backend.
4. In `mirror` mode: sync local to remote before exec, run, sync back after.
5. In `remote` mode: seed once on create, then operate directly on the remote
workspace.
## Related
- [Sandboxing](/gateway/sandboxing) - modes, scopes, and backend comparison
- [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) - debugging blocked tools
- [Multi-Agent Sandbox and Tools](/tools/multi-agent-sandbox-tools) - per-agent overrides
- [Sandbox CLI](/cli/sandbox) - `openclaw sandbox` commands