/sandbox-claude-inside
Run Claude Code INSIDE a ca-sandbox box (`--with-claude`). Routed to when the user wants an agent loop running against an isolated, ephemeral sandbox rather than the host. Authenticates via an env-injected CLAUDE_CODE_OAUTH_TOKEN with no host bind of ~/.claude; the image pins
$ npx -y skills add arbiterForge/codeArbiter --skill sandbox-claude-inside --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/sandbox-claude-inside
Context preview
The summary Claude sees to decide when to auto-load this skill.
Run Claude Code INSIDE a ca-sandbox box (`--with-claude`). Routed to when the user wants an agent loop running against an isolated, ephemeral sandbox rather than the host. Authenticates via an env-injected CLAUDE_CODE_OAUTH_TOKEN with no host bind of ~/.claude; the image pins
SKILL.md
sandbox-claude-inside.SKILL.mdname: sandbox-claude-inside
description: Run Claude Code INSIDE a ca-sandbox box (`--with-claude`). Routed to when the user wants an agent loop running against an isolated, ephemeral sandbox rather than the host. Authenticates via an env-injected CLAUDE_CODE_OAUTH_TOKEN with no host bind of ~/.claude; the image pins the CLI and disables the autoupdater; HOME is backed by a named volume so the .claude state persists across restart. Five gated phases — posture, image, token, run, teardown. The hard default is offline or Anthropic-domains-only egress, and the token volume is NEVER co-mounted with an untrusted-code run; both are enforced, not advised.
sandbox-claude-inside
Put Claude Code in the box, not the box on your machine. `--with-claude` runs the CLI inside a host-FS-isolated ca-sandbox container, authenticating from an env-injected token with no host bind of `~/.claude` — the mechanism proven by Spike B (`.codearbiter/spikes/ca-sandbox-claude-auth.md`, CONFIRM-07). It is the deliberately-hardened lane: a token in a box is stealable, so the posture is locked down by construction (offline or Anthropic-only egress, token volume never shared with untrusted code), never left to operator discipline.
Pre-flight
Read these, or STOP and surface the gap — never guess the token source, the egress posture, or the persistence mechanism:
- `${CLAUDE_PROJECT_DIR}/.codearbiter/spikes/ca-sandbox-claude-auth.md` — the
proven auth path (env token → real `401` on a dummy), the named-volume HOME persistence mechanism, and the load-bearing caveat that fixes the hard default.
- `${CLAUDE_PROJECT_DIR}/.codearbiter/spikes/ca-sandbox-egress.md` — why the
egress allowlist is EXPERIMENTAL (CDN drift + DNS-exfil hole), so `offline` is the only GUARANTEED posture for a token-bearing box.
- `${CLAUDE_PROJECT_DIR}/.codearbiter/decisions/0007-second-plugin-ca-sandbox.md`
— the governing decision; ca-sandbox is infrastructure, sibling to `ca`.
The shipped driver is `plugins/ca-sandbox/tools/claude-inside.js`, its OWN binary rather than a `sandbox` subcommand (#377):
node <plugin>/tools/claude-inside.js --image <tag> --home-volume <name> [--net offline|anthropic-only]
That separation IS the gate. A `sandbox with-claude` subcommand would let anyone start a token-bearing box with one ungated command, which would turn the five BLOCK phases below from enforcement into advice. This routine is the only sanctioned caller.
The token MUST come from the approved store as `CLAUDE_CODE_OAUTH_TOKEN`, in the ENVIRONMENT. The entry point refuses a `--token` flag outright: an argument list is world-readable, so passing a credential there publishes it to every process on the host. In tests use a DUMMY token only.
Sources: `plugins/ca-sandbox/tools/claude-inside.ts` (`buildClaudeImageDockerfile`, `buildClaudeRunArgs`, `runClaudeInside`, `TokenCoMountRejectedError`) and `claude-inside-cli.ts` (the entry).
Phase 1 — Posture · gate: BLOCK
Fix the egress posture and the trust boundary BEFORE anything is built or started. A token-bearing box is the one place ca-sandbox's FS-isolation invariant and a live credential are in direct tension — resolve it here, explicitly.
- **Egress** — choose exactly one: `offline` (default, GUARANTEED — no interface at
all) or `anthropic-only` (the EXPERIMENTAL Anthropic-domains allowlist, for interactive inference). No third option exists; a wide-open policy is rejected.
- **Trust boundary** — the box runs Claude, NOT the untrusted source repo. Confirm
the run mounts only the token/home volume, never the source volume at `/work/repo`. If the user wants Claude to read an untrusted repo, that is a SEPARATE, source-only box without the token — say so.
Gate: a named egress posture (`offline` or `anthropic-only`) AND an explicit statement that this box carries the token and NOT untrusted source. If the user asks for both at once, STOP and split them — the co-mount is forbidden (Phase 4).
Phase 2 — Image · gate: BLOCK
Build (or reuse) the pinned `--with-claude` image via `buildClaudeImageDockerfile`.
- The image installs `@anthropic-ai/claude-code@<pinned>` — a PINNED semver,
never `@latest` — and bakes `DISABLE_AUTOUPDATER=1` so the box never silently pulls an unreviewed CLI into a token-bearing environment.
- The base is `node:22-slim` (Spike B installed the CLI cleanly there), bound to a
reviewed content DIGEST — `node:22-slim@sha256:…`, the `CLAUDE_BASE_IMAGE` constant. The tag is kept only as human-readable provenance; docker resolves the digest. This is the driver's highest-stakes pin: the base image's code runs in the SAME container as `CLAUDE_CODE_OAUTH_TOKEN`, so a retag or registry compromise would otherwise execute unreviewed code alongside a live credential. Pinning the CLI version alone is not enough. HOME is baked to the in-container claude home so the named volume has a writable mount point.
Gate: the image carries the exact pinned version (`claude --version` reports it), `DISABLE_AUTOUPDATER=1`, and a digest-pinned base. A floating or unpinned CLI — or an unpinned base image — fails the gate; image reproducibility is non-negotiable for a token box. Changing the digest is a reviewed dependency change: re-resolve it with `docker buildx imagetools inspect`, then re-run the credential-boundary and isolation suites.
Phase 3 — Token · gate: BLOCK
Source the OAuth token and confirm it is injected as ENV, never bound from the host.
- The token comes from the approved secret store as `CLAUDE_CODE_OAUTH_TOKEN`
(auth-precedence #5, from `claude setup-token`). It is env-injected (`-e CLAUDE_CODE_OAUTH_TOKEN=…`) — this IS the auth path; no host bind of `~/.claude` is required or permitted.
- The token MUST NOT be echoed to logs, written to a file the source volume can
read, or passed into any LLM prompt. Prefer a scoped/short-lived setup-token.
- Persistence: HOME is backed by a docker NAMED VOLUME, so the credential
Read more
name: sandbox-claude-inside description: Run Claude Code INSIDE a ca-sandbox box (`--with-claude`). Routed to when the user wants an agent loop running against an isolated, ephemeral sandbox rather than the host. Authenticates via an env-injected CLAUDE_CODE_OAUTH_TOKEN with no host bind of ~/.claude; the image pins the CLI and disables the autoupdater; HOME is backed by a named volume so the .claude state persists across restart. Five gated phases — posture, image, token, run, teardown. The hard default is offline or Anthropic-domains-only egress, and the token volume is NEVER co-mounted with an untrusted-code run; both are enforced, not advised.
sandbox-claude-inside
Put Claude Code in the box, not the box on your machine. `--with-claude` runs the CLI inside a host-FS-isolated ca-sandbox container, authenticating from an env-injected token with no host bind of `~/.claude` — the mechanism proven by Spike B (`.codearbiter/spikes/ca-sandbox-claude-auth.md`, CONFIRM-07). It is the deliberately-hardened lane: a token in a box is stealable, so the posture is locked down by construction (offline or Anthropic-only egress, token volume never shared with untrusted code), never left to operator discipline.
Pre-flight
Read these, or STOP and surface the gap — never guess the token source, the egress posture, or the persistence mechanism:
- `${CLAUDE_PROJECT_DIR}/.codearbiter/spikes/ca-sandbox-claude-auth.md` — the
proven auth path (env token → real `401` on a dummy), the named-volume HOME persistence mechanism, and the load-bearing caveat that fixes the hard default.
- `${CLAUDE_PROJECT_DIR}/.codearbiter/spikes/ca-sandbox-egress.md` — why the
egress allowlist is EXPERIMENTAL (CDN drift + DNS-exfil hole), so `offline` is the only GUARANTEED posture for a token-bearing box.
- `${CLAUDE_PROJECT_DIR}/.codearbiter/decisions/0007-second-plugin-ca-sandbox.md`
— the governing decision; ca-sandbox is infrastructure, sibling to `ca`.
The shipped driver is `plugins/ca-sandbox/tools/claude-inside.js`, its OWN binary rather than a `sandbox` subcommand (#377):
node <plugin>/tools/claude-inside.js --image <tag> --home-volume <name> [--net offline|anthropic-only]
That separation IS the gate. A `sandbox with-claude` subcommand would let anyone start a token-bearing box with one ungated command, which would turn the five BLOCK phases below from enforcement into advice. This routine is the only sanctioned caller.
The token MUST come from the approved store as `CLAUDE_CODE_OAUTH_TOKEN`, in the ENVIRONMENT. The entry point refuses a `--token` flag outright: an argument list is world-readable, so passing a credential there publishes it to every process on the host. In tests use a DUMMY token only.
Sources: `plugins/ca-sandbox/tools/claude-inside.ts` (`buildClaudeImageDockerfile`, `buildClaudeRunArgs`, `runClaudeInside`, `TokenCoMountRejectedError`) and `claude-inside-cli.ts` (the entry).
Phase 1 — Posture · gate: BLOCK
Fix the egress posture and the trust boundary BEFORE anything is built or started. A token-bearing box is the one place ca-sandbox's FS-isolation invariant and a live credential are in direct tension — resolve it here, explicitly.
- **Egress** — choose exactly one: `offline` (default, GUARANTEED — no interface at
all) or `anthropic-only` (the EXPERIMENTAL Anthropic-domains allowlist, for interactive inference). No third option exists; a wide-open policy is rejected.
- **Trust boundary** — the box runs Claude, NOT the untrusted source repo. Confirm
the run mounts only the token/home volume, never the source volume at `/work/repo`. If the user wants Claude to read an untrusted repo, that is a SEPARATE, source-only box without the token — say so.
Gate: a named egress posture (`offline` or `anthropic-only`) AND an explicit statement that this box carries the token and NOT untrusted source. If the user asks for both at once, STOP and split them — the co-mount is forbidden (Phase 4).
Phase 2 — Image · gate: BLOCK
Build (or reuse) the pinned `--with-claude` image via `buildClaudeImageDockerfile`.
- The image installs `@anthropic-ai/claude-code@<pinned>` — a PINNED semver,
never `@latest` — and bakes `DISABLE_AUTOUPDATER=1` so the box never silently pulls an unreviewed CLI into a token-bearing environment.
- The base is `node:22-slim` (Spike B installed the CLI cleanly there), bound to a
reviewed content DIGEST — `node:22-slim@sha256:…`, the `CLAUDE_BASE_IMAGE` constant. The tag is kept only as human-readable provenance; docker resolves the digest. This is the driver's highest-stakes pin: the base image's code runs in the SAME container as `CLAUDE_CODE_OAUTH_TOKEN`, so a retag or registry compromise would otherwise execute unreviewed code alongside a live credential. Pinning the CLI version alone is not enough. HOME is baked to the in-container claude home so the named volume has a writable mount point.
Gate: the image carries the exact pinned version (`claude --version` reports it), `DISABLE_AUTOUPDATER=1`, and a digest-pinned base. A floating or unpinned CLI — or an unpinned base image — fails the gate; image reproducibility is non-negotiable for a token box. Changing the digest is a reviewed dependency change: re-resolve it with `docker buildx imagetools inspect`, then re-run the credential-boundary and isolation suites.
Phase 3 — Token · gate: BLOCK
Source the OAuth token and confirm it is injected as ENV, never bound from the host.
- The token comes from the approved secret store as `CLAUDE_CODE_OAUTH_TOKEN`
(auth-precedence #5, from `claude setup-token`). It is env-injected (`-e CLAUDE_CODE_OAUTH_TOKEN=…`) — this IS the auth path; no host bind of `~/.claude` is required or permitted.
- The token MUST NOT be echoed to logs, written to a file the source volume can
read, or passed into any LLM prompt. Prefer a scoped/short-lived setup-token.
- Persistence: HOME is backed by a docker NAMED VOLUME, so the credential
Showing the first part of this file.
When you can't trust yourself with your code base, trust Arbiter.
Repo: arbiterForge/codeArbiter
Other skills on codearbiter.
- /brainstorming
The Socratic spec-refinement front of /feature, and the planning front of /sprint. Routed to BEFORE any code — it takes a one-line idea and drives it to an approved, concrete spec with testable acceptance criteria. Four gated phases — frame, refine, write, approve. No
Open skill - /commit-gate
The only path to a commit. Routed to when the user invokes /commit or otherwise instructs codeArbiter to persist staged changes. Nine gated phases — permission, branch, classification, verification (test/lint/secrets), behavioral proof, diff review, selective stage, message,
Open skill - /context-check
Optional manual drift audit — report stale provenance-tracked docs (via _provenancelib drift detection across .codearbiter/.provenance/), then per stale doc offer re-scout / re-baseline / defer. Not the daily loop; commit-gate auto-heal owns routine maintenance.
Open skill - /context-creation
The brownfield back-fill. Routed to by /create-context, and by startup when .codearbiter/CONTEXT.md lacks the <!--INITIALIZED--> body marker but source code exists. Six gated phases — pre-flight, scout dispatch, synthesis, gap interview, write, lock. Reads the existing codebase
Open skill - /crypto-compliance
The banned-primitive gate. Routed to when changed code hashes, signs, encrypts, derives keys, generates security-relevant randomness, configures TLS, or imports a crypto library. Rejects broken primitives, disabled TLS verification, and home-rolled crypto; the approved-primitive
Open skill - /debug
Investigate-then-decide root-cause analysis for a defect whose cause is unknown (distinct from /fix, which assumes a known bug). Five gated phases: capture, hypothesize, gather, decide, hand off. Investigation only, no code changes; exits to /fix, /adr, or a no-action close.
Open skill

