Sandbox CLI
Every defenseclaw sandbox command and flag for NVIDIA OpenShell sandboxes, with an example for each. Covers setup and doctor, run and connect, the activity feed and asks, undo, review and pull, policy and packs, images, wrappers, and teardown.
defenseclaw sandbox runs Claude Code, Codex, and other hook-based coding
agents in NVIDIA OpenShell 0.1 sandboxes on Linux, and on Macs with Apple
silicon in OpenShell MicroVMs, where every run works on a copy (see
macOS). This page lists every
sandbox command and flag; see also Sandbox.
Packs and organization limits are covered in
Sandbox policy packs and admin controls, and
the openshell: keys in
Configuration.
The flag tables are generated from the defenseclaw-gateway sandbox command
tree, and a test keeps them in step with it. defenseclaw sandbox <command> --help prints the same flags.
How the commands run
- One entry point. Type
defenseclaw sandbox …. The Python CLI checks the command line against the same commands and flags, then replaces itself withdefenseclaw-gateway sandbox …and passes your arguments on exactly as typed.legacy-cleanupis the only command the Python CLI runs itself. - Linux and macOS only. On Windows every command except
legacy-cleanupstops with exit status 3 before doing anything;legacy-cleanupstops with status 1.setup,run,image build, andenablealso stop with status 3 under WSL2, in amanaged_enterpriseinstall, and when run as root: sandboxes run as your own user.teardownalso stops with status 3 in amanaged_enterpriseinstall. On a Mac sandboxes run in OpenShell MicroVMs, on Apple silicon only: on an Intel Mac every command exceptteardownandlegacy-cleanupstops with exit status 3. A MicroVM mounts no host folders, so every run on a Mac works on a copy (see macOS). - The daemon does the work. Commands that create, change, or read
sandboxes call the DefenseClaw daemon's
sandbox API on the main API
port, using the gateway token. The daemon runs them only while
openshell.enabledistrue, whichsandbox setupturns on. The CLI keeps the terminal, the copy-mode workspace, the image builds, and the installer.pack,image,enable,disable, anddoctorwork without the daemon. - Harness names. A harness can be named by the command you type
(
claude,codex,opencode,copilot,kiro-cli-chat,hermes,openhands,omnigent,agy,amp,cursor-agent,devin), by its connector name (claudecode,kiro,antigravity), or by its display name. Help and hints name Kiro and Antigravity by their connector names, asimage buildandimage listdo. Setup and the image commands default toopenshell.harnesses, and then to Claude Code and Codex;image rmremoves only the harnesses you name. Amp, Cursor Agent, and Devin CLI are not verified end to end yet: their images build, but they never pass the hook check, so no sandbox runs them. The capability matrix says why for each harness. - Sandbox names. A name is lowercase letters, digits, and
-, at most 19 characters: OpenShell 0.1.1 refuses to create a sandbox with a longer name. Without--name,runpicks<folder>-<random>, the folder name cut to fit, for examplemyapp-7f3a. The harness is a label on the sandbox, not part of its name, andsandbox listshows both. - Output. Commands with
-o, --outputprinttext(the default) orjson. - Exit status.
0on success and1on an error.runandconnectreturn the exit status of the harness, andexecthat of its command (connect --shellexits0when the shell ends). When the harness exits0but not one of the session's hooks reached DefenseClaw, so that every tool call was blocked,runandconnectexit69. A harness that sends its first hook only with your first prompt (Kiro CLI, Hermes Agent, Antigravity, OpenHands, OmniGent, GitHub Copilot CLI) and was never prompted is not counted, unless the daemon saw it work without hooks.logsdoes the same when it reports a finished detached run none of whose hooks reached DefenseClaw.pull --applyexits4when it could not merge in place (a conflict, or git older than 2.38) and left your working tree alone: the changes went to a patch file and, in a git project, to adc/<name>branch instead. An interrupted command returns130(Ctrl-C at the end-of-session question too), and an unsupported platform or setup (an Intel Mac included) returns3.
| Command | What it does |
|---|---|
sandbox setup | One-time setup: OpenShell, bind mounts, telemetry, harnesses, wrappers, and images. |
sandbox doctor | Check that this machine can run sandboxes. |
sandbox image | Build, list, prune, and remove the harness images. |
sandbox enable, disable | Add or remove the shell wrapper that runs a harness command in a sandbox. |
sandbox teardown | Remove everything DefenseClaw set up for sandboxes. |
sandbox run | Run a harness in a new sandbox on the current folder. |
sandbox connect | Resume a sandbox and attach the harness, or a shell. |
sandbox exec | Run one command in a sandbox. |
sandbox logs | Show the output of a detached run. |
sandbox list, status | List sandboxes, or show one in detail. |
sandbox stop, start, delete | Stop, start, or delete sandboxes. |
sandbox activity | The live activity feed. |
sandbox approvals, approve, reject | The asks waiting for you, and your answers. |
sandbox unblock | Lift an egress block. |
sandbox review, undo | Review a mounted project's changes, or restore its undo point. |
sandbox pull | Bring a copy-mode sandbox's work back. |
sandbox policy | Show, explain, suggest, and edit the sandbox policy. |
sandbox pack | List, show, and validate policy packs. |
sandbox legacy-cleanup | Remove a retired openshell-sandbox 0.0.x install. |
Set up and maintain
sandbox setup
One-time setup. It checks this machine and installs OpenShell with NVIDIA's
installer when you agree (sudo, sha256-verified). On Linux it enables
project-folder bind mounts on your local OpenShell gateway, backing up the
gateway config so that teardown can restore it, and turns OpenShell's
anonymous usage telemetry off unless you keep it. On a Mac it installs
OpenShell's Homebrew formula (and e2fsprogs, with the same consent) and
asks instead whether to run sandboxes in OpenShell MicroVMs: yes switches the
gateway to the MicroVM driver and sets its sandbox identity to your uid and
gid, in one backed-up change with one restart. It then records the harnesses
in openshell.harnesses, sets openshell.enabled: true, offers the shell
wrappers and builds the harness images (the first build downloads about
3 GB).
defenseclaw sandbox setup
defenseclaw sandbox setup --harness claude --harness codex --wrappers
defenseclaw sandbox setup --non-interactive --skip-images| Flag | Takes | Default | Description |
|---|---|---|---|
--harness | text, repeatable or comma-separated | Harness to set up, added to openshell.harnesses (repeatable; default: openshell.harnesses, else claude and codex). | |
--install-openshell | switch | Install OpenShell with NVIDIA's pinned, sha256-verified installer (uses sudo). | |
--no-mounts | switch | Leave bind mounts off (Linux); every run then works on a copy. | |
--no-wrappers | switch | Do not offer the shell wrappers. | |
--non-interactive | switch | Never prompt: take the defaults and skip steps that need consent. | |
--restart-gateway | switch | Restart the OpenShell gateway to apply its configuration even while sandboxes run on it. | |
--skip-images | switch | Do not build the harness images now (the first run builds them). | |
--upstream-telemetry | switch | Keep OpenShell's anonymous usage telemetry on. | |
--wrappers | switch | Make the harness commands run sandboxed without asking. | |
-y, --yes | switch | Answer every question with its default. |
sandbox doctor
Checks the platform, Landlock, Docker, the OpenShell service, CLI,
registration, version and compute driver, bind mounts, telemetry, ports, the
DefenseClaw daemon, harness images, shell wrappers, and the organization
policy. On a Mac it checks the MicroVM driver too (e2fsprogs and the
driver's Hypervisor signature, the sandbox identity, the gateway-wide
resources and the disk of its prepared images) and skips the checks that
only matter for the Docker driver, with the reason. While the
daemon serves sandboxes, it also checks that the hooks of running sandboxes
reach DefenseClaw, and fails when a sandbox's hooks don't. Each failed check
names its fix. --fix applies the fixes it can make as your user, after
asking. Doctor exits 1 when a check fails. With --output json it prints the
result and exits 0, so read the ok field instead. When sandboxes are on
(openshell.enabled: true), defenseclaw doctor shows the same checks in its
Sandbox section; otherwise that section is one skipped row.
defenseclaw sandbox doctor
defenseclaw sandbox doctor --fix
defenseclaw sandbox doctor --output json| Flag | Takes | Default | Description |
|---|---|---|---|
--fix | switch | Apply the fixes doctor can make as your user (asks first). | |
--json | switch | Same as --output json. | |
-o, --output | text | text | Output format: text or json. |
-y, --yes | switch | Apply fixes without asking. |
sandbox image
The harness images are a local DefenseClaw layer on a digest-pinned NVIDIA OpenShell community base. The layer holds the harness at DefenseClaw's reviewed version, root-owned hooks, and the harness's hook configuration. An image is used only after its hooks pass a live check: they fire, a blocked tool call has no effect, and an allowed one runs.
defenseclaw sandbox image list| Subcommand | Purpose |
|---|---|
sandbox image build | Build and hook-verify harness images (default: the configured harnesses). |
sandbox image list | List the harness images. |
sandbox image prune | Remove superseded harness images. |
sandbox image rm | Remove the harnesses' images (on a Mac also their MicroVM disks). |
sandbox image build
Builds and hook-checks the images of the named harnesses, or of
openshell.harnesses (then Claude Code and Codex) when you name none. A
current, checked image is kept unless you pass --force. The build log is
written to <data_dir>/logs/sandbox-image-<harness>.log. Some builds are
refused before docker runs: an openshell.image.harness_versions pin that is
not an exact release, a pin with no reviewed hook contract for sandboxes, or a
docker without BuildKit. Such a refusal says only why. It starts no build and
keeps the previous build's log. On a MicroVM gateway
it warns after a build when the volume of the driver's image cache lacks the
room the first start of the new image needs (see sandbox run).
defenseclaw sandbox image build
defenseclaw sandbox image build codex --force --verbose| Flag | Takes | Default | Description |
|---|---|---|---|
--force | switch | Rebuild even when a verified image is current. | |
--verbose | switch | Stream the docker build output. |
sandbox image list
Lists the recorded harness images, newest first. An image removed from Docker
(with docker rmi, say) is not in the table: a note names it, the next run of
its harness builds the image again, and sandbox image prune forgets its
record. The FOR column says which compute driver an image is for: MicroVM
for the vm driver (a Mac's gateway), docker for the docker driver. Images
recorded before DefenseClaw built MicroVM images are docker. A gateway boots
only the images for its driver, and when the list can tell which driver that
is, a note names the images the gateway does not use. The doctor does not
count those as built, and on a MicroVM gateway sandbox image prune removes
them. With --output json every recorded image is listed, with
"microvm": true for a MicroVM image, and one Docker no longer has carries
"missing": true.
defenseclaw sandbox image list --output json| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
sandbox image prune
Removes superseded harness images. It keeps the current images and the images
the daemon's sandboxes run, and leaves images that another DefenseClaw data
directory recorded, or that nothing recorded. It forgets, and names, the
records of images Docker no longer has. On a MicroVM (vm) gateway it
also removes the run images and aliases of superseded harness images, and only
while the daemon answers: without its list of sandboxes it leaves them alone.
With that list, a MicroVM gateway's prune also counts every harness image built
for the docker driver as superseded, however new it is (images recorded before
DefenseClaw built MicroVM images are such images). Such an image goes with its
run images and aliases unless a sandbox runs it. A docker gateway's prune, or
one that cannot tell which driver the gateway runs, keeps the newest image of
both kinds. With that list it also removes the MicroVM disk OpenShell prepared from each
image it removed (about 5 GB each, in the images folder of the MicroVM
driver's state directory, ~/.local/state/openshell/vm-driver by default) and
says how much it freed. It removes a disk only when Docker no longer has its
image and no sandbox is recorded with that image, and it never removes the
driver's other state there. --dry-run says which disks it would remove. A
start of an image whose disk is gone prepares it again (about a minute).
defenseclaw sandbox image prune --dry-run| Flag | Takes | Default | Description |
|---|---|---|---|
--dry-run | switch | Only show what would be removed. |
sandbox image rm
Removes the images this data directory recorded for the named harnesses,
current ones included, and forgets their records: the harness image and, on a
MicroVM (vm) gateway, the run images and aliases made from it. For an image
already removed from Docker (with docker rmi, say) only the record goes. On
a Mac it also removes the MicroVM disks OpenShell prepared from these images
(about 5 GB each), by the rules of sandbox image prune: only
sandbox-prepared-rootfs-* directories of image IDs Docker no longer has, and
only with the daemon's list of sandboxes. When the daemon does not answer and
such disks exist, it refuses and removes nothing, so that no disk is left
that no command would remove later. It also refuses, removing nothing, while a
sandbox uses one of the images (running, stopped, or only recorded), and names
it: delete that sandbox first. A sandbox deleted with --keep-snapshot uses
none. It shows what it removes and asks first; --yes does not ask, and
--dry-run only shows. The next run of the harness builds its image again.
defenseclaw sandbox image rm claude --dry-run
defenseclaw sandbox image rm kiro opencode --yes| Flag | Takes | Default | Description |
|---|---|---|---|
--dry-run | switch | Only show what would be removed. | |
-y, --yes | switch | Do not ask. |
sandbox enable
Makes typing the harness command run it in a sandbox. It writes a marked block
to your shell's rc file (~/.bashrc, ~/.zshrc or $ZDOTDIR/.zshrc, or
~/.config/fish/config.fish, which is $XDG_CONFIG_HOME/fish/config.fish
when XDG_CONFIG_HOME is set). The block defines a shell function named after
the command that runs sandbox run <harness> with your arguments after --.
The harness is also recorded in openshell.wrappers. New shells pick the
block up. To skip the sandbox for one call, run the command with
DEFENSECLAW_NO_SANDBOX=1 set. Inside a sandbox the function runs the harness
directly. The bash and zsh block first drops an alias of the same name (Claude
Code's installer adds one), which would otherwise keep running the harness
outside the sandbox, and drops it again just before the first prompt, in case
an installer or a file your rc sources defines one after the block. --version, --help and the harness's own management
commands (claude mcp add|list|…, claude config, claude update,
claude setup-token, codex login, codex mcp …) start no agent, so they
run with the harness installed on this machine. Nothing outside the block
changes, and removing the last wrapper removes the block. An --rc file is
recorded, so disable, doctor and teardown find it again.
defenseclaw sandbox enable claude
defenseclaw sandbox enable codex --shell zsh| Flag | Takes | Default | Description |
|---|---|---|---|
--rc | text | Rc file to edit (default: the shell's). | |
--shell | text | Bash, zsh or fish (default: $SHELL). |
sandbox disable
Removes the harness's wrapper block. Without --shell or --rc, it removes
the block from the rc files of bash, zsh, and fish, and from every --rc file
enable wrote.
defenseclaw sandbox disable claude| Flag | Takes | Default | Description |
|---|---|---|---|
--rc | text | Rc file to edit (default: the shell's). | |
--shell | text | Bash, zsh or fish (default: $SHELL). |
sandbox teardown
Deletes DefenseClaw's sandboxes, its OpenShell providers, and its harness
images. Provider profiles are shared by every DefenseClaw data directory on
the OpenShell gateway, and teardown removes each DefenseClaw profile that no
remaining provider uses: this data directory's ingress profiles, the legacy
defenseclaw-ingress profile, and the shared model-credential and
--credential profiles, including ones another DefenseClaw data directory
imported. The daemons import them again when they need them. Another daemon's
ingress profile is never removed. With the images it removes the MicroVM
disks OpenShell prepared from them, once no sandbox that could boot one is
left, as sandbox image prune does. Teardown restores the OpenShell gateway
config that setup changed, unless the file changed since. It also removes the
shell wrappers and sets openshell.enabled: false. OpenShell itself stays
installed. defenseclaw uninstall runs teardown for you. It works without a
DefenseClaw config, so it can clean up a half-installed host.
defenseclaw sandbox teardown --dry-run
defenseclaw sandbox teardown --yes --keep-images| Flag | Takes | Default | Description |
|---|---|---|---|
--dry-run | switch | Only show what would be removed. | |
--keep-images | switch | Keep the harness images. | |
-y, --yes | switch | Do not ask. |
Run and manage sandboxes
sandbox run
Runs a harness in a new sandbox on the current folder. On Linux (OpenShell's
Docker driver) the folder is mounted live by default, secret files are
masked, .git/hooks and .git/config are read-only, and a snapshot is taken
first so that undo can restore the folder. --copy works on a copy with
secrets held back instead, and you bring its work back with pull. On a Mac
(OpenShell's MicroVM driver, which mounts no host folders) every run works
on a copy, and run says so in one line before it copies anything.
Skip-permissions mode is on by default, and --safe keeps the harness's own
prompts. The harness gets your terminal. Arguments after -- go to the
harness.
While the harness runs, the session announces what can't wait: each ask (a
port on your machine, a private address, a destination the profile does not
list) with its destination and the sandbox approve command that answers it
from another terminal (or defenseclaw tui, key 7, then t for the Asks
view); a destination DefenseClaw blocked, with the sandbox unblock command
that lifts the block; a large upload the block did not cut (⚠ large upload to files.example.net (more than 25 MiB), with the block off or for a
destination exempt from it); a finding such as an alert on a tool call or
hook tamper; a quarantined nested repository; and a DefenseClaw daemon that
does not answer (the hooks fail closed until it is back). The harness draws
its own screen, so these notices go to the terminal's title and, where the
terminal has them, a desktop notification, and ring the bell, instead of
lines written over it. A harness that sets the title itself (Claude Code
does) takes it back at once, so the end-of-session summary repeats them.
Without a terminal (--prompt), they are lines on standard error. A
harness that sends its first hook only with your first prompt is not
warned about while it waits for one.
Before the harness runs (while the image, the sandbox and a copy are set
up), Ctrl-C, a closed terminal window or a kill of the CLI end the run and
delete the sandbox it created. At a question at the end of the session they
leave the changes where they are (kept in the folder, or in a copy-mode
sandbox for pull) and the session still ends as below; a second Ctrl-C
ends the CLI at once. run then exits with status 130.
When the harness exits (Ctrl-C, a closed terminal window or a kill of the
CLI end the harness, not the session), the sandbox the session started is
stopped first, so nothing it left running changes the folder after the
review. If the sandbox was stopped, undone or deleted from elsewhere (another
terminal, the TUI), which ends the harness, the summary starts by saying so.
You then get a summary line: tool calls and blocks (the blocking rule's
title and ID), new sites contacted and sites blocked (destinations, each
counted once; the blocked ones are the ✗ lines that follow, invalid
destinations included), and files changed,
followed by the session's notices. Changes that can run code on your machine
are called out, and asks still waiting are named. For a mounted folder you
then keep the changes, undo them, or see the diff first (a letter, then
Enter; a long diff opens in $PAGER, by default less), and a kept change
is confirmed (openshell.workdir.on_exit can decide for you). Ctrl-C at
that question decides nothing: the changes stay, the undo point is kept for
undo, the sandbox is stopped and kept, and the command exits 130.
Otherwise, without a terminal or with --yes, a mounted folder keeps them.
When the review fails, you are still asked, and --rm keeps the undo point.
--rm also keeps it when nobody accepted the changes (no terminal and no
--yes), so sandbox undo still reverts them; sandbox delete drops it.
In copy mode you apply them (3-way), put them on branch dc/<name>, write a
patch, or skip, which leaves them in the sandbox for pull. Without a
terminal, or with --yes, copy mode skips: nothing is applied, and the end
says how many files changed and names the sandbox pull that brings them
back. The sandbox is then stopped and kept for connect, unless you passed
--rm. In copy mode --rm is not honored while changes are left in the
sandbox (you skipped, declined changes that can run code on your machine, or
the pull or apply failed), so they aren't lost, and the end says so. A pull
that fails because the disk is full says whose disk: this machine's, or on a
Mac the MicroVM's own (overlay_disk_mib).
A kept sandbox's resume line is followed, last, by the command that
continues the same conversation inside the sandbox, for every harness that
can continue one: → continue this conversation: defenseclaw sandbox connect myapp-7f3a -- --continue for Claude Code, OpenCode, GitHub Copilot CLI,
Hermes Agent and OmniGent, -- resume --last for Codex, -- --resume for
Kiro CLI, -- --resume --last for OpenHands and -- -c for Antigravity. A
plain connect starts a new conversation. The resume line the harness itself
prints as it exits (claude --resume <id>, codex resume <id>,
opencode -s <id>, copilot --resume=<id>, kiro-cli --resume-id <id>,
hermes --resume <id>,
openhands --resume <id>, omnigent run … --resume <id>,
agy --conversation=<id>) works only inside the sandbox, where the
conversation is: typed on this machine it does not reach it, unless the
shell wrapper is on
(sandbox enable) for that command, which sends it into the folder's
sandbox. DefenseClaw cannot keep that line off the screen, so its own line
says so. After a session with no tool call it does not say the harness
printed one: GitHub Copilot CLI, for one, prints its line only after a
prompt. To resume a particular conversation, pass the harness's own flag
and ID after --: defenseclaw sandbox connect myapp-7f3a -- --resume <id>.
When you run interactively without --name and this folder already has a
sandbox of the same harness, run offers to resume it; --new starts
another one instead. A resumed sandbox keeps the settings it was created
with, so when you pass flags only a new sandbox takes (--safe, --pack,
--credential, --env and the like) and the sandbox doesn't already have
them, the offer names them and defaults to no. It keeps its credential
bindings and host ports too: the offer names those this run did not ask for
and defaults to no, and the banner and sandbox status NAME show the
sandbox's own. Typing the run's own command again is a plain resume. A sandbox the current policy would not start (a
live mount your organization now runs on a copy, a harness it no longer
allows) is not offered: run names it and the sandbox delete command,
and status and connect say the same. Only one sandbox can mount a
folder live, so while any sandbox that mounts the folder exists (even
stopped), a new live run there is refused. In a terminal, run names that
sandbox, its phase and the sandbox connect and sandbox delete commands,
then asks whether to work on a copy (the default), delete it first, or quit;
without a terminal, use --copy, or delete the other sandbox first. Inside a sandbox, sandbox run <harness> runs the
harness directly.
run remembers, for the sandbox it created, the harness options after
-- (not a prompt), the --credential names and hosts, the --env names
and the banner's model line; secret values are never kept. The options
stop at the first word that is not one, except for OmniGent, whose every
argument is kept in order (the agent path included), an OpenCode project
path, and Hermes's chat. connect, and a shell wrapper's resume, pass
those options again before any new ones, and show the same Model and Secret
lines as the run.
defenseclaw sandbox run claude
defenseclaw sandbox run codex --copy --name fix-tests
defenseclaw sandbox run claude --detach --prompt "fix the failing tests"
defenseclaw sandbox run claude --credential STRIPE_API_KEY=api.stripe.com -- --model sonnet
defenseclaw sandbox run claude --profile balanced --context ~/code/shared-lib --host-port 5432A few rules the flags follow:
--detachneeds a prompt:--prompt TEXT, or the harness's own print mode after--(for example-- -p "TEXT"for Claude Code or-- exec "TEXT"for Codex). It can't be combined with--rm. Follow the run withsandbox logs -f.- Without a terminal,
runneeds--prompt. - A headless run in the foreground (
--prompt, or the harness's print flag after--, as the shell wrapper'sclaude -ppasses it) deletes the sandbox it created when it ends, by the rules of--rm: a mounted folder's undo point stays when nobody kept the changes, and a copy whose work was not brought back keeps its sandbox.--keep, oropenshell.keep_headless: true, keeps it;--keepwith--rmis refused. Interactive sessions,--detachruns and a run that resumes this folder's sandbox keep theirs. --llm autoshares the first model credential it finds for the harness. For Claude Code that isANTHROPIC_API_KEY, thenCLAUDE_CODE_OAUTH_TOKEN. For Codex it isOPENAI_API_KEY(orCODEX_API_KEY), then the API key thatcodex login --with-api-keysaved in~/.codex/auth.json; a ChatGPT login is not shared. An Amazon Bedrock key (AWS_BEARER_TOKEN_BEDROCK) comes last, for the harnesses that have a Bedrock profile.--llm bedrockshares only that key, for Amazon Bedrock in--bedrock-region. OpenShell gives the harness a placeholder that works only against the provider's hosts.- Without
--llm, a run takesopenshell.llm(autounless set). The shell wrappers, the TUI and the macOS app pass no--llm, so that key is how the runs they start share a chosen credential. A provider inopenshell.llmthat the harness has no profile for gives way toauto, and the run says so (a harness that shares no model credential at all, such as Kiro CLI, takesautowithout a note); one whose key is not set refuses the run, naming the key. With--llm none, or when nothing is found, you log in inside the sandbox, which stores a real token there that the agent can read. A Claude subscription can instead runclaude setup-tokenon this machine (with the shell wrapper on,DEFENSECLAW_NO_SANDBOX=1 claude setup-token) and export the token it prints asCLAUDE_CODE_OAUTH_TOKEN; the banner suggests it only when Claude Code is installed here. --credential NAME=host[:port]gives the sandbox a placeholder in$NAMEthat OpenShell swaps for your value only on requests to that host (port 443 unless you give one).--github-writedoes the same for yourGH_TOKENorGITHUB_TOKENandapi.github.com: the placeholder works there with everything the token may do, in any repository it reaches, andgit pushover HTTPS (togithub.com) is not authenticated. A binding of the harness's model key is the run's model credential, as the banner's Model line says.--env KEY=VALUEis for non-secret settings: the sandbox holds the value in plain text, which the agent can read. A name that looks like a secret (KIRO_API_KEY,*_TOKEN,*_PASSWORD) gets a warning; bind a key with--credential NAME=HOSTinstead, so the sandbox sees only a placeholder.- A sandbox with the egress proxy sets
NODE_NO_WARNINGS=1, so Node's[UNDICI-EHPA] EnvHttpProxyAgent is experimentalwarning, which the proxy settings trigger, does not print above the harness or in the agent'snodeandnpmoutput. It hides Node's other warnings too, including the one that says TLS certificate checks are off (NODE_TLS_REJECT_UNAUTHORIZED=0); pass--env NODE_NO_WARNINGS=0to a new sandbox to keep them. - Hermes Agent's managed
defenseclawprovider reads an OpenAI-compatible endpoint fromHERMES_DEFENSECLAW_BASE_URLand its key fromHERMES_DEFENSECLAW_API_KEY: for your own endpoint, rundefenseclaw sandbox run hermes --llm none --credential HERMES_DEFENSECLAW_API_KEY=HOST[:PORT] --env HERMES_DEFENSECLAW_BASE_URL=https://HOST/v1 -- --provider defenseclaw -m MODEL. --pack,--profile,--copy,--safe,--unmask,--host-port,--no-mcp,--cpu, and--memorygo through the sandbox policy. An organization limit can refuse them ("blocked by your organization's DefenseClaw policy") or lower them ("limited by …; running with X instead of Y"), andsandbox policy explainshows the outcome before you run. A flag the organization lowers,--cpuand--memoryincluded, is confirmed before anything is created; answering no creates nothing. When the organization puts the folder on a copy (openshell.admin.require_copy_for, or a required pack that works on copies),runsays so before it copies.- In a safe run (
--safe, or a policy that keeps the prompts), harness arguments that would turn the prompts off are dropped with a warning that names the organization when the policy is its. OmniGent has no skip-permissions switch: its banner shows that its approvals come from its own policies, DefenseClaw's included. - A folder that can't be mounted live (a linked git worktree, a git directory outside it) runs on a copy, with one line saying why.
- A copy larger than
openshell.workdir.max_upload_mb(500 MB by default) is refused before a sandbox exists, and the refusal names the setting; on a Mac it also says that a copy is the only way the project runs there. - On a gateway whose compute driver mounts no host folders (a Mac's MicroVM
driver),
--contextis refused before anything is copied,--no-snapshotis said not to apply, and--cpuand--memoryare said to have no effect: every MicroVM gets the gateway'svcpusandmem_mib, so an organization's limit on the flags is not applied to them. The first start of an image the driver has not prepared yet says it takes about a minute. That start prepares a disk of about the image's size in the driver's image cache: before anything is copied,runrefuses it when the volume has less free space than the image's size plus 1 GiB (at least 6 GiB), and warns below twice that (at least 12 GiB), naming what is free andsandbox image prune. The daemon refuses such a create from any client the same way.
| Flag | Takes | Default | Description |
|---|---|---|---|
--bedrock-region | text | Amazon Bedrock region for --llm bedrock (default $AWS_REGION, then $AWS_DEFAULT_REGION, then us-east-1). | |
--context | text, repeatable | Extra folder mounted read-only (repeatable; mount mode only). | |
--copy | switch | Work on a copy of the folder with secrets held back; bring changes back with pull. | |
--cpu | text | CPU limit, for example 2 or 500m. | |
--credential | text, repeatable | NAME=host[:port]: give the sandbox a placeholder for $NAME that works only against that host (repeatable). | |
-d, --detach | switch | Run in the background (needs --prompt); follow with sandbox logs -f. | |
--env | text, repeatable | KEY=VALUE non-secret variable for the sandbox (repeatable). | |
--github-write | switch | Bind your GitHub token (GH_TOKEN or GITHUB_TOKEN) to api.github.com so gh can call the GitHub API (for example to open pull requests) with everything the token may do; git push over HTTPS is not covered. | |
--host-port | port, repeatable or comma-separated | Open this localhost port on your machine to the sandbox (repeatable). | |
--keep | switch | Keep the sandbox of a headless run (--prompt), which is otherwise deleted at its end when nothing is left in it to bring back or undo. | |
--llm | text | Model credential to share: auto, none, anthropic, claude-oauth, openai, bedrock or gemini (default: openshell.llm, which is auto unless set). | |
--memory | text | Memory limit, for example 4Gi. | |
--name | text | Sandbox name, at most 19 lowercase letters, digits and '-' (default <folder>-<random>). | |
--new | switch | Start a new sandbox even when one already holds this folder. | |
--no-build | switch | Fail instead of building a missing harness image. | |
--no-mcp | switch | Leave the harness's MCP servers behind. | |
--no-snapshot | switch | Skip the pre-session snapshot (and so undo). | |
--pack | text | Sandbox policy pack (open, balanced, strict, or a custom pack). | |
--profile | text | Network profile: open, balanced or strict. | |
-p, --prompt | text | Run the harness headless with this prompt. | |
--refresh | switch | When resuming a copy-mode sandbox, copy the folder again. | |
--rm | switch | Delete the sandbox when the session ends. | |
--safe | switch | Keep the harness's own permission prompts (skip-permissions off). | |
--unmask | text, repeatable | Share a masked secret file or glob with the sandbox (repeatable). | |
-y, --yes | switch | Take the defaults at the end of the session (mount: keep the changes; copy: leave them in the sandbox for pull). |
sandbox connect
Resumes a sandbox: it starts the sandbox if it is stopped, then attaches the
harness to your terminal, or a login shell in the project folder with
--shell. The harness gets the options its run was given after --
first, then the ones you pass now, and the banner shows the run's Model and
Secret lines. Both kinds of session end the same way as a run session,
with the summary and the keep-or-undo question (a --shell session exits
0). Needs a terminal, except with --prompt TEXT (or the harness's own
print flag after --), which runs one prompt headless. A session stops the
sandbox at its end only when it started it, and leaves one whose detached
run is still going, or that another session is attached to, running. Two
sessions can share a sandbox (a second claude in the folder offers to
resume it): neither one's end stops it, undoes the folder or deletes it
(--rm) under the other, and the one that ends first names the review and
undo commands for later. To continue the harness's last conversation,
pass its own flag: -- --continue for Claude Code, OpenCode, GitHub Copilot
CLI, Hermes Agent and OmniGent, -- resume --last for Codex, -- --resume
for Kiro CLI, -- --resume --last for OpenHands and -- -c for Antigravity.
defenseclaw sandbox connect myapp-7f3a
defenseclaw sandbox connect myapp-7f3a -- --continue
defenseclaw sandbox connect fix-tests --refresh -- --model sonnet
defenseclaw sandbox connect myapp-7f3a --shell| Flag | Takes | Default | Description |
|---|---|---|---|
-p, --prompt | text | Run the harness headless with this prompt. | |
--refresh | switch | Copy-mode: copy the folder into the sandbox again first. | |
--rm | switch | Delete the sandbox when the session ends. | |
--shell | switch | Open a shell in the sandbox instead of the harness. | |
-y, --yes | switch | Take the defaults at the end of the session (mount: keep the changes; copy: leave them in the sandbox for pull). |
sandbox exec
Runs one command in a running sandbox, in the project folder unless you pass
--workdir. The command gets the same environment, including the egress
proxy, as the harness. A terminal is allocated when yours is one. The command
goes after --.
defenseclaw sandbox exec myapp-7f3a -- npm test
defenseclaw sandbox exec fix-tests --no-tty -- git status --shortWhat the command starts in the background keeps running after it exits.
With a terminal, OpenShell keeps the exec open while such a process runs
(a nohup server, say), for about 30 seconds, and then ends it with status
74. DefenseClaw names the process as the command exits. Start a background
server with --no-tty to get the prompt back at once.
| Flag | Takes | Default | Description |
|---|---|---|---|
--no-tty | switch | Never allocate a terminal. | |
--tty | switch | Allocate a terminal even when this one is not. | |
--workdir | text | Working directory in the sandbox (default: the project). |
sandbox logs
Shows the output of a detached run (run --detach) and whether the run is
still going, finished (with its exit status) or was interrupted. -f follows
the output until the run ends. Once the sandbox is stopped, it shows the last
1 MiB of the log that DefenseClaw kept on this machine as it stopped the
sandbox, whoever stopped it (stop, the TUI, the macOS app, undo, a tamper
stop). The agent writes this log, so on a terminal
its escape sequences (other than colors) and control characters print as
� rather than acting on the terminal; piped or redirected to a file, the
log is written as it is. A one-prompt run --prompt prints the harness's
output the same way.
defenseclaw sandbox logs fix-tests -f
defenseclaw sandbox logs fix-tests --lines 50| Flag | Takes | Default | Description |
|---|---|---|---|
-f, --follow | switch | Keep following the output. | |
-n, --lines | number | 200 | Lines to show. |
sandbox list
Lists this DefenseClaw's sandboxes with their harness, phase, workspace mode,
profile, uptime, hook traffic, and project folder. The HOOKS column reads
tamper! once a tool call ran without a DefenseClaw verdict, unreachable!
while the hooks do not reach DefenseClaw, and silent! while the harness
works without hook traffic.
defenseclaw sandbox list| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
sandbox status
Without a name, shows the sandbox subsystem: whether it is on and reachable,
the OpenShell gateway, the listener addresses, the default pack and profile,
the organization policy, and counts. With a name, shows that sandbox in
detail: the harness and its version, phase, project folder, permissions mode,
policy, hook tamper tier, hook traffic, the verdicts per hook event under
the harness's own event names ("Hook events PreToolUse 12 · PostToolUse 11
· Stop 2"), the last blocked tool call, the tool calls that ran without a DefenseClaw verdict (hook tamper), egress
totals (destinations contacted and blocked, each counted once, as the
activity feed names them; the JSON also has blocked_requests), credential
endpoints, the undo point, waiting asks, nested
repositories, and warnings, including a stopped sandbox the current policy
would not start.
defenseclaw sandbox status
defenseclaw sandbox status myapp-7f3a --output json| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
sandbox stop
Stops a sandbox. It is kept, so start or connect can resume it. When a
detached run is still going, stop asks first on a terminal (--yes skips
the question; without a terminal it warns). The stop marks the run
interrupted and keeps its log for sandbox logs, as every stop does.
For a copy-mode sandbox that no detached run and no other session is using,
stop first looks at its copy. When nothing in it is left to bring back (it
is as it was uploaded, or as its last pull took it and that pull went to your
folder, a branch or a patch file), delete of the stopped sandbox does not
warn about unpulled work, as after a session that brought everything back.
When the copy is as its last pull took it, the next pull uses that pull
instead of starting the sandbox.
defenseclaw sandbox stop myapp-7f3a| Flag | Takes | Default | Description |
|---|---|---|---|
-y, --yes | switch | Stop without asking when a detached run is still going. |
sandbox start
Starts a stopped sandbox as a new session. A mounted project gets a fresh
snapshot only when nothing would be lost: there is no snapshot yet, the last
one was undone, or the folder hasn't changed since it. If an earlier
session's changes are still in the folder, the old snapshot is kept, so
undo can still revert them, and the activity feed says so. Changes you
kept at the end of a session ("Keep changes?", --yes or on_exit: keep)
count as accepted: DefenseClaw records it, and the next start takes a fresh
snapshot, whether start, connect, the TUI or the macOS app starts it.
--new-snapshot accepts the changes and takes a fresh snapshot;
--no-snapshot always keeps the old one. start says which undo point
applies, and when it kept the old one, that stopping the sandbox and
starting it with --new-snapshot accepts the changes instead. A sandbox
that is already running is left as it is. Attach to it with connect.
defenseclaw sandbox start myapp-7f3a| Flag | Takes | Default | Description |
|---|---|---|---|
--new-snapshot | switch | Take a new snapshot even if the folder still has an earlier session's changes (undo no longer reverts them). | |
--no-snapshot | switch | Keep the previous session's snapshot instead of taking a new one. |
sandbox delete
Deletes sandboxes together with their OpenShell providers and credentials,
and their undo point (snapshot) unless you pass --keep-snapshot. Asks once per
sandbox unless you pass --yes. A copy-mode sandbox holding work that was
never pulled back (or a pull never applied) is named in the question, which
then defaults to no; teardown lists such sandboxes before it asks. A
stopped copy-mode sandbox is not warned about when what stopped it (a
session's end, a pull that started it, or stop) found nothing left in it
to bring back. For a copy-mode sandbox whose work came back, delete says
where it last went and when, and so does its warning:
fix-tests's work was last applied to ~/code/myapp at 14:03; nothing newer is left in itdefenseclaw sandbox delete myapp-7f3a
defenseclaw sandbox delete fix-tests docs --yes| Flag | Takes | Default | Description |
|---|---|---|---|
--keep-snapshot | switch | Keep the pre-session snapshot. | |
-y, --yes | switch | Do not ask. |
During a session
sandbox activity
Shows the activity feed of every sandbox, or one: destinations reached (✓)
and blocked (✗), large uploads, unblocks, asks and their answers, blocked tool
calls, findings such as hooks that stopped reaching DefenseClaw, lifecycle
changes (a sandbox being created, becoming ready, stopping, or being deleted),
and workspace events such as an undo or a copy-mode upload. A destination
shows its port unless that is 443 (HTTPS): a plain-HTTP request reads
example.com:80, so an HTTPS and an HTTP request refused at the same host
are two different lines. An IPv6 address with its port is bracketed:
[fd00:ec2::254]:80. A blocked destination that can be unblocked shows
the unblock command to run. A large upload is a ⚠ report, made as it crosses the threshold, so it says more than
it (⚠ large upload to files.example.net (more than 25 MiB)), or, with
the large-upload block
on, a ✗ that names the threshold, such as ✗ files.example.net (large upload blocked: this sandbox tried to send more than 10 MiB to a destination it had not contacted before), with its unblock command. -f
keeps following the feed. The daemon keeps a bounded buffer of recent events. Each event has a
sequence number, and --since starts after one.
defenseclaw sandbox activity -f
defenseclaw sandbox activity --sandbox myapp-7f3a --output json| Flag | Takes | Default | Description |
|---|---|---|---|
-f, --follow | switch | Keep following the feed. | |
-o, --output | text | text | Output format: text or json. |
--sandbox | text | Only this sandbox. | |
--since | number | 0 | Start after this event sequence number. |
sandbox approvals
Lists the asks waiting for you. Asks are rare: a program in the sandbox tried
to connect somewhere directly, around the egress proxy, and the policy would
not decide it alone. Typical asks are ports on your machine and private
network addresses. --watch keeps the list current.
defenseclaw sandbox approvals
defenseclaw sandbox approvals --sandbox myapp-7f3a --watch| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
--sandbox | text | Only this sandbox. | |
--watch | switch | Keep watching for new asks. |
sandbox approve
Approves an ask. The approval opens a direct OpenShell rule for the
destination. It is applied at the sandbox's next quiet moment, because every
OpenShell policy change closes the sandbox's open connections. --always
also saves the hosts to openshell.egress.unblocked for future sandboxes.
It is refused, and nothing is approved, for the typical asks: a port on your
machine, a destination on your private network (a private address, an
intranet name such as *.corp, or a name that resolves to a private
address), or an ask with allowed IP addresses (allowed_ips). Those open for
one sandbox only, so approve them without --always; to open a private
destination for every sandbox, add it to openshell.egress.allow. For a port that future sandboxes need, pass --host-port to run
or add it to openshell.mcp.host_ports.
defenseclaw sandbox approve myapp-7f3a a1b2c3
defenseclaw sandbox approve myapp-7f3a a1b2c3 --always --reason "team registry"| Flag | Takes | Default | Description |
|---|---|---|---|
--always | switch | Keep the decision for future sandboxes. | |
--reason | text | Note recorded with the decision. |
sandbox reject
Rejects an ask. --always also adds the hosts to openshell.egress.block.
defenseclaw sandbox reject myapp-7f3a a1b2c3 --reason "not needed"| Flag | Takes | Default | Description |
|---|---|---|---|
--always | switch | Keep the decision for future sandboxes. | |
--reason | text | Note recorded with the decision. |
sandbox unblock
Lifts an egress block for one sandbox (--sandbox NAME) or for every sandbox
(--always, saved to openshell.egress.unblocked). Choose exactly one of
the two. Only blocks from the blocklist feed or the profile's default can be
lifted: IP addresses under open, and hosts off the allowlist under
balanced. Your own block list, private networks, this machine, and your
organization's lists can't be unblocked, and neither can anything under
strict, which runs without the egress proxy. With
openshell.admin.allow_unblock: false, nothing can be unblocked. The
decision order
has the details.
An unblock also stops DefenseClaw's destination rules (such as
C2-WEBHOOK-SITE for webhook.site, or C2-NGROK) from flagging or
blocking tool calls that name the unblocked host, in the sandboxes the
unblock covers: the agent is no longer told a destination is blocked that
the proxy lets it reach, and the activity feed shows no finding for it. A
call that names a subdomain you did not unblock, that another rule flags
too, or that Cisco AI Defense or the LLM judge flags or blocks (even without
naming a rule), keeps its verdict.
The agent learns the command from DefenseClaw too. When the proxy refuses an
HTTPS destination, the hook of the next shell or web-fetch tool call tells
the agent the destination, why it is blocked, and the sandbox unblock
command for you to run (Claude Code, Codex, Copilot CLI, Cursor and Devin).
Once you unblock the host, the agent is no longer told of that block.
defenseclaw sandbox unblock webhook.site --sandbox myapp-7f3a
defenseclaw sandbox unblock docs.example.com --always| Flag | Takes | Default | Description |
|---|---|---|---|
--always | switch | Unblock for every sandbox from now on. | |
--sandbox | text | Unblock for this sandbox only. |
After a session
sandbox review
Reviews a mounted project's changes since the session's snapshot. It prints
a summary of the changes and flags the files that can run code on your
machine, such as package.json scripts, build and task files, CI workflows,
git attributes and submodules, harness and agent config (git-ignored files
such as .claude/settings.local.json included), lock files, new or newly
executable files, symbolic links, and embedded git repositories, new ones and
changes to the git config, hooks or .git pointer of those that were there
before. It also flags secret-like files, and lists the review's findings and
the nested repositories the session's guard found. --diff prints the
unified diff too.
For a copy-mode sandbox (every sandbox on a Mac) review previews what
sandbox pull would bring back, the same review and the changed files, and
applies nothing; a stopped sandbox is started to read its work and stopped
again. -o json then prints the pull's result, as pull -o json does, and
sandbox pull NAME --patch-out FILE writes the diff.
defenseclaw sandbox review myapp-7f3a
defenseclaw sandbox review myapp-7f3a --diff| Flag | Takes | Default | Description |
|---|---|---|---|
--diff | switch | Print the unified diff too. | |
-o, --output | text | text | Output format: text or json. |
sandbox undo
Restores a mounted project to its undo point (the snapshot a session
started from). It shows a preview first, then asks. The sandbox is stopped
before the restore, and --restart starts it again afterwards. Branches and
tags the session moved are put back too, unless you pass --keep-refs. The
session's own state is kept in a commit, and the command undo prints
(git -C FOLDER checkout COMMIT -- .) brings its files back. Files git
ignores have no copy in the undo point: undo deletes what the session wrote
to Python bytecode caches and names the rest, unless
openshell.workdir.undo_ignored has the undo point keep a copy of
dependency directories such as node_modules and .venv, which undo then
restores as the session found them.
For a copy-mode sandbox, which changes your folder only through
pull --apply, undo reverts the last pull --apply instead, after the
same preview and question. Edits you made since the apply stay; when they
overlap the apply, undo changes nothing and names the files. It neither stops
nor starts the sandbox, and --restart and --keep-refs don't apply. A
branch or patch file the work went to is yours to delete.
defenseclaw sandbox undo myapp-7f3a --preview
defenseclaw sandbox undo myapp-7f3a --yes --restart| Flag | Takes | Default | Description |
|---|---|---|---|
--keep-refs | switch | Leave branches and tags as the session left them. | |
-o, --output | text | text | Output format: text or json. |
--preview | switch | Only show what undo would change. | |
--restart | switch | Start the sandbox again afterwards. | |
-y, --yes | switch | Do not ask after the preview. |
sandbox pull
Brings a copy-mode sandbox's work back, starting the sandbox first if it is
stopped (unless its copy has not changed since its last pull, see below). Without a
mode it shows the review: the changed files, the ones that
can run code on your machine, and files held back from the sandbox. Choose
one mode to bring the work back: --apply (a
3-way merge into your working tree), --branch (branch dc/<name>) or
--branch-name NAME, or --patch-out FILE. A folder that is not a git
repository has no branch mode. When --apply cannot merge in place (a
conflict, or git older than 2.38), it leaves your working tree alone and
exits 4: the changes go to <name>.patch in your folder and, in a git
project, to branch dc/<name>. Changes that can run code on your machine
need your confirmation, or --accept-sensitive without a terminal.
Once an --apply (or the apply at a session's end) has put the work in your
folder, the next pull, a session's end included, shows only what changed in
the sandbox since (2 files changed (+3 −0) since the last apply), flags and
asks about only that, and its apply, patch or 3-way merge starts from that
point, so a change you took back from your folder since stays taken back.
With nothing new it says so and asks nothing, and sandbox delete of the
stopped sandbox does not warn about work it holds. sandbox undo of the
apply starts the next pull from the uploaded copy again, so the undone work
is offered anew. A branch or a patch file does not move that point: your
folder does not have those changes. A later pull of the same state still
counts as brought back, so delete does not warn about it.
--branch, --branch-name and --patch-out FILE are checked before the
sandbox is started or read: a branch that exists and does not hold the last
pull's work, a patch file that exists (without --force) or whose folder
does not, and a branch for a folder without git are refused at once. A branch
that already holds the work is done: nothing to do: branch dc/<name> already has these changes, with nothing asked ("up_to_date": true with -o json).
A branch that holds the last pull's work is refused at once too when the
stopped sandbox has run since that pull, since only starting it tells whether
its work changed (branch dc/<name> already exists: it holds <name>'s pull at 14:03, and <name> has run since, so its work may have changed): pass
--branch-name NAME, or --force to move the branch to the new work.
A stopped sandbox whose copy has not changed since its last pull read it (the
pull, the session's end or the stop that stopped it saw its copy in that
state, and it has not run since) is not started: that pull is made again, its
changes and review measured anew (fix-tests's copy has not changed since its last pull at 14:03; using that pull instead of starting it). On a Mac this
saves booting the MicroVM.
defenseclaw sandbox pull fix-tests
defenseclaw sandbox pull fix-tests --branch
defenseclaw sandbox pull fix-tests --patch-out fix-tests.patch| Flag | Takes | Default | Description |
|---|---|---|---|
--accept-sensitive | switch | Bring back changes that can run code on this machine. | |
--apply | switch | Merge the changes into your working tree (3-way). | |
--branch | switch | Put the changes on branch dc/<name>. | |
--branch-name | text | Put the changes on this branch. | |
--force | switch | Override blocking review gates, an existing branch or patch file. | |
-o, --output | text | text | Output format: text or json. |
--patch-out | text | Write the changes to this patch file. |
Policy and packs
sandbox policy
The effective sandbox policy combines the pack, your openshell keys, the run
flags, and the organization's openshell.admin limits. See
How the effective policy is computed.
defenseclaw sandbox policy show| Subcommand | Purpose |
|---|---|
sandbox policy allow | Add hosts to openshell.egress.allow (used by the balanced and strict profiles). |
sandbox policy block | Add hosts to openshell.egress.block. |
sandbox policy explain | Show every resolved setting and where it comes from (pack, config, flag, organization). |
sandbox policy show | Show the effective sandbox policy. |
sandbox policy suggest | Suggest an egress allowlist from the destinations sandboxes reached. |
sandbox policy show
Shows the effective policy of one sandbox (--sandbox), or the policy a
run in this folder with the given flags would get. It lists the pack and
its digest, the profile, network and approvals modes, the organization
policy, the main settings, and any setting a limit refused.
defenseclaw sandbox policy show
defenseclaw sandbox policy show --harness codex --profile balanced --copy| Flag | Takes | Default | Description |
|---|---|---|---|
--copy | switch | Resolve for a copy-mode run. | |
--harness | text | Resolve for this harness. | |
-o, --output | text | text | Output format: text or json. |
--pack | text | Resolve with this pack. | |
--profile | text | Resolve with this profile. | |
--safe | switch | Resolve for a --safe run. | |
--sandbox | text | The policy of this sandbox. | |
--unmask | text, repeatable | Resolve with these --unmask globs. |
sandbox policy explain
Shows every resolved setting with its value, the layer that set it (pack,
user, flag, admin, or default), and its precise origin, such as
openshell.admin.min_profile. A clamped setting also shows the value that
was asked for.
defenseclaw sandbox policy explain
defenseclaw sandbox policy explain --sandbox myapp-7f3a --output json| Flag | Takes | Default | Description |
|---|---|---|---|
--copy | switch | Resolve for a copy-mode run. | |
--harness | text | Resolve for this harness. | |
-o, --output | text | text | Output format: text or json. |
--pack | text | Resolve with this pack. | |
--profile | text | Resolve with this profile. | |
--safe | switch | Resolve for a --safe run. | |
--sandbox | text | The policy of this sandbox. | |
--unmask | text, repeatable | Resolve with these --unmask globs. |
sandbox policy suggest
Prints an openshell.egress.allow list, as YAML, of the destinations your
sandboxes reached in the daemon's activity buffer, with a count for each and
the blocked ones listed apart. Use it before you move to the default-deny
balanced profile.
defenseclaw sandbox policy suggest
defenseclaw sandbox policy suggest --sandbox myapp-7f3a --output json| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
--sandbox | text | Only this sandbox's destinations. |
sandbox policy allow
Adds host patterns to openshell.egress.allow in config.yaml, and refuses
patterns that cover every host or a whole top-level domain. Allow entries
matter under the balanced profile, which reaches only allowed hosts. Under
strict, a direct connection to an allowed host is approved without asking.
The daemon applies the change to running sandboxes within a few seconds.
Under your organization's openshell.admin limits the command refuses an
entry, names the limit, and changes nothing: every entry when
allow_unblock is false (your own allow entries would be ignored), and a
host on egress_block (or a subdomain of a host name there) or outside
egress_allow_only.
defenseclaw sandbox policy allow artifacts.example.com "*.docs.example.com"This command has no flags.
sandbox policy block
Adds host patterns to openshell.egress.block in config.yaml. A host on the
block list can't be unblocked; remove the entry to reach it again.
defenseclaw sandbox policy block files.example.netThis command has no flags.
Both commands check each pattern and refuse a change that would make
config.yaml invalid. In a managed_enterprise install they are refused,
because the administrator owns config.yaml.
sandbox pack
Policy packs set the whole sandbox posture. See Sandbox policy packs.
defenseclaw sandbox pack list| Subcommand | Purpose |
|---|---|
sandbox pack list | List the built-in and custom packs with their sha256 digests. |
sandbox pack show | Print a pack and its sha256 digest (for openshell.admin.required_pack_digest). |
sandbox pack validate | Validate a pack file strictly. |
sandbox pack list
Lists the built-in packs and the custom packs under openshell.pack_dir, with
their profile and sha256 digest. A custom pack that fails to load shows why.
defenseclaw sandbox pack list| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
sandbox pack show
Prints a pack, normalized, with its source and digest. The digest is the one
openshell.admin.required_pack_digest pins. It takes the same references as
openshell.pack: a built-in name, a custom pack name, or an absolute path.
defenseclaw sandbox pack show balanced
defenseclaw sandbox pack show ~/.defenseclaw/policies/sandbox/team-web| Flag | Takes | Default | Description |
|---|---|---|---|
-o, --output | text | text | Output format: text or json. |
sandbox pack validate
Loads a custom pack file strictly, with the same checks a run applies, and
prints its name, profile, and digest. It takes an absolute path (or one
starting with ~/) to a pack.yaml or its directory.
defenseclaw sandbox pack validate ~/.defenseclaw/policies/sandbox/team-web/pack.yamlThis command has no flags.
Legacy cleanup
sandbox legacy-cleanup
Linux only, and the one sandbox command the Python CLI runs itself. It
removes a retired openshell-sandbox 0.0.x standalone install and restores
the host's OpenClaw networking, ownership, and config. It prints every step
with its exact commands and asks once, unless you pass --yes. Progress is
recorded in <data_dir>/legacy-sandbox-cleanup.json, so running it again only
does what is left.
Detect a legacy install says
when you need it.
defenseclaw sandbox legacy-cleanup --dry-run
defenseclaw sandbox legacy-cleanup| Flag | Description |
|---|---|
--dry-run | Print the cleanup plan and exact commands; change nothing. |
-y, --yes | Apply the plan without asking for confirmation. |
--remove-user | Also delete the sandbox user and its home (userdel -r). Refused while it has processes, or until its ownership and ACLs are gone from the OpenClaw home. |
--remove-binary | Also remove /usr/local/bin/openshell-sandbox when it is a legacy 0.0.x build that no package owns. |