Skip to content
This repository was archived by the owner on Apr 30, 2026. It is now read-only.

Commit 9b37d32

Browse files
authored
Merge branch 'google-gemini:main' into main
2 parents 321695d + 2498114 commit 9b37d32

102 files changed

Lines changed: 7047 additions & 1981 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/changelogs/index.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ on GitHub.
1818
| [Preview](preview.md) | Experimental features ready for early feedback. |
1919
| [Stable](latest.md) | Stable, recommended for general use. |
2020

21+
## Announcements: v0.27.0 - 2026-02-03
22+
23+
- **Event-Driven Architecture:** The CLI now uses a new event-driven scheduler
24+
for tool execution, resulting in a more responsive and performant experience
25+
([#17078](https://github.com/google-gemini/gemini-cli/pull/17078) by
26+
@abhipatel12).
27+
- **Enhanced User Experience:** This release includes queued tool confirmations,
28+
and expandable large text pastes for a smoother workflow.
29+
- **New `/rewind` Command:** Easily navigate your session history with the new
30+
`/rewind` command
31+
([#15720](https://github.com/google-gemini/gemini-cli/pull/15720) by
32+
@Adib234).
33+
- **Linux Clipboard Support:** You can now paste images on Linux with Wayland
34+
and X11 ([#17144](https://github.com/google-gemini/gemini-cli/pull/17144) by
35+
@devr0306).
36+
2137
## Announcements: v0.26.0 - 2026-01-27
2238

2339
- **Agents and Skills:** We've introduced a new `skill-creator` skill

docs/changelogs/latest.md

Lines changed: 424 additions & 315 deletions
Large diffs are not rendered by default.

docs/changelogs/preview.md

Lines changed: 289 additions & 419 deletions
Large diffs are not rendered by default.

docs/cli/cli-reference.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,18 @@ See [Extensions Documentation](../extensions/index.md) for more details.
9999
| `gemini mcp list` | List all configured MCP servers | `gemini mcp list` |
100100

101101
See [MCP Server Integration](../tools/mcp-server.md) for more details.
102+
103+
## Skills management
104+
105+
| Command | Description | Example |
106+
| -------------------------------- | ------------------------------------- | ------------------------------------------------- |
107+
| `gemini skills list` | List all discovered agent skills | `gemini skills list` |
108+
| `gemini skills install <source>` | Install skill from Git, path, or file | `gemini skills install https://github.com/u/repo` |
109+
| `gemini skills link <path>` | Link local agent skills via symlink | `gemini skills link /path/to/my-skills` |
110+
| `gemini skills uninstall <name>` | Uninstall an agent skill | `gemini skills uninstall my-skill` |
111+
| `gemini skills enable <name>` | Enable an agent skill | `gemini skills enable my-skill` |
112+
| `gemini skills disable <name>` | Disable an agent skill | `gemini skills disable my-skill` |
113+
| `gemini skills enable --all` | Enable all skills | `gemini skills enable --all` |
114+
| `gemini skills disable --all` | Disable all skills | `gemini skills disable --all` |
115+
116+
See [Agent Skills Documentation](./skills.md) for more details.

docs/cli/commands.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,11 @@ please see the dedicated [Custom Commands documentation](./custom-commands.md).
343343
These shortcuts apply directly to the input prompt for text manipulation.
344344

345345
- **Undo:**
346-
- **Keyboard shortcut:** Press **Cmd+z** or **Alt+z** to undo the last action
346+
- **Keyboard shortcut:** Press **Alt+z** or **Cmd+z** to undo the last action
347347
in the input prompt.
348348

349349
- **Redo:**
350-
- **Keyboard shortcut:** Press **Shift+Cmd+Z** or **Shift+Alt+Z** to redo the
350+
- **Keyboard shortcut:** Press **Shift+Alt+Z** or **Shift+Cmd+Z** to redo the
351351
last undone action in the input prompt.
352352

353353
## At commands (`@`)

docs/cli/skills.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ locations override lower ones: **Workspace > User > Extension**.
5252
Use the `/skills` slash command to view and manage available expertise:
5353

5454
- `/skills list` (default): Shows all discovered skills and their status.
55+
- `/skills link <path>`: Links agent skills from a local directory via symlink.
5556
- `/skills disable <name>`: Prevents a specific skill from being used.
5657
- `/skills enable <name>`: Re-enables a disabled skill.
5758
- `/skills reload`: Refreshes the list of discovered skills from all tiers.
@@ -67,6 +68,13 @@ The `gemini skills` command provides management utilities:
6768
# List all discovered skills
6869
gemini skills list
6970

71+
# Link agent skills from a local directory via symlink
72+
# Discovers skills (SKILL.md or */SKILL.md) and creates symlinks in ~/.gemini/skills (user)
73+
gemini skills link /path/to/my-skills-repo
74+
75+
# Link to the workspace scope (.gemini/skills)
76+
gemini skills link /path/to/my-skills-repo --scope workspace
77+
7078
# Install a skill from a Git repository, local directory, or zipped skill file (.skill)
7179
# Uses the user scope by default (~/.gemini/skills)
7280
gemini skills install https://github.com/user/repo.git

docs/get-started/configuration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,10 @@ their corresponding top-level category object in your `settings.json` file.
995995
- **Description:** If false, disallows MCP servers from being used.
996996
- **Default:** `true`
997997

998+
- **`admin.mcp.config`** (object):
999+
- **Description:** Admin-configured MCP servers.
1000+
- **Default:** `{}`
1001+
9981002
- **`admin.skills.enabled`** (boolean):
9991003
- **Description:** If false, disallows agent skills from being used.
10001004
- **Default:** `true`

docs/index.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,8 @@ Connect Gemini CLI to external services and other development tools.
100100
the Model Context Protocol.
101101
- **[IDE integration](./ide-integration/index.md):** Use Gemini CLI alongside VS
102102
Code.
103-
- **[Hooks](./hooks/index.md):** (Preview) Write scripts that run on specific
104-
CLI events.
105-
- **[Agent skills](./cli/skills.md):** (Preview) Add specialized expertise and
106-
workflows.
103+
- **[Hooks](./hooks/index.md):** Write scripts that run on specific CLI events.
104+
- **[Agent skills](./cli/skills.md):** Add specialized expertise and workflows.
107105
- **[Sub-agents](./core/subagents.md):** (Preview) Delegate tasks to specialized
108106
agents.
109107

docs/sidebar.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,14 +123,6 @@
123123
"items": [
124124
{ "label": "FAQ", "slug": "docs/faq" },
125125
{ "label": "Quota and pricing", "slug": "docs/quota-and-pricing" },
126-
{
127-
"label": "Releases",
128-
"items": [
129-
{ "label": "Release notes", "slug": "docs/changelogs/" },
130-
{ "label": "Stable release", "slug": "docs/changelogs/latest" },
131-
{ "label": "Preview release", "slug": "docs/changelogs/preview" }
132-
]
133-
},
134126
{ "label": "Terms and privacy", "slug": "docs/tos-privacy" },
135127
{ "label": "Troubleshooting", "slug": "docs/troubleshooting" },
136128
{ "label": "Uninstall", "slug": "docs/cli/uninstall" }
@@ -148,5 +140,13 @@
148140
{ "label": "Local development", "slug": "docs/local-development" },
149141
{ "label": "NPM package structure", "slug": "docs/npm" }
150142
]
143+
},
144+
{
145+
"label": "Releases",
146+
"items": [
147+
{ "label": "Release notes", "slug": "docs/changelogs/" },
148+
{ "label": "Stable release", "slug": "docs/changelogs/latest" },
149+
{ "label": "Preview release", "slug": "docs/changelogs/preview" }
150+
]
151151
}
152152
]

evals/save_memory.eval.ts

Lines changed: 216 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,234 @@
66

77
import { describe, expect } from 'vitest';
88
import { evalTest } from './test-helper.js';
9-
import { validateModelOutput } from '../integration-tests/test-helper.js';
9+
import {
10+
assertModelHasOutput,
11+
checkModelOutputContent,
12+
} from '../integration-tests/test-helper.js';
1013

1114
describe('save_memory', () => {
15+
const TEST_PREFIX = 'Save memory test: ';
16+
const rememberingFavoriteColor = "Agent remembers user's favorite color";
1217
evalTest('ALWAYS_PASSES', {
13-
name: 'should be able to save to memory',
18+
name: rememberingFavoriteColor,
1419
params: {
1520
settings: { tools: { core: ['save_memory'] } },
1621
},
1722
prompt: `remember that my favorite color is blue.
1823
1924
what is my favorite color? tell me that and surround it with $ symbol`,
2025
assert: async (rig, result) => {
21-
const foundToolCall = await rig.waitForToolCall('save_memory');
26+
const wasToolCalled = await rig.waitForToolCall('save_memory');
27+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
28+
true,
29+
);
30+
31+
assertModelHasOutput(result);
32+
checkModelOutputContent(result, {
33+
expectedContent: 'blue',
34+
testName: `${TEST_PREFIX}${rememberingFavoriteColor}`,
35+
});
36+
},
37+
});
38+
const rememberingCommandRestrictions = 'Agent remembers command restrictions';
39+
evalTest('ALWAYS_PASSES', {
40+
name: rememberingCommandRestrictions,
41+
params: {
42+
settings: { tools: { core: ['save_memory'] } },
43+
},
44+
prompt: `I don't want you to ever run npm commands.`,
45+
assert: async (rig, result) => {
46+
const wasToolCalled = await rig.waitForToolCall('save_memory');
47+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
48+
true,
49+
);
50+
51+
assertModelHasOutput(result);
52+
checkModelOutputContent(result, {
53+
expectedContent: [/not run npm commands|remember|ok/i],
54+
testName: `${TEST_PREFIX}${rememberingCommandRestrictions}`,
55+
});
56+
},
57+
});
58+
59+
const rememberingWorkflow = 'Agent remembers workflow preferences';
60+
evalTest('ALWAYS_PASSES', {
61+
name: rememberingWorkflow,
62+
params: {
63+
settings: { tools: { core: ['save_memory'] } },
64+
},
65+
prompt: `I want you to always lint after building.`,
66+
assert: async (rig, result) => {
67+
const wasToolCalled = await rig.waitForToolCall('save_memory');
68+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
69+
true,
70+
);
71+
72+
assertModelHasOutput(result);
73+
checkModelOutputContent(result, {
74+
expectedContent: [/always|ok|remember|will do/i],
75+
testName: `${TEST_PREFIX}${rememberingWorkflow}`,
76+
});
77+
},
78+
});
79+
80+
const ignoringTemporaryInformation =
81+
'Agent ignores temporary conversation details';
82+
evalTest('ALWAYS_PASSES', {
83+
name: ignoringTemporaryInformation,
84+
params: {
85+
settings: { tools: { core: ['save_memory'] } },
86+
},
87+
prompt: `I'm going to get a coffee.`,
88+
assert: async (rig, result) => {
89+
await rig.waitForTelemetryReady();
90+
const wasToolCalled = rig
91+
.readToolLogs()
92+
.some((log) => log.toolRequest.name === 'save_memory');
2293
expect(
23-
foundToolCall,
24-
'Expected to find a save_memory tool call',
25-
).toBeTruthy();
94+
wasToolCalled,
95+
'save_memory should not be called for temporary information',
96+
).toBe(false);
97+
98+
assertModelHasOutput(result);
99+
checkModelOutputContent(result, {
100+
testName: `${TEST_PREFIX}${ignoringTemporaryInformation}`,
101+
forbiddenContent: [/remember|will do/i],
102+
});
103+
},
104+
});
105+
106+
const rememberingPetName = "Agent remembers user's pet's name";
107+
evalTest('ALWAYS_PASSES', {
108+
name: rememberingPetName,
109+
params: {
110+
settings: { tools: { core: ['save_memory'] } },
111+
},
112+
prompt: `My dog's name is Buddy. What is my dog's name?`,
113+
assert: async (rig, result) => {
114+
const wasToolCalled = await rig.waitForToolCall('save_memory');
115+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
116+
true,
117+
);
118+
119+
assertModelHasOutput(result);
120+
checkModelOutputContent(result, {
121+
expectedContent: [/Buddy/i],
122+
testName: `${TEST_PREFIX}${rememberingPetName}`,
123+
});
124+
},
125+
});
126+
127+
const rememberingCommandAlias = 'Agent remembers custom command aliases';
128+
evalTest('ALWAYS_PASSES', {
129+
name: rememberingCommandAlias,
130+
params: {
131+
settings: { tools: { core: ['save_memory'] } },
132+
},
133+
prompt: `When I say 'start server', you should run 'npm run dev'.`,
134+
assert: async (rig, result) => {
135+
const wasToolCalled = await rig.waitForToolCall('save_memory');
136+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
137+
true,
138+
);
139+
140+
assertModelHasOutput(result);
141+
checkModelOutputContent(result, {
142+
expectedContent: [/npm run dev|start server|ok|remember|will do/i],
143+
testName: `${TEST_PREFIX}${rememberingCommandAlias}`,
144+
});
145+
},
146+
});
147+
148+
const rememberingDbSchemaLocation =
149+
"Agent remembers project's database schema location";
150+
evalTest('ALWAYS_PASSES', {
151+
name: rememberingDbSchemaLocation,
152+
params: {
153+
settings: { tools: { core: ['save_memory'] } },
154+
},
155+
prompt: `The database schema for this project is located in \`db/schema.sql\`.`,
156+
assert: async (rig, result) => {
157+
const wasToolCalled = await rig.waitForToolCall('save_memory');
158+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
159+
true,
160+
);
161+
162+
assertModelHasOutput(result);
163+
checkModelOutputContent(result, {
164+
expectedContent: [/database schema|ok|remember|will do/i],
165+
testName: `${TEST_PREFIX}${rememberingDbSchemaLocation}`,
166+
});
167+
},
168+
});
169+
170+
const rememberingCodingStyle =
171+
"Agent remembers user's coding style preference";
172+
evalTest('ALWAYS_PASSES', {
173+
name: rememberingCodingStyle,
174+
params: {
175+
settings: { tools: { core: ['save_memory'] } },
176+
},
177+
prompt: `I prefer to use tabs instead of spaces for indentation.`,
178+
assert: async (rig, result) => {
179+
const wasToolCalled = await rig.waitForToolCall('save_memory');
180+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
181+
true,
182+
);
183+
184+
assertModelHasOutput(result);
185+
checkModelOutputContent(result, {
186+
expectedContent: [/tabs instead of spaces|ok|remember|will do/i],
187+
testName: `${TEST_PREFIX}${rememberingCodingStyle}`,
188+
});
189+
},
190+
});
191+
192+
const rememberingTestCommand =
193+
'Agent remembers specific project test command';
194+
evalTest('ALWAYS_PASSES', {
195+
name: rememberingTestCommand,
196+
params: {
197+
settings: { tools: { core: ['save_memory'] } },
198+
},
199+
prompt: `The command to run all backend tests is \`npm run test:backend\`.`,
200+
assert: async (rig, result) => {
201+
const wasToolCalled = await rig.waitForToolCall('save_memory');
202+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
203+
true,
204+
);
205+
206+
assertModelHasOutput(result);
207+
checkModelOutputContent(result, {
208+
expectedContent: [
209+
/command to run all backend tests|ok|remember|will do/i,
210+
],
211+
testName: `${TEST_PREFIX}${rememberingTestCommand}`,
212+
});
213+
},
214+
});
215+
216+
const rememberingMainEntryPoint =
217+
"Agent remembers project's main entry point";
218+
evalTest('ALWAYS_PASSES', {
219+
name: rememberingMainEntryPoint,
220+
params: {
221+
settings: { tools: { core: ['save_memory'] } },
222+
},
223+
prompt: `The main entry point for this project is \`src/index.js\`.`,
224+
assert: async (rig, result) => {
225+
const wasToolCalled = await rig.waitForToolCall('save_memory');
226+
expect(wasToolCalled, 'Expected save_memory tool to be called').toBe(
227+
true,
228+
);
26229

27-
validateModelOutput(result, 'blue', 'Save memory test');
230+
assertModelHasOutput(result);
231+
checkModelOutputContent(result, {
232+
expectedContent: [
233+
/main entry point for this project|ok|remember|will do/i,
234+
],
235+
testName: `${TEST_PREFIX}${rememberingMainEntryPoint}`,
236+
});
28237
},
29238
});
30239
});

0 commit comments

Comments
 (0)