Run AI coding agents in a lightweight Bubblewrap sandbox, with project tooling
managed by direnv and Nix devShells.
aibox is the lightweight successor to
aidock: no container image, no image commits
on exit, no per-session agent binary drift, and no runtime configuration file.
aibox codex
aibox claude
aibox copilot
aibox -- bashSupported agent state/config policy is maintained for Codex, Claude Code, and GitHub Copilot CLI. Other commands can be useful for debugging, but they are best-effort and do not get dedicated persistent state/config mounts.
Nix is the recommended installation method:
nix profile install github:ruifm/aiboxRun without installing:
nix run github:ruifm/aibox -- codexFrom a clone:
nix profile install .Secondary direct-script install:
mkdir -p ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/ruifm/aibox/main/aibox -o ~/.local/bin/aibox
chmod +x ~/.local/bin/aiboxAfter installing, run an end-to-end smoke check:
aibox -- true && echo "aibox smoke check passed"This also creates the known persistent agent state paths when they are missing.
Use direnv and a Nix devShell per project. The agent can edit flake.nix,
refresh the devShell, and install project-specific tools declaratively.
Example .envrc:
use flakeIf the project has no .envrc and no Nix devShell yet, start by adding a
minimal flake.nix devShell plus the .envrc above, then run direnv allow.
Then launch the agent from the project directory:
cd my-project
aibox codexBefore starting a session, paste the generated prompt into the agent. Inside an
active agent session, aibox is available on PATH, so you can also run
!aibox -p and ask the agent to follow it.
aibox -p- Linux.
- Bash 4+.
- Bubblewrap.
- Unprivileged user namespaces available to Bubblewrap.
- Nix multi-user daemon.
nix store infomust work. - direnv and Nix devShells for the recommended workflow.
For an agent session, install the supported agent command you intend to run
(codex, claude, or copilot) somewhere the sandbox can see it: the project
Nix devShell, a Nix profile, or the host system paths mounted read-only at
/usr and /bin.
aibox builds a Bubblewrap command that:
- binds the current directory read/write at the same absolute path;
- keeps host networking available;
- starts
$HOMEas a private tmpfs skeleton at the same absolute path; - mounts selected real agent state/config directories back into that home;
- exposes
/nix/storeread-only; - binds the Nix daemon socket so
nix develop,nix build, anddirenv reloadcan work; - mounts
aiboxitself read-only at/run/aibox/bin/aiboxand prepends that directory toPATH; - leaves the inherited
PATHvisible, but does not discover or bind-mount arbitrary agent binaries from host-only paths such as~/.local/bin; - remounts the synthetic root read-only after setup;
- prints the final
bwrapcommand to stderr before execution.
aibox does not try to bind a single resolved agent executable into the
sandbox. Many agent commands are scripts or wrappers that need interpreters,
dynamic libraries, Node package trees, plugin files, or a Nix closure. Keeping
agent CLIs in a project devShell or Nix profile makes the executable and its
runtime closure available through the already-mounted Nix paths without adding
an arbitrary host-path mount interface.
Persistent agent state/config mounts:
~/.codex~/.claude~/.claude.json~/.copilot~/.config/claude~/.config/claude-code~/.config/github-copilot
These writable state paths are created on the host before launch when missing.
~/.claude.json is initialized as {}. If one of the expected directories is
a file, or ~/.claude.json is not a file, aibox fails before starting the
sandbox.
aibox intentionally does not mount GitHub CLI config, Git config, SSH agent,
GPG agent, D-Bus, Docker, Kubernetes config, browser profiles, or arbitrary
extra paths.
This is an accident-safety tool, not hostile-code containment.
The sandbox is intended to prevent routine agent/tool mistakes from writing outside the project or reading broad host state. It still gives the agent full network access, and it mounts real agent auth/session/config directories. Any readable mounted data can be exfiltrated by code running in the sandbox.
aibox does not clear the ordinary process environment. API keys, cloud
credentials, package tokens, and other variables inherited by aibox are
visible to processes inside the sandbox. The printed bwrap command also
contains the command arguments you passed to aibox, so do not pass secrets as
CLI arguments.
Nix builds are performed by the host Nix daemon, outside Bubblewrap. Use host Nix sandboxing if build isolation matters.
On Ubuntu 24.04+, AppArmor may restrict unprivileged user namespaces. If
aibox -- true fails with a Bubblewrap namespace permission error, add a
targeted profile for Bubblewrap instead of disabling the restriction globally:
cat <<'EOF' | sudo tee /etc/apparmor.d/local-aibox-bwrap >/dev/null
abi <abi/4.0>,
include <tunables/global>
profile local-aibox-bwrap /usr/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/aibox-bwrap>
}
profile local-aibox-bwrap-nix /nix/store/*-bubblewrap-*/bin/bwrap flags=(unconfined) {
userns,
include if exists <local/aibox-bwrap-nix>
}
EOF
sudo apparmor_parser -r /etc/apparmor.d/local-aibox-bwrap
aibox -- trueIf bwrap is installed somewhere else, add another profile stanza for the
absolute path printed by readlink -f "$(command -v bwrap)".
Development setup and test commands live in CONTRIBUTING.md.