Claude Sandbox for VS Code
README.md
# Claude Sandbox for VS Code
Makes VS Code the IDE of a Claude Code session that runs inside
[claude-sandbox](https://github.com/DiamondLightSource/claude-sandbox): Claude
sees your editor selection, shows proposed edits as diffs in VS Code for you to
accept or reject, and reads the workspace's diagnostics. It speaks Claude
Code's IDE protocol (MCP over a WebSocket), the role Anthropic's own extension
plays for an unsandboxed Claude. claude-sandbox itself is not changed.
**Status: stage 1.** The bridge works; the terminal launcher is not built yet.
Run **Claude Sandbox: Copy launch command** and paste the copied
`claude --settings '…'` into a devcontainer terminal in the workspace folder.
## How it works
1. The extension listens on a Unix socket in the workspace root
(`.claude-sandbox-vscode-<port>.sock`, mode 0600), which the jail can see.
2. claude-sandbox is given `--settings` with `CLAUDE_CODE_SSE_PORT` and
`SessionStart`/`SessionEnd` hooks. Inside the jail the start hook starts
`socat` (TCP `127.0.0.1:<port>` to the socket) unless it already runs, and
once it listens writes Claude Code's lock file
(`~/.claude/ide/<port>.lock`, with the auth token), never over an existing
one. The end hook removes it on a real exit (not on `/clear` or `/resume`).
3. Claude Code connects; the extension checks the token and serves four MCP
tools: `openDiff`, `close_tab`, `closeAllDiffTabs`, `getDiagnostics`.
One linked Claude session per VS Code window, in a devcontainer with
claude-sandbox installed: while it is connected, another connection is
refused. Other Claude sessions run sandboxed without the IDE link.
The full design and the protocol notes are in [docs/design.md](docs/design.md).
## Security
The extension host runs outside the sandbox with your full privileges, and
anything inside the sandbox can read the token and reach the socket, so every
message is treated as hostile ([trust boundary](docs/design.md#trust-boundary)):
- Only the four tools above; nothing that runs code, opens URLs or writes files.
- `openDiff` reads only real paths inside a workspace folder, never in `.git`,
one path component at a time without following symlinks (a symlink swapped
in after the check is refused).
- The extension never writes a workspace file: Accept hands the text back and
Claude writes it from inside the sandbox. Closing a diff is a rejection.
Accept and Reject work from either side of the diff.
- Diagnostics and selections are sent only for workspace files.
- The host never writes into the sandbox's `~/.claude`; the in-sandbox hook
writes the lock file, and every value in its shell command is validated and
quoted. The host deletes nothing in the workspace either (its own socket
goes when the link closes).
- The hand-written WebSocket server has no runtime dependencies: messages are
capped at 16 MiB (from the frame header), at most 4 connections in their
handshake and one linked session, a handshake timeout, backpressure on
output (a client that stops reading is not read, and is dropped past
32 MiB queued), a ping every 30 s (a client that answers nothing is
dropped), permessage-deflate refused, parsed JSON never merged into
objects, and nothing from the sandbox logged unescaped.
- The token appears in claude-sandbox's argv. Other users cannot use it (the
socket is 0600); processes running as you are already trusted.
Every rule has a test in `test/hostile/` or `test/unit/`; the mapping is in
[docs/design.md](docs/design.md#rule--test).
**Out of scope (residual risk).** VS Code on a workspace the sandbox can write
is exposed whether or not this extension is installed: `.vscode/settings.json`
(interpreter paths, tasks) and `.git/config` (fsmonitor, filter drivers) run
on the host. Keep such workspaces untrusted in VS Code's Workspace Trust, or
review the agent's changes to them before reopening.
## Development
Linux, Node 22.18 or later (tests run the TypeScript directly), and `socat` for
the end-to-end hook test.
```sh
npm ci
npm run typecheck
npm test # node --test: test/unit and test/hostile
npm run build # esbuild → dist/extension.cjs
npm run package # .vsix via @vscode/vsce
```
## License
MIT, Copyright (c) 2026 Diamond Light Source Ltd.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues