@google/gemini-cli-core 0.21.0-nightly.20251218.739c02bd6 → 0.21.0-nightly.20251220.41a1a3eed
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.
- package/dist/docs/CONTRIBUTING.md +546 -0
- package/dist/docs/architecture.md +80 -0
- package/dist/docs/assets/connected_devtools.png +0 -0
- package/dist/docs/assets/gemini-screenshot.png +0 -0
- package/dist/docs/assets/release_patch.png +0 -0
- package/dist/docs/assets/theme-ansi-light.png +0 -0
- package/dist/docs/assets/theme-ansi.png +0 -0
- package/dist/docs/assets/theme-atom-one.png +0 -0
- package/dist/docs/assets/theme-ayu-light.png +0 -0
- package/dist/docs/assets/theme-ayu.png +0 -0
- package/dist/docs/assets/theme-custom.png +0 -0
- package/dist/docs/assets/theme-default-light.png +0 -0
- package/dist/docs/assets/theme-default.png +0 -0
- package/dist/docs/assets/theme-dracula.png +0 -0
- package/dist/docs/assets/theme-github-light.png +0 -0
- package/dist/docs/assets/theme-github.png +0 -0
- package/dist/docs/assets/theme-google-light.png +0 -0
- package/dist/docs/assets/theme-xcode-light.png +0 -0
- package/dist/docs/changelogs/index.md +592 -0
- package/dist/docs/changelogs/latest.md +225 -0
- package/dist/docs/changelogs/preview.md +129 -0
- package/dist/docs/changelogs/releases.md +896 -0
- package/dist/docs/cli/authentication.md +3 -0
- package/dist/docs/cli/checkpointing.md +94 -0
- package/dist/docs/cli/commands.md +354 -0
- package/dist/docs/cli/configuration.md +780 -0
- package/dist/docs/cli/custom-commands.md +315 -0
- package/dist/docs/cli/enterprise.md +565 -0
- package/dist/docs/cli/gemini-ignore.md +71 -0
- package/dist/docs/cli/gemini-md.md +108 -0
- package/dist/docs/cli/generation-settings.md +210 -0
- package/dist/docs/cli/headless.md +388 -0
- package/dist/docs/cli/index.md +63 -0
- package/dist/docs/cli/keyboard-shortcuts.md +143 -0
- package/dist/docs/cli/model-routing.md +37 -0
- package/dist/docs/cli/model.md +62 -0
- package/dist/docs/cli/sandbox.md +171 -0
- package/dist/docs/cli/session-management.md +158 -0
- package/dist/docs/cli/settings.md +112 -0
- package/dist/docs/cli/system-prompt.md +93 -0
- package/dist/docs/cli/telemetry.md +791 -0
- package/dist/docs/cli/themes.md +237 -0
- package/dist/docs/cli/token-caching.md +20 -0
- package/dist/docs/cli/trusted-folders.md +95 -0
- package/dist/docs/cli/tutorials.md +83 -0
- package/dist/docs/cli/uninstall.md +47 -0
- package/dist/docs/core/index.md +101 -0
- package/dist/docs/core/memport.md +244 -0
- package/dist/docs/core/policy-engine.md +267 -0
- package/dist/docs/core/tools-api.md +131 -0
- package/dist/docs/examples/proxy-script.md +83 -0
- package/dist/docs/extensions/extension-releasing.md +183 -0
- package/dist/docs/extensions/getting-started-extensions.md +245 -0
- package/dist/docs/extensions/index.md +293 -0
- package/dist/docs/faq.md +154 -0
- package/dist/docs/get-started/authentication.md +321 -0
- package/dist/docs/get-started/configuration-v1.md +888 -0
- package/dist/docs/get-started/configuration.md +1444 -0
- package/dist/docs/get-started/deployment.md +143 -0
- package/dist/docs/get-started/examples.md +219 -0
- package/dist/docs/get-started/gemini-3.md +116 -0
- package/dist/docs/get-started/index.md +71 -0
- package/dist/docs/get-started/installation.md +141 -0
- package/dist/docs/hooks/best-practices.md +806 -0
- package/dist/docs/hooks/index.md +665 -0
- package/dist/docs/hooks/reference.md +168 -0
- package/dist/docs/hooks/writing-hooks.md +1026 -0
- package/dist/docs/ide-integration/ide-companion-spec.md +267 -0
- package/dist/docs/ide-integration/index.md +202 -0
- package/dist/docs/index.md +147 -0
- package/dist/docs/integration-tests.md +211 -0
- package/dist/docs/issue-and-pr-automation.md +134 -0
- package/dist/docs/local-development.md +128 -0
- package/dist/docs/mermaid/context.mmd +103 -0
- package/dist/docs/mermaid/render-path.mmd +64 -0
- package/dist/docs/npm.md +62 -0
- package/dist/docs/quota-and-pricing.md +158 -0
- package/dist/docs/release-confidence.md +164 -0
- package/dist/docs/releases.md +540 -0
- package/dist/docs/sidebar.json +297 -0
- package/dist/docs/tools/file-system.md +217 -0
- package/dist/docs/tools/index.md +95 -0
- package/dist/docs/tools/mcp-server.md +1044 -0
- package/dist/docs/tools/memory.md +54 -0
- package/dist/docs/tools/shell.md +260 -0
- package/dist/docs/tools/todos.md +57 -0
- package/dist/docs/tools/web-fetch.md +59 -0
- package/dist/docs/tools/web-search.md +42 -0
- package/dist/docs/tos-privacy.md +96 -0
- package/dist/docs/troubleshooting.md +158 -0
- package/dist/google-gemini-cli-core-0.21.0-nightly.20251219.70696e364.tgz +0 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js +1 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -1
- package/dist/src/agents/introspection-agent.d.ts +23 -0
- package/dist/src/agents/introspection-agent.js +72 -0
- package/dist/src/agents/introspection-agent.js.map +1 -0
- package/dist/src/agents/introspection-agent.test.d.ts +6 -0
- package/dist/src/agents/introspection-agent.test.js +47 -0
- package/dist/src/agents/introspection-agent.test.js.map +1 -0
- package/dist/src/agents/local-executor.d.ts +0 -6
- package/dist/src/agents/local-executor.js +73 -47
- package/dist/src/agents/local-executor.js.map +1 -1
- package/dist/src/agents/local-executor.test.d.ts +1 -7
- package/dist/src/agents/local-executor.test.js +27 -9
- package/dist/src/agents/local-executor.test.js.map +1 -1
- package/dist/src/agents/registry.d.ts +1 -0
- package/dist/src/agents/registry.js +51 -7
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js +112 -1
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/agents/toml-loader.d.ts +65 -0
- package/dist/src/agents/toml-loader.js +176 -0
- package/dist/src/agents/toml-loader.js.map +1 -0
- package/dist/src/agents/toml-loader.test.d.ts +6 -0
- package/dist/src/agents/toml-loader.test.js +190 -0
- package/dist/src/agents/toml-loader.test.js.map +1 -0
- package/dist/src/availability/modelAvailabilityService.d.ts +2 -1
- package/dist/src/config/config.d.ts +9 -0
- package/dist/src/config/config.js +29 -0
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +59 -1
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/storage.d.ts +2 -0
- package/dist/src/config/storage.js +6 -0
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +8 -0
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/core/client.js +8 -4
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +20 -0
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/clientHookTriggers.js +2 -2
- package/dist/src/core/clientHookTriggers.js.map +1 -1
- package/dist/src/core/coreToolHookTriggers.js +3 -3
- package/dist/src/core/coreToolHookTriggers.js.map +1 -1
- package/dist/src/core/geminiChatHookTriggers.js +3 -3
- package/dist/src/core/geminiChatHookTriggers.js.map +1 -1
- package/dist/src/core/sessionHookTriggers.js +3 -3
- package/dist/src/core/sessionHookTriggers.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookEventHandler.js +10 -4
- package/dist/src/hooks/hookEventHandler.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.test.js +40 -0
- package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
- package/dist/src/hooks/hookPlanner.js +3 -1
- package/dist/src/hooks/hookPlanner.js.map +1 -1
- package/dist/src/hooks/hookPlanner.test.js +61 -0
- package/dist/src/hooks/hookPlanner.test.js.map +1 -1
- package/dist/src/hooks/hookRegistry.d.ts +1 -1
- package/dist/src/hooks/hookRegistry.js +2 -2
- package/dist/src/hooks/hookRegistry.js.map +1 -1
- package/dist/src/hooks/hookRegistry.test.js +73 -0
- package/dist/src/hooks/hookRegistry.test.js.map +1 -1
- package/dist/src/hooks/hookRunner.js +14 -10
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js +81 -33
- package/dist/src/hooks/hookRunner.test.js.map +1 -1
- package/dist/src/hooks/types.d.ts +2 -0
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js +6 -2
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +4 -1
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.d.ts +8 -1
- package/dist/src/mcp/oauth-utils.js +30 -1
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +42 -0
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/services/contextManager.d.ts +5 -11
- package/dist/src/services/contextManager.js +20 -17
- package/dist/src/services/contextManager.js.map +1 -1
- package/dist/src/services/contextManager.test.js +40 -41
- package/dist/src/services/contextManager.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +18 -2
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/tools/get-internal-docs.d.ts +27 -0
- package/dist/src/tools/get-internal-docs.js +129 -0
- package/dist/src/tools/get-internal-docs.js.map +1 -0
- package/dist/src/tools/get-internal-docs.test.d.ts +6 -0
- package/dist/src/tools/get-internal-docs.test.js +56 -0
- package/dist/src/tools/get-internal-docs.test.js.map +1 -0
- package/dist/src/tools/tool-names.d.ts +14 -0
- package/dist/src/tools/tool-names.js +55 -0
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-names.test.d.ts +6 -0
- package/dist/src/tools/tool-names.test.js +43 -0
- package/dist/src/tools/tool-names.test.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +0 -1
- package/dist/src/tools/tool-registry.js +1 -1
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +2 -1
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/utils/environmentContext.js +3 -0
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +2 -0
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/events.d.ts +3 -2
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.js +20 -0
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.test.js +53 -2
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.js +1 -1
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +3 -1
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/shell-utils.js +25 -4
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -6
- package/dist/google-gemini-cli-core-0.21.0-nightly.20251216.bb0c0d8ee.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.
|