Approval Modes · crystl Docs
When an agent needs to run a tool (editing a file, running a command, searching your codebase), it asks for permission. crystl intercepts that request and decides whether to auto-approve it or float it to you as a glass panel.
The setting is called auto-approval. It has three states.
The three modes
off
crystl auto-approves nothing. Every tool call waits for you. A floating approval card appears with allow and deny buttons.
Best for: unfamiliar code, sensitive operations, watching what an agent does step by step.
in gem
Reads anything. Makes changes only inside this gem. Runs git that cannot lose work. Asks before anything else.
That sentence is the whole contract. In detail:
- Reads auto-approve.
Read,Glob,Grep,WebSearch,WebFetch, and the subagent toolsAgentandExplore. Reads change nothing, so they never wait. - Writes auto-approve inside the tree.
Edit,Write, andNotebookEditgo through when the target path is inside the shard’s own worktree or repo root. A write outside that tree asks, and so do writes into.git/. - Safe git auto-approves.
git add,commit,status,diff,log,show,rev-parse,git stash list/git stash show, andgit brancheither in its listing forms or creating a branch by name, which is additive. Anything that can discard work asks. - Everything else asks. Any other command, any other tool. The one exception is a worker’s own reporting helpers.
Writes into .git/ still ask
.git/ sits inside the tree and is not workspace. A write to .git/config or .git/hooks/* installs something a later git run executes, often outside the run that wrote it, so it raises a panel even under in gem.
One plain invocation only
The safe-git list covers one plain git command and nothing else. A shell operator anywhere disqualifies the request whatever the subcommand: &, ||, ;, |, a backtick, $(, =(, >, <, or a newline.
all
Every tool call is approved. Nothing waits.
Best for: a task you defined tightly, in a gem you are happy to hand over.
The gem is the ceiling
A permission mode declared inside your project may narrow what crystl auto-approves. It may never widen it.
Agents read permission settings out of the repo: a .claude/agents/*.md file can declare permissionMode: bypassPermissions, and a CLI flag can ask for the same thing. Now your gem’s mode takes precedence:
- Gem off: nothing auto-approves, whatever the repo declares.
- Gem in gem:
bypassPermissionsanddontAskgrant nothing extra. - Gem all: everything auto-approves, including a declared bypass.
You may notice this as “crystl started asking me things.” If a repo you work in declares a bypass mode, work that used to run unattended under in gem now raises panels.
Pause
pause auto-approvals in the crystl app menu is a global kill-switch. It overrides every mode: per-gem, per-shard, and global settings alike.
Use it when you want to take the wheel back for a minute without editing any gem’s setting.
Approval cards
Each approval card is a floating glass panel that shows:
- The tool name (Edit, Bash, Read, etc.)
- The target (file path or command)
- A preview of what will change
- allow, always, and deny buttons, plus show › to jump to the shard
Denial panels
When crystl denies a tool under in gem, an orange denial panel appears showing what was blocked. A retry button lets you override the auto-deny without switching modes, and dismiss clears the panel.
Per-gem auto-approval
You can override the global mode per gem. Open the gem menu and choose auto-approval › to set the mode directly.
Priority chain
crystl resolves the active mode in this order:
- pause auto-approvals: the app-menu kill-switch.
- Session override: a temporary override supplied programmatically for an individual shard.
- Per-project config: the nearest
.crystl/project.jsonat or above the shard’s working directory. - Crystl session default: the fallback a quest or fanout launch sets for its own shards.
- Global mode: the default set on the agents settings page.
When you set a per-gem mode, the terminal prints a confirmation.
Global default
Set the global default in settings, agents > defaults, under AUTO-APPROVAL (DEFAULT). This is the fallback used when a gem has no override of its own.
Upgrading from the old names
The modes used to be called Ask Every Time, Smart, and Auto. They are now off, in gem, and all. Same three modes, clearer names.
Which agents get cards
| Agent | Cards | What is different |
|---|---|---|
| Claude Code | yes | the full behaviour this page describes |
| Codex | yes | option+deny denies the one call |
| opencode | yes | cards start from opencode’s own permission event |
| goose | yes, in auto mode |
goose resolves approvals before the hook runs |
| Kimi | yes | allow releases the hold rather than pre-approving |
| GitHub Copilot CLI | yes | allow fully replaces Copilot’s own prompt. |
A worker’s approval goes to its orchestrator first
When a shard you fanned out hits an approval, the card does not land on you straight away. crystl dispatches one line into the lead shard’s terminal instead, naming the request and the two commands that decide it.
From the CLI
Approvals are also reachable via the crystl CLI. This helps when you’re triaging from another terminal, scripting a workflow, or running an agent that needs to coordinate with whoever holds the approval seat.
crystl pending # list every pending request
crystl approve 3 # approve request id 3
crystl deny 4 # deny request id 4
crystl wait pending --timeout 60 # block until the next one appears, then exit
crystl events --type pending_changed # stream approval lifecycle as JSON lines
Switching modes
You can change the mode at any time from the gem menu’s auto-approval › shortcut or the Gem Settings panel. The change takes effect immediately for pending and future requests in that gem.