diff --git a/docs/extensions/index.md b/docs/extensions/index.md index 2c1ab9cd93..2d00a4f7d4 100644 --- a/docs/extensions/index.md +++ b/docs/extensions/index.md @@ -263,6 +263,54 @@ Would provide these commands: - `/deploy` - Shows as `[gcp] Custom command from deploy.toml` in help - `/gcs:sync` - Shows as `[gcp] Custom command from sync.toml` in help +### Hooks + +Extensions can provide [hooks](../hooks/index.md) to intercept and customize +Gemini CLI behavior at specific lifecycle events. Hooks provided by an extension +must be defined in a `hooks/hooks.json` file within the extension directory. + +> [!IMPORTANT] Hooks are not defined directly in `gemini-extension.json`. The +> CLI specifically looks for the `hooks/hooks.json` file. + +#### Directory structure + +``` +.gemini/extensions/my-extension/ +├── gemini-extension.json +└── hooks/ + └── hooks.json +``` + +#### `hooks/hooks.json` format + +The `hooks.json` file contains a `hooks` object where keys are +[event names](../hooks/reference.md#supported-events) and values are arrays of +[hook definitions](../hooks/reference.md#hook-definition). + +```json +{ + "hooks": { + "before_agent": [ + { + "hooks": [ + { + "type": "command", + "command": "node ${extensionPath}/scripts/setup.js", + "name": "Extension Setup" + } + ] + } + ] + } +} +``` + +#### Supported variables + +Just like `gemini-extension.json`, the `hooks/hooks.json` file supports +[variable substitution](#variables). This is particularly useful for referencing +scripts within the extension directory using `${extensionPath}`. + ### Conflict resolution Extension commands have the lowest precedence. When a conflict occurs with user @@ -278,11 +326,12 @@ For example, if both a user and the `gcp` extension define a `deploy` command: - `/gcp.deploy` - Executes the extension's deploy command (marked with `[gcp]` tag) -## Variables +### Variables -Gemini CLI extensions allow variable substitution in `gemini-extension.json`. -This can be useful if e.g., you need the current directory to run an MCP server -using `"cwd": "${extensionPath}${/}run.ts"`. +Gemini CLI extensions allow variable substitution in both +`gemini-extension.json` and `hooks/hooks.json`. This can be useful if e.g., you +need the current directory to run an MCP server or hook script using +`"cwd": "${extensionPath}${/}run.ts"`. **Supported variables:** @@ -291,3 +340,4 @@ using `"cwd": "${extensionPath}${/}run.ts"`. | `${extensionPath}` | The fully-qualified path of the extension in the user's filesystem e.g., '/Users/username/.gemini/extensions/example-extension'. This will not unwrap symlinks. | | `${workspacePath}` | The fully-qualified path of the current workspace. | | `${/} or ${pathSeparator}` | The path separator (differs per OS). | +| `${process.execPath}` | The path to the Node.js binary executing the CLI. | diff --git a/docs/hooks/index.md b/docs/hooks/index.md index 48b30a721d..3470a54196 100644 --- a/docs/hooks/index.md +++ b/docs/hooks/index.md @@ -46,6 +46,11 @@ project hook (identified by its name and command), but it is **your responsibility** to review these hooks (and any installed extensions) before trusting them. +> [!NOTE] Extension hooks are subject to a mandatory security warning and +> consent flow during extension installation or update if hooks are detected. +> You must explicitly approve the installation or update of any extension that +> contains hooks. + See [Security Considerations](best-practices.md#using-hooks-securely) for a detailed threat model and mitigation strategies. @@ -444,7 +449,8 @@ numbers run first): 2. **User settings:** `~/.gemini/settings.json` 3. **System settings:** `/etc/gemini-cli/settings.json` 4. **Extensions:** Internal hooks defined by installed extensions (lowest - priority) + priority). See [Extensions documentation](../extensions/index.md#hooks) for + details on how extensions define and configure hooks. #### Deduplication and shadowing diff --git a/docs/hooks/writing-hooks.md b/docs/hooks/writing-hooks.md index 12fcb69758..e11fb049cb 100644 --- a/docs/hooks/writing-hooks.md +++ b/docs/hooks/writing-hooks.md @@ -1018,6 +1018,24 @@ const SECRET_PATTERNS = [ ]; ``` +## Packaging as an extension + +While project-level hooks are great for specific repositories, you might want to +share your hooks across multiple projects or with other users. You can do this +by packaging your hooks as a [Gemini CLI extension](../extensions/index.md). + +Packaging as an extension provides: + +- **Easy distribution:** Share hooks via a git repository or GitHub release. +- **Centralized management:** Install, update, and disable hooks using + `gemini extensions` commands. +- **Version control:** Manage hook versions separately from your project code. +- **Variable substitution:** Use `${extensionPath}` and `${process.execPath}` + for portable, cross-platform scripts. + +To package hooks as an extension, follow the +[extensions hook documentation](../extensions/index.md#hooks). + ## Learn more - [Hooks Reference](index.md) - Complete API reference and configuration