@google/gemini-cli-core 0.21.0-nightly.20251219.70696e364 → 0.21.0-nightly.20251221.8feeffb29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/docs/CONTRIBUTING.md +546 -0
  2. package/dist/docs/architecture.md +80 -0
  3. package/dist/docs/assets/connected_devtools.png +0 -0
  4. package/dist/docs/assets/gemini-screenshot.png +0 -0
  5. package/dist/docs/assets/release_patch.png +0 -0
  6. package/dist/docs/assets/theme-ansi-light.png +0 -0
  7. package/dist/docs/assets/theme-ansi.png +0 -0
  8. package/dist/docs/assets/theme-atom-one.png +0 -0
  9. package/dist/docs/assets/theme-ayu-light.png +0 -0
  10. package/dist/docs/assets/theme-ayu.png +0 -0
  11. package/dist/docs/assets/theme-custom.png +0 -0
  12. package/dist/docs/assets/theme-default-light.png +0 -0
  13. package/dist/docs/assets/theme-default.png +0 -0
  14. package/dist/docs/assets/theme-dracula.png +0 -0
  15. package/dist/docs/assets/theme-github-light.png +0 -0
  16. package/dist/docs/assets/theme-github.png +0 -0
  17. package/dist/docs/assets/theme-google-light.png +0 -0
  18. package/dist/docs/assets/theme-xcode-light.png +0 -0
  19. package/dist/docs/changelogs/index.md +592 -0
  20. package/dist/docs/changelogs/latest.md +225 -0
  21. package/dist/docs/changelogs/preview.md +129 -0
  22. package/dist/docs/changelogs/releases.md +896 -0
  23. package/dist/docs/cli/authentication.md +3 -0
  24. package/dist/docs/cli/checkpointing.md +94 -0
  25. package/dist/docs/cli/commands.md +354 -0
  26. package/dist/docs/cli/configuration.md +780 -0
  27. package/dist/docs/cli/custom-commands.md +315 -0
  28. package/dist/docs/cli/enterprise.md +565 -0
  29. package/dist/docs/cli/gemini-ignore.md +71 -0
  30. package/dist/docs/cli/gemini-md.md +108 -0
  31. package/dist/docs/cli/generation-settings.md +210 -0
  32. package/dist/docs/cli/headless.md +388 -0
  33. package/dist/docs/cli/index.md +63 -0
  34. package/dist/docs/cli/keyboard-shortcuts.md +143 -0
  35. package/dist/docs/cli/model-routing.md +37 -0
  36. package/dist/docs/cli/model.md +62 -0
  37. package/dist/docs/cli/sandbox.md +171 -0
  38. package/dist/docs/cli/session-management.md +158 -0
  39. package/dist/docs/cli/settings.md +112 -0
  40. package/dist/docs/cli/system-prompt.md +93 -0
  41. package/dist/docs/cli/telemetry.md +791 -0
  42. package/dist/docs/cli/themes.md +237 -0
  43. package/dist/docs/cli/token-caching.md +20 -0
  44. package/dist/docs/cli/trusted-folders.md +95 -0
  45. package/dist/docs/cli/tutorials.md +83 -0
  46. package/dist/docs/cli/uninstall.md +47 -0
  47. package/dist/docs/core/index.md +101 -0
  48. package/dist/docs/core/memport.md +244 -0
  49. package/dist/docs/core/policy-engine.md +267 -0
  50. package/dist/docs/core/tools-api.md +131 -0
  51. package/dist/docs/examples/proxy-script.md +83 -0
  52. package/dist/docs/extensions/extension-releasing.md +183 -0
  53. package/dist/docs/extensions/getting-started-extensions.md +245 -0
  54. package/dist/docs/extensions/index.md +293 -0
  55. package/dist/docs/faq.md +154 -0
  56. package/dist/docs/get-started/authentication.md +321 -0
  57. package/dist/docs/get-started/configuration-v1.md +888 -0
  58. package/dist/docs/get-started/configuration.md +1444 -0
  59. package/dist/docs/get-started/deployment.md +143 -0
  60. package/dist/docs/get-started/examples.md +219 -0
  61. package/dist/docs/get-started/gemini-3.md +116 -0
  62. package/dist/docs/get-started/index.md +71 -0
  63. package/dist/docs/get-started/installation.md +141 -0
  64. package/dist/docs/hooks/best-practices.md +806 -0
  65. package/dist/docs/hooks/index.md +665 -0
  66. package/dist/docs/hooks/reference.md +168 -0
  67. package/dist/docs/hooks/writing-hooks.md +1026 -0
  68. package/dist/docs/ide-integration/ide-companion-spec.md +267 -0
  69. package/dist/docs/ide-integration/index.md +202 -0
  70. package/dist/docs/index.md +147 -0
  71. package/dist/docs/integration-tests.md +211 -0
  72. package/dist/docs/issue-and-pr-automation.md +134 -0
  73. package/dist/docs/local-development.md +128 -0
  74. package/dist/docs/mermaid/context.mmd +103 -0
  75. package/dist/docs/mermaid/render-path.mmd +64 -0
  76. package/dist/docs/npm.md +62 -0
  77. package/dist/docs/quota-and-pricing.md +158 -0
  78. package/dist/docs/release-confidence.md +164 -0
  79. package/dist/docs/releases.md +540 -0
  80. package/dist/docs/sidebar.json +297 -0
  81. package/dist/docs/tools/file-system.md +217 -0
  82. package/dist/docs/tools/index.md +95 -0
  83. package/dist/docs/tools/mcp-server.md +1044 -0
  84. package/dist/docs/tools/memory.md +54 -0
  85. package/dist/docs/tools/shell.md +260 -0
  86. package/dist/docs/tools/todos.md +57 -0
  87. package/dist/docs/tools/web-fetch.md +59 -0
  88. package/dist/docs/tools/web-search.md +42 -0
  89. package/dist/docs/tos-privacy.md +96 -0
  90. package/dist/docs/troubleshooting.md +158 -0
  91. package/dist/google-gemini-cli-core-0.21.0-nightly.20251219.70696e364.tgz +0 -0
  92. package/dist/src/agents/delegate-to-agent-tool.test.js +1 -0
  93. package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -1
  94. package/dist/src/agents/introspection-agent.d.ts +23 -0
  95. package/dist/src/agents/introspection-agent.js +72 -0
  96. package/dist/src/agents/introspection-agent.js.map +1 -0
  97. package/dist/src/agents/introspection-agent.test.d.ts +6 -0
  98. package/dist/src/agents/introspection-agent.test.js +47 -0
  99. package/dist/src/agents/introspection-agent.test.js.map +1 -0
  100. package/dist/src/agents/local-executor.js +14 -12
  101. package/dist/src/agents/local-executor.js.map +1 -1
  102. package/dist/src/agents/local-executor.test.js +3 -0
  103. package/dist/src/agents/local-executor.test.js.map +1 -1
  104. package/dist/src/agents/registry.js +6 -0
  105. package/dist/src/agents/registry.js.map +1 -1
  106. package/dist/src/agents/registry.test.js +16 -0
  107. package/dist/src/agents/registry.test.js.map +1 -1
  108. package/dist/src/config/config.d.ts +6 -0
  109. package/dist/src/config/config.js +22 -0
  110. package/dist/src/config/config.js.map +1 -1
  111. package/dist/src/config/config.test.js +59 -1
  112. package/dist/src/config/config.test.js.map +1 -1
  113. package/dist/src/core/client.js +8 -4
  114. package/dist/src/core/client.js.map +1 -1
  115. package/dist/src/core/client.test.js +20 -0
  116. package/dist/src/core/client.test.js.map +1 -1
  117. package/dist/src/core/clientHookTriggers.js +2 -2
  118. package/dist/src/core/clientHookTriggers.js.map +1 -1
  119. package/dist/src/core/coreToolHookTriggers.js +3 -3
  120. package/dist/src/core/coreToolHookTriggers.js.map +1 -1
  121. package/dist/src/core/geminiChatHookTriggers.js +3 -3
  122. package/dist/src/core/geminiChatHookTriggers.js.map +1 -1
  123. package/dist/src/core/sessionHookTriggers.js +3 -3
  124. package/dist/src/core/sessionHookTriggers.js.map +1 -1
  125. package/dist/src/generated/git-commit.d.ts +2 -2
  126. package/dist/src/generated/git-commit.js +2 -2
  127. package/dist/src/hooks/hookEventHandler.js +10 -4
  128. package/dist/src/hooks/hookEventHandler.js.map +1 -1
  129. package/dist/src/hooks/hookEventHandler.test.js +40 -0
  130. package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
  131. package/dist/src/hooks/hookRunner.js +12 -8
  132. package/dist/src/hooks/hookRunner.js.map +1 -1
  133. package/dist/src/hooks/hookRunner.test.js +58 -33
  134. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  135. package/dist/src/mcp/oauth-provider.js +6 -2
  136. package/dist/src/mcp/oauth-provider.js.map +1 -1
  137. package/dist/src/mcp/oauth-provider.test.js +4 -1
  138. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  139. package/dist/src/mcp/oauth-utils.d.ts +8 -1
  140. package/dist/src/mcp/oauth-utils.js +30 -1
  141. package/dist/src/mcp/oauth-utils.js.map +1 -1
  142. package/dist/src/mcp/oauth-utils.test.js +42 -0
  143. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  144. package/dist/src/services/contextManager.d.ts +5 -11
  145. package/dist/src/services/contextManager.js +20 -17
  146. package/dist/src/services/contextManager.js.map +1 -1
  147. package/dist/src/services/contextManager.test.js +40 -41
  148. package/dist/src/services/contextManager.test.js.map +1 -1
  149. package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
  150. package/dist/src/tools/confirmation-policy.test.js +152 -0
  151. package/dist/src/tools/confirmation-policy.test.js.map +1 -0
  152. package/dist/src/tools/edit.js +5 -1
  153. package/dist/src/tools/edit.js.map +1 -1
  154. package/dist/src/tools/get-internal-docs.d.ts +27 -0
  155. package/dist/src/tools/get-internal-docs.js +129 -0
  156. package/dist/src/tools/get-internal-docs.js.map +1 -0
  157. package/dist/src/tools/get-internal-docs.test.d.ts +6 -0
  158. package/dist/src/tools/get-internal-docs.test.js +56 -0
  159. package/dist/src/tools/get-internal-docs.test.js.map +1 -0
  160. package/dist/src/tools/smart-edit.js +5 -1
  161. package/dist/src/tools/smart-edit.js.map +1 -1
  162. package/dist/src/tools/tool-names.d.ts +1 -0
  163. package/dist/src/tools/tool-names.js +1 -0
  164. package/dist/src/tools/tool-names.js.map +1 -1
  165. package/dist/src/tools/web-fetch.js +5 -1
  166. package/dist/src/tools/web-fetch.js.map +1 -1
  167. package/dist/src/tools/write-file.js +5 -1
  168. package/dist/src/tools/write-file.js.map +1 -1
  169. package/dist/src/utils/environmentContext.js +3 -0
  170. package/dist/src/utils/environmentContext.js.map +1 -1
  171. package/dist/src/utils/environmentContext.test.js +2 -0
  172. package/dist/src/utils/environmentContext.test.js.map +1 -1
  173. package/dist/src/utils/events.d.ts +3 -2
  174. package/dist/src/utils/events.js.map +1 -1
  175. package/dist/src/utils/memoryDiscovery.js +1 -1
  176. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  177. package/dist/src/utils/memoryDiscovery.test.js +3 -1
  178. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  179. package/dist/src/utils/shell-utils.js +25 -4
  180. package/dist/src/utils/shell-utils.js.map +1 -1
  181. package/dist/tsconfig.tsbuildinfo +1 -1
  182. package/package.json +1 -1
  183. package/dist/google-gemini-cli-core-0.21.0-nightly.20251218.739c02bd6.tgz +0 -0
@@ -0,0 +1,83 @@
1
+ # Example proxy script
2
+
3
+ The following is an example of a proxy script that can be used with the
4
+ `GEMINI_SANDBOX_PROXY_COMMAND` environment variable. This script only allows
5
+ `HTTPS` connections to `example.com:443` and declines all other requests.
6
+
7
+ ```javascript
8
+ #!/usr/bin/env node
9
+
10
+ /**
11
+ * @license
12
+ * Copyright 2025 Google LLC
13
+ * SPDX-License-Identifier: Apache-2.0
14
+ */
15
+
16
+ // Example proxy server that listens on :::8877 and only allows HTTPS connections to example.com.
17
+ // Set `GEMINI_SANDBOX_PROXY_COMMAND=scripts/example-proxy.js` to run proxy alongside sandbox
18
+ // Test via `curl https://example.com` inside sandbox (in shell mode or via shell tool)
19
+
20
+ import http from 'node:http';
21
+ import net from 'node:net';
22
+ import { URL } from 'node:url';
23
+ import console from 'node:console';
24
+
25
+ const PROXY_PORT = 8877;
26
+ const ALLOWED_DOMAINS = ['example.com', 'googleapis.com'];
27
+ const ALLOWED_PORT = '443';
28
+
29
+ const server = http.createServer((req, res) => {
30
+ // Deny all requests other than CONNECT for HTTPS
31
+ console.log(
32
+ `[PROXY] Denying non-CONNECT request for: ${req.method} ${req.url}`,
33
+ );
34
+ res.writeHead(405, { 'Content-Type': 'text/plain' });
35
+ res.end('Method Not Allowed');
36
+ });
37
+
38
+ server.on('connect', (req, clientSocket, head) => {
39
+ // req.url will be in the format "hostname:port" for a CONNECT request.
40
+ const { port, hostname } = new URL(`http://${req.url}`);
41
+
42
+ console.log(`[PROXY] Intercepted CONNECT request for: ${hostname}:${port}`);
43
+
44
+ if (
45
+ ALLOWED_DOMAINS.some(
46
+ (domain) => hostname == domain || hostname.endsWith(`.${domain}`),
47
+ ) &&
48
+ port === ALLOWED_PORT
49
+ ) {
50
+ console.log(`[PROXY] Allowing connection to ${hostname}:${port}`);
51
+
52
+ // Establish a TCP connection to the original destination.
53
+ const serverSocket = net.connect(port, hostname, () => {
54
+ clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
55
+ // Create a tunnel by piping data between the client and the destination server.
56
+ serverSocket.write(head);
57
+ serverSocket.pipe(clientSocket);
58
+ clientSocket.pipe(serverSocket);
59
+ });
60
+
61
+ serverSocket.on('error', (err) => {
62
+ console.error(`[PROXY] Error connecting to destination: ${err.message}`);
63
+ clientSocket.end(`HTTP/1.1 502 Bad Gateway\r\n\r\n`);
64
+ });
65
+ } else {
66
+ console.log(`[PROXY] Denying connection to ${hostname}:${port}`);
67
+ clientSocket.end('HTTP/1.1 403 Forbidden\r\n\r\n');
68
+ }
69
+
70
+ clientSocket.on('error', (err) => {
71
+ // This can happen if the client hangs up.
72
+ console.error(`[PROXY] Client socket error: ${err.message}`);
73
+ });
74
+ });
75
+
76
+ server.listen(PROXY_PORT, () => {
77
+ const address = server.address();
78
+ console.log(`[PROXY] Proxy listening on ${address.address}:${address.port}`);
79
+ console.log(
80
+ `[PROXY] Allowing HTTPS connections to domains: ${ALLOWED_DOMAINS.join(', ')}`,
81
+ );
82
+ });
83
+ ```
@@ -0,0 +1,183 @@
1
+ # Extension releasing
2
+
3
+ There are two primary ways of releasing extensions to users:
4
+
5
+ - [Git repository](#releasing-through-a-git-repository)
6
+ - [Github Releases](#releasing-through-github-releases)
7
+
8
+ Git repository releases tend to be the simplest and most flexible approach,
9
+ while GitHub releases can be more efficient on initial install as they are
10
+ shipped as single archives instead of requiring a git clone which downloads each
11
+ file individually. Github releases may also contain platform specific archives
12
+ if you need to ship platform specific binary files.
13
+
14
+ ## Releasing through a git repository
15
+
16
+ This is the most flexible and simple option. All you need to do is create a
17
+ publicly accessible git repo (such as a public github repository) and then users
18
+ can install your extension using `gemini extensions install <your-repo-uri>`.
19
+ They can optionally depend on a specific ref (branch/tag/commit) using the
20
+ `--ref=<some-ref>` argument, this defaults to the default branch.
21
+
22
+ Whenever commits are pushed to the ref that a user depends on, they will be
23
+ prompted to update the extension. Note that this also allows for easy rollbacks,
24
+ the HEAD commit is always treated as the latest version regardless of the actual
25
+ version in the `gemini-extension.json` file.
26
+
27
+ ### Managing release channels using a git repository
28
+
29
+ Users can depend on any ref from your git repo, such as a branch or tag, which
30
+ allows you to manage multiple release channels.
31
+
32
+ For instance, you can maintain a `stable` branch, which users can install this
33
+ way `gemini extensions install <your-repo-uri> --ref=stable`. Or, you could make
34
+ this the default by treating your default branch as your stable release branch,
35
+ and doing development in a different branch (for instance called `dev`). You can
36
+ maintain as many branches or tags as you like, providing maximum flexibility for
37
+ you and your users.
38
+
39
+ Note that these `ref` arguments can be tags, branches, or even specific commits,
40
+ which allows users to depend on a specific version of your extension. It is up
41
+ to you how you want to manage your tags and branches.
42
+
43
+ ### Example releasing flow using a git repo
44
+
45
+ While there are many options for how you want to manage releases using a git
46
+ flow, we recommend treating your default branch as your "stable" release branch.
47
+ This means that the default behavior for
48
+ `gemini extensions install <your-repo-uri>` is to be on the stable release
49
+ branch.
50
+
51
+ Lets say you want to maintain three standard release channels, `stable`,
52
+ `preview`, and `dev`. You would do all your standard development in the `dev`
53
+ branch. When you are ready to do a preview release, you merge that branch into
54
+ your `preview` branch. When you are ready to promote your preview branch to
55
+ stable, you merge `preview` into your stable branch (which might be your default
56
+ branch or a different branch).
57
+
58
+ You can also cherry pick changes from one branch into another using
59
+ `git cherry-pick`, but do note that this will result in your branches having a
60
+ slightly divergent history from each other, unless you force push changes to
61
+ your branches on each release to restore the history to a clean slate (which may
62
+ not be possible for the default branch depending on your repository settings).
63
+ If you plan on doing cherry picks, you may want to avoid having your default
64
+ branch be the stable branch to avoid force-pushing to the default branch which
65
+ should generally be avoided.
66
+
67
+ ## Releasing through GitHub releases
68
+
69
+ Gemini CLI extensions can be distributed through
70
+ [GitHub Releases](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases).
71
+ This provides a faster and more reliable initial installation experience for
72
+ users, as it avoids the need to clone the repository.
73
+
74
+ Each release includes at least one archive file, which contains the full
75
+ contents of the repo at the tag that it was linked to. Releases may also include
76
+ [pre-built archives](#custom-pre-built-archives) if your extension requires some
77
+ build step or has platform specific binaries attached to it.
78
+
79
+ When checking for updates, gemini will just look for the "latest" release on
80
+ github (you must mark it as such when creating the release), unless the user
81
+ installed a specific release by passing `--ref=<some-release-tag>`.
82
+
83
+ You may also install extensions with the `--pre-release` flag in order to get
84
+ the latest release regardless of whether it has been marked as "latest". This
85
+ allows you to test that your release works before actually pushing it to all
86
+ users.
87
+
88
+ ### Custom pre-built archives
89
+
90
+ Custom archives must be attached directly to the github release as assets and
91
+ must be fully self-contained. This means they should include the entire
92
+ extension, see [archive structure](#archive-structure).
93
+
94
+ If your extension is platform-independent, you can provide a single generic
95
+ asset. In this case, there should be only one asset attached to the release.
96
+
97
+ Custom archives may also be used if you want to develop your extension within a
98
+ larger repository, you can build an archive which has a different layout from
99
+ the repo itself (for instance it might just be an archive of a subdirectory
100
+ containing the extension).
101
+
102
+ #### Platform specific archives
103
+
104
+ To ensure Gemini CLI can automatically find the correct release asset for each
105
+ platform, you must follow this naming convention. The CLI will search for assets
106
+ in the following order:
107
+
108
+ 1. **Platform and architecture-Specific:**
109
+ `{platform}.{arch}.{name}.{extension}`
110
+ 2. **Platform-specific:** `{platform}.{name}.{extension}`
111
+ 3. **Generic:** If only one asset is provided, it will be used as a generic
112
+ fallback.
113
+
114
+ - `{name}`: The name of your extension.
115
+ - `{platform}`: The operating system. Supported values are:
116
+ - `darwin` (macOS)
117
+ - `linux`
118
+ - `win32` (Windows)
119
+ - `{arch}`: The architecture. Supported values are:
120
+ - `x64`
121
+ - `arm64`
122
+ - `{extension}`: The file extension of the archive (e.g., `.tar.gz` or `.zip`).
123
+
124
+ **Examples:**
125
+
126
+ - `darwin.arm64.my-tool.tar.gz` (specific to Apple Silicon Macs)
127
+ - `darwin.my-tool.tar.gz` (for all Macs)
128
+ - `linux.x64.my-tool.tar.gz`
129
+ - `win32.my-tool.zip`
130
+
131
+ #### Archive structure
132
+
133
+ Archives must be fully contained extensions and have all the standard
134
+ requirements - specifically the `gemini-extension.json` file must be at the root
135
+ of the archive.
136
+
137
+ The rest of the layout should look exactly the same as a typical extension, see
138
+ [extensions.md](./index.md).
139
+
140
+ #### Example GitHub Actions workflow
141
+
142
+ Here is an example of a GitHub Actions workflow that builds and releases a
143
+ Gemini CLI extension for multiple platforms:
144
+
145
+ ```yaml
146
+ name: Release Extension
147
+
148
+ on:
149
+ push:
150
+ tags:
151
+ - 'v*'
152
+
153
+ jobs:
154
+ release:
155
+ runs-on: ubuntu-latest
156
+ steps:
157
+ - uses: actions/checkout@v3
158
+
159
+ - name: Set up Node.js
160
+ uses: actions/setup-node@v3
161
+ with:
162
+ node-version: '20'
163
+
164
+ - name: Install dependencies
165
+ run: npm ci
166
+
167
+ - name: Build extension
168
+ run: npm run build
169
+
170
+ - name: Create release assets
171
+ run: |
172
+ npm run package -- --platform=darwin --arch=arm64
173
+ npm run package -- --platform=linux --arch=x64
174
+ npm run package -- --platform=win32 --arch=x64
175
+
176
+ - name: Create GitHub Release
177
+ uses: softprops/action-gh-release@v1
178
+ with:
179
+ files: |
180
+ release/darwin.arm64.my-tool.tar.gz
181
+ release/linux.arm64.my-tool.tar.gz
182
+ release/win32.arm64.my-tool.zip
183
+ ```
@@ -0,0 +1,245 @@
1
+ # Getting started with Gemini CLI extensions
2
+
3
+ This guide will walk you through creating your first Gemini CLI extension.
4
+ You'll learn how to set up a new extension, add a custom tool via an MCP server,
5
+ create a custom command, and provide context to the model with a `GEMINI.md`
6
+ file.
7
+
8
+ ## Prerequisites
9
+
10
+ Before you start, make sure you have the Gemini CLI installed and a basic
11
+ understanding of Node.js and TypeScript.
12
+
13
+ ## Step 1: Create a new extension
14
+
15
+ The easiest way to start is by using one of the built-in templates. We'll use
16
+ the `mcp-server` example as our foundation.
17
+
18
+ Run the following command to create a new directory called `my-first-extension`
19
+ with the template files:
20
+
21
+ ```bash
22
+ gemini extensions new my-first-extension mcp-server
23
+ ```
24
+
25
+ This will create a new directory with the following structure:
26
+
27
+ ```
28
+ my-first-extension/
29
+ ├── example.ts
30
+ ├── gemini-extension.json
31
+ ├── package.json
32
+ └── tsconfig.json
33
+ ```
34
+
35
+ ## Step 2: Understand the extension files
36
+
37
+ Let's look at the key files in your new extension.
38
+
39
+ ### `gemini-extension.json`
40
+
41
+ This is the manifest file for your extension. It tells Gemini CLI how to load
42
+ and use your extension.
43
+
44
+ ```json
45
+ {
46
+ "name": "my-first-extension",
47
+ "version": "1.0.0",
48
+ "mcpServers": {
49
+ "nodeServer": {
50
+ "command": "node",
51
+ "args": ["${extensionPath}${/}dist${/}example.js"],
52
+ "cwd": "${extensionPath}"
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ - `name`: The unique name for your extension.
59
+ - `version`: The version of your extension.
60
+ - `mcpServers`: This section defines one or more Model Context Protocol (MCP)
61
+ servers. MCP servers are how you can add new tools for the model to use.
62
+ - `command`, `args`, `cwd`: These fields specify how to start your server.
63
+ Notice the use of the `${extensionPath}` variable, which Gemini CLI replaces
64
+ with the absolute path to your extension's installation directory. This
65
+ allows your extension to work regardless of where it's installed.
66
+
67
+ ### `example.ts`
68
+
69
+ This file contains the source code for your MCP server. It's a simple Node.js
70
+ server that uses the `@modelcontextprotocol/sdk`.
71
+
72
+ ```typescript
73
+ /**
74
+ * @license
75
+ * Copyright 2025 Google LLC
76
+ * SPDX-License-Identifier: Apache-2.0
77
+ */
78
+
79
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
80
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
81
+ import { z } from 'zod';
82
+
83
+ const server = new McpServer({
84
+ name: 'prompt-server',
85
+ version: '1.0.0',
86
+ });
87
+
88
+ // Registers a new tool named 'fetch_posts'
89
+ server.registerTool(
90
+ 'fetch_posts',
91
+ {
92
+ description: 'Fetches a list of posts from a public API.',
93
+ inputSchema: z.object({}).shape,
94
+ },
95
+ async () => {
96
+ const apiResponse = await fetch(
97
+ 'https://jsonplaceholder.typicode.com/posts',
98
+ );
99
+ const posts = await apiResponse.json();
100
+ const response = { posts: posts.slice(0, 5) };
101
+ return {
102
+ content: [
103
+ {
104
+ type: 'text',
105
+ text: JSON.stringify(response),
106
+ },
107
+ ],
108
+ };
109
+ },
110
+ );
111
+
112
+ // ... (prompt registration omitted for brevity)
113
+
114
+ const transport = new StdioServerTransport();
115
+ await server.connect(transport);
116
+ ```
117
+
118
+ This server defines a single tool called `fetch_posts` that fetches data from a
119
+ public API.
120
+
121
+ ### `package.json` and `tsconfig.json`
122
+
123
+ These are standard configuration files for a TypeScript project. The
124
+ `package.json` file defines dependencies and a `build` script, and
125
+ `tsconfig.json` configures the TypeScript compiler.
126
+
127
+ ## Step 3: Build and link your extension
128
+
129
+ Before you can use the extension, you need to compile the TypeScript code and
130
+ link the extension to your Gemini CLI installation for local development.
131
+
132
+ 1. **Install dependencies:**
133
+
134
+ ```bash
135
+ cd my-first-extension
136
+ npm install
137
+ ```
138
+
139
+ 2. **Build the server:**
140
+
141
+ ```bash
142
+ npm run build
143
+ ```
144
+
145
+ This will compile `example.ts` into `dist/example.js`, which is the file
146
+ referenced in your `gemini-extension.json`.
147
+
148
+ 3. **Link the extension:**
149
+
150
+ The `link` command creates a symbolic link from the Gemini CLI extensions
151
+ directory to your development directory. This means any changes you make
152
+ will be reflected immediately without needing to reinstall.
153
+
154
+ ```bash
155
+ gemini extensions link .
156
+ ```
157
+
158
+ Now, restart your Gemini CLI session. The new `fetch_posts` tool will be
159
+ available. You can test it by asking: "fetch posts".
160
+
161
+ ## Step 4: Add a custom command
162
+
163
+ Custom commands provide a way to create shortcuts for complex prompts. Let's add
164
+ a command that searches for a pattern in your code.
165
+
166
+ 1. Create a `commands` directory and a subdirectory for your command group:
167
+
168
+ ```bash
169
+ mkdir -p commands/fs
170
+ ```
171
+
172
+ 2. Create a file named `commands/fs/grep-code.toml`:
173
+
174
+ ```toml
175
+ prompt = """
176
+ Please summarize the findings for the pattern `{{args}}`.
177
+
178
+ Search Results:
179
+ !{grep -r {{args}} .}
180
+ """
181
+ ```
182
+
183
+ This command, `/fs:grep-code`, will take an argument, run the `grep` shell
184
+ command with it, and pipe the results into a prompt for summarization.
185
+
186
+ After saving the file, restart the Gemini CLI. You can now run
187
+ `/fs:grep-code "some pattern"` to use your new command.
188
+
189
+ ## Step 5: Add a custom `GEMINI.md`
190
+
191
+ You can provide persistent context to the model by adding a `GEMINI.md` file to
192
+ your extension. This is useful for giving the model instructions on how to
193
+ behave or information about your extension's tools. Note that you may not always
194
+ need this for extensions built to expose commands and prompts.
195
+
196
+ 1. Create a file named `GEMINI.md` in the root of your extension directory:
197
+
198
+ ```markdown
199
+ # My First Extension Instructions
200
+
201
+ You are an expert developer assistant. When the user asks you to fetch
202
+ posts, use the `fetch_posts` tool. Be concise in your responses.
203
+ ```
204
+
205
+ 2. Update your `gemini-extension.json` to tell the CLI to load this file:
206
+
207
+ ```json
208
+ {
209
+ "name": "my-first-extension",
210
+ "version": "1.0.0",
211
+ "contextFileName": "GEMINI.md",
212
+ "mcpServers": {
213
+ "nodeServer": {
214
+ "command": "node",
215
+ "args": ["${extensionPath}${/}dist${/}example.js"],
216
+ "cwd": "${extensionPath}"
217
+ }
218
+ }
219
+ }
220
+ ```
221
+
222
+ Restart the CLI again. The model will now have the context from your `GEMINI.md`
223
+ file in every session where the extension is active.
224
+
225
+ ## Step 6: Releasing your extension
226
+
227
+ Once you are happy with your extension, you can share it with others. The two
228
+ primary ways of releasing extensions are via a Git repository or through GitHub
229
+ Releases. Using a public Git repository is the simplest method.
230
+
231
+ For detailed instructions on both methods, please refer to the
232
+ [Extension Releasing Guide](./extension-releasing.md).
233
+
234
+ ## Conclusion
235
+
236
+ You've successfully created a Gemini CLI extension! You learned how to:
237
+
238
+ - Bootstrap a new extension from a template.
239
+ - Add custom tools with an MCP server.
240
+ - Create convenient custom commands.
241
+ - Provide persistent context to the model.
242
+ - Link your extension for local development.
243
+
244
+ From here, you can explore more advanced features and build powerful new
245
+ capabilities into the Gemini CLI.