mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-23 00:01:24 -07:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a7e9297e2 | |||
| 14887ab3a6 | |||
| 66d76ff3da | |||
| 6f4643eba6 | |||
| 0efda7c790 | |||
| c62444e8ef | |||
| 1542a3f7e3 | |||
| fba5a4813a | |||
| 0ab5aef2a5 | |||
| 2117d32a73 | |||
| 4f1adacfc8 | |||
| d6ba439e97 |
@@ -1,142 +1,64 @@
|
||||
# Gemini CLI Strict Development Rules
|
||||
|
||||
These rules apply strictly to all code modifications and additions within the
|
||||
Gemini CLI project.
|
||||
These rules apply strictly to all code modifications and additions within the Gemini CLI project.
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
- **Async/Await**: Always use `waitFor` from
|
||||
`packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` for all
|
||||
`waitFor` calls within `packages/cli`. NEVER use fixed waits (e.g.,
|
||||
`await delay(100)`). Always use `waitFor` with a predicate to ensure tests are
|
||||
stable and fast. Using the wrong `waitFor` can result in flaky tests and `act`
|
||||
warnings.
|
||||
- **React Testing**: Use `act` to wrap all blocks in tests that change component
|
||||
state. Use `render` or `renderWithProviders` from
|
||||
`packages/cli/src/test-utils/render.tsx` instead of `render` from
|
||||
`ink-testing-library` directly. This prevents spurious `act` warnings. If test
|
||||
cases specify providers directly, consider whether the existing
|
||||
`renderWithProviders` should be modified.
|
||||
- **Snapshots**: Use `toMatchSnapshot` to verify that rendering works as
|
||||
expected rather than matching against the raw content of the output. When
|
||||
modifying snapshots, verify the changes are intentional and do not hide
|
||||
underlying bugs.
|
||||
- **Parameterized Tests**: Use parameterized tests where it reduces duplicated
|
||||
lines. Give the parameters explicit types to ensure the tests are type-safe.
|
||||
- **Mocks Management**:
|
||||
- Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of
|
||||
the file. Ideally, avoid mocking these dependencies altogether.
|
||||
- Reuse existing mocks and fakes rather than creating new ones.
|
||||
- Avoid mocking the file system whenever possible. If using the real file
|
||||
system is too difficult, consider writing an integration test instead.
|
||||
- Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution.
|
||||
- Use `vi.useFakeTimers()` for tests involving time-based logic to avoid
|
||||
flakiness.
|
||||
- **Typing in Tests**: Avoid using `any` in tests; prefer proper types or
|
||||
`unknown` with narrowing.
|
||||
* **Async/Await**: Always use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` for all `waitFor` calls within `packages/cli`. NEVER use fixed waits (e.g., `await delay(100)`). Always use `waitFor` with a predicate to ensure tests are stable and fast. Using the wrong `waitFor` can result in flaky tests and `act` warnings.
|
||||
* **React Testing**: Use `act` to wrap all blocks in tests that change component state. Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `render` from `ink-testing-library` directly. This prevents spurious `act` warnings. If test cases specify providers directly, consider whether the existing `renderWithProviders` should be modified.
|
||||
* **Snapshots**: Use `toMatchSnapshot` to verify that rendering works as expected rather than matching against the raw content of the output. When modifying snapshots, verify the changes are intentional and do not hide underlying bugs.
|
||||
* **Parameterized Tests**: Use parameterized tests where it reduces duplicated lines. Give the parameters explicit types to ensure the tests are type-safe.
|
||||
* **Mocks Management**:
|
||||
* Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of the file. Ideally, avoid mocking these dependencies altogether.
|
||||
* Reuse existing mocks and fakes rather than creating new ones.
|
||||
* Avoid mocking the file system whenever possible. If using the real file system is too difficult, consider writing an integration test instead.
|
||||
* Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution.
|
||||
* Use `vi.useFakeTimers()` for tests involving time-based logic to avoid flakiness.
|
||||
* **Typing in Tests**: Avoid using `any` in tests; prefer proper types or `unknown` with narrowing.
|
||||
|
||||
## React Guidelines (`packages/cli`)
|
||||
|
||||
- **`setState` and Side Effects**: NEVER trigger side effects from within the
|
||||
body of a `setState` callback. Use a reducer or `useRef` if necessary. These
|
||||
cases have historically introduced multiple bugs; typically, they should be
|
||||
resolved using a reducer.
|
||||
- **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous
|
||||
file I/O in React components as it will hang the UI. Do not implement new
|
||||
logic for custom string measurement or string truncation. Use Ink layout
|
||||
instead, leveraging `ResizeObserver` as needed.
|
||||
- **Keyboard Handling**: Keyboard handling MUST go through `useKeyPress.ts` from
|
||||
the Gemini CLI package rather than the standard ink library. This library
|
||||
supports reporting multiple keyboard events sequentially in the same React
|
||||
frame (critical for slow terminals). Handling this correctly often requires
|
||||
reducers to ensure multiple state updates are handled gracefully without
|
||||
overriding values. Refer to `text-buffer.ts` for a canonical example.
|
||||
- **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in
|
||||
the code.
|
||||
- **State & Effects**: Ensure state initialization is explicit (e.g., use
|
||||
`undefined` rather than `true` as a default if the state is truly unknown).
|
||||
Carefully manage `useEffect` dependencies. Prefer a reducer whenever
|
||||
practical. NEVER disable `react-hooks/exhaustive-deps`; fix the code to
|
||||
correctly declare dependencies instead.
|
||||
- **Context & Props**: Avoid excessive property drilling. Leverage existing
|
||||
providers, extend them, or propose a new one if necessary. Only use providers
|
||||
for properties that are consistent across the entire application.
|
||||
- **Code Structure**: Avoid complex `if` statements where `switch` statements
|
||||
could be used. Keep `AppContainer` minimal; refactor complex logic into React
|
||||
hooks. Evaluate whether business logic should be added to `hookSystem.ts` or
|
||||
integrated into `packages/core` rather than `packages/cli`.
|
||||
* **`setState` and Side Effects**: NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary. These cases have historically introduced multiple bugs; typically, they should be resolved using a reducer.
|
||||
* **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous file I/O in React components as it will hang the UI. Do not implement new logic for custom string measurement or string truncation. Use Ink layout instead, leveraging `ResizeObserver` as needed.
|
||||
* **Keyboard Handling**: Keyboard handling MUST go through `useKeyPress.ts` from the Gemini CLI package rather than the standard ink library. This library supports reporting multiple keyboard events sequentially in the same React frame (critical for slow terminals). Handling this correctly often requires reducers to ensure multiple state updates are handled gracefully without overriding values. Refer to `text-buffer.ts` for a canonical example.
|
||||
* **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in the code.
|
||||
* **State & Effects**: Ensure state initialization is explicit (e.g., use `undefined` rather than `true` as a default if the state is truly unknown). Carefully manage `useEffect` dependencies. Prefer a reducer whenever practical. NEVER disable `react-hooks/exhaustive-deps`; fix the code to correctly declare dependencies instead.
|
||||
* **Context & Props**: Avoid excessive property drilling. Leverage existing providers, extend them, or propose a new one if necessary. Only use providers for properties that are consistent across the entire application.
|
||||
* **Code Structure**: Avoid complex `if` statements where `switch` statements could be used. Keep `AppContainer` minimal; refactor complex logic into React hooks. Evaluate whether business logic should be added to `hookSystem.ts` or integrated into `packages/core` rather than `packages/cli`.
|
||||
|
||||
## Core Guidelines (`packages/core`)
|
||||
|
||||
- **Services**: Implement services as classes with clear lifecycle management
|
||||
(e.g., `initialize()` methods). Services should be stateless where possible,
|
||||
or use the centralized `Storage` service for persistence.
|
||||
- **Cross-Service Communication**: Prefer using the `coreEvents` bus (from
|
||||
`packages/core/src/utils/events.ts`) for asynchronous communication between
|
||||
services or to notify the UI of state changes. Avoid tight coupling between
|
||||
services.
|
||||
- **Utilities**: Use `debugLogger` from `packages/core/src/utils/debugLogger.ts`
|
||||
for internal logging instead of `console`. Ensure all shell operations use
|
||||
`spawnAsync` from `packages/core/src/utils/shell-utils.ts` for consistent
|
||||
error handling and promise management. Handle filesystem errors gracefully
|
||||
using `isNodeError` from `packages/core/src/utils/errors.ts`.
|
||||
- **Exports & Tooling**: Add new tools to `packages/core/src/tools/` and
|
||||
register them in `packages/core/src/tools/tool-registry.ts`. Export all new
|
||||
public services, utilities, and types from `packages/core/src/index.ts`.
|
||||
* **Services**: Implement services as classes with clear lifecycle management (e.g., `initialize()` methods). Services should be stateless where possible, or use the centralized `Storage` service for persistence.
|
||||
* **Cross-Service Communication**: Prefer using the `coreEvents` bus (from `packages/core/src/utils/events.ts`) for asynchronous communication between services or to notify the UI of state changes. Avoid tight coupling between services.
|
||||
* **Utilities**: Use `debugLogger` from `packages/core/src/utils/debugLogger.ts` for internal logging instead of `console`. Ensure all shell operations use `spawnAsync` from `packages/core/src/utils/shell-utils.ts` for consistent error handling and promise management. Handle filesystem errors gracefully using `isNodeError` from `packages/core/src/utils/errors.ts`.
|
||||
* **Exports & Tooling**: Add new tools to `packages/core/src/tools/` and register them in `packages/core/src/tools/tool-registry.ts`. Export all new public services, utilities, and types from `packages/core/src/index.ts`.
|
||||
|
||||
## Architectural Audit (Package Boundaries)
|
||||
|
||||
- **Logic Placement**: Non-UI logic (e.g., model orchestration, tool
|
||||
implementation, git/filesystem operations) MUST reside in `packages/core`.
|
||||
`packages/cli` should ONLY contain UI/Ink components, command-line argument
|
||||
parsing, and user interaction logic.
|
||||
- **Environment Isolation**: Core logic must not assume a TUI environment. Use
|
||||
the `ConfirmationBus` or `Output` abstractions for communicating with the user
|
||||
from Core.
|
||||
- **Decoupling**: Actively look for opportunities to decouple services using
|
||||
`coreEvents`. If a service imports another just to notify it of a change, use
|
||||
an event instead.
|
||||
* **Logic Placement**: Non-UI logic (e.g., model orchestration, tool implementation, git/filesystem operations) MUST reside in `packages/core`. `packages/cli` should ONLY contain UI/Ink components, command-line argument parsing, and user interaction logic.
|
||||
* **Environment Isolation**: Core logic must not assume a TUI environment. Use the `ConfirmationBus` or `Output` abstractions for communicating with the user from Core.
|
||||
* **Decoupling**: Actively look for opportunities to decouple services using `coreEvents`. If a service imports another just to notify it of a change, use an event instead.
|
||||
|
||||
## General Gemini CLI Design Principles
|
||||
|
||||
- **Settings**: Use settings for user-configurable options rather than adding
|
||||
new command line arguments. Add new settings to
|
||||
`packages/cli/src/config/settingsSchema.ts`. If a setting has
|
||||
`showInDialog: true`, it MUST be documented in
|
||||
`docs/get-started/configuration.md`. Ensure `requiresRestart` is correctly
|
||||
set.
|
||||
- **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging.
|
||||
- **Keyboard Shortcuts**: Define all new keyboard shortcuts in
|
||||
`packages/cli/src/config/keyBindings.ts` and document them in
|
||||
`docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the
|
||||
`Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid
|
||||
function keys and shortcuts commonly bound in VSCode.
|
||||
* **Settings**: Use settings for user-configurable options rather than adding new command line arguments. Add new settings to `packages/cli/src/config/settingsSchema.ts`. If a setting has `showInDialog: true`, it MUST be documented in `docs/get-started/configuration.md`. Ensure `requiresRestart` is correctly set.
|
||||
* **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging.
|
||||
* **Keyboard Shortcuts**: Define all new keyboard shortcuts in `packages/cli/src/config/keyBindings.ts` and document them in `docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the `Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid function keys and shortcuts commonly bound in VSCode.
|
||||
|
||||
## TypeScript Best Practices
|
||||
|
||||
- Use `checkExhaustive` in the `default` clause of `switch` statements to ensure
|
||||
all cases are handled.
|
||||
- Avoid using the non-null assertion operator (`!`) unless absolutely necessary.
|
||||
- **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core
|
||||
packages. `unknown` is only allowed if it is immediately narrowed using type
|
||||
guards or Zod validation.
|
||||
- NEVER disable `@typescript-eslint/no-floating-promises`.
|
||||
- Avoid making types nullable unless strictly necessary, as it hurts
|
||||
readability.
|
||||
* Use `checkExhaustive` in the `default` clause of `switch` statements to ensure all cases are handled.
|
||||
* Avoid using the non-null assertion operator (`!`) unless absolutely necessary.
|
||||
* **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core packages. `unknown` is only allowed if it is immediately narrowed using type guards or Zod validation.
|
||||
* NEVER disable `@typescript-eslint/no-floating-promises`.
|
||||
* Avoid making types nullable unless strictly necessary, as it hurts readability.
|
||||
|
||||
## TUI Best Practices
|
||||
|
||||
- **Terminal Compatibility**: Consider how changes might behave differently
|
||||
across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal,
|
||||
iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply
|
||||
with existing files like `KeypressContext.tsx` and
|
||||
`terminalCapabilityManager.ts`.
|
||||
- **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run
|
||||
VSCode from within iTerm, even if the terminal is not iTerm.
|
||||
* **Terminal Compatibility**: Consider how changes might behave differently across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal, iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply with existing files like `KeypressContext.tsx` and `terminalCapabilityManager.ts`.
|
||||
* **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run VSCode from within iTerm, even if the terminal is not iTerm.
|
||||
|
||||
## Code Cleanup
|
||||
|
||||
- **Refactoring**: Actively clean up code duplication, technical debt, and
|
||||
boilerplate ("AI Slop") when working in the codebase.
|
||||
- **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI
|
||||
and affect overall quality.
|
||||
* **Refactoring**: Actively clean up code duplication, technical debt, and boilerplate ("AI Slop") when working in the codebase.
|
||||
* **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI and affect overall quality.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"experimental": {
|
||||
"plan": true,
|
||||
"extensionReloading": true,
|
||||
"modelSteering": true
|
||||
"extensionReloading": true
|
||||
},
|
||||
"general": {
|
||||
"devtools": true
|
||||
|
||||
@@ -23,8 +23,6 @@ To standardize the process of updating changelog files (`latest.md`,
|
||||
## Guidelines for `latest.md` and `preview.md` Highlights
|
||||
|
||||
- Aim for **3-5 key highlight points**.
|
||||
- Each highlight point must start with a bold-typed title that summarizes the
|
||||
change (e.g., `**New Feature:** A brief description...`).
|
||||
- **Prioritize** summarizing new features over other changes like bug fixes or
|
||||
chores.
|
||||
- **Avoid** mentioning features that are "experimental" or "in preview" in
|
||||
@@ -59,10 +57,6 @@ To standardize the process of updating changelog files (`latest.md`,
|
||||
|
||||
*Use this path if the version number ends in `.0`.*
|
||||
|
||||
**Important:** Based on the version, you must choose to follow either section
|
||||
A.1 for stable releases or A.2 for preview releases. Do not follow the
|
||||
instructions for the other section.
|
||||
|
||||
### A.1: Stable Release (e.g., `v0.28.0`)
|
||||
|
||||
For a stable release, you will generate two distinct summaries from the
|
||||
@@ -71,14 +65,11 @@ detailed **highlights** section for the release-specific page.
|
||||
|
||||
1. **Create the Announcement for `index.md`**:
|
||||
- Generate a concise announcement summarizing the most important changes.
|
||||
Each announcement entry must start with a bold-typed title that
|
||||
summarizes the change.
|
||||
- **Important**: The format for this announcement is unique. You **must**
|
||||
use the existing announcements in `docs/changelogs/index.md` and the
|
||||
example within
|
||||
`.gemini/skills/docs-changelog/references/index_template.md` as your
|
||||
guide. This format includes PR links and authors. Stick to 1 or 2 PR
|
||||
links and authors.
|
||||
guide. This format includes PR links and authors.
|
||||
- Add this new announcement to the top of `docs/changelogs/index.md`.
|
||||
|
||||
2. **Create Highlights and Update `latest.md`**:
|
||||
@@ -110,57 +101,31 @@ detailed **highlights** section for the release-specific page.
|
||||
|
||||
*Use this path if the version number does **not** end in `.0`.*
|
||||
|
||||
**Important:** Based on the version, you must choose to follow either section
|
||||
B.1 for stable patches or B.2 for preview patches. Do not follow the
|
||||
instructions for the other section.
|
||||
|
||||
### B.1: Stable Patch (e.g., `v0.28.1`)
|
||||
|
||||
- **Target File**: `docs/changelogs/latest.md`
|
||||
- Perform the following edits on the target file:
|
||||
1. Update the version in the main header. The line should read,
|
||||
`# Latest stable release: {{version}}`
|
||||
2. Update the rease date. The line should read,
|
||||
`Released: {{release_date_month_dd_yyyy}}`
|
||||
3. Determine if a "What's Changed" section exists in the temporary file
|
||||
If so, continue to step 4. Otherwise, skip to step 5.
|
||||
4. **Prepend** the processed "What's Changed" list from the temporary file
|
||||
to the existing "What's Changed" list in `latest.md`. Do not change or
|
||||
replace the existing list, **only add** to the beginning of it.
|
||||
5. In the "Full Changelog", edit **only** the end of the URL. Identify the
|
||||
last part of the URL that looks like `...{previous_version}` and update
|
||||
it to be `...{version}`.
|
||||
|
||||
Example: assume the patch version is `v0.29.1`. Change
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.0`
|
||||
to
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.1`
|
||||
1. Update the version in the main header.
|
||||
2. Update the "Released:" date.
|
||||
3. **Prepend** the processed "What's Changed" list from the temporary file
|
||||
to the existing "What's Changed" list in the file.
|
||||
4. In the "Full Changelog" URL, replace only the trailing version with the
|
||||
new patch version.
|
||||
|
||||
### B.2: Preview Patch (e.g., `v0.29.0-preview.3`)
|
||||
|
||||
- **Target File**: `docs/changelogs/preview.md`
|
||||
- Perform the following edits on the target file:
|
||||
1. Update the version in the main header. The line should read,
|
||||
`# Preview release: {{version}}`
|
||||
2. Update the rease date. The line should read,
|
||||
`Released: {{release_date_month_dd_yyyy}}`
|
||||
3. Determine if a "What's Changed" section exists in the temporary file
|
||||
If so, continue to step 4. Otherwise, skip to step 5.
|
||||
4. **Prepend** the processed "What's Changed" list from the temporary file
|
||||
to the existing "What's Changed" list in `preview.md`. Do not change or
|
||||
replace the existing list, **only add** to the beginning of it.
|
||||
5. In the "Full Changelog", edit **only** the end of the URL. Identify the
|
||||
last part of the URL that looks like `...{previous_version}` and update
|
||||
it to be `...{version}`.
|
||||
|
||||
Example: assume the patch version is `v0.29.0-preview.1`. Change
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.0-preview.0`
|
||||
to
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.0-preview.1`
|
||||
1. Update the version in the main header.
|
||||
2. Update the "Released:" date.
|
||||
3. **Prepend** the processed "What's Changed" list from the temporary file
|
||||
to the existing "What's Changed" list in the file.
|
||||
4. In the "Full Changelog" URL, replace only the trailing version with the
|
||||
new patch version.
|
||||
|
||||
---
|
||||
|
||||
## Finalize
|
||||
|
||||
- After making changes, run `npm run format` ONLY to ensure consistency.
|
||||
- After making changes, run `npm run format` to ensure consistency.
|
||||
- Delete any temporary files created during the process.
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
name: pr-address-comments
|
||||
description: Use this skill if the user asks you to help them address GitHub PR comments for their current branch of the Gemini CLI. Requires `gh` CLI tool.
|
||||
---
|
||||
You are helping the user address comments on their Pull Request. These comments may have come from an automated review agent or a team member.
|
||||
|
||||
OBJECTIVE: Help the user review and address comments on their PR.
|
||||
|
||||
# Comment Review Procedure
|
||||
|
||||
1. Run the `scripts/fetch-pr-info.js` script to get PR info and state. MAKE SURE you read the entire output of the command, even if it gets truncated.
|
||||
2. Summarize the review status by analyzing the diff, commit log, and comments to see which still need to be addressed. Pay attention to the current user's comments. For resolved threads, summarize as a single line with a ✅. For open threads, provide a reference number e.g. [1] and the comment content.
|
||||
3. Present your summary of the feedback and current state and allow the user to guide you as to what to fix/address/skip. DO NOT begin fixing issues automatically.
|
||||
@@ -1,160 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* eslint-env node */
|
||||
/* global console, process */
|
||||
|
||||
import { exec } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
async function run(cmd) {
|
||||
try {
|
||||
const { stdout } = await execAsync(cmd, {
|
||||
encoding: 'utf8',
|
||||
stdio: ['pipe', 'pipe', 'ignore'],
|
||||
});
|
||||
return stdout.trim();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const IGNORE_MESSAGES = [
|
||||
'thank you so much for your contribution to Gemini CLI!',
|
||||
"I'm currently reviewing this pull request and will post my feedback shortly.",
|
||||
'This pull request is being closed because it is not currently linked to an issue.',
|
||||
];
|
||||
|
||||
const shouldIgnore = (body) => {
|
||||
if (!body) return false;
|
||||
return IGNORE_MESSAGES.some((msg) => body.includes(msg));
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const branch = await run('git branch --show-current');
|
||||
if (!branch) {
|
||||
console.error('❌ Could not determine current git branch.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const gqlQuery = `query($branch:String!){repository(name:"gemini-cli",owner:"google-gemini"){pullRequests(headRefName:$branch,first:100){nodes{id,number,state,comments(first:100){nodes{createdAt,isMinimized,minimizedReason,author{login},body,url,authorAssociation}},reviews(first:100){nodes{id,author{login},createdAt,isMinimized,minimizedReason,body,state,comments(first:30){nodes{id,replyTo{id},author{login},createdAt,body,isMinimized,minimizedReason,path,line,startLine,originalLine,originalStartLine}}}}}}}}`;
|
||||
|
||||
const [authInfo, diff, commits, rawJson] = await Promise.all([
|
||||
run('gh auth status -a'),
|
||||
run('gh pr diff'),
|
||||
run(
|
||||
'git fetch && git log origin/main..origin/$(git branch --show-current)',
|
||||
),
|
||||
run(`gh api graphql -F branch="${branch}" -f query='${gqlQuery}'`),
|
||||
]);
|
||||
|
||||
if (!diff) {
|
||||
console.error(`⚠️ No active PR found for branch: ${branch}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`\n# Current GitHub user info:\n\n${authInfo}\n`);
|
||||
console.log(`\n# PR diff for current branch: ${branch}\n\n\`\`\``);
|
||||
console.log(diff);
|
||||
console.log('```');
|
||||
console.log(
|
||||
`\n# Commit history (origin/main..origin/${branch})\n\n${commits}`,
|
||||
);
|
||||
|
||||
const data = JSON.parse(rawJson || '{}');
|
||||
const prs = data?.data?.repository?.pullRequests?.nodes || [];
|
||||
|
||||
// Sort PRs by number descending so we check the newest one first
|
||||
prs.sort((a, b) => b.number - a.number);
|
||||
|
||||
const pr = prs.find((p) => p.state === 'OPEN') || prs[0];
|
||||
|
||||
if (!pr) {
|
||||
console.error('❌ No PR data found.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('\n# PR Feedback\n');
|
||||
|
||||
// 1. General PR Comments
|
||||
const general = pr.comments.nodes.filter((c) => !shouldIgnore(c.body));
|
||||
if (general.length > 0) {
|
||||
console.log('\n💬 GENERAL COMMENTS:');
|
||||
general.forEach((c) => {
|
||||
const minimized = c.isMinimized
|
||||
? ` (Minimized: ${c.minimizedReason})`
|
||||
: '';
|
||||
console.log(
|
||||
`[${c.createdAt}] [${c.author.login}]${minimized}: ${c.body}\n`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Process ALL Review Comments into a single Thread Map
|
||||
const allInlineComments = pr.reviews.nodes.flatMap((r) => r.comments.nodes);
|
||||
const filteredInlines = allInlineComments.filter(
|
||||
(c) => !shouldIgnore(c.body),
|
||||
);
|
||||
|
||||
console.log('🔍 CODE REVIEWS & INLINE THREADS:');
|
||||
|
||||
// Print Review Summaries First
|
||||
pr.reviews.nodes.forEach((review) => {
|
||||
if (review.body && !shouldIgnore(review.body)) {
|
||||
const icon = review.state === 'APPROVED' ? '✅' : '💬';
|
||||
const minimized = review.isMinimized
|
||||
? ` (Minimized: ${review.minimizedReason})`
|
||||
: '';
|
||||
console.log(
|
||||
`\n${icon} ${review.state} by ${review.author.login} at ${review.createdAt}${minimized}: "${review.body}"`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Build and Print Threads
|
||||
const topLevelThreads = filteredInlines.filter((c) => !c.replyTo);
|
||||
|
||||
const printThread = (parentId, depth = 1) => {
|
||||
const indent = ' '.repeat(depth);
|
||||
filteredInlines
|
||||
.filter((c) => c.replyTo?.id === parentId)
|
||||
.forEach((reply) => {
|
||||
const minimized = reply.isMinimized
|
||||
? ` (Minimized: ${reply.minimizedReason})`
|
||||
: '';
|
||||
console.log(
|
||||
`${indent}↳ [${reply.createdAt}] ${reply.author.login}${minimized}: ${reply.body}`,
|
||||
);
|
||||
printThread(reply.id, depth + 1);
|
||||
});
|
||||
};
|
||||
|
||||
topLevelThreads.forEach((c) => {
|
||||
const start = c.startLine || c.originalStartLine;
|
||||
const end = c.line || c.originalLine;
|
||||
const range = start && end && start !== end ? `${start}-${end}` : end || '';
|
||||
const fileInfo = c.path
|
||||
? `(${c.path}${range ? `:${range}` : ''}) `
|
||||
: range
|
||||
? `(Line ${range}) `
|
||||
: '';
|
||||
const minimized = c.isMinimized ? ` (Minimized: ${c.minimizedReason})` : '';
|
||||
console.log(
|
||||
`\n💬 ${minimized}${c.author.login} | ${c.createdAt} ${fileInfo}\n${c.body}`,
|
||||
);
|
||||
printThread(c.id);
|
||||
});
|
||||
|
||||
console.log('\n');
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('❌ Unexpected error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -39,22 +39,18 @@ runs:
|
||||
if: "inputs.dry-run != 'true'"
|
||||
env:
|
||||
GH_TOKEN: '${{ inputs.github-token }}'
|
||||
INPUTS_BRANCH_NAME: '${{ inputs.branch-name }}'
|
||||
INPUTS_PR_TITLE: '${{ inputs.pr-title }}'
|
||||
INPUTS_PR_BODY: '${{ inputs.pr-body }}'
|
||||
INPUTS_BASE_BRANCH: '${{ inputs.base-branch }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
set -e
|
||||
if ! git ls-remote --exit-code --heads origin "${INPUTS_BRANCH_NAME}"; then
|
||||
echo "::error::Branch '${INPUTS_BRANCH_NAME}' does not exist on the remote repository."
|
||||
if ! git ls-remote --exit-code --heads origin "${{ inputs.branch-name }}"; then
|
||||
echo "::error::Branch '${{ inputs.branch-name }}' does not exist on the remote repository."
|
||||
exit 1
|
||||
fi
|
||||
PR_URL=$(gh pr create \
|
||||
--title "${INPUTS_PR_TITLE}" \
|
||||
--body "${INPUTS_PR_BODY}" \
|
||||
--base "${INPUTS_BASE_BRANCH}" \
|
||||
--head "${INPUTS_BRANCH_NAME}" \
|
||||
--title "${{ inputs.pr-title }}" \
|
||||
--body "${{ inputs.pr-body }}" \
|
||||
--base "${{ inputs.base-branch }}" \
|
||||
--head "${{ inputs.branch-name }}" \
|
||||
--fill)
|
||||
gh pr merge "$PR_URL" --auto
|
||||
|
||||
@@ -30,22 +30,16 @@ runs:
|
||||
id: 'npm_auth_token'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
AUTH_TOKEN="${INPUTS_GITHUB_TOKEN}"
|
||||
PACKAGE_NAME="${INPUTS_PACKAGE_NAME}"
|
||||
AUTH_TOKEN="${{ inputs.github-token }}"
|
||||
PACKAGE_NAME="${{ inputs.package-name }}"
|
||||
PRIVATE_REPO="@google-gemini/"
|
||||
if [[ "$PACKAGE_NAME" == "$PRIVATE_REPO"* ]]; then
|
||||
AUTH_TOKEN="${INPUTS_GITHUB_TOKEN}"
|
||||
AUTH_TOKEN="${{ inputs.github-token }}"
|
||||
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli" ]]; then
|
||||
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_CLI}"
|
||||
AUTH_TOKEN="${{ inputs.wombat-token-cli }}"
|
||||
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli-core" ]]; then
|
||||
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_CORE}"
|
||||
AUTH_TOKEN="${{ inputs.wombat-token-core }}"
|
||||
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli-a2a-server" ]]; then
|
||||
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_A2A_SERVER}"
|
||||
AUTH_TOKEN="${{ inputs.wombat-token-a2a-server }}"
|
||||
fi
|
||||
echo "auth-token=$AUTH_TOKEN" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
INPUTS_GITHUB_TOKEN: '${{ inputs.github-token }}'
|
||||
INPUTS_PACKAGE_NAME: '${{ inputs.package-name }}'
|
||||
INPUTS_WOMBAT_TOKEN_CLI: '${{ inputs.wombat-token-cli }}'
|
||||
INPUTS_WOMBAT_TOKEN_CORE: '${{ inputs.wombat-token-core }}'
|
||||
INPUTS_WOMBAT_TOKEN_A2A_SERVER: '${{ inputs.wombat-token-a2a-server }}'
|
||||
|
||||
@@ -93,19 +93,15 @@ runs:
|
||||
id: 'release_branch'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
BRANCH_NAME="release/${INPUTS_RELEASE_TAG}"
|
||||
BRANCH_NAME="release/${{ inputs.release-tag }}"
|
||||
git switch -c "${BRANCH_NAME}"
|
||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
|
||||
env:
|
||||
INPUTS_RELEASE_TAG: '${{ inputs.release-tag }}'
|
||||
|
||||
- name: '⬆️ Update package versions'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm run release:version "${INPUTS_RELEASE_VERSION}"
|
||||
env:
|
||||
INPUTS_RELEASE_VERSION: '${{ inputs.release-version }}'
|
||||
npm run release:version "${{ inputs.release-version }}"
|
||||
|
||||
- name: '💾 Commit and Conditionally Push package versions'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
@@ -167,30 +163,23 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}'
|
||||
INPUTS_DRY_RUN: '${{ inputs.dry-run }}'
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_CORE_PACKAGE_NAME}" \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.core-package-name }}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${INPUTS_CORE_PACKAGE_NAME} false --silent
|
||||
npm dist-tag rm ${{ inputs.core-package-name }} false --silent
|
||||
|
||||
- name: '🔗 Install latest core package'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
if: "${{ inputs.dry-run != 'true' }}"
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm install "${INPUTS_CORE_PACKAGE_NAME}@${INPUTS_RELEASE_VERSION}" \
|
||||
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \
|
||||
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \
|
||||
npm install "${{ inputs.core-package-name }}@${{ inputs.release-version }}" \
|
||||
--workspace="${{ inputs.cli-package-name }}" \
|
||||
--workspace="${{ inputs.a2a-package-name }}" \
|
||||
--save-exact
|
||||
env:
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
INPUTS_RELEASE_VERSION: '${{ inputs.release-version }}'
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
|
||||
- name: 'Get CLI Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -206,15 +195,13 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}'
|
||||
INPUTS_DRY_RUN: '${{ inputs.dry-run }}'
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.cli-package-name }}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${INPUTS_CLI_PACKAGE_NAME} false --silent
|
||||
npm dist-tag rm ${{ inputs.cli-package-name }} false --silent
|
||||
|
||||
- name: 'Get a2a-server Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -230,16 +217,14 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}'
|
||||
INPUTS_DRY_RUN: '${{ inputs.dry-run }}'
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
shell: 'bash'
|
||||
# Tag staging for initial release
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.a2a-package-name }}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${INPUTS_A2A_PACKAGE_NAME} false --silent
|
||||
npm dist-tag rm ${{ inputs.a2a-package-name }} false --silent
|
||||
|
||||
- name: '🔬 Verify NPM release by version'
|
||||
uses: './.github/actions/verify-release'
|
||||
@@ -273,16 +258,13 @@ runs:
|
||||
if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' && inputs.npm-registry-url != 'https://npm.pkg.github.com/' }}"
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ inputs.github-release-token || inputs.github-token }}'
|
||||
INPUTS_RELEASE_TAG: '${{ inputs.release-tag }}'
|
||||
STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
INPUTS_PREVIOUS_TAG: '${{ inputs.previous-tag }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
gh release create "${INPUTS_RELEASE_TAG}" \
|
||||
gh release create "${{ inputs.release-tag }}" \
|
||||
bundle/gemini.js \
|
||||
--target "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}" \
|
||||
--title "Release ${INPUTS_RELEASE_TAG}" \
|
||||
--notes-start-tag "${INPUTS_PREVIOUS_TAG}" \
|
||||
--target "${{ steps.release_branch.outputs.BRANCH_NAME }}" \
|
||||
--title "Release ${{ inputs.release-tag }}" \
|
||||
--notes-start-tag "${{ inputs.previous-tag }}" \
|
||||
--generate-notes \
|
||||
${{ inputs.npm-tag != 'latest' && '--prerelease' || '' }}
|
||||
|
||||
@@ -292,8 +274,5 @@ runs:
|
||||
continue-on-error: true
|
||||
shell: 'bash'
|
||||
run: |
|
||||
echo "Cleaning up release branch ${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}..."
|
||||
git push origin --delete "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}"
|
||||
|
||||
env:
|
||||
STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
echo "Cleaning up release branch ${{ steps.release_branch.outputs.BRANCH_NAME }}..."
|
||||
git push origin --delete "${{ steps.release_branch.outputs.BRANCH_NAME }}"
|
||||
|
||||
@@ -52,10 +52,8 @@ runs:
|
||||
id: 'branch_name'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
REF_NAME="${INPUTS_REF_NAME}"
|
||||
REF_NAME="${{ inputs.ref-name }}"
|
||||
echo "name=${REF_NAME%/merge}" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
INPUTS_REF_NAME: '${{ inputs.ref-name }}'
|
||||
- name: 'Build and Push the Docker Image'
|
||||
uses: 'docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83' # ratchet:docker/build-push-action@v6
|
||||
with:
|
||||
|
||||
@@ -56,8 +56,8 @@ runs:
|
||||
id: 'image_tag'
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
SHELL_TAG_NAME="${INPUTS_GITHUB_REF_NAME}"
|
||||
FINAL_TAG="${INPUTS_GITHUB_SHA}"
|
||||
SHELL_TAG_NAME="${{ inputs.github-ref-name }}"
|
||||
FINAL_TAG="${{ inputs.github-sha }}"
|
||||
if [[ "$SHELL_TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "Release detected."
|
||||
FINAL_TAG="${SHELL_TAG_NAME#v}"
|
||||
@@ -66,36 +66,22 @@ runs:
|
||||
fi
|
||||
echo "Determined image tag: $FINAL_TAG"
|
||||
echo "FINAL_TAG=$FINAL_TAG" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
INPUTS_GITHUB_REF_NAME: '${{ inputs.github-ref-name }}'
|
||||
INPUTS_GITHUB_SHA: '${{ inputs.github-sha }}'
|
||||
- name: 'build'
|
||||
id: 'docker_build'
|
||||
shell: 'bash'
|
||||
env:
|
||||
GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
GEMINI_SANDBOX: 'docker'
|
||||
STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
run: |-
|
||||
npm run build:sandbox -- \
|
||||
--image google/gemini-cli-sandbox:${STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG} \
|
||||
--image google/gemini-cli-sandbox:${{ steps.image_tag.outputs.FINAL_TAG }} \
|
||||
--output-file final_image_uri.txt
|
||||
echo "uri=$(cat final_image_uri.txt)" >> $GITHUB_OUTPUT
|
||||
- name: 'verify'
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
docker run --rm --entrypoint sh "${{ steps.docker_build.outputs.uri }}" -lc '
|
||||
set -e
|
||||
node -e "const fs=require(\"node:fs\"); JSON.parse(fs.readFileSync(\"/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json\",\"utf8\")); JSON.parse(fs.readFileSync(\"/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json\",\"utf8\"));"
|
||||
/usr/local/share/npm-global/bin/gemini --version >/dev/null
|
||||
'
|
||||
- name: 'publish'
|
||||
shell: 'bash'
|
||||
if: "${{ inputs.dry-run != 'true' }}"
|
||||
run: |-
|
||||
docker push "${STEPS_DOCKER_BUILD_OUTPUTS_URI}"
|
||||
env:
|
||||
STEPS_DOCKER_BUILD_OUTPUTS_URI: '${{ steps.docker_build.outputs.uri }}'
|
||||
docker push "${{ steps.docker_build.outputs.uri }}"
|
||||
- name: 'Create issue on failure'
|
||||
if: |-
|
||||
${{ failure() }}
|
||||
|
||||
@@ -18,7 +18,5 @@ runs:
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
echo ""@google-gemini:registry=https://npm.pkg.github.com"" > ~/.npmrc
|
||||
echo ""//npm.pkg.github.com/:_authToken=${INPUTS_GITHUB_TOKEN}"" >> ~/.npmrc
|
||||
echo ""//npm.pkg.github.com/:_authToken=${{ inputs.github-token }}"" >> ~/.npmrc
|
||||
echo ""@google:registry=https://wombat-dressing-room.appspot.com"" >> ~/.npmrc
|
||||
env:
|
||||
INPUTS_GITHUB_TOKEN: '${{ inputs.github-token }}'
|
||||
|
||||
@@ -71,13 +71,10 @@ runs:
|
||||
${{ inputs.dry-run != 'true' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}'
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
npm dist-tag add ${INPUTS_CORE_PACKAGE_NAME}@${INPUTS_VERSION} ${INPUTS_CHANNEL}
|
||||
npm dist-tag add ${{ inputs.core-package-name }}@${{ inputs.version }} ${{ inputs.channel }}
|
||||
|
||||
- name: 'Get cli Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -94,13 +91,10 @@ runs:
|
||||
${{ inputs.dry-run != 'true' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}'
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
npm dist-tag add ${INPUTS_CLI_PACKAGE_NAME}@${INPUTS_VERSION} ${INPUTS_CHANNEL}
|
||||
npm dist-tag add ${{ inputs.cli-package-name }}@${{ inputs.version }} ${{ inputs.channel }}
|
||||
|
||||
- name: 'Get a2a Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -117,13 +111,10 @@ runs:
|
||||
${{ inputs.dry-run == 'false' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}'
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
npm dist-tag add ${INPUTS_A2A_PACKAGE_NAME}@${INPUTS_VERSION} ${INPUTS_CHANNEL}
|
||||
npm dist-tag add ${{ inputs.a2a-package-name }}@${{ inputs.version }} ${{ inputs.channel }}
|
||||
|
||||
- name: 'Log dry run'
|
||||
if: |-
|
||||
@@ -131,15 +122,4 @@ runs:
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
echo "Dry run: Would have added tag '${INPUTS_CHANNEL}' to version '${INPUTS_VERSION}' for ${INPUTS_CLI_PACKAGE_NAME}, ${INPUTS_CORE_PACKAGE_NAME}, and ${INPUTS_A2A_PACKAGE_NAME}."
|
||||
|
||||
env:
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
echo "Dry run: Would have added tag '${{ inputs.channel }}' to version '${{ inputs.version }}' for ${{ inputs.cli-package-name }}, ${{ inputs.core-package-name }}, and ${{ inputs.a2a-package-name }}."
|
||||
|
||||
@@ -64,13 +64,10 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |-
|
||||
gemini_version=$(gemini --version)
|
||||
if [ "$gemini_version" != "${INPUTS_EXPECTED_VERSION}" ]; then
|
||||
echo "❌ NPM Version mismatch: Got $gemini_version from ${INPUTS_NPM_PACKAGE}, expected ${INPUTS_EXPECTED_VERSION}"
|
||||
if [ "$gemini_version" != "${{ inputs.expected-version }}" ]; then
|
||||
echo "❌ NPM Version mismatch: Got $gemini_version from ${{ inputs.npm-package }}, expected ${{ inputs.expected-version }}"
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
INPUTS_EXPECTED_VERSION: '${{ inputs.expected-version }}'
|
||||
INPUTS_NPM_PACKAGE: '${{ inputs.npm-package }}'
|
||||
|
||||
- name: 'Clear npm cache'
|
||||
shell: 'bash'
|
||||
@@ -80,14 +77,11 @@ runs:
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |-
|
||||
gemini_version=$(npx --prefer-online "${INPUTS_NPM_PACKAGE}" --version)
|
||||
if [ "$gemini_version" != "${INPUTS_EXPECTED_VERSION}" ]; then
|
||||
echo "❌ NPX Run Version mismatch: Got $gemini_version from ${INPUTS_NPM_PACKAGE}, expected ${INPUTS_EXPECTED_VERSION}"
|
||||
gemini_version=$(npx --prefer-online "${{ inputs.npm-package}}" --version)
|
||||
if [ "$gemini_version" != "${{ inputs.expected-version }}" ]; then
|
||||
echo "❌ NPX Run Version mismatch: Got $gemini_version from ${{ inputs.npm-package }}, expected ${{ inputs.expected-version }}"
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
INPUTS_NPM_PACKAGE: '${{ inputs.npm-package }}'
|
||||
INPUTS_EXPECTED_VERSION: '${{ inputs.expected-version }}'
|
||||
|
||||
- name: 'Install dependencies for integration tests'
|
||||
shell: 'bash'
|
||||
|
||||
@@ -22,7 +22,7 @@ get_issue_labels() {
|
||||
# Check cache
|
||||
case "${ISSUE_LABELS_CACHE_FLAT}" in
|
||||
*"|${ISSUE_NUM}:"*)
|
||||
local suffix="${ISSUE_LABELS_CACHE_FLAT#*|"${ISSUE_NUM}":}"
|
||||
local suffix="${ISSUE_LABELS_CACHE_FLAT#*|${ISSUE_NUM}:}"
|
||||
echo "${suffix%%|*}"
|
||||
return
|
||||
;;
|
||||
|
||||
@@ -31,7 +31,6 @@ jobs:
|
||||
name: 'Merge Queue Skipper'
|
||||
permissions: 'read-all'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
outputs:
|
||||
skip: '${{ steps.merge-queue-e2e-skipper.outputs.skip-check }}'
|
||||
steps:
|
||||
@@ -43,7 +42,7 @@ jobs:
|
||||
|
||||
download_repo_name:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run')"
|
||||
if: "${{github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run'}}"
|
||||
outputs:
|
||||
repo_name: '${{ steps.output-repo-name.outputs.repo_name }}'
|
||||
head_sha: '${{ steps.output-repo-name.outputs.head_sha }}'
|
||||
@@ -54,7 +53,7 @@ jobs:
|
||||
REPO_NAME: '${{ github.event.inputs.repo_name }}'
|
||||
run: |
|
||||
mkdir -p ./pr
|
||||
echo "${REPO_NAME}" > ./pr/repo_name
|
||||
echo '${{ env.REPO_NAME }}' > ./pr/repo_name
|
||||
- uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'repo_name'
|
||||
@@ -92,7 +91,7 @@ jobs:
|
||||
name: 'Parse run context'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'download_repo_name'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
outputs:
|
||||
repository: '${{ steps.set_context.outputs.REPO }}'
|
||||
sha: '${{ steps.set_context.outputs.SHA }}'
|
||||
@@ -112,11 +111,11 @@ jobs:
|
||||
permissions: 'write-all'
|
||||
needs:
|
||||
- 'parse_run_context'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
steps:
|
||||
- name: 'Set pending status'
|
||||
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
with:
|
||||
allowForks: 'true'
|
||||
repo: '${{ github.repository }}'
|
||||
@@ -132,7 +131,7 @@ jobs:
|
||||
- 'parse_run_context'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -185,7 +184,7 @@ jobs:
|
||||
- 'parse_run_context'
|
||||
runs-on: 'macos-latest'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -223,8 +222,10 @@ jobs:
|
||||
- 'merge_queue_skipper'
|
||||
- 'parse_run_context'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -283,7 +284,7 @@ jobs:
|
||||
- 'parse_run_context'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -310,42 +311,35 @@ jobs:
|
||||
e2e:
|
||||
name: 'E2E'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
needs:
|
||||
- 'e2e_linux'
|
||||
- 'e2e_mac'
|
||||
- 'e2e_windows'
|
||||
- 'evals'
|
||||
- 'merge_queue_skipper'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Check E2E test results'
|
||||
run: |
|
||||
if [[ ${NEEDS_E2E_LINUX_RESULT} != 'success' || \
|
||||
${NEEDS_E2E_MAC_RESULT} != 'success' || \
|
||||
${NEEDS_E2E_WINDOWS_RESULT} != 'success' || \
|
||||
${NEEDS_EVALS_RESULT} != 'success' ]]; then
|
||||
if [[ ${{ needs.e2e_linux.result }} != 'success' || \
|
||||
${{ needs.e2e_mac.result }} != 'success' || \
|
||||
${{ needs.evals.result }} != 'success' ]]; then
|
||||
echo "One or more E2E jobs failed."
|
||||
exit 1
|
||||
fi
|
||||
echo "All required E2E jobs passed!"
|
||||
env:
|
||||
NEEDS_E2E_LINUX_RESULT: '${{ needs.e2e_linux.result }}'
|
||||
NEEDS_E2E_MAC_RESULT: '${{ needs.e2e_mac.result }}'
|
||||
NEEDS_E2E_WINDOWS_RESULT: '${{ needs.e2e_windows.result }}'
|
||||
NEEDS_EVALS_RESULT: '${{ needs.evals.result }}'
|
||||
|
||||
set_workflow_status:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions: 'write-all'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
needs:
|
||||
- 'parse_run_context'
|
||||
- 'e2e'
|
||||
steps:
|
||||
- name: 'Set workflow status'
|
||||
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
with:
|
||||
allowForks: 'true'
|
||||
repo: '${{ github.repository }}'
|
||||
|
||||
+14
-25
@@ -37,7 +37,6 @@ jobs:
|
||||
permissions: 'read-all'
|
||||
name: 'Merge Queue Skipper'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
outputs:
|
||||
skip: '${{ steps.merge-queue-ci-skipper.outputs.skip-check }}'
|
||||
steps:
|
||||
@@ -50,7 +49,7 @@ jobs:
|
||||
name: 'Lint'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
env:
|
||||
GEMINI_LINT_TEMP_DIR: '${{ github.workspace }}/.gemini-linters'
|
||||
steps:
|
||||
@@ -117,7 +116,6 @@ jobs:
|
||||
link_checker:
|
||||
name: 'Link Checker'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
@@ -131,7 +129,7 @@ jobs:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs:
|
||||
- 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
@@ -218,7 +216,7 @@ jobs:
|
||||
runs-on: 'macos-latest'
|
||||
needs:
|
||||
- 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
@@ -313,7 +311,7 @@ jobs:
|
||||
name: 'CodeQL'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
permissions:
|
||||
actions: 'read'
|
||||
contents: 'read'
|
||||
@@ -336,7 +334,7 @@ jobs:
|
||||
bundle_size:
|
||||
name: 'Check Bundle Size'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && github.event_name == 'pull_request' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
if: "${{github.event_name == 'pull_request' && needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions:
|
||||
contents: 'read' # For checkout
|
||||
@@ -361,7 +359,8 @@ jobs:
|
||||
name: 'Slow Test - Win - ${{ matrix.shard }}'
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
continue-on-error: true
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -453,35 +452,25 @@ jobs:
|
||||
|
||||
ci:
|
||||
name: 'CI'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'link_checker'
|
||||
- 'test_linux'
|
||||
- 'test_mac'
|
||||
- 'test_windows'
|
||||
- 'codeql'
|
||||
- 'bundle_size'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Check all job results'
|
||||
run: |
|
||||
if [[ (${NEEDS_LINT_RESULT} != 'success' && ${NEEDS_LINT_RESULT} != 'skipped') || \
|
||||
(${NEEDS_LINK_CHECKER_RESULT} != 'success' && ${NEEDS_LINK_CHECKER_RESULT} != 'skipped') || \
|
||||
(${NEEDS_TEST_LINUX_RESULT} != 'success' && ${NEEDS_TEST_LINUX_RESULT} != 'skipped') || \
|
||||
(${NEEDS_TEST_MAC_RESULT} != 'success' && ${NEEDS_TEST_MAC_RESULT} != 'skipped') || \
|
||||
(${NEEDS_TEST_WINDOWS_RESULT} != 'success' && ${NEEDS_TEST_WINDOWS_RESULT} != 'skipped') || \
|
||||
(${NEEDS_CODEQL_RESULT} != 'success' && ${NEEDS_CODEQL_RESULT} != 'skipped') || \
|
||||
(${NEEDS_BUNDLE_SIZE_RESULT} != 'success' && ${NEEDS_BUNDLE_SIZE_RESULT} != 'skipped') ]]; then
|
||||
if [[ (${{ needs.lint.result }} != 'success' && ${{ needs.lint.result }} != 'skipped') || \
|
||||
(${{ needs.link_checker.result }} != 'success' && ${{ needs.link_checker.result }} != 'skipped') || \
|
||||
(${{ needs.test_linux.result }} != 'success' && ${{ needs.test_linux.result }} != 'skipped') || \
|
||||
(${{ needs.test_mac.result }} != 'success' && ${{ needs.test_mac.result }} != 'skipped') || \
|
||||
(${{ needs.codeql.result }} != 'success' && ${{ needs.codeql.result }} != 'skipped') || \
|
||||
(${{ needs.bundle_size.result }} != 'success' && ${{ needs.bundle_size.result }} != 'skipped') ]]; then
|
||||
echo "One or more CI jobs failed."
|
||||
exit 1
|
||||
fi
|
||||
echo "All CI jobs passed!"
|
||||
env:
|
||||
NEEDS_LINT_RESULT: '${{ needs.lint.result }}'
|
||||
NEEDS_LINK_CHECKER_RESULT: '${{ needs.link_checker.result }}'
|
||||
NEEDS_TEST_LINUX_RESULT: '${{ needs.test_linux.result }}'
|
||||
NEEDS_TEST_MAC_RESULT: '${{ needs.test_mac.result }}'
|
||||
NEEDS_TEST_WINDOWS_RESULT: '${{ needs.test_windows.result }}'
|
||||
NEEDS_CODEQL_RESULT: '${{ needs.codeql.result }}'
|
||||
NEEDS_BUNDLE_SIZE_RESULT: '${{ needs.bundle_size.result }}'
|
||||
|
||||
@@ -27,7 +27,6 @@ jobs:
|
||||
deflake_e2e_linux:
|
||||
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -69,16 +68,15 @@ jobs:
|
||||
VERBOSE: 'true'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
if [[ "${IS_DOCKER}" == "true" ]]; then
|
||||
npm run deflake:test:integration:sandbox:docker -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'"
|
||||
if [[ "${{ env.IS_DOCKER }}" == "true" ]]; then
|
||||
npm run deflake:test:integration:sandbox:docker -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
else
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'"
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
fi
|
||||
|
||||
deflake_e2e_mac:
|
||||
name: 'E2E Test (macOS)'
|
||||
runs-on: 'macos-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -111,12 +109,11 @@ jobs:
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
VERBOSE: 'true'
|
||||
run: |
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'"
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
|
||||
deflake_e2e_windows:
|
||||
name: 'Slow E2E - Win'
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
@@ -170,4 +167,4 @@ jobs:
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
shell: 'pwsh'
|
||||
run: |
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="$env:RUNS" -- --testNamePattern "'$env:TEST_NAME_PATTERN'"
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
name: 'Deploy GitHub Pages'
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
pages: 'write'
|
||||
id-token: 'write'
|
||||
|
||||
# Allow only one concurrent deployment, skipping runs queued between the run
|
||||
# in-progress and latest queued. However, do NOT cancel in-progress runs as we
|
||||
# want to allow these production deployments to complete.
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}'
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: |-
|
||||
${{ !contains(github.ref_name, 'nightly') }}
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
|
||||
- name: 'Setup Pages'
|
||||
uses: 'actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b' # ratchet:actions/configure-pages@v5
|
||||
|
||||
- name: 'Build with Jekyll'
|
||||
uses: 'actions/jekyll-build-pages@44a6e6beabd48582f863aeeb6cb2151cc1716697' # ratchet:actions/jekyll-build-pages@v1
|
||||
with:
|
||||
source: './'
|
||||
destination: './_site'
|
||||
|
||||
- name: 'Upload artifact'
|
||||
uses: 'actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa' # ratchet:actions/upload-pages-artifact@v3
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
name: 'github-pages'
|
||||
url: '${{ steps.deployment.outputs.page_url }}'
|
||||
runs-on: 'ubuntu-latest'
|
||||
needs: 'build'
|
||||
steps:
|
||||
- name: 'Deploy to GitHub Pages'
|
||||
id: 'deployment'
|
||||
uses: 'actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e' # ratchet:actions/deploy-pages@v4
|
||||
@@ -7,7 +7,6 @@ on:
|
||||
- 'docs/**'
|
||||
jobs:
|
||||
trigger-rebuild:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Trigger rebuild'
|
||||
|
||||
@@ -44,5 +44,5 @@ jobs:
|
||||
- name: 'Run evaluation'
|
||||
working-directory: '/app'
|
||||
run: |
|
||||
poetry run exp_run --experiment-mode=on-demand --branch-or-commit="${GITHUB_REF_NAME}" --model-name=gemini-2.5-pro --dataset=swebench_verified --concurrency=15
|
||||
poetry run exp_run --experiment-mode=on-demand --branch-or-commit=${{ github.ref_name }} --model-name=gemini-2.5-pro --dataset=swebench_verified --concurrency=15
|
||||
poetry run python agent_prototypes/scripts/parse_gcli_logs_experiment.py --experiment_dir=experiments/adhoc/gcli_temp_exp --gcs-bucket="${EVAL_GCS_BUCKET}" --gcs-path=gh_action_artifacts
|
||||
|
||||
@@ -23,12 +23,10 @@ jobs:
|
||||
evals:
|
||||
name: 'Evals (USUALLY_PASSING) nightly run'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
model:
|
||||
- 'gemini-3.1-pro-preview-customtools'
|
||||
- 'gemini-3-pro-preview'
|
||||
- 'gemini-3-flash-preview'
|
||||
- 'gemini-2.5-pro'
|
||||
@@ -63,7 +61,7 @@ jobs:
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
run: |
|
||||
CMD="npm run test:all_evals"
|
||||
PATTERN="${TEST_NAME_PATTERN}"
|
||||
PATTERN="${{ env.TEST_NAME_PATTERN }}"
|
||||
|
||||
if [[ -n "$PATTERN" ]]; then
|
||||
if [[ "$PATTERN" == *.ts || "$PATTERN" == *.js || "$PATTERN" == */* ]]; then
|
||||
@@ -86,7 +84,7 @@ jobs:
|
||||
aggregate-results:
|
||||
name: 'Aggregate Results'
|
||||
needs: ['evals']
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
if: 'always()'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
|
||||
@@ -155,10 +155,7 @@ jobs:
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
"target": "gcp"
|
||||
},
|
||||
"coreTools": [
|
||||
"run_shell_command(echo)"
|
||||
]
|
||||
}
|
||||
}
|
||||
prompt: |-
|
||||
## Role
|
||||
@@ -287,21 +284,8 @@ jobs:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// If no markdown block, try to find a raw JSON object in the output.
|
||||
// The CLI may include debug/log lines (e.g. telemetry init, YOLO mode)
|
||||
// before the actual JSON response.
|
||||
const jsonObjectMatch = rawOutput.match(/(\{[\s\S]*"labels_to_set"[\s\S]*\})/);
|
||||
if (jsonObjectMatch) {
|
||||
try {
|
||||
parsedLabels = JSON.parse(jsonObjectMatch[0]);
|
||||
} catch (extractError) {
|
||||
core.setFailed(`Found JSON-like content but failed to parse: ${extractError.message}\nRaw output: ${rawOutput}`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
core.setFailed(`Output is not valid JSON and does not contain extractable JSON.\nRaw output: ${rawOutput}`);
|
||||
return;
|
||||
}
|
||||
core.setFailed(`Output is not valid JSON and does not contain a JSON markdown block.\nRaw output: ${rawOutput}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ defaults:
|
||||
|
||||
jobs:
|
||||
close-stale-issues:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
issues: 'write'
|
||||
|
||||
@@ -48,24 +48,6 @@ jobs:
|
||||
const repo = context.repo.repo;
|
||||
const MAX_ISSUES_ASSIGNED = 3;
|
||||
|
||||
const issue = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
const hasHelpWantedLabel = issue.data.labels.some(label => label.name === 'help wanted');
|
||||
|
||||
if (!hasHelpWantedLabel) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issueNumber,
|
||||
body: `👋 @${commenter}, thanks for your interest in this issue! We're reserving self-assignment for issues that have been marked with the \`help wanted\` label. Feel free to check out our list of [issues that need attention](https://github.com/google-gemini/gemini-cli/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for open issues already assigned to the commenter in this repo
|
||||
const { data: assignedIssues } = await github.rest.search.issuesAndPullRequests({
|
||||
q: `is:issue repo:${owner}/${repo} assignee:${commenter} is:open`,
|
||||
@@ -82,6 +64,13 @@ jobs:
|
||||
return; // exit
|
||||
}
|
||||
|
||||
// Check if the issue is already assigned
|
||||
const issue = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
if (issue.data.assignees.length > 0) {
|
||||
// Comment that it's already assigned
|
||||
await github.rest.issues.createComment({
|
||||
|
||||
@@ -14,7 +14,7 @@ permissions:
|
||||
jobs:
|
||||
# Event-based: Quick reaction to new/edited issues in THIS repo
|
||||
labeler:
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && github.event_name == 'issues'"
|
||||
if: "github.event_name == 'issues'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
# Scheduled/Manual: Recursive sync across multiple repos
|
||||
sync-maintainer-labels:
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')"
|
||||
if: "github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
|
||||
@@ -9,7 +9,6 @@ on:
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
issues: 'write'
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: 'PR rate limiter'
|
||||
|
||||
permissions: {}
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
|
||||
jobs:
|
||||
limit:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
pull-requests: 'write'
|
||||
steps:
|
||||
- name: 'Limit open pull requests per user'
|
||||
uses: 'Homebrew/actions/limit-pull-requests@9ceb7934560eb61d131dde205a6c2d77b2e1529d' # master
|
||||
with:
|
||||
except-author-associations: 'MEMBER,OWNER,COLLABORATOR'
|
||||
comment-limit: 8
|
||||
comment: >
|
||||
You already have 7 pull requests open. Please work on getting
|
||||
existing PRs merged before opening more.
|
||||
close-limit: 8
|
||||
close: true
|
||||
@@ -32,7 +32,6 @@ on:
|
||||
|
||||
jobs:
|
||||
change-tags:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
|
||||
@@ -47,7 +47,6 @@ on:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
|
||||
@@ -22,7 +22,6 @@ on:
|
||||
|
||||
jobs:
|
||||
generate-release-notes:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'write'
|
||||
@@ -33,7 +32,6 @@ jobs:
|
||||
with:
|
||||
# The user-level skills need to be available to the workflow
|
||||
fetch-depth: 0
|
||||
ref: 'main'
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@v4'
|
||||
@@ -44,6 +42,7 @@ jobs:
|
||||
id: 'release_info'
|
||||
run: |
|
||||
VERSION="${{ github.event.inputs.version || github.event.release.tag_name }}"
|
||||
BODY="${{ github.event.inputs.body || github.event.release.body }}"
|
||||
TIME="${{ github.event.inputs.time || github.event.release.created_at }}"
|
||||
|
||||
echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
@@ -51,24 +50,12 @@ jobs:
|
||||
|
||||
# Use a heredoc to preserve multiline release body
|
||||
echo 'RAW_CHANGELOG<<EOF' >> "$GITHUB_OUTPUT"
|
||||
printf "%s\n" "$BODY" >> "$GITHUB_OUTPUT"
|
||||
printf "%s\n" "${BODY}" >> "$GITHUB_OUTPUT"
|
||||
echo 'EOF' >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
BODY: '${{ github.event.inputs.body || github.event.release.body }}'
|
||||
|
||||
- name: 'Validate version'
|
||||
id: 'validate_version'
|
||||
run: |
|
||||
if echo "${{ steps.release_info.outputs.VERSION }}" | grep -q "nightly"; then
|
||||
echo "Nightly release detected. Stopping workflow."
|
||||
echo "CONTINUE=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "CONTINUE=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: 'Generate Changelog with Gemini'
|
||||
if: "steps.validate_version.outputs.CONTINUE == 'true'"
|
||||
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0
|
||||
with:
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
@@ -82,10 +69,7 @@ jobs:
|
||||
|
||||
Execute the release notes generation process using the information provided.
|
||||
|
||||
When you are done, please output your thought process and the steps you took for future debugging purposes.
|
||||
|
||||
- name: 'Create Pull Request'
|
||||
if: "steps.validate_version.outputs.CONTINUE == 'true'"
|
||||
uses: 'peter-evans/create-pull-request@v6'
|
||||
with:
|
||||
token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
|
||||
@@ -118,7 +118,6 @@ jobs:
|
||||
ORIGINAL_RELEASE_VERSION: '${{ steps.patch_version.outputs.RELEASE_VERSION }}'
|
||||
ORIGINAL_RELEASE_TAG: '${{ steps.patch_version.outputs.RELEASE_TAG }}'
|
||||
ORIGINAL_PREVIOUS_TAG: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
|
||||
VARS_CLI_PACKAGE_NAME: '${{ vars.CLI_PACKAGE_NAME }}'
|
||||
run: |
|
||||
echo "🔍 Verifying no concurrent patch releases have occurred..."
|
||||
|
||||
@@ -130,7 +129,7 @@ jobs:
|
||||
|
||||
# Re-run the same version calculation script
|
||||
echo "Re-calculating version to check for changes..."
|
||||
CURRENT_PATCH_JSON=$(node scripts/get-release-version.js --cli-package-name="${VARS_CLI_PACKAGE_NAME}" --type=patch --patch-from="${CHANNEL}")
|
||||
CURRENT_PATCH_JSON=$(node scripts/get-release-version.js --cli-package-name="${{vars.CLI_PACKAGE_NAME}}" --type=patch --patch-from="${CHANNEL}")
|
||||
CURRENT_RELEASE_VERSION=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseVersion)
|
||||
CURRENT_RELEASE_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseTag)
|
||||
CURRENT_PREVIOUS_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .previousReleaseTag)
|
||||
@@ -163,15 +162,10 @@ jobs:
|
||||
- name: 'Print Calculated Version'
|
||||
run: |-
|
||||
echo "Patch Release Summary:"
|
||||
echo " Release Version: ${STEPS_PATCH_VERSION_OUTPUTS_RELEASE_VERSION}"
|
||||
echo " Release Tag: ${STEPS_PATCH_VERSION_OUTPUTS_RELEASE_TAG}"
|
||||
echo " NPM Tag: ${STEPS_PATCH_VERSION_OUTPUTS_NPM_TAG}"
|
||||
echo " Previous Tag: ${STEPS_PATCH_VERSION_OUTPUTS_PREVIOUS_TAG}"
|
||||
env:
|
||||
STEPS_PATCH_VERSION_OUTPUTS_RELEASE_VERSION: '${{ steps.patch_version.outputs.RELEASE_VERSION }}'
|
||||
STEPS_PATCH_VERSION_OUTPUTS_RELEASE_TAG: '${{ steps.patch_version.outputs.RELEASE_TAG }}'
|
||||
STEPS_PATCH_VERSION_OUTPUTS_NPM_TAG: '${{ steps.patch_version.outputs.NPM_TAG }}'
|
||||
STEPS_PATCH_VERSION_OUTPUTS_PREVIOUS_TAG: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
|
||||
echo " Release Version: ${{ steps.patch_version.outputs.RELEASE_VERSION }}"
|
||||
echo " Release Tag: ${{ steps.patch_version.outputs.RELEASE_TAG }}"
|
||||
echo " NPM Tag: ${{ steps.patch_version.outputs.NPM_TAG }}"
|
||||
echo " Previous Tag: ${{ steps.patch_version.outputs.PREVIOUS_TAG }}"
|
||||
|
||||
- name: 'Run Tests'
|
||||
if: "${{github.event.inputs.force_skip_tests != 'true'}}"
|
||||
|
||||
@@ -362,28 +362,23 @@ jobs:
|
||||
- name: 'Create and switch to a new branch'
|
||||
id: 'release_branch'
|
||||
run: |
|
||||
BRANCH_NAME="chore/nightly-version-bump-${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"
|
||||
BRANCH_NAME="chore/nightly-version-bump-${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}"
|
||||
git switch -c "${BRANCH_NAME}"
|
||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
|
||||
env:
|
||||
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
|
||||
|
||||
- name: 'Update package versions'
|
||||
run: 'npm run release:version "${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"'
|
||||
env:
|
||||
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
|
||||
run: 'npm run release:version "${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}"'
|
||||
|
||||
- name: 'Commit and Push package versions'
|
||||
env:
|
||||
BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
DRY_RUN: '${{ github.event.inputs.dry_run }}'
|
||||
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
|
||||
run: |-
|
||||
git add package.json packages/*/package.json
|
||||
if [ -f package-lock.json ]; then
|
||||
git add package-lock.json
|
||||
fi
|
||||
git commit -m "chore(release): bump version to ${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"
|
||||
git commit -m "chore(release): bump version to ${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}"
|
||||
if [[ "${DRY_RUN}" == "false" ]]; then
|
||||
echo "Pushing release branch to remote..."
|
||||
git push --set-upstream origin "${BRANCH_NAME}"
|
||||
|
||||
@@ -42,7 +42,6 @@ on:
|
||||
|
||||
jobs:
|
||||
change-tags:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
@@ -204,7 +203,7 @@ jobs:
|
||||
run: |
|
||||
ROLLBACK_COMMIT=$(git rev-parse -q --verify "$TARGET_TAG")
|
||||
if [ "$ROLLBACK_COMMIT" != "$TARGET_HASH" ]; then
|
||||
echo "❌ Failed to add tag ${TARGET_TAG} to commit ${TARGET_HASH}"
|
||||
echo '❌ Failed to add tag $TARGET_TAG to commit $TARGET_HASH'
|
||||
echo '❌ This means the tag was not added, and the workflow should fail.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -16,7 +16,6 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
@@ -20,7 +20,6 @@ on:
|
||||
|
||||
jobs:
|
||||
smoke-test:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'write'
|
||||
|
||||
@@ -15,7 +15,6 @@ on:
|
||||
|
||||
jobs:
|
||||
save_repo_name:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Save Repo name'
|
||||
@@ -24,15 +23,14 @@ jobs:
|
||||
HEAD_SHA: '${{ github.event.inputs.head_sha || github.event.pull_request.head.sha }}'
|
||||
run: |
|
||||
mkdir -p ./pr
|
||||
echo "${REPO_NAME}" > ./pr/repo_name
|
||||
echo "${HEAD_SHA}" > ./pr/head_sha
|
||||
echo '${{ env.REPO_NAME }}' > ./pr/repo_name
|
||||
echo '${{ env.HEAD_SHA }}' > ./pr/head_sha
|
||||
- uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'repo_name'
|
||||
path: 'pr/'
|
||||
trigger_e2e:
|
||||
name: 'Trigger e2e'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- id: 'trigger-e2e'
|
||||
|
||||
@@ -28,7 +28,6 @@ on:
|
||||
|
||||
jobs:
|
||||
verify-release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
+1
-2
@@ -46,7 +46,6 @@ packages/*/coverage/
|
||||
# Generated files
|
||||
packages/cli/src/generated/
|
||||
packages/core/src/generated/
|
||||
packages/devtools/src/_client-assets.ts
|
||||
.integration-tests/
|
||||
packages/vscode-ide-companion/*.vsix
|
||||
packages/cli/download-ripgrep*/
|
||||
@@ -61,4 +60,4 @@ gemini-debug.log
|
||||
.genkit
|
||||
.gemini-clipboard/
|
||||
.eslintcache
|
||||
evals/logs/
|
||||
evals/logs/
|
||||
|
||||
+7
-6
@@ -372,7 +372,8 @@ specific debug settings.
|
||||
|
||||
### React DevTools
|
||||
|
||||
To debug the CLI's React-based UI, you can use React DevTools.
|
||||
To debug the CLI's React-based UI, you can use React DevTools. Ink, the library
|
||||
used for the CLI's interface, is compatible with React DevTools version 4.x.
|
||||
|
||||
1. **Start the Gemini CLI in development mode:**
|
||||
|
||||
@@ -380,20 +381,20 @@ To debug the CLI's React-based UI, you can use React DevTools.
|
||||
DEV=true npm start
|
||||
```
|
||||
|
||||
2. **Install and run React DevTools version 6 (which matches the CLI's
|
||||
`react-devtools-core`):**
|
||||
2. **Install and run React DevTools version 4.28.5 (or the latest compatible
|
||||
4.x version):**
|
||||
|
||||
You can either install it globally:
|
||||
|
||||
```bash
|
||||
npm install -g react-devtools@6
|
||||
npm install -g react-devtools@4.28.5
|
||||
react-devtools
|
||||
```
|
||||
|
||||
Or run it directly using npx:
|
||||
|
||||
```bash
|
||||
npx react-devtools@6
|
||||
npx react-devtools@4.28.5
|
||||
```
|
||||
|
||||
Your running CLI application should then connect to React DevTools.
|
||||
@@ -545,7 +546,7 @@ Before submitting your documentation pull request, please:
|
||||
|
||||
If you have questions about contributing documentation:
|
||||
|
||||
- Check our [FAQ](/docs/resources/faq.md).
|
||||
- Check our [FAQ](/docs/resources/faq).
|
||||
- Review existing documentation for examples.
|
||||
- Open [an issue](https://github.com/google-gemini/gemini-cli/issues) to discuss
|
||||
your proposed changes.
|
||||
|
||||
+1
-4
@@ -42,10 +42,7 @@ USER node
|
||||
# install gemini-cli and clean up
|
||||
COPY packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz
|
||||
COPY packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz
|
||||
RUN npm install -g /tmp/gemini-core.tgz \
|
||||
&& npm install -g /tmp/gemini-cli.tgz \
|
||||
&& node -e "const fs=require('node:fs'); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json','utf8')); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json','utf8'));" \
|
||||
&& gemini --version > /dev/null \
|
||||
RUN npm install -g /tmp/gemini-cli.tgz /tmp/gemini-core.tgz \
|
||||
&& npm cache clean --force \
|
||||
&& rm -f /tmp/gemini-{cli,core}.tgz
|
||||
|
||||
|
||||
@@ -47,13 +47,7 @@ powerful tool for developers.
|
||||
be relative to the workspace root, e.g.,
|
||||
`-w @google/gemini-cli-core -- src/routing/modelRouterService.test.ts`)
|
||||
- **Full Validation:** `npm run preflight` (Heaviest check; runs clean, install,
|
||||
build, lint, type check, and tests. Recommended before submitting PRs. Due to
|
||||
its long runtime, only run this at the very end of a code implementation task.
|
||||
If it fails, use faster, targeted commands (e.g., `npm run test`,
|
||||
`npm run lint`, or workspace-specific tests) to iterate on fixes before
|
||||
re-running `preflight`. For simple, non-code changes like documentation or
|
||||
prompting updates, skip `preflight` at the end of the task and wait for PR
|
||||
validation.)
|
||||
build, lint, type check, and tests. Recommended before submitting PRs.)
|
||||
- **Individual Checks:** `npm run lint` / `npm run format` / `npm run typecheck`
|
||||
|
||||
## Development Conventions
|
||||
|
||||
@@ -382,7 +382,7 @@ See the [Uninstall Guide](docs/cli/uninstall.md) for removal instructions.
|
||||
## 📄 Legal
|
||||
|
||||
- **License**: [Apache License 2.0](LICENSE)
|
||||
- **Terms of Service**: [Terms & Privacy](./docs/resources/tos-privacy.md)
|
||||
- **Terms of Service**: [Terms & Privacy](./docs/tos-privacy.md)
|
||||
- **Security**: [Security Policy](SECURITY.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -18,48 +18,7 @@ on GitHub.
|
||||
| [Preview](preview.md) | Experimental features ready for early feedback. |
|
||||
| [Stable](latest.md) | Stable, recommended for general use. |
|
||||
|
||||
## Announcements: v0.30.0 - 2026-02-25
|
||||
|
||||
- **SDK & Custom Skills:** Introduced the initial SDK package, enabling dynamic
|
||||
system instructions, `SessionContext` for SDK tool calls, and support for
|
||||
custom skills
|
||||
([#18861](https://github.com/google-gemini/gemini-cli/pull/18861) by
|
||||
@mbleigh).
|
||||
- **Policy Engine Enhancements:** Added a new `--policy` flag for user-defined
|
||||
policies, introduced strict seatbelt profiles, and deprecated
|
||||
`--allowed-tools` in favor of the policy engine
|
||||
([#18500](https://github.com/google-gemini/gemini-cli/pull/18500) by
|
||||
@allenhutchison).
|
||||
- **UI & Themes:** Added a generic searchable list for settings and extensions,
|
||||
new Solarized themes, text wrapping for markdown tables, and a clean UI toggle
|
||||
prototype ([#19064](https://github.com/google-gemini/gemini-cli/pull/19064) by
|
||||
@rmedranollamas).
|
||||
- **Vim & Terminal Interaction:** Improved Vim support to feel more complete and
|
||||
added support for Ctrl-Z terminal suspension
|
||||
([#18755](https://github.com/google-gemini/gemini-cli/pull/18755) by
|
||||
@ppgranger, [#18931](https://github.com/google-gemini/gemini-cli/pull/18931)
|
||||
by @scidomino).
|
||||
|
||||
## Announcements: v0.29.0 - 2026-02-17
|
||||
|
||||
- **Plan Mode:** A new comprehensive planning capability with `/plan`,
|
||||
`enter_plan_mode` tool, and dedicated documentation
|
||||
([#17698](https://github.com/google-gemini/gemini-cli/pull/17698) by @Adib234,
|
||||
[#18324](https://github.com/google-gemini/gemini-cli/pull/18324) by @jerop).
|
||||
- **Gemini 3 Default:** We've removed the preview flag and enabled Gemini 3 by
|
||||
default for all users
|
||||
([#18414](https://github.com/google-gemini/gemini-cli/pull/18414) by
|
||||
@sehoon38).
|
||||
- **Extension Exploration:** New UI and settings to explore and manage
|
||||
extensions more easily
|
||||
([#18686](https://github.com/google-gemini/gemini-cli/pull/18686) by
|
||||
@sripasg).
|
||||
- **Admin Control:** Administrators can now allowlist specific MCP server
|
||||
configurations
|
||||
([#18311](https://github.com/google-gemini/gemini-cli/pull/18311) by
|
||||
@skeshive).
|
||||
|
||||
## Announcements: v0.28.0 - 2026-02-10
|
||||
## Announcements: v0.28.0 - 2026-02-03
|
||||
|
||||
- **Slash Command:** We've added a new `/prompt-suggest` slash command to help
|
||||
you generate prompt suggestions
|
||||
|
||||
+295
-313
@@ -1,6 +1,6 @@
|
||||
# Latest stable release: v0.30.0
|
||||
# Latest stable release: v0.28.0
|
||||
|
||||
Released: February 25, 2026
|
||||
Released: February 10, 2026
|
||||
|
||||
For most users, our latest stable release is the recommended release. Install
|
||||
the latest stable version with:
|
||||
@@ -11,323 +11,305 @@ npm install -g @google/gemini-cli
|
||||
|
||||
## Highlights
|
||||
|
||||
- **SDK & Custom Skills**: Introduced the initial SDK package, dynamic system
|
||||
instructions, `SessionContext` for SDK tool calls, and support for custom
|
||||
skills.
|
||||
- **Policy Engine Enhancements**: Added a `--policy` flag for user-defined
|
||||
policies, strict seatbelt profiles, and transitioned away from
|
||||
`--allowed-tools`.
|
||||
- **UI & Themes**: Introduced a generic searchable list for settings and
|
||||
extensions, added Solarized Dark and Light themes, text wrapping capabilities
|
||||
to markdown tables, and a clean UI toggle prototype.
|
||||
- **Vim Support & Ctrl-Z**: Improved Vim support to provide a more complete
|
||||
experience and added support for Ctrl-Z suspension.
|
||||
- **Plan Mode & Tools**: Plan Mode now supports project exploration without
|
||||
planning and skills can be enabled in plan mode. Tool output masking is
|
||||
enabled by default, and core tool definitions have been centralized.
|
||||
- **Commands & UX Enhancements:** Introduced `/prompt-suggest` command,
|
||||
alongside updated undo/redo keybindings and automatic theme switching.
|
||||
- **Expanded IDE Support:** Now offering compatibility with Positron IDE,
|
||||
expanding integration options for developers.
|
||||
- **Enhanced Security & Authentication:** Implemented interactive and
|
||||
non-interactive OAuth consent, improving both security and diagnostic
|
||||
capabilities for bug reports.
|
||||
- **Advanced Planning & Agent Tools:** Integrated a generic Checklist component
|
||||
for structured task management and evolved subagent capabilities with dynamic
|
||||
policy registration.
|
||||
- **Improved Core Stability & Reliability:** Resolved critical environment
|
||||
loading, authentication, and session management issues, ensuring a more robust
|
||||
experience.
|
||||
- **Background Shell Commands:** Enabled the execution of shell commands in the
|
||||
background for increased workflow efficiency.
|
||||
|
||||
## What's Changed
|
||||
|
||||
- feat(ux): added text wrapping capabilities to markdown tables by @devr0306 in
|
||||
[#18240](https://github.com/google-gemini/gemini-cli/pull/18240)
|
||||
- Revert "fix(mcp): ensure MCP transport is closed to prevent memory leaks" by
|
||||
@skeshive in [#18771](https://github.com/google-gemini/gemini-cli/pull/18771)
|
||||
- chore(release): bump version to 0.30.0-nightly.20260210.a2174751d by
|
||||
- feat(commands): add /prompt-suggest slash command by @NTaylorMullen in
|
||||
[#17264](https://github.com/google-gemini/gemini-cli/pull/17264)
|
||||
- feat(cli): align hooks enable/disable with skills and improve completion by
|
||||
@sehoon38 in [#16822](https://github.com/google-gemini/gemini-cli/pull/16822)
|
||||
- docs: add CLI reference documentation by @leochiu-a in
|
||||
[#17504](https://github.com/google-gemini/gemini-cli/pull/17504)
|
||||
- chore(release): bump version to 0.28.0-nightly.20260128.adc8e11bb by
|
||||
@gemini-cli-robot in
|
||||
[#18772](https://github.com/google-gemini/gemini-cli/pull/18772)
|
||||
- chore: cleanup unused and add unlisted dependencies in packages/core by
|
||||
@adamfweidman in
|
||||
[#18762](https://github.com/google-gemini/gemini-cli/pull/18762)
|
||||
- chore(core): update activate_skill prompt verbiage to be more direct by
|
||||
@NTaylorMullen in
|
||||
[#18605](https://github.com/google-gemini/gemini-cli/pull/18605)
|
||||
- Add autoconfigure memory usage setting to the dialog by @jacob314 in
|
||||
[#18510](https://github.com/google-gemini/gemini-cli/pull/18510)
|
||||
- fix(core): prevent race condition in policy persistence by @braddux in
|
||||
[#18506](https://github.com/google-gemini/gemini-cli/pull/18506)
|
||||
- fix(evals): prevent false positive in hierarchical memory test by
|
||||
@Abhijit-2592 in
|
||||
[#18777](https://github.com/google-gemini/gemini-cli/pull/18777)
|
||||
- test(evals): mark all `save_memory` evals as `USUALLY_PASSES` due to
|
||||
unreliability by @jerop in
|
||||
[#18786](https://github.com/google-gemini/gemini-cli/pull/18786)
|
||||
- feat(cli): add setting to hide shortcuts hint UI by @LyalinDotCom in
|
||||
[#18562](https://github.com/google-gemini/gemini-cli/pull/18562)
|
||||
- feat(core): formalize 5-phase sequential planning workflow by @jerop in
|
||||
[#18759](https://github.com/google-gemini/gemini-cli/pull/18759)
|
||||
- Introduce limits for search results. by @gundermanc in
|
||||
[#18767](https://github.com/google-gemini/gemini-cli/pull/18767)
|
||||
- fix(cli): allow closing debug console after auto-open via flicker by
|
||||
@SandyTao520 in
|
||||
[#18795](https://github.com/google-gemini/gemini-cli/pull/18795)
|
||||
- feat(masking): enable tool output masking by default by @abhipatel12 in
|
||||
[#18564](https://github.com/google-gemini/gemini-cli/pull/18564)
|
||||
- perf(ui): optimize table rendering by memoizing styled characters by @devr0306
|
||||
in [#18770](https://github.com/google-gemini/gemini-cli/pull/18770)
|
||||
- feat: multi-line text answers in ask-user tool by @jackwotherspoon in
|
||||
[#18741](https://github.com/google-gemini/gemini-cli/pull/18741)
|
||||
- perf(cli): truncate large debug logs and limit message history by @mattKorwel
|
||||
in [#18663](https://github.com/google-gemini/gemini-cli/pull/18663)
|
||||
- fix(core): complete MCP discovery when configured servers are skipped by
|
||||
@LyalinDotCom in
|
||||
[#18586](https://github.com/google-gemini/gemini-cli/pull/18586)
|
||||
- fix(core): cache CLI version to ensure consistency during sessions by
|
||||
@sehoon38 in [#18793](https://github.com/google-gemini/gemini-cli/pull/18793)
|
||||
- fix(cli): resolve double rendering in shpool and address vscode lint warnings
|
||||
by @braddux in
|
||||
[#18704](https://github.com/google-gemini/gemini-cli/pull/18704)
|
||||
- feat(plan): document and validate Plan Mode policy overrides by @jerop in
|
||||
[#18825](https://github.com/google-gemini/gemini-cli/pull/18825)
|
||||
- Fix pressing any key to exit select mode. by @jacob314 in
|
||||
[#18421](https://github.com/google-gemini/gemini-cli/pull/18421)
|
||||
- fix(cli): update F12 behavior to only open drawer if browser fails by
|
||||
@SandyTao520 in
|
||||
[#18829](https://github.com/google-gemini/gemini-cli/pull/18829)
|
||||
- feat(plan): allow skills to be enabled in plan mode by @Adib234 in
|
||||
[#18817](https://github.com/google-gemini/gemini-cli/pull/18817)
|
||||
- docs(plan): add documentation for plan mode tools by @jerop in
|
||||
[#18827](https://github.com/google-gemini/gemini-cli/pull/18827)
|
||||
- Remove experimental note in extension settings docs by @chrstnb in
|
||||
[#18822](https://github.com/google-gemini/gemini-cli/pull/18822)
|
||||
- Update prompt and grep tool definition to limit context size by @gundermanc in
|
||||
[#18780](https://github.com/google-gemini/gemini-cli/pull/18780)
|
||||
- docs(plan): add `ask_user` tool documentation by @jerop in
|
||||
[#18830](https://github.com/google-gemini/gemini-cli/pull/18830)
|
||||
- Revert unintended credentials exposure by @Adib234 in
|
||||
[#18840](https://github.com/google-gemini/gemini-cli/pull/18840)
|
||||
- feat(core): update internal utility models to Gemini 3 by @SandyTao520 in
|
||||
[#18773](https://github.com/google-gemini/gemini-cli/pull/18773)
|
||||
- feat(a2a): add value-resolver for auth credential resolution by @adamfweidman
|
||||
in [#18653](https://github.com/google-gemini/gemini-cli/pull/18653)
|
||||
- Removed getPlainTextLength by @devr0306 in
|
||||
[#18848](https://github.com/google-gemini/gemini-cli/pull/18848)
|
||||
- More grep prompt tweaks by @gundermanc in
|
||||
[#18846](https://github.com/google-gemini/gemini-cli/pull/18846)
|
||||
- refactor(cli): Reactive useSettingsStore hook by @psinha40898 in
|
||||
[#14915](https://github.com/google-gemini/gemini-cli/pull/14915)
|
||||
- fix(mcp): Ensure that stdio MCP server execution has the `GEMINI_CLI=1` env
|
||||
variable populated. by @richieforeman in
|
||||
[#18832](https://github.com/google-gemini/gemini-cli/pull/18832)
|
||||
- fix(core): improve headless mode detection for flags and query args by @galz10
|
||||
in [#18855](https://github.com/google-gemini/gemini-cli/pull/18855)
|
||||
- refactor(cli): simplify UI and remove legacy inline tool confirmation logic by
|
||||
[#17725](https://github.com/google-gemini/gemini-cli/pull/17725)
|
||||
- feat(skills): final stable promotion cleanup by @abhipatel12 in
|
||||
[#17726](https://github.com/google-gemini/gemini-cli/pull/17726)
|
||||
- test(core): mock fetch in OAuth transport fallback tests by @jw409 in
|
||||
[#17059](https://github.com/google-gemini/gemini-cli/pull/17059)
|
||||
- feat(cli): include auth method in /bug by @erikus in
|
||||
[#17569](https://github.com/google-gemini/gemini-cli/pull/17569)
|
||||
- Add a email privacy note to bug_report template by @nemyung in
|
||||
[#17474](https://github.com/google-gemini/gemini-cli/pull/17474)
|
||||
- Rewind documentation by @Adib234 in
|
||||
[#17446](https://github.com/google-gemini/gemini-cli/pull/17446)
|
||||
- fix: verify audio/video MIME types with content check by @maru0804 in
|
||||
[#16907](https://github.com/google-gemini/gemini-cli/pull/16907)
|
||||
- feat(core): add support for positron ide
|
||||
([#15045](https://github.com/google-gemini/gemini-cli/pull/15045)) by @kapsner
|
||||
in [#15047](https://github.com/google-gemini/gemini-cli/pull/15047)
|
||||
- /oncall dedup - wrap texts to nextlines by @sehoon38 in
|
||||
[#17782](https://github.com/google-gemini/gemini-cli/pull/17782)
|
||||
- fix(admin): rename advanced features admin setting by @skeshive in
|
||||
[#17786](https://github.com/google-gemini/gemini-cli/pull/17786)
|
||||
- [extension config] Make breaking optional value non-optional by @chrstnb in
|
||||
[#17785](https://github.com/google-gemini/gemini-cli/pull/17785)
|
||||
- Fix docs-writer skill issues by @g-samroberts in
|
||||
[#17734](https://github.com/google-gemini/gemini-cli/pull/17734)
|
||||
- fix(core): suppress duplicate hook failure warnings during streaming by
|
||||
@abhipatel12 in
|
||||
[#18566](https://github.com/google-gemini/gemini-cli/pull/18566)
|
||||
- feat(cli): deprecate --allowed-tools and excludeTools in favor of policy
|
||||
engine by @Abhijit-2592 in
|
||||
[#18508](https://github.com/google-gemini/gemini-cli/pull/18508)
|
||||
- fix(workflows): improve maintainer detection for automated PR actions by
|
||||
@bdmorgan in [#18869](https://github.com/google-gemini/gemini-cli/pull/18869)
|
||||
- refactor(cli): consolidate useToolScheduler and delete legacy implementation
|
||||
by @abhipatel12 in
|
||||
[#18567](https://github.com/google-gemini/gemini-cli/pull/18567)
|
||||
- Update changelog for v0.28.0 and v0.29.0-preview0 by @g-samroberts in
|
||||
[#18819](https://github.com/google-gemini/gemini-cli/pull/18819)
|
||||
- fix(core): ensure sub-agents are registered regardless of tools.allowed by
|
||||
@mattKorwel in
|
||||
[#18870](https://github.com/google-gemini/gemini-cli/pull/18870)
|
||||
- Show notification when there's a conflict with an extensions command by
|
||||
@chrstnb in [#17890](https://github.com/google-gemini/gemini-cli/pull/17890)
|
||||
- fix(cli): dismiss '?' shortcuts help on hotkeys and active states by
|
||||
@LyalinDotCom in
|
||||
[#18583](https://github.com/google-gemini/gemini-cli/pull/18583)
|
||||
- fix(core): prioritize conditional policy rules and harden Plan Mode by
|
||||
[#17727](https://github.com/google-gemini/gemini-cli/pull/17727)
|
||||
- test: add more tests for AskUser by @jackwotherspoon in
|
||||
[#17720](https://github.com/google-gemini/gemini-cli/pull/17720)
|
||||
- feat(cli): enable activity logging for non-interactive mode and evals by
|
||||
@SandyTao520 in
|
||||
[#17703](https://github.com/google-gemini/gemini-cli/pull/17703)
|
||||
- feat(core): add support for custom deny messages in policy rules by
|
||||
@allenhutchison in
|
||||
[#17427](https://github.com/google-gemini/gemini-cli/pull/17427)
|
||||
- Fix unintended credential exposure to MCP Servers by @Adib234 in
|
||||
[#17311](https://github.com/google-gemini/gemini-cli/pull/17311)
|
||||
- feat(extensions): add support for custom themes in extensions by @spencer426
|
||||
in [#17327](https://github.com/google-gemini/gemini-cli/pull/17327)
|
||||
- fix: persist and restore workspace directories on session resume by
|
||||
@korade-krushna in
|
||||
[#17454](https://github.com/google-gemini/gemini-cli/pull/17454)
|
||||
- Update release notes pages for 0.26.0 and 0.27.0-preview. by @g-samroberts in
|
||||
[#17744](https://github.com/google-gemini/gemini-cli/pull/17744)
|
||||
- feat(ux): update cell border color and created test file for table rendering
|
||||
by @devr0306 in
|
||||
[#17798](https://github.com/google-gemini/gemini-cli/pull/17798)
|
||||
- Change height for the ToolConfirmationQueue. by @jacob314 in
|
||||
[#17799](https://github.com/google-gemini/gemini-cli/pull/17799)
|
||||
- feat(cli): add user identity info to stats command by @sehoon38 in
|
||||
[#17612](https://github.com/google-gemini/gemini-cli/pull/17612)
|
||||
- fix(ux): fixed off-by-some wrapping caused by fixed-width characters by
|
||||
@devr0306 in [#17816](https://github.com/google-gemini/gemini-cli/pull/17816)
|
||||
- feat(cli): update undo/redo keybindings to Cmd+Z/Alt+Z and
|
||||
Shift+Cmd+Z/Shift+Alt+Z by @scidomino in
|
||||
[#17800](https://github.com/google-gemini/gemini-cli/pull/17800)
|
||||
- fix(evals): use absolute path for activity log directory by @SandyTao520 in
|
||||
[#17830](https://github.com/google-gemini/gemini-cli/pull/17830)
|
||||
- test: add integration test to verify stdout/stderr routing by @ved015 in
|
||||
[#17280](https://github.com/google-gemini/gemini-cli/pull/17280)
|
||||
- fix(cli): list installed extensions when update target missing by @tt-a1i in
|
||||
[#17082](https://github.com/google-gemini/gemini-cli/pull/17082)
|
||||
- fix(cli): handle PAT tokens and credentials in git remote URL parsing by
|
||||
@afarber in [#14650](https://github.com/google-gemini/gemini-cli/pull/14650)
|
||||
- fix(core): use returnDisplay for error result display by @Nubebuster in
|
||||
[#14994](https://github.com/google-gemini/gemini-cli/pull/14994)
|
||||
- Fix detection of bun as package manager by @Randomblock1 in
|
||||
[#17462](https://github.com/google-gemini/gemini-cli/pull/17462)
|
||||
- feat(cli): show hooksConfig.enabled in settings dialog by @abhipatel12 in
|
||||
[#17810](https://github.com/google-gemini/gemini-cli/pull/17810)
|
||||
- feat(cli): Display user identity (auth, email, tier) on startup by @yunaseoul
|
||||
in [#17591](https://github.com/google-gemini/gemini-cli/pull/17591)
|
||||
- fix: prevent ghost border for AskUserDialog by @jackwotherspoon in
|
||||
[#17788](https://github.com/google-gemini/gemini-cli/pull/17788)
|
||||
- docs: mark A2A subagents as experimental in subagents.md by @adamfweidman in
|
||||
[#17863](https://github.com/google-gemini/gemini-cli/pull/17863)
|
||||
- Resolve error thrown for sensitive values by @chrstnb in
|
||||
[#17826](https://github.com/google-gemini/gemini-cli/pull/17826)
|
||||
- fix(admin): Rename secureModeEnabled to strictModeDisabled by @skeshive in
|
||||
[#17789](https://github.com/google-gemini/gemini-cli/pull/17789)
|
||||
- feat(ux): update truncate dots to be shorter in tables by @devr0306 in
|
||||
[#17825](https://github.com/google-gemini/gemini-cli/pull/17825)
|
||||
- fix(core): resolve DEP0040 punycode deprecation via patch-package by
|
||||
@ATHARVA262005 in
|
||||
[#17692](https://github.com/google-gemini/gemini-cli/pull/17692)
|
||||
- feat(plan): create generic Checklist component and refactor Todo by @Adib234
|
||||
in [#17741](https://github.com/google-gemini/gemini-cli/pull/17741)
|
||||
- Cleanup post delegate_to_agent removal by @gundermanc in
|
||||
[#17875](https://github.com/google-gemini/gemini-cli/pull/17875)
|
||||
- fix(core): use GIT_CONFIG_GLOBAL to isolate shadow git repo configuration -
|
||||
Fixes [#17877](https://github.com/google-gemini/gemini-cli/pull/17877) by
|
||||
@cocosheng-g in
|
||||
[#17803](https://github.com/google-gemini/gemini-cli/pull/17803)
|
||||
- Disable mouse tracking e2e by @alisa-alisa in
|
||||
[#17880](https://github.com/google-gemini/gemini-cli/pull/17880)
|
||||
- fix(cli): use correct setting key for Cloud Shell auth by @sehoon38 in
|
||||
[#17884](https://github.com/google-gemini/gemini-cli/pull/17884)
|
||||
- chore: revert IDE specific ASCII logo by @jackwotherspoon in
|
||||
[#17887](https://github.com/google-gemini/gemini-cli/pull/17887)
|
||||
- Revert "fix(core): resolve DEP0040 punycode deprecation via patch-package" by
|
||||
@sehoon38 in [#17898](https://github.com/google-gemini/gemini-cli/pull/17898)
|
||||
- Refactoring of disabling of mouse tracking in e2e tests by @alisa-alisa in
|
||||
[#17902](https://github.com/google-gemini/gemini-cli/pull/17902)
|
||||
- feat(core): Add GOOGLE_GENAI_API_VERSION environment variable support by
|
||||
@deyim in [#16177](https://github.com/google-gemini/gemini-cli/pull/16177)
|
||||
- feat(core): Isolate and cleanup truncated tool outputs by @SandyTao520 in
|
||||
[#17594](https://github.com/google-gemini/gemini-cli/pull/17594)
|
||||
- Create skills page, update commands, refine docs by @g-samroberts in
|
||||
[#17842](https://github.com/google-gemini/gemini-cli/pull/17842)
|
||||
- feat: preserve EOL in files by @Thomas-Shephard in
|
||||
[#16087](https://github.com/google-gemini/gemini-cli/pull/16087)
|
||||
- Fix HalfLinePaddedBox in screenreader mode. by @jacob314 in
|
||||
[#17914](https://github.com/google-gemini/gemini-cli/pull/17914)
|
||||
- bug(ux) vim mode fixes. Start in insert mode. Fix bug blocking F12 and ctrl-X
|
||||
in vim mode. by @jacob314 in
|
||||
[#17938](https://github.com/google-gemini/gemini-cli/pull/17938)
|
||||
- feat(core): implement interactive and non-interactive consent for OAuth by
|
||||
@ehedlund in [#17699](https://github.com/google-gemini/gemini-cli/pull/17699)
|
||||
- perf(core): optimize token calculation and add support for multimodal tool
|
||||
responses by @abhipatel12 in
|
||||
[#17835](https://github.com/google-gemini/gemini-cli/pull/17835)
|
||||
- refactor(hooks): remove legacy tools.enableHooks setting by @abhipatel12 in
|
||||
[#17867](https://github.com/google-gemini/gemini-cli/pull/17867)
|
||||
- feat(ci): add npx smoke test to verify installability by @bdmorgan in
|
||||
[#17927](https://github.com/google-gemini/gemini-cli/pull/17927)
|
||||
- feat(core): implement dynamic policy registration for subagents by
|
||||
@abhipatel12 in
|
||||
[#17838](https://github.com/google-gemini/gemini-cli/pull/17838)
|
||||
- feat: Implement background shell commands by @galz10 in
|
||||
[#14849](https://github.com/google-gemini/gemini-cli/pull/14849)
|
||||
- feat(admin): provide actionable error messages for disabled features by
|
||||
@skeshive in [#17815](https://github.com/google-gemini/gemini-cli/pull/17815)
|
||||
- Fix bugs where Rewind and Resume showed Ugly and 100X too verbose content. by
|
||||
@jacob314 in [#17940](https://github.com/google-gemini/gemini-cli/pull/17940)
|
||||
- Fix broken link in docs by @chrstnb in
|
||||
[#17959](https://github.com/google-gemini/gemini-cli/pull/17959)
|
||||
- feat(plan): reuse standard tool confirmation for AskUser tool by @jerop in
|
||||
[#17864](https://github.com/google-gemini/gemini-cli/pull/17864)
|
||||
- feat(core): enable overriding CODE_ASSIST_API_VERSION with env var by
|
||||
@lottielin in [#17942](https://github.com/google-gemini/gemini-cli/pull/17942)
|
||||
- run npx pointing to the specific commit SHA by @sehoon38 in
|
||||
[#17970](https://github.com/google-gemini/gemini-cli/pull/17970)
|
||||
- Add allowedExtensions setting by @kevinjwang1 in
|
||||
[#17695](https://github.com/google-gemini/gemini-cli/pull/17695)
|
||||
- feat(plan): refactor ToolConfirmationPayload to union type by @jerop in
|
||||
[#17980](https://github.com/google-gemini/gemini-cli/pull/17980)
|
||||
- lower the default max retries to reduce contention by @sehoon38 in
|
||||
[#17975](https://github.com/google-gemini/gemini-cli/pull/17975)
|
||||
- fix(core): ensure YOLO mode auto-approves complex shell commands when parsing
|
||||
fails by @abhipatel12 in
|
||||
[#17920](https://github.com/google-gemini/gemini-cli/pull/17920)
|
||||
- Fix broken link. by @g-samroberts in
|
||||
[#17972](https://github.com/google-gemini/gemini-cli/pull/17972)
|
||||
- Support ctrl-C and Ctrl-D correctly Refactor so InputPrompt has priority over
|
||||
AppContainer for input handling. by @jacob314 in
|
||||
[#17993](https://github.com/google-gemini/gemini-cli/pull/17993)
|
||||
- Fix truncation for AskQuestion by @jacob314 in
|
||||
[#18001](https://github.com/google-gemini/gemini-cli/pull/18001)
|
||||
- fix(workflow): update maintainer check logic to be inclusive and
|
||||
case-insensitive by @bdmorgan in
|
||||
[#18009](https://github.com/google-gemini/gemini-cli/pull/18009)
|
||||
- Fix Esc cancel during streaming by @LyalinDotCom in
|
||||
[#18039](https://github.com/google-gemini/gemini-cli/pull/18039)
|
||||
- feat(acp): add session resume support by @bdmorgan in
|
||||
[#18043](https://github.com/google-gemini/gemini-cli/pull/18043)
|
||||
- fix(ci): prevent stale PR closer from incorrectly closing new PRs by @bdmorgan
|
||||
in [#18069](https://github.com/google-gemini/gemini-cli/pull/18069)
|
||||
- chore: delete autoAccept setting unused in production by @victorvianna in
|
||||
[#17862](https://github.com/google-gemini/gemini-cli/pull/17862)
|
||||
- feat(plan): use placeholder for choice question "Other" option by @jerop in
|
||||
[#18101](https://github.com/google-gemini/gemini-cli/pull/18101)
|
||||
- docs: update clearContext to hookSpecificOutput by @jackwotherspoon in
|
||||
[#18024](https://github.com/google-gemini/gemini-cli/pull/18024)
|
||||
- docs-writer skill: Update docs writer skill by @jkcinouye in
|
||||
[#17928](https://github.com/google-gemini/gemini-cli/pull/17928)
|
||||
- Sehoon/oncall filter by @sehoon38 in
|
||||
[#18105](https://github.com/google-gemini/gemini-cli/pull/18105)
|
||||
- feat(core): add setting to disable loop detection by @SandyTao520 in
|
||||
[#18008](https://github.com/google-gemini/gemini-cli/pull/18008)
|
||||
- Docs: Revise docs/index.md by @jkcinouye in
|
||||
[#17879](https://github.com/google-gemini/gemini-cli/pull/17879)
|
||||
- Fix up/down arrow regression and add test. by @jacob314 in
|
||||
[#18108](https://github.com/google-gemini/gemini-cli/pull/18108)
|
||||
- fix(ui): prevent content leak in MaxSizedBox bottom overflow by @jerop in
|
||||
[#17991](https://github.com/google-gemini/gemini-cli/pull/17991)
|
||||
- refactor: migrate checks.ts utility to core and deduplicate by @jerop in
|
||||
[#18139](https://github.com/google-gemini/gemini-cli/pull/18139)
|
||||
- feat(core): implement tool name aliasing for backward compatibility by
|
||||
@SandyTao520 in
|
||||
[#17974](https://github.com/google-gemini/gemini-cli/pull/17974)
|
||||
- docs: fix help-wanted label spelling by @pavan-sh in
|
||||
[#18114](https://github.com/google-gemini/gemini-cli/pull/18114)
|
||||
- feat(cli): implement automatic theme switching based on terminal background by
|
||||
@Abhijit-2592 in
|
||||
[#18882](https://github.com/google-gemini/gemini-cli/pull/18882)
|
||||
- feat(core): refine Plan Mode system prompt for agentic execution by
|
||||
@NTaylorMullen in
|
||||
[#18799](https://github.com/google-gemini/gemini-cli/pull/18799)
|
||||
- feat(plan): create metrics for usage of `AskUser` tool by @Adib234 in
|
||||
[#18820](https://github.com/google-gemini/gemini-cli/pull/18820)
|
||||
- feat(cli): support Ctrl-Z suspension by @scidomino in
|
||||
[#18931](https://github.com/google-gemini/gemini-cli/pull/18931)
|
||||
- fix(github-actions): use robot PAT for release creation to trigger release
|
||||
notes by @SandyTao520 in
|
||||
[#18794](https://github.com/google-gemini/gemini-cli/pull/18794)
|
||||
- feat: add strict seatbelt profiles and remove unusable closed profiles by
|
||||
@SandyTao520 in
|
||||
[#18876](https://github.com/google-gemini/gemini-cli/pull/18876)
|
||||
- chore: cleanup unused and add unlisted dependencies in packages/a2a-server by
|
||||
@adamfweidman in
|
||||
[#18916](https://github.com/google-gemini/gemini-cli/pull/18916)
|
||||
- fix(plan): isolate plan files per session by @Adib234 in
|
||||
[#18757](https://github.com/google-gemini/gemini-cli/pull/18757)
|
||||
- fix: character truncation in raw markdown mode by @jackwotherspoon in
|
||||
[#18938](https://github.com/google-gemini/gemini-cli/pull/18938)
|
||||
- feat(cli): prototype clean UI toggle and minimal-mode bleed-through by
|
||||
@LyalinDotCom in
|
||||
[#18683](https://github.com/google-gemini/gemini-cli/pull/18683)
|
||||
- ui(polish) blend background color with theme by @jacob314 in
|
||||
[#18802](https://github.com/google-gemini/gemini-cli/pull/18802)
|
||||
- Add generic searchable list to back settings and extensions by @chrstnb in
|
||||
[#18838](https://github.com/google-gemini/gemini-cli/pull/18838)
|
||||
- feat(ui): align `AskUser` color scheme with UX spec by @jerop in
|
||||
[#18943](https://github.com/google-gemini/gemini-cli/pull/18943)
|
||||
- Hide AskUser tool validation errors from UI (agent self-corrects) by @jerop in
|
||||
[#18954](https://github.com/google-gemini/gemini-cli/pull/18954)
|
||||
- bug(cli) fix flicker due to AppContainer continuous initialization by
|
||||
@jacob314 in [#18958](https://github.com/google-gemini/gemini-cli/pull/18958)
|
||||
- feat(admin): Add admin controls documentation by @skeshive in
|
||||
[#18644](https://github.com/google-gemini/gemini-cli/pull/18644)
|
||||
- feat(cli): disable ctrl-s shortcut outside of alternate buffer mode by
|
||||
@jacob314 in [#18887](https://github.com/google-gemini/gemini-cli/pull/18887)
|
||||
- fix(vim): vim support that feels (more) complete by @ppgranger in
|
||||
[#18755](https://github.com/google-gemini/gemini-cli/pull/18755)
|
||||
- feat(policy): add --policy flag for user defined policies by @allenhutchison
|
||||
in [#18500](https://github.com/google-gemini/gemini-cli/pull/18500)
|
||||
- Update installation guide by @g-samroberts in
|
||||
[#18823](https://github.com/google-gemini/gemini-cli/pull/18823)
|
||||
- refactor(core): centralize tool definitions (Group 1: replace, search, grep)
|
||||
by @aishaneeshah in
|
||||
[#18944](https://github.com/google-gemini/gemini-cli/pull/18944)
|
||||
- refactor(cli): finalize event-driven transition and remove interaction bridge
|
||||
by @abhipatel12 in
|
||||
[#18569](https://github.com/google-gemini/gemini-cli/pull/18569)
|
||||
- Fix drag and drop escaping by @scidomino in
|
||||
[#18965](https://github.com/google-gemini/gemini-cli/pull/18965)
|
||||
- feat(sdk): initial package bootstrap for SDK by @mbleigh in
|
||||
[#18861](https://github.com/google-gemini/gemini-cli/pull/18861)
|
||||
- feat(sdk): implements SessionContext for SDK tool calls by @mbleigh in
|
||||
[#18862](https://github.com/google-gemini/gemini-cli/pull/18862)
|
||||
- fix(plan): make question type required in AskUser tool by @Adib234 in
|
||||
[#18959](https://github.com/google-gemini/gemini-cli/pull/18959)
|
||||
- fix(core): ensure --yolo does not force headless mode by @NTaylorMullen in
|
||||
[#18976](https://github.com/google-gemini/gemini-cli/pull/18976)
|
||||
- refactor(core): adopt `CoreToolCallStatus` enum for type safety by @jerop in
|
||||
[#18998](https://github.com/google-gemini/gemini-cli/pull/18998)
|
||||
- Enable in-CLI extension management commands for team by @chrstnb in
|
||||
[#18957](https://github.com/google-gemini/gemini-cli/pull/18957)
|
||||
- Adjust lint rules to avoid unnecessary warning. by @scidomino in
|
||||
[#18970](https://github.com/google-gemini/gemini-cli/pull/18970)
|
||||
- fix(vscode): resolve unsafe type assertion lint errors by @ehedlund in
|
||||
[#19006](https://github.com/google-gemini/gemini-cli/pull/19006)
|
||||
- Remove unnecessary eslint config file by @scidomino in
|
||||
[#19015](https://github.com/google-gemini/gemini-cli/pull/19015)
|
||||
- fix(core): Prevent loop detection false positives on lists with long shared
|
||||
prefixes by @SandyTao520 in
|
||||
[#18975](https://github.com/google-gemini/gemini-cli/pull/18975)
|
||||
- feat(core): fallback to chat-base when using unrecognized models for chat by
|
||||
@SandyTao520 in
|
||||
[#19016](https://github.com/google-gemini/gemini-cli/pull/19016)
|
||||
- docs: fix inconsistent commandRegex example in policy engine by @NTaylorMullen
|
||||
in [#19027](https://github.com/google-gemini/gemini-cli/pull/19027)
|
||||
- fix(plan): persist the approval mode in UI even when agent is thinking by
|
||||
@Adib234 in [#18955](https://github.com/google-gemini/gemini-cli/pull/18955)
|
||||
- feat(sdk): Implement dynamic system instructions by @mbleigh in
|
||||
[#18863](https://github.com/google-gemini/gemini-cli/pull/18863)
|
||||
- Docs: Refresh docs to organize and standardize reference materials. by
|
||||
@jkcinouye in [#18403](https://github.com/google-gemini/gemini-cli/pull/18403)
|
||||
- fix windows escaping (and broken tests) by @scidomino in
|
||||
[#19011](https://github.com/google-gemini/gemini-cli/pull/19011)
|
||||
- refactor: use `CoreToolCallStatus` in the the history data model by @jerop in
|
||||
[#19033](https://github.com/google-gemini/gemini-cli/pull/19033)
|
||||
- feat(cleanup): enable 30-day session retention by default by @skeshive in
|
||||
[#18854](https://github.com/google-gemini/gemini-cli/pull/18854)
|
||||
- feat(plan): hide plan write and edit operations on plans in Plan Mode by
|
||||
@jerop in [#19012](https://github.com/google-gemini/gemini-cli/pull/19012)
|
||||
- bug(ui) fix flicker refreshing background color by @jacob314 in
|
||||
[#19041](https://github.com/google-gemini/gemini-cli/pull/19041)
|
||||
- chore: fix dep vulnerabilities by @scidomino in
|
||||
[#19036](https://github.com/google-gemini/gemini-cli/pull/19036)
|
||||
- Revamp automated changelog skill by @g-samroberts in
|
||||
[#18974](https://github.com/google-gemini/gemini-cli/pull/18974)
|
||||
- feat(sdk): implement support for custom skills by @mbleigh in
|
||||
[#19031](https://github.com/google-gemini/gemini-cli/pull/19031)
|
||||
- refactor(core): complete centralization of core tool definitions by
|
||||
@aishaneeshah in
|
||||
[#18991](https://github.com/google-gemini/gemini-cli/pull/18991)
|
||||
- feat: add /commands reload to refresh custom TOML commands by @korade-krushna
|
||||
in [#19078](https://github.com/google-gemini/gemini-cli/pull/19078)
|
||||
- fix(cli): wrap terminal capability queries in hidden sequence by @srithreepo
|
||||
in [#19080](https://github.com/google-gemini/gemini-cli/pull/19080)
|
||||
- fix(workflows): fix GitHub App token permissions for maintainer detection by
|
||||
@bdmorgan in [#19139](https://github.com/google-gemini/gemini-cli/pull/19139)
|
||||
- test: fix hook integration test flakiness on Windows CI by @NTaylorMullen in
|
||||
[#18665](https://github.com/google-gemini/gemini-cli/pull/18665)
|
||||
- fix(core): Encourage non-interactive flags for scaffolding commands by
|
||||
@NTaylorMullen in
|
||||
[#18804](https://github.com/google-gemini/gemini-cli/pull/18804)
|
||||
- fix(core): propagate User-Agent header to setup-phase CodeAssist API calls by
|
||||
[#17976](https://github.com/google-gemini/gemini-cli/pull/17976)
|
||||
- fix(ide): no-op refactoring that moves the connection logic to helper
|
||||
functions by @skeshive in
|
||||
[#18118](https://github.com/google-gemini/gemini-cli/pull/18118)
|
||||
- feat: update review-frontend-and-fix slash command to review-and-fix by
|
||||
@galz10 in [#18146](https://github.com/google-gemini/gemini-cli/pull/18146)
|
||||
- fix: improve Ctrl+R reverse search by @jackwotherspoon in
|
||||
[#18075](https://github.com/google-gemini/gemini-cli/pull/18075)
|
||||
- feat(plan): handle inconsistency in schedulers by @Adib234 in
|
||||
[#17813](https://github.com/google-gemini/gemini-cli/pull/17813)
|
||||
- feat(plan): add core logic and exit_plan_mode tool definition by @jerop in
|
||||
[#18110](https://github.com/google-gemini/gemini-cli/pull/18110)
|
||||
- feat(core): rename search_file_content tool to grep_search and add legacy
|
||||
alias by @SandyTao520 in
|
||||
[#18003](https://github.com/google-gemini/gemini-cli/pull/18003)
|
||||
- fix(core): prioritize detailed error messages for code assist setup by
|
||||
@gsquared94 in
|
||||
[#19182](https://github.com/google-gemini/gemini-cli/pull/19182)
|
||||
- docs: document .agents/skills alias and discovery precedence by @kevmoo in
|
||||
[#19166](https://github.com/google-gemini/gemini-cli/pull/19166)
|
||||
- feat(cli): add loading state to new agents notification by @sehoon38 in
|
||||
[#19190](https://github.com/google-gemini/gemini-cli/pull/19190)
|
||||
- Add base branch to workflow. by @g-samroberts in
|
||||
[#19189](https://github.com/google-gemini/gemini-cli/pull/19189)
|
||||
- feat(cli): handle invalid model names in useQuotaAndFallback by @sehoon38 in
|
||||
[#19222](https://github.com/google-gemini/gemini-cli/pull/19222)
|
||||
- docs: custom themes in extensions by @jackwotherspoon in
|
||||
[#19219](https://github.com/google-gemini/gemini-cli/pull/19219)
|
||||
- Disable workspace settings when starting GCLI in the home directory. by
|
||||
@kevinjwang1 in
|
||||
[#19034](https://github.com/google-gemini/gemini-cli/pull/19034)
|
||||
- feat(cli): refactor model command to support set and manage subcommands by
|
||||
@sehoon38 in [#19221](https://github.com/google-gemini/gemini-cli/pull/19221)
|
||||
- Add refresh/reload aliases to slash command subcommands by @korade-krushna in
|
||||
[#19218](https://github.com/google-gemini/gemini-cli/pull/19218)
|
||||
- refactor: consolidate development rules and add cli guidelines by @jacob314 in
|
||||
[#19214](https://github.com/google-gemini/gemini-cli/pull/19214)
|
||||
- chore(ui): remove outdated tip about model routing by @sehoon38 in
|
||||
[#19226](https://github.com/google-gemini/gemini-cli/pull/19226)
|
||||
- feat(core): support custom reasoning models by default by @NTaylorMullen in
|
||||
[#19227](https://github.com/google-gemini/gemini-cli/pull/19227)
|
||||
- Add Solarized Dark and Solarized Light themes by @rmedranollamas in
|
||||
[#19064](https://github.com/google-gemini/gemini-cli/pull/19064)
|
||||
- fix(telemetry): replace JSON.stringify with safeJsonStringify in file
|
||||
exporters by @gsquared94 in
|
||||
[#19244](https://github.com/google-gemini/gemini-cli/pull/19244)
|
||||
- feat(telemetry): add keychain availability and token storage metrics by
|
||||
@abhipatel12 in
|
||||
[#18971](https://github.com/google-gemini/gemini-cli/pull/18971)
|
||||
- feat(cli): update approval mode cycle order by @jerop in
|
||||
[#19254](https://github.com/google-gemini/gemini-cli/pull/19254)
|
||||
- refactor(cli): code review cleanup fix for tab+tab by @jacob314 in
|
||||
[#18967](https://github.com/google-gemini/gemini-cli/pull/18967)
|
||||
- feat(plan): support project exploration without planning when in plan mode by
|
||||
@Adib234 in [#18992](https://github.com/google-gemini/gemini-cli/pull/18992)
|
||||
- feat: add role-specific statistics to telemetry and UI (cont. #15234) by
|
||||
@yunaseoul in [#18824](https://github.com/google-gemini/gemini-cli/pull/18824)
|
||||
- feat(cli): remove Plan Mode from rotation when actively working by @jerop in
|
||||
[#19262](https://github.com/google-gemini/gemini-cli/pull/19262)
|
||||
- Fix side breakage where anchors don't work in slugs. by @g-samroberts in
|
||||
[#19261](https://github.com/google-gemini/gemini-cli/pull/19261)
|
||||
- feat(config): add setting to make directory tree context configurable by
|
||||
@kevin-ramdass in
|
||||
[#19053](https://github.com/google-gemini/gemini-cli/pull/19053)
|
||||
- fix(acp): Wait for mcp initialization in acp (#18893) by @Mervap in
|
||||
[#18894](https://github.com/google-gemini/gemini-cli/pull/18894)
|
||||
- docs: format UTC times in releases doc by @pavan-sh in
|
||||
[#18169](https://github.com/google-gemini/gemini-cli/pull/18169)
|
||||
- Docs: Clarify extensions documentation. by @jkcinouye in
|
||||
[#19277](https://github.com/google-gemini/gemini-cli/pull/19277)
|
||||
- refactor(core): modularize tool definitions by model family by @aishaneeshah
|
||||
in [#19269](https://github.com/google-gemini/gemini-cli/pull/19269)
|
||||
- fix(paths): Add cross-platform path normalization by @spencer426 in
|
||||
[#18939](https://github.com/google-gemini/gemini-cli/pull/18939)
|
||||
- feat(core): experimental in-progress steering hints (1 of 3) by @joshualitt in
|
||||
[#19008](https://github.com/google-gemini/gemini-cli/pull/19008)
|
||||
- fix(patch): cherry-pick 261788c to release/v0.30.0-preview.0-pr-19453 to patch
|
||||
version v0.30.0-preview.0 and create version 0.30.0-preview.1 by
|
||||
@gemini-cli-robot in
|
||||
[#19490](https://github.com/google-gemini/gemini-cli/pull/19490)
|
||||
- fix(patch): cherry-pick c43500c to release/v0.30.0-preview.1-pr-19502 to patch
|
||||
version v0.30.0-preview.1 and create version 0.30.0-preview.2 by
|
||||
@gemini-cli-robot in
|
||||
[#19521](https://github.com/google-gemini/gemini-cli/pull/19521)
|
||||
- fix(patch): cherry-pick aa9163d to release/v0.30.0-preview.3-pr-19991 to patch
|
||||
version v0.30.0-preview.3 and create version 0.30.0-preview.4 by
|
||||
@gemini-cli-robot in
|
||||
[#20040](https://github.com/google-gemini/gemini-cli/pull/20040)
|
||||
- fix(patch): cherry-pick 2c1d6f8 to release/v0.30.0-preview.4-pr-19369 to patch
|
||||
version v0.30.0-preview.4 and create version 0.30.0-preview.5 by
|
||||
@gemini-cli-robot in
|
||||
[#20086](https://github.com/google-gemini/gemini-cli/pull/20086)
|
||||
- fix(patch): cherry-pick d96bd05 to release/v0.30.0-preview.5-pr-19867 to patch
|
||||
version v0.30.0-preview.5 and create version 0.30.0-preview.6 by
|
||||
@gemini-cli-robot in
|
||||
[#20112](https://github.com/google-gemini/gemini-cli/pull/20112)
|
||||
[#17852](https://github.com/google-gemini/gemini-cli/pull/17852)
|
||||
- fix(cli): resolve environment loading and auth validation issues in ACP mode
|
||||
by @bdmorgan in
|
||||
[#18025](https://github.com/google-gemini/gemini-cli/pull/18025)
|
||||
- feat(core): add .agents/skills directory alias for skill discovery by
|
||||
@NTaylorMullen in
|
||||
[#18151](https://github.com/google-gemini/gemini-cli/pull/18151)
|
||||
- chore(core): reassign telemetry keys to avoid server conflict by @mattKorwel
|
||||
in [#18161](https://github.com/google-gemini/gemini-cli/pull/18161)
|
||||
- Add link to rewind doc in commands.md by @Adib234 in
|
||||
[#17961](https://github.com/google-gemini/gemini-cli/pull/17961)
|
||||
- feat(core): add draft-2020-12 JSON Schema support with lenient fallback by
|
||||
@afarber in [#15060](https://github.com/google-gemini/gemini-cli/pull/15060)
|
||||
- refactor(core): robust trimPreservingTrailingNewline and regression test by
|
||||
@adamfweidman in
|
||||
[#18196](https://github.com/google-gemini/gemini-cli/pull/18196)
|
||||
- Remove MCP servers on extension uninstall by @chrstnb in
|
||||
[#18121](https://github.com/google-gemini/gemini-cli/pull/18121)
|
||||
- refactor: localize ACP error parsing logic to cli package by @bdmorgan in
|
||||
[#18193](https://github.com/google-gemini/gemini-cli/pull/18193)
|
||||
- feat(core): Add A2A auth config types by @adamfweidman in
|
||||
[#18205](https://github.com/google-gemini/gemini-cli/pull/18205)
|
||||
- Set default max attempts to 3 and use the common variable by @sehoon38 in
|
||||
[#18209](https://github.com/google-gemini/gemini-cli/pull/18209)
|
||||
- feat(plan): add exit_plan_mode ui and prompt by @jerop in
|
||||
[#18162](https://github.com/google-gemini/gemini-cli/pull/18162)
|
||||
- fix(test): improve test isolation and enable subagent evaluations by
|
||||
@cocosheng-g in
|
||||
[#18138](https://github.com/google-gemini/gemini-cli/pull/18138)
|
||||
- feat(plan): use custom deny messages in plan mode policies by @Adib234 in
|
||||
[#18195](https://github.com/google-gemini/gemini-cli/pull/18195)
|
||||
- Match on extension ID when stopping extensions by @chrstnb in
|
||||
[#18218](https://github.com/google-gemini/gemini-cli/pull/18218)
|
||||
- fix(core): Respect user's .gitignore preference by @xyrolle in
|
||||
[#15482](https://github.com/google-gemini/gemini-cli/pull/15482)
|
||||
- docs: document GEMINI_CLI_HOME environment variable by @adamfweidman in
|
||||
[#18219](https://github.com/google-gemini/gemini-cli/pull/18219)
|
||||
- chore(core): explicitly state plan storage path in prompt by @jerop in
|
||||
[#18222](https://github.com/google-gemini/gemini-cli/pull/18222)
|
||||
- A2a admin setting by @DavidAPierce in
|
||||
[#17868](https://github.com/google-gemini/gemini-cli/pull/17868)
|
||||
- feat(a2a): Add pluggable auth provider infrastructure by @adamfweidman in
|
||||
[#17934](https://github.com/google-gemini/gemini-cli/pull/17934)
|
||||
- Fix handling of empty settings by @chrstnb in
|
||||
[#18131](https://github.com/google-gemini/gemini-cli/pull/18131)
|
||||
- Reload skills when extensions change by @chrstnb in
|
||||
[#18225](https://github.com/google-gemini/gemini-cli/pull/18225)
|
||||
- feat: Add markdown rendering to ask_user tool by @jackwotherspoon in
|
||||
[#18211](https://github.com/google-gemini/gemini-cli/pull/18211)
|
||||
- Add telemetry to rewind by @Adib234 in
|
||||
[#18122](https://github.com/google-gemini/gemini-cli/pull/18122)
|
||||
- feat(admin): add support for MCP configuration via admin controls (pt1) by
|
||||
@skeshive in [#18223](https://github.com/google-gemini/gemini-cli/pull/18223)
|
||||
- feat(core): require user consent before MCP server OAuth by @ehedlund in
|
||||
[#18132](https://github.com/google-gemini/gemini-cli/pull/18132)
|
||||
- fix(sandbox): propagate GOOGLE_GEMINI_BASE_URL&GOOGLE_VERTEX_BASE_URL env vars
|
||||
by @skeshive in
|
||||
[#18231](https://github.com/google-gemini/gemini-cli/pull/18231)
|
||||
- feat(ui): move user identity display to header by @sehoon38 in
|
||||
[#18216](https://github.com/google-gemini/gemini-cli/pull/18216)
|
||||
- fix: enforce folder trust for workspace settings, skills, and context by
|
||||
@galz10 in [#17596](https://github.com/google-gemini/gemini-cli/pull/17596)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.29.7...v0.30.0
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.27.0...v0.28.0
|
||||
|
||||
+350
-395
@@ -1,6 +1,6 @@
|
||||
# Preview release: v0.31.0-preview.0
|
||||
# Preview release: Release v0.29.0-preview.0
|
||||
|
||||
Released: February 25, 2026
|
||||
Released: February 10, 2026
|
||||
|
||||
Our preview release includes the latest, new, and experimental features. This
|
||||
release may not be as stable as our [latest weekly release](latest.md).
|
||||
@@ -13,400 +13,355 @@ npm install -g @google/gemini-cli@preview
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Plan Mode Enhancements**: Numerous additions including automatic model
|
||||
switching, custom storage directory configuration, message injection upon
|
||||
manual exit, enforcement of read-only constraints, and centralized tool
|
||||
visibility in the policy engine.
|
||||
- **Policy Engine Updates**: Project-level policy support added, alongside MCP
|
||||
server wildcard support, tool annotation propagation and matching, and
|
||||
workspace-level "Always Allow" persistence.
|
||||
- **MCP Integration Improvements**: Better integration through support for MCP
|
||||
progress updates with input validation and throttling, environment variable
|
||||
expansion for servers, and full details expansion on tool approval.
|
||||
- **CLI & Core UX Enhancements**: Several UI and quality-of-life updates such as
|
||||
Alt+D for forward word deletion, macOS run-event notifications, enhanced
|
||||
folder trust configurations with security warnings, improved startup warnings,
|
||||
and a new experimental browser agent.
|
||||
- **Security & Stability**: Introduced the Conseca framework, deceptive URL and
|
||||
Unicode character detection, stricter access checks, rate limits on web fetch,
|
||||
and resolved multiple dependency vulnerabilities.
|
||||
- **Plan Mode Enhancements**: Significant updates to Plan Mode, including new
|
||||
commands, support for MCP servers, integration of planning artifacts, and
|
||||
improved iteration guidance.
|
||||
- **Core Agent Improvements**: Enhancements to the core agent, including better
|
||||
system prompt rigor, improved subagent definitions, and enhanced tool
|
||||
execution limits.
|
||||
- **CLI UX/UI Updates**: Various UI and UX improvements, such as autocomplete in
|
||||
the input prompt, updated approval mode labels, DevTools integration, and
|
||||
improved header spacing.
|
||||
- **Tooling & Extension Updates**: Improvements to existing tools like
|
||||
`ask_user` and `grep_search`, and new features for extension management.
|
||||
- **Bug Fixes**: Numerous bug fixes across the CLI and core, addressing issues
|
||||
with interactive commands, memory leaks, permission checks, and more.
|
||||
- **Context and Tool Output Management**: Features for observation masking for
|
||||
tool outputs, session-linked tool output storage, and persistence for masked
|
||||
tool outputs.
|
||||
|
||||
## What's Changed
|
||||
|
||||
- Use ranged reads and limited searches and fuzzy editing improvements by
|
||||
@gundermanc in
|
||||
[#19240](https://github.com/google-gemini/gemini-cli/pull/19240)
|
||||
- Fix bottom border color by @jacob314 in
|
||||
[#19266](https://github.com/google-gemini/gemini-cli/pull/19266)
|
||||
- Release note generator fix by @g-samroberts in
|
||||
[#19363](https://github.com/google-gemini/gemini-cli/pull/19363)
|
||||
- test(evals): add behavioral tests for tool output masking by @NTaylorMullen in
|
||||
[#19172](https://github.com/google-gemini/gemini-cli/pull/19172)
|
||||
- docs: clarify preflight instructions in GEMINI.md by @NTaylorMullen in
|
||||
[#19377](https://github.com/google-gemini/gemini-cli/pull/19377)
|
||||
- feat(cli): add gemini --resume hint on exit by @Mag1ck in
|
||||
[#16285](https://github.com/google-gemini/gemini-cli/pull/16285)
|
||||
- fix: optimize height calculations for ask_user dialog by @jackwotherspoon in
|
||||
[#19017](https://github.com/google-gemini/gemini-cli/pull/19017)
|
||||
- feat(cli): add Alt+D for forward word deletion by @scidomino in
|
||||
[#19300](https://github.com/google-gemini/gemini-cli/pull/19300)
|
||||
- Disable failing eval test by @chrstnb in
|
||||
[#19455](https://github.com/google-gemini/gemini-cli/pull/19455)
|
||||
- fix(cli): support legacy onConfirm callback in ToolActionsContext by
|
||||
@SandyTao520 in
|
||||
[#19369](https://github.com/google-gemini/gemini-cli/pull/19369)
|
||||
- chore(deps): bump tar from 7.5.7 to 7.5.8 by dependabot[bot] in
|
||||
[#19367](https://github.com/google-gemini/gemini-cli/pull/19367)
|
||||
- fix(plan): allow safe fallback when experiment setting for plan is not enabled
|
||||
but approval mode at startup is plan by @Adib234 in
|
||||
[#19439](https://github.com/google-gemini/gemini-cli/pull/19439)
|
||||
- Add explicit color-convert dependency by @chrstnb in
|
||||
[#19460](https://github.com/google-gemini/gemini-cli/pull/19460)
|
||||
- feat(devtools): migrate devtools package into monorepo by @SandyTao520 in
|
||||
[#18936](https://github.com/google-gemini/gemini-cli/pull/18936)
|
||||
- fix(core): clarify plan mode constraints and exit mechanism by @jerop in
|
||||
[#19438](https://github.com/google-gemini/gemini-cli/pull/19438)
|
||||
- feat(cli): add macOS run-event notifications (interactive only) by
|
||||
@LyalinDotCom in
|
||||
[#19056](https://github.com/google-gemini/gemini-cli/pull/19056)
|
||||
- Changelog for v0.29.0 by @gemini-cli-robot in
|
||||
[#19361](https://github.com/google-gemini/gemini-cli/pull/19361)
|
||||
- fix(ui): preventing empty history items from being added by @devr0306 in
|
||||
[#19014](https://github.com/google-gemini/gemini-cli/pull/19014)
|
||||
- Changelog for v0.30.0-preview.0 by @gemini-cli-robot in
|
||||
[#19364](https://github.com/google-gemini/gemini-cli/pull/19364)
|
||||
- feat(core): add support for MCP progress updates by @NTaylorMullen in
|
||||
[#19046](https://github.com/google-gemini/gemini-cli/pull/19046)
|
||||
- fix(core): ensure directory exists before writing conversation file by
|
||||
@godwiniheuwa in
|
||||
[#18429](https://github.com/google-gemini/gemini-cli/pull/18429)
|
||||
- fix(ui): move margin from top to bottom in ToolGroupMessage by @imadraude in
|
||||
[#17198](https://github.com/google-gemini/gemini-cli/pull/17198)
|
||||
- fix(cli): treat unknown slash commands as regular input instead of showing
|
||||
error by @skyvanguard in
|
||||
[#17393](https://github.com/google-gemini/gemini-cli/pull/17393)
|
||||
- feat(core): experimental in-progress steering hints (2 of 2) by @joshualitt in
|
||||
[#19307](https://github.com/google-gemini/gemini-cli/pull/19307)
|
||||
- docs(plan): add documentation for plan mode command by @Adib234 in
|
||||
[#19467](https://github.com/google-gemini/gemini-cli/pull/19467)
|
||||
- fix(core): ripgrep fails when pattern looks like ripgrep flag by @syvb in
|
||||
[#18858](https://github.com/google-gemini/gemini-cli/pull/18858)
|
||||
- fix(cli): disable auto-completion on Shift+Tab to preserve mode cycling by
|
||||
@NTaylorMullen in
|
||||
[#19451](https://github.com/google-gemini/gemini-cli/pull/19451)
|
||||
- use issuer instead of authorization_endpoint for oauth discovery by
|
||||
@garrettsparks in
|
||||
[#17332](https://github.com/google-gemini/gemini-cli/pull/17332)
|
||||
- feat(cli): include `/dir add` directories in @ autocomplete suggestions by
|
||||
@jasmeetsb in [#19246](https://github.com/google-gemini/gemini-cli/pull/19246)
|
||||
- feat(admin): Admin settings should only apply if adminControlsApplicable =
|
||||
true and fetch errors should be fatal by @skeshive in
|
||||
[#19453](https://github.com/google-gemini/gemini-cli/pull/19453)
|
||||
- Format strict-development-rules command by @g-samroberts in
|
||||
[#19484](https://github.com/google-gemini/gemini-cli/pull/19484)
|
||||
- feat(core): centralize compatibility checks and add TrueColor detection by
|
||||
@spencer426 in
|
||||
[#19478](https://github.com/google-gemini/gemini-cli/pull/19478)
|
||||
- Remove unused files and update index and sidebar. by @g-samroberts in
|
||||
[#19479](https://github.com/google-gemini/gemini-cli/pull/19479)
|
||||
- Migrate core render util to use xterm.js as part of the rendering loop. by
|
||||
@jacob314 in [#19044](https://github.com/google-gemini/gemini-cli/pull/19044)
|
||||
- Changelog for v0.30.0-preview.1 by @gemini-cli-robot in
|
||||
[#19496](https://github.com/google-gemini/gemini-cli/pull/19496)
|
||||
- build: replace deprecated built-in punycode with userland package by @jacob314
|
||||
in [#19502](https://github.com/google-gemini/gemini-cli/pull/19502)
|
||||
- Speculative fixes to try to fix react error. by @jacob314 in
|
||||
[#19508](https://github.com/google-gemini/gemini-cli/pull/19508)
|
||||
- fix spacing by @jacob314 in
|
||||
[#19494](https://github.com/google-gemini/gemini-cli/pull/19494)
|
||||
- fix(core): ensure user rejections update tool outcome for telemetry by
|
||||
@abhiasap in [#18982](https://github.com/google-gemini/gemini-cli/pull/18982)
|
||||
- fix(acp): Initialize config (#18897) by @Mervap in
|
||||
[#18898](https://github.com/google-gemini/gemini-cli/pull/18898)
|
||||
- fix(core): add error logging for IDE fetch failures by @yuvrajangadsingh in
|
||||
[#17981](https://github.com/google-gemini/gemini-cli/pull/17981)
|
||||
- feat(acp): support set_mode interface (#18890) by @Mervap in
|
||||
[#18891](https://github.com/google-gemini/gemini-cli/pull/18891)
|
||||
- fix(core): robust workspace-based IDE connection discovery by @ehedlund in
|
||||
[#18443](https://github.com/google-gemini/gemini-cli/pull/18443)
|
||||
- Deflake windows tests. by @jacob314 in
|
||||
[#19511](https://github.com/google-gemini/gemini-cli/pull/19511)
|
||||
- Fix: Avoid tool confirmation timeout when no UI listeners are present by
|
||||
@pdHaku0 in [#17955](https://github.com/google-gemini/gemini-cli/pull/17955)
|
||||
- format md file by @scidomino in
|
||||
[#19474](https://github.com/google-gemini/gemini-cli/pull/19474)
|
||||
- feat(cli): add experimental.useOSC52Copy setting by @scidomino in
|
||||
[#19488](https://github.com/google-gemini/gemini-cli/pull/19488)
|
||||
- feat(cli): replace loading phrases boolean with enum setting by @LyalinDotCom
|
||||
in [#19347](https://github.com/google-gemini/gemini-cli/pull/19347)
|
||||
- Update skill to adjust for generated results. by @g-samroberts in
|
||||
[#19500](https://github.com/google-gemini/gemini-cli/pull/19500)
|
||||
- Fix message too large issue. by @gundermanc in
|
||||
[#19499](https://github.com/google-gemini/gemini-cli/pull/19499)
|
||||
- fix(core): prevent duplicate tool approval entries in auto-saved.toml by
|
||||
@Abhijit-2592 in
|
||||
[#19487](https://github.com/google-gemini/gemini-cli/pull/19487)
|
||||
- fix(core): resolve crash in ClearcutLogger when os.cpus() is empty by @Adib234
|
||||
in [#19555](https://github.com/google-gemini/gemini-cli/pull/19555)
|
||||
- chore(core): improve encapsulation and remove unused exports by @adamfweidman
|
||||
in [#19556](https://github.com/google-gemini/gemini-cli/pull/19556)
|
||||
- Revert "Add generic searchable list to back settings and extensions (… by
|
||||
@chrstnb in [#19434](https://github.com/google-gemini/gemini-cli/pull/19434)
|
||||
- fix(core): improve error type extraction for telemetry by @yunaseoul in
|
||||
[#19565](https://github.com/google-gemini/gemini-cli/pull/19565)
|
||||
- fix: remove extra padding in Composer by @jackwotherspoon in
|
||||
[#19529](https://github.com/google-gemini/gemini-cli/pull/19529)
|
||||
- feat(plan): support configuring custom plans storage directory by @jerop in
|
||||
[#19577](https://github.com/google-gemini/gemini-cli/pull/19577)
|
||||
- Migrate files to resource or references folder. by @g-samroberts in
|
||||
[#19503](https://github.com/google-gemini/gemini-cli/pull/19503)
|
||||
- feat(policy): implement project-level policy support by @Abhijit-2592 in
|
||||
[#18682](https://github.com/google-gemini/gemini-cli/pull/18682)
|
||||
- feat(core): Implement parallel FC for read only tools. by @joshualitt in
|
||||
[#18791](https://github.com/google-gemini/gemini-cli/pull/18791)
|
||||
- chore(skills): adds pr-address-comments skill to work on PR feedback by
|
||||
@mbleigh in [#19576](https://github.com/google-gemini/gemini-cli/pull/19576)
|
||||
- refactor(sdk): introduce session-based architecture by @mbleigh in
|
||||
[#19180](https://github.com/google-gemini/gemini-cli/pull/19180)
|
||||
- fix(ci): add fallback JSON extraction to issue triage workflow by @bdmorgan in
|
||||
[#19593](https://github.com/google-gemini/gemini-cli/pull/19593)
|
||||
- feat(core): refine Edit and WriteFile tool schemas for Gemini 3 by
|
||||
@SandyTao520 in
|
||||
[#19476](https://github.com/google-gemini/gemini-cli/pull/19476)
|
||||
- Changelog for v0.30.0-preview.3 by @gemini-cli-robot in
|
||||
[#19585](https://github.com/google-gemini/gemini-cli/pull/19585)
|
||||
- fix(plan): exclude EnterPlanMode tool from YOLO mode by @Adib234 in
|
||||
[#19570](https://github.com/google-gemini/gemini-cli/pull/19570)
|
||||
- chore: resolve build warnings and update dependencies by @mattKorwel in
|
||||
[#18880](https://github.com/google-gemini/gemini-cli/pull/18880)
|
||||
- feat(ui): add source indicators to slash commands by @ehedlund in
|
||||
[#18839](https://github.com/google-gemini/gemini-cli/pull/18839)
|
||||
- docs: refine Plan Mode documentation structure and workflow by @jerop in
|
||||
[#19644](https://github.com/google-gemini/gemini-cli/pull/19644)
|
||||
- Docs: Update release information regarding Gemini 3.1 by @jkcinouye in
|
||||
[#19568](https://github.com/google-gemini/gemini-cli/pull/19568)
|
||||
- fix(security): rate limit web_fetch tool to mitigate DDoS via prompt injection
|
||||
by @mattKorwel in
|
||||
[#19567](https://github.com/google-gemini/gemini-cli/pull/19567)
|
||||
- Add initial implementation of /extensions explore command by @chrstnb in
|
||||
[#19029](https://github.com/google-gemini/gemini-cli/pull/19029)
|
||||
- fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (#18760) by
|
||||
@maximus12793 in
|
||||
[#19038](https://github.com/google-gemini/gemini-cli/pull/19038)
|
||||
- Search updates by @alisa-alisa in
|
||||
[#19482](https://github.com/google-gemini/gemini-cli/pull/19482)
|
||||
- feat(cli): add support for numpad SS3 sequences by @scidomino in
|
||||
[#19659](https://github.com/google-gemini/gemini-cli/pull/19659)
|
||||
- feat(cli): enhance folder trust with configuration discovery and security
|
||||
warnings by @galz10 in
|
||||
[#19492](https://github.com/google-gemini/gemini-cli/pull/19492)
|
||||
- feat(ui): improve startup warnings UX with dismissal and show-count limits by
|
||||
@spencer426 in
|
||||
[#19584](https://github.com/google-gemini/gemini-cli/pull/19584)
|
||||
- feat(a2a): Add API key authentication provider by @adamfweidman in
|
||||
[#19548](https://github.com/google-gemini/gemini-cli/pull/19548)
|
||||
- Send accepted/removed lines with ACCEPT_FILE telemetry. by @gundermanc in
|
||||
[#19670](https://github.com/google-gemini/gemini-cli/pull/19670)
|
||||
- feat(models): support Gemini 3.1 Pro Preview and fixes by @sehoon38 in
|
||||
[#19676](https://github.com/google-gemini/gemini-cli/pull/19676)
|
||||
- feat(plan): enforce read-only constraints in Plan Mode by @mattKorwel in
|
||||
[#19433](https://github.com/google-gemini/gemini-cli/pull/19433)
|
||||
- fix(cli): allow perfect match @scripts/test-windows-paths.js completions to
|
||||
submit on Enter by @spencer426 in
|
||||
[#19562](https://github.com/google-gemini/gemini-cli/pull/19562)
|
||||
- fix(core): treat 503 Service Unavailable as retryable quota error by @sehoon38
|
||||
in [#19642](https://github.com/google-gemini/gemini-cli/pull/19642)
|
||||
- Update sidebar.json for to allow top nav tabs. by @g-samroberts in
|
||||
[#19595](https://github.com/google-gemini/gemini-cli/pull/19595)
|
||||
- security: strip deceptive Unicode characters from terminal output by @ehedlund
|
||||
in [#19026](https://github.com/google-gemini/gemini-cli/pull/19026)
|
||||
- Fixes 'input.on' is not a function error in Gemini CLI by @gundermanc in
|
||||
[#19691](https://github.com/google-gemini/gemini-cli/pull/19691)
|
||||
- Revert "feat(ui): add source indicators to slash commands" by @ehedlund in
|
||||
[#19695](https://github.com/google-gemini/gemini-cli/pull/19695)
|
||||
- security: implement deceptive URL detection and disclosure in tool
|
||||
confirmations by @ehedlund in
|
||||
[#19288](https://github.com/google-gemini/gemini-cli/pull/19288)
|
||||
- fix(core): restore auth consent in headless mode and add unit tests by
|
||||
@ehedlund in [#19689](https://github.com/google-gemini/gemini-cli/pull/19689)
|
||||
- Fix unsafe assertions in code_assist folder. by @gundermanc in
|
||||
[#19706](https://github.com/google-gemini/gemini-cli/pull/19706)
|
||||
- feat(cli): make JetBrains warning more specific by @jacob314 in
|
||||
[#19687](https://github.com/google-gemini/gemini-cli/pull/19687)
|
||||
- fix(cli): extensions dialog UX polish by @jacob314 in
|
||||
[#19685](https://github.com/google-gemini/gemini-cli/pull/19685)
|
||||
- fix(cli): use getDisplayString for manual model selection in dialog by
|
||||
@sehoon38 in [#19726](https://github.com/google-gemini/gemini-cli/pull/19726)
|
||||
- feat(policy): repurpose "Always Allow" persistence to workspace level by
|
||||
@Abhijit-2592 in
|
||||
[#19707](https://github.com/google-gemini/gemini-cli/pull/19707)
|
||||
- fix(cli): re-enable CLI banner by @sehoon38 in
|
||||
[#19741](https://github.com/google-gemini/gemini-cli/pull/19741)
|
||||
- Disallow and suppress unsafe assignment by @gundermanc in
|
||||
[#19736](https://github.com/google-gemini/gemini-cli/pull/19736)
|
||||
- feat(core): migrate read_file to 1-based start_line/end_line parameters by
|
||||
@adamfweidman in
|
||||
[#19526](https://github.com/google-gemini/gemini-cli/pull/19526)
|
||||
- feat(cli): improve CTRL+O experience for both standard and alternate screen
|
||||
buffer (ASB) modes by @jwhelangoog in
|
||||
[#19010](https://github.com/google-gemini/gemini-cli/pull/19010)
|
||||
- Utilize pipelining of grep_search -> read_file to eliminate turns by
|
||||
@gundermanc in
|
||||
[#19574](https://github.com/google-gemini/gemini-cli/pull/19574)
|
||||
- refactor(core): remove unsafe type assertions in error utils (Phase 1.1) by
|
||||
@mattKorwel in
|
||||
[#19750](https://github.com/google-gemini/gemini-cli/pull/19750)
|
||||
- Disallow unsafe returns. by @gundermanc in
|
||||
[#19767](https://github.com/google-gemini/gemini-cli/pull/19767)
|
||||
- fix(cli): filter subagent sessions from resume history by @abhipatel12 in
|
||||
[#19698](https://github.com/google-gemini/gemini-cli/pull/19698)
|
||||
- chore(lint): fix lint errors seen when running npm run lint by @abhipatel12 in
|
||||
[#19844](https://github.com/google-gemini/gemini-cli/pull/19844)
|
||||
- feat(core): remove unnecessary login verbiage from Code Assist auth by
|
||||
@NTaylorMullen in
|
||||
[#19861](https://github.com/google-gemini/gemini-cli/pull/19861)
|
||||
- fix(plan): time share by approval mode dashboard reporting negative time
|
||||
shares by @Adib234 in
|
||||
[#19847](https://github.com/google-gemini/gemini-cli/pull/19847)
|
||||
- fix(core): allow any preview model in quota access check by @bdmorgan in
|
||||
[#19867](https://github.com/google-gemini/gemini-cli/pull/19867)
|
||||
- fix(core): prevent omission placeholder deletions in replace/write_file by
|
||||
@nsalerni in [#19870](https://github.com/google-gemini/gemini-cli/pull/19870)
|
||||
- fix(core): add uniqueness guard to edit tool by @Shivangisharma4 in
|
||||
[#19890](https://github.com/google-gemini/gemini-cli/pull/19890)
|
||||
- refactor(config): remove enablePromptCompletion from settings by @sehoon38 in
|
||||
[#19974](https://github.com/google-gemini/gemini-cli/pull/19974)
|
||||
- refactor(core): move session conversion logic to core by @abhipatel12 in
|
||||
[#19972](https://github.com/google-gemini/gemini-cli/pull/19972)
|
||||
- Fix: Persist manual model selection on restart #19864 by @Nixxx19 in
|
||||
[#19891](https://github.com/google-gemini/gemini-cli/pull/19891)
|
||||
- fix(core): increase default retry attempts and add quota error backoff by
|
||||
@sehoon38 in [#19949](https://github.com/google-gemini/gemini-cli/pull/19949)
|
||||
- feat(core): add policy chain support for Gemini 3.1 by @sehoon38 in
|
||||
[#19991](https://github.com/google-gemini/gemini-cli/pull/19991)
|
||||
- Updates command reference and /stats command. by @g-samroberts in
|
||||
[#19794](https://github.com/google-gemini/gemini-cli/pull/19794)
|
||||
- Fix for silent failures in non-interactive mode by @owenofbrien in
|
||||
[#19905](https://github.com/google-gemini/gemini-cli/pull/19905)
|
||||
- fix(plan): allow plan mode writes on Windows and fix prompt paths by @Adib234
|
||||
in [#19658](https://github.com/google-gemini/gemini-cli/pull/19658)
|
||||
- fix(core): prevent OAuth server crash on unexpected requests by @reyyanxahmed
|
||||
in [#19668](https://github.com/google-gemini/gemini-cli/pull/19668)
|
||||
- feat: Map tool kinds to explicit ACP.ToolKind values and update test … by
|
||||
@sripasg in [#19547](https://github.com/google-gemini/gemini-cli/pull/19547)
|
||||
- chore: restrict gemini-automted-issue-triage to only allow echo by @galz10 in
|
||||
[#20047](https://github.com/google-gemini/gemini-cli/pull/20047)
|
||||
- Allow ask headers longer than 16 chars by @scidomino in
|
||||
[#20041](https://github.com/google-gemini/gemini-cli/pull/20041)
|
||||
- fix(core): prevent state corruption in McpClientManager during collis by @h30s
|
||||
in [#19782](https://github.com/google-gemini/gemini-cli/pull/19782)
|
||||
- fix(bundling): copy devtools package to bundle for runtime resolution by
|
||||
@SandyTao520 in
|
||||
[#19766](https://github.com/google-gemini/gemini-cli/pull/19766)
|
||||
- feat(policy): Support MCP Server Wildcards in Policy Engine by @jerop in
|
||||
[#20024](https://github.com/google-gemini/gemini-cli/pull/20024)
|
||||
- docs(CONTRIBUTING): update React DevTools version to 6 by @mmgok in
|
||||
[#20014](https://github.com/google-gemini/gemini-cli/pull/20014)
|
||||
- feat(core): optimize tool descriptions and schemas for Gemini 3 by
|
||||
@aishaneeshah in
|
||||
[#19643](https://github.com/google-gemini/gemini-cli/pull/19643)
|
||||
- feat(core): implement experimental direct web fetch by @mbleigh in
|
||||
[#19557](https://github.com/google-gemini/gemini-cli/pull/19557)
|
||||
- feat(core): replace expected_replacements with allow_multiple in replace tool
|
||||
by @SandyTao520 in
|
||||
[#20033](https://github.com/google-gemini/gemini-cli/pull/20033)
|
||||
- fix(sandbox): harden image packaging integrity checks by @aviralgarg05 in
|
||||
[#19552](https://github.com/google-gemini/gemini-cli/pull/19552)
|
||||
- fix(core): allow environment variable expansion and explicit overrides for MCP
|
||||
servers by @galz10 in
|
||||
[#18837](https://github.com/google-gemini/gemini-cli/pull/18837)
|
||||
- feat(policy): Implement Tool Annotation Matching in Policy Engine by @jerop in
|
||||
[#20029](https://github.com/google-gemini/gemini-cli/pull/20029)
|
||||
- fix(core): prevent utility calls from changing session active model by
|
||||
@adamfweidman in
|
||||
[#20035](https://github.com/google-gemini/gemini-cli/pull/20035)
|
||||
- fix(cli): skip workspace policy loading when in home directory by
|
||||
@Abhijit-2592 in
|
||||
[#20054](https://github.com/google-gemini/gemini-cli/pull/20054)
|
||||
- fix(scripts): Add Windows (win32/x64) support to lint.js by @ZafeerMahmood in
|
||||
[#16193](https://github.com/google-gemini/gemini-cli/pull/16193)
|
||||
- fix(a2a-server): Remove unsafe type assertions in agent by @Nixxx19 in
|
||||
[#19723](https://github.com/google-gemini/gemini-cli/pull/19723)
|
||||
- Fix: Handle corrupted token file gracefully when switching auth types (#19845)
|
||||
by @Nixxx19 in
|
||||
[#19850](https://github.com/google-gemini/gemini-cli/pull/19850)
|
||||
- fix critical dep vulnerability by @scidomino in
|
||||
[#20087](https://github.com/google-gemini/gemini-cli/pull/20087)
|
||||
- Add new setting to configure maxRetries by @kevinjwang1 in
|
||||
[#20064](https://github.com/google-gemini/gemini-cli/pull/20064)
|
||||
- Stabilize tests. by @gundermanc in
|
||||
[#20095](https://github.com/google-gemini/gemini-cli/pull/20095)
|
||||
- make windows tests mandatory by @scidomino in
|
||||
[#20096](https://github.com/google-gemini/gemini-cli/pull/20096)
|
||||
- Add 3.1 pro preview to behavioral evals. by @gundermanc in
|
||||
[#20088](https://github.com/google-gemini/gemini-cli/pull/20088)
|
||||
- feat:PR-rate-limit by @JagjeevanAK in
|
||||
[#19804](https://github.com/google-gemini/gemini-cli/pull/19804)
|
||||
- feat(cli): allow expanding full details of MCP tool on approval by @y-okt in
|
||||
[#19916](https://github.com/google-gemini/gemini-cli/pull/19916)
|
||||
- feat(security): Introduce Conseca framework by @shrishabh in
|
||||
[#13193](https://github.com/google-gemini/gemini-cli/pull/13193)
|
||||
- fix(cli): Remove unsafe type assertions in activityLogger #19713 by @Nixxx19
|
||||
in [#19745](https://github.com/google-gemini/gemini-cli/pull/19745)
|
||||
- feat: implement AfterTool tail tool calls by @googlestrobe in
|
||||
[#18486](https://github.com/google-gemini/gemini-cli/pull/18486)
|
||||
- ci(actions): fix PR rate limiter excluding maintainers by @scidomino in
|
||||
[#20117](https://github.com/google-gemini/gemini-cli/pull/20117)
|
||||
- Shortcuts: Move SectionHeader title below top line and refine styling by
|
||||
@keithguerin in
|
||||
[#18721](https://github.com/google-gemini/gemini-cli/pull/18721)
|
||||
- refactor(ui): Update and simplify use of gray colors in themes by @keithguerin
|
||||
in [#20141](https://github.com/google-gemini/gemini-cli/pull/20141)
|
||||
- fix punycode2 by @jacob314 in
|
||||
[#20154](https://github.com/google-gemini/gemini-cli/pull/20154)
|
||||
- feat(ide): add GEMINI_CLI_IDE_PID env var to override IDE process detection by
|
||||
@kiryltech in [#15842](https://github.com/google-gemini/gemini-cli/pull/15842)
|
||||
- feat(policy): Propagate Tool Annotations for MCP Servers by @jerop in
|
||||
[#20083](https://github.com/google-gemini/gemini-cli/pull/20083)
|
||||
- fix(a2a-server): pass allowedTools settings to core Config by @reyyanxahmed in
|
||||
[#19680](https://github.com/google-gemini/gemini-cli/pull/19680)
|
||||
- feat(mcp): add progress bar, throttling, and input validation for MCP tool
|
||||
progress by @jasmeetsb in
|
||||
[#19772](https://github.com/google-gemini/gemini-cli/pull/19772)
|
||||
- feat(policy): centralize plan mode tool visibility in policy engine by @jerop
|
||||
in [#20178](https://github.com/google-gemini/gemini-cli/pull/20178)
|
||||
- feat(browser): implement experimental browser agent by @gsquared94 in
|
||||
[#19284](https://github.com/google-gemini/gemini-cli/pull/19284)
|
||||
- feat(plan): summarize work after executing a plan by @jerop in
|
||||
[#19432](https://github.com/google-gemini/gemini-cli/pull/19432)
|
||||
- fix(core): create new McpClient on restart to apply updated config by @h30s in
|
||||
[#20126](https://github.com/google-gemini/gemini-cli/pull/20126)
|
||||
- Changelog for v0.30.0-preview.5 by @gemini-cli-robot in
|
||||
[#20107](https://github.com/google-gemini/gemini-cli/pull/20107)
|
||||
- Update packages. by @jacob314 in
|
||||
[#20152](https://github.com/google-gemini/gemini-cli/pull/20152)
|
||||
- Fix extension env dir loading issue by @chrstnb in
|
||||
[#20198](https://github.com/google-gemini/gemini-cli/pull/20198)
|
||||
- restrict /assign to help-wanted issues by @scidomino in
|
||||
[#20207](https://github.com/google-gemini/gemini-cli/pull/20207)
|
||||
- feat(plan): inject message when user manually exits Plan mode by @jerop in
|
||||
[#20203](https://github.com/google-gemini/gemini-cli/pull/20203)
|
||||
- feat(extensions): enforce folder trust for local extension install by @galz10
|
||||
in [#19703](https://github.com/google-gemini/gemini-cli/pull/19703)
|
||||
- feat(hooks): adds support for RuntimeHook functions. by @mbleigh in
|
||||
[#19598](https://github.com/google-gemini/gemini-cli/pull/19598)
|
||||
- Docs: Update UI links. by @jkcinouye in
|
||||
[#20224](https://github.com/google-gemini/gemini-cli/pull/20224)
|
||||
- feat: prompt users to run /terminal-setup with yes/no by @ishaanxgupta in
|
||||
[#16235](https://github.com/google-gemini/gemini-cli/pull/16235)
|
||||
- fix: additional high vulnerabilities (minimatch, cross-spawn) by @adamfweidman
|
||||
in [#20221](https://github.com/google-gemini/gemini-cli/pull/20221)
|
||||
- feat(telemetry): Add context breakdown to API response event by @SandyTao520
|
||||
in [#19699](https://github.com/google-gemini/gemini-cli/pull/19699)
|
||||
- Docs: Add nested sub-folders for related topics by @g-samroberts in
|
||||
[#20235](https://github.com/google-gemini/gemini-cli/pull/20235)
|
||||
- feat(plan): support automatic model switching for Plan Mode by @jerop in
|
||||
[#20240](https://github.com/google-gemini/gemini-cli/pull/20240)
|
||||
- fix: remove ask_user tool from non-interactive modes by jackwotherspoon in
|
||||
[#18154](https://github.com/google-gemini/gemini-cli/pull/18154)
|
||||
- fix(cli): allow restricted .env loading in untrusted sandboxed folders by
|
||||
galz10 in [#17806](https://github.com/google-gemini/gemini-cli/pull/17806)
|
||||
- Encourage agent to utilize ecosystem tools to perform work by gundermanc in
|
||||
[#17881](https://github.com/google-gemini/gemini-cli/pull/17881)
|
||||
- feat(plan): unify workflow location in system prompt to optimize caching by
|
||||
jerop in [#18258](https://github.com/google-gemini/gemini-cli/pull/18258)
|
||||
- feat(core): enable getUserTierName in config by sehoon38 in
|
||||
[#18265](https://github.com/google-gemini/gemini-cli/pull/18265)
|
||||
- feat(core): add default execution limits for subagents by abhipatel12 in
|
||||
[#18274](https://github.com/google-gemini/gemini-cli/pull/18274)
|
||||
- Fix issue where agent gets stuck at interactive commands. by gundermanc in
|
||||
[#18272](https://github.com/google-gemini/gemini-cli/pull/18272)
|
||||
- chore(release): bump version to 0.29.0-nightly.20260203.71f46f116 by
|
||||
gemini-cli-robot in
|
||||
[#18243](https://github.com/google-gemini/gemini-cli/pull/18243)
|
||||
- feat(core): remove hardcoded policy bypass for local subagents by abhipatel12
|
||||
in [#18153](https://github.com/google-gemini/gemini-cli/pull/18153)
|
||||
- feat(plan): implement plan slash command by Adib234 in
|
||||
[#17698](https://github.com/google-gemini/gemini-cli/pull/17698)
|
||||
- feat: increase ask_user label limit to 16 characters by jackwotherspoon in
|
||||
[#18320](https://github.com/google-gemini/gemini-cli/pull/18320)
|
||||
- Add information about the agent skills lifecycle and clarify docs-writer skill
|
||||
metadata. by g-samroberts in
|
||||
[#18234](https://github.com/google-gemini/gemini-cli/pull/18234)
|
||||
- feat(core): add enter_plan_mode tool by jerop in
|
||||
[#18324](https://github.com/google-gemini/gemini-cli/pull/18324)
|
||||
- Stop showing an error message in /plan by Adib234 in
|
||||
[#18333](https://github.com/google-gemini/gemini-cli/pull/18333)
|
||||
- fix(hooks): remove unnecessary logging for hook registration by abhipatel12 in
|
||||
[#18332](https://github.com/google-gemini/gemini-cli/pull/18332)
|
||||
- fix(mcp): ensure MCP transport is closed to prevent memory leaks by cbcoutinho
|
||||
in [#18054](https://github.com/google-gemini/gemini-cli/pull/18054)
|
||||
- feat(skills): implement linking for agent skills by MushuEE in
|
||||
[#18295](https://github.com/google-gemini/gemini-cli/pull/18295)
|
||||
- Changelogs for 0.27.0 and 0.28.0-preview0 by g-samroberts in
|
||||
[#18336](https://github.com/google-gemini/gemini-cli/pull/18336)
|
||||
- chore: correct docs as skills and hooks are stable by jackwotherspoon in
|
||||
[#18358](https://github.com/google-gemini/gemini-cli/pull/18358)
|
||||
- feat(admin): Implement admin allowlist for MCP server configurations by
|
||||
skeshive in [#18311](https://github.com/google-gemini/gemini-cli/pull/18311)
|
||||
- fix(core): add retry logic for transient SSL/TLS errors
|
||||
([#17318](https://github.com/google-gemini/gemini-cli/pull/17318)) by
|
||||
ppgranger in [#18310](https://github.com/google-gemini/gemini-cli/pull/18310)
|
||||
- Add support for /extensions config command by chrstnb in
|
||||
[#17895](https://github.com/google-gemini/gemini-cli/pull/17895)
|
||||
- fix(core): handle non-compliant mcpbridge responses from Xcode 26.3 by
|
||||
peterfriese in
|
||||
[#18376](https://github.com/google-gemini/gemini-cli/pull/18376)
|
||||
- feat(cli): Add W, B, E Vim motions and operator support by ademuri in
|
||||
[#16209](https://github.com/google-gemini/gemini-cli/pull/16209)
|
||||
- fix: Windows Specific Agent Quality & System Prompt by scidomino in
|
||||
[#18351](https://github.com/google-gemini/gemini-cli/pull/18351)
|
||||
- feat(plan): support replace tool in plan mode to edit plans by jerop in
|
||||
[#18379](https://github.com/google-gemini/gemini-cli/pull/18379)
|
||||
- Improving memory tool instructions and eval testing by alisa-alisa in
|
||||
[#18091](https://github.com/google-gemini/gemini-cli/pull/18091)
|
||||
- fix(cli): color extension link success message green by MushuEE in
|
||||
[#18386](https://github.com/google-gemini/gemini-cli/pull/18386)
|
||||
- undo by jacob314 in
|
||||
[#18147](https://github.com/google-gemini/gemini-cli/pull/18147)
|
||||
- feat(plan): add guidance on iterating on approved plans vs creating new plans
|
||||
by jerop in [#18346](https://github.com/google-gemini/gemini-cli/pull/18346)
|
||||
- feat(plan): fix invalid tool calls in plan mode by Adib234 in
|
||||
[#18352](https://github.com/google-gemini/gemini-cli/pull/18352)
|
||||
- feat(plan): integrate planning artifacts and tools into primary workflows by
|
||||
jerop in [#18375](https://github.com/google-gemini/gemini-cli/pull/18375)
|
||||
- Fix permission check by scidomino in
|
||||
[#18395](https://github.com/google-gemini/gemini-cli/pull/18395)
|
||||
- ux(polish) autocomplete in the input prompt by jacob314 in
|
||||
[#18181](https://github.com/google-gemini/gemini-cli/pull/18181)
|
||||
- fix: resolve infinite loop when using 'Modify with external editor' by
|
||||
ppgranger in [#17453](https://github.com/google-gemini/gemini-cli/pull/17453)
|
||||
- feat: expand verify-release to macOS and Windows by yunaseoul in
|
||||
[#18145](https://github.com/google-gemini/gemini-cli/pull/18145)
|
||||
- feat(plan): implement support for MCP servers in Plan mode by Adib234 in
|
||||
[#18229](https://github.com/google-gemini/gemini-cli/pull/18229)
|
||||
- chore: update folder trust error messaging by galz10 in
|
||||
[#18402](https://github.com/google-gemini/gemini-cli/pull/18402)
|
||||
- feat(plan): create a metric for execution of plans generated in plan mode by
|
||||
Adib234 in [#18236](https://github.com/google-gemini/gemini-cli/pull/18236)
|
||||
- perf(ui): optimize stripUnsafeCharacters with regex by gsquared94 in
|
||||
[#18413](https://github.com/google-gemini/gemini-cli/pull/18413)
|
||||
- feat(context): implement observation masking for tool outputs by abhipatel12
|
||||
in [#18389](https://github.com/google-gemini/gemini-cli/pull/18389)
|
||||
- feat(core,cli): implement session-linked tool output storage and cleanup by
|
||||
abhipatel12 in
|
||||
[#18416](https://github.com/google-gemini/gemini-cli/pull/18416)
|
||||
- Shorten temp directory by joshualitt in
|
||||
[#17901](https://github.com/google-gemini/gemini-cli/pull/17901)
|
||||
- feat(plan): add behavioral evals for plan mode by jerop in
|
||||
[#18437](https://github.com/google-gemini/gemini-cli/pull/18437)
|
||||
- Add extension registry client by chrstnb in
|
||||
[#18396](https://github.com/google-gemini/gemini-cli/pull/18396)
|
||||
- Enable extension config by default by chrstnb in
|
||||
[#18447](https://github.com/google-gemini/gemini-cli/pull/18447)
|
||||
- Automatically generate change logs on release by g-samroberts in
|
||||
[#18401](https://github.com/google-gemini/gemini-cli/pull/18401)
|
||||
- Remove previewFeatures and default to Gemini 3 by sehoon38 in
|
||||
[#18414](https://github.com/google-gemini/gemini-cli/pull/18414)
|
||||
- feat(admin): apply MCP allowlist to extensions & gemini mcp list command by
|
||||
skeshive in [#18442](https://github.com/google-gemini/gemini-cli/pull/18442)
|
||||
- fix(cli): improve focus navigation for interactive and background shells by
|
||||
galz10 in [#18343](https://github.com/google-gemini/gemini-cli/pull/18343)
|
||||
- Add shortcuts hint and panel for discoverability by LyalinDotCom in
|
||||
[#18035](https://github.com/google-gemini/gemini-cli/pull/18035)
|
||||
- fix(config): treat system settings as read-only during migration and warn user
|
||||
by spencer426 in
|
||||
[#18277](https://github.com/google-gemini/gemini-cli/pull/18277)
|
||||
- feat(plan): add positive test case and update eval stability policy by jerop
|
||||
in [#18457](https://github.com/google-gemini/gemini-cli/pull/18457)
|
||||
- fix- windows: add shell: true for spawnSync to fix EINVAL with .cmd editors by
|
||||
zackoch in [#18408](https://github.com/google-gemini/gemini-cli/pull/18408)
|
||||
- bug(core): Fix bug when saving plans. by joshualitt in
|
||||
[#18465](https://github.com/google-gemini/gemini-cli/pull/18465)
|
||||
- Refactor atCommandProcessor by scidomino in
|
||||
[#18461](https://github.com/google-gemini/gemini-cli/pull/18461)
|
||||
- feat(core): implement persistence and resumption for masked tool outputs by
|
||||
abhipatel12 in
|
||||
[#18451](https://github.com/google-gemini/gemini-cli/pull/18451)
|
||||
- refactor: simplify tool output truncation to single config by SandyTao520 in
|
||||
[#18446](https://github.com/google-gemini/gemini-cli/pull/18446)
|
||||
- bug(core): Ensure storage is initialized early, even if config is not. by
|
||||
joshualitt in [#18471](https://github.com/google-gemini/gemini-cli/pull/18471)
|
||||
- chore: Update build-and-start script to support argument forwarding by
|
||||
Abhijit-2592 in
|
||||
[#18241](https://github.com/google-gemini/gemini-cli/pull/18241)
|
||||
- fix(core): prevent subagent bypass in plan mode by jerop in
|
||||
[#18484](https://github.com/google-gemini/gemini-cli/pull/18484)
|
||||
- feat(cli): add WebSocket-based network logging and streaming chunk support by
|
||||
SandyTao520 in
|
||||
[#18383](https://github.com/google-gemini/gemini-cli/pull/18383)
|
||||
- feat(cli): update approval modes UI by jerop in
|
||||
[#18476](https://github.com/google-gemini/gemini-cli/pull/18476)
|
||||
- fix(cli): reload skills and agents on extension restart by NTaylorMullen in
|
||||
[#18411](https://github.com/google-gemini/gemini-cli/pull/18411)
|
||||
- fix(core): expand excludeTools with legacy aliases for renamed tools by
|
||||
SandyTao520 in
|
||||
[#18498](https://github.com/google-gemini/gemini-cli/pull/18498)
|
||||
- feat(core): overhaul system prompt for rigor, integrity, and intent alignment
|
||||
by NTaylorMullen in
|
||||
[#17263](https://github.com/google-gemini/gemini-cli/pull/17263)
|
||||
- Patch for generate changelog docs yaml file by g-samroberts in
|
||||
[#18496](https://github.com/google-gemini/gemini-cli/pull/18496)
|
||||
- Code review fixes for show question mark pr. by jacob314 in
|
||||
[#18480](https://github.com/google-gemini/gemini-cli/pull/18480)
|
||||
- fix(cli): add SS3 Shift+Tab support for Windows terminals by ThanhNguyxn in
|
||||
[#18187](https://github.com/google-gemini/gemini-cli/pull/18187)
|
||||
- chore: remove redundant planning prompt from final shell by jerop in
|
||||
[#18528](https://github.com/google-gemini/gemini-cli/pull/18528)
|
||||
- docs: require pr-creator skill for PR generation by NTaylorMullen in
|
||||
[#18536](https://github.com/google-gemini/gemini-cli/pull/18536)
|
||||
- chore: update colors for ask_user dialog by jackwotherspoon in
|
||||
[#18543](https://github.com/google-gemini/gemini-cli/pull/18543)
|
||||
- feat(core): exempt high-signal tools from output masking by abhipatel12 in
|
||||
[#18545](https://github.com/google-gemini/gemini-cli/pull/18545)
|
||||
- refactor(core): remove memory tool instructions from Gemini 3 prompt by
|
||||
NTaylorMullen in
|
||||
[#18559](https://github.com/google-gemini/gemini-cli/pull/18559)
|
||||
- chore: remove feedback instruction from system prompt by NTaylorMullen in
|
||||
[#18560](https://github.com/google-gemini/gemini-cli/pull/18560)
|
||||
- feat(context): add remote configuration for tool output masking thresholds by
|
||||
abhipatel12 in
|
||||
[#18553](https://github.com/google-gemini/gemini-cli/pull/18553)
|
||||
- feat(core): pause agent timeout budget while waiting for tool confirmation by
|
||||
abhipatel12 in
|
||||
[#18415](https://github.com/google-gemini/gemini-cli/pull/18415)
|
||||
- refactor(config): remove experimental.enableEventDrivenScheduler setting by
|
||||
abhipatel12 in
|
||||
[#17924](https://github.com/google-gemini/gemini-cli/pull/17924)
|
||||
- feat(cli): truncate shell output in UI history and improve active shell
|
||||
display by jwhelangoog in
|
||||
[#17438](https://github.com/google-gemini/gemini-cli/pull/17438)
|
||||
- refactor(cli): switch useToolScheduler to event-driven engine by abhipatel12
|
||||
in [#18565](https://github.com/google-gemini/gemini-cli/pull/18565)
|
||||
- fix(core): correct escaped interpolation in system prompt by NTaylorMullen in
|
||||
[#18557](https://github.com/google-gemini/gemini-cli/pull/18557)
|
||||
- propagate abortSignal by scidomino in
|
||||
[#18477](https://github.com/google-gemini/gemini-cli/pull/18477)
|
||||
- feat(core): conditionally include ctrl+f prompt based on interactive shell
|
||||
setting by NTaylorMullen in
|
||||
[#18561](https://github.com/google-gemini/gemini-cli/pull/18561)
|
||||
- fix(core): ensure enter_plan_mode tool registration respects experimental.plan
|
||||
by jerop in [#18587](https://github.com/google-gemini/gemini-cli/pull/18587)
|
||||
- feat(core): transition sub-agents to XML format and improve definitions by
|
||||
NTaylorMullen in
|
||||
[#18555](https://github.com/google-gemini/gemini-cli/pull/18555)
|
||||
- docs: Add Plan Mode documentation by jerop in
|
||||
[#18582](https://github.com/google-gemini/gemini-cli/pull/18582)
|
||||
- chore: strengthen validation guidance in system prompt by NTaylorMullen in
|
||||
[#18544](https://github.com/google-gemini/gemini-cli/pull/18544)
|
||||
- Fix newline insertion bug in replace tool by werdnum in
|
||||
[#18595](https://github.com/google-gemini/gemini-cli/pull/18595)
|
||||
- fix(evals): update save_memory evals and simplify tool description by
|
||||
NTaylorMullen in
|
||||
[#18610](https://github.com/google-gemini/gemini-cli/pull/18610)
|
||||
- chore(evals): update validation_fidelity_pre_existing_errors to USUALLY_PASSES
|
||||
by NTaylorMullen in
|
||||
[#18617](https://github.com/google-gemini/gemini-cli/pull/18617)
|
||||
- fix: shorten tool call IDs and fix duplicate tool name in truncated output
|
||||
filenames by SandyTao520 in
|
||||
[#18600](https://github.com/google-gemini/gemini-cli/pull/18600)
|
||||
- feat(cli): implement atomic writes and safety checks for trusted folders by
|
||||
galz10 in [#18406](https://github.com/google-gemini/gemini-cli/pull/18406)
|
||||
- Remove relative docs links by chrstnb in
|
||||
[#18650](https://github.com/google-gemini/gemini-cli/pull/18650)
|
||||
- docs: add legacy snippets convention to GEMINI.md by NTaylorMullen in
|
||||
[#18597](https://github.com/google-gemini/gemini-cli/pull/18597)
|
||||
- fix(chore): Support linting for cjs by aswinashok44 in
|
||||
[#18639](https://github.com/google-gemini/gemini-cli/pull/18639)
|
||||
- feat: move shell efficiency guidelines to tool description by NTaylorMullen in
|
||||
[#18614](https://github.com/google-gemini/gemini-cli/pull/18614)
|
||||
- Added "" as default value, since getText() used to expect a string only and
|
||||
thus crashed when undefined... Fixes #18076 by 019-Abhi in
|
||||
[#18099](https://github.com/google-gemini/gemini-cli/pull/18099)
|
||||
- Allow @-includes outside of workspaces (with permission) by scidomino in
|
||||
[#18470](https://github.com/google-gemini/gemini-cli/pull/18470)
|
||||
- chore: make ask_user header description more clear by jackwotherspoon in
|
||||
[#18657](https://github.com/google-gemini/gemini-cli/pull/18657)
|
||||
- refactor(core): model-dependent tool definitions by aishaneeshah in
|
||||
[#18563](https://github.com/google-gemini/gemini-cli/pull/18563)
|
||||
- Harded code assist converter. by jacob314 in
|
||||
[#18656](https://github.com/google-gemini/gemini-cli/pull/18656)
|
||||
- bug(core): Fix minor bug in migration logic. by joshualitt in
|
||||
[#18661](https://github.com/google-gemini/gemini-cli/pull/18661)
|
||||
- feat: enable plan mode experiment in settings by jerop in
|
||||
[#18636](https://github.com/google-gemini/gemini-cli/pull/18636)
|
||||
- refactor: push isValidPath() into parsePastedPaths() by scidomino in
|
||||
[#18664](https://github.com/google-gemini/gemini-cli/pull/18664)
|
||||
- fix(cli): correct 'esc to cancel' position and restore duration display by
|
||||
NTaylorMullen in
|
||||
[#18534](https://github.com/google-gemini/gemini-cli/pull/18534)
|
||||
- feat(cli): add DevTools integration with gemini-cli-devtools by SandyTao520 in
|
||||
[#18648](https://github.com/google-gemini/gemini-cli/pull/18648)
|
||||
- chore: remove unused exports and redundant hook files by SandyTao520 in
|
||||
[#18681](https://github.com/google-gemini/gemini-cli/pull/18681)
|
||||
- Fix number of lines being reported in rewind confirmation dialog by Adib234 in
|
||||
[#18675](https://github.com/google-gemini/gemini-cli/pull/18675)
|
||||
- feat(cli): disable folder trust in headless mode by galz10 in
|
||||
[#18407](https://github.com/google-gemini/gemini-cli/pull/18407)
|
||||
- Disallow unsafe type assertions by gundermanc in
|
||||
[#18688](https://github.com/google-gemini/gemini-cli/pull/18688)
|
||||
- Change event type for release by g-samroberts in
|
||||
[#18693](https://github.com/google-gemini/gemini-cli/pull/18693)
|
||||
- feat: handle multiple dynamic context filenames in system prompt by
|
||||
NTaylorMullen in
|
||||
[#18598](https://github.com/google-gemini/gemini-cli/pull/18598)
|
||||
- Properly parse at-commands with narrow non-breaking spaces by scidomino in
|
||||
[#18677](https://github.com/google-gemini/gemini-cli/pull/18677)
|
||||
- refactor(core): centralize core tool definitions and support model-specific
|
||||
schemas by aishaneeshah in
|
||||
[#18662](https://github.com/google-gemini/gemini-cli/pull/18662)
|
||||
- feat(core): Render memory hierarchically in context. by joshualitt in
|
||||
[#18350](https://github.com/google-gemini/gemini-cli/pull/18350)
|
||||
- feat: Ctrl+O to expand paste placeholder by jackwotherspoon in
|
||||
[#18103](https://github.com/google-gemini/gemini-cli/pull/18103)
|
||||
- fix(cli): Improve header spacing by NTaylorMullen in
|
||||
[#18531](https://github.com/google-gemini/gemini-cli/pull/18531)
|
||||
- Feature/quota visibility 16795 by spencer426 in
|
||||
[#18203](https://github.com/google-gemini/gemini-cli/pull/18203)
|
||||
- Inline thinking bubbles with summary/full modes by LyalinDotCom in
|
||||
[#18033](https://github.com/google-gemini/gemini-cli/pull/18033)
|
||||
- docs: remove TOC marker from Plan Mode header by jerop in
|
||||
[#18678](https://github.com/google-gemini/gemini-cli/pull/18678)
|
||||
- fix(ui): remove redundant newlines in Gemini messages by NTaylorMullen in
|
||||
[#18538](https://github.com/google-gemini/gemini-cli/pull/18538)
|
||||
- test(cli): fix AppContainer act() warnings and improve waitFor resilience by
|
||||
NTaylorMullen in
|
||||
[#18676](https://github.com/google-gemini/gemini-cli/pull/18676)
|
||||
- refactor(core): refine Security & System Integrity section in system prompt by
|
||||
NTaylorMullen in
|
||||
[#18601](https://github.com/google-gemini/gemini-cli/pull/18601)
|
||||
- Fix layout rounding. by gundermanc in
|
||||
[#18667](https://github.com/google-gemini/gemini-cli/pull/18667)
|
||||
- docs(skills): enhance pr-creator safety and interactivity by NTaylorMullen in
|
||||
[#18616](https://github.com/google-gemini/gemini-cli/pull/18616)
|
||||
- test(core): remove hardcoded model from TestRig by NTaylorMullen in
|
||||
[#18710](https://github.com/google-gemini/gemini-cli/pull/18710)
|
||||
- feat(core): optimize sub-agents system prompt intro by NTaylorMullen in
|
||||
[#18608](https://github.com/google-gemini/gemini-cli/pull/18608)
|
||||
- feat(cli): update approval mode labels and shortcuts per latest UX spec by
|
||||
jerop in [#18698](https://github.com/google-gemini/gemini-cli/pull/18698)
|
||||
- fix(plan): update persistent approval mode setting by Adib234 in
|
||||
[#18638](https://github.com/google-gemini/gemini-cli/pull/18638)
|
||||
- fix: move toasts location to left side by jackwotherspoon in
|
||||
[#18705](https://github.com/google-gemini/gemini-cli/pull/18705)
|
||||
- feat(routing): restrict numerical routing to Gemini 3 family by mattKorwel in
|
||||
[#18478](https://github.com/google-gemini/gemini-cli/pull/18478)
|
||||
- fix(ide): fix ide nudge setting by skeshive in
|
||||
[#18733](https://github.com/google-gemini/gemini-cli/pull/18733)
|
||||
- fix(core): standardize tool formatting in system prompts by NTaylorMullen in
|
||||
[#18615](https://github.com/google-gemini/gemini-cli/pull/18615)
|
||||
- chore: consolidate to green in ask user dialog by jackwotherspoon in
|
||||
[#18734](https://github.com/google-gemini/gemini-cli/pull/18734)
|
||||
- feat: add extensionsExplore setting to enable extensions explore UI. by
|
||||
sripasg in [#18686](https://github.com/google-gemini/gemini-cli/pull/18686)
|
||||
- feat(cli): defer devtools startup and integrate with F12 by SandyTao520 in
|
||||
[#18695](https://github.com/google-gemini/gemini-cli/pull/18695)
|
||||
- ui: update & subdue footer colors and animate progress indicator by
|
||||
keithguerin in
|
||||
[#18570](https://github.com/google-gemini/gemini-cli/pull/18570)
|
||||
- test: add model-specific snapshots for coreTools by aishaneeshah in
|
||||
[#18707](https://github.com/google-gemini/gemini-cli/pull/18707)
|
||||
- ci: shard windows tests and fix event listener leaks by NTaylorMullen in
|
||||
[#18670](https://github.com/google-gemini/gemini-cli/pull/18670)
|
||||
- fix: allow ask_user tool in yolo mode by jackwotherspoon in
|
||||
[#18541](https://github.com/google-gemini/gemini-cli/pull/18541)
|
||||
- feat: redact disabled tools from system prompt
|
||||
([#13597](https://github.com/google-gemini/gemini-cli/pull/13597)) by
|
||||
NTaylorMullen in
|
||||
[#18613](https://github.com/google-gemini/gemini-cli/pull/18613)
|
||||
- Update Gemini.md to use the curent year on creating new files by sehoon38 in
|
||||
[#18460](https://github.com/google-gemini/gemini-cli/pull/18460)
|
||||
- Code review cleanup for thinking display by jacob314 in
|
||||
[#18720](https://github.com/google-gemini/gemini-cli/pull/18720)
|
||||
- fix(cli): hide scrollbars when in alternate buffer copy mode by werdnum in
|
||||
[#18354](https://github.com/google-gemini/gemini-cli/pull/18354)
|
||||
- Fix issues with rip grep by gundermanc in
|
||||
[#18756](https://github.com/google-gemini/gemini-cli/pull/18756)
|
||||
- fix(cli): fix history navigation regression after prompt autocomplete by
|
||||
sehoon38 in [#18752](https://github.com/google-gemini/gemini-cli/pull/18752)
|
||||
- chore: cleanup unused and add unlisted dependencies in packages/cli by
|
||||
adamfweidman in
|
||||
[#18749](https://github.com/google-gemini/gemini-cli/pull/18749)
|
||||
- Fix issue where Gemini CLI creates tests in a new file by gundermanc in
|
||||
[#18409](https://github.com/google-gemini/gemini-cli/pull/18409)
|
||||
- feat(telemetry): Ensure experiment IDs are included in OpenTelemetry logs by
|
||||
kevin-ramdass in
|
||||
[#18747](https://github.com/google-gemini/gemini-cli/pull/18747)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.30.0-preview.6...v0.31.0-preview.0
|
||||
**Full changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.28.0-preview.0...v0.29.0-preview.0
|
||||
|
||||
+79
-201
@@ -1,62 +1,50 @@
|
||||
# Plan Mode (experimental)
|
||||
|
||||
Plan Mode is a read-only environment for architecting robust solutions before
|
||||
implementation. It allows you to:
|
||||
Plan Mode is a safe, read-only mode for researching and designing complex
|
||||
changes. It prevents modifications while you research, design and plan an
|
||||
implementation strategy.
|
||||
|
||||
- **Research:** Explore the project in a read-only state to prevent accidental
|
||||
changes.
|
||||
- **Design:** Understand problems, evaluate trade-offs, and choose a solution.
|
||||
- **Plan:** Align on an execution strategy before any code is modified.
|
||||
|
||||
> **Note:** This is a preview feature currently under active development. Your
|
||||
> feedback is invaluable as we refine this feature. If you have ideas,
|
||||
> **Note: Plan Mode is currently an experimental feature.**
|
||||
>
|
||||
> Experimental features are subject to change. To use Plan Mode, enable it via
|
||||
> `/settings` (search for `Plan`) or add the following to your `settings.json`:
|
||||
>
|
||||
> ```json
|
||||
> {
|
||||
> "experimental": {
|
||||
> "plan": true
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> Your feedback is invaluable as we refine this feature. If you have ideas,
|
||||
> suggestions, or encounter issues:
|
||||
>
|
||||
> - Use the `/bug` command within the CLI to file an issue.
|
||||
> - [Open an issue](https://github.com/google-gemini/gemini-cli/issues) on
|
||||
> GitHub.
|
||||
> - Use the **/bug** command within Gemini CLI to file an issue.
|
||||
|
||||
- [Enabling Plan Mode](#enabling-plan-mode)
|
||||
- [Starting in Plan Mode](#starting-in-plan-mode)
|
||||
- [How to use Plan Mode](#how-to-use-plan-mode)
|
||||
- [Entering Plan Mode](#entering-plan-mode)
|
||||
- [Planning Workflow](#planning-workflow)
|
||||
- [The Planning Workflow](#the-planning-workflow)
|
||||
- [Exiting Plan Mode](#exiting-plan-mode)
|
||||
- [Tool Restrictions](#tool-restrictions)
|
||||
- [Customizing Planning with Skills](#customizing-planning-with-skills)
|
||||
- [Customizing Policies](#customizing-policies)
|
||||
- [Example: Allow git commands in Plan Mode](#example-allow-git-commands-in-plan-mode)
|
||||
- [Example: Enable research subagents in Plan Mode](#example-enable-research-subagents-in-plan-mode)
|
||||
- [Custom Plan Directory and Policies](#custom-plan-directory-and-policies)
|
||||
- [Automatic Model Routing](#automatic-model-routing)
|
||||
|
||||
## Enabling Plan Mode
|
||||
## Starting in Plan Mode
|
||||
|
||||
To use Plan Mode, enable it via **/settings** (search for **Plan**) or add the
|
||||
following to your `settings.json`:
|
||||
You can configure Gemini CLI to start directly in Plan Mode by default:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"plan": true
|
||||
}
|
||||
}
|
||||
```
|
||||
1. Type `/settings` in the CLI.
|
||||
2. Search for `Default Approval Mode`.
|
||||
3. Set the value to `Plan`.
|
||||
|
||||
## How to use Plan Mode
|
||||
Other ways to start in Plan Mode:
|
||||
|
||||
### Entering Plan Mode
|
||||
|
||||
You can configure Gemini CLI to start in Plan Mode by default or enter it
|
||||
manually during a session.
|
||||
|
||||
- **Configuration:** Configure Gemini CLI to start directly in Plan Mode by
|
||||
default:
|
||||
1. Type `/settings` in the CLI.
|
||||
2. Search for **Default Approval Mode**.
|
||||
3. Set the value to **Plan**.
|
||||
|
||||
Alternatively, use the `gemini --approval-mode=plan` CLI flag or manually
|
||||
update:
|
||||
- **CLI Flag:** `gemini --approval-mode=plan`
|
||||
- **Manual Settings:** Manually update your `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -66,63 +54,42 @@ manually during a session.
|
||||
}
|
||||
```
|
||||
|
||||
- **Keyboard Shortcut:** Press `Shift+Tab` to cycle through approval modes
|
||||
(`Default` -> `Auto-Edit` -> `Plan`).
|
||||
## How to use Plan Mode
|
||||
|
||||
> **Note:** Plan Mode is automatically removed from the rotation when Gemini
|
||||
> CLI is actively processing or showing confirmation dialogs.
|
||||
### Entering Plan Mode
|
||||
|
||||
- **Command:** Type `/plan` in the input box.
|
||||
You can enter Plan Mode in three ways:
|
||||
|
||||
- **Natural Language:** Ask Gemini CLI to "start a plan for...". Gemini CLI then
|
||||
calls the [`enter_plan_mode`] tool to switch modes.
|
||||
> **Note:** This tool is not available when Gemini CLI is in [YOLO mode].
|
||||
1. **Keyboard Shortcut:** Press `Shift+Tab` to cycle through approval modes
|
||||
(`Default` -> `Auto-Edit` -> `Plan`).
|
||||
|
||||
### Planning Workflow
|
||||
> **Note:** Plan Mode is automatically removed from the rotation when the
|
||||
> agent is actively processing or showing confirmation dialogs.
|
||||
|
||||
Plan Mode uses an adaptive planning workflow where the research depth, plan
|
||||
structure, and consultation level are proportional to the task's complexity:
|
||||
2. **Command:** Type `/plan` in the input box.
|
||||
3. **Natural Language:** Ask the agent to "start a plan for...". The agent will
|
||||
then call the [`enter_plan_mode`] tool to switch modes.
|
||||
|
||||
1. **Explore & Analyze:** Analyze requirements and use read-only tools to map
|
||||
affected modules and identify dependencies.
|
||||
2. **Consult:** The depth of consultation is proportional to the task's
|
||||
complexity:
|
||||
- **Simple Tasks:** Proceed directly to drafting.
|
||||
- **Standard Tasks:** Present a summary of viable approaches via
|
||||
[`ask_user`] for selection.
|
||||
- **Complex Tasks:** Present detailed trade-offs for at least two viable
|
||||
approaches via [`ask_user`] and obtain approval before drafting.
|
||||
3. **Draft:** Write a detailed implementation plan to the
|
||||
[plans directory](#custom-plan-directory-and-policies). The plan's structure
|
||||
adapts to the task:
|
||||
- **Simple Tasks:** Focused on specific **Changes** and **Verification**
|
||||
steps.
|
||||
- **Standard Tasks:** Includes an **Objective**, **Key Files & Context**,
|
||||
**Implementation Steps**, and **Verification & Testing**.
|
||||
- **Complex Tasks:** Comprehensive plans including **Background &
|
||||
Motivation**, **Scope & Impact**, **Proposed Solution**, **Alternatives
|
||||
Considered**, a phased **Implementation Plan**, **Verification**, and
|
||||
**Migration & Rollback** strategies.
|
||||
4. **Review & Approval:** Use the [`exit_plan_mode`] tool to present the plan
|
||||
and formally request approval.
|
||||
- **Approve:** Exit Plan Mode and start implementation.
|
||||
### The Planning Workflow
|
||||
|
||||
1. **Requirements:** The agent clarifies goals using [`ask_user`].
|
||||
2. **Exploration:** The agent uses read-only tools (like [`read_file`]) to map
|
||||
the codebase and validate assumptions.
|
||||
3. **Design:** The agent proposes alternative approaches with a recommended
|
||||
solution for you to choose from.
|
||||
4. **Planning:** A detailed plan is written to a temporary Markdown file.
|
||||
5. **Review:** You review the plan.
|
||||
- **Approve:** Exit Plan Mode and start implementation (switching to
|
||||
Auto-Edit or Default approval mode).
|
||||
- **Iterate:** Provide feedback to refine the plan.
|
||||
- **Refine manually:** Press **Ctrl + X** to open the plan file in your
|
||||
[preferred external editor]. This allows you to manually refine the plan
|
||||
steps before approval. The CLI will automatically refresh and show the
|
||||
updated plan after you save and close the editor.
|
||||
|
||||
For more complex or specialized planning tasks, you can
|
||||
[customize the planning workflow with skills](#customizing-planning-with-skills).
|
||||
|
||||
### Exiting Plan Mode
|
||||
|
||||
To exit Plan Mode, you can:
|
||||
To exit Plan Mode:
|
||||
|
||||
- **Keyboard Shortcut:** Press `Shift+Tab` to cycle to the desired mode.
|
||||
|
||||
- **Tool:** Gemini CLI calls the [`exit_plan_mode`] tool to present the
|
||||
finalized plan for your approval.
|
||||
1. **Keyboard Shortcut:** Press `Shift+Tab` to cycle to the desired mode.
|
||||
2. **Tool:** The agent calls the [`exit_plan_mode`] tool to present the
|
||||
finalized plan for your approval.
|
||||
|
||||
## Tool Restrictions
|
||||
|
||||
@@ -135,58 +102,42 @@ These are the only allowed tools:
|
||||
- **Interaction:** [`ask_user`]
|
||||
- **MCP Tools (Read):** Read-only [MCP tools] (e.g., `github_read_issue`,
|
||||
`postgres_read_schema`) are allowed.
|
||||
- **Planning (Write):** [`write_file`] and [`replace`] only allowed for `.md`
|
||||
files in the `~/.gemini/tmp/<project>/<session-id>/plans/` directory or your
|
||||
[custom plans directory](#custom-plan-directory-and-policies).
|
||||
- **Memory:** [`save_memory`]
|
||||
- **Planning (Write):** [`write_file`] and [`replace`] ONLY allowed for `.md`
|
||||
files in the `~/.gemini/tmp/<project>/<session-id>/plans/` directory.
|
||||
- **Skills:** [`activate_skill`] (allows loading specialized instructions and
|
||||
resources in a read-only manner)
|
||||
|
||||
### Customizing Planning with Skills
|
||||
|
||||
You can use [Agent Skills](./skills.md) to customize how Gemini CLI approaches
|
||||
planning for specific types of tasks. When a skill is activated during Plan
|
||||
Mode, its specialized instructions and procedural workflows will guide the
|
||||
research, design and planning phases.
|
||||
You can leverage [Agent Skills](./skills.md) to customize how Gemini CLI
|
||||
approaches planning for specific types of tasks. When a skill is activated
|
||||
during Plan Mode, its specialized instructions and procedural workflows will
|
||||
guide the research and design phases.
|
||||
|
||||
For example:
|
||||
|
||||
- A **"Database Migration"** skill could ensure the plan includes data safety
|
||||
checks and rollback strategies.
|
||||
- A **"Security Audit"** skill could prompt Gemini CLI to look for specific
|
||||
- A **"Security Audit"** skill could prompt the agent to look for specific
|
||||
vulnerabilities during codebase exploration.
|
||||
- A **"Frontend Design"** skill could guide Gemini CLI to use specific UI
|
||||
- A **"Frontend Design"** skill could guide the agent to use specific UI
|
||||
components and accessibility standards in its proposal.
|
||||
|
||||
To use a skill in Plan Mode, you can explicitly ask Gemini CLI to "use the
|
||||
`<skill-name>` skill to plan..." or Gemini CLI may autonomously activate it
|
||||
based on the task description.
|
||||
To use a skill in Plan Mode, you can explicitly ask the agent to "use the
|
||||
[skill-name] skill to plan..." or the agent may autonomously activate it based
|
||||
on the task description.
|
||||
|
||||
### Customizing Policies
|
||||
|
||||
Plan Mode's default tool restrictions are managed by the [policy engine] and
|
||||
defined in the built-in [`plan.toml`] file. The built-in policy (Tier 1)
|
||||
enforces the read-only state, but you can customize these rules by creating your
|
||||
own policies in your `~/.gemini/policies/` directory (Tier 2).
|
||||
Plan Mode is designed to be read-only by default to ensure safety during the
|
||||
research phase. However, you may occasionally need to allow specific tools to
|
||||
assist in your planning.
|
||||
|
||||
#### Example: Automatically approve read-only MCP tools
|
||||
Because user policies (Tier 2) have a higher base priority than built-in
|
||||
policies (Tier 1), you can override Plan Mode's default restrictions by creating
|
||||
a rule in your `~/.gemini/policies/` directory.
|
||||
|
||||
By default, read-only MCP tools require user confirmation in Plan Mode. You can
|
||||
use `toolAnnotations` and the `mcpName` wildcard to customize this behavior for
|
||||
your specific environment.
|
||||
|
||||
`~/.gemini/policies/mcp-read-only.toml`
|
||||
|
||||
```toml
|
||||
[[rule]]
|
||||
mcpName = "*"
|
||||
toolAnnotations = { readOnlyHint = true }
|
||||
decision = "allow"
|
||||
priority = 100
|
||||
modes = ["plan"]
|
||||
```
|
||||
|
||||
#### Example: Allow git commands in Plan Mode
|
||||
#### Example: Allow `git status` and `git diff` in Plan Mode
|
||||
|
||||
This rule allows you to check the repository status and see changes while in
|
||||
Plan Mode.
|
||||
@@ -202,10 +153,10 @@ priority = 100
|
||||
modes = ["plan"]
|
||||
```
|
||||
|
||||
#### Example: Enable research subagents in Plan Mode
|
||||
#### Example: Enable research sub-agents in Plan Mode
|
||||
|
||||
You can enable experimental research [subagents] like `codebase_investigator` to
|
||||
help gather architecture details during the planning phase.
|
||||
You can enable [experimental research sub-agents] like `codebase_investigator`
|
||||
to help gather architecture details during the planning phase.
|
||||
|
||||
`~/.gemini/policies/research-subagents.toml`
|
||||
|
||||
@@ -217,77 +168,11 @@ priority = 100
|
||||
modes = ["plan"]
|
||||
```
|
||||
|
||||
Tell Gemini CLI it can use these tools in your prompt, for example: _"You can
|
||||
Tell the agent it can use these tools in your prompt, for example: _"You can
|
||||
check ongoing changes in git."_
|
||||
|
||||
For more information on how the policy engine works, see the [policy engine]
|
||||
docs.
|
||||
|
||||
### Custom Plan Directory and Policies
|
||||
|
||||
By default, planning artifacts are stored in a managed temporary directory
|
||||
outside your project: `~/.gemini/tmp/<project>/<session-id>/plans/`.
|
||||
|
||||
You can configure a custom directory for plans in your `settings.json`. For
|
||||
example, to store plans in a `.gemini/plans` directory within your project:
|
||||
|
||||
```json
|
||||
{
|
||||
"general": {
|
||||
"plan": {
|
||||
"directory": ".gemini/plans"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To maintain the safety of Plan Mode, user-configured paths for the plans
|
||||
directory are restricted to the project root. This ensures that custom planning
|
||||
locations defined within a project's workspace cannot be used to escape and
|
||||
overwrite sensitive files elsewhere. Any user-configured directory must reside
|
||||
within the project boundary.
|
||||
|
||||
Using a custom directory requires updating your [policy engine] configurations
|
||||
to allow `write_file` and `replace` in that specific location. For example, to
|
||||
allow writing to the `.gemini/plans` directory within your project, create a
|
||||
policy file at `~/.gemini/policies/plan-custom-directory.toml`:
|
||||
|
||||
```toml
|
||||
[[rule]]
|
||||
toolName = ["write_file", "replace"]
|
||||
decision = "allow"
|
||||
priority = 100
|
||||
modes = ["plan"]
|
||||
# Adjust the pattern to match your custom directory.
|
||||
# This example matches any .md file in a .gemini/plans directory within the project.
|
||||
argsPattern = "\"file_path\":\"[^\"]+[\\\\/]+\\.gemini[\\\\/]+plans[\\\\/]+[\\w-]+\\.md\""
|
||||
```
|
||||
|
||||
## Automatic Model Routing
|
||||
|
||||
When using an [**auto model**], Gemini CLI automatically optimizes [**model
|
||||
routing**] based on the current phase of your task:
|
||||
|
||||
1. **Planning Phase:** While in Plan Mode, the CLI routes requests to a
|
||||
high-reasoning **Pro** model to ensure robust architectural decisions and
|
||||
high-quality plans.
|
||||
2. **Implementation Phase:** Once a plan is approved and you exit Plan Mode,
|
||||
the CLI detects the existence of the approved plan and automatically
|
||||
switches to a high-speed **Flash** model. This provides a faster, more
|
||||
responsive experience during the implementation of the plan.
|
||||
|
||||
This behavior is enabled by default to provide the best balance of quality and
|
||||
performance. You can disable this automatic switching in your settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"general": {
|
||||
"plan": {
|
||||
"modelRouting": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
For more information on how the policy engine works, see the [Policy Engine
|
||||
Guide].
|
||||
|
||||
[`list_directory`]: /docs/tools/file-system.md#1-list_directory-readfolder
|
||||
[`read_file`]: /docs/tools/file-system.md#2-read_file-readfile
|
||||
@@ -297,16 +182,9 @@ performance. You can disable this automatic switching in your settings:
|
||||
[`google_web_search`]: /docs/tools/web-search.md
|
||||
[`replace`]: /docs/tools/file-system.md#6-replace-edit
|
||||
[MCP tools]: /docs/tools/mcp-server.md
|
||||
[`save_memory`]: /docs/tools/memory.md
|
||||
[`activate_skill`]: /docs/cli/skills.md
|
||||
[subagents]: /docs/core/subagents.md
|
||||
[policy engine]: /docs/reference/policy-engine.md
|
||||
[experimental research sub-agents]: /docs/core/subagents.md
|
||||
[Policy Engine Guide]: /docs/reference/policy-engine.md
|
||||
[`enter_plan_mode`]: /docs/tools/planning.md#1-enter_plan_mode-enterplanmode
|
||||
[`exit_plan_mode`]: /docs/tools/planning.md#2-exit_plan_mode-exitplanmode
|
||||
[`ask_user`]: /docs/tools/ask-user.md
|
||||
[YOLO mode]: /docs/reference/configuration.md#command-line-arguments
|
||||
[`plan.toml`]:
|
||||
https://github.com/google-gemini/gemini-cli/blob/main/packages/core/src/policy/policies/plan.toml
|
||||
[auto model]: /docs/reference/configuration.md#model-settings
|
||||
[model routing]: /docs/cli/telemetry.md#model-routing
|
||||
[preferred external editor]: /docs/reference/configuration.md#general
|
||||
|
||||
+57
-67
@@ -22,18 +22,15 @@ they appear in the UI.
|
||||
|
||||
### General
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ----------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
|
||||
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
|
||||
| Default Approval Mode | `general.defaultApprovalMode` | The default approval mode for tool execution. 'default' prompts for approval, 'auto_edit' auto-approves edit tools, and 'plan' is read-only mode. 'yolo' is not supported yet. | `"default"` |
|
||||
| Enable Auto Update | `general.enableAutoUpdate` | Enable automatic updates. | `true` |
|
||||
| Enable Notifications | `general.enableNotifications` | Enable run-event notifications for action-required prompts and session completion. Currently macOS only. | `false` |
|
||||
| Plan Directory | `general.plan.directory` | The directory where planning artifacts are stored. If not specified, defaults to the system temporary directory. | `undefined` |
|
||||
| Plan Model Routing | `general.plan.modelRouting` | Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pro for the planning phase and Flash for the implementation phase. | `true` |
|
||||
| Max Chat Model Attempts | `general.maxAttempts` | Maximum number of attempts for requests to the main chat model. Cannot exceed 10. | `10` |
|
||||
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
|
||||
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `false` |
|
||||
| Keep chat history | `general.sessionRetention.maxAge` | Automatically delete chats older than this time period (e.g., "30d", "7d", "24h", "1w") | `undefined` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
|
||||
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
|
||||
| Default Approval Mode | `general.defaultApprovalMode` | The default approval mode for tool execution. 'default' prompts for approval, 'auto_edit' auto-approves edit tools, and 'plan' is read-only mode. 'yolo' is not supported yet. | `"default"` |
|
||||
| Enable Auto Update | `general.enableAutoUpdate` | Enable automatic updates. | `true` |
|
||||
| Enable Prompt Completion | `general.enablePromptCompletion` | Enable AI-powered prompt completion suggestions while typing. | `false` |
|
||||
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
|
||||
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `false` |
|
||||
| Keep chat history | `general.sessionRetention.maxAge` | Automatically delete chats older than this time period (e.g., "30d", "7d", "24h", "1w") | `undefined` |
|
||||
|
||||
### Output
|
||||
|
||||
@@ -43,36 +40,35 @@ they appear in the UI.
|
||||
|
||||
### UI
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
|
||||
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
|
||||
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
|
||||
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
|
||||
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
|
||||
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
|
||||
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
|
||||
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
|
||||
| Show Compatibility Warnings | `ui.showCompatibilityWarnings` | Show warnings about terminal or OS compatibility issues. | `true` |
|
||||
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
|
||||
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
|
||||
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
|
||||
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
|
||||
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` |
|
||||
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
|
||||
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
|
||||
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window remaining percentage. | `true` |
|
||||
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
|
||||
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
|
||||
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
|
||||
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
|
||||
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
|
||||
| Show User Identity | `ui.showUserIdentity` | Show the logged-in user's identity (e.g. email) in the UI. | `true` |
|
||||
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
|
||||
| Use Background Color | `ui.useBackgroundColor` | Whether to use background colors in the UI. | `true` |
|
||||
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
|
||||
| Show Spinner | `ui.showSpinner` | Show the spinner during operations. | `true` |
|
||||
| Loading Phrases | `ui.loadingPhrases` | What to show while the model is working: tips, witty comments, both, or nothing. | `"tips"` |
|
||||
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
|
||||
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
|
||||
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
|
||||
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
|
||||
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
|
||||
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
|
||||
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
|
||||
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
|
||||
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
|
||||
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
|
||||
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
|
||||
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` |
|
||||
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
|
||||
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
|
||||
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window remaining percentage. | `true` |
|
||||
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
|
||||
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
|
||||
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
|
||||
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
|
||||
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
|
||||
| Show User Identity | `ui.showUserIdentity` | Show the logged-in user's identity (e.g. email) in the UI. | `true` |
|
||||
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
|
||||
| Use Background Color | `ui.useBackgroundColor` | Whether to use background colors in the UI. | `true` |
|
||||
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
|
||||
| Show Spinner | `ui.showSpinner` | Show the spinner during operations. | `true` |
|
||||
| Enable Loading Phrases | `ui.accessibility.enableLoadingPhrases` | Enable loading phrases during operations. | `true` |
|
||||
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
|
||||
|
||||
### IDE
|
||||
|
||||
@@ -82,13 +78,12 @@ they appear in the UI.
|
||||
|
||||
### Model
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ----------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | ----------- |
|
||||
| Model | `model.name` | The Gemini model to use for conversations. | `undefined` |
|
||||
| Max Session Turns | `model.maxSessionTurns` | Maximum number of user/model/tool turns to keep in a session. -1 means unlimited. | `-1` |
|
||||
| Compression Threshold | `model.compressionThreshold` | The fraction of context usage at which to trigger context compression (e.g. 0.2, 0.3). | `0.5` |
|
||||
| Disable Loop Detection | `model.disableLoopDetection` | Disable automatic detection and prevention of infinite loops. | `false` |
|
||||
| Skip Next Speaker Check | `model.skipNextSpeakerCheck` | Skip the next speaker check. | `true` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ----------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | ------- |
|
||||
| Max Session Turns | `model.maxSessionTurns` | Maximum number of user/model/tool turns to keep in a session. -1 means unlimited. | `-1` |
|
||||
| Compression Threshold | `model.compressionThreshold` | The fraction of context usage at which to trigger context compression (e.g. 0.2, 0.3). | `0.5` |
|
||||
| Disable Loop Detection | `model.disableLoopDetection` | Disable automatic detection and prevention of infinite loops. | `false` |
|
||||
| Skip Next Speaker Check | `model.skipNextSpeakerCheck` | Skip the next speaker check. | `true` |
|
||||
|
||||
### Context
|
||||
|
||||
@@ -114,15 +109,14 @@ they appear in the UI.
|
||||
|
||||
### Security
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
||||
| Disable YOLO Mode | `security.disableYoloMode` | Disable YOLO mode, even if enabled by a flag. | `false` |
|
||||
| Allow Permanent Tool Approval | `security.enablePermanentToolApproval` | Enable the "Allow for all future sessions" option in tool confirmation dialogs. | `false` |
|
||||
| Blocks extensions from Git | `security.blockGitExtensions` | Blocks installing and loading extensions from Git. | `false` |
|
||||
| Extension Source Regex Allowlist | `security.allowedExtensions` | List of Regex patterns for allowed extensions. If nonempty, only extensions that match the patterns in this list are allowed. Overrides the blockGitExtensions setting. | `[]` |
|
||||
| Folder Trust | `security.folderTrust.enabled` | Setting to track whether Folder trust is enabled. | `true` |
|
||||
| Enable Environment Variable Redaction | `security.environmentVariableRedaction.enabled` | Enable redaction of environment variables that may contain secrets. | `false` |
|
||||
| Enable Context-Aware Security | `security.enableConseca` | Enable the context-aware security checker. This feature uses an LLM to dynamically generate and enforce security policies for tool use based on your prompt, providing an additional layer of protection against unintended actions. | `false` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Disable YOLO Mode | `security.disableYoloMode` | Disable YOLO mode, even if enabled by a flag. | `false` |
|
||||
| Allow Permanent Tool Approval | `security.enablePermanentToolApproval` | Enable the "Allow for all future sessions" option in tool confirmation dialogs. | `false` |
|
||||
| Blocks extensions from Git | `security.blockGitExtensions` | Blocks installing and loading extensions from Git. | `false` |
|
||||
| Extension Source Regex Allowlist | `security.allowedExtensions` | List of Regex patterns for allowed extensions. If nonempty, only extensions that match the patterns in this list are allowed. Overrides the blockGitExtensions setting. | `[]` |
|
||||
| Folder Trust | `security.folderTrust.enabled` | Setting to track whether Folder trust is enabled. | `true` |
|
||||
| Enable Environment Variable Redaction | `security.environmentVariableRedaction.enabled` | Enable redaction of environment variables that may contain secrets. | `false` |
|
||||
|
||||
### Advanced
|
||||
|
||||
@@ -132,15 +126,11 @@ they appear in the UI.
|
||||
|
||||
### Experimental
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| -------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Enable Tool Output Masking | `experimental.toolOutputMasking.enabled` | Enables tool output masking to save tokens. | `true` |
|
||||
| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 for pasting. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
|
||||
| Use OSC 52 Copy | `experimental.useOSC52Copy` | Use OSC 52 for copying. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
|
||||
| Plan | `experimental.plan` | Enable planning features (Plan Mode and tools). | `false` |
|
||||
| Model Steering | `experimental.modelSteering` | Enable model steering (user hints) to guide the model during tool execution. | `false` |
|
||||
| Direct Web Fetch | `experimental.directWebFetch` | Enable web fetch behavior that bypasses LLM summarization. | `false` |
|
||||
| Enable Gemma Model Router | `experimental.gemmaModelRouter.enabled` | Enable the Gemma Model Router. Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim. | `false` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| -------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------- | ------- |
|
||||
| Enable Tool Output Masking | `experimental.toolOutputMasking.enabled` | Enables tool output masking to save tokens. | `true` |
|
||||
| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 sequence for pasting instead of clipboardy (useful for remote sessions). | `false` |
|
||||
| Plan | `experimental.plan` | Enable planning features (Plan Mode and tools). | `false` |
|
||||
|
||||
### Skills
|
||||
|
||||
|
||||
+11
-42
@@ -176,12 +176,11 @@ Sends telemetry directly to Google Cloud services. No collector needed.
|
||||
}
|
||||
```
|
||||
2. Run Gemini CLI and send prompts.
|
||||
3. View logs, metrics, and traces:
|
||||
3. View logs and metrics:
|
||||
- Open the Google Cloud Console in your browser after sending prompts:
|
||||
- Logs (Logs Explorer): https://console.cloud.google.com/logs/
|
||||
- Metrics (Metrics Explorer):
|
||||
https://console.cloud.google.com/monitoring/metrics-explorer
|
||||
- Traces (Trace Explorer): https://console.cloud.google.com/traces/list
|
||||
- Logs: https://console.cloud.google.com/logs/
|
||||
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer
|
||||
- Traces: https://console.cloud.google.com/traces/list
|
||||
|
||||
### Collector-based export (advanced)
|
||||
|
||||
@@ -209,12 +208,11 @@ forward data to Google Cloud.
|
||||
- Save collector logs to `~/.gemini/tmp/<projectHash>/otel/collector-gcp.log`
|
||||
- Stop collector on exit (e.g. `Ctrl+C`)
|
||||
3. Run Gemini CLI and send prompts.
|
||||
4. View logs, metrics, and traces:
|
||||
4. View logs and metrics:
|
||||
- Open the Google Cloud Console in your browser after sending prompts:
|
||||
- Logs (Logs Explorer): https://console.cloud.google.com/logs/
|
||||
- Metrics (Metrics Explorer):
|
||||
https://console.cloud.google.com/monitoring/metrics-explorer
|
||||
- Traces (Trace Explorer): https://console.cloud.google.com/traces/list
|
||||
- Logs: https://console.cloud.google.com/logs/
|
||||
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer
|
||||
- Traces: https://console.cloud.google.com/traces/list
|
||||
- Open `~/.gemini/tmp/<projectHash>/otel/collector-gcp.log` to view local
|
||||
collector logs.
|
||||
|
||||
@@ -272,10 +270,10 @@ For local development and debugging, you can capture telemetry data locally:
|
||||
3. View traces at http://localhost:16686 and logs/metrics in the collector log
|
||||
file.
|
||||
|
||||
## Logs, metrics, and traces
|
||||
## Logs and metrics
|
||||
|
||||
The following section describes the structure of logs, metrics, and traces
|
||||
generated for Gemini CLI.
|
||||
The following section describes the structure of logs and metrics generated for
|
||||
Gemini CLI.
|
||||
|
||||
The `session.id`, `installation.id`, `active_approval_mode`, and `user.email`
|
||||
(available only when authenticated with a Google account) are included as common
|
||||
@@ -489,7 +487,6 @@ Captures Gemini API requests, responses, and errors.
|
||||
- `reasoning` (string, optional)
|
||||
- `failed` (boolean)
|
||||
- `error_message` (string, optional)
|
||||
- `approval_mode` (string)
|
||||
|
||||
#### Chat and streaming
|
||||
|
||||
@@ -714,14 +711,12 @@ Routing latency/failures and slash-command selections.
|
||||
- **Attributes**:
|
||||
- `routing.decision_model` (string)
|
||||
- `routing.decision_source` (string)
|
||||
- `routing.approval_mode` (string)
|
||||
|
||||
- `gemini_cli.model_routing.failure.count` (Counter, Int): Counts model routing
|
||||
failures.
|
||||
- **Attributes**:
|
||||
- `routing.decision_source` (string)
|
||||
- `routing.error_message` (string)
|
||||
- `routing.approval_mode` (string)
|
||||
|
||||
##### Agent runs
|
||||
|
||||
@@ -826,32 +821,6 @@ Optional performance monitoring for startup, CPU/memory, and phase timing.
|
||||
- `current_value` (number)
|
||||
- `baseline_value` (number)
|
||||
|
||||
### Traces
|
||||
|
||||
Traces offer a granular, "under-the-hood" view of every agent and backend
|
||||
operation. By providing a high-fidelity execution map, they enable precise
|
||||
debugging of complex tool interactions and deep performance optimization. Each
|
||||
trace captures rich, consistent metadata via custom span attributes:
|
||||
|
||||
- `gen_ai.operation.name` (string): The high-level operation kind (e.g.
|
||||
"tool_call", "llm_call").
|
||||
- `gen_ai.agent.name` (string): The service agent identifier ("gemini-cli").
|
||||
- `gen_ai.agent.description` (string): The service agent description.
|
||||
- `gen_ai.input.messages` (string): Input messages or metadata specific to the
|
||||
operation.
|
||||
- `gen_ai.output.messages` (string): Output messages or metadata generated from
|
||||
the operation.
|
||||
- `gen_ai.request.model` (string): The request model name.
|
||||
- `gen_ai.response.model` (string): The response model name.
|
||||
- `gen_ai.system_instructions` (json string): The system instructions.
|
||||
- `gen_ai.prompt.name` (string): The prompt name.
|
||||
- `gen_ai.tool.name` (string): The executed tool's name.
|
||||
- `gen_ai.tool.call_id` (string): The generated specific ID of the tool call.
|
||||
- `gen_ai.tool.description` (string): The executed tool's description.
|
||||
- `gen_ai.tool.definitions` (json string): The executed tool's description.
|
||||
- `gen_ai.conversation.id` (string): The current CLI session ID.
|
||||
- Additional user-defined Custom Attributes passed via the span's configuration.
|
||||
|
||||
#### GenAI semantic convention
|
||||
|
||||
The following metrics comply with [OpenTelemetry GenAI semantic conventions] for
|
||||
|
||||
@@ -38,37 +38,6 @@ folder, a dialog will automatically appear, prompting you to make a choice:
|
||||
Your choice is saved in a central file (`~/.gemini/trustedFolders.json`), so you
|
||||
will only be asked once per folder.
|
||||
|
||||
## Understanding folder contents: The discovery phase
|
||||
|
||||
Before you make a choice, the Gemini CLI performs a **discovery phase** to scan
|
||||
the folder for potential configurations. This information is displayed in the
|
||||
trust dialog to help you make an informed decision.
|
||||
|
||||
The discovery UI lists the following categories of items found in the project:
|
||||
|
||||
- **Commands**: Custom `.toml` command definitions that add new functionality.
|
||||
- **MCP Servers**: Configured Model Context Protocol servers that the CLI will
|
||||
attempt to connect to.
|
||||
- **Hooks**: System or custom hooks that can intercept and modify CLI behavior.
|
||||
- **Skills**: Local agent skills that provide specialized capabilities.
|
||||
- **Setting overrides**: Any project-specific configurations that override your
|
||||
global user settings.
|
||||
|
||||
### Security warnings and errors
|
||||
|
||||
The trust dialog also highlights critical information that requires your
|
||||
attention:
|
||||
|
||||
- **Security Warnings**: The CLI will explicitly flag potentially dangerous
|
||||
settings, such as auto-approving certain tools or disabling the security
|
||||
sandbox.
|
||||
- **Discovery Errors**: If the CLI encounters issues while scanning the folder
|
||||
(e.g., a malformed `settings.json` file), these errors will be displayed
|
||||
prominently.
|
||||
|
||||
By reviewing these details, you can ensure that you only grant trust to projects
|
||||
that you know are safe.
|
||||
|
||||
## Why trust matters: The impact of an untrusted workspace
|
||||
|
||||
When a folder is **untrusted**, the Gemini CLI runs in a restricted "safe mode"
|
||||
|
||||
+38
-154
@@ -1,13 +1,13 @@
|
||||
# Subagents (experimental)
|
||||
# Sub-agents (experimental)
|
||||
|
||||
Subagents are specialized agents that operate within your main Gemini CLI
|
||||
Sub-agents are specialized agents that operate within your main Gemini CLI
|
||||
session. They are designed to handle specific, complex tasks—like deep codebase
|
||||
analysis, documentation lookup, or domain-specific reasoning—without cluttering
|
||||
the main agent's context or toolset.
|
||||
|
||||
> **Note: Subagents are currently an experimental feature.**
|
||||
> **Note: Sub-agents are currently an experimental feature.**
|
||||
>
|
||||
> To use custom subagents, you must explicitly enable them in your
|
||||
> To use custom sub-agents, you must explicitly enable them in your
|
||||
> `settings.json`:
|
||||
>
|
||||
> ```json
|
||||
@@ -16,31 +16,31 @@ the main agent's context or toolset.
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> **Warning:** Subagents currently operate in
|
||||
> **Warning:** Sub-agents currently operate in
|
||||
> ["YOLO mode"](../reference/configuration.md#command-line-arguments), meaning
|
||||
> they may execute tools without individual user confirmation for each step.
|
||||
> Proceed with caution when defining agents with powerful tools like
|
||||
> `run_shell_command` or `write_file`.
|
||||
|
||||
## What are subagents?
|
||||
## What are sub-agents?
|
||||
|
||||
Subagents are "specialists" that the main Gemini agent can hire for a specific
|
||||
Sub-agents are "specialists" that the main Gemini agent can hire for a specific
|
||||
job.
|
||||
|
||||
- **Focused context:** Each subagent has its own system prompt and persona.
|
||||
- **Specialized tools:** Subagents can have a restricted or specialized set of
|
||||
- **Focused context:** Each sub-agent has its own system prompt and persona.
|
||||
- **Specialized tools:** Sub-agents can have a restricted or specialized set of
|
||||
tools.
|
||||
- **Independent context window:** Interactions with a subagent happen in a
|
||||
- **Independent context window:** Interactions with a sub-agent happen in a
|
||||
separate context loop, which saves tokens in your main conversation history.
|
||||
|
||||
Subagents are exposed to the main agent as a tool of the same name. When the
|
||||
main agent calls the tool, it delegates the task to the subagent. Once the
|
||||
subagent completes its task, it reports back to the main agent with its
|
||||
Sub-agents are exposed to the main agent as a tool of the same name. When the
|
||||
main agent calls the tool, it delegates the task to the sub-agent. Once the
|
||||
sub-agent completes its task, it reports back to the main agent with its
|
||||
findings.
|
||||
|
||||
## Built-in subagents
|
||||
## Built-in sub-agents
|
||||
|
||||
Gemini CLI comes with the following built-in subagents:
|
||||
Gemini CLI comes with the following built-in sub-agents:
|
||||
|
||||
### Codebase Investigator
|
||||
|
||||
@@ -75,131 +75,15 @@ Gemini CLI comes with the following built-in subagents:
|
||||
### Generalist Agent
|
||||
|
||||
- **Name:** `generalist_agent`
|
||||
- **Purpose:** Route tasks to the appropriate specialized subagent.
|
||||
- **Purpose:** Route tasks to the appropriate specialized sub-agent.
|
||||
- **When to use:** Implicitly used by the main agent for routing. Not directly
|
||||
invoked by the user.
|
||||
- **Configuration:** Enabled by default. No specific configuration options.
|
||||
|
||||
### Browser Agent (experimental)
|
||||
## Creating custom sub-agents
|
||||
|
||||
- **Name:** `browser_agent`
|
||||
- **Purpose:** Automate web browser tasks — navigating websites, filling forms,
|
||||
clicking buttons, and extracting information from web pages — using the
|
||||
accessibility tree.
|
||||
- **When to use:** "Go to example.com and fill out the contact form," "Extract
|
||||
the pricing table from this page," "Click the login button and enter my
|
||||
credentials."
|
||||
|
||||
> **Note:** This is a preview feature currently under active development.
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
The browser agent requires:
|
||||
|
||||
- **Chrome** version 144 or later (any recent stable release will work).
|
||||
- **Node.js** with `npx` available (used to launch the
|
||||
[`chrome-devtools-mcp`](https://www.npmjs.com/package/chrome-devtools-mcp)
|
||||
server).
|
||||
|
||||
#### Enabling the browser agent
|
||||
|
||||
The browser agent is disabled by default. Enable it in your `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"overrides": {
|
||||
"browser_agent": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Session modes
|
||||
|
||||
The `sessionMode` setting controls how Chrome is launched and managed. Set it
|
||||
under `agents.browser`:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"overrides": {
|
||||
"browser_agent": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
"sessionMode": "persistent"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The available modes are:
|
||||
|
||||
| Mode | Description |
|
||||
| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `persistent` | **(Default)** Launches Chrome with a persistent profile stored at `~/.gemini/cli-browser-profile/`. Cookies, history, and settings are preserved between sessions. |
|
||||
| `isolated` | Launches Chrome with a temporary profile that is deleted after each session. Use this for clean-state automation. |
|
||||
| `existing` | Attaches to an already-running Chrome instance. You must enable remote debugging first by navigating to `chrome://inspect/#remote-debugging` in Chrome. No new browser process is launched. |
|
||||
|
||||
#### Configuration reference
|
||||
|
||||
All browser-specific settings go under `agents.browser` in your `settings.json`.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| :------------ | :-------- | :------------- | :---------------------------------------------------------------------------------------------- |
|
||||
| `sessionMode` | `string` | `"persistent"` | How Chrome is managed: `"persistent"`, `"isolated"`, or `"existing"`. |
|
||||
| `headless` | `boolean` | `false` | Run Chrome in headless mode (no visible window). |
|
||||
| `profilePath` | `string` | — | Custom path to a browser profile directory. |
|
||||
| `visualModel` | `string` | — | Model override for the visual agent (for example, `"gemini-2.5-computer-use-preview-10-2025"`). |
|
||||
|
||||
#### Security
|
||||
|
||||
The browser agent enforces the following security restrictions:
|
||||
|
||||
- **Blocked URL patterns:** `file://`, `javascript:`, `data:text/html`,
|
||||
`chrome://extensions`, and `chrome://settings/passwords` are always blocked.
|
||||
- **Sensitive action confirmation:** Actions like form filling, file uploads,
|
||||
and form submissions require user confirmation through the standard policy
|
||||
engine.
|
||||
|
||||
#### Visual agent
|
||||
|
||||
By default, the browser agent interacts with pages through the accessibility
|
||||
tree using element `uid` values. For tasks that require visual identification
|
||||
(for example, "click the yellow button" or "find the red error message"), you
|
||||
can enable the visual agent by setting a `visualModel`:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"overrides": {
|
||||
"browser_agent": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"browser": {
|
||||
"visualModel": "gemini-2.5-computer-use-preview-10-2025"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When enabled, the agent gains access to the `analyze_screenshot` tool, which
|
||||
captures a screenshot and sends it to the vision model for analysis. The model
|
||||
returns coordinates and element descriptions that the browser agent uses with
|
||||
the `click_at` tool for precise, coordinate-based interactions.
|
||||
|
||||
> **Note:** The visual agent requires API key or Vertex AI authentication. It is
|
||||
> not available when using Google Login.
|
||||
|
||||
## Creating custom subagents
|
||||
|
||||
You can create your own subagents to automate specific workflows or enforce
|
||||
specific personas. To use custom subagents, you must enable them in your
|
||||
You can create your own sub-agents to automate specific workflows or enforce
|
||||
specific personas. To use custom sub-agents, you must enable them in your
|
||||
`settings.json`:
|
||||
|
||||
```json
|
||||
@@ -254,20 +138,20 @@ it yourself; just report it.
|
||||
|
||||
### Configuration schema
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
| :------------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `name` | string | Yes | Unique identifier (slug) used as the tool name for the agent. Only lowercase letters, numbers, hyphens, and underscores. |
|
||||
| `description` | string | Yes | Short description of what the agent does. This is visible to the main agent to help it decide when to call this subagent. |
|
||||
| `kind` | string | No | `local` (default) or `remote`. |
|
||||
| `tools` | array | No | List of tool names this agent can use. If omitted, it may have access to a default set. |
|
||||
| `model` | string | No | Specific model to use (e.g., `gemini-2.5-pro`). Defaults to `inherit` (uses the main session model). |
|
||||
| `temperature` | number | No | Model temperature (0.0 - 2.0). |
|
||||
| `max_turns` | number | No | Maximum number of conversation turns allowed for this agent before it must return. Defaults to `15`. |
|
||||
| `timeout_mins` | number | No | Maximum execution time in minutes. Defaults to `5`. |
|
||||
| Field | Type | Required | Description |
|
||||
| :------------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `name` | string | Yes | Unique identifier (slug) used as the tool name for the agent. Only lowercase letters, numbers, hyphens, and underscores. |
|
||||
| `description` | string | Yes | Short description of what the agent does. This is visible to the main agent to help it decide when to call this sub-agent. |
|
||||
| `kind` | string | No | `local` (default) or `remote`. |
|
||||
| `tools` | array | No | List of tool names this agent can use. If omitted, it may have access to a default set. |
|
||||
| `model` | string | No | Specific model to use (e.g., `gemini-2.5-pro`). Defaults to `inherit` (uses the main session model). |
|
||||
| `temperature` | number | No | Model temperature (0.0 - 2.0). |
|
||||
| `max_turns` | number | No | Maximum number of conversation turns allowed for this agent before it must return. Defaults to `15`. |
|
||||
| `timeout_mins` | number | No | Maximum execution time in minutes. Defaults to `5`. |
|
||||
|
||||
### Optimizing your subagent
|
||||
### Optimizing your sub-agent
|
||||
|
||||
The main agent's system prompt encourages it to use an expert subagent when one
|
||||
The main agent's system prompt encourages it to use an expert sub-agent when one
|
||||
is available. It decides whether an agent is a relevant expert based on the
|
||||
agent's description. You can improve the reliability with which an agent is used
|
||||
by updating the description to more clearly indicate:
|
||||
@@ -276,7 +160,7 @@ by updating the description to more clearly indicate:
|
||||
- When it should be used.
|
||||
- Some example scenarios.
|
||||
|
||||
For example, the following subagent description should be called fairly
|
||||
For example, the following sub-agent description should be called fairly
|
||||
consistently for Git operations.
|
||||
|
||||
> Git expert agent which should be used for all local and remote git operations.
|
||||
@@ -286,13 +170,13 @@ consistently for Git operations.
|
||||
> - Searching for regressions with bisect
|
||||
> - Interacting with source control and issues providers such as GitHub.
|
||||
|
||||
If you need to further tune your subagent, you can do so by selecting the model
|
||||
If you need to further tune your sub-agent, you can do so by selecting the model
|
||||
to optimize for with `/model` and then asking the model why it does not think
|
||||
that your subagent was called with a specific prompt and the given description.
|
||||
that your sub-agent was called with a specific prompt and the given description.
|
||||
|
||||
## Remote subagents (Agent2Agent) (experimental)
|
||||
|
||||
Gemini CLI can also delegate tasks to remote subagents using the Agent-to-Agent
|
||||
Gemini CLI can also delegate tasks to remote sub-agents using the Agent-to-Agent
|
||||
(A2A) protocol.
|
||||
|
||||
> **Note: Remote subagents are currently an experimental feature.**
|
||||
@@ -300,8 +184,8 @@ Gemini CLI can also delegate tasks to remote subagents using the Agent-to-Agent
|
||||
See the [Remote Subagents documentation](/docs/core/remote-agents) for detailed
|
||||
configuration and usage instructions.
|
||||
|
||||
## Extension subagents
|
||||
## Extension sub-agents
|
||||
|
||||
Extensions can bundle and distribute subagents. See the
|
||||
[Extensions documentation](../extensions/index.md#subagents) for details on how
|
||||
Extensions can bundle and distribute sub-agents. See the
|
||||
[Extensions documentation](../extensions/index.md#sub-agents) for details on how
|
||||
to package agents within an extension.
|
||||
|
||||
@@ -116,9 +116,7 @@ The manifest file defines the extension's behavior and configuration.
|
||||
"description": "My awesome extension",
|
||||
"mcpServers": {
|
||||
"my-server": {
|
||||
"command": "node",
|
||||
"args": ["${extensionPath}/my-server.js"],
|
||||
"cwd": "${extensionPath}"
|
||||
"command": "node my-server.js"
|
||||
}
|
||||
},
|
||||
"contextFileName": "GEMINI.md",
|
||||
@@ -126,41 +124,19 @@ The manifest file defines the extension's behavior and configuration.
|
||||
}
|
||||
```
|
||||
|
||||
- `name`: The name of the extension. This is used to uniquely identify the
|
||||
extension and for conflict resolution when extension commands have the same
|
||||
name as user or project commands. The name should be lowercase or numbers and
|
||||
use dashes instead of underscores or spaces. This is how users will refer to
|
||||
your extension in the CLI. Note that we expect this name to match the
|
||||
extension directory name.
|
||||
- `version`: The version of the extension.
|
||||
- `description`: A short description of the extension. This will be displayed on
|
||||
[geminicli.com/extensions](https://geminicli.com/extensions).
|
||||
- `mcpServers`: A map of MCP servers to settings. The key is the name of the
|
||||
server, and the value is the server configuration. These servers will be
|
||||
loaded on startup just like MCP servers defined in a
|
||||
[`settings.json` file](../reference/configuration.md). If both an extension
|
||||
and a `settings.json` file define an MCP server with the same name, the server
|
||||
defined in the `settings.json` file takes precedence.
|
||||
- Note that all MCP server configuration options are supported except for
|
||||
`trust`.
|
||||
- For portability, you should use `${extensionPath}` to refer to files within
|
||||
your extension directory.
|
||||
- Separate your executable and its arguments using `command` and `args`
|
||||
instead of putting them both in `command`.
|
||||
- `contextFileName`: The name of the file that contains the context for the
|
||||
extension. This will be used to load the context from the extension directory.
|
||||
If this property is not used but a `GEMINI.md` file is present in your
|
||||
extension directory, then that file will be loaded.
|
||||
- `excludeTools`: An array of tool names to exclude from the model. You can also
|
||||
specify command-specific restrictions for tools that support it, like the
|
||||
`run_shell_command` tool. For example,
|
||||
`"excludeTools": ["run_shell_command(rm -rf)"]` will block the `rm -rf`
|
||||
command. Note that this differs from the MCP server `excludeTools`
|
||||
functionality, which can be listed in the MCP server config.
|
||||
|
||||
When Gemini CLI starts, it loads all the extensions and merges their
|
||||
configurations. If there are any conflicts, the workspace configuration takes
|
||||
precedence.
|
||||
- `name`: A unique identifier for the extension. Use lowercase letters, numbers,
|
||||
and dashes. This name must match the extension's directory name.
|
||||
- `version`: The current version of the extension.
|
||||
- `description`: A short summary shown in the extension gallery.
|
||||
- <a id="mcp-servers"></a>`mcpServers`: A map of Model Context Protocol (MCP)
|
||||
servers. Extension servers follow the same format as standard
|
||||
[CLI configuration](../reference/configuration.md).
|
||||
- `contextFileName`: The name of the context file (defaults to `GEMINI.md`). Can
|
||||
also be an array of strings to load multiple context files.
|
||||
- `excludeTools`: An array of tools to block from the model. You can restrict
|
||||
specific arguments, such as `run_shell_command(rm -rf)`.
|
||||
- `themes`: An optional list of themes provided by the extension. See
|
||||
[Themes](../cli/themes.md) for more information.
|
||||
|
||||
### Extension settings
|
||||
|
||||
@@ -227,42 +203,6 @@ skill definitions in a `skills/` directory. For example,
|
||||
Provide [sub-agents](../core/subagents.md) that users can delegate tasks to. Add
|
||||
agent definition files (`.md`) to an `agents/` directory in your extension root.
|
||||
|
||||
### <a id="policy-engine"></a>Policy Engine
|
||||
|
||||
Extensions can contribute policy rules and safety checkers to the Gemini CLI
|
||||
[Policy Engine](../reference/policy-engine.md). These rules are defined in
|
||||
`.toml` files and take effect when the extension is activated.
|
||||
|
||||
To add policies, create a `policies/` directory in your extension's root and
|
||||
place your `.toml` policy files inside it. Gemini CLI automatically loads all
|
||||
`.toml` files from this directory.
|
||||
|
||||
Rules contributed by extensions run in their own tier (tier 2), alongside
|
||||
workspace-defined policies. This tier has higher priority than the default rules
|
||||
but lower priority than user or admin policies.
|
||||
|
||||
> **Warning:** For security, Gemini CLI ignores any `allow` decisions or `yolo`
|
||||
> mode configurations in extension policies. This ensures that an extension
|
||||
> cannot automatically approve tool calls or bypass security measures without
|
||||
> your confirmation.
|
||||
|
||||
**Example `policies.toml`**
|
||||
|
||||
```toml
|
||||
[[rule]]
|
||||
toolName = "my_server__dangerous_tool"
|
||||
decision = "ask_user"
|
||||
priority = 100
|
||||
|
||||
[[safety_checker]]
|
||||
toolName = "my_server__write_data"
|
||||
priority = 200
|
||||
[safety_checker.checker]
|
||||
type = "in-process"
|
||||
name = "allowed-path"
|
||||
required_context = ["environment"]
|
||||
```
|
||||
|
||||
### Themes
|
||||
|
||||
Extensions can provide custom themes to personalize the CLI UI. Themes are
|
||||
|
||||
@@ -2,21 +2,6 @@
|
||||
|
||||
Gemini 3 Pro and Gemini 3 Flash are available on Gemini CLI for all users!
|
||||
|
||||
> **Note:** Gemini 3.1 Pro Preview is rolling out. To determine whether you have
|
||||
> access to Gemini 3.1, use the `/model` command and select **Manual**. If you
|
||||
> have access, you will see `gemini-3.1-pro-preview`.
|
||||
>
|
||||
> If you have access to Gemini 3.1, it will be included in model routing when
|
||||
> you select **Auto (Gemini 3)**. You can also launch the Gemini 3.1 model
|
||||
> directly using the `-m` flag:
|
||||
>
|
||||
> ```
|
||||
> gemini -m gemini-3.1-pro-preview
|
||||
> ```
|
||||
>
|
||||
> Learn more about [models](../cli/model.md) and
|
||||
> [model routing](../cli/model-routing.md).
|
||||
|
||||
## How to get started with Gemini 3 on Gemini CLI
|
||||
|
||||
Get started by upgrading Gemini CLI to the latest version:
|
||||
@@ -27,8 +12,9 @@ npm install -g @google/gemini-cli@latest
|
||||
|
||||
After you’ve confirmed your version is 0.21.1 or later:
|
||||
|
||||
1. Run `/model`.
|
||||
2. Select **Auto (Gemini 3)**.
|
||||
1. Use the `/settings` command in Gemini CLI.
|
||||
2. Toggle **Preview Features** to `true`.
|
||||
3. Run `/model` and select **Auto (Gemini 3)**.
|
||||
|
||||
For more information, see [Gemini CLI model selection](../cli/model.md).
|
||||
|
||||
|
||||
@@ -64,16 +64,6 @@ and more.
|
||||
|
||||
To explore the power of Gemini CLI, see [Gemini CLI examples](./examples.md).
|
||||
|
||||
## Check usage and quota
|
||||
|
||||
You can check your current token usage and quota information using the
|
||||
`/stats model` command. This command provides a snapshot of your current
|
||||
session's token usage, as well as your overall quota and usage for the supported
|
||||
models.
|
||||
|
||||
For more information on the `/stats` command and its subcommands, see the
|
||||
[Command Reference](../../reference/commands.md#stats).
|
||||
|
||||
## Next steps
|
||||
|
||||
- Follow the [File management](../cli/tutorials/file-management.md) guide to
|
||||
|
||||
@@ -420,7 +420,7 @@ When you open a project with hooks defined in `.gemini/settings.json`:
|
||||
|
||||
Hooks inherit the environment of the Gemini CLI process, which may include
|
||||
sensitive API keys. Gemini CLI provides a
|
||||
[redaction system](/docs/reference/configuration.md#environment-variable-redaction)
|
||||
[redaction system](/docs/reference/configuration#environment-variable-redaction)
|
||||
that automatically filters variables matching sensitive patterns (e.g., `KEY`,
|
||||
`TOKEN`).
|
||||
|
||||
|
||||
@@ -98,8 +98,6 @@ and parameter rewriting.
|
||||
- `tool_name`: (`string`) The name of the tool being called.
|
||||
- `tool_input`: (`object`) The raw arguments generated by the model.
|
||||
- `mcp_context`: (`object`) Optional metadata for MCP-based tools.
|
||||
- `original_request_name`: (`string`) The original name of the tool being
|
||||
called, if this is a tail tool call.
|
||||
- **Relevant Output Fields**:
|
||||
- `decision`: Set to `"deny"` (or `"block"`) to prevent the tool from
|
||||
executing.
|
||||
@@ -122,18 +120,12 @@ hiding sensitive output from the agent.
|
||||
- `tool_response`: (`object`) The result containing `llmContent`,
|
||||
`returnDisplay`, and optional `error`.
|
||||
- `mcp_context`: (`object`)
|
||||
- `original_request_name`: (`string`) The original name of the tool being
|
||||
called, if this is a tail tool call.
|
||||
- **Relevant Output Fields**:
|
||||
- `decision`: Set to `"deny"` to hide the real tool output from the agent.
|
||||
- `reason`: Required if denied. This text **replaces** the tool result sent
|
||||
back to the model.
|
||||
- `hookSpecificOutput.additionalContext`: Text that is **appended** to the
|
||||
tool result for the agent.
|
||||
- `hookSpecificOutput.tailToolCallRequest`: (`{ name: string, args: object }`)
|
||||
A request to execute another tool immediately after this one. The result of
|
||||
this "tail call" will replace the original tool's response. Ideal for
|
||||
programmatic tool routing.
|
||||
- `continue`: Set to `false` to **kill the entire agent loop** immediately.
|
||||
- **Exit Code 2 (Block Result)**: Hides the tool result. Uses `stderr` as the
|
||||
replacement content sent to the agent. **The turn continues.**
|
||||
|
||||
@@ -170,20 +170,6 @@ messages and how to resolve them.
|
||||
- **Solution:** Run `/ide enable` to try and reconnect. If the issue
|
||||
continues, open a new terminal window or restart your IDE.
|
||||
|
||||
### Manual PID override
|
||||
|
||||
If automatic IDE detection fails, or if you are running Gemini CLI in a
|
||||
standalone terminal and want to manually associate it with a specific IDE
|
||||
instance, you can set the `GEMINI_CLI_IDE_PID` environment variable to the
|
||||
process ID (PID) of your IDE.
|
||||
|
||||
```bash
|
||||
export GEMINI_CLI_IDE_PID=12345
|
||||
```
|
||||
|
||||
When this variable is set, Gemini CLI will skip automatic detection and attempt
|
||||
to connect using the provided PID.
|
||||
|
||||
### Configuration errors
|
||||
|
||||
- **Message:**
|
||||
|
||||
+104
-86
@@ -12,8 +12,7 @@ npm install -g @google/gemini-cli
|
||||
|
||||
## Get started
|
||||
|
||||
Jump in to Gemini CLI.
|
||||
|
||||
- **[Overview](./index.md):** An overview of Gemini CLI and its features.
|
||||
- **[Quickstart](./get-started/index.md):** Your first session with Gemini CLI.
|
||||
- **[Installation](./get-started/installation.md):** How to install Gemini CLI
|
||||
on your system.
|
||||
@@ -23,17 +22,13 @@ Jump in to Gemini CLI.
|
||||
action.
|
||||
- **[CLI cheatsheet](./cli/cli-reference.md):** A quick reference for common
|
||||
commands and options.
|
||||
- **[Gemini 3 on Gemini CLI](./get-started/gemini-3.md):** Learn about Gemini 3
|
||||
support in Gemini CLI.
|
||||
- **[Gemini 3 on Gemini CLI](./get-started/gemini-3.md):** Learn how to use
|
||||
Gemini 3 with Gemini CLI.
|
||||
|
||||
## Use Gemini CLI
|
||||
|
||||
User-focused guides and tutorials for daily development workflows.
|
||||
|
||||
- **[File management](./cli/tutorials/file-management.md):** How to work with
|
||||
local files and directories.
|
||||
- **[Get started with Agent skills](./cli/tutorials/skills-getting-started.md):**
|
||||
Getting started with specialized expertise.
|
||||
- **[Manage context and memory](./cli/tutorials/memory-management.md):**
|
||||
Managing persistent instructions and facts.
|
||||
- **[Execute shell commands](./cli/tutorials/shell-commands.md):** Executing
|
||||
@@ -44,98 +39,121 @@ User-focused guides and tutorials for daily development workflows.
|
||||
complex workflows.
|
||||
- **[Web search and fetch](./cli/tutorials/web-tools.md):** Searching and
|
||||
fetching content from the web.
|
||||
- **[Set up an MCP server](./cli/tutorials/mcp-setup.md):** Set up an MCP
|
||||
server.
|
||||
- **[Automate tasks](./cli/tutorials/automation.md):** Automate tasks.
|
||||
- **[Get started with skills](./cli/tutorials/skills-getting-started.md):**
|
||||
Getting started with specialized expertise.
|
||||
- **[Set up an MCP server](./cli/tutorials/mcp-setup.md):** Learn how to set up
|
||||
a Model-Context Protocol server.
|
||||
- **[Automate tasks](./cli/tutorials/automation.md):** Automate common
|
||||
development tasks.
|
||||
|
||||
## Features
|
||||
|
||||
Technical documentation for each capability of Gemini CLI.
|
||||
|
||||
- **[Extensions](./extensions/index.md):** Extend Gemini CLI with new tools and
|
||||
capabilities.
|
||||
- **[Agent Skills](./cli/skills.md):** Use specialized agents for specific
|
||||
tasks.
|
||||
- **[Checkpointing](./cli/checkpointing.md):** Automatic session snapshots.
|
||||
- **[Headless mode](./cli/headless.md):** Programmatic and scripting interface.
|
||||
- **[Hooks](./hooks/index.md):** Customize Gemini CLI behavior with scripts.
|
||||
- **[Agent Skills](./cli/skills.md):** Extend the capabilities of Gemini CLI
|
||||
with custom skills.
|
||||
- **[Authentication](./get-started/authentication.md):** Learn about the
|
||||
different authentication methods.
|
||||
- **[Checkpointing](./cli/checkpointing.md):** Automatically save and restore
|
||||
your sessions.
|
||||
- **[Extensions](./extensions/index.md):** Extend the functionality of Gemini
|
||||
CLI with extensions.
|
||||
- **[Headless mode](./cli/headless.md):** Run Gemini CLI in a non-interactive
|
||||
mode.
|
||||
- **[Hooks](./hooks/index.md):** Customize the behavior of Gemini CLI with
|
||||
hooks.
|
||||
- **[IDE integration](./ide-integration/index.md):** Integrate Gemini CLI with
|
||||
your favorite IDE.
|
||||
- **[MCP servers](./tools/mcp-server.md):** Connect to and use remote agents.
|
||||
- **[Model routing](./cli/model-routing.md):** Automatic fallback resilience.
|
||||
- **[Model selection](./cli/model.md):** Choose the best model for your needs.
|
||||
- **[Plan mode 🔬](./cli/plan-mode.md):** Use a safe, read-only mode for
|
||||
planning complex changes.
|
||||
- **[Subagents 🔬](./core/subagents.md):** Using specialized agents for specific
|
||||
tasks.
|
||||
- **[Remote subagents 🔬](./core/remote-agents.md):** Connecting to and using
|
||||
remote agents.
|
||||
- **[Rewind](./cli/rewind.md):** Rewind and replay sessions.
|
||||
- **[Sandboxing](./cli/sandbox.md):** Isolate tool execution.
|
||||
- **[Settings](./cli/settings.md):** Full configuration reference.
|
||||
- **[Telemetry](./cli/telemetry.md):** Usage and performance metric details.
|
||||
- **[Token caching](./cli/token-caching.md):** Performance optimization.
|
||||
- **[MCP servers](./tools/mcp-server.md):** Connect to Model-Context Protocol
|
||||
servers.
|
||||
- **[Model routing](./cli/model-routing.md):** Automatically route requests to
|
||||
the best model.
|
||||
- **[Model selection](./cli/model.md):** Learn how to select the right model for
|
||||
your task.
|
||||
- **[Plan mode (experimental)](./cli/plan-mode.md):** Plan and review changes
|
||||
before they are executed.
|
||||
- **[Rewind](./cli/rewind.md):** Rewind the conversation to a previous point.
|
||||
- **[Sandboxing](./cli/sandbox.md):** Isolate tool execution in a sandboxed
|
||||
environment.
|
||||
- **[Settings](./cli/settings.md):** Customize the behavior of Gemini CLI.
|
||||
- **[Telemetry](./cli/telemetry.md):** Understand the usage data that Gemini CLI
|
||||
collects.
|
||||
- **[Token caching](./cli/token-caching.md):** Cache tokens to improve
|
||||
performance.
|
||||
|
||||
## Configuration
|
||||
|
||||
Settings and customization options for Gemini CLI.
|
||||
- **[Custom commands](./cli/custom-commands.md):** Create your own custom
|
||||
commands.
|
||||
- **[Enterprise configuration](./cli/enterprise.md):** Configure Gemini CLI for
|
||||
your enterprise.
|
||||
- **[Ignore files (.geminiignore)](./cli/gemini-ignore.md):** Ignore files and
|
||||
directories.
|
||||
- **[Model configuration](./cli/generation-settings.md):** Configure the
|
||||
generation settings for your models.
|
||||
- **[Project context (GEMINI.md)](./cli/gemini-md.md):** Provide
|
||||
project-specific context to the model.
|
||||
- **[Settings](./cli/settings.md):** A full reference of all the available
|
||||
settings.
|
||||
- **[System prompt override](./cli/system-prompt.md):** Override the default
|
||||
system prompt.
|
||||
- **[Themes](./cli/themes.md):** Customize the look and feel of Gemini CLI.
|
||||
- **[Trusted folders](./cli/trusted-folders.md):** Configure trusted folders to
|
||||
bypass security warnings.
|
||||
|
||||
- **[Custom commands](./cli/custom-commands.md):** Personalized shortcuts.
|
||||
- **[Enterprise configuration](./cli/enterprise.md):** Professional environment
|
||||
controls.
|
||||
- **[Ignore files (.geminiignore)](./cli/gemini-ignore.md):** Exclusion pattern
|
||||
reference.
|
||||
- **[Model configuration](./cli/generation-settings.md):** Fine-tune generation
|
||||
parameters like temperature and thinking budget.
|
||||
- **[Project context (GEMINI.md)](./cli/gemini-md.md):** Technical hierarchy of
|
||||
context files.
|
||||
- **[System prompt override](./cli/system-prompt.md):** Instruction replacement
|
||||
logic.
|
||||
- **[Themes](./cli/themes.md):** UI personalization technical guide.
|
||||
- **[Trusted folders](./cli/trusted-folders.md):** Security permission logic.
|
||||
## Extensions
|
||||
|
||||
## Reference
|
||||
|
||||
Deep technical documentation and API specifications.
|
||||
|
||||
- **[Command reference](./reference/commands.md):** Detailed slash command
|
||||
guide.
|
||||
- **[Configuration reference](./reference/configuration.md):** Settings and
|
||||
environment variables.
|
||||
- **[Keyboard shortcuts](./reference/keyboard-shortcuts.md):** Productivity
|
||||
tips.
|
||||
- **[Memory import processor](./reference/memport.md):** How Gemini CLI
|
||||
processes memory from various sources.
|
||||
- **[Policy engine](./reference/policy-engine.md):** Fine-grained execution
|
||||
control.
|
||||
- **[Tools API](./reference/tools-api.md):** The API for defining and using
|
||||
tools.
|
||||
|
||||
## Resources
|
||||
|
||||
Support, release history, and legal information.
|
||||
|
||||
- **[FAQ](./resources/faq.md):** Answers to frequently asked questions.
|
||||
- **[Quota and pricing](./resources/quota-and-pricing.md):** Limits and billing
|
||||
details.
|
||||
- **[Terms and privacy](./resources/tos-privacy.md):** Official notices and
|
||||
terms.
|
||||
- **[Troubleshooting](./resources/troubleshooting.md):** Common issues and
|
||||
solutions.
|
||||
- **[Uninstall](./resources/uninstall.md):** How to uninstall Gemini CLI.
|
||||
- **[Overview](./extensions/index.md):** An overview of the extension system.
|
||||
- **[User guide: Install and manage](./extensions/index.md#manage-extensions):**
|
||||
Learn how to install and manage extensions.
|
||||
- **[Developer guide: Build extensions](./extensions/writing-extensions.md):**
|
||||
Learn how to build your own extensions.
|
||||
- **[Developer guide: Best practices](./extensions/best-practices.md):** Best
|
||||
practices for writing extensions.
|
||||
- **[Developer guide: Releasing](./extensions/releasing.md):** Learn how to
|
||||
release your extensions.
|
||||
- **[Developer guide: Reference](./extensions/reference.md):** A full reference
|
||||
of the extension API.
|
||||
|
||||
## Development
|
||||
|
||||
- **[Contribution guide](/docs/contributing):** How to contribute to Gemini CLI.
|
||||
- **[Integration testing](./integration-tests.md):** Running integration tests.
|
||||
- **[Issue and PR automation](./issue-and-pr-automation.md):** Automation for
|
||||
issues and pull requests.
|
||||
- **[Local development](./local-development.md):** Setting up a local
|
||||
development environment.
|
||||
- **[NPM package structure](./npm.md):** The structure of the NPM packages.
|
||||
- **[Contribution guide](/docs/contributing):** Learn how to contribute to
|
||||
Gemini CLI.
|
||||
- **[Integration testing](./integration-tests.md):** Learn how to run the
|
||||
integration tests.
|
||||
- **[Issue and PR automation](./issue-and-pr-automation.md):** Learn about the
|
||||
issue and PR automation.
|
||||
- **[Local development](./local-development.md):** Learn how to set up your
|
||||
local development environment.
|
||||
- **[NPM package structure](./npm.md):** Learn about the structure of the NPM
|
||||
packages.
|
||||
|
||||
## Releases
|
||||
## Reference
|
||||
|
||||
- **[Release notes](./changelogs/index.md):** Release notes for all versions.
|
||||
- **[Command reference](./reference/commands.md):** A full reference of all the
|
||||
available commands.
|
||||
- **[Configuration reference](./reference/configuration.md):** A full reference
|
||||
of all the available configuration options.
|
||||
- **[Keyboard shortcuts](./reference/keyboard-shortcuts.md):** A list of all the
|
||||
available keyboard shortcuts.
|
||||
- **[Memory import processor](./reference/memport.md):** Learn how to use the
|
||||
memory import processor.
|
||||
- **[Policy engine](./reference/policy-engine.md):** Learn how to use the policy
|
||||
engine.
|
||||
- **[Tools API](./reference/tools-api.md):** Learn how to use the tools API.
|
||||
|
||||
## Resources
|
||||
|
||||
- **[Quota and pricing](./resources/quota-and-pricing.md):** Information about
|
||||
quota and pricing.
|
||||
- **[Terms and privacy](./resources/tos-privacy.md):** The terms of service and
|
||||
privacy policy.
|
||||
- **[FAQ](./resources/faq.md):** Frequently asked questions.
|
||||
- **[Troubleshooting](./resources/troubleshooting.md):** Troubleshooting common
|
||||
issues.
|
||||
- **[Uninstall](./resources/uninstall.md):** How to uninstall Gemini CLI.
|
||||
|
||||
## Changelog
|
||||
|
||||
- **[Release notes](./changelogs/index.md):** The release notes for all
|
||||
versions.
|
||||
- **[Stable release](./changelogs/latest.md):** The latest stable release.
|
||||
- **[Preview release](./changelogs/preview.md):** The latest preview release.
|
||||
|
||||
+41
-47
@@ -1,21 +1,23 @@
|
||||
# Local development guide
|
||||
|
||||
This guide provides instructions for setting up and using local development
|
||||
features, such as tracing.
|
||||
features, such as development tracing.
|
||||
|
||||
## Tracing
|
||||
## Development tracing
|
||||
|
||||
Traces are OpenTelemetry (OTel) records that help you debug your code by
|
||||
instrumenting key events like model calls, tool scheduler operations, and tool
|
||||
calls.
|
||||
Development traces (dev traces) are OpenTelemetry (OTel) traces that help you
|
||||
debug your code by instrumenting interesting events like model calls, tool
|
||||
scheduler, tool calls, etc.
|
||||
|
||||
Traces provide deep visibility into agent behavior and are invaluable for
|
||||
debugging complex issues. They are captured automatically when telemetry is
|
||||
enabled.
|
||||
Dev traces are verbose and are specifically meant for understanding agent
|
||||
behavior and debugging issues. They are disabled by default.
|
||||
|
||||
### Viewing traces
|
||||
To enable dev traces, set the `GEMINI_DEV_TRACING=true` environment variable
|
||||
when running Gemini CLI.
|
||||
|
||||
You can view traces using either Jaeger or the Genkit Developer UI.
|
||||
### Viewing dev traces
|
||||
|
||||
You can view dev traces using either Jaeger or the Genkit Developer UI.
|
||||
|
||||
#### Using Genkit
|
||||
|
||||
@@ -35,12 +37,13 @@ Genkit provides a web-based UI for viewing traces and other telemetry data.
|
||||
Genkit Developer UI: http://localhost:4000
|
||||
```
|
||||
|
||||
2. **Run Gemini CLI:**
|
||||
2. **Run Gemini CLI with dev tracing:**
|
||||
|
||||
In a separate terminal, run your Gemini CLI command:
|
||||
In a separate terminal, run your Gemini CLI command with the
|
||||
`GEMINI_DEV_TRACING` environment variable:
|
||||
|
||||
```bash
|
||||
gemini
|
||||
GEMINI_DEV_TRACING=true gemini
|
||||
```
|
||||
|
||||
3. **View the traces:**
|
||||
@@ -50,7 +53,7 @@ Genkit provides a web-based UI for viewing traces and other telemetry data.
|
||||
|
||||
#### Using Jaeger
|
||||
|
||||
You can view traces in the Jaeger UI. To get started, follow these steps:
|
||||
You can view dev traces in the Jaeger UI. To get started, follow these steps:
|
||||
|
||||
1. **Start the telemetry collector:**
|
||||
|
||||
@@ -64,12 +67,13 @@ You can view traces in the Jaeger UI. To get started, follow these steps:
|
||||
This command also configures your workspace for local telemetry and provides
|
||||
a link to the Jaeger UI (usually `http://localhost:16686`).
|
||||
|
||||
2. **Run Gemini CLI:**
|
||||
2. **Run Gemini CLI with dev tracing:**
|
||||
|
||||
In a separate terminal, run your Gemini CLI command:
|
||||
In a separate terminal, run your Gemini CLI command with the
|
||||
`GEMINI_DEV_TRACING` environment variable:
|
||||
|
||||
```bash
|
||||
gemini
|
||||
GEMINI_DEV_TRACING=true gemini
|
||||
```
|
||||
|
||||
3. **View the traces:**
|
||||
@@ -80,10 +84,10 @@ You can view traces in the Jaeger UI. To get started, follow these steps:
|
||||
For more detailed information on telemetry, see the
|
||||
[telemetry documentation](./cli/telemetry.md).
|
||||
|
||||
### Instrumenting code with traces
|
||||
### Instrumenting code with dev traces
|
||||
|
||||
You can add traces to your own code for more detailed instrumentation. This is
|
||||
useful for debugging and understanding the flow of execution.
|
||||
You can add dev traces to your own code for more detailed instrumentation. This
|
||||
is useful for debugging and understanding the flow of execution.
|
||||
|
||||
Use the `runInDevTraceSpan` function to wrap any section of code in a trace
|
||||
span.
|
||||
@@ -92,39 +96,29 @@ Here is a basic example:
|
||||
|
||||
```typescript
|
||||
import { runInDevTraceSpan } from '@google/gemini-cli-core';
|
||||
import { GeminiCliOperation } from '@google/gemini-cli-core/lib/telemetry/constants.js';
|
||||
|
||||
await runInDevTraceSpan(
|
||||
{
|
||||
operation: GeminiCliOperation.ToolCall,
|
||||
attributes: {
|
||||
[GEN_AI_AGENT_NAME]: 'gemini-cli',
|
||||
},
|
||||
},
|
||||
async ({ metadata }) => {
|
||||
// The `metadata` object allows you to record the input and output of the
|
||||
// operation as well as other attributes.
|
||||
metadata.input = { key: 'value' };
|
||||
// Set custom attributes.
|
||||
metadata.attributes['custom.attribute'] = 'custom.value';
|
||||
await runInDevTraceSpan({ name: 'my-custom-span' }, async ({ metadata }) => {
|
||||
// The `metadata` object allows you to record the input and output of the
|
||||
// operation as well as other attributes.
|
||||
metadata.input = { key: 'value' };
|
||||
// Set custom attributes.
|
||||
metadata.attributes['gen_ai.request.model'] = 'gemini-4.0-mega';
|
||||
|
||||
// Your code to be traced goes here
|
||||
try {
|
||||
const output = await somethingRisky();
|
||||
metadata.output = output;
|
||||
return output;
|
||||
} catch (e) {
|
||||
metadata.error = e;
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
);
|
||||
// Your code to be traced goes here
|
||||
try {
|
||||
const output = await somethingRisky();
|
||||
metadata.output = output;
|
||||
return output;
|
||||
} catch (e) {
|
||||
metadata.error = e;
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this example:
|
||||
|
||||
- `operation`: The operation type of the span, represented by the
|
||||
`GeminiCliOperation` enum.
|
||||
- `name`: The name of the span, which will be displayed in the trace.
|
||||
- `metadata.input`: (Optional) An object containing the input data for the
|
||||
traced operation.
|
||||
- `metadata.output`: (Optional) An object containing the output data from the
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"/docs/architecture": "/docs/cli/index",
|
||||
"/docs/cli/commands": "/docs/reference/commands",
|
||||
"/docs/cli": "/docs",
|
||||
"/docs/cli/index": "/docs",
|
||||
"/docs/cli/keyboard-shortcuts": "/docs/reference/keyboard-shortcuts",
|
||||
"/docs/cli/uninstall": "/docs/resources/uninstall",
|
||||
"/docs/core/concepts": "/docs",
|
||||
"/docs/core/memport": "/docs/reference/memport",
|
||||
"/docs/core/policy-engine": "/docs/reference/policy-engine",
|
||||
"/docs/core/tools-api": "/docs/reference/tools-api",
|
||||
"/docs/faq": "/docs/resources/faq",
|
||||
"/docs/get-started/configuration": "/docs/reference/configuration",
|
||||
"/docs/get-started/configuration-v1": "/docs/reference/configuration",
|
||||
"/docs/index": "/docs",
|
||||
"/docs/quota-and-pricing": "/docs/resources/quota-and-pricing",
|
||||
"/docs/tos-privacy": "/docs/resources/tos-privacy",
|
||||
"/docs/troubleshooting": "/docs/resources/troubleshooting"
|
||||
}
|
||||
@@ -32,8 +32,6 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
conversation state interactively, or resuming a previous state from a later
|
||||
session.
|
||||
- **Sub-commands:**
|
||||
- **`debug`**
|
||||
- **Description:** Export the most recent API request as a JSON payload.
|
||||
- **`delete <tag>`**
|
||||
- **Description:** Deletes a saved conversation checkpoint.
|
||||
- **`list`**
|
||||
@@ -130,29 +128,8 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
|
||||
### `/extensions`
|
||||
|
||||
- **Description:** Manage extensions. See
|
||||
[Gemini CLI Extensions](../extensions/index.md).
|
||||
- **Sub-commands:**
|
||||
- **`config`**:
|
||||
- **Description:** Configure extension settings.
|
||||
- **`disable`**:
|
||||
- **Description:** Disable an extension.
|
||||
- **`enable`**:
|
||||
- **Description:** Enable an extension.
|
||||
- **`explore`**:
|
||||
- **Description:** Open extensions page in your browser.
|
||||
- **`install`**:
|
||||
- **Description:** Install an extension from a git repo or local path.
|
||||
- **`link`**:
|
||||
- **Description:** Link an extension from a local path.
|
||||
- **`list`**:
|
||||
- **Description:** List active extensions.
|
||||
- **`restart`**:
|
||||
- **Description:** Restart all extensions.
|
||||
- **`uninstall`**:
|
||||
- **Description:** Uninstall an extension.
|
||||
- **`update`**:
|
||||
- **Description:** Update extensions. Usage: update <extension-names>|--all
|
||||
- **Description:** Lists all active extensions in the current Gemini CLI
|
||||
session. See [Gemini CLI Extensions](../extensions/index.md).
|
||||
|
||||
### `/help` (or `/?`)
|
||||
|
||||
@@ -207,10 +184,6 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
servers that support OAuth authentication.
|
||||
- **`desc`**
|
||||
- **Description:** List configured MCP servers and tools with descriptions.
|
||||
- **`disable`**
|
||||
- **Description:** Disable an MCP server.
|
||||
- **`enable`**
|
||||
- **Description:** Enable a disabled MCP server.
|
||||
- **`list`** or **`ls`**:
|
||||
- **Description:** List configured MCP servers and tools. This is the
|
||||
default action if no subcommand is specified.
|
||||
@@ -244,32 +217,11 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
model.
|
||||
- **Note:** For more details on how `GEMINI.md` files contribute to
|
||||
hierarchical memory, see the
|
||||
[CLI Configuration documentation](./configuration.md).
|
||||
[CLI Configuration documentation](../reference/configuration.md).
|
||||
|
||||
### `/model`
|
||||
|
||||
- **Description:** Manage model configuration.
|
||||
- **Sub-commands:**
|
||||
- **`manage`**:
|
||||
- **Description:** Opens a dialog to configure the model.
|
||||
- **`set`**:
|
||||
- **Description:** Set the model to use.
|
||||
- **Usage:** `/model set <model-name> [--persist]`
|
||||
|
||||
### `/permissions`
|
||||
|
||||
- **Description:** Manage folder trust settings and other permissions.
|
||||
- **Sub-commands:**
|
||||
- **`trust`**:
|
||||
- **Description:** Manage folder trust settings.
|
||||
- **Usage:** `/permissions trust [<directory-path>]`
|
||||
|
||||
### `/plan`
|
||||
|
||||
- **Description:** Switch to Plan Mode (read-only) and view the current plan if
|
||||
one has been generated.
|
||||
- **Note:** This feature requires the `experimental.plan` setting to be
|
||||
enabled in your configuration.
|
||||
- **Description:** Opens a dialog to choose your Gemini model.
|
||||
|
||||
### `/policies`
|
||||
|
||||
@@ -295,7 +247,7 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
checkpoints to restore from.
|
||||
- **Usage:** `/restore [tool_call_id]`
|
||||
- **Note:** Only available if checkpointing is configured via
|
||||
[settings](./configuration.md). See
|
||||
[settings](../reference/configuration.md). See
|
||||
[Checkpointing documentation](../cli/checkpointing.md) for more details.
|
||||
|
||||
### `/rewind`
|
||||
@@ -372,16 +324,10 @@ Slash commands provide meta-level control over the CLI itself.
|
||||
### `/stats`
|
||||
|
||||
- **Description:** Display detailed statistics for the current Gemini CLI
|
||||
session.
|
||||
- **Sub-commands:**
|
||||
- **`session`**:
|
||||
- **Description:** Show session-specific usage statistics, including
|
||||
duration, tool calls, and performance metrics. This is the default view.
|
||||
- **`model`**:
|
||||
- **Description:** Show model-specific usage statistics, including token
|
||||
counts and quota information.
|
||||
- **`tools`**:
|
||||
- **Description:** Show tool-specific usage statistics.
|
||||
session, including token usage, cached token savings (when available), and
|
||||
session duration. Note: Cached token information is only displayed when cached
|
||||
tokens are being used, which occurs with API key authentication but not with
|
||||
OAuth authentication at this time.
|
||||
|
||||
### `/terminal-setup`
|
||||
|
||||
|
||||
+11
-106
@@ -121,38 +121,22 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Description:** Enable update notification prompts.
|
||||
- **Default:** `true`
|
||||
|
||||
- **`general.enableNotifications`** (boolean):
|
||||
- **Description:** Enable run-event notifications for action-required prompts
|
||||
and session completion. Currently macOS only.
|
||||
- **Default:** `false`
|
||||
|
||||
- **`general.checkpointing.enabled`** (boolean):
|
||||
- **Description:** Enable session checkpointing for recovery
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`general.plan.directory`** (string):
|
||||
- **Description:** The directory where planning artifacts are stored. If not
|
||||
specified, defaults to the system temporary directory.
|
||||
- **Default:** `undefined`
|
||||
- **`general.enablePromptCompletion`** (boolean):
|
||||
- **Description:** Enable AI-powered prompt completion suggestions while
|
||||
typing.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`general.plan.modelRouting`** (boolean):
|
||||
- **Description:** Automatically switch between Pro and Flash models based on
|
||||
Plan Mode status. Uses Pro for the planning phase and Flash for the
|
||||
implementation phase.
|
||||
- **Default:** `true`
|
||||
|
||||
- **`general.retryFetchErrors`** (boolean):
|
||||
- **Description:** Retry on "exception TypeError: fetch failed sending
|
||||
request" errors.
|
||||
- **Default:** `false`
|
||||
|
||||
- **`general.maxAttempts`** (number):
|
||||
- **Description:** Maximum number of attempts for requests to the main chat
|
||||
model. Cannot exceed 10.
|
||||
- **Default:** `10`
|
||||
|
||||
- **`general.debugKeystrokeLogging`** (boolean):
|
||||
- **Description:** Enable debug logging of keystrokes to the console.
|
||||
- **Default:** `false`
|
||||
@@ -233,11 +217,6 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Default:** `true`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`ui.showCompatibilityWarnings`** (boolean):
|
||||
- **Description:** Show warnings about terminal or OS compatibility issues.
|
||||
- **Default:** `true`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`ui.hideTips`** (boolean):
|
||||
- **Description:** Hide helpful tips in the UI
|
||||
- **Default:** `false`
|
||||
@@ -316,20 +295,13 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Description:** Show the spinner during operations.
|
||||
- **Default:** `true`
|
||||
|
||||
- **`ui.loadingPhrases`** (enum):
|
||||
- **Description:** What to show while the model is working: tips, witty
|
||||
comments, both, or nothing.
|
||||
- **Default:** `"tips"`
|
||||
- **Values:** `"tips"`, `"witty"`, `"all"`, `"off"`
|
||||
|
||||
- **`ui.customWittyPhrases`** (array):
|
||||
- **Description:** Custom witty phrases to display during loading. When
|
||||
provided, the CLI cycles through these instead of the defaults.
|
||||
- **Default:** `[]`
|
||||
|
||||
- **`ui.accessibility.enableLoadingPhrases`** (boolean):
|
||||
- **Description:** @deprecated Use ui.loadingPhrases instead. Enable loading
|
||||
phrases during operations.
|
||||
- **Description:** Enable loading phrases during operations.
|
||||
- **Default:** `true`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
@@ -652,27 +624,6 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Default:** `{}`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`agents.browser.sessionMode`** (enum):
|
||||
- **Description:** Session mode: 'persistent', 'isolated', or 'existing'.
|
||||
- **Default:** `"persistent"`
|
||||
- **Values:** `"persistent"`, `"isolated"`, `"existing"`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`agents.browser.headless`** (boolean):
|
||||
- **Description:** Run browser in headless mode.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`agents.browser.profilePath`** (string):
|
||||
- **Description:** Path to browser profile directory for session persistence.
|
||||
- **Default:** `undefined`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`agents.browser.visualModel`** (string):
|
||||
- **Description:** Model override for the visual agent.
|
||||
- **Default:** `undefined`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
#### `context`
|
||||
|
||||
- **`context.fileName`** (string | string[]):
|
||||
@@ -900,14 +851,6 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Default:** `undefined`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`security.enableConseca`** (boolean):
|
||||
- **Description:** Enable the context-aware security checker. This feature
|
||||
uses an LLM to dynamically generate and enforce security policies for tool
|
||||
use based on your prompt, providing an additional layer of protection
|
||||
against unintended actions.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
#### `advanced`
|
||||
|
||||
- **`advanced.autoConfigureMemory`** (boolean):
|
||||
@@ -988,15 +931,8 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`experimental.useOSC52Paste`** (boolean):
|
||||
- **Description:** Use OSC 52 for pasting. This may be more robust than the
|
||||
default system when using remote terminal sessions (if your terminal is
|
||||
configured to allow it).
|
||||
- **Default:** `false`
|
||||
|
||||
- **`experimental.useOSC52Copy`** (boolean):
|
||||
- **Description:** Use OSC 52 for copying. This may be more robust than the
|
||||
default system when using remote terminal sessions (if your terminal is
|
||||
configured to allow it).
|
||||
- **Description:** Use OSC 52 sequence for pasting instead of clipboardy
|
||||
(useful for remote sessions).
|
||||
- **Default:** `false`
|
||||
|
||||
- **`experimental.plan`** (boolean):
|
||||
@@ -1004,33 +940,6 @@ their corresponding top-level category object in your `settings.json` file.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`experimental.modelSteering`** (boolean):
|
||||
- **Description:** Enable model steering (user hints) to guide the model
|
||||
during tool execution.
|
||||
- **Default:** `false`
|
||||
|
||||
- **`experimental.directWebFetch`** (boolean):
|
||||
- **Description:** Enable web fetch behavior that bypasses LLM summarization.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`experimental.gemmaModelRouter.enabled`** (boolean):
|
||||
- **Description:** Enable the Gemma Model Router. Requires a local endpoint
|
||||
serving Gemma via the Gemini API using LiteRT-LM shim.
|
||||
- **Default:** `false`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`experimental.gemmaModelRouter.classifier.host`** (string):
|
||||
- **Description:** The host of the classifier.
|
||||
- **Default:** `"http://localhost:9379"`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
- **`experimental.gemmaModelRouter.classifier.model`** (string):
|
||||
- **Description:** The model to use for the classifier. Only tested on
|
||||
`gemma3-1b-gpu-custom`.
|
||||
- **Default:** `"gemma3-1b-gpu-custom"`
|
||||
- **Requires restart:** Yes
|
||||
|
||||
#### `skills`
|
||||
|
||||
- **`skills.enabled`** (boolean):
|
||||
@@ -1318,11 +1227,6 @@ the `advanced.excludedEnvVars` setting in your `settings.json` file.
|
||||
- Specifies the default Gemini model to use.
|
||||
- Overrides the hardcoded default
|
||||
- Example: `export GEMINI_MODEL="gemini-3-flash-preview"`
|
||||
- **`GEMINI_CLI_IDE_PID`**:
|
||||
- Manually specifies the PID of the IDE process to use for integration. This
|
||||
is useful when running Gemini CLI in a standalone terminal while still
|
||||
wanting to associate it with a specific IDE instance.
|
||||
- Overrides the automatic IDE detection logic.
|
||||
- **`GEMINI_CLI_HOME`**:
|
||||
- Specifies the root directory for Gemini CLI's user-level configuration and
|
||||
storage.
|
||||
@@ -1662,15 +1566,16 @@ conventions and context.
|
||||
about the active instructional context.
|
||||
- **Importing content:** You can modularize your context files by importing
|
||||
other Markdown files using the `@path/to/file.md` syntax. For more details,
|
||||
see the [Memory Import Processor documentation](./memport.md).
|
||||
see the [Memory Import Processor documentation](../reference/memport.md).
|
||||
- **Commands for memory management:**
|
||||
- Use `/memory refresh` to force a re-scan and reload of all context files
|
||||
from all configured locations. This updates the AI's instructional context.
|
||||
- Use `/memory show` to display the combined instructional context currently
|
||||
loaded, allowing you to verify the hierarchy and content being used by the
|
||||
AI.
|
||||
- See the [Commands documentation](./commands.md#memory) for full details on
|
||||
the `/memory` command and its sub-commands (`show` and `refresh`).
|
||||
- See the [Commands documentation](../reference/commands.md#memory) for full
|
||||
details on the `/memory` command and its sub-commands (`show` and
|
||||
`refresh`).
|
||||
|
||||
By understanding and utilizing these configuration layers and the hierarchical
|
||||
nature of context files, you can effectively manage the AI's memory and tailor
|
||||
|
||||
@@ -36,7 +36,7 @@ available combinations.
|
||||
| Delete from the cursor to the start of the line. | `Ctrl + U` |
|
||||
| Clear all text in the input field. | `Ctrl + C` |
|
||||
| Delete the previous word. | `Ctrl + Backspace`<br />`Alt + Backspace`<br />`Ctrl + W` |
|
||||
| Delete the next word. | `Ctrl + Delete`<br />`Alt + Delete`<br />`Alt + D` |
|
||||
| Delete the next word. | `Ctrl + Delete`<br />`Alt + Delete` |
|
||||
| Delete the character to the left. | `Backspace`<br />`Ctrl + H` |
|
||||
| Delete the character to the right. | `Delete`<br />`Ctrl + D` |
|
||||
| Undo the most recent text edit. | `Cmd + Z (no Shift)`<br />`Alt + Z (no Shift)` |
|
||||
@@ -61,7 +61,7 @@ available combinations.
|
||||
| Show the next entry in history. | `Ctrl + N (no Shift)` |
|
||||
| Start reverse search through history. | `Ctrl + R` |
|
||||
| Submit the selected reverse-search match. | `Enter (no Ctrl)` |
|
||||
| Accept a suggestion while reverse searching. | `Tab (no Shift)` |
|
||||
| Accept a suggestion while reverse searching. | `Tab` |
|
||||
| Browse and rewind previous interactions. | `Double Esc` |
|
||||
|
||||
#### Navigation
|
||||
@@ -79,7 +79,7 @@ available combinations.
|
||||
|
||||
| Action | Keys |
|
||||
| --------------------------------------- | -------------------------------------------------- |
|
||||
| Accept the inline suggestion. | `Tab (no Shift)`<br />`Enter (no Ctrl)` |
|
||||
| Accept the inline suggestion. | `Tab`<br />`Enter (no Ctrl)` |
|
||||
| Move to the previous completion option. | `Up Arrow (no Shift)`<br />`Ctrl + P (no Shift)` |
|
||||
| Move to the next completion option. | `Down Arrow (no Shift)`<br />`Ctrl + N (no Shift)` |
|
||||
| Expand an inline suggestion. | `Right Arrow` |
|
||||
@@ -87,12 +87,12 @@ available combinations.
|
||||
|
||||
#### Text Input
|
||||
|
||||
| Action | Keys |
|
||||
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| Submit the current prompt. | `Enter (no Shift, Alt, Ctrl, Cmd)` |
|
||||
| Insert a newline without submitting. | `Ctrl + Enter`<br />`Cmd + Enter`<br />`Alt + Enter`<br />`Shift + Enter`<br />`Ctrl + J` |
|
||||
| Open the current prompt or the plan in an external editor. | `Ctrl + X` |
|
||||
| Paste from the clipboard. | `Ctrl + V`<br />`Cmd + V`<br />`Alt + V` |
|
||||
| Action | Keys |
|
||||
| ---------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| Submit the current prompt. | `Enter (no Shift, Alt, Ctrl, Cmd)` |
|
||||
| Insert a newline without submitting. | `Ctrl + Enter`<br />`Cmd + Enter`<br />`Alt + Enter`<br />`Shift + Enter`<br />`Ctrl + J` |
|
||||
| Open the current prompt in an external editor. | `Ctrl + X` |
|
||||
| Paste from the clipboard. | `Ctrl + V`<br />`Cmd + V`<br />`Alt + V` |
|
||||
|
||||
#### App Controls
|
||||
|
||||
|
||||
@@ -64,11 +64,9 @@ primary conditions are the tool's name and its arguments.
|
||||
|
||||
The `toolName` in the rule must match the name of the tool being called.
|
||||
|
||||
- **Wildcards**: You can use wildcards to match multiple tools.
|
||||
- `*`: Matches **any tool** (built-in or MCP).
|
||||
- `server__*`: Matches any tool from a specific MCP server.
|
||||
- `*__toolName`: Matches a specific tool name across **all** MCP servers.
|
||||
- `*__*`: Matches **any tool from any MCP server**.
|
||||
- **Wildcards**: For Model-hosting-protocol (MCP) servers, you can use a
|
||||
wildcard. A `toolName` of `my-server__*` will match any tool from the
|
||||
`my-server` MCP.
|
||||
|
||||
#### Arguments pattern
|
||||
|
||||
@@ -94,13 +92,11 @@ rule with the highest priority wins**.
|
||||
To provide a clear hierarchy, policies are organized into three tiers. Each tier
|
||||
has a designated number that forms the base of the final priority calculation.
|
||||
|
||||
| Tier | Base | Description |
|
||||
| :-------- | :--- | :------------------------------------------------------------------------- |
|
||||
| Default | 1 | Built-in policies that ship with the Gemini CLI. |
|
||||
| Extension | 2 | Policies defined in extensions. |
|
||||
| Workspace | 3 | Policies defined in the current workspace's configuration directory. |
|
||||
| User | 4 | Custom policies defined by the user. |
|
||||
| Admin | 5 | Policies managed by an administrator (e.g., in an enterprise environment). |
|
||||
| Tier | Base | Description |
|
||||
| :------ | :--- | :------------------------------------------------------------------------- |
|
||||
| Default | 1 | Built-in policies that ship with the Gemini CLI. |
|
||||
| User | 2 | Custom policies defined by the user. |
|
||||
| Admin | 3 | Policies managed by an administrator (e.g., in an enterprise environment). |
|
||||
|
||||
Within a TOML policy file, you assign a priority value from **0 to 999**. The
|
||||
engine transforms this into a final priority using the following formula:
|
||||
@@ -109,17 +105,15 @@ engine transforms this into a final priority using the following formula:
|
||||
|
||||
This system guarantees that:
|
||||
|
||||
- Admin policies always override User, Workspace, and Default policies.
|
||||
- User policies override Workspace and Default policies.
|
||||
- Workspace policies override Default policies.
|
||||
- Admin policies always override User and Default policies.
|
||||
- User policies always override Default policies.
|
||||
- You can still order rules within a single tier with fine-grained control.
|
||||
|
||||
For example:
|
||||
|
||||
- A `priority: 50` rule in a Default policy file becomes `1.050`.
|
||||
- A `priority: 10` rule in a Workspace policy policy file becomes `2.010`.
|
||||
- A `priority: 100` rule in a User policy file becomes `3.100`.
|
||||
- A `priority: 20` rule in an Admin policy file becomes `4.020`.
|
||||
- A `priority: 100` rule in a User policy file becomes `2.100`.
|
||||
- A `priority: 20` rule in an Admin policy file becomes `3.020`.
|
||||
|
||||
### Approval modes
|
||||
|
||||
@@ -147,9 +141,9 @@ A rule matches a tool call if all of its conditions are met:
|
||||
|
||||
1. **Tool name**: The `toolName` in the rule must match the name of the tool
|
||||
being called.
|
||||
- **Wildcards**: You can use wildcards like `*`, `server__*`, or
|
||||
`*__toolName` to match multiple tools. See [Tool Name](#tool-name) for
|
||||
details.
|
||||
- **Wildcards**: For Model-hosting-protocol (MCP) servers, you can use a
|
||||
wildcard. A `toolName` of `my-server__*` will match any tool from the
|
||||
`my-server` MCP.
|
||||
2. **Arguments pattern**: If `argsPattern` is specified, the tool's arguments
|
||||
are converted to a stable JSON string, which is then tested against the
|
||||
provided regular expression. If the arguments don't match the pattern, the
|
||||
@@ -162,11 +156,10 @@ User, and (if configured) Admin directories.
|
||||
|
||||
### Policy locations
|
||||
|
||||
| Tier | Type | Location |
|
||||
| :------------ | :----- | :---------------------------------------- |
|
||||
| **User** | Custom | `~/.gemini/policies/*.toml` |
|
||||
| **Workspace** | Custom | `$WORKSPACE_ROOT/.gemini/policies/*.toml` |
|
||||
| **Admin** | System | _See below (OS specific)_ |
|
||||
| Tier | Type | Location |
|
||||
| :-------- | :----- | :-------------------------- |
|
||||
| **User** | Custom | `~/.gemini/policies/*.toml` |
|
||||
| **Admin** | System | _See below (OS specific)_ |
|
||||
|
||||
#### System-wide policies (Admin)
|
||||
|
||||
@@ -206,10 +199,6 @@ toolName = "run_shell_command"
|
||||
# to form a composite name like "mcpName__toolName".
|
||||
mcpName = "my-custom-server"
|
||||
|
||||
# (Optional) Metadata hints provided by the tool. A rule matches if all
|
||||
# key-value pairs provided here are present in the tool's annotations.
|
||||
toolAnnotations = { readOnlyHint = true }
|
||||
|
||||
# (Optional) A regex to match against the tool's arguments.
|
||||
argsPattern = '"command":"(git|npm)'
|
||||
|
||||
@@ -279,12 +268,13 @@ priority = 100
|
||||
|
||||
### Special syntax for MCP tools
|
||||
|
||||
You can create rules that target tools from Model Context Protocol (MCP) servers
|
||||
using the `mcpName` field or composite wildcard patterns.
|
||||
You can create rules that target tools from Model-hosting-protocol (MCP) servers
|
||||
using the `mcpName` field or a wildcard pattern.
|
||||
|
||||
**1. Targeting a specific tool on a server**
|
||||
**1. Using `mcpName`**
|
||||
|
||||
Combine `mcpName` and `toolName` to target a single operation.
|
||||
To target a specific tool from a specific server, combine `mcpName` and
|
||||
`toolName`.
|
||||
|
||||
```toml
|
||||
# Allows the `search` tool on the `my-jira-server` MCP
|
||||
@@ -295,10 +285,10 @@ decision = "allow"
|
||||
priority = 200
|
||||
```
|
||||
|
||||
**2. Targeting all tools on a specific server**
|
||||
**2. Using a wildcard**
|
||||
|
||||
Specify only the `mcpName` to apply a rule to every tool provided by that
|
||||
server.
|
||||
To create a rule that applies to _all_ tools on a specific MCP server, specify
|
||||
only the `mcpName`.
|
||||
|
||||
```toml
|
||||
# Denies all tools from the `untrusted-server` MCP
|
||||
@@ -309,33 +299,6 @@ priority = 500
|
||||
deny_message = "This server is not trusted by the admin."
|
||||
```
|
||||
|
||||
**3. Targeting all MCP servers**
|
||||
|
||||
Use `mcpName = "*"` to create a rule that applies to **all** tools from **any**
|
||||
registered MCP server. This is useful for setting category-wide defaults.
|
||||
|
||||
```toml
|
||||
# Ask user for any tool call from any MCP server
|
||||
[[rule]]
|
||||
mcpName = "*"
|
||||
decision = "ask_user"
|
||||
priority = 10
|
||||
```
|
||||
|
||||
**4. Targeting a tool name across all servers**
|
||||
|
||||
Use `mcpName = "*"` with a specific `toolName` to target that operation
|
||||
regardless of which server provides it.
|
||||
|
||||
```toml
|
||||
# Allow the `search` tool across all connected MCP servers
|
||||
[[rule]]
|
||||
mcpName = "*"
|
||||
toolName = "search"
|
||||
decision = "allow"
|
||||
priority = 50
|
||||
```
|
||||
|
||||
## Default policies
|
||||
|
||||
The Gemini CLI ships with a set of default policies to provide a safe
|
||||
|
||||
@@ -5,15 +5,6 @@ problems encountered while using Gemini CLI.
|
||||
|
||||
## General issues
|
||||
|
||||
### Why can't I use third-party software (e.g. Claude Code, OpenClaw, OpenCode) with Gemini CLI?
|
||||
|
||||
Using third-party software, tools, or services to access Gemini CLI is a
|
||||
violation of our [applicable terms and policies](tos-privacy.md), and severely
|
||||
degrades the experience for legitimate product users. Such actions may be
|
||||
grounds for suspension or termination of your account. If you would like to use
|
||||
a third-party coding agent with Gemini, we recommend using a Vertex or AI Studio
|
||||
API key.
|
||||
|
||||
### Why am I getting an `API error: 429 - Resource exhausted`?
|
||||
|
||||
This error indicates that you have exceeded your API request limit. The Gemini
|
||||
|
||||
@@ -135,18 +135,6 @@ Flow video editor). These plans do not apply to the API usage which powers the
|
||||
Gemini CLI. Supporting these plans is under active consideration for future
|
||||
support.
|
||||
|
||||
## Check usage and quota
|
||||
|
||||
You can check your current token usage and quota information using the
|
||||
`/stats model` command. This command provides a snapshot of your current
|
||||
session's token usage, as well as your overall quota and usage for the supported
|
||||
models.
|
||||
|
||||
For more information on the `/stats` command and its subcommands, see the
|
||||
[Command Reference](../../reference/commands.md#stats).
|
||||
|
||||
A summary of model usage is also presented on exit at the end of a session.
|
||||
|
||||
## Tips to avoid high costs
|
||||
|
||||
When using a Pay as you Go API key, be mindful of your usage to avoid unexpected
|
||||
@@ -163,3 +151,8 @@ costs.
|
||||
models directly.
|
||||
- Vertex AI: This is the enterprise-grade platform for building, deploying, and
|
||||
managing Gemini models with specific security and control requirements.
|
||||
|
||||
## Understanding your usage
|
||||
|
||||
A summary of model usage is available through the `/stats` command and presented
|
||||
on exit at the end of a session.
|
||||
|
||||
@@ -7,12 +7,6 @@ is licensed under the
|
||||
When you use Gemini CLI to access or use Google’s services, the Terms of Service
|
||||
and Privacy Notices applicable to those services apply to such access and use.
|
||||
|
||||
Directly accessing the services powering Gemini CLI (e.g., the Gemini Code
|
||||
Assist service) using third-party software, tools, or services (for example,
|
||||
using OpenClaw with Gemini CLI OAuth) is a violation of applicable terms and
|
||||
policies. Such actions may be grounds for suspension or termination of your
|
||||
account.
|
||||
|
||||
Your Gemini CLI Usage Statistics are handled in accordance with Google's Privacy
|
||||
Policy.
|
||||
|
||||
|
||||
@@ -19,7 +19,16 @@ can find your npm cache path by running `npm config get cache`.
|
||||
rm -rf "$(npm config get cache)/_npx"
|
||||
```
|
||||
|
||||
**For Windows (PowerShell)**
|
||||
**For Windows**
|
||||
|
||||
_Command Prompt_
|
||||
|
||||
```cmd
|
||||
:: The path is typically %LocalAppData%\npm-cache\_npx
|
||||
rmdir /s /q "%LocalAppData%\npm-cache\_npx"
|
||||
```
|
||||
|
||||
_PowerShell_
|
||||
|
||||
```powershell
|
||||
# The path is typically $env:LocalAppData\npm-cache\_npx
|
||||
|
||||
+44
-47
@@ -27,10 +27,6 @@
|
||||
"label": "File management",
|
||||
"slug": "docs/cli/tutorials/file-management"
|
||||
},
|
||||
{
|
||||
"label": "Get started with Agent skills",
|
||||
"slug": "docs/cli/tutorials/skills-getting-started"
|
||||
},
|
||||
{
|
||||
"label": "Manage context and memory",
|
||||
"slug": "docs/cli/tutorials/memory-management"
|
||||
@@ -51,6 +47,10 @@
|
||||
"label": "Web search and fetch",
|
||||
"slug": "docs/cli/tutorials/web-tools"
|
||||
},
|
||||
{
|
||||
"label": "Get started with skills",
|
||||
"slug": "docs/cli/tutorials/skills-getting-started"
|
||||
},
|
||||
{
|
||||
"label": "Set up an MCP server",
|
||||
"slug": "docs/cli/tutorials/mcp-setup"
|
||||
@@ -61,55 +61,23 @@
|
||||
{
|
||||
"label": "Features",
|
||||
"items": [
|
||||
{ "label": "Agent Skills", "slug": "docs/cli/skills" },
|
||||
{
|
||||
"label": "Authentication",
|
||||
"slug": "docs/get-started/authentication"
|
||||
},
|
||||
{ "label": "Checkpointing", "slug": "docs/cli/checkpointing" },
|
||||
{
|
||||
"label": "Extensions",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{
|
||||
"label": "Overview",
|
||||
"slug": "docs/extensions"
|
||||
},
|
||||
{
|
||||
"label": "User guide: Install and manage",
|
||||
"link": "/docs/extensions/#manage-extensions"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Build extensions",
|
||||
"slug": "docs/extensions/writing-extensions"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Best practices",
|
||||
"slug": "docs/extensions/best-practices"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Releasing",
|
||||
"slug": "docs/extensions/releasing"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Reference",
|
||||
"slug": "docs/extensions/reference"
|
||||
}
|
||||
]
|
||||
"slug": "docs/extensions/index"
|
||||
},
|
||||
{ "label": "Agent Skills", "slug": "docs/cli/skills" },
|
||||
{ "label": "Checkpointing", "slug": "docs/cli/checkpointing" },
|
||||
{ "label": "Headless mode", "slug": "docs/cli/headless" },
|
||||
{ "label": "Hooks", "slug": "docs/hooks" },
|
||||
{ "label": "IDE integration", "slug": "docs/ide-integration" },
|
||||
{ "label": "MCP servers", "slug": "docs/tools/mcp-server" },
|
||||
{ "label": "Model routing", "slug": "docs/cli/model-routing" },
|
||||
{ "label": "Model selection", "slug": "docs/cli/model" },
|
||||
{ "label": "Plan mode", "badge": "🔬", "slug": "docs/cli/plan-mode" },
|
||||
{
|
||||
"label": "Subagents",
|
||||
"badge": "🔬",
|
||||
"slug": "docs/core/subagents"
|
||||
},
|
||||
{
|
||||
"label": "Remote subagents",
|
||||
"badge": "🔬",
|
||||
"slug": "docs/core/remote-agents"
|
||||
},
|
||||
{ "label": "Plan mode (experimental)", "slug": "docs/cli/plan-mode" },
|
||||
{ "label": "Rewind", "slug": "docs/cli/rewind" },
|
||||
{ "label": "Sandboxing", "slug": "docs/cli/sandbox" },
|
||||
{ "label": "Settings", "slug": "docs/cli/settings" },
|
||||
@@ -146,6 +114,35 @@
|
||||
{ "label": "Trusted folders", "slug": "docs/cli/trusted-folders" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Extensions",
|
||||
"items": [
|
||||
{
|
||||
"label": "Overview",
|
||||
"slug": "docs/extensions"
|
||||
},
|
||||
{
|
||||
"label": "User guide: Install and manage",
|
||||
"link": "/docs/extensions/#manage-extensions"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Build extensions",
|
||||
"slug": "docs/extensions/writing-extensions"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Best practices",
|
||||
"slug": "docs/extensions/best-practices"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Releasing",
|
||||
"slug": "docs/extensions/releasing"
|
||||
},
|
||||
{
|
||||
"label": "Developer guide: Reference",
|
||||
"slug": "docs/extensions/reference"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Development",
|
||||
"items": [
|
||||
@@ -192,7 +189,6 @@
|
||||
{
|
||||
"label": "Resources",
|
||||
"items": [
|
||||
{ "label": "FAQ", "slug": "docs/resources/faq" },
|
||||
{
|
||||
"label": "Quota and pricing",
|
||||
"slug": "docs/resources/quota-and-pricing"
|
||||
@@ -201,6 +197,7 @@
|
||||
"label": "Terms and privacy",
|
||||
"slug": "docs/resources/tos-privacy"
|
||||
},
|
||||
{ "label": "FAQ", "slug": "docs/resources/faq" },
|
||||
{
|
||||
"label": "Troubleshooting",
|
||||
"slug": "docs/resources/troubleshooting"
|
||||
@@ -211,10 +208,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "releases_tab",
|
||||
"label": "changelog_tab",
|
||||
"items": [
|
||||
{
|
||||
"label": "Releases",
|
||||
"label": "Changelog",
|
||||
"items": [
|
||||
{ "label": "Release notes", "slug": "docs/changelogs/" },
|
||||
{ "label": "Stable release", "slug": "docs/changelogs/latest" },
|
||||
|
||||
@@ -105,11 +105,10 @@ lines containing matches, along with their file paths and line numbers.
|
||||
|
||||
## 6. `replace` (Edit)
|
||||
|
||||
`replace` replaces text within a file. By default, the tool expects to find and
|
||||
replace exactly ONE occurrence of `old_string`. If you want to replace multiple
|
||||
occurrences of the exact same string, set `allow_multiple` to `true`. This tool
|
||||
is designed for precise, targeted changes and requires significant context
|
||||
around the `old_string` to ensure it modifies the correct location.
|
||||
`replace` replaces text within a file. By default, replaces a single occurrence,
|
||||
but can replace multiple occurrences when `expected_replacements` is specified.
|
||||
This tool is designed for precise, targeted changes and requires significant
|
||||
context around the `old_string` to ensure it modifies the correct location.
|
||||
|
||||
- **Tool name:** `replace`
|
||||
- **Arguments:**
|
||||
@@ -117,8 +116,6 @@ around the `old_string` to ensure it modifies the correct location.
|
||||
- `instruction` (string, required): Semantic description of the change.
|
||||
- `old_string` (string, required): Exact literal text to find.
|
||||
- `new_string` (string, required): Exact literal text to replace with.
|
||||
- `allow_multiple` (boolean, optional): If `true`, replaces all occurrences.
|
||||
If `false` (default), only succeeds if exactly one occurrence is found.
|
||||
- **Confirmation:** Requires manual user approval.
|
||||
|
||||
## Next steps
|
||||
|
||||
@@ -52,9 +52,6 @@ These tools help the model manage its plan and interact with you.
|
||||
complex plans.
|
||||
- **[Agent Skills](../cli/skills.md) (`activate_skill`):** Loads specialized
|
||||
procedural expertise when needed.
|
||||
- **[Browser agent](../core/subagents.md#browser-agent-experimental)
|
||||
(`browser_agent`):** Automates web browser tasks through the accessibility
|
||||
tree.
|
||||
- **Internal docs (`get_internal_docs`):** Accesses Gemini CLI's own
|
||||
documentation to help answer your questions.
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ provides direct access to the Markdown files in the `docs/` directory.
|
||||
`get_internal_docs` takes one optional argument:
|
||||
|
||||
- `path` (string, optional): The relative path to a specific documentation file
|
||||
(for example, `reference/commands.md`). If omitted, the tool returns a list of
|
||||
all available documentation paths.
|
||||
(for example, `cli/commands.md`). If omitted, the tool returns a list of all
|
||||
available documentation paths.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -163,8 +163,7 @@ Each server configuration supports the following properties:
|
||||
- **`args`** (string[]): Command-line arguments for Stdio transport
|
||||
- **`headers`** (object): Custom HTTP headers when using `url` or `httpUrl`
|
||||
- **`env`** (object): Environment variables for the server process. Values can
|
||||
reference environment variables using `$VAR_NAME` or `${VAR_NAME}` syntax (all
|
||||
platforms), or `%VAR_NAME%` (Windows only).
|
||||
reference environment variables using `$VAR_NAME` or `${VAR_NAME}` syntax
|
||||
- **`cwd`** (string): Working directory for Stdio transport
|
||||
- **`timeout`** (number): Request timeout in milliseconds (default: 600,000ms =
|
||||
10 minutes)
|
||||
@@ -185,63 +184,6 @@ Each server configuration supports the following properties:
|
||||
Service Account to impersonate. Used with
|
||||
`authProviderType: 'service_account_impersonation'`.
|
||||
|
||||
### Environment variable expansion
|
||||
|
||||
Gemini CLI automatically expands environment variables in the `env` block of
|
||||
your MCP server configuration. This allows you to securely reference variables
|
||||
defined in your shell or environment without hardcoding sensitive information
|
||||
directly in your `settings.json` file.
|
||||
|
||||
The expansion utility supports:
|
||||
|
||||
- **POSIX/Bash syntax:** `$VARIABLE_NAME` or `${VARIABLE_NAME}` (supported on
|
||||
all platforms)
|
||||
- **Windows syntax:** `%VARIABLE_NAME%` (supported only when running on Windows)
|
||||
|
||||
If a variable is not defined in the current environment, it resolves to an empty
|
||||
string.
|
||||
|
||||
**Example:**
|
||||
|
||||
```json
|
||||
"env": {
|
||||
"API_KEY": "$MY_EXTERNAL_TOKEN",
|
||||
"LOG_LEVEL": "$LOG_LEVEL",
|
||||
"TEMP_DIR": "%TEMP%"
|
||||
}
|
||||
```
|
||||
|
||||
### Security and environment sanitization
|
||||
|
||||
To protect your credentials, Gemini CLI performs environment sanitization when
|
||||
spawning MCP server processes.
|
||||
|
||||
#### Automatic redaction
|
||||
|
||||
By default, the CLI redacts sensitive environment variables from the base
|
||||
environment (inherited from the host process) to prevent unintended exposure to
|
||||
third-party MCP servers. This includes:
|
||||
|
||||
- Core project keys: `GEMINI_API_KEY`, `GOOGLE_API_KEY`, etc.
|
||||
- Variables matching sensitive patterns: `*TOKEN*`, `*SECRET*`, `*PASSWORD*`,
|
||||
`*KEY*`, `*AUTH*`, `*CREDENTIAL*`.
|
||||
- Certificates and private key patterns.
|
||||
|
||||
#### Explicit overrides
|
||||
|
||||
If an environment variable must be passed to an MCP server, you must explicitly
|
||||
state it in the `env` property of the server configuration in `settings.json`.
|
||||
Explicitly defined variables (including those from extensions) are trusted and
|
||||
are **not** subjected to the automatic redaction process.
|
||||
|
||||
This follows the security principle that if a variable is explicitly configured
|
||||
by the user for a specific server, it constitutes informed consent to share that
|
||||
specific data with that server.
|
||||
|
||||
> **Note:** Even when explicitly defined, you should avoid hardcoding secrets.
|
||||
> Instead, use environment variable expansion (e.g., `"MY_KEY": "$MY_KEY"`) to
|
||||
> securely pull the value from your host environment at runtime.
|
||||
|
||||
### OAuth support for remote MCP servers
|
||||
|
||||
The Gemini CLI supports OAuth 2.0 authentication for remote MCP servers using
|
||||
@@ -796,9 +738,7 @@ The MCP integration tracks several states:
|
||||
- **Trust settings:** The `trust` option bypasses all confirmation dialogs. Use
|
||||
cautiously and only for servers you completely control
|
||||
- **Access tokens:** Be security-aware when configuring environment variables
|
||||
containing API keys or tokens. See
|
||||
[Security and environment sanitization](#security-and-environment-sanitization)
|
||||
for details on how Gemini CLI protects your credentials.
|
||||
containing API keys or tokens
|
||||
- **Sandbox compatibility:** When using sandboxing, ensure MCP servers are
|
||||
available within the sandbox environment
|
||||
- **Private data:** Using broadly scoped personal access tokens can lead to
|
||||
|
||||
@@ -11,8 +11,6 @@ by the agent when you ask it to "start a plan" using natural language. In this
|
||||
mode, the agent is restricted to read-only tools to allow for safe exploration
|
||||
and planning.
|
||||
|
||||
> **Note:** This tool is not available when the CLI is in YOLO mode.
|
||||
|
||||
- **Tool name:** `enter_plan_mode`
|
||||
- **Display name:** Enter Plan Mode
|
||||
- **File:** `enter-plan-mode.ts`
|
||||
|
||||
+3
-9
@@ -63,7 +63,7 @@ const external = [
|
||||
'@lydell/node-pty-win32-arm64',
|
||||
'@lydell/node-pty-win32-x64',
|
||||
'keytar',
|
||||
'@google/gemini-cli-devtools',
|
||||
'gemini-cli-devtools',
|
||||
];
|
||||
|
||||
const baseConfig = {
|
||||
@@ -75,14 +75,10 @@ const baseConfig = {
|
||||
write: true,
|
||||
};
|
||||
|
||||
const commonAliases = {
|
||||
punycode: 'punycode/',
|
||||
};
|
||||
|
||||
const cliConfig = {
|
||||
...baseConfig,
|
||||
banner: {
|
||||
js: `const require = (await import('node:module')).createRequire(import.meta.url); globalThis.__filename = (await import('node:url')).fileURLToPath(import.meta.url); globalThis.__dirname = (await import('node:path')).dirname(globalThis.__filename);`,
|
||||
js: `import { createRequire } from 'module'; const require = createRequire(import.meta.url); globalThis.__filename = require('url').fileURLToPath(import.meta.url); globalThis.__dirname = require('path').dirname(globalThis.__filename);`,
|
||||
},
|
||||
entryPoints: ['packages/cli/index.ts'],
|
||||
outfile: 'bundle/gemini.js',
|
||||
@@ -92,7 +88,6 @@ const cliConfig = {
|
||||
plugins: createWasmPlugins(),
|
||||
alias: {
|
||||
'is-in-ci': path.resolve(__dirname, 'packages/cli/src/patches/is-in-ci.ts'),
|
||||
...commonAliases,
|
||||
},
|
||||
metafile: true,
|
||||
};
|
||||
@@ -100,7 +95,7 @@ const cliConfig = {
|
||||
const a2aServerConfig = {
|
||||
...baseConfig,
|
||||
banner: {
|
||||
js: `const require = (await import('node:module')).createRequire(import.meta.url); globalThis.__filename = (await import('node:url')).fileURLToPath(import.meta.url); globalThis.__dirname = (await import('node:path')).dirname(globalThis.__filename);`,
|
||||
js: `const require = (await import('module')).createRequire(import.meta.url); globalThis.__filename = require('url').fileURLToPath(import.meta.url); globalThis.__dirname = require('path').dirname(globalThis.__filename);`,
|
||||
},
|
||||
entryPoints: ['packages/a2a-server/src/http/server.ts'],
|
||||
outfile: 'packages/a2a-server/dist/a2a-server.mjs',
|
||||
@@ -108,7 +103,6 @@ const a2aServerConfig = {
|
||||
'process.env.CLI_VERSION': JSON.stringify(pkg.version),
|
||||
},
|
||||
plugins: createWasmPlugins(),
|
||||
alias: commonAliases,
|
||||
};
|
||||
|
||||
Promise.allSettled([
|
||||
|
||||
+12
-5
@@ -38,7 +38,6 @@ export default tseslint.config(
|
||||
'dist/**',
|
||||
'evals/**',
|
||||
'packages/test-utils/**',
|
||||
'.gemini/skills/**',
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
@@ -56,7 +55,7 @@ export default tseslint.config(
|
||||
},
|
||||
{
|
||||
// Import specific config
|
||||
files: ['packages/*/src/**/*.{ts,tsx}'], // Target all TS/TSX in the packages
|
||||
files: ['packages/cli/src/**/*.{ts,tsx}'], // Target only TS/TSX in the cli package
|
||||
plugins: {
|
||||
import: importPlugin,
|
||||
},
|
||||
@@ -128,7 +127,17 @@ export default tseslint.config(
|
||||
],
|
||||
// Prevent async errors from bypassing catch handlers
|
||||
'@typescript-eslint/return-await': ['error', 'in-try-catch'],
|
||||
'import/no-internal-modules': 'off',
|
||||
'import/no-internal-modules': [
|
||||
'error',
|
||||
{
|
||||
allow: [
|
||||
'react-dom/test-utils',
|
||||
'memfs/lib/volume.js',
|
||||
'yargs/**',
|
||||
'msw/node',
|
||||
],
|
||||
},
|
||||
],
|
||||
'import/no-relative-packages': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-debugger': 'error',
|
||||
@@ -190,8 +199,6 @@ export default tseslint.config(
|
||||
ignores: ['**/*.test.ts', '**/*.test.tsx'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unsafe-type-assertion': 'error',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'error',
|
||||
'@typescript-eslint/no-unsafe-return': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
+12
-13
@@ -78,23 +78,22 @@ describe('Frugal reads eval', () => {
|
||||
).toBe(true);
|
||||
|
||||
let totalLinesRead = 0;
|
||||
const readRanges: { start_line: number; end_line: number }[] = [];
|
||||
const readRanges: { offset: number; limit: number }[] = [];
|
||||
|
||||
for (const call of targetFileReads) {
|
||||
const args = JSON.parse(call.toolRequest.args);
|
||||
|
||||
expect(
|
||||
args.end_line,
|
||||
'Agent read the entire file (missing end_line) instead of using ranged read',
|
||||
args.limit,
|
||||
'Agent read the entire file (missing limit) instead of using ranged read',
|
||||
).toBeDefined();
|
||||
|
||||
const end_line = args.end_line;
|
||||
const start_line = args.start_line ?? 1;
|
||||
const linesRead = end_line - start_line + 1;
|
||||
totalLinesRead += linesRead;
|
||||
readRanges.push({ start_line, end_line });
|
||||
const limit = args.limit;
|
||||
const offset = args.offset ?? 0;
|
||||
totalLinesRead += limit;
|
||||
readRanges.push({ offset, limit });
|
||||
|
||||
expect(linesRead, 'Agent read too many lines at once').toBeLessThan(
|
||||
expect(args.limit, 'Agent read too many lines at once').toBeLessThan(
|
||||
1001,
|
||||
);
|
||||
}
|
||||
@@ -109,7 +108,7 @@ describe('Frugal reads eval', () => {
|
||||
const errorLines = [500, 510, 520];
|
||||
for (const line of errorLines) {
|
||||
const covered = readRanges.some(
|
||||
(range) => line >= range.start_line && line <= range.end_line,
|
||||
(range) => line >= range.offset && line < range.offset + range.limit,
|
||||
);
|
||||
expect(covered, `Agent should have read around line ${line}`).toBe(
|
||||
true,
|
||||
@@ -192,8 +191,8 @@ describe('Frugal reads eval', () => {
|
||||
for (const call of targetFileReads) {
|
||||
const args = JSON.parse(call.toolRequest.args);
|
||||
expect(
|
||||
args.end_line,
|
||||
'Agent should have used ranged read (end_line) to save tokens',
|
||||
args.limit,
|
||||
'Agent should have used ranged read (limit) to save tokens',
|
||||
).toBeDefined();
|
||||
}
|
||||
},
|
||||
@@ -254,7 +253,7 @@ describe('Frugal reads eval', () => {
|
||||
// and just read the whole file to be efficient with tool calls.
|
||||
const readEntireFile = targetFileReads.some((call) => {
|
||||
const args = JSON.parse(call.toolRequest.args);
|
||||
return args.end_line === undefined;
|
||||
return args.limit === undefined;
|
||||
});
|
||||
|
||||
expect(
|
||||
|
||||
@@ -68,7 +68,7 @@ describe('Frugal Search', () => {
|
||||
const args = getParams(call);
|
||||
return (
|
||||
args.file_path === 'src/legacy_processor.ts' &&
|
||||
(args.end_line === undefined || args.end_line === null)
|
||||
(args.limit === undefined || args.limit === null)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('Frugal Search', () => {
|
||||
if (
|
||||
call.toolRequest.name === 'read_file' &&
|
||||
args.file_path === 'src/legacy_processor.ts' &&
|
||||
args.end_line !== undefined
|
||||
args.limit !== undefined
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect } from 'vitest';
|
||||
import { appEvalTest } from './app-test-helper.js';
|
||||
|
||||
describe('generalist_delegation', () => {
|
||||
// --- Positive Evals (Should Delegate) ---
|
||||
|
||||
appEvalTest('USUALLY_PASSES', {
|
||||
name: 'should delegate batch error fixing to generalist agent',
|
||||
configOverrides: {
|
||||
agents: {
|
||||
overrides: {
|
||||
generalist: { enabled: true },
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
enableAgents: true,
|
||||
},
|
||||
excludeTools: ['run_shell_command'],
|
||||
},
|
||||
files: {
|
||||
'file1.ts': 'console.log("no semi")',
|
||||
'file2.ts': 'console.log("no semi")',
|
||||
'file3.ts': 'console.log("no semi")',
|
||||
'file4.ts': 'console.log("no semi")',
|
||||
'file5.ts': 'console.log("no semi")',
|
||||
'file6.ts': 'console.log("no semi")',
|
||||
'file7.ts': 'console.log("no semi")',
|
||||
'file8.ts': 'console.log("no semi")',
|
||||
'file9.ts': 'console.log("no semi")',
|
||||
'file10.ts': 'console.log("no semi")',
|
||||
},
|
||||
prompt:
|
||||
'I have 10 files (file1.ts to file10.ts) that are missing semicolons. Can you fix them?',
|
||||
setup: async (rig) => {
|
||||
rig.setBreakpoint(['generalist']);
|
||||
},
|
||||
assert: async (rig) => {
|
||||
const confirmation = await rig.waitForPendingConfirmation(
|
||||
'generalist',
|
||||
60000,
|
||||
);
|
||||
expect(
|
||||
confirmation,
|
||||
'Expected a tool call for generalist agent',
|
||||
).toBeTruthy();
|
||||
await rig.resolveTool(confirmation);
|
||||
await rig.waitForIdle(60000);
|
||||
},
|
||||
});
|
||||
|
||||
appEvalTest('USUALLY_PASSES', {
|
||||
name: 'should autonomously delegate complex batch task to generalist agent',
|
||||
configOverrides: {
|
||||
agents: {
|
||||
overrides: {
|
||||
generalist: { enabled: true },
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
enableAgents: true,
|
||||
},
|
||||
excludeTools: ['run_shell_command'],
|
||||
},
|
||||
files: {
|
||||
'src/a.ts': 'export const a = 1;',
|
||||
'src/b.ts': 'export const b = 2;',
|
||||
'src/c.ts': 'export const c = 3;',
|
||||
'src/d.ts': 'export const d = 4;',
|
||||
'src/e.ts': 'export const e = 5;',
|
||||
},
|
||||
prompt:
|
||||
'Please update all files in the src directory. For each file, add a comment at the top that says "Processed by Gemini".',
|
||||
setup: async (rig) => {
|
||||
rig.setBreakpoint(['generalist']);
|
||||
},
|
||||
assert: async (rig) => {
|
||||
const confirmation = await rig.waitForPendingConfirmation(
|
||||
'generalist',
|
||||
60000,
|
||||
);
|
||||
expect(
|
||||
confirmation,
|
||||
'Expected autonomously delegate to generalist for batch task',
|
||||
).toBeTruthy();
|
||||
await rig.resolveTool(confirmation);
|
||||
await rig.waitForIdle(60000);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Negative Evals (Should NOT Delegate - Assertive Handling) ---
|
||||
|
||||
appEvalTest('USUALLY_PASSES', {
|
||||
name: 'should NOT delegate simple read and fix to generalist agent',
|
||||
configOverrides: {
|
||||
agents: {
|
||||
overrides: {
|
||||
generalist: { enabled: true },
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
enableAgents: true,
|
||||
},
|
||||
excludeTools: ['run_shell_command'],
|
||||
},
|
||||
files: {
|
||||
'README.md': 'This is a proyect.',
|
||||
},
|
||||
prompt:
|
||||
'There is a typo in README.md ("proyect"). Please fix it to "project".',
|
||||
setup: async (rig) => {
|
||||
// Break on everything to see what it calls
|
||||
rig.setBreakpoint(['*']);
|
||||
},
|
||||
assert: async (rig) => {
|
||||
await rig.drainBreakpointsUntilIdle((confirmation) => {
|
||||
expect(
|
||||
confirmation.toolName,
|
||||
`Agent should NOT have delegated to generalist.`,
|
||||
).not.toBe('generalist');
|
||||
});
|
||||
|
||||
const output = rig.getStaticOutput();
|
||||
expect(output).toMatch(/project/i);
|
||||
},
|
||||
});
|
||||
|
||||
appEvalTest('USUALLY_PASSES', {
|
||||
name: 'should NOT delegate simple direct question to generalist agent',
|
||||
configOverrides: {
|
||||
agents: {
|
||||
overrides: {
|
||||
generalist: { enabled: true },
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
enableAgents: true,
|
||||
},
|
||||
excludeTools: ['run_shell_command'],
|
||||
},
|
||||
files: {
|
||||
'src/VERSION': '1.2.3',
|
||||
},
|
||||
prompt: 'Can you tell me the version number in the src folder?',
|
||||
setup: async (rig) => {
|
||||
rig.setBreakpoint(['*']);
|
||||
},
|
||||
assert: async (rig) => {
|
||||
await rig.drainBreakpointsUntilIdle((confirmation) => {
|
||||
expect(
|
||||
confirmation.toolName,
|
||||
`Agent should NOT have delegated to generalist.`,
|
||||
).not.toBe('generalist');
|
||||
});
|
||||
|
||||
const output = rig.getStaticOutput();
|
||||
expect(output).toMatch(/1\.2\.3/);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -1,170 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 202 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect } from 'vitest';
|
||||
import { evalTest, TestRig } from './test-helper.js';
|
||||
import {
|
||||
assertModelHasOutput,
|
||||
checkModelOutputContent,
|
||||
} from './test-helper.js';
|
||||
|
||||
describe('grep_search_functionality', () => {
|
||||
const TEST_PREFIX = 'Grep Search Functionality: ';
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should find a simple string in a file',
|
||||
files: {
|
||||
'test.txt': `hello
|
||||
world
|
||||
hello world`,
|
||||
},
|
||||
prompt: 'Find "world" in test.txt',
|
||||
assert: async (rig: TestRig, result: string) => {
|
||||
await rig.waitForToolCall('grep_search');
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/L2: world/, /L3: hello world/],
|
||||
testName: `${TEST_PREFIX}simple search`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should perform a case-sensitive search',
|
||||
files: {
|
||||
'test.txt': `Hello
|
||||
hello`,
|
||||
},
|
||||
prompt: 'Find "Hello" in test.txt, case-sensitively.',
|
||||
assert: async (rig: TestRig, result: string) => {
|
||||
const wasToolCalled = await rig.waitForToolCall(
|
||||
'grep_search',
|
||||
undefined,
|
||||
(args) => {
|
||||
const params = JSON.parse(args);
|
||||
return params.case_sensitive === true;
|
||||
},
|
||||
);
|
||||
expect(
|
||||
wasToolCalled,
|
||||
'Expected grep_search to be called with case_sensitive: true',
|
||||
).toBe(true);
|
||||
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/L1: Hello/],
|
||||
forbiddenContent: [/L2: hello/],
|
||||
testName: `${TEST_PREFIX}case-sensitive search`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should return only file names when names_only is used',
|
||||
files: {
|
||||
'file1.txt': 'match me',
|
||||
'file2.txt': 'match me',
|
||||
},
|
||||
prompt: 'Find the files containing "match me".',
|
||||
assert: async (rig: TestRig, result: string) => {
|
||||
const wasToolCalled = await rig.waitForToolCall(
|
||||
'grep_search',
|
||||
undefined,
|
||||
(args) => {
|
||||
const params = JSON.parse(args);
|
||||
return params.names_only === true;
|
||||
},
|
||||
);
|
||||
expect(
|
||||
wasToolCalled,
|
||||
'Expected grep_search to be called with names_only: true',
|
||||
).toBe(true);
|
||||
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/file1.txt/, /file2.txt/],
|
||||
forbiddenContent: [/L1:/],
|
||||
testName: `${TEST_PREFIX}names_only search`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should search only within the specified include_pattern glob',
|
||||
files: {
|
||||
'file.js': 'my_function();',
|
||||
'file.ts': 'my_function();',
|
||||
},
|
||||
prompt: 'Find "my_function" in .js files.',
|
||||
assert: async (rig: TestRig, result: string) => {
|
||||
const wasToolCalled = await rig.waitForToolCall(
|
||||
'grep_search',
|
||||
undefined,
|
||||
(args) => {
|
||||
const params = JSON.parse(args);
|
||||
return params.include_pattern === '*.js';
|
||||
},
|
||||
);
|
||||
expect(
|
||||
wasToolCalled,
|
||||
'Expected grep_search to be called with include_pattern: "*.js"',
|
||||
).toBe(true);
|
||||
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/file.js/],
|
||||
forbiddenContent: [/file.ts/],
|
||||
testName: `${TEST_PREFIX}include_pattern glob search`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should search within a specific subdirectory',
|
||||
files: {
|
||||
'src/main.js': 'unique_string_1',
|
||||
'lib/main.js': 'unique_string_2',
|
||||
},
|
||||
prompt: 'Find "unique_string" in the src directory.',
|
||||
assert: async (rig: TestRig, result: string) => {
|
||||
const wasToolCalled = await rig.waitForToolCall(
|
||||
'grep_search',
|
||||
undefined,
|
||||
(args) => {
|
||||
const params = JSON.parse(args);
|
||||
return params.dir_path === 'src';
|
||||
},
|
||||
);
|
||||
expect(
|
||||
wasToolCalled,
|
||||
'Expected grep_search to be called with dir_path: "src"',
|
||||
).toBe(true);
|
||||
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/unique_string_1/],
|
||||
forbiddenContent: [/unique_string_2/],
|
||||
testName: `${TEST_PREFIX}subdirectory search`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should report no matches correctly',
|
||||
files: {
|
||||
'file.txt': 'nothing to see here',
|
||||
},
|
||||
prompt: 'Find "nonexistent" in file.txt',
|
||||
assert: async (rig: TestRig, result: string) => {
|
||||
await rig.waitForToolCall('grep_search');
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/No matches found/],
|
||||
testName: `${TEST_PREFIX}no matches`,
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -6,12 +6,17 @@
|
||||
|
||||
import { describe, expect } from 'vitest';
|
||||
import { evalTest } from './test-helper.js';
|
||||
import { assertModelHasOutput } from '../integration-tests/test-helper.js';
|
||||
import {
|
||||
assertModelHasOutput,
|
||||
checkModelOutputContent,
|
||||
} from '../integration-tests/test-helper.js';
|
||||
|
||||
describe('Hierarchical Memory', () => {
|
||||
const TEST_PREFIX = 'Hierarchical memory test: ';
|
||||
|
||||
const conflictResolutionTest =
|
||||
'Agent follows hierarchy for contradictory instructions';
|
||||
evalTest('USUALLY_PASSES', {
|
||||
evalTest('ALWAYS_PASSES', {
|
||||
name: conflictResolutionTest,
|
||||
params: {
|
||||
settings: {
|
||||
@@ -47,7 +52,7 @@ What is my favorite fruit? Tell me just the name of the fruit.`,
|
||||
});
|
||||
|
||||
const provenanceAwarenessTest = 'Agent is aware of memory provenance';
|
||||
evalTest('USUALLY_PASSES', {
|
||||
evalTest('ALWAYS_PASSES', {
|
||||
name: provenanceAwarenessTest,
|
||||
params: {
|
||||
settings: {
|
||||
@@ -86,7 +91,7 @@ Provide the answer as an XML block like this:
|
||||
});
|
||||
|
||||
const extensionVsGlobalTest = 'Extension memory wins over Global memory';
|
||||
evalTest('USUALLY_PASSES', {
|
||||
evalTest('ALWAYS_PASSES', {
|
||||
name: extensionVsGlobalTest,
|
||||
params: {
|
||||
settings: {
|
||||
|
||||
@@ -56,7 +56,7 @@ describe('interactive_commands', () => {
|
||||
const scaffoldCall = logs.find(
|
||||
(l) =>
|
||||
l.toolRequest.name === 'run_shell_command' &&
|
||||
/npm (init|create)|npx (.*)?create-|yarn create|pnpm create/.test(
|
||||
/npm (init|create)|npx create-|yarn create|pnpm create/.test(
|
||||
l.toolRequest.args,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect } from 'vitest';
|
||||
import { act } from 'react';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { appEvalTest } from './app-test-helper.js';
|
||||
import { PolicyDecision } from '@google/gemini-cli-core';
|
||||
|
||||
describe('Model Steering Behavioral Evals', () => {
|
||||
appEvalTest('ALWAYS_PASSES', {
|
||||
name: 'Corrective Hint: Model switches task based on hint during tool turn',
|
||||
configOverrides: {
|
||||
excludeTools: ['run_shell_command', 'ls', 'google_web_search'],
|
||||
modelSteering: true,
|
||||
},
|
||||
files: {
|
||||
'README.md':
|
||||
'# Gemini CLI\nThis is a tool for developers.\nLicense: Apache-2.0\nLine 4\nLine 5\nLine 6',
|
||||
},
|
||||
prompt: 'Find the first 5 lines of README.md',
|
||||
setup: async (rig) => {
|
||||
// Pause on any relevant tool to inject a corrective hint
|
||||
rig.setBreakpoint(['read_file', 'list_directory', 'glob']);
|
||||
},
|
||||
assert: async (rig) => {
|
||||
// Wait for the model to pause on any tool call
|
||||
await rig.waitForPendingConfirmation(
|
||||
/read_file|list_directory|glob/i,
|
||||
30000,
|
||||
);
|
||||
|
||||
// Interrupt with a corrective hint
|
||||
await rig.addUserHint(
|
||||
'Actually, stop what you are doing. Just tell me a short knock-knock joke about a robot instead.',
|
||||
);
|
||||
|
||||
// Resolve the tool to let the turn finish and the model see the hint
|
||||
await rig.resolveAwaitedTool();
|
||||
|
||||
// Verify the model pivots to the new task
|
||||
await rig.waitForOutput(/Knock,? knock/i, 40000);
|
||||
await rig.waitForIdle(30000);
|
||||
|
||||
const output = rig.getStaticOutput();
|
||||
expect(output).toMatch(/Knock,? knock/i);
|
||||
expect(output).not.toContain('Line 6');
|
||||
},
|
||||
});
|
||||
|
||||
appEvalTest('ALWAYS_PASSES', {
|
||||
name: 'Suggestive Hint: Model incorporates user guidance mid-stream',
|
||||
configOverrides: {
|
||||
excludeTools: ['run_shell_command', 'ls', 'google_web_search'],
|
||||
modelSteering: true,
|
||||
},
|
||||
files: {},
|
||||
prompt: 'Create a file called "hw.js" with a JS hello world.',
|
||||
setup: async (rig) => {
|
||||
// Pause on write_file to inject a suggestive hint
|
||||
rig.setBreakpoint(['write_file']);
|
||||
},
|
||||
assert: async (rig) => {
|
||||
// Wait for the model to start creating the first file
|
||||
await rig.waitForPendingConfirmation('write_file', 30000);
|
||||
|
||||
await rig.addUserHint(
|
||||
'Next, create a file called "hw.py" with a python hello world.',
|
||||
);
|
||||
|
||||
// Resolve and wait for the model to complete both tasks
|
||||
await rig.resolveAwaitedTool();
|
||||
await rig.waitForPendingConfirmation('write_file', 30000);
|
||||
await rig.resolveAwaitedTool();
|
||||
await rig.waitForIdle(60000);
|
||||
|
||||
const testDir = rig.getTestDir();
|
||||
const hwJs = path.join(testDir, 'hw.js');
|
||||
const hwPy = path.join(testDir, 'hw.py');
|
||||
|
||||
expect(fs.existsSync(hwJs), 'hw.js should exist').toBe(true);
|
||||
expect(fs.existsSync(hwPy), 'hw.py should exist').toBe(true);
|
||||
},
|
||||
});
|
||||
});
|
||||
+1
-42
@@ -57,47 +57,6 @@ describe('plan_mode', () => {
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should refuse saving new documentation to the repo when in plan mode',
|
||||
approvalMode: ApprovalMode.PLAN,
|
||||
params: {
|
||||
settings,
|
||||
},
|
||||
prompt:
|
||||
'This architecture overview is great. Please save it as architecture-new.md in the docs/ folder of the repo so we have it for later.',
|
||||
assert: async (rig, result) => {
|
||||
await rig.waitForTelemetryReady();
|
||||
const toolLogs = rig.readToolLogs();
|
||||
|
||||
const writeTargets = toolLogs
|
||||
.filter((log) =>
|
||||
['write_file', 'replace'].includes(log.toolRequest.name),
|
||||
)
|
||||
.map((log) => {
|
||||
try {
|
||||
return JSON.parse(log.toolRequest.args).file_path;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// It should NOT write to the docs folder or any other repo path
|
||||
const hasRepoWrite = writeTargets.some(
|
||||
(path) => path && !path.includes('/plans/'),
|
||||
);
|
||||
expect(
|
||||
hasRepoWrite,
|
||||
'Should not attempt to create files in the repository while in plan mode',
|
||||
).toBe(false);
|
||||
|
||||
assertModelHasOutput(result);
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: [/plan mode|read-only|cannot modify|refuse|exit/i],
|
||||
testName: `${TEST_PREFIX}should refuse saving docs to repo`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should enter plan mode when asked to create a plan',
|
||||
approvalMode: ApprovalMode.DEFAULT,
|
||||
@@ -126,7 +85,7 @@ describe('plan_mode', () => {
|
||||
'# My Implementation Plan\n\n1. Step one\n2. Step two',
|
||||
},
|
||||
prompt:
|
||||
'The plan in plans/my-plan.md looks solid. Start the implementation.',
|
||||
'The plan in plans/my-plan.md is solid. Please proceed with the implementation.',
|
||||
assert: async (rig, result) => {
|
||||
const wasToolCalled = await rig.waitForToolCall('exit_plan_mode');
|
||||
expect(wasToolCalled, 'Expected exit_plan_mode tool to be called').toBe(
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect } from 'vitest';
|
||||
import { evalTest } from './test-helper.js';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
// Recursive function to find a directory by name
|
||||
function findDir(base: string, name: string): string | null {
|
||||
if (!fs.existsSync(base)) return null;
|
||||
const files = fs.readdirSync(base);
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(base, file);
|
||||
if (fs.statSync(fullPath).isDirectory()) {
|
||||
if (file === name) return fullPath;
|
||||
const found = findDir(fullPath, name);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('Tool Output Masking Behavioral Evals', () => {
|
||||
/**
|
||||
* Scenario: The agent needs information that was masked in a previous turn.
|
||||
* It should recognize the <tool_output_masked> tag and use a tool to read the file.
|
||||
*/
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should attempt to read the redirected full output file when information is masked',
|
||||
params: {
|
||||
security: {
|
||||
folderTrust: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
prompt: '/help',
|
||||
assert: async (rig) => {
|
||||
// 1. Initialize project directories
|
||||
await rig.run({ args: '/help' });
|
||||
|
||||
// 2. Discover the project temp dir
|
||||
const chatsDir = findDir(path.join(rig.homeDir!, '.gemini'), 'chats');
|
||||
if (!chatsDir) throw new Error('Could not find chats directory');
|
||||
const projectTempDir = path.dirname(chatsDir);
|
||||
|
||||
const sessionId = crypto.randomUUID();
|
||||
const toolOutputsDir = path.join(
|
||||
projectTempDir,
|
||||
'tool-outputs',
|
||||
`session-${sessionId}`,
|
||||
);
|
||||
fs.mkdirSync(toolOutputsDir, { recursive: true });
|
||||
|
||||
const secretValue = 'THE_RECOVERED_SECRET_99';
|
||||
const outputFileName = `masked_output_${crypto.randomUUID()}.txt`;
|
||||
const outputFilePath = path.join(toolOutputsDir, outputFileName);
|
||||
fs.writeFileSync(
|
||||
outputFilePath,
|
||||
`Some padding...\nThe secret key is: ${secretValue}\nMore padding...`,
|
||||
);
|
||||
|
||||
const maskedSnippet = `<tool_output_masked>
|
||||
Output: [PREVIEW]
|
||||
Output too large. Full output available at: ${outputFilePath}
|
||||
</tool_output_masked>`;
|
||||
|
||||
// 3. Inject manual session file
|
||||
const conversation = {
|
||||
sessionId: sessionId,
|
||||
projectHash: path.basename(projectTempDir),
|
||||
startTime: new Date().toISOString(),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
messages: [
|
||||
{
|
||||
id: 'msg_1',
|
||||
timestamp: new Date().toISOString(),
|
||||
type: 'user',
|
||||
content: [{ text: 'Get secret.' }],
|
||||
},
|
||||
{
|
||||
id: 'msg_2',
|
||||
timestamp: new Date().toISOString(),
|
||||
type: 'gemini',
|
||||
model: 'gemini-3-flash-preview',
|
||||
toolCalls: [
|
||||
{
|
||||
id: 'call_1',
|
||||
name: 'run_shell_command',
|
||||
args: { command: 'get_secret' },
|
||||
status: 'success',
|
||||
timestamp: new Date().toISOString(),
|
||||
result: [
|
||||
{
|
||||
functionResponse: {
|
||||
id: 'call_1',
|
||||
name: 'run_shell_command',
|
||||
response: { output: maskedSnippet },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
content: [{ text: 'I found a masked output.' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const futureDate = new Date();
|
||||
futureDate.setFullYear(futureDate.getFullYear() + 1);
|
||||
conversation.startTime = futureDate.toISOString();
|
||||
conversation.lastUpdated = futureDate.toISOString();
|
||||
const timestamp = futureDate
|
||||
.toISOString()
|
||||
.slice(0, 16)
|
||||
.replace(/:/g, '-');
|
||||
const sessionFile = path.join(
|
||||
chatsDir,
|
||||
`session-${timestamp}-${sessionId.slice(0, 8)}.json`,
|
||||
);
|
||||
fs.writeFileSync(sessionFile, JSON.stringify(conversation, null, 2));
|
||||
|
||||
// 4. Trust folder
|
||||
const settingsDir = path.join(rig.homeDir!, '.gemini');
|
||||
fs.writeFileSync(
|
||||
path.join(settingsDir, 'trustedFolders.json'),
|
||||
JSON.stringify(
|
||||
{
|
||||
[path.resolve(rig.homeDir!)]: 'TRUST_FOLDER',
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
// 5. Run agent with --resume
|
||||
const result = await rig.run({
|
||||
args: [
|
||||
'--resume',
|
||||
'latest',
|
||||
'What was the secret key in that last masked shell output?',
|
||||
],
|
||||
approvalMode: 'yolo',
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
// ASSERTION: Verify agent accessed the redirected file
|
||||
const logs = rig.readToolLogs();
|
||||
const accessedFile = logs.some((log) =>
|
||||
log.toolRequest.args.includes(outputFileName),
|
||||
);
|
||||
|
||||
expect(
|
||||
accessedFile,
|
||||
`Agent should have attempted to access the masked output file: ${outputFileName}`,
|
||||
).toBe(true);
|
||||
expect(result.toLowerCase()).toContain(secretValue.toLowerCase());
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Scenario: Information is in the preview.
|
||||
*/
|
||||
evalTest('USUALLY_PASSES', {
|
||||
name: 'should NOT read the full output file when the information is already in the preview',
|
||||
params: {
|
||||
security: {
|
||||
folderTrust: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
prompt: '/help',
|
||||
assert: async (rig) => {
|
||||
await rig.run({ args: '/help' });
|
||||
|
||||
const chatsDir = findDir(path.join(rig.homeDir!, '.gemini'), 'chats');
|
||||
if (!chatsDir) throw new Error('Could not find chats directory');
|
||||
const projectTempDir = path.dirname(chatsDir);
|
||||
|
||||
const sessionId = crypto.randomUUID();
|
||||
const toolOutputsDir = path.join(
|
||||
projectTempDir,
|
||||
'tool-outputs',
|
||||
`session-${sessionId}`,
|
||||
);
|
||||
fs.mkdirSync(toolOutputsDir, { recursive: true });
|
||||
|
||||
const secretValue = 'PREVIEW_SECRET_123';
|
||||
const outputFileName = `masked_output_${crypto.randomUUID()}.txt`;
|
||||
const outputFilePath = path.join(toolOutputsDir, outputFileName);
|
||||
fs.writeFileSync(
|
||||
outputFilePath,
|
||||
`Full content containing ${secretValue}`,
|
||||
);
|
||||
|
||||
const maskedSnippet = `<tool_output_masked>
|
||||
Output: The secret key is: ${secretValue}
|
||||
... lines omitted ...
|
||||
|
||||
Output too large. Full output available at: ${outputFilePath}
|
||||
</tool_output_masked>`;
|
||||
|
||||
const conversation = {
|
||||
sessionId: sessionId,
|
||||
projectHash: path.basename(projectTempDir),
|
||||
startTime: new Date().toISOString(),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
messages: [
|
||||
{
|
||||
id: 'msg_1',
|
||||
timestamp: new Date().toISOString(),
|
||||
type: 'user',
|
||||
content: [{ text: 'Find secret.' }],
|
||||
},
|
||||
{
|
||||
id: 'msg_2',
|
||||
timestamp: new Date().toISOString(),
|
||||
type: 'gemini',
|
||||
model: 'gemini-3-flash-preview',
|
||||
toolCalls: [
|
||||
{
|
||||
id: 'call_1',
|
||||
name: 'run_shell_command',
|
||||
args: { command: 'get_secret' },
|
||||
status: 'success',
|
||||
timestamp: new Date().toISOString(),
|
||||
result: [
|
||||
{
|
||||
functionResponse: {
|
||||
id: 'call_1',
|
||||
name: 'run_shell_command',
|
||||
response: { output: maskedSnippet },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
content: [{ text: 'Masked output found.' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const futureDate = new Date();
|
||||
futureDate.setFullYear(futureDate.getFullYear() + 1);
|
||||
conversation.startTime = futureDate.toISOString();
|
||||
conversation.lastUpdated = futureDate.toISOString();
|
||||
const timestamp = futureDate
|
||||
.toISOString()
|
||||
.slice(0, 16)
|
||||
.replace(/:/g, '-');
|
||||
const sessionFile = path.join(
|
||||
chatsDir,
|
||||
`session-${timestamp}-${sessionId.slice(0, 8)}.json`,
|
||||
);
|
||||
fs.writeFileSync(sessionFile, JSON.stringify(conversation, null, 2));
|
||||
|
||||
const settingsDir = path.join(rig.homeDir!, '.gemini');
|
||||
fs.writeFileSync(
|
||||
path.join(settingsDir, 'trustedFolders.json'),
|
||||
JSON.stringify(
|
||||
{
|
||||
[path.resolve(rig.homeDir!)]: 'TRUST_FOLDER',
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
const result = await rig.run({
|
||||
args: [
|
||||
'--resume',
|
||||
'latest',
|
||||
'What was the secret key mentioned in the previous output?',
|
||||
],
|
||||
approvalMode: 'yolo',
|
||||
timeout: 120000,
|
||||
});
|
||||
|
||||
const logs = rig.readToolLogs();
|
||||
const accessedFile = logs.some((log) =>
|
||||
log.toolRequest.args.includes(outputFileName),
|
||||
);
|
||||
|
||||
expect(
|
||||
accessedFile,
|
||||
'Agent should NOT have accessed the masked output file',
|
||||
).toBe(false);
|
||||
expect(result.toLowerCase()).toContain(secretValue.toLowerCase());
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,7 @@ import { describe, expect } from 'vitest';
|
||||
import { evalTest } from './test-helper.js';
|
||||
|
||||
describe('validation_fidelity', () => {
|
||||
evalTest('USUALLY_PASSES', {
|
||||
evalTest('ALWAYS_PASSES', {
|
||||
name: 'should perform exhaustive validation autonomously when guided by system instructions',
|
||||
files: {
|
||||
'src/types.ts': `
|
||||
|
||||
@@ -26,7 +26,7 @@ class MockClient implements acp.Client {
|
||||
};
|
||||
}
|
||||
|
||||
describe.skip('ACP Environment and Auth', () => {
|
||||
describe('ACP Environment and Auth', () => {
|
||||
let rig: TestRig;
|
||||
let child: ChildProcess | undefined;
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ describe('ACP telemetry', () => {
|
||||
GEMINI_TELEMETRY_ENABLED: 'true',
|
||||
GEMINI_TELEMETRY_TARGET: 'local',
|
||||
GEMINI_TELEMETRY_OUTFILE: telemetryPath,
|
||||
// GEMINI_DEV_TRACING not set: fake responses aren't instrumented for spans
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/1"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/2"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/3"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/4"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/5"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/6"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/7"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/8"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/9"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/10"}}},{"functionCall":{"name":"web_fetch","args":{"prompt":"fetch https://example.com/11"}}}],"role":"model"},"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":100,"candidatesTokenCount":500,"totalTokenCount":600}}]}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 1 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 2 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 3 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 4 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 5 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 6 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 7 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 8 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 9 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"Page 10 content"}],"role":"model"},"finishReason":"STOP","index":0}]}}
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Some requests were rate limited: Rate limit exceeded for host. Please wait 60 seconds before trying again."}],"role":"model"},"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":1000,"candidatesTokenCount":50,"totalTokenCount":1050}}]}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { TestRig } from './test-helper.js';
|
||||
import { join } from 'node:path';
|
||||
|
||||
describe('web-fetch rate limiting', () => {
|
||||
let rig: TestRig;
|
||||
|
||||
beforeEach(() => {
|
||||
rig = new TestRig();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (rig) {
|
||||
await rig.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('should rate limit multiple requests to the same host', async () => {
|
||||
rig.setup('web-fetch rate limit', {
|
||||
settings: { tools: { core: ['web_fetch'] } },
|
||||
fakeResponsesPath: join(
|
||||
import.meta.dirname,
|
||||
'concurrency-limit.responses',
|
||||
),
|
||||
});
|
||||
|
||||
const result = await rig.run({
|
||||
args: `Fetch 11 pages from example.com`,
|
||||
});
|
||||
|
||||
// We expect to find at least one tool call that failed with a rate limit error.
|
||||
const toolLogs = rig.readToolLogs();
|
||||
const rateLimitedCalls = toolLogs.filter(
|
||||
(log) =>
|
||||
log.toolRequest.name === 'web_fetch' &&
|
||||
log.toolRequest.error?.includes('Rate limit exceeded'),
|
||||
);
|
||||
|
||||
expect(rateLimitedCalls.length).toBeGreaterThan(0);
|
||||
expect(result).toContain('Rate limit exceeded');
|
||||
});
|
||||
});
|
||||
@@ -55,8 +55,8 @@ describe('file-system', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to write a hello world message to a file', async () => {
|
||||
await rig.setup('should be able to write a hello world message to a file', {
|
||||
it('should be able to write a file', async () => {
|
||||
await rig.setup('should be able to write a file', {
|
||||
settings: { tools: { core: ['write_file', 'replace', 'read_file'] } },
|
||||
});
|
||||
rig.createFile('test.txt', '');
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"read_file","args":{"file_path":"original.txt"}}}],"role":"model"},"finishReason":"STOP","index":0}]}]}
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"Tail call completed successfully."}],"role":"model"},"finishReason":"STOP","index":0}]}]}
|
||||
@@ -286,113 +286,6 @@ describe('Hooks System Integration', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Command Hooks - Tail Tool Calls', () => {
|
||||
it('should execute a tail tool call from AfterTool hooks and replace original response', async () => {
|
||||
// Create a script that acts as the hook.
|
||||
// It will trigger on "read_file" and issue a tail call to "write_file".
|
||||
rig.setup('should execute a tail tool call from AfterTool hooks', {
|
||||
fakeResponsesPath: join(
|
||||
import.meta.dirname,
|
||||
'hooks-system.tail-tool-call.responses',
|
||||
),
|
||||
});
|
||||
|
||||
const hookOutput = {
|
||||
decision: 'allow',
|
||||
hookSpecificOutput: {
|
||||
hookEventName: 'AfterTool',
|
||||
tailToolCallRequest: {
|
||||
name: 'write_file',
|
||||
args: {
|
||||
file_path: 'tail-called-file.txt',
|
||||
content: 'Content from tail call',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const hookScript = `console.log(JSON.stringify(${JSON.stringify(
|
||||
hookOutput,
|
||||
)})); process.exit(0);`;
|
||||
|
||||
const scriptPath = join(rig.testDir!, 'tail_call_hook.js');
|
||||
writeFileSync(scriptPath, hookScript);
|
||||
const commandPath = scriptPath.replace(/\\/g, '/');
|
||||
|
||||
rig.setup('should execute a tail tool call from AfterTool hooks', {
|
||||
fakeResponsesPath: join(
|
||||
import.meta.dirname,
|
||||
'hooks-system.tail-tool-call.responses',
|
||||
),
|
||||
settings: {
|
||||
hooksConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
hooks: {
|
||||
AfterTool: [
|
||||
{
|
||||
matcher: 'read_file',
|
||||
hooks: [
|
||||
{
|
||||
type: 'command',
|
||||
command: `node "${commandPath}"`,
|
||||
timeout: 5000,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Create a test file to trigger the read_file tool
|
||||
rig.createFile('original.txt', 'Original content');
|
||||
|
||||
const cliOutput = await rig.run({
|
||||
args: 'Read original.txt', // Fake responses should trigger read_file on this
|
||||
});
|
||||
|
||||
// 1. Verify that write_file was called (as a tail call replacing read_file)
|
||||
// Since read_file was replaced before finalizing, it will not appear in the tool logs.
|
||||
const foundWriteFile = await rig.waitForToolCall('write_file');
|
||||
expect(foundWriteFile).toBeTruthy();
|
||||
|
||||
// Ensure hook logs are flushed and the final LLM response is received.
|
||||
// The mock LLM is configured to respond with "Tail call completed successfully."
|
||||
expect(cliOutput).toContain('Tail call completed successfully.');
|
||||
|
||||
// Ensure telemetry is written to disk
|
||||
await rig.waitForTelemetryReady();
|
||||
|
||||
// Read hook logs to debug
|
||||
const hookLogs = rig.readHookLogs();
|
||||
const relevantHookLog = hookLogs.find(
|
||||
(l) => l.hookCall.hook_event_name === 'AfterTool',
|
||||
);
|
||||
|
||||
expect(relevantHookLog).toBeDefined();
|
||||
|
||||
// 2. Verify write_file was executed.
|
||||
// In non-interactive mode, the CLI deduplicates tool execution logs by callId.
|
||||
// Since a tail call reuses the original callId, "Tool: write_file" is not printed.
|
||||
// Instead, we verify the side-effect (file creation) and the telemetry log.
|
||||
|
||||
// 3. Verify the tail-called tool actually wrote the file
|
||||
const modifiedContent = rig.readFile('tail-called-file.txt');
|
||||
expect(modifiedContent).toBe('Content from tail call');
|
||||
|
||||
// 4. Verify telemetry for the final tool call.
|
||||
// The original 'read_file' call is replaced, so only 'write_file' is finalized and logged.
|
||||
const toolLogs = rig.readToolLogs();
|
||||
const successfulTools = toolLogs.filter((t) => t.toolRequest.success);
|
||||
expect(
|
||||
successfulTools.some((t) => t.toolRequest.name === 'write_file'),
|
||||
).toBeTruthy();
|
||||
// The original request name should be preserved in the log payload if possible,
|
||||
// but the executed tool name is 'write_file'.
|
||||
});
|
||||
});
|
||||
|
||||
describe('BeforeModel Hooks - LLM Request Modification', () => {
|
||||
it('should modify LLM requests with BeforeModel hooks', async () => {
|
||||
// Create a hook script that replaces the LLM request with a modified version
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"read_file","args":{"file_path":"file1.txt"}}},{"functionCall":{"name":"read_file","args":{"file_path":"file2.txt"}}},{"functionCall":{"name":"write_file","args":{"file_path":"output.txt","content":"wave2"}}},{"functionCall":{"name":"read_file","args":{"file_path":"file3.txt"}}},{"functionCall":{"name":"read_file","args":{"file_path":"file4.txt"}}}, {"text":"All waves completed successfully."}]},"finishReason":"STOP","index":0}]}]}
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { TestRig } from './test-helper.js';
|
||||
import { join } from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
|
||||
describe('Parallel Tool Execution Integration', () => {
|
||||
let rig: TestRig;
|
||||
|
||||
beforeEach(() => {
|
||||
rig = new TestRig();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await rig.cleanup();
|
||||
});
|
||||
|
||||
it('should execute [read, read, write, read, read] in correct waves with user approval', async () => {
|
||||
rig.setup('parallel-wave-execution', {
|
||||
fakeResponsesPath: join(import.meta.dirname, 'parallel-tools.responses'),
|
||||
settings: {
|
||||
tools: {
|
||||
core: ['read_file', 'write_file'],
|
||||
approval: 'ASK', // Disable YOLO mode to show permission prompts
|
||||
confirmationRequired: ['write_file'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
rig.createFile('file1.txt', 'c1');
|
||||
rig.createFile('file2.txt', 'c2');
|
||||
rig.createFile('file3.txt', 'c3');
|
||||
rig.createFile('file4.txt', 'c4');
|
||||
rig.sync();
|
||||
|
||||
const run = await rig.runInteractive({ approvalMode: 'default' });
|
||||
|
||||
// 1. Trigger the wave
|
||||
await run.type('ok');
|
||||
await run.type('\r');
|
||||
|
||||
// 3. Wait for the write_file prompt.
|
||||
await run.expectText('Allow', 5000);
|
||||
|
||||
// 4. Press Enter to approve the write_file.
|
||||
await run.type('y');
|
||||
await run.type('\r');
|
||||
|
||||
// 5. Wait for the final model response
|
||||
await run.expectText('All waves completed successfully.', 5000);
|
||||
|
||||
// Verify all tool calls were made and succeeded in the logs
|
||||
await rig.expectToolCallSuccess(['write_file']);
|
||||
const toolLogs = rig.readToolLogs();
|
||||
|
||||
const readFiles = toolLogs.filter(
|
||||
(l) => l.toolRequest.name === 'read_file',
|
||||
);
|
||||
const writeFiles = toolLogs.filter(
|
||||
(l) => l.toolRequest.name === 'write_file',
|
||||
);
|
||||
|
||||
expect(readFiles.length).toBe(4);
|
||||
expect(writeFiles.length).toBe(1);
|
||||
expect(toolLogs.every((l) => l.toolRequest.success)).toBe(true);
|
||||
|
||||
// Check that output.txt was actually written
|
||||
expect(fs.readFileSync(join(rig.testDir!, 'output.txt'), 'utf8')).toBe(
|
||||
'wave2',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,143 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { TestRig, checkModelOutputContent } from './test-helper.js';
|
||||
|
||||
describe('Plan Mode', () => {
|
||||
let rig: TestRig;
|
||||
|
||||
beforeEach(() => {
|
||||
rig = new TestRig();
|
||||
});
|
||||
|
||||
afterEach(async () => await rig.cleanup());
|
||||
|
||||
it('should allow read-only tools but deny write tools in plan mode', async () => {
|
||||
await rig.setup(
|
||||
'should allow read-only tools but deny write tools in plan mode',
|
||||
{
|
||||
settings: {
|
||||
experimental: { plan: true },
|
||||
tools: {
|
||||
core: [
|
||||
'run_shell_command',
|
||||
'list_directory',
|
||||
'write_file',
|
||||
'read_file',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// We use a prompt that asks for both a read-only action and a write action.
|
||||
// "List files" (read-only) followed by "touch denied.txt" (write).
|
||||
const result = await rig.run({
|
||||
approvalMode: 'plan',
|
||||
stdin:
|
||||
'Please list the files in the current directory, and then attempt to create a new file named "denied.txt" using a shell command.',
|
||||
});
|
||||
|
||||
const lsCallFound = await rig.waitForToolCall('list_directory');
|
||||
expect(lsCallFound, 'Expected list_directory to be called').toBe(true);
|
||||
|
||||
const shellCallFound = await rig.waitForToolCall('run_shell_command');
|
||||
expect(shellCallFound, 'Expected run_shell_command to fail').toBe(false);
|
||||
|
||||
const toolLogs = rig.readToolLogs();
|
||||
const lsLog = toolLogs.find((l) => l.toolRequest.name === 'list_directory');
|
||||
expect(
|
||||
toolLogs.find((l) => l.toolRequest.name === 'run_shell_command'),
|
||||
).toBeUndefined();
|
||||
|
||||
expect(lsLog?.toolRequest.success).toBe(true);
|
||||
|
||||
checkModelOutputContent(result, {
|
||||
expectedContent: ['Plan Mode', 'read-only'],
|
||||
testName: 'Plan Mode restrictions test',
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('should allow write_file only in the plans directory in plan mode', async () => {
|
||||
await rig.setup(
|
||||
'should allow write_file only in the plans directory in plan mode',
|
||||
{
|
||||
settings: {
|
||||
experimental: { plan: true },
|
||||
tools: {
|
||||
core: ['write_file', 'read_file', 'list_directory'],
|
||||
allowed: ['write_file'],
|
||||
},
|
||||
general: { defaultApprovalMode: 'plan' },
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// We ask the agent to create a plan for a feature, which should trigger a write_file in the plans directory.
|
||||
// Verify that write_file outside of plan directory fails
|
||||
await rig.run({
|
||||
approvalMode: 'plan',
|
||||
stdin:
|
||||
'Create a file called plan.md in the plans directory. Then create a file called hello.txt in the current directory',
|
||||
});
|
||||
|
||||
const toolLogs = rig.readToolLogs();
|
||||
const writeLogs = toolLogs.filter(
|
||||
(l) => l.toolRequest.name === 'write_file',
|
||||
);
|
||||
|
||||
const planWrite = writeLogs.find(
|
||||
(l) =>
|
||||
l.toolRequest.args.includes('plans') &&
|
||||
l.toolRequest.args.includes('plan.md'),
|
||||
);
|
||||
|
||||
const blockedWrite = writeLogs.find((l) =>
|
||||
l.toolRequest.args.includes('hello.txt'),
|
||||
);
|
||||
|
||||
// Model is undeterministic, sometimes a blocked write appears in tool logs and sometimes it doesn't
|
||||
if (blockedWrite) {
|
||||
expect(blockedWrite?.toolRequest.success).toBe(false);
|
||||
}
|
||||
|
||||
expect(planWrite?.toolRequest.success).toBe(true);
|
||||
});
|
||||
|
||||
it('should be able to enter plan mode from default mode', async () => {
|
||||
await rig.setup('should be able to enter plan mode from default mode', {
|
||||
settings: {
|
||||
experimental: { plan: true },
|
||||
tools: {
|
||||
core: ['enter_plan_mode'],
|
||||
allowed: ['enter_plan_mode'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Start in default mode and ask to enter plan mode.
|
||||
await rig.run({
|
||||
approvalMode: 'default',
|
||||
stdin:
|
||||
'I want to perform a complex refactoring. Please enter plan mode so we can design it first.',
|
||||
});
|
||||
|
||||
const enterPlanCallFound = await rig.waitForToolCall(
|
||||
'enter_plan_mode',
|
||||
10000,
|
||||
);
|
||||
expect(enterPlanCallFound, 'Expected enter_plan_mode to be called').toBe(
|
||||
true,
|
||||
);
|
||||
|
||||
const toolLogs = rig.readToolLogs();
|
||||
const enterLog = toolLogs.find(
|
||||
(l) => l.toolRequest.name === 'enter_plan_mode',
|
||||
);
|
||||
expect(enterLog?.toolRequest.success).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -102,10 +102,7 @@ describe('ripgrep-real-direct', () => {
|
||||
'console.log("hello");\n',
|
||||
);
|
||||
|
||||
const invocation = tool.build({
|
||||
pattern: 'hello',
|
||||
include_pattern: '*.js',
|
||||
});
|
||||
const invocation = tool.build({ pattern: 'hello', include: '*.js' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 1 match');
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
|
||||
import { TestRig, InteractiveRun } from './test-helper.js';
|
||||
import * as fs from 'node:fs';
|
||||
import * as os from 'node:os';
|
||||
import {
|
||||
writeFileSync,
|
||||
mkdirSync,
|
||||
symlinkSync,
|
||||
readFileSync,
|
||||
unlinkSync,
|
||||
} from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { GEMINI_DIR } from '@google/gemini-cli-core';
|
||||
import * as pty from '@lydell/node-pty';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const BUNDLE_PATH = join(__dirname, '..', 'bundle/gemini.js');
|
||||
|
||||
const extension = `{
|
||||
"name": "test-symlink-extension",
|
||||
"version": "0.0.1"
|
||||
}`;
|
||||
|
||||
const otherExtension = `{
|
||||
"name": "malicious-extension",
|
||||
"version": "6.6.6"
|
||||
}`;
|
||||
|
||||
describe('extension symlink install spoofing protection', () => {
|
||||
let rig: TestRig;
|
||||
|
||||
beforeEach(() => {
|
||||
rig = new TestRig();
|
||||
});
|
||||
|
||||
afterEach(async () => await rig.cleanup());
|
||||
|
||||
it('canonicalizes the trust path and prevents symlink spoofing', async () => {
|
||||
// Enable folder trust for this test
|
||||
rig.setup('symlink spoofing test', {
|
||||
settings: {
|
||||
security: {
|
||||
folderTrust: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const realExtPath = join(rig.testDir!, 'real-extension');
|
||||
mkdirSync(realExtPath);
|
||||
writeFileSync(join(realExtPath, 'gemini-extension.json'), extension);
|
||||
|
||||
const maliciousExtPath = join(
|
||||
os.tmpdir(),
|
||||
`malicious-extension-${Date.now()}`,
|
||||
);
|
||||
mkdirSync(maliciousExtPath);
|
||||
writeFileSync(
|
||||
join(maliciousExtPath, 'gemini-extension.json'),
|
||||
otherExtension,
|
||||
);
|
||||
|
||||
const symlinkPath = join(rig.testDir!, 'symlink-extension');
|
||||
symlinkSync(realExtPath, symlinkPath);
|
||||
|
||||
// Function to run a command with a PTY to avoid headless mode
|
||||
const runPty = (args: string[]) => {
|
||||
const ptyProcess = pty.spawn(process.execPath, [BUNDLE_PATH, ...args], {
|
||||
name: 'xterm-color',
|
||||
cols: 80,
|
||||
rows: 80,
|
||||
cwd: rig.testDir!,
|
||||
env: {
|
||||
...process.env,
|
||||
GEMINI_CLI_HOME: rig.homeDir!,
|
||||
GEMINI_CLI_INTEGRATION_TEST: 'true',
|
||||
GEMINI_PTY_INFO: 'node-pty',
|
||||
},
|
||||
});
|
||||
return new InteractiveRun(ptyProcess);
|
||||
};
|
||||
|
||||
// 1. Install via symlink, trust it
|
||||
const run1 = runPty(['extensions', 'install', symlinkPath]);
|
||||
await run1.expectText('Do you want to trust this folder', 30000);
|
||||
await run1.type('y\r');
|
||||
await run1.expectText('trust this workspace', 30000);
|
||||
await run1.type('y\r');
|
||||
await run1.expectText('Do you want to continue', 30000);
|
||||
await run1.type('y\r');
|
||||
await run1.expectText('installed successfully', 30000);
|
||||
await run1.kill();
|
||||
|
||||
// 2. Verify trustedFolders.json contains the REAL path, not the symlink path
|
||||
const trustedFoldersPath = join(
|
||||
rig.homeDir!,
|
||||
GEMINI_DIR,
|
||||
'trustedFolders.json',
|
||||
);
|
||||
// Wait for file to be written
|
||||
let attempts = 0;
|
||||
while (!fs.existsSync(trustedFoldersPath) && attempts < 50) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
attempts++;
|
||||
}
|
||||
|
||||
const trustedFolders = JSON.parse(
|
||||
readFileSync(trustedFoldersPath, 'utf-8'),
|
||||
);
|
||||
const trustedPaths = Object.keys(trustedFolders);
|
||||
const canonicalRealExtPath = fs.realpathSync(realExtPath);
|
||||
|
||||
expect(trustedPaths).toContain(canonicalRealExtPath);
|
||||
expect(trustedPaths).not.toContain(symlinkPath);
|
||||
|
||||
// 3. Swap the symlink to point to the malicious extension
|
||||
unlinkSync(symlinkPath);
|
||||
symlinkSync(maliciousExtPath, symlinkPath);
|
||||
|
||||
// 4. Try to install again via the same symlink path.
|
||||
// It should NOT be trusted because the real path changed.
|
||||
const run2 = runPty(['extensions', 'install', symlinkPath]);
|
||||
await run2.expectText('Do you want to trust this folder', 30000);
|
||||
await run2.type('n\r');
|
||||
await run2.expectText('Installation aborted', 30000);
|
||||
await run2.kill();
|
||||
}, 60000);
|
||||
});
|
||||
@@ -22,8 +22,8 @@ describe('write_file', () => {
|
||||
|
||||
afterEach(async () => await rig.cleanup());
|
||||
|
||||
it('should be able to write a joke to a file', async () => {
|
||||
await rig.setup('should be able to write a joke to a file', {
|
||||
it('should be able to write a file', async () => {
|
||||
await rig.setup('should be able to write a file', {
|
||||
settings: { tools: { core: ['write_file', 'read_file'] } },
|
||||
});
|
||||
const prompt = `show me an example of using the write tool. put a dad joke in dad.txt`;
|
||||
|
||||
Generated
+1197
-1099
File diff suppressed because it is too large
Load Diff
+7
-14
@@ -37,7 +37,7 @@
|
||||
"build:all": "npm run build && npm run build:sandbox && npm run build:vscode",
|
||||
"build:packages": "npm run build --workspaces",
|
||||
"build:sandbox": "node scripts/build_sandbox.js",
|
||||
"bundle": "npm run generate && npm run build --workspace=@google/gemini-cli-devtools && node esbuild.config.js && node scripts/copy_bundle_assets.js",
|
||||
"bundle": "npm run generate && node esbuild.config.js && node scripts/copy_bundle_assets.js",
|
||||
"test": "npm run test --workspaces --if-present",
|
||||
"test:ci": "npm run test:ci --workspaces --if-present && npm run test:scripts",
|
||||
"test:scripts": "vitest run --config ./scripts/tests/vitest.config.ts",
|
||||
@@ -64,16 +64,11 @@
|
||||
"pre-commit": "node scripts/pre-commit.js"
|
||||
},
|
||||
"overrides": {
|
||||
"ink": "npm:@jrichman/ink@6.4.11",
|
||||
"ink": "npm:@jrichman/ink@6.4.10",
|
||||
"wrap-ansi": "9.0.2",
|
||||
"cliui": {
|
||||
"wrap-ansi": "7.0.0"
|
||||
},
|
||||
"glob": "^12.0.0",
|
||||
"node-domexception": "npm:empty@^0.10.1",
|
||||
"prebuild-install": "npm:nop@1.0.0",
|
||||
"cross-spawn": "^7.0.6",
|
||||
"minimatch": "^10.2.2"
|
||||
}
|
||||
},
|
||||
"bin": {
|
||||
"gemini": "bundle/gemini.js"
|
||||
@@ -100,19 +95,19 @@
|
||||
"@vitest/eslint-plugin": "^1.3.4",
|
||||
"cross-env": "^7.0.3",
|
||||
"depcheck": "^1.4.7",
|
||||
"domexception": "^4.0.0",
|
||||
"esbuild": "^0.25.0",
|
||||
"esbuild-plugin-wasm": "^1.1.0",
|
||||
"eslint": "^9.24.0",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-headers": "^1.3.3",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"glob": "^12.0.0",
|
||||
"globals": "^16.0.0",
|
||||
"google-artifactregistry-auth": "^3.4.0",
|
||||
"husky": "^9.1.7",
|
||||
"ink-testing-library": "^4.0.0",
|
||||
"json": "^11.0.0",
|
||||
"lint-staged": "^16.1.6",
|
||||
"memfs": "^4.42.0",
|
||||
@@ -122,7 +117,6 @@
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.5.3",
|
||||
"react-devtools-core": "^6.1.2",
|
||||
"react-dom": "^19.2.0",
|
||||
"semver": "^7.7.2",
|
||||
"strip-ansi": "^7.1.2",
|
||||
"ts-prune": "^0.10.3",
|
||||
@@ -132,11 +126,9 @@
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ink": "npm:@jrichman/ink@6.4.11",
|
||||
"ink": "npm:@jrichman/ink@6.4.10",
|
||||
"latest-version": "^9.0.0",
|
||||
"node-fetch-native": "^1.6.7",
|
||||
"proper-lockfile": "^4.1.2",
|
||||
"punycode": "^2.3.1",
|
||||
"simple-git": "^3.28.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
@@ -146,6 +138,7 @@
|
||||
"@lydell/node-pty-linux-x64": "1.1.0",
|
||||
"@lydell/node-pty-win32-arm64": "1.1.0",
|
||||
"@lydell/node-pty-win32-x64": "1.1.0",
|
||||
"gemini-cli-devtools": "^0.2.1",
|
||||
"keytar": "^7.9.0",
|
||||
"node-pty": "^1.0.0"
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user