diff --git a/docs/extensions/best-practices.md b/docs/extensions/best-practices.md index 73c578f1beb..8ed3e7fc230 100644 --- a/docs/extensions/best-practices.md +++ b/docs/extensions/best-practices.md @@ -1,19 +1,19 @@ -# Extensions on Gemini CLI: Best practices +# Gemini CLI extension best practices This guide covers best practices for developing, securing, and maintaining Gemini CLI extensions. ## Development -Developing extensions for Gemini CLI is intended to be a lightweight, iterative -process. +Developing extensions for Gemini CLI is a lightweight, iterative process. Use +these strategies to build robust and efficient extensions. ### Structure your extension -While simple extensions can just be a few files, we recommend a robust structure -for complex extensions: +While simple extensions may contain only a few files, we recommend a organized +structure for complex projects. -``` +```text my-extension/ ├── package.json ├── tsconfig.json @@ -24,47 +24,50 @@ my-extension/ └── dist/ ``` -- **Use TypeScript**: We strongly recommend using TypeScript for type safety and - better tooling. -- **Separate source and build**: Keep your source code in `src` and build to - `dist`. -- **Bundle dependencies**: If your extension has many dependencies, consider - bundling them (e.g., with `esbuild` or `webpack`) to reduce install time and - potential conflicts. +- **Use TypeScript:** We strongly recommend using TypeScript for type safety and + improved developer experience. +- **Separate source and build:** Keep your source code in `src/` and output + build artifacts to `dist/`. +- **Bundle dependencies:** If your extension has many dependencies, bundle them + using a tool like `esbuild` to reduce installation time and avoid conflicts. ### Iterate with `link` -Use `gemini extensions link` to develop locally without constantly reinstalling: +Use the `gemini extensions link` command to develop locally without reinstalling +your extension after every change. ```bash cd my-extension gemini extensions link . ``` -Changes to your code (after rebuilding) will be immediately available in the CLI -on restart. +Changes to your code are immediately available in the CLI after you rebuild the +project and restart the session. ### Use `GEMINI.md` effectively -Your `GEMINI.md` file provides context to the model. Keep it focused: +Your `GEMINI.md` file provides essential context to the model. -- **Do:** Explain high-level goals and how to use the provided tools. -- **Don't:** Dump your entire documentation. -- **Do:** Use clear, concise language. +- **Focus on goals:** Explain the high-level purpose of the extension and how to + interact with its tools. +- **Be concise:** Avoid dumping exhaustive documentation into the file. Use + clear, direct language. +- **Provide examples:** Include brief examples of how the model should use + specific tools or commands. ## Security -When building a Gemini CLI extension, follow general security best practices -(such as least privilege and input validation) to reduce risk. +Follow the principle of least privilege and rigorous input validation when +building extensions. ### Minimal permissions -When defining tools in your MCP server, only request the permissions necessary. -Avoid giving the model broad access (like full shell access) if a more -restricted set of tools will suffice. +Only request the permissions your MCP server needs to function. Avoid giving the +model broad access (such as full shell access) if restricted tools are +sufficient. -If you must use powerful tools like `run_shell_command`, consider restricting -them to specific commands in your `gemini-extension.json`: +If your extension uses powerful tools like `run_shell_command`, restrict them in +your `gemini-extension.json` file: ```json { @@ -73,27 +76,26 @@ them to specific commands in your `gemini-extension.json`: } ``` -This ensures that even if the model tries to execute a dangerous command, it -will be blocked at the CLI level. +This ensures the CLI blocks dangerous commands even if the model attempts to +execute them. ### Validate inputs -Your MCP server is running on the user's machine. Always validate inputs to your -tools to prevent arbitrary code execution or filesystem access outside the -intended scope. +Your MCP server runs on the user's machine. Always validate tool inputs to +prevent arbitrary code execution or unauthorized filesystem access. ```typescript -// Good: Validating paths +// Example: Validating paths if (!path.resolve(inputPath).startsWith(path.resolve(allowedDir) + path.sep)) { throw new Error('Access denied'); } ``` -### Sensitive settings +### Secure sensitive settings -If your extension requires API keys, use the `sensitive: true` option in -`gemini-extension.json`. This ensures keys are stored securely in the system -keychain and obfuscated in the UI. +If your extension requires API keys or other secrets, use the `sensitive: true` +option in your manifest. This ensures keys are stored in the system keychain and +obfuscated in the CLI output. ```json "settings": [ @@ -105,35 +107,82 @@ keychain and obfuscated in the UI. ] ``` -## Releasing +## Release -You can upload your extension directly to GitHub to list it in the gallery. -Gemini CLI extensions also offers support for more complicated -[releases](releasing.md). +Follow standard versioning and release practices to ensure a smooth experience +for your users. ### Semantic versioning -Follow [Semantic Versioning](https://semver.org/). +Follow [Semantic Versioning (SemVer)](https://semver.org/) to communicate +changes clearly. -- **Major**: Breaking changes (renaming tools, changing arguments). -- **Minor**: New features (new tools, commands). -- **Patch**: Bug fixes. +- **Major:** Breaking changes (e.g., renaming tools or changing arguments). +- **Minor:** New features (e.g., adding new tools or commands). +- **Patch:** Bug fixes and performance improvements. -### Release Channels +### Release channels -Use git branches to manage release channels (e.g., `main` for stable, `dev` for -bleeding edge). This allows users to choose their stability level: +Use Git branches to manage release channels. This lets users choose between +stability and the latest features. ```bash -# Stable +# Install the stable version (default branch) gemini extensions install github.com/user/repo -# Dev +# Install the development version gemini extensions install github.com/user/repo --ref dev ``` ### Clean artifacts -If you are using GitHub Releases, ensure your release artifacts only contain the -necessary files (`dist/`, `gemini-extension.json`, `package.json`). Exclude -`node_modules` (users will install them) and `src/` to keep downloads small. +When using GitHub Releases, ensure your archives only contain necessary files +(such as `dist/`, `gemini-extension.json`, and `package.json`). Exclude +`node_modules/` and `src/` to minimize download size. + +## Test and verify + +Test your extension thoroughly before releasing it to users. + +- **Manual verification:** Use `gemini extensions link` to test your extension + in a live CLI session. Verify that tools appear in the debug console (F12) and + that custom commands resolve correctly. +- **Automated testing:** If your extension includes an MCP server, write unit + tests for your tool logic using a framework like Vitest or Jest. You can test + MCP tools in isolation by mocking the transport layer. + +## Troubleshooting + +Use these tips to diagnose and fix common extension issues. + +### Extension not loading + +If your extension doesn't appear in `/extensions list`: + +- **Check the manifest:** Ensure `gemini-extension.json` is in the root + directory and contains valid JSON. +- **Verify the name:** The `name` field in the manifest must match the extension + directory name exactly. +- **Restart the CLI:** Extensions are loaded at the start of a session. Restart + Gemini CLI after making changes to the manifest or linking a new extension. + +### MCP server failures + +If your tools aren't working as expected: + +- **Check the logs:** View the CLI logs to see if the MCP server failed to + start. +- **Test the command:** Run the server's `command` and `args` directly in your + terminal to ensure it starts correctly outside of Gemini CLI. +- **Debug console:** In interactive mode, press **F12** to open the debug + console and inspect tool calls and responses. + +### Command conflicts + +If a custom command isn't responding: + +- **Check precedence:** Remember that user and project commands take precedence + over extension commands. Use the prefixed name (e.g., `/extension.command`) to + verify the extension's version. +- **Help command:** Run `/help` to see a list of all available commands and + their sources. diff --git a/docs/extensions/index.md b/docs/extensions/index.md index 64171e1c18b..1c6ce1e6997 100644 --- a/docs/extensions/index.md +++ b/docs/extensions/index.md @@ -6,19 +6,44 @@ With extensions, you can expand the capabilities of Gemini CLI and share those capabilities with others. They are 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/). +To see what's possible, browse the +[Gemini CLI extension gallery](https://geminicli.com/extensions/browse/). -## Managing extensions +## Choose your path -You can verify your installed extensions and their status using the interactive -command: +Choose the guide that best fits your needs. + +### I want to use extensions + +Learn how to discover, install, and manage extensions to enhance your Gemini CLI +experience. + +- **[Manage extensions](#manage-extensions):** List and verify your installed + extensions. +- **[Install extensions](#installation):** Add new capabilities from GitHub or + local paths. + +### I want to build extensions + +Learn how to create, test, and share your own extensions with the community. + +- **[Build extensions](writing-extensions.md):** Create your first extension + from a template. +- **[Best practices](best-practices.md):** Learn how to build secure and + reliable extensions. +- **[Publish to the gallery](releasing.md):** Share your work with the world. + +## Manage extensions + +Use the interactive `/extensions` command to verify your installed extensions +and their status: ```bash /extensions list ``` -or in noninteractive mode: +You can also manage extensions from your terminal using the `gemini extensions` +command group: ```bash gemini extensions list @@ -26,20 +51,11 @@ gemini extensions list ## Installation -To install a real extension, you can use the `extensions install` command with a -GitHub repository URL in noninteractive mode. For example: +Install an extension by providing its GitHub repository URL. For example: ```bash gemini extensions install https://github.com/gemini-cli-extensions/workspace ``` -## Next steps - -- [Writing extensions](writing-extensions.md): Learn how to create your first - extension. -- [Extensions reference](reference.md): Deeply understand the extension format, - commands, and configuration. -- [Best practices](best-practices.md): Learn strategies for building great - extensions. -- [Extensions releasing](releasing.md): Learn how to share your extensions with - the world. +For more advanced installation options, see the +[Extension reference](reference.md#install-an-extension). diff --git a/docs/extensions/reference.md b/docs/extensions/reference.md index 4fc94dd1621..eec5b82025c 100644 --- a/docs/extensions/reference.md +++ b/docs/extensions/reference.md @@ -1,134 +1,113 @@ -# Extensions reference +# Extension reference This guide covers the `gemini extensions` commands and the structure of the `gemini-extension.json` configuration file. -## Extension management +## Manage extensions -We offer a suite of extension management tools using `gemini extensions` -commands. +Use the `gemini extensions` command group to manage your extensions from the +terminal. -Note that these commands (e.g. `gemini extensions install`) are not supported -from within the CLI's **interactive mode**, although you can list installed -extensions using the `/extensions list` slash command. +Note that commands like `gemini extensions install` are not supported within the +CLI's interactive mode. However, you can use the `/extensions list` command to +view installed extensions. All management operations, including updates to slash +commands, take effect only after you restart the CLI session. -Note that all of these management operations (including updates to slash -commands) will only be reflected in active CLI sessions on **restart**. +### Install an extension -### Installing an extension +Install an extension by providing its GitHub repository URL or a local file +path. -You can install an extension using `gemini extensions install` with either a -GitHub URL or a local path. +Gemini CLI creates a copy of the extension during installation. You must run +`gemini extensions update` to pull changes from the source. To install from +GitHub, you must have `git` installed on your machine. -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. - -``` +```bash gemini extensions install [--ref ] [--auto-update] [--pre-release] [--consent] ``` -- ``: 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. +- ``: The GitHub URL or local path of the extension. +- `--ref`: The git ref (branch, tag, or commit) to install. +- `--auto-update`: Enable automatic updates for this extension. +- `--pre-release`: Enable installation of pre-release versions. +- `--consent`: Acknowledge security risks and skip the confirmation prompt. -### Uninstalling an extension +### Uninstall an extension -To uninstall one or more extensions, run -`gemini extensions uninstall `: +To uninstall one or more extensions, use the `uninstall` command: -``` -gemini extensions uninstall gemini-cli-security gemini-cli-another-extension +```bash +gemini extensions uninstall ``` -### Disabling an extension +### Disable an extension -Extensions are, by default, enabled across all workspaces. You can disable an -extension entirely or for specific workspace. +Extensions are enabled globally by default. You can disable an extension +entirely or for a specific workspace. -``` +```bash gemini extensions disable [--scope ] ``` - ``: The name of the extension to disable. - `--scope`: The scope to disable the extension in (`user` or `workspace`). -### Enabling an extension +### Enable an extension -You can enable extensions using `gemini extensions enable `. You can also -enable an extension for a specific workspace using -`gemini extensions enable --scope=workspace` from within that workspace. +Re-enable a disabled extension using the `enable` command: -``` +```bash gemini extensions enable [--scope ] ``` - ``: 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 `. +### Update an extension -You can update all extensions with: +Update an extension to the version specified in its `gemini-extension.json` +file. +```bash +gemini extensions update ``` + +To update all installed extensions at once: + +```bash 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). +### Create an extension from a template -To copy one of these examples into a development directory using the type of -your choosing, run: +Create a new extension directory using a built-in template. -``` +```bash gemini extensions new [template] ``` -- ``: The path to create the extension in. -- `[template]`: The boilerplate template to use. +- ``: The directory to create. +- `[template]`: The template to use (e.g., `mcp-server`, `context`, + `custom-commands`). ### 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. +Create a symbolic link between your development directory and the Gemini CLI +extensions directory. This lets you test changes immediately without +reinstalling. -``` +```bash gemini extensions link ``` -- ``: The path of the extension to link. - ## Extension format -On startup, Gemini CLI looks for extensions in `/.gemini/extensions` - -Extensions exist as a directory that contains a `gemini-extension.json` file. -For example: - -`/.gemini/extensions/my-extension/gemini-extension.json` +Gemini CLI loads extensions from `/.gemini/extensions`. Each extension +must have a `gemini-extension.json` file in its root directory. ### `gemini-extension.json` -The `gemini-extension.json` file contains the configuration for the extension. -The file has the following structure: +The manifest file defines the extension's behavior and configuration. ```json { @@ -145,56 +124,27 @@ The file has the following structure: } ``` -- `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. -- `description`: A short description of the extension. This will be displayed on - [geminicli.com/extensions](https://geminicli.com/extensions). -- `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 settingsd 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. -- `themes`: An array of custom themes provided by the extension. Each theme is - an object that defines the color scheme for the CLI UI. See the - [Themes guide](../cli/themes.md) for more details on the theme format. - -When Gemini CLI starts, it loads all the extensions and merges their -configurations. If there are any conflicts, the workspace configuration takes -precedence. - -### Settings - -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** +- `name`: A unique identifier for the extension. Use lowercase letters, numbers, + and dashes. This name must match the extension's directory name. +- `version`: The current version of the extension. +- `description`: A short summary shown in the extension gallery. +- `mcpServers`: A map of Model Context Protocol (MCP) + servers. Extension servers follow the same format as standard + [CLI configuration](../get-started/configuration.md). +- `contextFileName`: The name of the context file (defaults to `GEMINI.md`). Can + also be an array of strings to load multiple context files. +- `excludeTools`: An array of tools to block from the model. You can restrict + specific arguments, such as `run_shell_command(rm -rf)`. +- `themes`: An optional list of themes provided by the extension. See + [Themes](../cli/themes.md) for more information. + +### Extension settings + +Extensions can define settings that users provide during installation, such as +API keys or URLs. These values are stored in a `.env` file within the extension +directory. + +To define settings, add a `settings` array to your manifest: ```json { @@ -204,106 +154,54 @@ Each object in the array should have the following properties: { "name": "API Key", "description": "Your API key for the service.", - "envVar": "MY_API_KEY" + "envVar": "MY_API_KEY", + "sensitive": true } ] } ``` -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., `/.gemini/extensions/my-api-extension/.env`). +- `name`: The setting's display name. +- `description`: A clear explanation of the setting. +- `envVar`: The environment variable name where the value is stored. +- `sensitive`: If `true`, the value is stored in the system keychain and + obfuscated in the UI. -You can view a list of an extension's settings by running: +To update an extension's settings: +```bash +gemini extensions config [setting] [--scope ] ``` -gemini extensions list -``` - -and you can update a given setting using: - -``` -gemini extensions config [setting name] [--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. +Provide [custom commands](../cli/custom-commands.md) by placing TOML files in a +`commands/` subdirectory. Gemini CLI uses the directory structure to determine +the command name. -**Example** - -An extension named `gcp` with the following structure: +For an extension named `gcp`: -``` -.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 +- `commands/deploy.toml` becomes `/deploy` +- `commands/gcs/sync.toml` becomes `/gcs:sync` (namespaced with a colon) ### 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. +Intercept and customize CLI behavior using [hooks](../hooks/index.md). Define +hooks in a `hooks/hooks.json` file within your extension directory. Note that +hooks are not defined in the `gemini-extension.json` manifest. -### Agent Skills +### Agent skills -Extensions can bundle [Agent Skills](../cli/skills.md) to provide specialized -workflows. Skills must be placed in a `skills/` directory within the extension. - -**Example** - -An extension with the following structure: - -``` -.gemini/extensions/my-extension/ -├── gemini-extension.json -└── skills/ - └── security-audit/ - └── SKILL.md -``` - -Will expose a `security-audit` skill that the model can activate. +Bundle [agent skills](../cli/skills.md) to provide specialized workflows. Place +skill definitions in a `skills/` directory. For example, +`skills/security-audit/SKILL.md` exposes a `security-audit` skill. ### Sub-agents -> **Note: Sub-agents are currently an experimental feature.** - -Extensions can provide [sub-agents](../core/subagents.md) that users can -delegate tasks to. - -To bundle sub-agents with your extension, create an `agents/` directory in your -extension's root folder and add your agent definition files (`.md`) there. - -**Example** - -``` -.gemini/extensions/my-extension/ -├── gemini-extension.json -└── agents/ - ├── security-auditor.md - └── database-expert.md -``` +> **Note:** Sub-agents are a preview feature currently under active development. -Gemini CLI will automatically discover and load these agents when the extension -is installed and enabled. +Provide [sub-agents](../core/subagents.md) that users can delegate tasks to. Add +agent definition files (`.md`) to an `agents/` directory in your extension root. ### Themes @@ -351,30 +249,17 @@ the theme name in parentheses, e.g., `shades-of-green (my-green-extension)`. ### 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) +Extension commands have the lowest precedence. If an extension command name +conflicts with a user or project command, the extension command is prefixed with +the extension name (e.g., `/gcp.deploy`) using a dot separator. ## 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 using an argument like -`"args": ["${extensionPath}${/}dist${/}server.js"]`. - -**Supported variables:** +Gemini CLI supports variable substitution in `gemini-extension.json` and +`hooks/hooks.json`. -| 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). | +| Variable | Description | +| :----------------- | :---------------------------------------------- | +| `${extensionPath}` | The absolute path to the extension's directory. | +| `${workspacePath}` | The absolute path to the current workspace. | +| `${/}` | The platform-specific path separator. | diff --git a/docs/extensions/releasing.md b/docs/extensions/releasing.md index 18e94f2f58f..f29a1eac6e0 100644 --- a/docs/extensions/releasing.md +++ b/docs/extensions/releasing.md @@ -1,146 +1,117 @@ -# Extension releasing - -There are two primary ways of releasing extensions to users: - -- [Git repository](#releasing-through-a-git-repository) -- [Github Releases](#releasing-through-github-releases) - -Git repository releases tend to be the simplest and most flexible approach, -while GitHub releases can be more efficient on initial install as they are -shipped as single archives instead of requiring a git clone which downloads each -file individually. Github releases may also contain platform specific archives -if you need to ship platform specific binary files. - -## Releasing through a git repository - -This is the most flexible and simple option. All you need to do is create a -publicly accessible git repo (such as a public github repository) and then users -can install your extension using `gemini extensions install `. -They can optionally depend on a specific ref (branch/tag/commit) using the -`--ref=` argument, this defaults to the default branch. - -Whenever commits are pushed to the ref that a user depends on, they will be -prompted to update the extension. Note that this also allows for easy rollbacks, -the HEAD commit is always treated as the latest version regardless of the actual -version in the `gemini-extension.json` file. - -### Managing release channels using a git repository - -Users can depend on any ref from your git repo, such as a branch or tag, which -allows you to manage multiple release channels. - -For instance, you can maintain a `stable` branch, which users can install this -way `gemini extensions install --ref=stable`. Or, you could make -this the default by treating your default branch as your stable release branch, -and doing development in a different branch (for instance called `dev`). You can -maintain as many branches or tags as you like, providing maximum flexibility for -you and your users. - -Note that these `ref` arguments can be tags, branches, or even specific commits, -which allows users to depend on a specific version of your extension. It is up -to you how you want to manage your tags and branches. - -### Example releasing flow using a git repo - -While there are many options for how you want to manage releases using a git -flow, we recommend treating your default branch as your "stable" release branch. -This means that the default behavior for -`gemini extensions install ` is to be on the stable release -branch. - -Lets say you want to maintain three standard release channels, `stable`, -`preview`, and `dev`. You would do all your standard development in the `dev` -branch. When you are ready to do a preview release, you merge that branch into -your `preview` branch. When you are ready to promote your preview branch to -stable, you merge `preview` into your stable branch (which might be your default -branch or a different branch). - -You can also cherry pick changes from one branch into another using -`git cherry-pick`, but do note that this will result in your branches having a -slightly divergent history from each other, unless you force push changes to -your branches on each release to restore the history to a clean slate (which may -not be possible for the default branch depending on your repository settings). -If you plan on doing cherry picks, you may want to avoid having your default -branch be the stable branch to avoid force-pushing to the default branch which -should generally be avoided. - -## Releasing through GitHub releases - -Gemini CLI extensions can be distributed through -[GitHub Releases](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases). -This provides a faster and more reliable initial installation experience for -users, as it avoids the need to clone the repository. - -Each release includes at least one archive file, which contains the full -contents of the repo at the tag that it was linked to. Releases may also include -[pre-built archives](#custom-pre-built-archives) if your extension requires some -build step or has platform specific binaries attached to it. - -When checking for updates, gemini will just look for the "latest" release on -github (you must mark it as such when creating the release), unless the user -installed a specific release by passing `--ref=`. - -You may also install extensions with the `--pre-release` flag in order to get -the latest release regardless of whether it has been marked as "latest". This -allows you to test that your release works before actually pushing it to all -users. +# Release extensions -### Custom pre-built archives +Release Gemini CLI extensions to your users through a Git repository or GitHub +Releases. + +Git repository releases are the simplest approach and offer the most flexibility +for managing development branches. GitHub Releases are more efficient for +initial installations because they ship as single archives rather than requiring +a full `git clone`. Use GitHub Releases if you need to include platform-specific +binary files. + +## List your extension in the gallery + +The [Gemini CLI extension gallery](https://geminicli.com/extensions/browse/) +automatically indexes public extensions to help users discover your work. You +don't need to submit an issue or email us to list your extension. + +To have your extension automatically discovered and listed: + +1. **Use a public repository:** Ensure your extension is hosted in a public + GitHub repository. +2. **Add the GitHub topic:** Add the `gemini-cli-extension` topic to your + repository's **About** section. Our crawler uses this topic to find new + extensions. +3. **Place the manifest at the root:** Ensure your `gemini-extension.json` file + is in the absolute root of the repository or the release archive. + +Our system crawls tagged repositories daily. Once you tag your repository, your +extension will appear in the gallery if it passes validation. + +## Release through a Git repository + +Releasing through Git is the most flexible option. Create a public Git +repository and provide the URL to your users. They can then install your +extension using `gemini extensions install `. + +Users can optionally depend on a specific branch, tag, or commit using the +`--ref` argument. For example: + +```bash +gemini extensions install --ref=stable +``` -Custom archives must be attached directly to the github release as assets and -must be fully self-contained. This means they should include the entire -extension, see [archive structure](#archive-structure). +Whenever you push commits to the referenced branch, the CLI prompts users to +update their installation. The `HEAD` commit is always treated as the latest +version. -If your extension is platform-independent, you can provide a single generic -asset. In this case, there should be only one asset attached to the release. +### Manage release channels -Custom archives may also be used if you want to develop your extension within a -larger repository, you can build an archive which has a different layout from -the repo itself (for instance it might just be an archive of a subdirectory -containing the extension). +You can use branches or tags to manage different release channels, such as +`stable`, `preview`, or `dev`. -#### Platform specific archives +We recommend using your default branch as the stable release channel. This +ensures that the default installation command always provides the most reliable +version of your extension. You can then use a `dev` branch for active +development and merge it into the default branch when you are ready for a +release. -To ensure Gemini CLI can automatically find the correct release asset for each -platform, you must follow this naming convention. The CLI will search for assets -in the following order: +## Release through GitHub Releases -1. **Platform and architecture-Specific:** +Distributing extensions through +[GitHub Releases](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases) +provides a faster installation experience by avoiding a repository clone. + +Gemini CLI checks for updates by looking for the **Latest** release on GitHub. +Users can also install specific versions using the `--ref` argument with a +release tag. Use the `--pre-release` flag to install the latest version even if +it isn't marked as **Latest**. + +### Custom pre-built archives + +You can attach custom archives directly to your GitHub Release as assets. This +is useful if your extension requires a build step or includes platform-specific +binaries. + +Custom archives must be fully self-contained and follow the required +[archive structure](#archive-structure). If your extension is +platform-independent, provide a single generic asset. + +#### Platform-specific archives + +To let Gemini CLI find the correct asset for a user's platform, use the +following naming convention: + +1. **Platform and architecture-specific:** `{platform}.{arch}.{name}.{extension}` 2. **Platform-specific:** `{platform}.{name}.{extension}` -3. **Generic:** If only one asset is provided, it will be used as a generic - fallback. - -- `{name}`: The name of your extension. -- `{platform}`: The operating system. Supported values are: - - `darwin` (macOS) - - `linux` - - `win32` (Windows) -- `{arch}`: The architecture. Supported values are: - - `x64` - - `arm64` -- `{extension}`: The file extension of the archive (e.g., `.tar.gz` or `.zip`). +3. **Generic:** A single asset will be used as a fallback if no specific match + is found. + +Use these values for the placeholders: + +- `{name}`: Your extension name. +- `{platform}`: Use `darwin` (macOS), `linux`, or `win32` (Windows). +- `{arch}`: Use `x64` or `arm64`. +- `{extension}`: Use `.tar.gz` or `.zip`. **Examples:** - `darwin.arm64.my-tool.tar.gz` (specific to Apple Silicon Macs) -- `darwin.my-tool.tar.gz` (for all Macs) +- `darwin.my-tool.tar.gz` (fallback for all Macs, e.g. Intel) - `linux.x64.my-tool.tar.gz` - `win32.my-tool.zip` #### Archive structure -Archives must be fully contained extensions and have all the standard -requirements - specifically the `gemini-extension.json` file must be at the root -of the archive. - -The rest of the layout should look exactly the same as a typical extension, see -[extensions.md](./index.md). +Archives must be fully contained extensions. The `gemini-extension.json` file +must be at the root of the archive. The rest of the layout should match a +standard extension structure. #### Example GitHub Actions workflow -Here is an example of a GitHub Actions workflow that builds and releases a -Gemini CLI extension for multiple platforms: +Use this example workflow to build and release your extension for multiple +platforms: ```yaml name: Release Extension diff --git a/docs/extensions/writing-extensions.md b/docs/extensions/writing-extensions.md index 589d9c2211d..213d77542ed 100644 --- a/docs/extensions/writing-extensions.md +++ b/docs/extensions/writing-extensions.md @@ -1,18 +1,19 @@ -# Getting started with Gemini CLI extensions +# Build Gemini CLI extensions -This guide will walk you through creating your first Gemini CLI extension. -You'll learn how to set up a new extension, add a custom tool via an MCP server, -create a custom command, and provide context to the model with a `GEMINI.md` -file. +Gemini CLI extensions let you expand the capabilities of Gemini CLI by adding +custom tools, commands, and context. This guide walks you through creating your +first extension, from setting up a template to adding custom functionality and +linking it for local development. ## Prerequisites -Before you start, make sure you have the Gemini CLI installed and a basic +Before you start, ensure you have the Gemini CLI installed and a basic understanding of Node.js. -## When to use what +## Extension features -Extensions offer a variety of ways to customize Gemini CLI. +Extensions offer several ways to customize Gemini CLI. Use this table to decide +which features your extension needs. | Feature | What it is | When to use it | Invoked by | | :------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------- | @@ -25,8 +26,8 @@ Extensions offer a variety of ways to customize Gemini CLI. ## Step 1: Create a new extension -The easiest way to start is by using one of the built-in templates. We'll use -the `mcp-server` example as our foundation. +The easiest way to start is by using a built-in template. We'll use the +`mcp-server` example as our foundation. Run the following command to create a new directory called `my-first-extension` with the template files: @@ -35,7 +36,7 @@ with the template files: gemini extensions new my-first-extension mcp-server ``` -This will create a new directory with the following structure: +This creates a directory with the following structure: ``` my-first-extension/ @@ -46,12 +47,11 @@ my-first-extension/ ## Step 2: Understand the extension files -Let's look at the key files in your new extension. +Your new extension contains several key files that define its behavior. ### `gemini-extension.json` -This is the manifest file for your extension. It tells Gemini CLI how to load -and use your extension. +The manifest file tells Gemini CLI how to load and use your extension. ```json { @@ -69,17 +69,15 @@ and use your extension. - `name`: The unique name for your extension. - `version`: The version of your extension. -- `mcpServers`: This section defines one or more Model Context Protocol (MCP) - servers. MCP servers are how you can add new tools for the model to use. - - `command`, `args`, `cwd`: These fields specify how to start your server. - Notice the use of the `${extensionPath}` variable, which Gemini CLI replaces - with the absolute path to your extension's installation directory. This - allows your extension to work regardless of where it's installed. +- `mcpServers`: Defines Model Context Protocol (MCP) servers to add new tools. + - `command`, `args`, `cwd`: Specify how to start your server. The + `${extensionPath}` variable is replaced with the absolute path to your + extension's directory. ### `example.js` -This file contains the source code for your MCP server. It's a simple Node.js -server that uses the `@modelcontextprotocol/sdk`. +This file contains the source code for your MCP server. It uses the +`@modelcontextprotocol/sdk` to define tools. ```javascript /** @@ -121,24 +119,49 @@ server.registerTool( }, ); -// ... (prompt registration omitted for brevity) - const transport = new StdioServerTransport(); await server.connect(transport); ``` -This server defines a single tool called `fetch_posts` that fetches data from a -public API. - ### `package.json` -This is the standard configuration file for a Node.js project. It defines -dependencies and scripts. +The standard configuration file for a Node.js project. It defines dependencies +and scripts for your extension. + +## Step 3: Add extension settings + +Some extensions need configuration, such as API keys or user preferences. Let's +add a setting for an API key. + +1. Open `gemini-extension.json`. +2. Add a `settings` array to the configuration: + + ```json + { + "name": "mcp-server-example", + "version": "1.0.0", + "settings": [ + { + "name": "API Key", + "description": "The API key for the service.", + "envVar": "MY_SERVICE_API_KEY", + "sensitive": true + } + ], + "mcpServers": { + // ... + } + } + ``` + +When a user installs this extension, Gemini CLI will prompt them to enter the +"API Key". The value will be stored securely in the system keychain (because +`sensitive` is true) and injected into the MCP server's process as the +`MY_SERVICE_API_KEY` environment variable. -## Step 3: Link your extension +## Step 4: Link your extension -Before you can use the extension, you need to link it to your Gemini CLI -installation for local development. +Link your extension to your Gemini CLI installation for local development. 1. **Install dependencies:** @@ -150,20 +173,19 @@ installation for local development. 2. **Link the extension:** The `link` command creates a symbolic link from the Gemini CLI extensions - directory to your development directory. This means any changes you make - will be reflected immediately without needing to reinstall. + directory to your development directory. Changes you make are reflected + immediately. ```bash gemini extensions link . ``` -Now, restart your Gemini CLI session. The new `fetch_posts` tool will be -available. You can test it by asking: "fetch posts". +Restart your Gemini CLI session to use the new `fetch_posts` tool. Test it by +asking: "fetch posts". -## Step 4: Add a custom command +## Step 5: Add a custom command -Custom commands provide a way to create shortcuts for complex prompts. Let's add -a command that searches for a pattern in your code. +Custom commands create shortcuts for complex prompts. 1. Create a `commands` directory and a subdirectory for your command group: @@ -182,18 +204,17 @@ a command that searches for a pattern in your code. """ ``` - This command, `/fs:grep-code`, will take an argument, run the `grep` shell - command with it, and pipe the results into a prompt for summarization. + This command, `/fs:grep-code`, takes an argument, runs the `grep` shell + command, and pipes the results into a prompt for summarization. -After saving the file, restart the Gemini CLI. You can now run -`/fs:grep-code "some pattern"` to use your new command. +After saving the file, restart Gemini CLI. Run `/fs:grep-code "some pattern"` to +use your new command. -## Step 5: Add a custom `GEMINI.md` +## Step 6: Add a custom `GEMINI.md` -You can provide persistent context to the model by adding a `GEMINI.md` file to -your extension. This is useful for giving the model instructions on how to -behave or information about your extension's tools. Note that you may not always -need this for extensions built to expose commands and prompts. +Provide persistent context to the model by adding a `GEMINI.md` file to your +extension. This is useful for setting behavior or providing essential tool +information. 1. Create a file named `GEMINI.md` in the root of your extension directory: @@ -204,7 +225,7 @@ need this for extensions built to expose commands and prompts. posts, use the `fetch_posts` tool. Be concise in your responses. ``` -2. Update your `gemini-extension.json` to tell the CLI to load this file: +2. Update your `gemini-extension.json` to load this file: ```json { @@ -221,14 +242,13 @@ need this for extensions built to expose commands and prompts. } ``` -Restart the CLI again. The model will now have the context from your `GEMINI.md` -file in every session where the extension is active. +Restart Gemini CLI. The model now has the context from your `GEMINI.md` file in +every session where the extension is active. -## (Optional) Step 6: Add an Agent Skill +## (Optional) Step 7: Add an Agent Skill -[Agent Skills](../cli/skills.md) let you bundle specialized expertise and -procedural workflows. Unlike `GEMINI.md`, which provides persistent context, -skills are activated only when needed, saving context tokens. +[Agent Skills](../cli/skills.md) bundle specialized expertise and workflows. +Skills are activated only when needed, which saves context tokens. 1. Create a `skills` directory and a subdirectory for your skill: @@ -255,28 +275,18 @@ skills are activated only when needed, saving context tokens. 3. Suggest remediation steps for any findings. ``` -Skills bundled with your extension are automatically discovered and can be -activated by the model during a session when it identifies a relevant task. - -## Step 7: Release your extension - -Once you're happy with your extension, you can share it with others. The two -primary ways of releasing extensions are via a Git repository or through GitHub -Releases. Using a public Git repository is the simplest method. - -For detailed instructions on both methods, please refer to the -[Extension Releasing Guide](./releasing.md). +Gemini CLI automatically discovers skills bundled with your extension. The model +activates them when it identifies a relevant task. -## Conclusion +## Step 8: Release your extension -You've successfully created a Gemini CLI extension! You learned how to: +When your extension is ready, share it with others via a Git repository or +GitHub Releases. Refer to the [Extension Releasing Guide](./releasing.md) for +detailed instructions and learn how to list your extension in the gallery. -- Bootstrap a new extension from a template. -- Add custom tools with an MCP server. -- Create convenient custom commands. -- Provide persistent context to the model. -- Bundle specialized Agent Skills. -- Link your extension for local development. +## Next steps -From here, you can explore more advanced features and build powerful new -capabilities into the Gemini CLI. +- [Extension reference](reference.md): Deeply understand the extension format, + commands, and configuration. +- [Best practices](best-practices.md): Learn strategies for building great + extensions. diff --git a/docs/sidebar.json b/docs/sidebar.json index e59742274ba..617c31756e9 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -52,115 +52,42 @@ { "label": "Features", "items": [ + { "label": "Agent Skills", "slug": "docs/cli/skills" }, { - "label": "/about - About Gemini CLI", - "link": "/docs/cli/commands/#about" - }, - { - "label": "/auth - Authentication", + "label": "Authentication", "slug": "docs/get-started/authentication" }, - { "label": "/bug - Report a bug", "link": "/docs/cli/commands/#bug" }, - { "label": "/chat - Chat history", "link": "/docs/cli/commands/#chat" }, - { "label": "/clear - Clear screen", "link": "/docs/cli/commands/#clear" }, - { - "label": "/compress - Compress context", - "link": "/docs/cli/commands/#compress" - }, - { "label": "/copy - Copy output", "link": "/docs/cli/commands/#copy" }, - { - "label": "/directory - Manage workspace", - "link": "/docs/cli/commands/#directory-or-dir" - }, - { - "label": "/docs - Open documentation", - "link": "/docs/cli/commands/#docs" - }, - { - "label": "/editor - Select editor", - "link": "/docs/cli/commands/#editor" - }, + { "label": "Checkpointing", "slug": "docs/cli/checkpointing" }, { - "label": "/extensions - Manage extensions", + "label": "Extensions", "slug": "docs/extensions/index" }, - { "label": "/help - Show help", "link": "/docs/cli/commands/#help-or" }, - { "label": "/hooks - Hooks", "slug": "docs/hooks" }, - { "label": "/ide - IDE integration", "slug": "docs/ide-integration" }, - { - "label": "/init - Initialize context", - "link": "/docs/cli/commands/#init" - }, - { "label": "/mcp - MCP servers", "slug": "docs/tools/mcp-server" }, - + { "label": "Headless mode", "slug": "docs/cli/headless" }, + { "label": "Help", "link": "/docs/cli/commands/#help-or" }, + { "label": "Hooks", "slug": "docs/hooks" }, + { "label": "IDE integration", "slug": "docs/ide-integration" }, + { "label": "MCP servers", "slug": "docs/tools/mcp-server" }, { - "label": "/memory - Manage memory", + "label": "Memory management", "link": "/docs/cli/commands/#memory" }, - { "label": "/model - Model selection", "slug": "docs/cli/model" }, - { - "label": "/policies - Manage policies", - "link": "/docs/cli/commands/#policies" - }, - { - "label": "/privacy - Privacy notice", - "link": "/docs/cli/commands/#privacy" - }, - { - "label": "/quit - Exit CLI", - "link": "/docs/cli/commands/#quit-or-exit" - }, - { "label": "/restore - Restore files", "slug": "docs/cli/checkpointing" }, - { - "label": "/resume - Resume session", - - "link": "/docs/cli/commands/#resume" - }, - { "label": "/rewind - Rewind", "slug": "docs/cli/rewind" }, - { "label": "/settings - Settings", "slug": "docs/cli/settings" }, - { - "label": "/setup-github - GitHub setup", - "link": "/docs/cli/commands/#setup-github" - }, + { "label": "Model routing", "slug": "docs/cli/model-routing" }, + { "label": "Model selection", "slug": "docs/cli/model" }, + { "label": "Plan mode (experimental)", "slug": "docs/cli/plan-mode" }, + { "label": "Rewind", "slug": "docs/cli/rewind" }, + { "label": "Sandboxing", "slug": "docs/cli/sandbox" }, + { "label": "Settings", "slug": "docs/cli/settings" }, { - "label": "/shells - Manage processes", + "label": "Shell", "link": "/docs/cli/commands/#shells-or-bashes" }, - { "label": "/skills - Agent skills", "slug": "docs/cli/skills" }, { - "label": "/stats - Session statistics", + "label": "Stats", "link": "/docs/cli/commands/#stats" }, - { - "label": "/terminal-setup - Terminal keybindings", - "link": "/docs/cli/commands/#terminal-setup" - }, - { "label": "/theme - Themes", "slug": "docs/cli/themes" }, - { "label": "/tools - List tools", "link": "/docs/cli/commands/#tools" }, - { "label": "/vim - Vim mode", "link": "/docs/cli/commands/#vim" }, - - { - "label": "Activate skill (tool)", - "slug": "docs/tools/activate-skill" - }, - { "label": "Ask user (tool)", "slug": "docs/tools/ask-user" }, - { "label": "Checkpointing", "slug": "docs/cli/checkpointing" }, - { "label": "File system (tool)", "slug": "docs/tools/file-system" }, - { "label": "Headless mode", "slug": "docs/cli/headless" }, - { - "label": "Internal documentation (tool)", - "slug": "docs/tools/internal-docs" - }, - { "label": "Memory (tool)", "slug": "docs/tools/memory" }, - { "label": "Model routing", "slug": "docs/cli/model-routing" }, - { "label": "Plan mode (experimental)", "slug": "docs/cli/plan-mode" }, - { "label": "Sandboxing", "slug": "docs/cli/sandbox" }, - { "label": "Shell (tool)", "slug": "docs/tools/shell" }, { "label": "Telemetry", "slug": "docs/cli/telemetry" }, - { "label": "Todo (tool)", "slug": "docs/tools/todos" }, { "label": "Token caching", "slug": "docs/cli/token-caching" }, - { "label": "Web fetch (tool)", "slug": "docs/tools/web-fetch" }, - { "label": "Web search (tool)", "slug": "docs/tools/web-search" } + { "label": "Tools", "link": "/docs/cli/commands/#tools" } ] }, { @@ -186,14 +113,30 @@ { "label": "Extensions", "items": [ - { "label": "Introduction", "slug": "docs/extensions" }, { - "label": "Writing extensions", + "label": "Overview", + "slug": "docs/extensions" + }, + { + "label": "User guide: Install and manage", + "link": "/docs/extensions/#manage-extensions" + }, + { + "label": "Developer guide: Build extensions", "slug": "docs/extensions/writing-extensions" }, - { "label": "Reference", "slug": "docs/extensions/reference" }, - { "label": "Best practices", "slug": "docs/extensions/best-practices" }, - { "label": "Releasing", "slug": "docs/extensions/releasing" } + { + "label": "Developer guide: Best practices", + "slug": "docs/extensions/best-practices" + }, + { + "label": "Developer guide: Releasing", + "slug": "docs/extensions/releasing" + }, + { + "label": "Developer guide: Reference", + "slug": "docs/extensions/reference" + } ] }, {