Claude Code, Cursor, Copilot, and Aider all rely on application-level permission systems (ignore files, allow/deny lists) that can be bypassed. aigate moves that boundary into the OS kernel: POSIX ACLs, Linux namespaces, and egress allowlists physically block what the agent can read, execute, and reach on the network, regardless of what the model decides to try.
The most-starred tool in the AxeForge portfolio. See it on GitHub.
Every file read, command, and network call the agent makes is checked against your rules before it runs.
Four enforcement layers, each backed by an OS primitive the sandboxed process cannot negotiate with.
Persistent POSIX ACLs (setfacl) on Linux, extended ACLs (chmod +a) on macOS, deny read access at rest. At run time, mount namespaces overmount denied directories with empty tmpfs and files with /dev/null: two layers of defense-in-depth.
allowed_paths hides everything in $HOME except the working directory and paths you allow. Non-scoped files are invisible: reads fail, listings don't leak names, writes land in a discarded overlay.
Bubblewrap's --unshare-net plus slirp4netns and iptables/ip6tables restrict egress to your allow_net allowlist on Linux; Seatbelt network-outbound rules do the same on macOS.
User and PID namespaces (--unshare-user --unshare-pid) mean the sandboxed process can't see or signal anything on the host, and needs no real root to set up mounts and networking.
aigate prefers bwrap when it's installed and falls back cleanly when it isn't; run aigate doctor to see which mode is active.
| Layer | Linux (bwrap) | Linux (unshare fallback) | macOS |
|---|---|---|---|
| File | Declarative bind-mount overrides | Shell-script mount overrides | Seatbelt file-read* deny rules |
| Network | --unshare-net + slirp4netns + iptables | Nested unshare + slirp4netns + iptables | sandbox-exec network-outbound rules |
| Process | --unshare-user --unshare-pid, sandboxed PID 1 | unshare --user --map-root-user | Enforced by Sandbox.kext |
| Command exec | mount --bind deny stubs + arg-checking wrappers | Same bind-mount stubs | (deny process-exec) rules |
setupOne-time, needs sudo. Creates the ai-agents OS group and ai-runner user that ACL rules attach to.
initWrites ~/.aigate/config.yaml with sensible defaults: .env, secrets/, ~/.ssh/, and friends, denied out of the box.
deny / allowAdd or remove file, exec, and network rules, globally or per-project, via .aigate.yaml, which extends the global config.
runLaunches any AI tool inside the sandbox and prints exactly which restrictions are active to stderr before it starts.
doctorChecks bwrap/slirp4netns/namespaces and prints a READY/DEGRADED/BLOCKED verdict, and exits non-zero so CI can gate on it.
GDPR/ISO/security teams need a trust boundary that isn't "the model chose not to read the file." ACLs and namespaces don't have that failure mode.
sudo aigate setup && aigate init
Deny read on .env, secrets/, and SSH keys, then mask API keys and tokens that still make it into stdout.
aigate deny read .env secrets/ *.pem
An agent that can only resolve the hosts you named can't phone home to anywhere else, curl an attacker's server, or exfiltrate over DNS.
aigate deny net --except api.anthropic.com
doctor exits non-zero when full isolation isn't available, so a pipeline can refuse to run an agent unsandboxed.
aigate doctor || exit 1
Install the binary
curl -L https://github.com/AxeForging/aigate/releases/latest/download/aigate-linux-amd64.tar.gz | tar xz
sudo mv aigate-linux-amd64 /usr/local/bin/aigate
One-time system setup: sudo aigate setup && aigate init
Run any AI tool sandboxed: aigate run -- claude