Checkpoints, sandboxes, and trust in Gemini CLI
Hand an agent a shell and you have made a trust decision, whether you meant to or not. Gemini CLI's answer is a layered toolkit: approvals, checkpoints, sandboxes. The layers deserve to be understood separately, because each catches a different class of failure and none covers the others' blind spots.
Approvals catch bad intentions
By default, every mutating tool call stops and asks. Reads run freely; shell commands and file edits wait for a yes, and you can grant it once or for the rest of the session. This is the layer against intent mismatch: you see the command before it exists in the world, and the diff before it lands. It is also the human firewall against prompt injection: instructions smuggled in through a fetched web page or a pasted log become tool calls you get to refuse.
Its weakness is arithmetic. Fifty prompts in a session breed approval fatigue, and the day you hit always-allow on the shell tool, you have switched this layer off without admitting it.
Checkpoints catch bad edits
Run with --checkpointing and the CLI snapshots your project before each file-modifying tool call (into a shadow git repository, not your real history), along with the conversation state. /restore lists the snapshots and rolls files and conversation back together. It is an undo button for agent edits, and it dissolves a specific anxiety: let the big refactor run, read it calmly, restore if it went sideways.
Know what it does not cover. A checkpoint restores files; it cannot un-run a command. The deleted branch, the migration executed against a real database, the push that already left the building. None of that comes back with /restore. Checkpoints protect your working tree, not the world. And the feature is off by default, which means the day you need it tends to be the day you learn you did not have it on.
Sandboxes catch bad commands
Sandboxing (--sandbox, or -s) bounds what a command can touch while it runs. The light option leans on the operating system's own process-isolation profiles; the heavier, more portable option executes tool calls inside a container with your project mounted, so even a catastrophic command reaches only what the container exposes. This is the layer for the failures approvals cannot catch: the command that looked innocent and was not. The general case for isolation over vigilance is in sandboxing coding agents, and Codex sandbox internals shows OpenAI converging on the same architecture from the other direction.
Two caveats from real use. Default profiles can still permit network egress, so data exfiltration is not automatically off the table. And containers bring friction: your toolchain has to exist inside one, which costs an afternoon the first time.
Approvals catch bad intentions, checkpoints catch bad edits, sandboxes catch bad commands. YOLO mode discards all three at once.
YOLO mode is honestly named
--yolo auto-approves every tool call. Google could have called it auto-approve or non-interactive; they named it after you-only-live-once, and I choose to read that as documentation. There are legitimate uses: unattended CI runs with permissions pinned to the floor, a disposable container where the worst case is recreating the container. The pattern that matters: YOLO is safe exactly in proportion to the other layers still standing. It should mean the sandbox is my approval, never a shrug on your main checkout with production credentials in the environment.
My settled configuration: checkpointing always on, because it is cheap and I have used /restore more than I expected; approvals on whenever credentials are within reach; the container sandbox for anything touching untrusted input; YOLO only inside something I would happily delete. The layering is the point. Any single mechanism fails embarrassingly, but stacked they let you extend the leash further than vigilance alone ever could. The upgrade I am still waiting for is deny-by-default network policy out of the box. Until then, that last piece of the trust decision ships unconfigured, and it is yours.