# Gemini CLI extensions

_This documentation is up-to-date with the v0.4.0 release._

Gemini CLI extensions package prompts, MCP servers, Agent Skills, and custom
commands into a familiar and user-friendly format. With extensions, you can
expand the capabilities of Gemini CLI and share those capabilities with others.
They're designed to be easily installable and shareable.

To see examples of extensions, you can browse a gallery of
[Gemini CLI extensions](https://geminicli.com/extensions/browse/).

See [getting started docs](getting-started-extensions.md) for a guide on
creating your first extension.

See [releasing docs](extension-releasing.md) for an advanced guide on setting up
GitHub releases.

## Extension management

We offer a suite of extension management tools using `gemini extensions`
commands.

Note that these commands are not supported from within the CLI, although you can
list installed extensions using the `/extensions list` subcommand.

Note that all of these commands will only be reflected in active CLI sessions on
restart.

### Installing an extension

You can install an extension using `gemini extensions install` with either a
GitHub URL or a local path.

Note that we create a copy of the installed extension, so you will need to run
`gemini extensions update` to pull in changes from both locally-defined
extensions and those on GitHub.

NOTE: If you are installing an extension from GitHub, you'll need to have `git`
installed on your machine. See
[git installation instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
for help.

```
gemini extensions install <source> [--ref <ref>] [--auto-update] [--pre-release] [--consent]
```

- `<source>`: The github URL or local path of the extension to install.
- `--ref`: The git ref to install from.
- `--auto-update`: Enable auto-update for this extension.
- `--pre-release`: Enable pre-release versions for this extension.
- `--consent`: Acknowledge the security risks of installing an extension and
  skip the confirmation prompt.

### Uninstalling an extension

To uninstall one or more extensions, run
`gemini extensions uninstall <name...>`:

```
gemini extensions uninstall gemini-cli-security gemini-cli-another-extension
```

### Disabling an extension

Extensions are, by default, enabled across all workspaces. You can disable an
extension entirely or for specific workspace.

```
gemini extensions disable <name> [--scope <scope>]
```

- `<name>`: The name of the extension to disable.
- `--scope`: The scope to disable the extension in (`user` or `workspace`).

### Enabling an extension

You can enable extensions using `gemini extensions enable <name>`. You can also
enable an extension for a specific workspace using
`gemini extensions enable <name> --scope=workspace` from within that workspace.

```
gemini extensions enable <name> [--scope <scope>]
```

- `<name>`: The name of the extension to enable.
- `--scope`: The scope to enable the extension in (`user` or `workspace`).

### Updating an extension

For extensions installed from a local path or a git repository, you can
explicitly update to the latest version (as reflected in the
`gemini-extension.json` `version` field) with `gemini extensions update <name>`.

You can update all extensions with:

```
gemini extensions update --all
```

### Create a boilerplate extension

We offer several example extensions `context`, `custom-commands`,
`exclude-tools` and `mcp-server`. You can view these examples
[here](https://github.com/google-gemini/gemini-cli/tree/main/packages/cli/src/commands/extensions/examples).

To copy one of these examples into a development directory using the type of
your choosing, run:

```
gemini extensions new <path> [template]
```

- `<path>`: The path to create the extension in.
- `[template]`: The boilerplate template to use.

### Link a local extension

The `gemini extensions link` command will create a symbolic link from the
extension installation directory to the development path.

This is useful so you don't have to run `gemini extensions update` every time
you make changes you'd like to test.

```
gemini extensions link <path>
```

- `<path>`: The path of the extension to link.

## How it works

On startup, Gemini CLI looks for extensions in `<home>/.gemini/extensions`

Extensions exist as a directory that contains a `gemini-extension.json` file.
For example:

`<home>/.gemini/extensions/my-extension/gemini-extension.json`

### `gemini-extension.json`

The `gemini-extension.json` file contains the configuration for the extension.
The file has the following structure:

```json
{
  "name": "my-extension",
  "version": "1.0.0",
  "mcpServers": {
    "my-server": {
      "command": "node my-server.js"
    }
  },
  "contextFileName": "GEMINI.md",
  "excludeTools": ["run_shell_command"]
}
```

- `name`: The name of the extension. This is used to uniquely identify the
  extension and for conflict resolution when extension commands have the same
  name as user or project commands. The name should be lowercase or numbers and
  use dashes instead of underscores or spaces. This is how users will refer to
  your extension in the CLI. Note that we expect this name to match the
  extension directory name.
- `version`: The version of the extension.
- `mcpServers`: A map of MCP servers to settings. The key is the name of the
  server, and the value is the server configuration. These servers will be
  loaded on startup just like MCP servers settings in a
  [`settings.json` file](../get-started/configuration.md). If both an extension
  and a `settings.json` file settings an MCP server with the same name, the
  server defined in the `settings.json` file takes precedence.
  - Note that all MCP server configuration options are supported except for
    `trust`.
- `contextFileName`: The name of the file that contains the context for the
  extension. This will be used to load the context from the extension directory.
  If this property is not used but a `GEMINI.md` file is present in your
  extension directory, then that file will be loaded.
- `excludeTools`: An array of tool names to exclude from the model. You can also
  specify command-specific restrictions for tools that support it, like the
  `run_shell_command` tool. For example,
  `"excludeTools": ["run_shell_command(rm -rf)"]` will block the `rm -rf`
  command. Note that this differs from the MCP server `excludeTools`
  functionality, which can be listed in the MCP server config.

When Gemini CLI starts, it loads all the extensions and merges their
configurations. If there are any conflicts, the workspace configuration takes
precedence.

### Settings

_Note: This is an experimental feature. We do not yet recommend extension
authors introduce settings as part of their core flows._

Extensions can define settings that the user will be prompted to provide upon
installation. This is useful for things like API keys, URLs, or other
configuration that the extension needs to function.

To define settings, add a `settings` array to your `gemini-extension.json` file.
Each object in the array should have the following properties:

- `name`: A user-friendly name for the setting.
- `description`: A description of the setting and what it's used for.
- `envVar`: The name of the environment variable that the setting will be stored
  as.
- `sensitive`: Optional boolean. If true, obfuscates the input the user provides
  and stores the secret in keychain storage. **Example**

```json
{
  "name": "my-api-extension",
  "version": "1.0.0",
  "settings": [
    {
      "name": "API Key",
      "description": "Your API key for the service.",
      "envVar": "MY_API_KEY"
    }
  ]
}
```

When a user installs this extension, they will be prompted to enter their API
key. The value will be saved to a `.env` file in the extension's directory
(e.g., `<home>/.gemini/extensions/my-api-extension/.env`).

You can view a list of an extension's settings by running:

```
gemini extensions list
```

and you can update a given setting using:

```
gemini extensions config <extension name> [setting name] [--scope <scope>]
```

- `--scope`: The scope to set the setting in (`user` or `workspace`). This is
  optional and will default to `user`.

### Custom commands

Extensions can provide [custom commands](../cli/custom-commands.md) by placing
TOML files in a `commands/` subdirectory within the extension directory. These
commands follow the same format as user and project custom commands and use
standard naming conventions.

**Example**

An extension named `gcp` with the following structure:

```
.gemini/extensions/gcp/
├── gemini-extension.json
└── commands/
    ├── deploy.toml
    └── gcs/
        └── sync.toml
```

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

### Agent Skills

_Note: This is an experimental feature enabled via `experimental.skills`._

Extensions can bundle [Agent Skills](../cli/skills.md) to provide on-demand
expertise and specialized workflows. To include skills in your extension, place
them in a `skills/` subdirectory within the extension directory. Each skill must
follow the [Agent Skills structure](../cli/skills.md#folder-structure),
including a `SKILL.md` file.

**Example**

An extension named `security-toolkit` with the following structure:

```
.gemini/extensions/security-toolkit/
├── gemini-extension.json
└── skills/
    ├── audit/
    │   ├── SKILL.md
    │   └── scripts/
    │       └── scan.py
    └── hardening/
        └── SKILL.md
```

Upon installation, these skills will be discovered by Gemini CLI and can be
activated during a session when the model identifies a task matching their
descriptions.

Extension skills have the lowest precedence and will be overridden by user or
workspace skills of the same name. They can be viewed and managed (enabled or
disabled) using the [`/skills` command](../cli/skills.md#managing-skills).

### 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
or project commands:

1. **No conflict**: Extension command uses its natural name (e.g., `/deploy`)
2. **With conflict**: Extension command is renamed with the extension prefix
   (e.g., `/gcp.deploy`)

For example, if both a user and the `gcp` extension define a `deploy` command:

- `/deploy` - Executes the user's deploy command
- `/gcp.deploy` - Executes the extension's deploy command (marked with `[gcp]`
  tag)

### Variables

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:**

| variable                   | description                                                                                                                                                     |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `${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.                                                                                                               |
