Gemini CLI
Gemini CLI hooks: settings.json, BeforeTool, AfterTool, exit codes and /hooks
How do I set up hooks in Gemini CLI?
Add a hooks object to .gemini/settings.json (project) or ~/.gemini/settings.json (user). Each event, such as BeforeTool or AfterTool, holds a list of groups with a matcher and a hooks array of command hooks. A hook gets JSON on stdin and replies with JSON on stdout. Exit 0 with a deny decision, or exit 2 with a reason on stderr, blocks the action. Use /hooks panel to see what is loaded.
Compare: hooks in every AI coding agent →
Gemini CLI settings change often
Get one email a week when a setting, flag or permission rule changes, checked against the vendor docs.
Where hooks are configured
Gemini CLI reads hooks from these places, highest precedence first:
- Project: .gemini/settings.json in the current directory.
- User: ~/.gemini/settings.json.
- System: /etc/gemini-cli/settings.json.
- Extensions: hooks that installed extensions define.
Example: check every file write
.gemini/settings.json
{
"hooks": {
"BeforeTool": [
{
"matcher": "write_file|replace",
"hooks": [
{
"name": "security-check",
"type": "command",
"command": "$GEMINI_PROJECT_DIR/.gemini/hooks/security.sh",
"timeout": 5000
}
]
}
]
}
}- type: required. Only "command" is supported today.
- command: the shell command to run.
- name: optional. Used in logs and by /hooks enable and /hooks disable.
- timeout: optional, in milliseconds. The default is 60000 (60 seconds).
- A group can set "sequential" to run its hooks one after another instead of in parallel.
Hook events
- SessionStart and SessionEnd
- BeforeAgent and AfterAgent
- BeforeModel and AfterModel
- BeforeToolSelection
- BeforeTool and AfterTool
- PreCompress
- Notification
How matchers work
- BeforeTool and AfterTool: the matcher is a regex tested against the tool name, such as "write_.*".
- Lifecycle events: the matcher is an exact string, such as "startup".
- "*" or an empty string matches everything.
- Built-in tools use names like read_file and run_shell_command. MCP tools are named mcp_<server_name>_<tool_name>.
Input, output and exit codes
Every hook gets JSON on stdin with session_id, transcript_path, cwd, hook_event_name and timestamp, plus fields for its event. Stdout must contain only the final JSON object. If that JSON is invalid, Gemini CLI defaults to allow.
- Exit 0: success. Stdout is parsed as JSON. The docs prefer this for all logic, including intentional blocks.
- Exit 2: system block. The action is aborted and stderr is the reason.
- Any other code: a non-fatal warning. The action goes ahead with the original parameters.
- decision: "allow" or "deny" ("block" also works), with reason as the feedback when you deny.
- continue: false stops the agent loop. stopReason is shown to the user.
- systemMessage: a message shown to the user.
- hookSpecificOutput: event fields such as additionalContext or a rewritten tool_input for BeforeTool.
Manage hooks with /hooks
- /hooks panel shows the configured hooks.
- /hooks enable-all and /hooks disable-all toggle every hook.
- /hooks enable <name> and /hooks disable <name> toggle one hook.
Gemini CLI fingerprints project hooks. If a hook's name or command changes, for example after a git pull, it is treated as a new, untrusted hook and you are warned before it runs.
Get Gemini CLI settings changes by email
When a setting, flag or permission rule in this guide changes, it goes in the weekly AgentAtlas update, checked against the vendor docs. One email a week.
Sources
More on Gemini CLI
More Gemini CLI guides
- Gemini CLI: YOLO mode, auto_edit and allowing specific shell commands
- Gemini CLI: turn off usage statistics and telemetry
- Configure Gemini CLI with settings.json
- Gemini CLI extensions and custom commands
- GEMINI.md in Gemini CLI: context file locations, imports and /memory
- Gemini CLI MCP servers: gemini mcp add and mcpServers in settings.json
- Gemini CLI custom slash commands: TOML files, {{args}}, !{shell} and @{file}
- Gemini CLI headless mode: gemini -p, JSON output and exit codes for scripts and CI
- Gemini CLI sandbox: enable Docker, Podman, macOS Seatbelt or gVisor
Other guides
Reviewed Oct 18, 2026. Settings change often; the linked vendor docs are the source of truth.