Skip to content

Repository files navigation

Sandkeep

Run Claude Code agents in isolated, disposable sandboxes — one per task, with cheap rollback and a human gate before anything merges.

CI PyPI License

⚠️ Security status — read before using

Sandkeep is alpha. The current sandbox backend is Docker, which is NOT a security boundary — it is a mechanics harness. A determined or compromised agent can escape a container. Do not point Sandkeep at code or agents you genuinely do not trust yet. Real containment (a microVM backend) is planned and will be announced explicitly when it ships. See SECURITY.md.

What it is

Sandkeep orchestrates headless Claude Code agents so each task runs in its own disposable sandbox. The git worktree lives inside the sandbox; only a diff comes back out; a human approves before anything touches your real repo. The point is to run agents on real code without trusting them, and to walk back anything that goes wrong for free.

What it is not

  • Not an agent framework. You bring the agent (Claude Code); Sandkeep governs where it runs.
  • Not production-grade isolation yet. See the security status above.
  • Not autonomous merge. A human gates every change, by design.

Sandkeep or Cordon? — pick by how much you trust the run

Sandkeep has a lighter-weight sibling, Cordon, that enforces the same isolate → review → gate workflow using only Claude Code's native features (worktrees, sandbox, hooks, a governing CLAUDE.md) — no Docker. They sit at two points on one trust dial:

 TRUST HIGH ───────────────────────────────────► TRUST LOW
        CORDON (native discipline)        SANDKEEP (real containment)
   "I trust the agent — keep its work     "I don't trust the agent or the code —
    isolated, reversible, reviewed"        keep it away from my machine"
Use Cordon when… Use Sandkeep when…
Your devs, your code, you want every session isolated/reviewable by default The agent or the code is untrusted (3rd-party, a fork, a sketchy dep)
You want full native speed and the complete Claude Code harness You need a boundary you can point to in a security review
No container runtime available The run is unattended (CI, batch, a fleet)
"Keep me safe from mistakes" "Keep it away from my machine"

They share one vocabulary — isolate → review → gate, accept/reject, an audit trail — so a developer learns it once and slides along the dial as trust changes. Cordon is the everyday driver; Sandkeep is the vault you escalate to.

Quickstart

pip install sandkeep                 # or: uvx sandkeep
sandkeep image build                 # build the sandbox image (Node 22 + claude CLI + git + mise)
sandkeep auth set                    # store your Anthropic API key (hidden prompt, 0600)
                                     # (or: export ANTHROPIC_API_KEY=sk-ant-... — env always wins)
sandkeep auth set E2B_API_KEY        # store other keys the same way (e.g. for the E2B backend)
sandkeep auth status                 # show every stored/active key, masked

# unattended: hand it one task, get back a reviewable diff
sandkeep run --repo /path/to/repo --task "Add input validation to parse_config()"

# OR interactive: a full Claude Code session (chat, skills, MCP, plan mode)
# inside the sandbox, on a throwaway clone — exits at the same review gate
sandkeep shell --repo /path/to/repo

# OR many tasks at once, each in its own sandbox, all landing at the gate
sandkeep batch --repo /path/to/repo --task "fix A" --task "fix B" --max-parallel 4

sandkeep show <task_id>              # review summary + patch + risk flags + conflicts
sandkeep test <task_id> --test-cmd "pytest -q"   # run the tests in the sandbox
sandkeep accept <task_id>            # apply to a fresh branch on your repo
# or
sandkeep reject <task_id>            # discard and tear down the sandbox

sandkeep skills list --repo /path/to/repo   # skills the agent authored for this repo

sandkeep ps                         # list live sandboxes + their task state
sandkeep gc                         # reap orphaned/stale sandboxes (--dry-run to preview)

Useful flags on run/shell:

