Extensions on Gemini CLI: Best practices
This guide covers best practices for developing, securing, and maintaining Gemini CLI extensions.
Development
Section titled “Development”Developing extensions for Gemini CLI is intended to be a lightweight, iterative process.
Structure your extension
Section titled “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
srcand build todist. - Bundle dependencies: If your extension has many dependencies, consider
bundling them (e.g., with
esbuildorwebpack) to reduce install time and potential conflicts.
Iterate with link
Section titled “Iterate with link”Use gemini extensions link to develop locally without constantly reinstalling:
cd my-extensiongemini extensions link .Changes to your code (after rebuilding) will be immediately available in the CLI on restart.
Use GEMINI.md effectively
Section titled “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
Section titled “Security”When building a Gemini CLI extension, follow general security best practices (such as least privilege and input validation) to reduce risk.
Minimal permissions
Section titled “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.
If you must use powerful tools like run_shell_command, consider restricting
them to specific commands in your gemini-extension.json:
{ "name": "my-safe-extension", "excludeTools": ["run_shell_command(rm -rf *)"]}This ensures that even if the model tries to execute a dangerous command, it will be blocked at the CLI level.
Validate inputs
Section titled “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.
// Good: Validating pathsif (!path.resolve(inputPath).startsWith(path.resolve(allowedDir) + path.sep)) { throw new Error('Access denied');}Sensitive settings
Section titled “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.
"settings": [ { "name": "API Key", "envVar": "MY_API_KEY", "sensitive": true }]Releasing
Section titled “Releasing”You can upload your extension directly to GitHub to list it in the gallery. Gemini CLI extensions also offers support for more complicated releases.
Semantic versioning
Section titled “Semantic versioning”Follow Semantic Versioning.
- Major: Breaking changes (renaming tools, changing arguments).
- Minor: New features (new tools, commands).
- Patch: Bug fixes.
Release Channels
Section titled “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:
# Stablegemini extensions install github.com/user/repo
# Devgemini extensions install github.com/user/repo --ref devClean artifacts
Section titled “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.