2026-01-27 20:06:12 -05:00
# Gemini CLI hooks
2025-12-03 10:57:05 -08:00
Hooks are scripts or programs that Gemini CLI executes at specific points in the
agentic loop, allowing you to intercept and customize behavior without modifying
the CLI's source code.
2026-01-21 22:13:15 -05:00
## What are hooks?
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
Hooks run synchronously as part of the agent loop—when a hook event fires,
Gemini CLI waits for all matching hooks to complete before continuing.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
With hooks, you can:
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
- **Add context:** Inject relevant information (like git history) before the
model processes a request.
- **Validate actions:** Review tool arguments and block potentially dangerous
operations.
- **Enforce policies:** Implement security scanners and compliance checks.
- **Log interactions:** Track tool usage and model responses for auditing.
- **Optimize behavior:** Dynamically filter available tools or adjust model
parameters.
2025-12-03 10:57:05 -08:00
2026-01-27 20:06:12 -05:00
### Getting started
2026-03-09 08:23:00 -07:00
- **[Writing hooks guide ](../hooks/writing-hooks )**: A tutorial on creating your
first hook with comprehensive examples.
- **[Best practices ](../hooks/best-practices )**: Guidelines on security,
2026-01-27 20:06:12 -05:00
performance, and debugging.
2026-03-09 08:23:00 -07:00
- **[Hooks reference ](../hooks/reference )**: The definitive technical
2026-01-27 20:06:12 -05:00
specification of I/O schemas and exit codes.
2026-01-21 22:13:15 -05:00
## Core concepts
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
### Hook events
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
Hooks are triggered by specific events in Gemini CLI's lifecycle.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
| Event | When It Fires | Impact | Common Use Cases |
| --------------------- | ---------------------------------------------- | ---------------------- | -------------------------------------------- |
| `SessionStart` | When a session begins (startup, resume, clear) | Inject Context | Initialize resources, load context |
| `SessionEnd` | When a session ends (exit, clear) | Advisory | Clean up, save state |
| `BeforeAgent` | After user submits prompt, before planning | Block Turn / Context | Add context, validate prompts, block turns |
| `AfterAgent` | When agent loop ends | Retry / Halt | Review output, force retry or halt execution |
| `BeforeModel` | Before sending request to LLM | Block Turn / Mock | Modify prompts, swap models, mock responses |
| `AfterModel` | After receiving LLM response | Block Turn / Redact | Filter/redact responses, log interactions |
| `BeforeToolSelection` | Before LLM selects tools | Filter Tools | Filter available tools, optimize selection |
| `BeforeTool` | Before a tool executes | Block Tool / Rewrite | Validate arguments, block dangerous ops |
| `AfterTool` | After a tool executes | Block Result / Context | Process results, run tests, hide results |
| `PreCompress` | Before context compression | Advisory | Save state, notify user |
| `Notification` | When a system notification occurs | Advisory | Forward to desktop alerts, logging |
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
### Global mechanics
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
Understanding these core principles is essential for building robust hooks.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
#### Strict JSON requirements (The "Golden Rule")
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
Hooks communicate via `stdin` (Input) and `stdout` (Output).
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
1. **Silence is Mandatory ** : Your script **must not ** print any plain text to
`stdout` other than the final JSON object. **Even a single `echo` or `print`
call before the JSON will break parsing.**
2. **Pollution = Failure ** : If `stdout` contains non-JSON text, parsing will
fail. The CLI will default to "Allow" and treat the entire output as a
`systemMessage` .
3. **Debug via Stderr ** : Use `stderr` for **all ** logging and debugging (e.g.,
`echo "debug" >&2` ). Gemini CLI captures `stderr` but never attempts to parse
it as JSON.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
#### Exit codes
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
Gemini CLI uses exit codes to determine the high-level outcome of a hook
execution:
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
| Exit Code | Label | Behavioral Impact |
| --------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **0 ** | **Success ** | The `stdout` is parsed as JSON. **Preferred code ** for all logic, including intentional blocks (e.g., `{"decision": "deny"}` ). |
| **2 ** | **System Block ** | **Critical Block ** . The target action (tool, turn, or stop) is aborted. `stderr` is used as the rejection reason. High severity; used for security stops or script failures. |
| **Other ** | **Warning ** | Non-fatal failure. A warning is shown, but the interaction proceeds using original parameters. |
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
#### Matchers
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
You can filter which specific tools or triggers fire your hook using the
`matcher` field.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
- **Tool events** (`BeforeTool` , `AfterTool` ): Matchers are **Regular
Expressions**. (e.g., `"write_.*"` ).
- **Lifecycle events**: Matchers are **Exact Strings ** . (e.g., `"startup"` ).
- **Wildcards**: `"*"` or `""` (empty string) matches all occurrences.
2025-12-03 10:57:05 -08:00
## Configuration
2026-01-25 18:33:12 -05:00
Hooks are configured in `settings.json` . Gemini CLI merges configurations from
multiple layers in the following order of precedence (highest to lowest):
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
1. **Project settings ** : `.gemini/settings.json` in the current directory.
2. **User settings ** : `~/.gemini/settings.json` .
3. **System settings ** : `/etc/gemini-cli/settings.json` .
4. **Extensions ** : Hooks defined by installed extensions.
2025-12-03 10:57:05 -08:00
### Configuration schema
```json
{
"hooks": {
2026-01-21 22:13:15 -05:00
"BeforeTool": [
2025-12-03 10:57:05 -08:00
{
2026-01-21 22:13:15 -05:00
"matcher": "write_file|replace",
2025-12-03 10:57:05 -08:00
"hooks": [
{
2026-01-21 22:13:15 -05:00
"name": "security-check",
2025-12-03 10:57:05 -08:00
"type": "command",
2026-01-21 22:13:15 -05:00
"command": "$GEMINI_PROJECT_DIR/.gemini/hooks/security.sh",
2026-01-25 18:33:12 -05:00
"timeout": 5000
2025-12-03 10:57:05 -08:00
}
]
}
]
}
}
```
2026-01-25 18:33:12 -05:00
#### Hook configuration fields
| Field | Type | Required | Description |
| :------------ | :----- | :-------- | :------------------------------------------------------------------- |
| `type` | string | **Yes ** | The execution engine. Currently only `"command"` is supported. |
| `command` | string | **Yes\ ** * | The shell command to execute. (Required when `type` is `"command"` ). |
| `name` | string | No | A friendly name for identifying the hook in logs and CLI commands. |
| `timeout` | number | No | Execution timeout in milliseconds (default: 60000). |
| `description` | string | No | A brief explanation of the hook's purpose. |
---
2025-12-03 10:57:05 -08:00
### Environment variables
2026-01-21 22:13:15 -05:00
Hooks are executed with a sanitized environment.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
- `GEMINI_PROJECT_DIR` : The absolute path to the project root.
- `GEMINI_SESSION_ID` : The unique ID for the current session.
- `GEMINI_CWD` : The current working directory.
- `CLAUDE_PROJECT_DIR` : (Alias) Provided for compatibility.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
## Security and risks
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
> **Warning: Hooks execute arbitrary code with your user privileges.** By
> configuring hooks, you are allowing scripts to run shell commands on your
> machine.
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
**Project-level hooks** are particularly risky when opening untrusted projects.
Gemini CLI **fingerprints ** project hooks. If a hook's name or command changes
(e.g., via `git pull` ), it is treated as a **new, untrusted hook ** and you will
be warned before it executes.
2026-01-12 12:42:04 +05:00
2026-03-09 08:23:00 -07:00
See [Security Considerations ](../hooks/best-practices#using-hooks-securely ) for
a detailed threat model.
2026-01-12 12:42:04 +05:00
2026-01-21 22:13:15 -05:00
## Managing hooks
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
Use the CLI commands to manage hooks without editing JSON manually:
2025-12-03 10:57:05 -08:00
2026-01-21 22:13:15 -05:00
- **View hooks:** `/hooks panel`
- **Enable/Disable all:** `/hooks enable-all` or `/hooks disable-all`
- **Toggle individual:** `/hooks enable <name>` or `/hooks disable <name>`