Flag Effect
--agent <name> pick which agent runs in the sandbox (default claude; also SANDKEEP_AGENT)
--no-network run with no network at all (agent can't reach its API; for boundary testing / offline agents; also SANDKEEP_NETWORK=none)
--browser attach a headless-Chromium sidecar the agent drives over CDP ($SANDKEEP_BROWSER_CDP) — a browser capability without giving the sandbox one; page loads obey the egress policy. Build it with image build --with-browser. Also SANDKEEP_BROWSER
--no-skip-permissions (shell) restore Claude Code permission prompts
--model <id> override the task-tier model

Two ways to run the agent: run (headless, fire-and-forget — good for unattended/CI) and shell (interactive — the full harness on a disposable clone). Both end at the same human gate; nothing touches your real repo until you accept.

Permissions are skipped by default. Both run and shell launch Claude Code with --dangerously-skip-permissions, so the agent never stops to ask you to approve a tool call. This is deliberate: the session runs inside the sandbox on a throwaway clone, so the permission prompt would only add friction without adding a boundary — the containment is the boundary. To restore the prompts in an interactive session, run sandkeep shell --no-skip-permissions. (This flag is host-dangerous and is only ever used inside the sandbox — never on your machine.)

See examples/quickstart.md for an end-to-end first run on a throwaway repo.

How it works

How Sandkeep works — seven steps from provisioning a read-only clone, through running the agent in an isolated sandbox, extracting only the diff, to the human accept/reject gate

  1. Provision — your repo is mounted read-only; the sandbox makes its own independent clone on a task branch.
  2. Run — a headless Claude Code agent works only inside the sandbox, with a scoped tool set.
  3. Extract — only a patch + a structured results contract leave the sandbox.
  4. Gate — you review; on accept, Sandkeep applies the patch to a fresh branch on your repo. Nothing touches your working tree or .git until you say so.

Architecture

The controller is deterministic and runs on the host; agent code only ever executes inside a sandbox. Backends (Docker / E2B microVM) sit behind one SandboxProvider seam, agents behind one AgentDriver seam, and only a patch + results JSON ever crosses back to the human gate. Dashed boxes are the deliberately-unbuilt Phase 2 pieces.

Sandkeep architecture: host controller with SandboxProvider and AgentDriver seams, pluggable Docker/E2B backends, a disposable sandbox holding the read-only clone and agent, an orange patch+JSON return channel, the human gate, and a dashed roadmap band

Source: docs/assets/architecture.svg

What the gate shows you

Every run lands at the human gate with more than just a diff:

  • Diff risk flags — changes touching sensitive surfaces are called out by category: ci/workflow, deploy, auth, secret, dependency. The secret check scans both file paths and added lines (Anthropic/AWS/GitHub tokens, private keys, hardcoded credentials). You see what kind of change you're approving, not just a file list.
  • Cross-task conflicts — if another task awaiting review touches the same files, the gate says so (and accept warns), so approving one can't silently collide with another in flight.

It's advisory — the human still decides. Nothing auto-blocks, nothing auto-merges.

Pluggable agents

The boundary is agent-agnostic — containment comes from the sandbox, not from which agent runs inside it. Agents live behind a single AgentDriver interface, selectable with --agent / SANDKEEP_AGENT. Three ship today: claude (the default, writes a results contract), codex (OpenAI Codex CLI), and gemini (Google Gemini CLI) — the latter two produces_contract=False drivers that land via host-side diff synthesis, and all three run key-broker-protected in proxy mode. Proof the seam works, not just an assertion. Adding another CLI agent is a small, contained change: register a driver and teach the image to install its CLI. An unknown agent fails loud on the host before any sandbox is created, and the unmodified boundary suite passes whichever agent is selected. (Codex CLI flags should be re-verified with codex --help against the installed version, per the same discipline as the Claude driver.)

Capability authoring (per-repo skills)

An agent can author skills while it works — small markdown capability files written under .sandkeep/skills/. These are sandkeep-managed metadata: they're excluded from the patch (they never land in your repo's working tree or .git), surfaced at the gate, and registered to a per-repo store only when you accept. On later runs against the same repo, stored skills are injected so the agent builds on what earlier runs learned. Inspect them with sandkeep skills list --repo <path>. Nothing the agent authored becomes durable without your gate.

Extending it

