Add claude-code-sandbox example - #20
Draft
opencolin wants to merge 3 commits into
Draft
Conversation
Runs Claude Code headless against a real Git checkout inside a disposable Tenki microVM, then reads back the diff the agent produced. verify.mjs proves the Tenki-facing half with no model key: boot with cloneRepoUrl, npm i -g the CLI, assert its version, edit a file in the checkout, assert the diff round-trips. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uz85xGA4zWSge1BtiDNnSN
Measured: Node 22.22.2 fails to parse `await using`, Node 24.19.0 accepts it. verify.mjs uses try/finally, so CI on Node 20 is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uz85xGA4zWSge1BtiDNnSN
verify.mjs now checks `claude --help` still lists `-p, --print` and `--dangerously-skip-permissions`, since npm installs whatever version is latest at run time. An ExecOptions.env value of undefined arrives in the guest as an empty string rather than unset, which is why run.mjs filters the passthrough list; measured, and now stated where it matters. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uz85xGA4zWSge1BtiDNnSN
This was referenced Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude Code running headless against a real Git checkout inside a disposable Tenki microVM. The last line of
run.mjsprintsgit diff— the agent changed a real upstream repo in a machine that gets deleted a second later.Shape:
createAndWait({ cloneRepoUrl })→npm i -g @anthropic-ai/claude-code→claude -p "<task>" --dangerously-skip-permissionswith the model key passed throughExecOptions.envand the turn streamed viaonOutput→git -C repo diff.The task given to the agent is concrete (add a
toArray()method toyocto-queue, declare it inindex.d.ts, add a test), so the diff spans three real files rather than demonstrating nothing.Verification
Ran
node verify.mjslocally against the live API:Exit code 0. Per CONTRIBUTING, it proves the Tenki-facing half with no model key (the
langchain-code-interpreterpattern), asserting real values rather than truthiness:repo/package.jsonreally isyocto-queuenpm i -g @anthropic-ai/claude-codeexits 0claude --versionmatches\d+\.\d+\.\d+ (Claude Code)claude --helpstill lists-p, --printand--dangerously-skip-permissions— npm installs whatever is latest at run time, so the flagsrun.mjsdepends on are checked rather than assumedNot exercised: the agent turn in
run.mjsneeds anANTHROPIC_API_KEY, which this environment does not have, so theclaude -pcall itself was not run end to end. Everything around it was measured live inside a sandbox — CLI install (~5s),claude --version→ 2.1.209,cwd: "repo"resolution,ExecOptions.envpassthrough, andclaude -p "hi" --dangerously-skip-permissionsreachingNot logged inas usertenki, which confirms the flag parses and there is no root refusal.Table placement
Added one row to Developer tools, next to the MCP server row. Claude Code is a CLI you point at a repo, not a framework you build an agent with — it belongs beside AgentBox and the MCP server rather than in Agent frameworks, which is for SDKs given a sandboxed execution tool.
Two gotchas worth a reviewer's eye
sandbox.git.diff()does not work here.sandbox.git.*executes at the sandbox workdir (/home/tenki), butcloneRepoUrlchecks out one level down into/home/tenki/repo, so it fails withnot a git repository. Confirmed live for bothcloneRepoUrlandsandbox.git.clone();git.diff({ path: "repo" })fails the same way, andgit.clone(url, { directory: "." })fails because the workdir already has dotfiles. The example reads the diff withsandbox.exec("git", { args: ["-C", "repo", "diff"] })and documents why in Notes.Top-level
await usingneeds Node 24+, not Node 20. Node 22.22.2 fails to parse it; 24.19.0 accepts it.run.mjssays so;verify.mjsusestry/finally, so CI on Node 20 is unaffected. Note this also applies to the already-shippedrun.mjsfiles and the root README's "Node.js 20 or later" — out of scope for this PR, but worth a follow-up.Touches only
examples/claude-code-sandbox/and the one README row.