CLI reference
Every launchsafe-firewall command and option
Every command parses its arguments against a declared spec before anything runs:
--helpor-hanywhere (before--) prints that command's help and exits 0 without side effects.- An unknown flag, a missing value, a bad choice or a surplus argument exits 64 with one line on stderr and changes nothing.
hooknever exits 64: a malformed hook command exits 2, which blocks the tool (fail closed).- Commands marked changes state are refused when an agent runs them (
FW-TAMPER) and, under the test marker, refuse to write under the real home directory.
Commands that need the approval passphrase ask for it in your own terminal. Never type it into an agent.
install
Register the firewall's hooks in an agent's settings (Claude Code, Codex, Gemini CLI, Cursor). Changes state.
launchsafe-firewall install [--agent claude|codex|gemini|cursor] [--scope user|project|local] [--project DIR] [--no-approver]
launchsafe-firewall install --agent gemini --seatbelt PROFILE [--gemini-package DIR] [--scope user|project] [--project DIR] [--no-approver]
launchsafe-firewall install --managed [--agent claude|codex|gemini|cursor] [--lock-other-hooks] [--print]--agent claude|codex|gemini|cursor: which agent's settings (default claude).--scope user|project|local: which settings file (Codex, Gemini CLI and Cursor: user or project).--project DIR: the project directory (default: the current directory).--managed: print managed settings for an administrator to deploy.--lock-other-hooks: with--managed, also setallowManagedHooksOnly.--print: with--managed, print the JSON only.--no-approver: do not offer to set an approval passphrase.--seatbelt permissive-open|permissive-proxied|restrictive-open|restrictive-proxied|strict-open|strict-proxied: with--agent gemini, macOS: also write~/.gemini/sandbox-macos-launchsafe.sb, Gemini CLI's own profile plus write access to the hook's state directories only, forgemini -swithSEATBELT_PROFILE=launchsafe(permissive-openis Gemini CLI's default).--gemini-package DIR: with--seatbelt, Gemini CLI's package (or its bundle directory) to copy the profile from (default: found from thegeminicommand on PATH).
uninstall
Remove the firewall's hooks (needs the approval passphrase). Changes state.
launchsafe-firewall uninstall [--agent claude|codex|gemini|cursor] [--scope user|project|local] [--project DIR] [--restore-backup [--force]] [--remove-sandbox] [--purge]--agent,--scope,--project: as forinstall.--restore-backup: put each settings file back exactly as it was before the first install (a file install created is removed; the current file is saved asFILE.before-restore.TIMESTAMPfirst; settings you changed since install are listed and need a yes or--force; this also removes a sandbox profiledoctor --fixadded).--force: with--restore-backup, discard settings you changed since install without asking (the file as it is now is still saved beside it first).--remove-sandbox: also remove the sandbox profiledoctor --fixinstalled (it is kept otherwise).--purge: also delete the firewall's state directory.
doctor
Check that the firewall is actually protecting this machine. Does not change state on its own.
launchsafe-firewall doctor [--json] [--project DIR]
launchsafe-firewall doctor --fix [--scope user|project|local] [--dry-run] [--project DIR]
launchsafe-firewall doctor --repair-state [--project DIR]--json: print JSON.--project DIR: the project directory (default: the current directory).--fix: offer fixes after showing each change: Claude Code's sandbox profile from your policy (needs the approval passphrase), pinning the approval key in the hook, a package cooldown in your user config, downloading malicious-package data.--scope user|project|local: with--fix, which Claude Code settings file gets the sandbox profile (default: user).--repair-state: rebuild a damagedinstall.jsonfrom the agent settings files that hold the firewall's hooks (the damaged file is kept beside it; person-run, needs the approval passphrase).--dry-run: with--fix, print the changes and exit without writing anything or asking for the passphrase.
update
Download the malicious-package data (OSV MAL- entries) used to check installs. This is the only network use. Changes state.
launchsafe-firewall update [--source URL|DIR] [--ecosystem LIST]--source URL|DIR: where to fetch<Ecosystem>/all.zipfrom (default: OSV's public bulk exports).--ecosystem LIST: comma-separated ecosystems (default: npm, PyPI, crates.io, RubyGems, Go, Maven, NuGet, Packagist).
status
Sessions, held actions and recent decisions.
launchsafe-firewall status [--json]queue
Actions held for a person.
launchsafe-firewall queue [--json] # same as queue list
launchsafe-firewall queue list [--json]
launchsafe-firewall queue show <id> [--json] # one held action, with the diff for a proposed change
launchsafe-firewall queue review # go through every held action (needs the approval passphrase); changes state
launchsafe-firewall queue approve <id>... # allow held actions once (needs the approval passphrase); changes state
launchsafe-firewall queue reject <id>... # reject held actions; changes statepins
MCP servers' pinned configuration, tools and descriptions, and changes waiting for review.
launchsafe-firewall pins [--json] # same as pins list
launchsafe-firewall pins list [--json]
launchsafe-firewall pins accept <server>... # accept pending changes after review (needs the approval passphrase); changes statevault
Secrets the agent can use by reference but never sees. See Vault.
launchsafe-firewall vault [--json] # same as vault list
launchsafe-firewall vault list [--json] # names, kinds, fields, bindings; never a value
launchsafe-firewall vault add <name> [--kind credential|oauth|card|iban|national_id|personal] [--fields a,b] [--confirm always|never]
launchsafe-firewall vault allow <name> --host HOST [--allow-in-url] [--allow-http] | --mcp SERVER[:TOOL[:ARG]] | --process "PROGRAM ARGS..."
launchsafe-firewall vault revoke <name> <n>
launchsafe-firewall vault remove <name>
launchsafe-firewall vault rotate <name>add, allow, revoke, remove and rotate need the approval passphrase and change state.
vault add --kind: what it is (defaultcredential);card,iban,national_idandpersonalhave several fields.vault add --fields a,b: the field names (default per kind:value; cardnumber,expiry,cvc,name; ibaniban,bic,holder).vault add --confirm always|never: macOS, ask in a keychain dialog on every read (default:alwaysfor card, iban, national_id, personal;neverfor credential, oauth).vault allow --host HOST: an exact host name, or*.example.comfor its subdomains.--allow-in-urllets the value also appear in the URL itself (server logs keep URLs);--allow-httplets it also go over plain http (the default is https only).vault allow --mcp SERVER[:TOOL[:ARG]]: an MCP server, optionally a tool pattern and the one argument path it may appear in.vault allow --process ARGV: a command line it may be given to byrun(a trailing*allows further arguments).vault revoke <name> <n>: remove one binding of a secret, by its number invault list.
mcp
The MCP gateway. See MCP gateway. All of these change state.
launchsafe-firewall mcp wrap --client CLIENT --server NAME [--mode auto|full|hook] [--phones PIN] -- COMMAND [ARGS...]
launchsafe-firewall mcp serve [--port N]
launchsafe-firewall mcp wrap-config --client CLIENT [--server NAME,...] [--port N] [--dry-run]
launchsafe-firewall mcp unwrap-config --client CLIENT [--dry-run]
launchsafe-firewall mcp login <server>mcp wrap: the stdio gateway for one server (an MCP client starts this from its configuration).--client claude-desktop|claude-code|cursor|codex|gemini|vscode: which MCP client.--server NAME: the server's name in the client's configuration.--mode auto|full|hook:full, the gateway decides every call;hook, the client's firewall hook does (defaultauto).--phones sha256:HEX: the paired phones' pin (written bymcp wrap-config; phone approvals verify against it).mcp serve: the local Streamable HTTP gateway (127.0.0.1 only; person-run).--port Nsets the port (default 8473).mcp wrap-config: put the gateway in front of a client's MCP servers; shows the diff, backs up, needs the approval passphrase.--server NAME,...limits it to these servers,--port Nis the local gateway's port for HTTP servers (default 8473),--dry-runprints the changes and exits.mcp unwrap-config: put a client's MCP servers back as they were beforewrap-config(needs the approval passphrase).mcp login: sign the gateway in to a wrapped HTTP server's authorization server (OAuth, person-run).
gateway
launchsafe-firewall gateway [--json] # same as gateway status
launchsafe-firewall gateway status [--json] # servers wrapped, not wrapped, and withheld results
launchsafe-firewall gateway reset <client> # start a new gateway session for a client now; changes state
launchsafe-firewall gateway quarantine [--json] # MCP results the gateway withheld (never their text)
launchsafe-firewall gateway quarantine show <id> # the text of one withheld result, for you in your own terminal; changes stateThe email guard. See Email guard.
launchsafe-firewall mail [--json] # same as mail quarantine list
launchsafe-firewall mail quarantine [--all] [--json]
launchsafe-firewall mail quarantine list [--all] [--json]
launchsafe-firewall mail quarantine show <id> [--json] # one record, with its hidden text escaped
launchsafe-firewall mail quarantine release <id> # deliver next time, hidden parts stripped (needs the approval passphrase); changes state
launchsafe-firewall mail quarantine discard <id> # close the record; it stays withheld; changes state
launchsafe-firewall mail audit --path FILE|DIR [--limit N] [--json]--all: also list released and discarded records.mail audit: a dry run of the email guard over saved mail (.emlfiles, mbox files or folders of them): counts only, nothing changes or leaves the machine.--path FILE|DIRis an.emlfile, an mbox file, or a folder of them (searched recursively);--limit Nscans at most N messages (default 5000);--jsonprints the counts as JSON (no addresses, no subjects).
phone and relay
Phone approvals are not available yet. See Phone approvals.
launchsafe-firewall phone [--json] # same as phone list
launchsafe-firewall phone list [--json]
launchsafe-firewall phone pair [--label NAME] [--no-login-item] # needs the approval passphrase and a LaunchSafe account; changes state
launchsafe-firewall phone remove <label|id> # needs the approval passphrase; changes state
launchsafe-firewall phone unpair <label|id> # same as phone remove
launchsafe-firewall relay [--json] # same as relay status
launchsafe-firewall relay status [--json]
launchsafe-firewall relay run [--once] # the relay daemon; changes state--label NAME: this machine's name on the phone (default: the host name).--no-login-item: do not install the relay daemon as a login item (runrelay runyourself).--once: one upload and one decision check, then exit.
approver
The approval passphrase.
launchsafe-firewall approver # same as approver status
launchsafe-firewall approver status # whether an approval passphrase is set
launchsafe-firewall approver init # set the approval passphrase; changes state
launchsafe-firewall approver rotate # change the approval passphrase; changes statelog
The signed decision log.
launchsafe-firewall log # same as log tail
launchsafe-firewall log tail [N] # the last N decisions
launchsafe-firewall log verify # check the log's hash chain and signatures
launchsafe-firewall log rotate # start a new log file now; changes statepolicy
See Policy.
launchsafe-firewall policy # same as policy show
launchsafe-firewall policy show # print the merged policy
launchsafe-firewall policy validate # check every policy file and list ignored project settings
launchsafe-firewall policy init # write a starter user policy file; changes state
launchsafe-firewall policy migrate # rewrite the user policy in the current schema version, keeping a backup; changes statecanary
Decoy files.
launchsafe-firewall canary [--json] # same as canary list
launchsafe-firewall canary list [--json] # the decoys planted, and whether each is still there
launchsafe-firewall canary plant [--workspace DIR] [--home] [--kinds env,aws,ssh,gh,notes,npmrc,kube]
launchsafe-firewall canary remove <id>
launchsafe-firewall canary remove --allplant and remove change state.
--workspace DIR: the project to plant in (default: the current directory).--home: also plant decoys in your home directory (~/.aws,~/.ssh,~/.config/gh); off by default.--kinds LIST: comma-separated kinds (default:env,awsin the workspace;aws,ssh,ghwith--home).remove --all: remove every decoy (also resets a damaged registry).
scope
The task scope a session's prompt set.
launchsafe-firewall scope [<session>] [--json] # same as scope show
launchsafe-firewall scope show [<session>] [--json] # the scope and your widenings (default: the most recent session)
launchsafe-firewall scope widen <session> --path P | --repo OWNER/REPO | --host HOST | --intent push|pr|publish|deploy|message|delete|install|migratescope widen needs the approval passphrase and changes state. --path P is a file or directory (relative to the current directory), --repo OWNER/REPO a GitHub repository, --host HOST a host name, --intent a publish-type action the task may take.
check and explain
launchsafe-firewall check < action.json
launchsafe-firewall explain <id> [--json]
launchsafe-firewall explain < action.jsoncheckjudges one action without changing anything. It reads{"tool": "...", "input": {...}, "untrusted": false, "unattended": false, "prompt": "..."}on stdin.explainexplains a rule (FW-...), a queue item, a log entry or an agent-safety rule. With no id, it is the same ascheck.
ui
A read-only dashboard in your browser (127.0.0.1 only, a private address printed once). Approvals stay in the terminal. Only you can start it, from your own terminal. Changes state. See Dashboard.
launchsafe-firewall ui [--project DIR] [--no-open]--project DIR: the project doctor's checks look at (default: the current directory).--no-open: print the address without opening the browser.
run
Start an agent (or any command) inside the OS sandbox: writes only to the workspace and a private temporary directory, network only to your policy's hosts through a local proxy, decisions in the signed log (macOS sandbox-exec, Linux bubblewrap). Changes state. See Run and sandbox.
launchsafe-firewall run [--workspace DIR] [--allow-write LIST] [--send-host LIST] [--allow-localhost] [--allow-keychain] [--git-init] [--env NAME=vault://REF]... [--dry-run] [--verbose] -- <command> [args...]--env NAME=vault://REF: put a vaulted secret into the command's environment asNAME(repeatable); the secret must be bound to this exact command (vault allow <name> --process "<command>").--ticket T: a single-use ticket the firewall's hook issued for exactly this--envlist and command (Claude Code's rewrite of a shell command with references); runs without the sandbox, output filtered.--workspace DIR: the directory the command may write to (default: the current directory).--allow-write LIST: comma-separated extra directories it may write to (never the home directory, credential stores, agent settings or system directories).--send-host LIST: comma-separated hosts it may send to for this run, without byte budgets (for example the agent's model API).--allow-localhost: macOS, let it connect to any port on 127.0.0.1 (local test servers; every local service becomes reachable). Linux has its own loopback.--allow-keychain: macOS, let it use the keychain (denied by default, so vault items stay out of reach).--git-init: when the workspace has no.git, rungit initin it before the run starts (inside the run.gitcannot be created).--dry-run: print the sandbox profile and the hosts, start nothing.--verbose: also print each refused connection as it happens (a full-screen agent may draw over it).
demo, version and help
launchsafe-firewall demo # replay the public incidents through the policy
launchsafe-firewall version # print the version
launchsafe-firewall help [command...] # help for a commandhook
The agent hook. It reads the event on stdin and is what the agents' hook registrations run. Changes state.
launchsafe-firewall hook [--agent claude|codex|gemini|cursor] [--record DIR]--agent claude|codex|gemini|cursor: which agent sends the event (default claude).--record DIR: also save each raw event to DIR (only withLAUNCHSAFE_FIREWALL_RECORD=1).