DEV Community

Kohki Makimoto
Kohki Makimoto

Posted on

claude-sandbox: Yet another sandboxing tool for Claude Code on macOS

This post walks through claude-sandbox, a small tool I built to bring predictable, low-friction sandboxing to Claude Code on macOS.

The Problem with the Built-in Sandbox

Claude Code ships with a built-in sandboxing feature. It's capable, but it wasn't a great fit for my workflow:

  • It kept blocking legitimate operations in unexpected ways, and troubleshooting took more time than the protection was worth.
  • It includes network isolation, which I didn't need at all — just extra complexity with no benefit for my use case.

What I actually wanted was simple: restrict file writes to the current project directory, with an easy way to allow exceptions when needed. Nothing more.

That's claude-sandbox.

How It Works

claude-sandbox wraps the claude command and runs it under macOS's sandbox-exec (Apple Seatbelt — the same technology used in Claude Code's built-in sandboxing). The default policy is simple: allow everything, deny all file writes, then re-allow writes to a few specific paths — the current working directory, ~/.claude, and /tmp. If Claude Code tries to write outside those boundaries, the OS itself blocks it.

You can customize this policy by writing your own profile in TOML, but the defaults are sensible enough to use as-is.

Installation

claude-sandbox is a single binary with no dependencies. You can install it with Homebrew:

brew install kohkimakimoto/tap/claude-sandbox
Enter fullscreen mode Exit fullscreen mode

Basic Usage

claude-sandbox is a drop-in replacement for the claude command:

# Before
claude --dangerously-skip-permissions

# After
claude-sandbox --dangerously-skip-permissions
Enter fullscreen mode Exit fullscreen mode

That's it. Claude Code starts, but now it runs inside a sandbox that restricts where it can write files.

Try to write a file outside the current directory, and you'll see an error like the following:

❯ write current time into ~/now.txt

⏺ Bash(date > ~/now.txt && cat ~/now.txt)
  ⎿  Error: Exit code 1
     (eval):1: operation not permitted: /Users/kohkimakimoto/now.txt

     (eval):1: operation not permitted: /Users/kohkimakimoto/now.txt

⏺ The sandbox is restricting write access to the home directory. Let me try using the Write tool instead.
Enter fullscreen mode Exit fullscreen mode

Configuration

You don't need a config file to get started — the built-in defaults work fine. But if you want to customize things, run:

# Project-specific config
claude-sandbox init

# Global config
claude-sandbox init-global
Enter fullscreen mode Exit fullscreen mode

This creates a .claude/sandbox.toml file. Here's what it looks like:

[sandbox]
profile = '''
(version 1)
(allow default)
(deny file-write*)
(allow file-write*
    (subpath (param "WORKDIR"))
    (regex (string-append "^" (param "HOME") "/\\.claude"))
    (subpath "/tmp")
)
'''

[unboxexec]
allowed_commands = [
    "^playwright-cli",
]
Enter fullscreen mode Exit fullscreen mode

The profile is written in the sandbox-exec policy language (a Scheme-like DSL). Two parameters are automatically injected:

  • WORKDIR — the directory where you ran claude-sandbox
  • HOME — your home directory

To see what profile is actually active:

claude-sandbox profile
Enter fullscreen mode Exit fullscreen mode

The Escape Hatch: unboxexec

Here's where things get interesting. Some tools — like Playwright for browser automation — use their own sandboxing internally. Running them inside a macOS sandbox causes conflicts, and they simply don't work.

claude-sandbox solves this with a mechanism called unboxexec. When claude-sandbox starts, it launches a small daemon outside the sandbox. Claude Code, running inside the sandbox, can send a command execution request to that daemon — and the daemon runs the command outside the sandbox and returns the result.

The daemon won't execute arbitrary commands — only those matching the regex patterns in [unboxexec].allowed_commands. By default, everything is rejected.

To use unboxexec from inside Claude Code (or from a script running inside the sandbox):

claude-sandbox unboxexec -- playwright-cli open https://example.com
Enter fullscreen mode Exit fullscreen mode

For it to work, you need to add the pattern to your config:

[unboxexec]
allowed_commands = [
    "^playwright-cli",
]
Enter fullscreen mode Exit fullscreen mode

Telling Claude About the Sandbox

One more practical detail: Claude Code doesn't automatically know it's running in a sandbox. If you want it to use unboxexec correctly — and to understand what it can and can't do — you should add a rules file.

The repo includes a ready-to-use example at rules/sandbox.md. Copy its contents into .claude/rules/sandbox.md in your project, or into ~/.claude/rules/sandbox.md to apply it globally. Adjust the contents based on which commands you've allowed.

Wrapping Up

claude-sandbox gives you a practical middle ground: run Claude Code with full permissions for reading and executing, but with file writes safely scoped to your project directory. No network lockdown, no complex configuration to troubleshoot — just a straightforward constraint that covers the most common concern.

GitHub: https://github.com/kohkimakimoto/claude-sandbox

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.