/sandbox-lifecycle
The lifecycle gate for a local Codespace-equivalent sandbox. Routed to when the user invokes /ca-sandbox:sandbox to pull an untrusted repo into an ephemeral, host-FS-isolated Docker container, or any of the interaction commands (/ca-sandbox:sandbox-shell,
$ npx -y skills add arbiterForge/codeArbiter --skill sandbox-lifecycle --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-lifecycle
Context preview
The summary Claude sees to decide when to auto-load this skill.
The lifecycle gate for a local Codespace-equivalent sandbox. Routed to when the user invokes /ca-sandbox:sandbox to pull an untrusted repo into an ephemeral, host-FS-isolated Docker container, or any of the interaction commands (/ca-sandbox:sandbox-shell,
SKILL.md
sandbox-lifecycle.SKILL.mdname: sandbox-lifecycle
description: The lifecycle gate for a local Codespace-equivalent sandbox. Routed to when the user invokes /ca-sandbox:sandbox to pull an untrusted repo into an ephemeral, host-FS-isolated Docker container, or any of the interaction commands (/ca-sandbox:sandbox-shell, /ca-sandbox:sandbox-exec, /ca-sandbox:sandbox-cp, /ca-sandbox:sandbox-destroy) against an existing box. Five gated phases — pre-flight, clone+build, isolated run, interact, teardown. The load-bearing invariant is structural: untrusted code in the box can never reach the host filesystem (no bind mount, no docker socket, never --privileged, cap-drop ALL, non-root, read-only root). Network defaults to offline; egress out is host-initiated only. Every object is labeled ca.sandbox=1 and torn down on exit.
sandbox-lifecycle
Pull an untrusted repo into a throwaway box, explore it without risking the host, then burn the box. This skill owns the whole arc — clone into a named volume, build a dep-cached image, run it under structural isolation, interact (shell / exec / cp out), destroy — and the one invariant that makes it safe: **the code inside the box can never touch the host filesystem.** That guarantee is enforced by construction (no bind mounts, no docker socket, never `--privileged`), not by trusting the repo.
The driver lives in `${CLAUDE_PLUGIN_ROOT}/tools`. The skill never hand-rolls a `docker run` argv — every container is started through `runContainer` in `${CLAUDE_PLUGIN_ROOT}/tools/run.ts`, whose mount argv comes only from `buildMountArgs` in `${CLAUDE_PLUGIN_ROOT}/tools/mounts.ts` (the chokepoint that throws on any bind spec).
Pre-flight
Read these, or STOP and surface the gap — never guess a Docker capability, a mount layout, or an egress posture:
- `${CLAUDE_PLUGIN_ROOT}/tools/mounts.ts` — the mount-arg chokepoint. Every mount is built here; it throws (`BindMountRejectedError`) on any `type=bind` spec. The structural half of the host-FS invariant.
- `${CLAUDE_PLUGIN_ROOT}/tools/run.ts` — the isolation flags (`--cap-drop ALL`, non-root `--user 1000:1000`, `--read-only`, `--security-opt no-new-privileges`, resource caps) and the `offline` => `--network none` default.
- `${CLAUDE_PLUGIN_ROOT}/tools/network.ts` — the network policies (offline / clone-then-cut / allowlist). The IP allowlist is EXPERIMENTAL (`ALLOWLIST_EXPERIMENTAL`); offline and clone-then-cut are the solid defaults.
Host prerequisites: **Docker** and **nixpacks** on `PATH` (the plugin's `description` states this). If `docker info` fails, STOP and report "Docker is not available" — do not proceed to clone or build. If the user supplies no repo URL to `/ca-sandbox:sandbox`, ask for one — do not guess a repo.
Phase 1 — Pre-flight & policy · gate: BLOCK
Establish what is being sandboxed and under what egress posture before any clone:
- **Target** — the repo URL (or local path) to pull. One source, stated explicitly.
- **Network policy** — `offline` (default), `clone-then-cut` (fetch deps at build, cut egress at run), or `allowlist` (EXPERIMENTAL — name it as experimental every time it is selected). Default to `offline` unless the user names another.
- **Docker reachable** — `docker info` returns 0. If not, STOP here.
- **`--with-claude`** — if requested, route to the `sandbox-claude-inside` skill (`${CLAUDE_PLUGIN_ROOT}/skills/sandbox-claude-inside/SKILL.md`) for its hardened defaults; it is NOT enabled on the default path.
Gate: a named target, a named network policy, and a reachable Docker. A sandbox with no stated target or an unreachable Docker cannot be built — do not improvise either. If `allowlist` is chosen, the BLOCK is conditional on the user acknowledging it is experimental.
Phase 2 — Clone & build · gate: BLOCK
Clone the target into a docker **named volume** (never onto the host FS, never a bind), then build a dep-cached image:
- Clone into the named volume via `createSandbox` (`${CLAUDE_PLUGIN_ROOT}/tools/create.ts`); the source lives at `/work/repo` inside the box.
- Build through `${CLAUDE_PLUGIN_ROOT}/tools/build.ts`: nixpacks wraps the repo, deps are relocated **out of tree to `/deps`** (exported via `NODE_PATH`/`PYTHONPATH`/`GOPATH`/`CARGO_HOME`), and the image is tagged `ca-sbx:<repo>-<dephash>`.
- The dephash comes from `computeDepHash` (`${CLAUDE_PLUGIN_ROOT}/tools/dephash.ts`) over the manifest/lockfile set. An unchanged dep set is a **cache hit** — no rebuild, identical tag. A manifest/lockfile change bumps the dephash and forces a rebuild; a source-only edit does not.
Gate: a built (or cache-hit) image tagged `ca-sbx:<repo>-<dephash>`, with deps at `/deps` (out of tree). The naive "mount the volume over the app dir" layout shadows baked deps and is forbidden — the volume mounts ONLY at `/work/repo`. If nixpacks is not installed, STOP with the install hint, not a stack trace.
Phase 3 — Isolated run · gate: BLOCK
Start the container through `runContainer` (`${CLAUDE_PLUGIN_ROOT}/tools/run.ts`) — never a hand-written `docker run`. The run carries the structural isolation set, all by construction:
- **No host bind mount, no `/var/run/docker.sock` mount, never `--privileged`** — the three negative guarantees. The mount argv is built only by `buildMountArgs`, which throws on any bind.
- `--cap-drop ALL`, `--user 1000:1000` (non-root), `--read-only` root, `--security-opt no-new-privileges`, resource caps (`--pids-limit`, `--memory`, `--cpus`).
- The live source named volume mounts ONLY at `/work/repo`; `/tmp` is a tmpfs (writable scratch, no host backing).
- Network per Phase 1: `offline` => `--network none`; the richer policies are applied by `${CLAUDE_PLUGIN_ROOT}/tools/network.ts`.
- Every object carries the `ca.sandbox=1` label (the teardown/registry anchor).
Gate: `docker inspect` on the started container shows no `"Type":"bind"` mount, no docker-socket mount, and not `Privileged:true`. If any of the three appears, the run is rejected — there is no override; the chokepoint
Read more
name: sandbox-lifecycle description: The lifecycle gate for a local Codespace-equivalent sandbox. Routed to when the user invokes /ca-sandbox:sandbox to pull an untrusted repo into an ephemeral, host-FS-isolated Docker container, or any of the interaction commands (/ca-sandbox:sandbox-shell, /ca-sandbox:sandbox-exec, /ca-sandbox:sandbox-cp, /ca-sandbox:sandbox-destroy) against an existing box. Five gated phases — pre-flight, clone+build, isolated run, interact, teardown. The load-bearing invariant is structural: untrusted code in the box can never reach the host filesystem (no bind mount, no docker socket, never --privileged, cap-drop ALL, non-root, read-only root). Network defaults to offline; egress out is host-initiated only. Every object is labeled ca.sandbox=1 and torn down on exit.
sandbox-lifecycle
Pull an untrusted repo into a throwaway box, explore it without risking the host, then burn the box. This skill owns the whole arc — clone into a named volume, build a dep-cached image, run it under structural isolation, interact (shell / exec / cp out), destroy — and the one invariant that makes it safe: **the code inside the box can never touch the host filesystem.** That guarantee is enforced by construction (no bind mounts, no docker socket, never `--privileged`), not by trusting the repo.
The driver lives in `${CLAUDE_PLUGIN_ROOT}/tools`. The skill never hand-rolls a `docker run` argv — every container is started through `runContainer` in `${CLAUDE_PLUGIN_ROOT}/tools/run.ts`, whose mount argv comes only from `buildMountArgs` in `${CLAUDE_PLUGIN_ROOT}/tools/mounts.ts` (the chokepoint that throws on any bind spec).
Pre-flight
Read these, or STOP and surface the gap — never guess a Docker capability, a mount layout, or an egress posture:
- `${CLAUDE_PLUGIN_ROOT}/tools/mounts.ts` — the mount-arg chokepoint. Every mount is built here; it throws (`BindMountRejectedError`) on any `type=bind` spec. The structural half of the host-FS invariant.
- `${CLAUDE_PLUGIN_ROOT}/tools/run.ts` — the isolation flags (`--cap-drop ALL`, non-root `--user 1000:1000`, `--read-only`, `--security-opt no-new-privileges`, resource caps) and the `offline` => `--network none` default.
- `${CLAUDE_PLUGIN_ROOT}/tools/network.ts` — the network policies (offline / clone-then-cut / allowlist). The IP allowlist is EXPERIMENTAL (`ALLOWLIST_EXPERIMENTAL`); offline and clone-then-cut are the solid defaults.
Host prerequisites: **Docker** and **nixpacks** on `PATH` (the plugin's `description` states this). If `docker info` fails, STOP and report "Docker is not available" — do not proceed to clone or build. If the user supplies no repo URL to `/ca-sandbox:sandbox`, ask for one — do not guess a repo.
Phase 1 — Pre-flight & policy · gate: BLOCK
Establish what is being sandboxed and under what egress posture before any clone:
- **Target** — the repo URL (or local path) to pull. One source, stated explicitly.
- **Network policy** — `offline` (default), `clone-then-cut` (fetch deps at build, cut egress at run), or `allowlist` (EXPERIMENTAL — name it as experimental every time it is selected). Default to `offline` unless the user names another.
- **Docker reachable** — `docker info` returns 0. If not, STOP here.
- **`--with-claude`** — if requested, route to the `sandbox-claude-inside` skill (`${CLAUDE_PLUGIN_ROOT}/skills/sandbox-claude-inside/SKILL.md`) for its hardened defaults; it is NOT enabled on the default path.
Gate: a named target, a named network policy, and a reachable Docker. A sandbox with no stated target or an unreachable Docker cannot be built — do not improvise either. If `allowlist` is chosen, the BLOCK is conditional on the user acknowledging it is experimental.
Phase 2 — Clone & build · gate: BLOCK
Clone the target into a docker **named volume** (never onto the host FS, never a bind), then build a dep-cached image:
- Clone into the named volume via `createSandbox` (`${CLAUDE_PLUGIN_ROOT}/tools/create.ts`); the source lives at `/work/repo` inside the box.
- Build through `${CLAUDE_PLUGIN_ROOT}/tools/build.ts`: nixpacks wraps the repo, deps are relocated **out of tree to `/deps`** (exported via `NODE_PATH`/`PYTHONPATH`/`GOPATH`/`CARGO_HOME`), and the image is tagged `ca-sbx:<repo>-<dephash>`.
- The dephash comes from `computeDepHash` (`${CLAUDE_PLUGIN_ROOT}/tools/dephash.ts`) over the manifest/lockfile set. An unchanged dep set is a **cache hit** — no rebuild, identical tag. A manifest/lockfile change bumps the dephash and forces a rebuild; a source-only edit does not.
Gate: a built (or cache-hit) image tagged `ca-sbx:<repo>-<dephash>`, with deps at `/deps` (out of tree). The naive "mount the volume over the app dir" layout shadows baked deps and is forbidden — the volume mounts ONLY at `/work/repo`. If nixpacks is not installed, STOP with the install hint, not a stack trace.
Phase 3 — Isolated run · gate: BLOCK
Start the container through `runContainer` (`${CLAUDE_PLUGIN_ROOT}/tools/run.ts`) — never a hand-written `docker run`. The run carries the structural isolation set, all by construction:
- **No host bind mount, no `/var/run/docker.sock` mount, never `--privileged`** — the three negative guarantees. The mount argv is built only by `buildMountArgs`, which throws on any bind.
- `--cap-drop ALL`, `--user 1000:1000` (non-root), `--read-only` root, `--security-opt no-new-privileges`, resource caps (`--pids-limit`, `--memory`, `--cpus`).
- The live source named volume mounts ONLY at `/work/repo`; `/tmp` is a tmpfs (writable scratch, no host backing).
- Network per Phase 1: `offline` => `--network none`; the richer policies are applied by `${CLAUDE_PLUGIN_ROOT}/tools/network.ts`.
- Every object carries the `ca.sandbox=1` label (the teardown/registry anchor).
Gate: `docker inspect` on the started container shows no `"Type":"bind"` mount, no docker-socket mount, and not `Privileged:true`. If any of the three appears, the run is rejected — there is no override; the chokepoint
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

