Documentation Index
Fetch the complete documentation index at: https://docs.agent-vault.dev/llms.txt
Use this file to discover all available pages before exploring further.
agent-vault vault run has two isolation modes:
--isolation=host(default) — forks the agent on the host withHTTPS_PROXYand CA-trust env vars pointing at Agent Vault. Cooperative: a misbehaving or malicious agent can unset the env, spawn a subprocess that doesn’t inherit them, use raw sockets, or exfiltrate over DNS.--isolation=container— launches the agent inside a Docker container whose egress is locked down with iptables. Non-cooperative: the only TCP destination the container can reach is the Agent Vault proxy. Everything else is dropped at the kernel.
Container mode is opt-in while it stabilizes. Host mode remains the default.
Quick start
What’s inside the container
- Image:
agent-vault/isolation:<hash>, built on first use from an embedded Dockerfile. Debian-slim + Node 22 +@anthropic-ai/claude-code+iptables/gosu/curl/git/python3. - Network: a dedicated per-invocation Docker bridge network (
agent-vault-<session>). Not the default bridge — other containers you’re running cannot reach the forwarder. - User:
claude(UID != 0), dropped viagosuafterinit-firewall.shruns as root.--security-opt=no-new-privileges+--cap-drop=ALLwith onlyNET_ADMIN/NET_RAW(for iptables),SETUID/SETGID(so gosu can change UID), andKILL(so tini at PID 1 can forward TTY signals across the UID boundary) added. Docker doesn’t grant container caps as ambient caps to non-root processes, soclaudepost-gosu has an empty effective cap set regardless. - Egress policy:
OUTPUT DROPby default on both IPv4 (iptables) and IPv6 (ip6tables).ACCEPTonly for loopback, ESTABLISHED/RELATED replies, and the two Agent Vault ports athost.docker.internalover IPv4 (the MITM path is v4-only by construction — we resolve viagetent ahostsv4). No DNS rule:host.docker.internalis resolved via/etc/hosts(docker run --add-host=host.docker.internal:host-gateway), closing the DNS-exfiltration channel. - Mounts:
$PWD → /workspace(read-write, your project)~/.agent-vault/isolation/ca-<session>.pem → /etc/agent-vault/ca.pem(read-only, MITM CA)agent-vault-claude-home-<session> → /home/claude/.claude(per-invocation by default; removed after the container exits. See--home-volume-sharedfor a persistent docker volume, or--share-agent-dirto bind-mount your host~/.claudeinstead.)
Flags
| Flag | Default | Description |
|---|---|---|
--isolation | host | host (default) or container. Also read from AGENT_VAULT_ISOLATION. |
--image | Override the bundled image. Use for your own base (different agent, pinned versions). | |
--mount | Extra bind mount src:dst[:ro]; repeatable. Host paths are symlink-resolved before validation; binds into ~/.agent-vault/ or /var/run/docker.sock are rejected. | |
--keep | false | Omit --rm so the container is available for docker inspect / docker logs after exit. |
--no-firewall | false | Debug only. Skip init-firewall.sh; container has unrestricted egress. Prints a loud warning. |
--home-volume-shared | false | Share /home/claude/.claude across invocations via a persistent docker volume. Default is per-invocation (auth doesn’t persist, but concurrent runs can’t corrupt each other). |
--share-agent-dir | false | Bind-mount the host’s agent state dir (~/.claude) into the container so it reuses your host login (auth, project history, MCP config). Mutually exclusive with --home-volume-shared. |
Bundled image vs --image
The default image pins @anthropic-ai/claude-code at build time. If you want a specific version, or a different agent entirely, provide your own image:
Agent state directory: three modes
/home/claude/.claude inside the container holds auth tokens, MCP config, and session history. There are three ways to back it:
-
Per-invocation docker volume (default). Fresh each run → you’ll be prompted to log in again on every
vault run. Safe to run concurrent sessions because every container has its own volume. -
Shared docker volume (
--home-volume-shared). Persistent named docker volume across invocations. Auth persists.Don’t run two--home-volume-sharedsessions concurrently — there’s no locking, and the volume’s contents will race. -
Bind-mount the host’s
~/.claude(--share-agent-dir). Reuses your existing host login — starting the container feels identical to runningclaudeon the host (no onboarding, your project history is there). Mutually exclusive with--home-volume-shared.Concurrency matches the status quo of runningclaudedirectly on the host — session files are UUID-keyed, so two concurrent containers behave the same as two host-level Claude sessions. On Linux, agent-vault passesHOST_UID/HOST_GIDso the container’sclaudeuser matches your host uid — writes to the bind mount land owned by you, not the baked-in container uid. macOS auth bridge. Claude stores its OAuth credential in the macOS Keychain, not on disk, so the bind mount alone doesn’t carry the login across. When--share-agent-diris set on a Mac host, agent-vault callssecurity find-generic-password -s "Claude Code-credentials" -wonce to extract the credential and writes it to~/.claude/.credentials.json(mode 0600) — the path Linux Claude reads. Only runs if the file is absent; the container (or you) can refresh it thereafter. First use may trigger a Keychain confirmation prompt. Trade-off: the credential now exists as a filesystem-readable file on your Mac, slightly weaker than Keychain-only storage. If you’d rather avoid that, skip--share-agent-dir(orrm ~/.claude/.credentials.jsonand/logininside the container — Claude will write a fresh file itself).
~/.claude is the agent’s own identity — sharing it with the agent inside the container is strictly a UX choice, not a credential exposure, since the agent already needs that identity to function. The genuinely sensitive ~/.agent-vault/ directory stays off-limits in all three modes.
Threat model
In scope. The agent (and any subprocess it spawns) cannot:- Reach destinations outside
host.docker.internal:<agent-vault-port>via any network method (HTTPS, raw sockets, ICMP, whatever) — iptables DROPs at the kernel before the packet leaves the container. - Exfiltrate over DNS — no DNS rule, no resolver,
host.docker.internalis baked into/etc/hosts. - Inspect or mutate host state outside the workspace and its own ephemeral home volume.
- Drop its own iptables rules —
gosu clauderuns UID != 0, Docker doesn’t grant container capabilities as ambient caps to non-root processes.
- Container escapes via kernel exploits. We rely on Docker’s standard isolation.
- Exfiltration through Agent Vault to whitelisted upstreams (e.g. Anthropic API). Agent Vault’s service catalog and credential-injection policy govern that; the container just guarantees traffic can’t bypass the broker.
- Side channels (timing, resource usage).
Platform support
- Linux: supported. Requires Docker 20.10+ for
--add-host=host.docker.internal:host-gateway. - macOS (Docker Desktop): supported.
- Windows: not supported in v1.
vault run --isolation=containererrors on Windows.
Troubleshooting
“docker not found in PATH” — install Docker Desktop (macOS) or Docker Engine (Linux) and make suredocker is on PATH.
“host.docker.internal not resolvable” inside the container — Docker version is too old. Upgrade to 20.10+ on Linux.
First run hangs — the image build pulls node:22-bookworm-slim and runs apt-get install + npm install -g @anthropic-ai/claude-code. ~60 seconds on a fast connection; a slow network or corporate registry proxy can make it much longer. Watch docker ps in another terminal to confirm progress.
iptables -S OUTPUT in the container shows DROP but the agent still makes external calls — that’s impossible unless you passed --no-firewall. Check for the loud warning banner on startup.
Containers leak after crashes — agent-vault vault run --isolation=container runs PruneStaleNetworks at startup, removing any agent-vault-* networks older than 60 seconds with zero attached containers. The 60-second grace window prevents racing invocations from deleting each other’s freshly-created networks.
Related
- Connect a coding agent — the standard
--isolation=hostworkflow. - CLI reference — full flag table.