2025-09-25 20:01:49 -04:00
|
|
|
# Getting Started with Gemini CLI Extensions
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
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.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Before you start, make sure you have the Gemini CLI installed and a basic
|
|
|
|
|
understanding of Node.js and TypeScript.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Step 1: Create a New Extension
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
The easiest way to start is by using one of the built-in templates. We'll use
|
|
|
|
|
the `mcp-server` example as our foundation.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Run the following command to create a new directory called `my-first-extension`
|
|
|
|
|
with the template files:
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
gemini extensions new my-first-extension mcp-server
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This will create a new directory with the following structure:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
my-first-extension/
|
|
|
|
|
├── example.ts
|
|
|
|
|
├── gemini-extension.json
|
|
|
|
|
├── package.json
|
|
|
|
|
└── tsconfig.json
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Step 2: Understand the Extension Files
|
|
|
|
|
|
|
|
|
|
Let's look at the key files in your new extension.
|
|
|
|
|
|
|
|
|
|
### `gemini-extension.json`
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
This is the manifest file for your extension. It tells Gemini CLI how to load
|
|
|
|
|
and use your extension.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"name": "my-first-extension",
|
|
|
|
|
"version": "1.0.0",
|
|
|
|
|
"mcpServers": {
|
|
|
|
|
"nodeServer": {
|
|
|
|
|
"command": "node",
|
|
|
|
|
"args": ["${extensionPath}${/}dist${/}example.js"],
|
|
|
|
|
"cwd": "${extensionPath}"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- `name`: The unique name for your extension.
|
|
|
|
|
- `version`: The version of your extension.
|
2025-10-09 08:17:37 -04:00
|
|
|
- `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.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
### `example.ts`
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
This file contains the source code for your MCP server. It's a simple Node.js
|
|
|
|
|
server that uses the `@modelcontextprotocol/sdk`.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
/**
|
|
|
|
|
* @license
|
|
|
|
|
* Copyright 2025 Google LLC
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
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',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Registers a new tool named 'fetch_posts'
|
|
|
|
|
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),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// ... (prompt registration omitted for brevity)
|
|
|
|
|
|
|
|
|
|
const transport = new StdioServerTransport();
|
|
|
|
|
await server.connect(transport);
|
|
|
|
|
```
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
This server defines a single tool called `fetch_posts` that fetches data from a
|
|
|
|
|
public API.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
### `package.json` and `tsconfig.json`
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
These are standard configuration files for a TypeScript project. The
|
|
|
|
|
`package.json` file defines dependencies and a `build` script, and
|
|
|
|
|
`tsconfig.json` configures the TypeScript compiler.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Step 3: Build and Link Your Extension
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Before you can use the extension, you need to compile the TypeScript code and
|
|
|
|
|
link the extension to your Gemini CLI installation for local development.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
1. **Install dependencies:**
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd my-first-extension
|
|
|
|
|
npm install
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2. **Build the server:**
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
npm run build
|
|
|
|
|
```
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
This will compile `example.ts` into `dist/example.js`, which is the file
|
|
|
|
|
referenced in your `gemini-extension.json`.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
3. **Link the extension:**
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
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.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
gemini extensions link .
|
|
|
|
|
```
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Now, restart your Gemini CLI session. The new `fetch_posts` tool will be
|
|
|
|
|
available. You can test it by asking: "fetch posts".
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Step 4: Add a Custom Command
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Custom commands provide a way to create shortcuts for complex prompts. Let's add
|
|
|
|
|
a command that searches for a pattern in your code.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
1. Create a `commands` directory and a subdirectory for your command group:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
mkdir -p commands/fs
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2. Create a file named `commands/fs/grep-code.toml`:
|
|
|
|
|
|
|
|
|
|
```toml
|
|
|
|
|
prompt = """
|
|
|
|
|
Please summarize the findings for the pattern `{{args}}`.
|
|
|
|
|
|
|
|
|
|
Search Results:
|
|
|
|
|
!{grep -r {{args}} .}
|
|
|
|
|
"""
|
|
|
|
|
```
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
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.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
After saving the file, restart the Gemini CLI. You can now run
|
|
|
|
|
`/fs:grep-code "some pattern"` to use your new command.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Step 5: Add a Custom `GEMINI.md`
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
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.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
1. Create a file named `GEMINI.md` in the root of your extension directory:
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
# My First Extension Instructions
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
You are an expert developer assistant. When the user asks you to fetch
|
|
|
|
|
posts, use the `fetch_posts` tool. Be concise in your responses.
|
2025-09-25 20:01:49 -04:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2. Update your `gemini-extension.json` to tell the CLI to load this file:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"name": "my-first-extension",
|
|
|
|
|
"version": "1.0.0",
|
|
|
|
|
"contextFileName": "GEMINI.md",
|
|
|
|
|
"mcpServers": {
|
|
|
|
|
"nodeServer": {
|
|
|
|
|
"command": "node",
|
|
|
|
|
"args": ["${extensionPath}${/}dist${/}example.js"],
|
|
|
|
|
"cwd": "${extensionPath}"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Restart the CLI again. The model will now have the context from your `GEMINI.md`
|
|
|
|
|
file in every session where the extension is active.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Step 6: Releasing Your Extension
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
Once you are 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.
|
2025-09-25 20:01:49 -04:00
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
For detailed instructions on both methods, please refer to the
|
|
|
|
|
[Extension Releasing Guide](./extension-releasing.md).
|
2025-09-25 20:01:49 -04:00
|
|
|
|
|
|
|
|
## Conclusion
|
|
|
|
|
|
|
|
|
|
You've successfully created a Gemini CLI extension! You learned how to:
|
|
|
|
|
|
|
|
|
|
- Bootstrap a new extension from a template.
|
|
|
|
|
- Add custom tools with an MCP server.
|
|
|
|
|
- Create convenient custom commands.
|
|
|
|
|
- Provide persistent context to the model.
|
|
|
|
|
- Link your extension for local development.
|
|
|
|
|
|
2025-10-09 08:17:37 -04:00
|
|
|
From here, you can explore more advanced features and build powerful new
|
|
|
|
|
capabilities into the Gemini CLI.
|