Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions docs/extensions/best-practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Extensions on Gemini CLI: Best practices

This guide covers best practices for developing, securing, and maintaining
Gemini CLI extensions.

## Development

### Structure your extension

While simple extensions can just be a few files, we recommend a robust structure
for complex extensions:

```
my-extension/
├── package.json
├── tsconfig.json
├── gemini-extension.json
├── src/
│ ├── index.ts
│ └── tools/
└── 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.

### Iterate with `link`

Use `gemini extensions link` to develop locally without constantly reinstalling:

```bash
cd my-extension
gemini extensions link .
```

Changes to your code (after rebuilding) will be immediately available in the CLI
on restart.

### Use `GEMINI.md` effectively

Your `GEMINI.md` file provides context to the model. Keep it focused:

- **Do:** Explain high-level goals and how to use the provided tools.
- **Don't:** Dump your entire documentation.
- **Do:** Use clear, concise language.

## Security

### Minimal permissions

When defining tools in your MCP server, only request the permissions necessary.

### 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.

```typescript
// Good: Validating paths
if (!path.resolve(inputPath).startsWith(path.resolve(allowedDir) + path.sep)) {
throw new Error('Access denied');
}
```

### 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.

```json
"settings": [
{
"name": "API Key",
"envVar": "MY_API_KEY",
"sensitive": true
}
]
```

## Releasing

### Semantic Versioning

Follow [Semantic Versioning](https://semver.org/).

- **Major**: Breaking changes (renaming tools, changing arguments).
- **Minor**: New features (new tools, commands).
- **Patch**: Bug fixes.

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

```bash
# Stable
gemini extensions install github.com/user/repo

# Dev
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.
Loading
Loading