Two clean extension points:

  • Sandbox backends — Sandkeep talks to sandboxes through one SandboxProvider interface. Adding a new backend (the microVM for real containment, or a remote sandbox service) is the main one, and the contract is strict: any backend must pass the unmodified boundary suite (tests/test_boundary.py).
  • Agents — agents are pluggable behind AgentDriver (--agent); claude is the default. Adding e.g. Codex is a contained change.

Start with CONTRIBUTING.md for setup, the rules, and the extension walkthroughs. If you specifically want to build the real boundary, the step-by-step guide — including a concrete E2B microVM path and how the egress proxy / secret broker slot in — is docs/phase-2-implementation.md.

Requirements

  • Python 3.12+
  • Docker (for the default sandbox backend) — or an E2B API key to use the microVM backend instead (SANDKEEP_BACKEND=e2b)
  • An Anthropic API key (ANTHROPIC_API_KEY)

Platform support

The controller is pure-stdlib Python and the sandbox is always a Linux container, so the host only needs Python, git, and a Docker daemon:

Platform Status
macOS (Intel & Apple Silicon) Tested — full suite, incl. the boundary tests, runs green
Linux ✅ Expected to work (native Docker)
Windows — WSL2 ✅ Recommended path on Windows; effectively the Linux case
Windows — native (PowerShell + Docker Desktop) ⚠️ Untested. Likely works; known risk spots: drive-letter volume-mount syntax, TTY behaviour of sandkeep shell, and CRLF (core.autocrlf) rejecting sandbox-generated patches on accept. Issues welcome.

Note for corporate users: Docker Desktop itself requires a paid subscription above Docker's company-size thresholds (macOS and Windows). That's a Docker constraint, not a Sandkeep one; the planned microVM backend (Phase 2) removes the Docker dependency.

Roadmap

  • Phase 0 — boundary proof (Docker mechanics)
  • Phase 1 — single governed task loop (run + interactive shell, human gate)
  • [~] Phase 2 — real isolation + parallelism. Done: network-off toggle (--no-network), concurrency (batch), an E2B microVM backend with containment verified (9 of the 11 boundary tests pass — all 9 isolation checks; the 2 remaining are tool-presence in the custom template, not containment gaps), and a local key-broker + egress-allowlist (SANDKEEP_NETWORK=proxy) so the agent never holds the API key and can only reach an allowlist — no cloud needed. Pending: E2B proxy parity, draft-PR gate, warm pool
  • Phase 3 — diff risk analysis, cross-task conflict detection, test-gated merge
  • Phase 4 — per-repo skill authoring
  • Phase 5 — pluggable agents (--agent, AgentDriver seam, per-agent images)

The build details for each phase live in BUILD_SPEC.md (§13–§16); the microVM build/verify guide is docs/phase-2-implementation.md.

Cordon — the native sibling

Cordon is the high-trust end of the dial: the same isolate → review → gate discipline, enforced with Claude Code's own primitives instead of a container. A governing CLAUDE.md shepherds the session, hooks block the escape hatches, the Bash sandbox + worktree isolate the work, and review skills (/cordon-review, /cordon-accept) gate the merge — all so every session in a Cordon project is isolated, reversible, and reviewable by default, with zero infrastructure.

It's containment against accidents and misbehavior, not against an adversary — when you genuinely don't trust the code, that's Sandkeep's job, and the two are designed to hand off to each other.

The full build spec lives here: docs/native-harness-build-spec.md. (Cordon ships from its own repo — link TBD once published.)

License

Source-available under the PolyForm Noncommercial License 1.0.0not an OSI open-source license. You may use, modify, and redistribute Sandkeep freely for any noncommercial purpose (personal, research, education, non-profit, evaluation).

Commercial use of any kind requires a paid license. If you want to use Sandkeep in or for a commercial product, service, or business, open an issue to get in touch and arrange one.

See NOTICE for attribution requirements.

About

Run Claude Code agents in isolated, disposable sandboxes — one per task, with cheap rollback and a human gate before anything merges.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages