Skip to main content
This guide walks you through creating your first Gemini CLI extension, from setting up a template to adding custom functionality and linking it for local development.

Prerequisites

Gemini CLI

Ensure you have the Gemini CLI installed

Node.js

Basic understanding of Node.js and npm

Step 1: Create a New Extension

The easiest way to start is by using a built-in template. We’ll use the mcp-server example as our foundation.
gemini extensions new my-first-extension mcp-server
This creates a directory with the following structure:
my-first-extension/
├── example.js
├── gemini-extension.json
└── package.json

Step 2: Understand the Extension Files

gemini-extension.json

The manifest file tells Gemini CLI how to load and use your extension.
{
  "name": "mcp-server-example",
  "version": "1.0.0",
  "mcpServers": {
    "nodeServer": {
      "command": "node",
      "args": ["${extensionPath}${/}example.js"],
      "cwd": "${extensionPath}"
    }
  }
}
name
string
required
Unique name for your extension
version
string
required
Version of your extension (semver format)
mcpServers
object
MCP server configurations. The ${extensionPath} variable is replaced with the absolute path to your extension directory.

example.js

This file contains the MCP server implementation using the @modelcontextprotocol/sdk.
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

const server = new McpServer({
  name: 'prompt-server',
  version: '1.0.0',
});

// Register a new tool
server.registerTool(
  'fetch_posts',
  {
    description: 'Fetches a list of posts from a public API.',
    inputSchema: z.object({}).shape,
  },
  async () => {
    const apiResponse = await fetch(
      'https://jsonplaceholder.typicode.com/posts',
    );
    const posts = await apiResponse.json();
    const response = { posts: posts.slice(0, 5) };
    return {
      content: [
        {
          type: 'text',
          text: JSON.stringify(response),
        },
      ],
    };
  },
);

const transport = new StdioServerTransport();
await server.connect(transport);

package.json

Standard Node.js configuration file that defines dependencies and scripts.
The template includes @modelcontextprotocol/sdk and zod as dependencies for building MCP servers.

Step 3: Add Extension Settings

Some extensions need configuration like API keys or user preferences. Let’s add a setting for an API key.
1

Open manifest

Open gemini-extension.json
2

Add settings

Add a settings array to the configuration:
{
  "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": {
    // ...
  }
}
name
string
required
Display name shown to the user
description
string
required
Description of what this setting is for
envVar
string
required
Environment variable name that will be set
sensitive
boolean
default:"false"
When true, the value is stored securely in the system keychain
When a user installs this extension, Gemini CLI will:
  1. Prompt them to enter the “API Key”
  2. Store it securely in the system keychain (because sensitive is true)
  3. Inject it into the MCP server’s process as the MY_SERVICE_API_KEY environment variable
Link your extension to your Gemini CLI installation for local development.
1

Install dependencies

cd my-first-extension
npm install
2

Link the extension

The link command creates a symbolic link from the Gemini CLI extensions directory to your development directory.
gemini extensions link .
Changes you make are reflected immediately.
3

Test the extension

Restart your Gemini CLI session and test the new tool:
fetch posts
You don’t need to restart Gemini CLI after making code changes. The MCP server will be reloaded automatically on the next tool invocation.

Step 5: Add a Custom Command

Custom commands create shortcuts for complex prompts.
1

Create directory structure

Create a commands directory and subdirectory:macOS/Linux:
mkdir -p commands/fs
Windows (PowerShell):
New-Item -ItemType Directory -Force -Path "commands\fs"
2

Create command file

Create commands/fs/grep-code.toml:
prompt = """
Please summarize the findings for the pattern `{{args}}`.

Search Results:
!{grep -r {{args}} .}
"""
This command:
  • Takes an argument ({{args}})
  • Runs the grep shell command
  • Pipes results into a prompt for summarization
3

Use the command

Restart Gemini CLI and run:
/fs:grep-code "some pattern"

Custom Commands Reference

Learn more about custom command syntax and features

Step 6: Add Custom Context

Provide persistent context to the model by adding a GEMINI.md file.
1

Create context file

Create GEMINI.md in the root of your extension directory:
# My First Extension Instructions

You are an expert developer assistant. When the user asks you to fetch
posts, use the `fetch_posts` tool. Be concise in your responses.
2

Update manifest

Update gemini-extension.json to load this file:
{
  "name": "my-first-extension",
  "version": "1.0.0",
  "contextFileName": "GEMINI.md",
  "mcpServers": {
    "nodeServer": {
      "command": "node",
      "args": ["${extensionPath}${/}example.js"],
      "cwd": "${extensionPath}"
    }
  }
}
3

Restart CLI

Restart Gemini CLI. The model now has the context from your GEMINI.md file in every session where the extension is active.
Context files are loaded at the start of every session, so keep them concise to avoid consuming too many tokens.

Step 7: Add an Agent Skill (Optional)

Agent Skills bundle specialized expertise and workflows. Skills are activated only when needed, saving context tokens.
1

Create skill directory

macOS/Linux:
mkdir -p skills/security-audit
Windows (PowerShell):
New-Item -ItemType Directory -Force -Path "skills\security-audit"
2

Create skill file

Create skills/security-audit/SKILL.md:
---
name: security-audit
description: Expertise in auditing code for security vulnerabilities. Use when the user asks to "check for security issues" or "audit" their changes.
---

# Security Auditor

You are an expert security researcher. When auditing code:

1. Look for common vulnerabilities (OWASP Top 10).
2. Check for hardcoded secrets or API keys.
3. Suggest remediation steps for any findings.
3

Automatic discovery

Gemini CLI automatically discovers skills bundled with your extension. The model activates them when it identifies a relevant task.

Agent Skills Guide

Learn more about the agent skills system

Extension Structure Summary

Here’s what your complete extension looks like:
my-first-extension/
├── commands/
│   └── fs/
│       └── grep-code.toml
├── skills/
│   └── security-audit/
│       └── SKILL.md
├── example.js
├── gemini-extension.json
├── GEMINI.md
└── package.json

Step 8: Release Your Extension

When your extension is ready, share it with others via a Git repository or GitHub Releases.

Extension Releasing Guide

Learn how to publish and list your extension in the gallery

Testing Your Extension

Ask the model to use your tools:
Can you fetch posts for me?
Verify the tool executes correctly and returns expected results.
Run your custom commands:
/fs:grep-code "function"
Verify the command executes and the prompt is formatted correctly.
Verify the model has your context:
What are your instructions?
The model should reference content from your GEMINI.md file.
Trigger your skill:
Please audit this code for security issues
Verify the skill is activated and provides specialized responses.

Best Practices

Keep Context Concise

Context files consume tokens in every session. Be brief and focused.

Use Skills for Complex Tasks

Move complex instructions to skills to save context when not needed.

Validate Inputs

Always validate tool inputs to prevent errors and security issues.

Handle Errors Gracefully

Return clear error messages when tools fail.

Document Your Extension

Include a README explaining what your extension does and how to use it.

Version Carefully

Follow semantic versioning for your extension releases.

Next Steps

Extension Reference

Detailed API reference and configuration options

Best Practices

Learn strategies for building great extensions

Publishing Guide

Share your extension with the community

MCP Server Guide

Deep dive into MCP server integration

Build docs developers (and LLMs) love