modebox

v0.1 prototype · MIT · open source

Code mode, sandboxed.

Code mode means your agent writes one script that calls your tools. modebox runs that script in a WebAssembly sandbox and pauses it mid-run when a call needs you. A fresh sandbox starts in about 0.2 ms.

$ npm install modebox

macOS and Linux · Windows isn't supported yet

sandbox · mb_7f3a2crunning
booted from snapshot · ~0.2 ms4 KiB pages

01 pause

How a pause works

1The agent's script runscomputer A1const rows = await db.find({ overdue: true });2for (const c of rows) {3 const amt = refundFor(c);4 await payments.refund(c.id, amt);5}❚❚ needs your OKIt stops right before the refund, and waits.2It saves only what changedmemory pages14 of 156 pages changed. Only those are kept.3It locks them into a tokenencryptedmb1.q8Zt3fX0kR…~16 KB in our benchmarkcompressedencryptedsingle-usezstd · XChaCha20-Poly13054You approve. It carries on.computer B · laterRefund $40.00 to customer c_1042?Approve1–3already done · not run again4 await payments.refund(c.id, amt);5}✓ Approved. It picked up at line 4; nothing ran twice.pauseseallater1The agent's script runscomputer A1const rows = await db.find({ overdue: true });2for (const c of rows) {3 const amt = refundFor(c);4 await payments.refund(c.id, amt);5}❚❚ needs your OKIt stops right before the refund, and waits.2It saves only what changedmemory pages14 of 156 pages changed. Only those are kept.3It locks them into a tokenencryptedmb1.q8Zt3fX0kR…~16 KB in our benchmarkcompressedencryptedsingle-usezstd · XChaCha20-Poly13054You approve. It carries on.computer B · laterRefund $40.00 to customer c_1042?Approve1–3already done · not run again4 await payments.refund(c.id, amt);5}✓ Approved. It picked up at line 4; nothing ran twice.pauseseallater
modebox freezes the run where it stopped, keeps only what changed, and picks it back up after you say yes. Nothing runs twice.

02 inside

What runs where

your app · Node, Python, Rust or the CLIsecretsfilesinternetout of reachSealed sandboxWebAssemblythe agent's scriptawait db.users()await fetch("evil.com")await payments.refund(c, 40)QuickJS engine, booted once · each run gets a fresh copyits own memorythe only doormodebox checksallow · ask · denyyour toolsdatabasepaymentsGitHub❚❚ asks you firstallowedblockedyour app · Node, Python, Rust or the CLIsecretsfilesinternetout of reachSealed sandboxWebAssemblythe agent's scriptawait db.users()await fetch("evil.com")await payments.refund(c, 40)QuickJS engine, booted once · a fresh copy per runits own memorythe only doormodebox checksallow · ask · deny❚❚ asks you firstdatabasepaymentsGitHubyour toolsallowedblocked
The agent's code runs in a sealed box. Its only way out is one door, where modebox lets a request through, asks you, or says no. Everything else is out of reach.

03 at a glance

Memory map

addresssegmentwhat it doescost
0x0000engineQuickJS-ng in WebAssembly. Booted once, copied per run.~0.2 ms
0x4000boundaryOnly the tools you hand it. MCP servers become typed functions.2 imports
0x8000pauseSeals the run into a token, ~16 KB in our benchmark. Resume later, in any process with the same key; nothing re-runs.single-use
0xC000filesOne API over local, S3, R2, GCS and Azure. Writes wait for you.staged
0x10000shellsh() under Seatbelt or bubblewrap + seccomp. Network off, or listed hosts only.per host

04 use it

Pick how you run it

Over MCP, or from your own code.

$ cargo install modebox
modebox.json
{
  "mcpServers": {
    "github": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"]
    }
  },
  "approve": ["github.*"]
}
$ claude mcp add --scope project modebox -- modebox mcp -c modebox.json

opencode, Codex, Cursor and other agents: the setup guide.

  • Claude Code
  • opencode
  • Codex
  • Cursor
  • T3 Code
  • Node
  • Python
  • Rust