Runs AI coding agents (Claude, Gemini, Goose) inside a bubblewrap sandbox. The host filesystem is read-only, only the current project directory and the dotfiles you whitelist are accessible. The sandbox also starts with a clean environment, only variables explicitly allowed are visible to the agent.
- Linux
bwrapinstalled (e.g.sudo dnf install bubblewraporsudo apt install bubblewrap)
curl -Lo ~/.local/bin/bwai https://github.com/umago/bubblewrap-ai/releases/latest/download/bwai
chmod +x ~/.local/bin/bwaimake build
cp bin/bwai ~/.local/bin/To update bwai to the latest release:
bwai updateThis downloads the latest binary from GitHub releases, verifies its SHA-256 digest, and replaces the running binary in-place.
Run bwai from inside the project directory you want to give the agent access to:
cd ~/my-project
bwaiBy default, bwai opens a sandboxed bash shell. From there you can launch any agent:
[🫧] > claude
[🫧] > goose
[🫧] > geminiTo skip the shell and launch an agent (or any command) directly, you can either:
- Set the
commandfield in~/.bwai.json:
{ "command": ["claude"] }- Use the
--command(or-c) CLI flag, which overrides the config file:
bwai --command claude
To append arguments to the command configured in ~/.bwai.json, use --:
# With "command": ["goose"] in config
bwai -- session -r # runs "goose session -r" to resume a session
# With "command": ["claude"] in config
bwai -- --model gemini-2.0-flash-exp # runs "claude --model gemini-2.0-flash-exp"Everything after -- is passed as extra arguments to the resolved command.
Use --ro-dir to give the agent read-only access to directories outside the current project. This is useful when the project you are working on depends on another local project that you want the agent to use as reference:
bwai --ro-dir ../other-project
bwai --ro-dir /absolute/path/to/lib --ro-dir /another/pathThe flag is repeatable and accepts both relative and absolute paths. Each directory is mounted at the same absolute path inside the sandbox. bwai will refuse to start if any of the given paths does not exist.
bwai works out of the box with no config file. To customise behaviour, create ~/.bwai.json as a global config. To use a different file for a single run:
bwai --config /path/to/my-config.jsonTo use the built-in defaults as a starting point, run bwai --dump-config > ~/.bwai.json, or browse them at cmd/bwai/defaults.json.
The available fields are:
| Field | Description |
|---|---|
bwrap_path |
Path to the bwrap binary |
bwrap_extra_args |
Extra arguments forwarded to bwrap (e.g. --unshare-net). Each element is split on whitespace, so "--ro-bind /var /var" and "--ro-bind", "/var", "/var" are equivalent |
command |
Command (and args) to run inside the sandbox |
home_allow |
Dotfiles/dirs in $HOME the agent may read and write |
home_block |
Dotfiles/dirs in $HOME that are never exposed |
env_allow |
Environment variables from the host passed into the sandbox |
home_block takes precedence over home_allow at the same nesting level. However, the two can be combined at different nesting levels to achieve more granular control:
- Block a sub-path inside an allowed directory —
home_allow: [".cache"]+home_block: [".cache/sccache"]exposes.cache(read-write) but hides.cache/sccacheinside it. - Re-expose a sub-path inside a blocked directory —
home_block: [".cache"]+home_allow: [".cache/sccache"]hides everything in.cacheexcept.cache/sccache, which is available read-write.