2026-02-17 13:57:27 -08:00
|
|
|
# Gemini CLI extension best practices
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
This guide covers best practices for developing, securing, and maintaining
|
|
|
|
|
Gemini CLI extensions.
|
|
|
|
|
|
|
|
|
|
## Development
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Developing extensions for Gemini CLI is a lightweight, iterative process. Use
|
|
|
|
|
these strategies to build robust and efficient extensions.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
### Structure your extension
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
While simple extensions may contain only a few files, we recommend a organized
|
|
|
|
|
structure for complex projects.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
```text
|
2026-01-26 15:14:38 -05:00
|
|
|
my-extension/
|
|
|
|
|
├── package.json
|
|
|
|
|
├── tsconfig.json
|
|
|
|
|
├── gemini-extension.json
|
|
|
|
|
├── src/
|
|
|
|
|
│ ├── index.ts
|
|
|
|
|
│ └── tools/
|
|
|
|
|
└── dist/
|
|
|
|
|
```
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
- **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.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
### Iterate with `link`
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Use the `gemini extensions link` command to develop locally without reinstalling
|
|
|
|
|
your extension after every change.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd my-extension
|
|
|
|
|
gemini extensions link .
|
|
|
|
|
```
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Changes to your code are immediately available in the CLI after you rebuild the
|
|
|
|
|
project and restart the session.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
### Use `GEMINI.md` effectively
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Your `GEMINI.md` file provides essential context to the model.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
- **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.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
## Security
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Follow the principle of least privilege and rigorous input validation when
|
|
|
|
|
building extensions.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
### Minimal permissions
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
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.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
If your extension uses powerful tools like `run_shell_command`, restrict them in
|
|
|
|
|
your `gemini-extension.json` file:
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"name": "my-safe-extension",
|
|
|
|
|
"excludeTools": ["run_shell_command(rm -rf *)"]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
This ensures the CLI blocks dangerous commands even if the model attempts to
|
|
|
|
|
execute them.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
### Validate inputs
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Your MCP server runs on the user's machine. Always validate tool inputs to
|
|
|
|
|
prevent arbitrary code execution or unauthorized filesystem access.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
```typescript
|
2026-02-17 13:57:27 -08:00
|
|
|
// Example: Validating paths
|
2026-01-26 15:14:38 -05:00
|
|
|
if (!path.resolve(inputPath).startsWith(path.resolve(allowedDir) + path.sep)) {
|
|
|
|
|
throw new Error('Access denied');
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
### Secure sensitive settings
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
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.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
"settings": [
|
|
|
|
|
{
|
|
|
|
|
"name": "API Key",
|
|
|
|
|
"envVar": "MY_API_KEY",
|
|
|
|
|
"sensitive": true
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
```
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
## Release
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Follow standard versioning and release practices to ensure a smooth experience
|
|
|
|
|
for your users.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
### Semantic versioning
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Follow [Semantic Versioning (SemVer)](https://semver.org/) to communicate
|
|
|
|
|
changes clearly.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
- **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.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
### Release channels
|
2026-01-26 15:14:38 -05:00
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
Use Git branches to manage release channels. This lets users choose between
|
|
|
|
|
stability and the latest features.
|
2026-01-26 15:14:38 -05:00
|
|
|
|
|
|
|
|
```bash
|
2026-02-17 13:57:27 -08:00
|
|
|
# Install the stable version (default branch)
|
2026-01-26 15:14:38 -05:00
|
|
|
gemini extensions install github.com/user/repo
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
# Install the development version
|
2026-01-26 15:14:38 -05:00
|
|
|
gemini extensions install github.com/user/repo --ref dev
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Clean artifacts
|
|
|
|
|
|
2026-02-17 13:57:27 -08:00
|
|
|
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.
|