Original Reddit post

I wanted Claude Code boxed in, away from my Mac’s files, credentials and other projects, without giving up the native apps I like. Here’s where I landed after a lot of testing. Happy to hear where it falls short. The setup Anthropic’s reference dev container (Dockerfile, devcontainer.json, firewall script) as the base, on OrbStack, started with the Dev Containers CLI pointed at one shared config: devcontainer up --workspace-folder <repo> --config <shared-folder>/devcontainer.json Repos live on the Mac; each container mounts its own repo as its workspace, without unrelated projects or personal folders Each container runs a key-only SSH server, so you can reach Claude Code however you like: Claude Desktop’s SSH sessions, or plain ssh from a terminal and run claude there. Either way, Claude’s commands and edits happen inside the container Zed and GitHub Desktop run natively on the Mac against the same folder The shared config lives outside every repo, so Claude can’t edit its own container config What I changed from the reference Added the SSH server: key-only, no passwords, no root, one user. No port is published; you reach it through OrbStack’s per-container hostname, claude-<repo>.orb.local Mounted .git/hooks and .git/config read-only, so Claude can’t directly modify the repo’s git hooks or local git config. Git runs on the Mac against the same folder (GitHub Desktop for me, but the same goes for the git CLI or an editor’s git panel), so this reduces the risk of something running on the Mac. It doesn’t cover other files you run on the Mac (see Limits) The firewall installs “block everything” rules before anything else; once those are in, a later failure leaves outbound traffic blocked. It allows DNS only to the container’s resolver and drops the reference’s rule allowing the whole host network. In my tests the container couldn’t reach the Mac or anything off the allowlist, over IPv4 or IPv6 SSH only starts if the firewall succeeds. Added to the reference’s existing mounts and settings: “mounts”: [ “source=${localWorkspaceFolder}/.git/hooks,target=${localWorkspaceFolder}/.git/hooks,type=bind,readonly”, “source=${localWorkspaceFolder}/.git/config,target=${localWorkspaceFolder}/.git/config,type=bind,readonly” ], “postStartCommand”: “sudo /usr/local/bin/init-firewall.sh && sudo /usr/local/bin/start-sshd.sh” What it buys you The main payoff: I’m comfortable running Claude in auto mode (Claude handles permissions) instead of approving every command. Anthropic’s dev container docs go further and allow skipping permissions entirely in a setup like this, since commands are confined to the container and outbound traffic is restricted Most mistakes stay inside the repo and the allowlist instead of reaching my Mac, and git plus backups cover the repo My Mac’s credentials, SSH keys and other projects aren’t mounted into the container. Claude’s own sign-in token and any secrets in the repo are still in there A prompt injection from a malicious file or web page has much less to work with: no host files, and no internet beyond the allowlist Gotchas On my Mac, Claude Desktop needed Local Network permission (macOS Privacy & Security) to reach the .orb.local hostnames. Without it, SSH failed with “no route to host” The firewall and SSH only start through devcontainer up . Start a container any other way (OrbStack’s play button, docker start ) and it runs without the firewall. After a reboot it’s one command per repo Plugin connectors (Slack, Notion, etc.) fail inside the container because the firewall blocks them. That’s intended You sign in to Claude once per container What I tried and dropped VS Code “Reopen in Container”: manages containers for you, but keeps a live link back to the Mac (credential sharing, port forwarding, a control socket). Some of that can be turned off in settings Zed’s built-in dev containers: on 1.23.3 I reproduced two bugs: startup commands with arguments break ( #62964 ), and readonly on mounts is silently ignored (reported upstream). Avoid for now if you rely on read-only mounts Claude Remote Control instead of SSH: would remove the SSH setup, but adds a control channel through Anthropic, so your Claude account becomes a way into the container. I haven’t tested it with my firewall. I preferred direct SSH Claude Code’s built-in sandbox on its own: per Anthropic’s docs, it covers shell commands only; Claude’s file tools, MCP servers and hooks run outside it. I wanted one boundary around the whole Claude process Limits Claude can still read and change anything in the mounted repo. It can also read its own sign-in token, so only use this with repos you trust Every allowed service is a possible way out if a prompt injection hands Claude someone else’s credentials (GitHub, npm, even the Anthropic API). The firewall also filters by IP address, so a CDN-hosted domain can open other sites on the same addresses, and DNS can still leak small amounts of data The container isolates Claude’s execution, not the repo’s contents. Because native apps use the same files, anything that runs repo code on the Mac (builds, npm scripts, an editor’s project settings) is a path across the boundary No setup like this is airtight. The firewall runs inside the container, so a root escalation could switch it off, and Anthropic’s reference is an example, not a maintained image submitted by /u/reminiscent-fruitbat

Originally posted by u/reminiscent-fruitbat on r/ClaudeCode