|
Download docs/hooks/reference.md from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 13.3 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/docs/hooks/reference.md
- Command line
-
hf download hf://SaylorTwift/gemini-cli/docs/hooks/reference.md
-
curl -L -o reference.md https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/docs/hooks/reference.md
13.3 kB
| # Hooks reference | |
| This document provides the technical specification for Gemini CLI hooks, | |
| including JSON schemas and API details. | |
| ## Global hook mechanics | |
| - **Communication**: `stdin` for Input (JSON), `stdout` for Output (JSON), and | |
| `stderr` for logs and feedback. | |
| - **Exit codes**: | |
| - `0`: Success. `stdout` is parsed as JSON. **Preferred for all logic.** | |
| - `2`: System Block. The action is blocked; `stderr` is used as the rejection | |
| reason. | |
| - `Other`: Warning. A non-fatal failure occurred; the CLI continues with a | |
| warning. | |
| - **Silence is Mandatory**: Your script **must not** print any plain text to | |
| `stdout` other than the final JSON. | |
| --- | |
| ## Configuration schema | |
| Hooks are defined in `settings.json` within the `hooks` object. Each event (for | |
| example, `BeforeTool`) contains an array of **hook definitions**. | |
| ### Hook definition | |
| | Field | Type | Required | Description | | |
| | :----------- | :-------- | :------- | :-------------------------------------------------------------------------------------- | | |
| | `matcher` | `string` | No | A regex (for tools) or exact string (for lifecycle) to filter when the hook runs. | | |
| | `sequential` | `boolean` | No | If `true`, hooks in this group run one after another. If `false`, they run in parallel. | | |
| | `hooks` | `array` | **Yes** | An array of **hook configurations**. | | |
| ### Hook configuration | |
| | 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. | | |
| --- | |
| ## Base input schema | |
| All hooks receive these common fields via `stdin`: | |
| ```typescript | |
| { | |
| "session_id": string, // Unique ID for the current session | |
| "transcript_path": string, // Absolute path to session transcript JSON | |
| "cwd": string, // Current working directory | |
| "hook_event_name": string, // The firing event (for example "BeforeTool") | |
| "timestamp": string // ISO 8601 execution time | |
| } | |
| ``` | |
| --- | |
| ## Common output fields | |
| Most hooks support these fields in their `stdout` JSON: | |
| | Field | Type | Description | | |
| | :--------------- | :-------- | :----------------------------------------------------------------------------- | | |
| | `systemMessage` | `string` | Displayed immediately to the user in the terminal. | | |
| | `suppressOutput` | `boolean` | If `true`, hides internal hook metadata from logs/telemetry. | | |
| | `continue` | `boolean` | If `false`, stops the entire agent loop immediately. | | |
| | `stopReason` | `string` | Displayed to the user when `continue` is `false`. | | |
| | `decision` | `string` | `"allow"` or `"deny"` (alias `"block"`). Specific impact depends on the event. | | |
| | `reason` | `string` | The feedback/error message provided when a `decision` is `"deny"`. | | |
| --- | |
| ## Tool hooks | |
| ### Matchers and tool names | |
| For `BeforeTool` and `AfterTool` events, the `matcher` field in your settings is | |
| compared against the name of the tool being executed. | |
| - **Built-in Tools**: You can match any built-in tool (for example, `read_file`, | |
| `run_shell_command`). See the [Tools Reference](../reference/tools) for a full | |
| list of available tool names. | |
| - **MCP Tools**: Tools from MCP servers follow the naming pattern | |
| `mcp_<server_name>_<tool_name>`. | |
| - **Regex Support**: Matchers support regular expressions (for example, | |
| `matcher: "read_.*"` matches all file reading tools). | |
| ### `BeforeTool` | |
| Fires before a tool is invoked. Used for argument validation, security checks, | |
| and parameter rewriting. | |
| - **Input Fields**: | |
| - `tool_name`: (`string`) The name of the tool being called. | |
| - `tool_input`: (`object`) The raw arguments generated by the model. | |
| - `mcp_context`: (`object`) Optional metadata for MCP-based tools. | |
| - `original_request_name`: (`string`) The original name of the tool being | |
| called, if this is a tail tool call. | |
| - **Relevant Output Fields**: | |
| - `decision`: Set to `"deny"` (or `"block"`) to prevent the tool from | |
| executing. | |
| - `reason`: Required if denied. This text is sent **to the agent** as a tool | |
| error, allowing it to respond or retry. | |
| - `hookSpecificOutput.tool_input`: An object that **merges with and | |
| overrides** the model's arguments before execution. | |
| - `continue`: Set to `false` to **kill the entire agent loop** immediately. | |
| - **Exit Code 2 (Block Tool)**: Prevents execution. Uses `stderr` as the | |
| `reason` sent to the agent. **The turn continues.** | |
| ### `AfterTool` | |
| Fires after a tool executes. Used for result auditing, context injection, or | |
| hiding sensitive output from the agent. | |
| - **Input Fields**: | |
| - `tool_name`: (`string`) | |
| - `tool_input`: (`object`) The original arguments. | |
| - `tool_response`: (`object`) The result containing `llmContent`, | |
| `returnDisplay`, and optional `error`. | |
| - `mcp_context`: (`object`) | |
| - `original_request_name`: (`string`) The original name of the tool being | |
| called, if this is a tail tool call. | |
| - **Relevant Output Fields**: | |
| - `decision`: Set to `"deny"` to hide the real tool output from the agent. | |
| - `reason`: Required if denied. This text **replaces** the tool result sent | |
| back to the model. | |
| - `hookSpecificOutput.additionalContext`: Text that is **appended** to the | |
| tool result for the agent. | |
| - `hookSpecificOutput.tailToolCallRequest`: (`{ name: string, args: object }`) | |
| A request to execute another tool immediately after this one. The result of | |
| this "tail call" will replace the original tool's response. Ideal for | |
| programmatic tool routing. | |
| - `continue`: Set to `false` to **kill the entire agent loop** immediately. | |
| - **Exit Code 2 (Block Result)**: Hides the tool result. Uses `stderr` as the | |
| replacement content sent to the agent. **The turn continues.** | |
| --- | |
| ## Agent hooks | |
| ### `BeforeAgent` | |
| Fires after a user submits a prompt, but before the agent begins planning. Used | |
| for prompt validation or injecting dynamic context. | |
| - **Input Fields**: | |
| - `prompt`: (`string`) The original text submitted by the user. | |
| - **Relevant Output Fields**: | |
| - `hookSpecificOutput.additionalContext`: Text that is **appended** to the | |
| prompt for this turn only. | |
| - `decision`: Set to `"deny"` to block the turn and **discard the user's | |
| message** (it will not appear in history). | |
| - `continue`: Set to `false` to block the turn but **save the message to | |
| history**. | |
| - `reason`: Required if denied or stopped. | |
| - **Exit Code 2 (Block Turn)**: Aborts the turn and erases the prompt from | |
| context. Same as `decision: "deny"`. | |
| ### `AfterAgent` | |
| Fires once per turn after the model generates its final response. Primary use | |
| case is response validation and automatic retries. | |
| - **Input Fields**: | |
| - `prompt`: (`string`) The user's original request. | |
| - `prompt_response`: (`string`) The final text generated by the agent. | |
| - `stop_hook_active`: (`boolean`) Indicates if this hook is already running as | |
| part of a retry sequence. | |
| - **Relevant Output Fields**: | |
| - `decision`: Set to `"deny"` to **reject the response** and force a retry. | |
| - `reason`: Required if denied. This text is sent **to the agent as a new | |
| prompt** to request a correction. | |
| - `continue`: Set to `false` to **stop the session** without retrying. | |
| - `hookSpecificOutput.clearContext`: If `true`, clears conversation history | |
| (LLM memory) while preserving UI display. | |
| - **Exit Code 2 (Retry)**: Rejects the response and triggers an automatic retry | |
| turn using `stderr` as the feedback prompt. | |
| --- | |
| ## Model hooks | |
| ### `BeforeModel` | |
| Fires before sending a request to the LLM. Operates on a stable, SDK-agnostic | |
| request format. | |
| - **Input Fields**: | |
| - `llm_request`: (`object`) Contains `model`, `messages`, and `config` | |
| (generation params). | |
| - **Relevant Output Fields**: | |
| - `hookSpecificOutput.llm_request`: An object that **overrides** parts of the | |
| outgoing request (for example, changing models or temperature). | |
| - `hookSpecificOutput.llm_response`: A **Synthetic Response** object. If | |
| provided, the CLI skips the LLM call entirely and uses this as the response. | |
| - `decision`: Set to `"deny"` to block the request and abort the turn. | |
| - **Exit Code 2 (Block Turn)**: Aborts the turn and skips the LLM call. Uses | |
| `stderr` as the error message. | |
| ### `BeforeToolSelection` | |
| Fires before the LLM decides which tools to call. Used to filter the available | |
| toolset or force specific tool modes. | |
| - **Input Fields**: | |
| - `llm_request`: (`object`) Same format as `BeforeModel`. | |
| - **Relevant Output Fields**: | |
| - `hookSpecificOutput.toolConfig.mode`: (`"AUTO" | "ANY" | "NONE"`) | |
| - `"NONE"`: Disables all tools (Wins over other hooks). | |
| - `"ANY"`: Forces at least one tool call. | |
| - `hookSpecificOutput.toolConfig.allowedFunctionNames`: (`string[]`) Whitelist | |
| of tool names. | |
| - **Union Strategy**: Multiple hooks' whitelists are **combined**. | |
| - **Limitations**: Does **not** support `decision`, `continue`, or | |
| `systemMessage`. | |
| ### `AfterModel` | |
| Fires immediately after an LLM response chunk is received. Used for real-time | |
| redaction or PII filtering. | |
| - **Input Fields**: | |
| - `llm_request`: (`object`) The original request. | |
| - `llm_response`: (`object`) The model's response (or a single chunk during | |
| streaming). | |
| - **Relevant Output Fields**: | |
| - `hookSpecificOutput.llm_response`: An object that **replaces** the model's | |
| response chunk. | |
| - `decision`: Set to `"deny"` to discard the response chunk and block the | |
| turn. | |
| - `continue`: Set to `false` to **kill the entire agent loop** immediately. | |
| - **Note on Streaming**: Fired for **every chunk** generated by the model. | |
| Modifying the response only affects the current chunk. | |
| - **Exit Code 2 (Block Response)**: Aborts the turn and discards the model's | |
| output. Uses `stderr` as the error message. | |
| --- | |
| ## Lifecycle & system hooks | |
| ### `SessionStart` | |
| Fires on application startup, resuming a session, or after a `/clear` command. | |
| Used for loading initial context. | |
| - **Input fields**: | |
| - `source`: (`"startup" | "resume" | "clear"`) | |
| - **Relevant output fields**: | |
| - `hookSpecificOutput.additionalContext`: (`string`) | |
| - **Interactive**: Injected as the first turn in history. | |
| - **Non-interactive**: Prepended to the user's prompt. | |
| - `systemMessage`: Shown at the start of the session. | |
| - **Advisory only**: `continue` and `decision` fields are **ignored**. Startup | |
| is never blocked. | |
| ### `SessionEnd` | |
| Fires when the CLI exits or a session is cleared. Used for cleanup or final | |
| telemetry. | |
| - **Input Fields**: | |
| - `reason`: (`"exit" | "clear" | "logout" | "prompt_input_exit" | "other"`) | |
| - **Relevant Output Fields**: | |
| - `systemMessage`: Displayed to the user during shutdown. | |
| - **Best Effort**: The CLI **will not wait** for this hook to complete and | |
| ignores all flow-control fields (`continue`, `decision`). | |
| ### `Notification` | |
| Fires when the CLI emits a system alert (for example, Tool Permissions). Used | |
| for external logging or cross-platform alerts. | |
| - **Input Fields**: | |
| - `notification_type`: (`"ToolPermission"`) | |
| - `message`: Summary of the alert. | |
| - `details`: JSON object with alert-specific metadata (for example, tool name, | |
| file path). | |
| - **Relevant Output Fields**: | |
| - `systemMessage`: Displayed alongside the system alert. | |
| - **Observability Only**: This hook **cannot** block alerts or grant permissions | |
| automatically. Flow-control fields are ignored. | |
| ### `PreCompress` | |
| Fires before the CLI summarizes history to save tokens. Used for logging or | |
| state saving. | |
| - **Input Fields**: | |
| - `trigger`: (`"auto" | "manual"`) | |
| - **Relevant Output Fields**: | |
| - `systemMessage`: Displayed to the user before compression. | |
| - **Advisory Only**: Fired asynchronously. It **cannot** block or modify the | |
| compression process. Flow-control fields are ignored. | |
| --- | |
| ## Stable Model API | |
| Gemini CLI uses these structures to ensure hooks don't break across SDK updates. | |
| **LLMRequest**: | |
| ```typescript | |
| { | |
| "model": string, | |
| "messages": Array<{ | |
| "role": "user" | "model" | "system", | |
| "content": string // Non-text parts are filtered out for hooks | |
| }>, | |
| "config": { "temperature": number, ... }, | |
| "toolConfig": { "mode": string, "allowedFunctionNames": string[] } | |
| } | |
| ``` | |
| **LLMResponse**: | |
| ```typescript | |
| { | |
| "candidates": Array<{ | |
| "content": { "role": "model", "parts": string[] }, | |
| "finishReason": string | |
| }>, | |
| "usageMetadata": { "totalTokenCount": number } | |
| } | |
| ``` | |