Guide · Gemini CLI
How do I run Gemini CLI in a sandbox?
Updated
Start Gemini CLI with -s (--sandbox), or set GEMINI_SANDBOX to docker, podman or sandbox-exec. On macOS the default Seatbelt profile, permissive-open, confines writes to the project folder but allows network access; Gemini's docs say sandboxing is off by default except in YOLO mode. For a boundary with its own kernel and a network allow-list, run Gemini CLI in a kosa8 microVM with the built-in gemini kit, which keeps your API key outside the VM.
01Steps
Sandbox one session.
-sor--sandboxenables sandbox mode for that session. On macOS it can use Seatbelt (sandbox-exec); elsewhere use a container engine.gemini -s -p "analyze the code structure"Make it the default.
GEMINI_SANDBOXacceptstrue,false,docker,podmanor a custom command. The same choice can go insettings.jsonundertools.sandbox. The flag wins over the variable, which wins over the settings file.export GEMINI_SANDBOX=docker{"tools": {"sandbox": "docker"}}On macOS, tighten the Seatbelt profile.
SEATBELT_PROFILEswitches the profile.strict-openrestricts reads as well as writes and still allows network access; the-proxiedprofiles send traffic through a proxy you configure.SEATBELT_PROFILE=strict-open gemini -sDebug a refusal.
DEBUG=1prints more detail. Put it in.gemini/.envrather than the project's.env, which Gemini's docs say has no effect for it. In a container sandbox,SANDBOX_MOUNTSadds mounts, read-only by default.DEBUG=1 gemini -s -p "debug command"For a VM boundary, install kosa8. On an Apple silicon Mac or x86-64 Linux, install kosa8, start its daemon and check the setup with
kosa8 doctor.curl -fsSL https://kosa8.com/install.sh | sh kosa8 daemon start kosa8 doctor
Run Gemini CLI in its own microVM. Set
GEMINI_API_KEYon your computer only, read the plan with--dry-run, then run thegeminikit from your project folder. Options for kosa8 go before the kit name; anything after it goes to Gemini CLI. The sandbox is removed when Gemini CLI exits; your folder keeps its changes.export GEMINI_API_KEY=... kosa8 agent run --dry-run gemini cd ~/code/api && kosa8 agent run gemini
Read the record. Every request through the broker, allowed or refused, and every tool call the model asked for is in kosa8's hash-chained audit log.
kosa8 audit ls kosa8 audit verify
02Is Gemini CLI sandboxed by default?
No. Gemini CLI's documentation says sandboxing is disabled by default, except that it is turned on when you use --yolo or --approval-mode=yolo. Turn it on with -s, the GEMINI_SANDBOX variable or tools.sandbox in settings.json.
Approval and sandboxing are separate controls. --approval-mode decides what Gemini CLI asks you about (default, auto_edit, plan or yolo); the sandbox decides what a command can touch once it runs. YOLO mode approves every tool call, which is why the sandbox matters most there.
03What does each SEATBELT_PROFILE allow?
Gemini CLI ships six Seatbelt profiles for macOS. permissive-open, the default, restricts writes and allows network access; restrictive-open applies stricter restrictions; strict-open restricts reads as well as writes. Each -proxied variant sends network traffic through a proxy instead of allowing it directly.
| Profile | Files | Network |
|---|---|---|
permissive-open (default) | Write restrictions | Allowed |
permissive-proxied | Write restrictions | Via proxy |
restrictive-open | Strict restrictions | Allowed |
restrictive-proxied | Strict restrictions | Via proxy |
strict-open | Read and write restrictions | Allowed |
strict-proxied | Read and write restrictions | Via proxy |
On Linux, GEMINI_SANDBOX=runsc runs the container under gVisor, a user-space kernel, and needs Docker installed. LXC/LXD is listed as experimental.
04Why does Gemini CLI say "Operation not permitted" in the sandbox?
The command needed access outside what the sandbox allows. Gemini CLI's documentation suggests trying a more permissive profile or adding mount points, and running with DEBUG=1 for more detail.
With the open profiles, network access is allowed; with the proxied ones, check the proxy configuration. Under gVisor, services bound to your host's loopback interface are not reachable from inside, even with --network host.
05What does a microVM add to Gemini CLI's own sandbox?
Seatbelt is a policy enforced by the macOS kernel, and Docker and Podman containers share the host's kernel. In a kosa8 microVM, Gemini CLI gets its own Linux kernel, sees one shared folder, reaches only the hosts its kit lists, and holds a placeholder instead of GEMINI_API_KEY: a broker on your side adds the real key to requests to generativelanguage.googleapis.com.
- Network allow-list, enforced on your side. The kit allows
registry.npmjs.organd the broker; anything else is refused and logged. - Recorded, not held. The
claudekit checks each tool call before it runs. Thegeminikit has no pre-run hook yet, so its calls, such asrun_shell_command, are checked against kosa8's rules in the audit log rather than held for approval. - Rewind. Start a kept sandbox with
--keep --nameand you cankosa8 checkpointandkosa8 rewindit. A rewind restores the machine, not the shared folder: keep git for that. - Not tested together. kosa8 does not document running Gemini CLI's own container sandbox, or
--yolo, which turns that sandbox on, inside the kit.
06Other options
- Seatbelt fits quick, local work on macOS with no extra install.
- Docker or Podman fits Linux and Windows hosts and teams that already run containers; a custom
.gemini/sandbox.Dockerfileadds project tools. - gVisor (runsc) adds a user-space kernel between the container and the host on Linux.
- Docker Sandboxes runs coding agents in isolated microVM sandboxes from Docker's tooling.
- A full VM in UTM or Lima fits a long-lived, general-purpose environment you manage yourself.
- Hosted sandboxes such as E2B, Daytona or Modal fit when the agent should run in the cloud.