Compare commits

..

1 Commits

Author SHA1 Message Date
Christine Betts baef6731bd make broken docs change 2026-02-04 16:04:14 -05:00
1780 changed files with 44714 additions and 175415 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ You are an expert at fixing behavioral evaluations.
the same scenario. We don't want to lose test fidelity by making the prompts too the same scenario. We don't want to lose test fidelity by making the prompts too
direct (i.e.: easy). direct (i.e.: easy).
- Your primary mechanism for improving the agent's behavior is to make changes to - Your primary mechanism for improving the agent's behavior is to make changes to
tool instructions, system prompt (snippets.ts), and/or modules that contribute to the prompt. tool instructions, prompt.ts, and/or modules that contribute to the prompt.
- If prompt and description changes are unsuccessful, use logs and debugging to - If prompt and description changes are unsuccessful, use logs and debugging to
confirm that everything is working as expected. confirm that everything is working as expected.
- If unable to fix the test, you can make recommendations for architecture changes - If unable to fix the test, you can make recommendations for architecture changes
+35 -1
View File
@@ -14,7 +14,41 @@ core architecture, component patterns, and testing standards.
In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines while adding code to packages/cli. In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines while adding code to packages/cli.
!{cat .gemini/commands/strict-development-rules.md} ## Testing Standards
* **Async Testing**: ALWAYS use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` to prevent flakiness and `act` warnings. NEVER use fixed waits (e.g., `await delay(100)`).
* **State Changes**: Wrap all blocks that change component state in `act`.
* **Snapshots**: Use `toMatchSnapshot` to verify rendering.
* **Rendering**: Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `ink-testing-library` directly.
* **Mocking**:
* Reuse existing mocks/fakes where possible.
* **Parameterized Tests**: Use parameterized tests with explicit types to reduce duplication and ensure type safety.
* Avoid mocking the file system, os, or child_process if at all possible; if you have to mock the Mock critical dependencies (`fs`, `os`, `child_process`) do so ONLY at the top of the file.
## React & Ink Architecture
* **Keyboard Handling**: You MUST use `useKeyPress.ts` from Gemini CLI for keyboard handling, NOT the standard ink library. This is critical for supporting slow terminals and multiple events per frame.
* Handle multiple events gracefully (often requires a reducer pattern, see `text-buffer.ts`).
* **State Management**:
* NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary.
* Initialize state explicitly (e.g., use `undefined` rather than `true` if unknown).
* **Performance**:
* Avoid synchronous file I/O in components.
* Do not introduce excessive property drilling; leverage or extend existing providers.
## Configuration & Settings
* **Settings vs Args**: Use settings for user-configurable options; do not add new CLI arguments.
* **Schema**: Add new settings to `packages/cli/src/config/settingsSchema.ts`.
* **Documentation**:
* If `showInDialog: true`, document in `docs/get-started/configuration.md`.
* Ensure `requiresRestart` is correctly set.
## Keyboard Shortcuts
* **Registration**: Define new shortcuts in `packages/cli/src/config/keyBindings.ts`.
* **Documentation**: Document all new shortcuts in `docs/cli/keyboard-shortcuts.md`.
* **Compatibility**: Avoid function keys and common VSCode shortcuts. Be cautious with `Meta` key (Mac-limited support).
## General
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
* **TypeScript**: Avoid the non-null assertion operator (`!`).
{{args}}. {{args}}.
""" """
+35 -1
View File
@@ -17,7 +17,41 @@ prompts.
In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines when writing code in packages/cli. In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines when writing code in packages/cli.
!{cat .gemini/commands/strict-development-rules.md} ## Testing Standards
* **Async Testing**: ALWAYS use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` to prevent flakiness and `act` warnings. NEVER use fixed waits (e.g., `await delay(100)`).
* **State Changes**: Wrap all blocks that change component state in `act`.
* **Snapshots**: Use `toMatchSnapshot` to verify rendering.
* **Rendering**: Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `ink-testing-library` directly.
* **Mocking**:
* Reuse existing mocks/fakes where possible.
* **Parameterized Tests**: Use parameterized tests with explicit types to reduce duplication and ensure type safety.
* Avoid mocking the file system, os, or child_process if at all possible; if you have to mock the Mock critical dependencies (`fs`, `os`, `child_process`) do so ONLY at the top of the file.
## React & Ink Architecture
* **Keyboard Handling**: You MUST use `useKeyPress.ts` from Gemini CLI for keyboard handling, NOT the standard ink library. This is critical for supporting slow terminals and multiple events per frame.
* Handle multiple events gracefully (often requires a reducer pattern, see `text-buffer.ts`).
* **State Management**:
* NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary.
* Initialize state explicitly (e.g., use `undefined` rather than `true` if unknown).
* **Performance**:
* Avoid synchronous file I/O in components.
* Do not introduce excessive property drilling; leverage or extend existing providers.
## Configuration & Settings
* **Settings vs Args**: Use settings for user-configurable options; do not add new CLI arguments.
* **Schema**: Add new settings to `packages/cli/src/config/settingsSchema.ts`.
* **Documentation**:
* If `showInDialog: true`, document in `docs/get-started/configuration.md`.
* Ensure `requiresRestart` is correctly set.
## Keyboard Shortcuts
* **Registration**: Define new shortcuts in `packages/cli/src/config/keyBindings.ts`.
* **Documentation**: Document all new shortcuts in `docs/cli/keyboard-shortcuts.md`.
* **Compatibility**: Avoid function keys and common VSCode shortcuts. Be cautious with `Meta` key (Mac-limited support).
## General
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
* **TypeScript**: Avoid the non-null assertion operator (`!`).
{{args}}. {{args}}.
""" """
@@ -1,29 +0,0 @@
description = "Promote behavioral evals that have a 100% success rate over the last 7 nightly runs."
prompt = """
You are an expert at analyzing and promoting behavioral evaluations.
1. **Investigate**:
- Use 'gh' cli to fetch the results from the most recent run from the main branch: https://github.com/google-gemini/gemini-cli/actions/workflows/evals-nightly.yml.
- DO NOT push any changes or start any runs. The rest of your evaluation will be local.
- Evals are in evals/ directory and are documented by evals/README.md.
- Identify tests that have passed 100% of the time for ALL enabled models across the past 7 runs in a row.
- NOTE: the results summary from the most recent run contains the last 7 runs test results. 100% means the test passed 3/3 times for that model and run.
- If a test meets this criteria, it is a candidate for promotion.
2. **Promote**:
- For each candidate test, locate the test file in the evals/ directory.
- Promote the test according to the project's standard promotion process (e.g., moving it to a stable suite, updating its tags, or removing skip/flaky annotations).
- Ensure you follow any guidelines in evals/README.md for stable tests.
- Your **final** change should be **minimal and targeted** to just promoting the test status.
3. **Verify**:
- Run the promoted tests locally to validate that they still execute correctly. Be sure to run vitest in non-interactive mode.
- Check that the test is now part of the expected standard or stable test suites.
4. **Report**:
- Provide a summary of the tests that were promoted.
- Include the success rate evidence (7/7 runs passed for all models) for each promoted test.
- If no tests met the criteria for promotion, clearly state that and summarize the closest candidates.
{{args}}
"""
+126 -3
View File
@@ -22,9 +22,132 @@ Follow these steps to conduct a thorough review:
4. Search the codebase if required. 4. Search the codebase if required.
5. Write a concise review of the changes, keeping in mind to encourage strong code quality and best practices. Pay particular attention to the Gemini MD file in the repo. 5. Write a concise review of the changes, keeping in mind to encourage strong code quality and best practices. Pay particular attention to the Gemini MD file in the repo.
6. Consider ways the code may not be consistent with existing code in the repo. In particular it is critical that the react code uses patterns consistent with existing code in the repo. 6. Consider ways the code may not be consistent with existing code in the repo. In particular it is critical that the react code uses patterns consistent with existing code in the repo.
7. Follow these detailed review rules: 7. Evaluate all tests on the changes and make sure that they are doing the following:
!{cat .gemini/commands/strict-development-rules.md} * Using `waitFor` from @{packages/cli/src/test-utils/async.ts} rather than
8. Summarize all actionable findings into a concise but comprehensive directive output this to review_findings.md and advance to phase 2. using `vi.waitFor` for all `waitFor` calls within `packages/cli`. Even if
tests pass, using the wrong `waitFor` could result in flaky tests as `act`
warnings could show up if timing is slightly different.
* Using `act` to wrap all blocks in tests that change component state.
* Using `toMatchSnapshot` to verify that rendering works as expected rather
than matching against the raw content of the output.
* If snapshots were changed as part of the changes, review the snapshots
changes to ensure they are intentional and comment if any look at all
suspicious. Too many snapshot changes that indicate bugs have been approved
in the past.
* Use `render` or `renderWithProviders` from
@{packages/cli/src/test-utils/render.tsx} rather than using `render` from
`ink-testing-library` directly. This is needed to ensure that we do not get
warnings about spurious `act` calls. If test cases specify providers
directly, consider whether the existing `renderWithProviders` should be
modified to support that use case.
* Ensure the test cases are using parameterized tests where that might reduce
the number of duplicated lines significantly.
* NEVER use fixed waits (e.g. 'await delay(100)'). Always use 'waitFor' with
a predicate to ensure tests are stable and fast.
* Ensure mocks are properly managed:
* Critical dependencies (fs, os, child_process) should only be mocked at
the top of the file. Ideally avoid mocking these dependencies altogether.
* Check to see if there are existing mocks or fakes that can be used rather
than creating new ones for the new tests added.
* Try to avoid mocking the file system whenever possible. If using the real
file system is difficult consider whether the test should be an
integration test rather than a unit test.
* `vi.restoreAllMocks()` should be called in `afterEach` to prevent test
pollution.
* Use `vi.useFakeTimers()` for tests involving time-based logic to avoid
flakiness.
* When creating parameterized tests, give the parameters types to ensure
that the tests are type-safe.
8. Evaluate all react logic carefully keeping in mind that the author of the
changes is not likely an expert on React. Key areas to audit carefully are:
* Whether `setState` calls trigger side effects from within the body of the
`setState` callback. If so, you *must* propose an alternate design using
reducers or other ways the code might be modified to not have to modify
state from within a `setState`. Make sure to comment about absolutely
every case like this as these cases have introduced multiple bugs in the
past. Typically these cases should be resolved using a reducer although
occassionally other techniques such as useRef are appropriate. Consider
suggesting that jacob314@ be tagged on the code review if the solution is
not 100% obvious.
* Whether code might introduce an infinite rendering loop in React.
* Whether keyboard handling is robust. Keyboard handling must go through
`useKeyPress.ts` from the Gemini CLI package rather than using the
standard ink library used by most keyboard handling. Unlike the standard
ink library, the keyboard handling library in Gemini CLI may report
multiple keyboard events one after another in the same React frame. This
is needed to support slow terminals but introduces complexity in all our
code that handles keyboard events. Handling this correctly often means
that reducers must be used or other mechanisms to ensure that multiple
state updates one after another are handled gracefully rather than
overriding values from the first update with the second update. Refer to
text-buffer.ts as a canonical example of using a reducer for this sort of
case.
* Ensure code does not use `console.log`, `console.warn`, or `console.error`
as these indicate debug logging that was accidentally left in the code.
* Avoid synchronous file I/O in React components as it will hang the UI.
* Ensure state initialization is explicit (e.g., use 'undefined' rather than
'true' as a default if the state is truly unknown initially).
* Carefully manage 'useEffect' dependencies. Prefer to use a reducer
whenever practical to resolve the issues. If that is not practical it is
ok to use 'useRef' to access the latest value of a prop or state inside an
effect without adding it to the dependency array if re-running the effect
is undesirable (common in event listeners).
* NEVER disable 'react-hooks/exhaustive-deps'. Fix the code to correctly
declare dependencies. Disabling this lint rule will almost always lead to
hard to detect bugs.
* Avoid making types nullable unless strictly necessary, as it hurts
readability.
* Do not introduce excessive property drilling. There are multiple providers
that can be leveraged to avoid property drilling. Make sure one of them
cannot be used. Do suggest a provider that might make sense to be extended
to include the new property or propose a new provider to add if the
property drilling is excessive. Only use providers for properties that are
consistent for the entire application.
9. Evaluate `packages/core` (Services, Tools, Utilities):
* Ensure services are implemented as classes with clear lifecycle management (e.g., `initialize()` methods).
* Verify that `debugLogger` from `packages/core/src/utils/debugLogger.ts` is used 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.
* Check that filesystem errors are handled gracefully using `isNodeError` from `packages/core/src/utils/errors.ts`.
* Verify that new tools are added to `packages/core/src/tools/` and registered in `packages/core/src/tools/tool-registry.ts`.
* Ensure all new public services, utilities, and types are exported from `packages/core/src/index.ts`.
* Check that services are 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.
10. 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 should 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 by using `coreEvents`. If a service is importing another service just to notify it of a change, it should probably be using an event instead.
11. General Gemini CLI design principles:
* Make sure that settings are only used for options that a user might
consider changing.
* Do not add new command line arguments and suggest settings instead.
* New settings must be added 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 for new settings.
* Use 'debugLogger' for rethrown errors to avoid duplicate logging.
* All new keyboard shortcuts MUST be documented in
docs/cli/keyboard-shortcuts.md.
* Ensure new keyboard shortcuts are defined in
packages/cli/src/config/keyBindings.ts.
* If new keyboard shortcuts are added, remind the user to test them in
VSCode, iTerm2, Ghostty, and Windows to ensure they work for all
users.
* Be careful of keybindings that require the meta key as only certain
meta key shortcuts are supported on Mac.
* Be skeptical of function keys and keyboard shortcuts that are commonly
bound in VSCode as they may conflict.
12. 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 and you are confident the value is not null.
* **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. Reject any code that uses 'any' or
'unknown' without narrowing.
13. **Ruthless Cleanup**:
* If you identify significant code duplication, technical debt, or "AI Slop" (boilerplate, redundant comments), explicitly suggest initiating a `ruthless-refactorer` loop to clean it up.
14. Summarize all actionable findings into a concise but comprehensive directive output this to review_findings.md and advance to phase 2.
Remember to use the GitHub CLI (`gh`) for all GitHub-related tasks, and local `git` commands if the target is 'staged'. Remember to use the GitHub CLI (`gh`) for all GitHub-related tasks, and local `git` commands if the target is 'staged'.
+113 -4
View File
@@ -18,12 +18,121 @@ Follow these steps:
8. Consider ways the code may not be consistent with existing code in the repo. 8. Consider ways the code may not be consistent with existing code in the repo.
In particular it is critical that the react code uses patterns consistent In particular it is critical that the react code uses patterns consistent
with existing code in the repo. with existing code in the repo.
9. Follow these detailed review rules: 9. Evaluate all tests on the PR and make sure that they are doing the following:
!{cat .gemini/commands/strict-development-rules.md} * Using `waitFor` from @{packages/cli/src/test-utils/async.ts} rather than
10. Discuss with me before making any comments on the issue. I will clarify using `vi.waitFor` for all `waitFor` calls within `packages/cli`. Even if
tests pass, using the wrong `waitFor` could result in flaky tests as `act`
warnings could show up if timing is slightly different.
* Using `act` to wrap all blocks in tests that change component state.
* Using `toMatchSnapshot` to verify that rendering works as expected rather
than matching against the raw content of the output.
* If snapshots were changed as part of the pull request, review the snapshots
changes to ensure they are intentional and comment if any look at all
suspicious. Too many snapshot changes that indicate bugs have been approved
in the past.
* Use `render` or `renderWithProviders` from
@{packages/cli/src/test-utils/render.tsx} rather than using `render` from
`ink-testing-library` directly. This is needed to ensure that we do not get
warnings about spurious `act` calls. If test cases specify providers
directly, consider whether the existing `renderWithProviders` should be
modified to support that use case.
* Ensure the test cases are using parameterized tests where that might reduce
the number of duplicated lines significantly.
* NEVER use fixed waits (e.g. 'await delay(100)'). Always use 'waitFor' with
a predicate to ensure tests are stable and fast.
* Ensure mocks are properly managed:
* Critical dependencies (fs, os, child_process) should only be mocked at
the top of the file. Ideally avoid mocking these dependencies altogether.
* Check to see if there are existing mocks or fakes that can be used rather
than creating new ones for the new tests added.
* Try to avoid mocking the file system whenever possible. If using the real
file system is difficult consider whether the test should be an
integration test rather than a unit test.
* `vi.restoreAllMocks()` should be called in `afterEach` to prevent test
pollution.
* Use `vi.useFakeTimers()` for tests involving time-based logic to avoid
flakiness.
* Avoid using `any` in tests; prefer proper types or `unknown` with
narrowing.
* When creating parameterized tests, give the parameters types to ensure
that the tests are type-safe.
10. Evaluate all react logic carefully keeping in mind that the author of the PR
is not likely an expert on React. Key areas to audit carefully are:
* Whether `setState` calls trigger side effects from within the body of the
`setState` callback. If so, you *must* propose an alternate design using
reducers or other ways the code might be modified to not have to modify
state from within a `setState`. Make sure to comment about absolutely
every case like this as these cases have introduced multiple bugs in the
past. Typically these cases should be resolved using a reducer although
occassionally other techniques such as useRef are appropriate. Consider
suggesting that jacob314@ be tagged on the code review if the solution is
not 100% obvious.
* Whether code might introduce an infinite rendering loop in React.
* Whether keyboard handling is robust. Keyboard handling must go through
`useKeyPress.ts` from the Gemini CLI package rather than using the
standard ink library used by most keyboard handling. Unlike the standard
ink library, the keyboard handling library in Gemini CLI may report
multiple keyboard events one after another in the same React frame. This
is needed to support slow terminals but introduces complexity in all our
code that handles keyboard events. Handling this correctly often means
that reducers must be used or other mechanisms to ensure that multiple
state updates one after another are handled gracefully rather than
overriding values from the first update with the second update. Refer to
text-buffer.ts as a canonical example of using a reducer for this sort of
case.
* Ensure code does not use `console.log`, `console.warn`, or `console.error`
as these indicate debug logging that was accidentally left in the code.
* Avoid synchronous file I/O in React components as it will hang the UI.
* Ensure state initialization is explicit (e.g., use 'undefined' rather than
'true' as a default if the state is truly unknown initially).
* Carefully manage 'useEffect' dependencies. Prefer to use a reducer
whenever practical to resolve the issues. If that is not practical it is
ok to use 'useRef' to access the latest value of a prop or state inside an
effect without adding it to the dependency array if re-running the effect
is undesirable (common in event listeners).
* NEVER disable 'react-hooks/exhaustive-deps'. Fix the code to correctly
declare dependencies. Disabling this lint rule will almost always lead to
hard to detect bugs.
* Avoid making types nullable unless strictly necessary, as it hurts
readability.
* Do not introduce excessive property drilling. There are multiple providers
that can be leveraged to avoid property drilling. Make sure one of them
cannot be used. Do suggest a provider that might make sense to be extended
to include the new property or propose a new provider to add if the
property drilling is excessive. Only use providers for properties that are
consistent for the entire application.
11. General Gemini CLI design principles:
* Make sure that settings are only used for options that a user might
consider changing.
* Do not add new command line arguments and suggest settings instead.
* New settings must be added 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 for new settings.
* Use 'debugLogger' for rethrown errors to avoid duplicate logging.
* All new keyboard shortcuts MUST be documented in
docs/cli/keyboard-shortcuts.md.
* Ensure new keyboard shortcuts are defined in
packages/cli/src/config/keyBindings.ts.
* If new keyboard shortcuts are added, remind the user to test them in
VSCode, iTerm2, Ghostty, and Windows to ensure they work for all
users.
* Be careful of keybindings that require the meta key as only certain
meta key shortcuts are supported on Mac.
* Be skeptical of function keys and keyboard shortcuts that are commonly
bound in VSCode as they may conflict.
12. 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 and you are confident the value is not null.
13. If the change might at all impact the prompts sent to Gemini CLI, flagged
that the change could impact Gemini CLI quality and make sure anj-s has been
tagged on the code review.
14. Discuss with me before making any comments on the issue. I will clarify
which possible issues you identified are problems, which ones you need to which possible issues you identified are problems, which ones you need to
investigate further, and which ones I do not care about. investigate further, and which ones I do not care about.
11. If I request you to add comments to the issue, use 15. If I request you to add comments to the issue, use
`gh pr comment {{args}} --body {{review}}` to post the review to the PR. `gh pr comment {{args}} --body {{review}}` to post the review to the PR.
Remember to use the GitHub CLI (`gh`) with the Shell tool for all Remember to use the GitHub CLI (`gh`) with the Shell tool for all
@@ -1,142 +0,0 @@
# Gemini CLI Strict Development Rules
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.
## 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`.
## 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`.
## 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.
## 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/ui/key/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.
## 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.
## 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.
-1
View File
@@ -9,5 +9,4 @@ code_review:
help: false help: false
summary: true summary: true
code_review: true code_review: true
include_drafts: false
ignore_patterns: [] ignore_patterns: []
-10
View File
@@ -1,10 +0,0 @@
{
"experimental": {
"plan": true,
"extensionReloading": true,
"modelSteering": true
},
"general": {
"devtools": true
}
}
-166
View File
@@ -1,166 +0,0 @@
---
name: docs-changelog
description: >-
Generates and formats changelog files for a new release based on provided
version and raw changelog data.
---
# Procedure: Updating Changelog for New Releases
## Objective
To standardize the process of updating changelog files (`latest.md`,
`preview.md`, `index.md`) based on automated release information.
## Inputs
- **version**: The release version string (e.g., `v0.28.0`,
`v0.29.0-preview.2`).
- **TIME**: The release timestamp (e.g., `2026-02-12T20:33:15Z`).
- **BODY**: The raw markdown release notes, containing a "What's Changed"
section and a "Full Changelog" link.
## 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
Stable Releases.
- **DO NOT** include PR numbers, links, or author names in these highlights.
- Refer to `.gemini/skills/docs-changelog/references/highlights_examples.md`
for the correct style and tone.
## Initial Processing
1. **Analyze Version**: Determine the release path based on the `version`
string.
- If `version` contains "nightly", **STOP**. No changes are made.
- If `version` ends in `.0`, follow the **Path A: New Minor Version**
procedure.
- If `version` does not end in `.0`, follow the **Path B: Patch Version**
procedure.
2. **Process Time**: Convert the `TIME` input into two formats for later use:
`yyyy-mm-dd` and `Month dd, yyyy`.
3. **Process Body**:
- Save the incoming `BODY` content to a temporary file for processing.
- In the "What's Changed" section of the temporary file, reformat all pull
request URLs to be markdown links with the PR number as the text (e.g.,
`[#12345](URL)`).
- If a "New Contributors" section exists, delete it.
- Preserve the "**Full Changelog**" link. The processed content of this
temporary file will be used in subsequent steps.
---
## Path A: New Minor Version
*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
changelog: a concise **announcement** for the main changelog page, and a more
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.
- Add this new announcement to the top of `docs/changelogs/index.md`.
2. **Create Highlights and Update `latest.md`**:
- Generate a comprehensive "Highlights" section, following the guidelines
in the "Guidelines for `latest.md` and `preview.md` Highlights" section
above.
- Take the content from
`.gemini/skills/docs-changelog/references/latest_template.md`.
- Populate the template with the `version`, `release_date`, generated
`highlights`, and the processed content from the temporary file.
- **Completely replace** the contents of `docs/changelogs/latest.md` with
the populated template.
### A.2: Preview Release (e.g., `v0.29.0-preview.0`)
1. **Update `preview.md`**:
- Generate a comprehensive "Highlights" section, following the highlight
guidelines.
- Take the content from
`.gemini/skills/docs-changelog/references/preview_template.md`.
- Populate the template with the `version`, `release_date`, generated
`highlights`, and the processed content from the temporary file.
- **Completely replace** the contents of `docs/changelogs/preview.md`
with the populated template.
---
## Path B: Patch Version
*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`
### 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`
---
## Finalize
- After making changes, run `npm run format` ONLY to ensure consistency.
- Delete any temporary files created during the process.
@@ -1,68 +0,0 @@
## Highlights example 1
- **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.
## Highlights example 2
- **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.
## Highlights example 3
- **Event-Driven Architecture:** The CLI now uses an event-driven scheduler for
tool execution, improving performance and responsiveness. This includes
migrating non-interactive flows and sub-agents to the new scheduler.
- **Enhanced User Experience:** This release introduces several UI/UX
improvements, including queued tool confirmations and the ability to expand
and collapse large pasted text blocks. The `Settings` dialog has been improved
to reduce jitter and preserve focus.
- **Agent and Skill Improvements:** Agent Skills have been promoted to a stable
feature. Sub-agents now use a JSON schema for input and are tracked by an
`AgentRegistry`.
- **New `/rewind` Command:** A new `/rewind` command has been implemented to
allow users to go back in their session history.
- **Improved Shell and File Handling:** The shell tool's output format has been
optimized, and the CLI now gracefully handles disk-full errors during chat
recording. A bug in detecting already added paths has been fixed.
- **Linux Clipboard Support:** Image pasting capabilities for Wayland and X11 on
Linux have been added.
## Highlights example 4
- **Improved Hooks Management:** Hooks enable/disable functionality now aligns
with skills and offers improved completion.
- **Custom Themes for Extensions:** Extensions can now support custom themes,
allowing for greater personalization.
- **User Identity Display:** User identity information (auth, email, tier) is
now displayed on startup and in the `stats` command.
- **Plan Mode Enhancements:** Plan mode has been improved with a generic
`Checklist` component and refactored `Todo`.
- **Background Shell Commands:** Implementation of background shell commands.
@@ -1,10 +0,0 @@
## Announcements: {{version}} - {{release_date_yyyy_mm_dd}}
{{announcement_content}}
<!-- Example entry, multiple entries per highlights
- **Highlighted Feature:** We've added a new highlighted feature to help
you generate prompt suggestions
([#nnnnn](https://github.com/google-gemini/gemini-cli/pull/nnnnn) by
@author).
-->
@@ -1,20 +0,0 @@
# Latest stable release: {{version}}
Released: {{release_date_month_dd_yyyy}}
For most users, our latest stable release is the recommended release. Install
the latest stable version with:
```
npm install -g @google/gemini-cli
```
## Highlights
{{highlights_content}}
## What's Changed
{{changelog_list}}
**Full Changelog**: {{full_changelog_link}}
@@ -1,22 +0,0 @@
# Preview release: {{version}}
Released: {{release_date_month_dd_yyyy}}
Our preview release includes the latest, new, and experimental features. This
release may not be as stable as our [latest weekly release](latest.md).
To install the preview release:
```
npm install -g @google/gemini-cli@preview
```
## Highlights
{{highlights_content}}
## What's Changed
{{changelog_list}}
**Full Changelog**: {{full_changelog_link}}
+1 -8
View File
@@ -45,10 +45,6 @@ Write precisely to ensure your instructions are unambiguous.
specific verbs. specific verbs.
- **Examples:** Use meaningful names in examples; avoid placeholders like - **Examples:** Use meaningful names in examples; avoid placeholders like
"foo" or "bar." "foo" or "bar."
- **Quota and limit terminology:** For any content involving resource capacity
or using the word "quota" or "limit", strictly adhere to the guidelines in
the `quota-limit-style-guide.md` resource file. Generally, Use "quota" for the
administrative bucket and "limit" for the numerical ceiling.
### Formatting and syntax ### Formatting and syntax
Apply consistent formatting to make documentation visually organized and Apply consistent formatting to make documentation visually organized and
@@ -118,8 +114,6 @@ documentation.
reflects existing code. reflects existing code.
- **Structure:** Apply "Structure (New Docs)" rules (BLUF, headings, etc.) when - **Structure:** Apply "Structure (New Docs)" rules (BLUF, headings, etc.) when
adding new sections to existing pages. adding new sections to existing pages.
- **Headers**: If you change a header, you must check for links that lead to
that header and update them.
- **Tone:** Ensure the tone is active and engaging. Use "you" and contractions. - **Tone:** Ensure the tone is active and engaging. Use "you" and contractions.
- **Clarity:** Correct awkward wording, spelling, and grammar. Rephrase - **Clarity:** Correct awkward wording, spelling, and grammar. Rephrase
sentences to make them easier for users to understand. sentences to make them easier for users to understand.
@@ -135,8 +129,7 @@ and that all links are functional.
technical behavior. technical behavior.
2. **Self-review:** Re-read changes for formatting, correctness, and flow. 2. **Self-review:** Re-read changes for formatting, correctness, and flow.
3. **Link check:** Verify all new and existing links leading to or from modified 3. **Link check:** Verify all new and existing links leading to or from modified
pages. If you changed a header, ensure that any links that lead to it are pages.
updated.
4. **Format:** Once all changes are complete, ask to execute `npm run format` 4. **Format:** Once all changes are complete, ask to execute `npm run format`
to ensure consistent formatting across the project. If the user confirms, to ensure consistent formatting across the project. If the user confirms,
execute the command. execute the command.
@@ -1,61 +0,0 @@
# Style Guide: Quota vs. Limit
This guide defines the usage of "quota," "limit," and related terms in
user-facing interfaces.
## TL;DR
- **`quota`**: The administrative "bucket." Use for settings, billing, and
requesting increases. (e.g., "Adjust your storage **quota**.")
- **`limit`**: The real-time numerical "ceiling." Use for error messages when a
user is blocked. (e.g., "You've reached your request **limit**.")
- **When blocked, combine them:** Explain the **limit** that was hit and the
**quota** that is the remedy. (e.g., "You've reached the request **limit** for
your developer **quota**.")
- **Related terms:** Use `usage` for consumption tracking, `restriction` for
fixed rules, and `reset` for when a limit refreshes.
---
## Detailed Guidelines
### Definitions
- **Quota is the "what":** It identifies the category of resource being managed
(e.g., storage quota, GPU quota, request/prompt quota).
- **Limit is the "how much":** It defines the numerical boundary.
Use **quota** when referring to the administrative concept or the request for
more. Use **limit** when discussing the specific point of exhaustion.
### When to use "quota"
Use this term for **account management, billing, and settings.** It describes
the entitlement the user has purchased or been assigned.
**Examples:**
- **Navigation label:** Quota and usage
- **Contextual help:** Your **usage quota** is managed by your organization. To
request an increase, contact your administrator.
### When to use "limit"
Use this term for **real-time feedback, notifications, and error messages.** It
identifies the specific wall the user just hit.
**Examples:**
- **Error message:** Youve reached the 50-request-per-minute **limit**.
- **Inline warning:** Input exceeds the 32k token **limit**.
### How to use both together
When a user is blocked, combine both terms to explain the **event** (limit) and
the **remedy** (quota).
**Example:**
- **Heading:** Daily usage limit reached
- **Body:** You've reached the maximum daily capacity for your developer quota.
To continue working today, upgrade your quota.
@@ -1,76 +0,0 @@
---
name: github-issue-creator
description:
Use this skill when asked to create a GitHub issue. It handles different issue
types (bug, feature, etc.) using repository templates and ensures proper
labeling.
---
# GitHub Issue Creator
This skill guides the creation of high-quality GitHub issues that adhere to the
repository's standards and use the appropriate templates.
## Workflow
Follow these steps to create a GitHub issue:
1. **Identify Issue Type**: Determine if the request is a bug report, feature
request, or other category.
2. **Locate Template**: Search for issue templates in
`.github/ISSUE_TEMPLATE/`.
- `bug_report.yml`
- `feature_request.yml`
- `website_issue.yml`
- If no relevant YAML template is found, look for `.md` templates in the same
directory.
3. **Read Template**: Read the content of the identified template file to
understand the required fields.
4. **Draft Content**: Draft the issue title and body/fields.
- If using a YAML template (form), prepare values for each `id` defined in
the template.
- If using a Markdown template, follow its structure exactly.
- **Default Label**: Always include the `🔒 maintainer only` label unless the
user explicitly requests otherwise.
5. **Create Issue**: Use the `gh` CLI to create the issue.
- **CRITICAL:** To avoid shell escaping and formatting issues with
multi-line Markdown or complex text, ALWAYS write the description/body to
a temporary file first.
**For Markdown Templates or Simple Body:**
```bash
# 1. Write the drafted content to a temporary file
# 2. Create the issue using the --body-file flag
gh issue create --title "Succinct title" --body-file <temp_file_path> --label "🔒 maintainer only"
# 3. Remove the temporary file
rm <temp_file_path>
```
**For YAML Templates (Forms):**
While `gh issue create` supports `--body-file`, YAML forms usually expect
key-value pairs via flags if you want to bypass the interactive prompt.
However, the most reliable non-interactive way to ensure formatting is
preserved for long text fields is to use the `--body` or `--body-file` if the
form has been converted to a standard body, OR to use the `--field` flags
for YAML forms.
*Note: For the `gemini-cli` repository which uses YAML forms, you can often
submit the content as a single body if a specific field-based submission is
not required by the automation.*
6. **Verify**: Confirm the issue was created successfully and provide the link
to the user.
## Principles
- **Clarity**: Titles should be descriptive and follow project conventions.
- **Defensive Formatting**: Always use temporary files with `--body-file` to
prevent newline and special character issues.
- **Maintainer Priority**: Default to internal/maintainer labels to keep the
backlog organized.
- **Completeness**: Provide all requested information (e.g., version info,
reproduction steps).
@@ -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);
});
+9 -29
View File
@@ -14,34 +14,25 @@ repository's standards.
Follow these steps to create a Pull Request: Follow these steps to create a Pull Request:
1. **Branch Management**: **CRITICAL:** Ensure you are NOT working on the 1. **Branch Management**: Check the current branch to avoid working directly
`main` branch. on `main`.
- Run `git branch --show-current`. - Run `git branch --show-current`.
- If the current branch is `main`, you MUST create and switch to a new - If the current branch is `main`, create and switch to a new descriptive
descriptive branch: branch:
```bash ```bash
git checkout -b <new-branch-name> git checkout -b <new-branch-name>
``` ```
2. **Commit Changes**: Verify that all intended changes are committed. 2. **Locate Template**: Search for a pull request template in the repository.
- Run `git status` to check for unstaged or uncommitted changes.
- If there are uncommitted changes, stage and commit them with a descriptive
message before proceeding. NEVER commit directly to `main`.
```bash
git add .
git commit -m "type(scope): description"
```
3. **Locate Template**: Search for a pull request template in the repository.
- Check `.github/pull_request_template.md` - Check `.github/pull_request_template.md`
- Check `.github/PULL_REQUEST_TEMPLATE.md` - Check `.github/PULL_REQUEST_TEMPLATE.md`
- If multiple templates exist (e.g., in `.github/PULL_REQUEST_TEMPLATE/`), - If multiple templates exist (e.g., in `.github/PULL_REQUEST_TEMPLATE/`),
ask the user which one to use or select the most appropriate one based on ask the user which one to use or select the most appropriate one based on
the context (e.g., `bug_fix.md` vs `feature.md`). the context (e.g., `bug_fix.md` vs `feature.md`).
4. **Read Template**: Read the content of the identified template file. 3. **Read Template**: Read the content of the identified template file.
5. **Draft Description**: Create a PR description that strictly follows the 4. **Draft Description**: Create a PR description that strictly follows the
template's structure. template's structure.
- **Headings**: Keep all headings from the template. - **Headings**: Keep all headings from the template.
- **Checklists**: Review each item. Mark with `[x]` if completed. If an item - **Checklists**: Review each item. Mark with `[x]` if completed. If an item
@@ -53,24 +44,14 @@ Follow these steps to create a Pull Request:
- **Related Issues**: Link any issues fixed or related to this PR (e.g., - **Related Issues**: Link any issues fixed or related to this PR (e.g.,
"Fixes #123"). "Fixes #123").
6. **Preflight Check**: Before creating the PR, run the workspace preflight 5. **Preflight Check**: Before creating the PR, run the workspace preflight
script to ensure all build, lint, and test checks pass. script to ensure all build, lint, and test checks pass.
```bash ```bash
npm run preflight npm run preflight
``` ```
If any checks fail, address the issues before proceeding to create the PR. If any checks fail, address the issues before proceeding to create the PR.
7. **Push Branch**: Push the current branch to the remote repository. 6. **Create PR**: Use the `gh` CLI to create the PR. To avoid shell escaping
**CRITICAL SAFETY RAIL:** Double-check your branch name before pushing.
NEVER push if the current branch is `main`.
```bash
# Verify current branch is NOT main
git branch --show-current
# Push non-interactively
git push -u origin HEAD
```
8. **Create PR**: Use the `gh` CLI to create the PR. To avoid shell escaping
issues with multi-line Markdown, write the description to a temporary file issues with multi-line Markdown, write the description to a temporary file
first. first.
```bash ```bash
@@ -87,7 +68,6 @@ Follow these steps to create a Pull Request:
## Principles ## Principles
- **Safety First**: NEVER push to `main`. This is your highest priority.
- **Compliance**: Never ignore the PR template. It exists for a reason. - **Compliance**: Never ignore the PR template. It exists for a reason.
- **Completeness**: Fill out all relevant sections. - **Completeness**: Fill out all relevant sections.
- **Accuracy**: Don't check boxes for tasks you haven't done. - **Accuracy**: Don't check boxes for tasks you haven't done.
-99
View File
@@ -1,99 +0,0 @@
---
name: string-reviewer
description: >
Use this skill when asked to review text and user-facing strings within the codebase. It ensures that these strings follow rules on clarity,
usefulness, brevity and style.
---
# String Reviewer
## Instructions
Act as a Senior UX Writer. Look for user-facing strings that are too long,
unclear, or inconsistent. This includes inline text, error messages, and other
user-facing text.
Do NOT automatically change strings without user approval. You must only suggest
changes and do not attempt to rewrite them directly unless the user explicitly
asks you to do so.
## Core voice principles
The system prioritizes deterministic clarity over conversational fluff. We
provide telemetry, not etiquette, ensuring the user retains absolute agency..
1. **Deterministic clarity:** Distinguish between certain system/service states
(Cloud Billing, IAM, the System) and probabilistic AI analysis (Gemini).
2. **System transparency:** Replace "Loading..." with active technical telemetry
(e.g., Tracing stack traces...). Keep status updates under 5 words.
3. **Front-loaded actionability:** Always use the [Goal] + [Action] pattern.
Lead with intent so users can scan left-to-right.
4. **Agentic error recovery:** Every error must be a pivot point. Pair failures
with one-click recovery commands or suggested prompts.
5. **Contextual humility:** Reserve disclaimers and "be careful" warnings for P0
(destructive/irreversible) tasks only. Stop warning-fatigue.
## The writing checklist
Use this checklist to audit UI strings and AI responses.
### Identity and voice
- **Eliminate the "I":** Remove all first-person pronouns (I, me, my, mine).
- **Subject attribution:** Refer to the AI as Gemini and the infrastructure as
the - system or the CLI.
- **Active voice:** Ensure the subject (Gemini or the system) is clearly
performing the action.
- **Ownership rule:** Use the system for execution (doing) and Gemini for
analysis (thinking)
### Structural scannability
- **The skip test:** Do the first 3 words describe the users intent? If not,
rewrite.
- **Goal-first sequence:** Use the template: [To Accomplish X] + [Do Y].
- **The 5-word rule:** Keep status updates and loading states under 5 words.
- **Telemetry over etiquette:** Remove polite filler (Please wait, Thank you,
Certainly). Replace with raw data or progress indicators.
- **Micro-state cycles:** For tasks $> 3$ seconds, cycle through specific
sub-states (e.g., Parsing logs... ➔ Identifying patterns...) to show momentum.
### Technical accuracy and humility
- **Verb signal check:** Use deterministic verbs (is, will, must) for system
state/infrastructure.
- Use probabilistic verbs (suggests, appears, may, identifies) for AI output.
- **No 100% certainty:** Never attribute absolute certainty to model-generated
content.
- **Precision over fuzziness:** Use technical metrics (latency, tokens, compute) instead of "speed" or "cost."
- **Instructional warnings:** Every warning must include a specific corrective action (e.g., "Perform a dry-run first" or "Review line 42").
### Agentic error recovery
- **The one-step rule:** Pair every error message with exactly one immediate
path to a fix (command, link, or prompt).
- **Human-first:** Provide a human-readable explanation before machine error
codes (e.g., 404, 500).
- **Suggested prompts:** Offer specific text for the user to copy/click like
“Ask Gemini: 'Explain this port error.'”
### Use consistent terminology
Ensure all terminology aligns with the project [word
list](./references/word-list.md).
If a string uses a term marked "do not use" or "use with caution," provide a
correction based on the preferred terms.
## Ensure consistent style for settings
If `packages/cli/src/config/settingsSchema.ts` is modified, confirm labels and
descriptions specifically follow the unique [Settings
guidelines](./references/settings.md).
## Output format
When suggesting changes, always present your review using the following list
format. Do not provide suggestions outside of this list..
```
1. **{Rationale/Principle Violated}**
- ❌ "{incorrect phrase}"
- ✅ `"{corrected phrase}"`
```
@@ -1,28 +0,0 @@
# Settings
## Noun-First Labeling (Scannability)
Labels must start with the subject of the setting, not the action. This allows
users to scan for the feature they want to change.
- **Rule:** `[Noun]` `[Attribute/Action]`
- **Example:** `Show line numbers` becomes simply `Line numbers`
## Positive Boolean Logic (Cognitive Ease)
Eliminate "double negatives." Booleans should represent the presence of a
feature, not its absence.
- **Rule:** Replace `Disable {feature}` or `Hide {Feature}` with
`{Feature} enabled` or simply `{Feature}`.
- **Example:** Change "Disable auto update" to "Auto update".
- **Implementation:** Invert the boolean value in your config loader so true
always equals `On`
## Verb Stripping (Brevity)
Remove redundant leading verbs like "Enable," "Use," "Display," or "Show" unless
they are part of a specific technical term.
- **Rule**: If the label works without the verb, remove it
- **Example**: Change `Enable prompt completion` to `Prompt completion`
@@ -1,61 +0,0 @@
## Terms
### Preferred
- Use **create** when a user is creating or setting up something.
- Use **allow** instead of **may** to indicate that permission has been granted
to perform some action.
- Use **canceled**, not **cancelled**.
- Use **configure** to refer to the process of changing the attributes of a
feature, even if that includes turning on or off the feature.
- Use **delete** when the action being performed is destructive.
- Use **enable** for binary operations that turn a feature or API on. Use "turn
on" and "turn off" instead of "enable" and "disable" for other situations.
- Use **key combination** to refer to pressing multiple keys simultaneously.
- Use **key sequence** to refer to pressing multiple keys separately in order.
- Use **modify** to refer to something that has changed vs obtaining the latest
version of something.
- Use **remove** when the action being performed takes an item out of a larger
whole, but doesn't destroy the item itself.
- Use **set up** as a verb. Use **setup** as a noun or adjective.
- Use **show**. In general, use paired with **hide**.
- Use **sign in**, **sign out** as a verb. Use **sign-in** or **sign-out** as a
noun or adjective.
- Use **update** when you mean to obtain the latest version of something.
- Use **want** instead of **like** or **would like**.
#### Don't use
- Don't use **etc.** It's redundant. To convey that a series is incomplete,
introduce it with "such as" instead.
- Don't use **hostname**, use "host name" instead.
- Don't use **in order to**. It's too formal. "Before you can" is usually better
in UI text.
- Don't use **one or more**. Specify the quantity where possible. Use "at least
one" when the quantity is 1+ but you can't be sure of the number. Likewise,
use "at least one" when the user must choose a quantity of 1+.
- Don't use the terms **log in**, **log on**, **login**, **logout** or **log
out**.
- Don't use **like** or **would you like**. Use **want** instead. Better yet,
rephrase so that it's not referring to the user's emotional state, but rather
what is required.
#### Use with caution
- Avoid using **leverage**, especially as a verb. "Leverage" is considered a
buzzword largely devoid of meaning apart from the simpler "use".
- Avoid using **once** as a synonym for "after". Typically, when "once" is used
in this way, it is followed by a verb in the perfect tense.
- Don't use **e.g.** Use "example", "such as", "like", or "for example". The
phrase is always followed by a comma.
- Don't use **i.e.** unless absolutely essential to make text fit. Use "that is"
instead.
- Use **disable** for binary operations that turn a feature or API off. Use
"turn on" and "turn off" instead of "enable" and "disable" for other
situations. For UI elements that are not available, use "dimmed" instead of
"disabled".
- Use **please** only when you're asking the user to do something inconvenient,
not just following the instructions in a typical flow.
- Use **really** sparingly in such constructions as "Do you really want to..."
Because of the weight it puts on the decision, it should be used to confirm
actions that the user is extremely unlikely to make.
-6
View File
@@ -14,9 +14,3 @@
# Docs have a dedicated approver group in addition to maintainers # Docs have a dedicated approver group in addition to maintainers
/docs/ @google-gemini/gemini-cli-maintainers @google-gemini/gemini-cli-docs /docs/ @google-gemini/gemini-cli-maintainers @google-gemini/gemini-cli-docs
/README.md @google-gemini/gemini-cli-maintainers @google-gemini/gemini-cli-docs
# Prompt contents, tool definitions, and evals require reviews from prompt approvers
/packages/core/src/prompts/ @google-gemini/gemini-cli-prompt-approvers
/packages/core/src/tools/ @google-gemini/gemini-cli-prompt-approvers
/evals/ @google-gemini/gemini-cli-prompt-approvers
+6 -10
View File
@@ -39,22 +39,18 @@ runs:
if: "inputs.dry-run != 'true'" if: "inputs.dry-run != 'true'"
env: env:
GH_TOKEN: '${{ inputs.github-token }}' 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' shell: 'bash'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: | run: |
set -e set -e
if ! git ls-remote --exit-code --heads origin "${INPUTS_BRANCH_NAME}"; then 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." echo "::error::Branch '${{ inputs.branch-name }}' does not exist on the remote repository."
exit 1 exit 1
fi fi
PR_URL=$(gh pr create \ PR_URL=$(gh pr create \
--title "${INPUTS_PR_TITLE}" \ --title "${{ inputs.pr-title }}" \
--body "${INPUTS_PR_BODY}" \ --body "${{ inputs.pr-body }}" \
--base "${INPUTS_BASE_BRANCH}" \ --base "${{ inputs.base-branch }}" \
--head "${INPUTS_BRANCH_NAME}" \ --head "${{ inputs.branch-name }}" \
--fill) --fill)
gh pr merge "$PR_URL" --auto gh pr merge "$PR_URL" --auto
+6 -12
View File
@@ -30,22 +30,16 @@ runs:
id: 'npm_auth_token' id: 'npm_auth_token'
shell: 'bash' shell: 'bash'
run: | run: |
AUTH_TOKEN="${INPUTS_GITHUB_TOKEN}" AUTH_TOKEN="${{ inputs.github-token }}"
PACKAGE_NAME="${INPUTS_PACKAGE_NAME}" PACKAGE_NAME="${{ inputs.package-name }}"
PRIVATE_REPO="@google-gemini/" PRIVATE_REPO="@google-gemini/"
if [[ "$PACKAGE_NAME" == "$PRIVATE_REPO"* ]]; then if [[ "$PACKAGE_NAME" == "$PRIVATE_REPO"* ]]; then
AUTH_TOKEN="${INPUTS_GITHUB_TOKEN}" AUTH_TOKEN="${{ inputs.github-token }}"
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli" ]]; then 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 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 elif [[ "$PACKAGE_NAME" == "@google/gemini-cli-a2a-server" ]]; then
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_A2A_SERVER}" AUTH_TOKEN="${{ inputs.wombat-token-a2a-server }}"
fi fi
echo "auth-token=$AUTH_TOKEN" >> $GITHUB_OUTPUT 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 }}'
+21 -52
View File
@@ -20,9 +20,6 @@ inputs:
github-token: github-token:
description: 'The GitHub token for creating the release.' description: 'The GitHub token for creating the release.'
required: true required: true
github-release-token:
description: 'The GitHub token used specifically for creating the GitHub release (to trigger other workflows).'
required: false
dry-run: dry-run:
description: 'Whether to run in dry-run mode.' description: 'Whether to run in dry-run mode.'
type: 'string' type: 'string'
@@ -93,19 +90,15 @@ runs:
id: 'release_branch' id: 'release_branch'
shell: 'bash' shell: 'bash'
run: | run: |
BRANCH_NAME="release/${INPUTS_RELEASE_TAG}" BRANCH_NAME="release/${{ inputs.release-tag }}"
git switch -c "${BRANCH_NAME}" git switch -c "${BRANCH_NAME}"
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}" echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
env:
INPUTS_RELEASE_TAG: '${{ inputs.release-tag }}'
- name: '⬆️ Update package versions' - name: '⬆️ Update package versions'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
shell: 'bash' shell: 'bash'
run: | run: |
npm run release:version "${INPUTS_RELEASE_VERSION}" npm run release:version "${{ inputs.release-version }}"
env:
INPUTS_RELEASE_VERSION: '${{ inputs.release-version }}'
- name: '💾 Commit and Conditionally Push package versions' - name: '💾 Commit and Conditionally Push package versions'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
@@ -167,37 +160,23 @@ runs:
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
env: env:
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}' 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' shell: 'bash'
run: | run: |
npm publish \ npm publish \
--dry-run="${INPUTS_DRY_RUN}" \ --dry-run="${{ inputs.dry-run }}" \
--workspace="${INPUTS_CORE_PACKAGE_NAME}" \ --workspace="${{ inputs.core-package-name }}" \
--no-tag --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' - name: '🔗 Install latest core package'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
if: "${{ inputs.dry-run != 'true' }}" if: "${{ inputs.dry-run != 'true' }}"
shell: 'bash' shell: 'bash'
run: | run: |
npm install "${INPUTS_CORE_PACKAGE_NAME}@${INPUTS_RELEASE_VERSION}" \ npm install "${{ inputs.core-package-name }}@${{ inputs.release-version }}" \
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \ --workspace="${{ inputs.cli-package-name }}" \
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \ --workspace="${{ inputs.a2a-package-name }}" \
--save-exact --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: '📦 Prepare bundled CLI for npm release'
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/' && inputs.npm-tag != 'latest'"
working-directory: '${{ inputs.working-directory }}'
shell: 'bash'
run: |
node ${{ github.workspace }}/scripts/prepare-npm-release.js
- name: 'Get CLI Token' - name: 'Get CLI Token'
uses: './.github/actions/npm-auth-token' uses: './.github/actions/npm-auth-token'
@@ -213,15 +192,13 @@ runs:
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
env: env:
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}' 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' shell: 'bash'
run: | run: |
npm publish \ npm publish \
--dry-run="${INPUTS_DRY_RUN}" \ --dry-run="${{ inputs.dry-run }}" \
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \ --workspace="${{ inputs.cli-package-name }}" \
--no-tag --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' - name: 'Get a2a-server Token'
uses: './.github/actions/npm-auth-token' uses: './.github/actions/npm-auth-token'
@@ -237,16 +214,14 @@ runs:
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
env: env:
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}' 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' shell: 'bash'
# Tag staging for initial release # Tag staging for initial release
run: | run: |
npm publish \ npm publish \
--dry-run="${INPUTS_DRY_RUN}" \ --dry-run="${{ inputs.dry-run }}" \
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \ --workspace="${{ inputs.a2a-package-name }}" \
--no-tag --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' - name: '🔬 Verify NPM release by version'
uses: './.github/actions/verify-release' uses: './.github/actions/verify-release'
@@ -279,17 +254,14 @@ runs:
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' && inputs.npm-registry-url != 'https://npm.pkg.github.com/' }}" if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' && inputs.npm-registry-url != 'https://npm.pkg.github.com/' }}"
env: env:
GITHUB_TOKEN: '${{ inputs.github-release-token || inputs.github-token }}' GITHUB_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' shell: 'bash'
run: | run: |
gh release create "${INPUTS_RELEASE_TAG}" \ gh release create "${{ inputs.release-tag }}" \
bundle/gemini.js \ bundle/gemini.js \
--target "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}" \ --target "${{ steps.release_branch.outputs.BRANCH_NAME }}" \
--title "Release ${INPUTS_RELEASE_TAG}" \ --title "Release ${{ inputs.release-tag }}" \
--notes-start-tag "${INPUTS_PREVIOUS_TAG}" \ --notes-start-tag "${{ inputs.previous-tag }}" \
--generate-notes \ --generate-notes \
${{ inputs.npm-tag != 'latest' && '--prerelease' || '' }} ${{ inputs.npm-tag != 'latest' && '--prerelease' || '' }}
@@ -299,8 +271,5 @@ runs:
continue-on-error: true continue-on-error: true
shell: 'bash' shell: 'bash'
run: | run: |
echo "Cleaning up release branch ${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}" git push origin --delete "${{ steps.release_branch.outputs.BRANCH_NAME }}"
env:
STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
+1 -3
View File
@@ -52,10 +52,8 @@ runs:
id: 'branch_name' id: 'branch_name'
shell: 'bash' shell: 'bash'
run: | run: |
REF_NAME="${INPUTS_REF_NAME}" REF_NAME="${{ inputs.ref-name }}"
echo "name=${REF_NAME%/merge}" >> $GITHUB_OUTPUT echo "name=${REF_NAME%/merge}" >> $GITHUB_OUTPUT
env:
INPUTS_REF_NAME: '${{ inputs.ref-name }}'
- name: 'Build and Push the Docker Image' - name: 'Build and Push the Docker Image'
uses: 'docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83' # ratchet:docker/build-push-action@v6 uses: 'docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83' # ratchet:docker/build-push-action@v6
with: with:
+4 -27
View File
@@ -44,8 +44,6 @@ runs:
- name: 'npm build' - name: 'npm build'
shell: 'bash' shell: 'bash'
run: 'npm run build' run: 'npm run build'
- name: 'Set up QEMU'
uses: 'docker/setup-qemu-action@v3'
- name: 'Set up Docker Buildx' - name: 'Set up Docker Buildx'
uses: 'docker/setup-buildx-action@v3' uses: 'docker/setup-buildx-action@v3'
- name: 'Log in to GitHub Container Registry' - name: 'Log in to GitHub Container Registry'
@@ -58,8 +56,8 @@ runs:
id: 'image_tag' id: 'image_tag'
shell: 'bash' shell: 'bash'
run: |- run: |-
SHELL_TAG_NAME="${INPUTS_GITHUB_REF_NAME}" SHELL_TAG_NAME="${{ inputs.github-ref-name }}"
FINAL_TAG="${INPUTS_GITHUB_SHA}" FINAL_TAG="${{ inputs.github-sha }}"
if [[ "$SHELL_TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then if [[ "$SHELL_TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
echo "Release detected." echo "Release detected."
FINAL_TAG="${SHELL_TAG_NAME#v}" FINAL_TAG="${SHELL_TAG_NAME#v}"
@@ -68,43 +66,22 @@ runs:
fi fi
echo "Determined image tag: $FINAL_TAG" echo "Determined image tag: $FINAL_TAG"
echo "FINAL_TAG=$FINAL_TAG" >> $GITHUB_OUTPUT echo "FINAL_TAG=$FINAL_TAG" >> $GITHUB_OUTPUT
env:
INPUTS_GITHUB_REF_NAME: '${{ inputs.github-ref-name }}'
INPUTS_GITHUB_SHA: '${{ inputs.github-sha }}'
# We build amd64 just so we can verify it.
# We build and push both amd64 and arm64 in the publish step.
- name: 'build' - name: 'build'
id: 'docker_build' id: 'docker_build'
shell: 'bash' shell: 'bash'
env: env:
GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}' GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
GEMINI_SANDBOX: 'docker' GEMINI_SANDBOX: 'docker'
BUILD_SANDBOX_FLAGS: '--platform linux/amd64 --load'
STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
run: |- run: |-
npm run build:sandbox -- \ 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 --output-file final_image_uri.txt
echo "uri=$(cat final_image_uri.txt)" >> $GITHUB_OUTPUT 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' - name: 'publish'
shell: 'bash' shell: 'bash'
if: "${{ inputs.dry-run != 'true' }}" if: "${{ inputs.dry-run != 'true' }}"
env:
GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
GEMINI_SANDBOX: 'docker'
BUILD_SANDBOX_FLAGS: '--platform linux/amd64,linux/arm64 --push'
STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
run: |- run: |-
npm run build:sandbox -- \ docker push "${{ steps.docker_build.outputs.uri }}"
--image "google/gemini-cli-sandbox:${STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG}"
- name: 'Create issue on failure' - name: 'Create issue on failure'
if: |- if: |-
${{ failure() }} ${{ failure() }}
+1 -3
View File
@@ -18,7 +18,5 @@ runs:
shell: 'bash' shell: 'bash'
run: |- run: |-
echo ""@google-gemini:registry=https://npm.pkg.github.com"" > ~/.npmrc 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 echo ""@google:registry=https://wombat-dressing-room.appspot.com"" >> ~/.npmrc
env:
INPUTS_GITHUB_TOKEN: '${{ inputs.github-token }}'
+4 -24
View File
@@ -71,13 +71,10 @@ runs:
${{ inputs.dry-run != 'true' }} ${{ inputs.dry-run != 'true' }}
env: env:
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}' 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' shell: 'bash'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: | 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' - name: 'Get cli Token'
uses: './.github/actions/npm-auth-token' uses: './.github/actions/npm-auth-token'
@@ -94,13 +91,10 @@ runs:
${{ inputs.dry-run != 'true' }} ${{ inputs.dry-run != 'true' }}
env: env:
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}' 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' shell: 'bash'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: | 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' - name: 'Get a2a Token'
uses: './.github/actions/npm-auth-token' uses: './.github/actions/npm-auth-token'
@@ -117,13 +111,10 @@ runs:
${{ inputs.dry-run == 'false' }} ${{ inputs.dry-run == 'false' }}
env: env:
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}' 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' shell: 'bash'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: | 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' - name: 'Log dry run'
if: |- if: |-
@@ -131,15 +122,4 @@ runs:
shell: 'bash' shell: 'bash'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: | 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}." 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 }}'
+5 -11
View File
@@ -64,13 +64,10 @@ runs:
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: |- run: |-
gemini_version=$(gemini --version) gemini_version=$(gemini --version)
if [ "$gemini_version" != "${INPUTS_EXPECTED_VERSION}" ]; then if [ "$gemini_version" != "${{ inputs.expected-version }}" ]; then
echo "❌ NPM Version mismatch: Got $gemini_version from ${INPUTS_NPM_PACKAGE}, expected ${INPUTS_EXPECTED_VERSION}" echo "❌ NPM Version mismatch: Got $gemini_version from ${{ inputs.npm-package }}, expected ${{ inputs.expected-version }}"
exit 1 exit 1
fi fi
env:
INPUTS_EXPECTED_VERSION: '${{ inputs.expected-version }}'
INPUTS_NPM_PACKAGE: '${{ inputs.npm-package }}'
- name: 'Clear npm cache' - name: 'Clear npm cache'
shell: 'bash' shell: 'bash'
@@ -80,14 +77,11 @@ runs:
shell: 'bash' shell: 'bash'
working-directory: '${{ inputs.working-directory }}' working-directory: '${{ inputs.working-directory }}'
run: |- run: |-
gemini_version=$(npx --prefer-online "${INPUTS_NPM_PACKAGE}" --version) gemini_version=$(npx --prefer-online "${{ inputs.npm-package}}" --version)
if [ "$gemini_version" != "${INPUTS_EXPECTED_VERSION}" ]; then if [ "$gemini_version" != "${{ inputs.expected-version }}" ]; then
echo "❌ NPX Run Version mismatch: Got $gemini_version from ${INPUTS_NPM_PACKAGE}, expected ${INPUTS_EXPECTED_VERSION}" echo "❌ NPX Run Version mismatch: Got $gemini_version from ${{ inputs.npm-package }}, expected ${{ inputs.expected-version }}"
exit 1 exit 1
fi fi
env:
INPUTS_NPM_PACKAGE: '${{ inputs.npm-package }}'
INPUTS_EXPECTED_VERSION: '${{ inputs.expected-version }}'
- name: 'Install dependencies for integration tests' - name: 'Install dependencies for integration tests'
shell: 'bash' shell: 'bash'
+1 -1
View File
@@ -22,7 +22,7 @@ get_issue_labels() {
# Check cache # Check cache
case "${ISSUE_LABELS_CACHE_FLAT}" in case "${ISSUE_LABELS_CACHE_FLAT}" in
*"|${ISSUE_NUM}:"*) *"|${ISSUE_NUM}:"*)
local suffix="${ISSUE_LABELS_CACHE_FLAT#*|"${ISSUE_NUM}":}" local suffix="${ISSUE_LABELS_CACHE_FLAT#*|${ISSUE_NUM}:}"
echo "${suffix%%|*}" echo "${suffix%%|*}"
return return
;; ;;
+2 -36
View File
@@ -1,9 +1,5 @@
/** /* eslint-disable @typescript-eslint/no-require-imports */
* @license /* global process, console, require */
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
const { Octokit } = require('@octokit/rest'); const { Octokit } = require('@octokit/rest');
/** /**
@@ -347,36 +343,6 @@ async function run() {
}); });
} }
} }
// Remove status/need-triage from maintainer-only issues since they
// don't need community triage. We always attempt removal rather than
// checking the (potentially stale) label snapshot, because the
// issue-opened-labeler workflow runs concurrently and may add the
// label after our snapshot was taken.
if (isDryRun) {
console.log(
`[DRY RUN] Would remove status/need-triage from ${issueKey}`,
);
} else {
try {
await octokit.rest.issues.removeLabel({
owner: issueInfo.owner,
repo: issueInfo.repo,
issue_number: issueInfo.number,
name: 'status/need-triage',
});
console.log(`Removed status/need-triage from ${issueKey}`);
} catch (removeError) {
// 404 means the label wasn't present — that's fine.
if (removeError.status === 404) {
console.log(
`status/need-triage not present on ${issueKey}, skipping.`,
);
} else {
throw removeError;
}
}
}
} catch (error) { } catch (error) {
console.error(`Error processing label for ${issueKey}: ${error.message}`); console.error(`Error processing label for ${issueKey}: ${error.message}`);
} }
+17 -52
View File
@@ -31,7 +31,6 @@ jobs:
name: 'Merge Queue Skipper' name: 'Merge Queue Skipper'
permissions: 'read-all' permissions: 'read-all'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
outputs: outputs:
skip: '${{ steps.merge-queue-e2e-skipper.outputs.skip-check }}' skip: '${{ steps.merge-queue-e2e-skipper.outputs.skip-check }}'
steps: steps:
@@ -43,7 +42,7 @@ jobs:
download_repo_name: download_repo_name:
runs-on: 'gemini-cli-ubuntu-16-core' 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: outputs:
repo_name: '${{ steps.output-repo-name.outputs.repo_name }}' repo_name: '${{ steps.output-repo-name.outputs.repo_name }}'
head_sha: '${{ steps.output-repo-name.outputs.head_sha }}' head_sha: '${{ steps.output-repo-name.outputs.head_sha }}'
@@ -54,7 +53,7 @@ jobs:
REPO_NAME: '${{ github.event.inputs.repo_name }}' REPO_NAME: '${{ github.event.inputs.repo_name }}'
run: | run: |
mkdir -p ./pr 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 - uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with: with:
name: 'repo_name' name: 'repo_name'
@@ -92,7 +91,7 @@ jobs:
name: 'Parse run context' name: 'Parse run context'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
needs: 'download_repo_name' needs: 'download_repo_name'
if: "github.repository == 'google-gemini/gemini-cli' && always()" if: 'always()'
outputs: outputs:
repository: '${{ steps.set_context.outputs.REPO }}' repository: '${{ steps.set_context.outputs.REPO }}'
sha: '${{ steps.set_context.outputs.SHA }}' sha: '${{ steps.set_context.outputs.SHA }}'
@@ -112,11 +111,11 @@ jobs:
permissions: 'write-all' permissions: 'write-all'
needs: needs:
- 'parse_run_context' - 'parse_run_context'
if: "github.repository == 'google-gemini/gemini-cli' && always()" if: 'always()'
steps: steps:
- name: 'Set pending status' - name: 'Set pending status'
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master 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: with:
allowForks: 'true' allowForks: 'true'
repo: '${{ github.repository }}' repo: '${{ github.repository }}'
@@ -132,7 +131,7 @@ jobs:
- 'parse_run_context' - 'parse_run_context'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
if: | 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: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -185,7 +184,7 @@ jobs:
- 'parse_run_context' - 'parse_run_context'
runs-on: 'macos-latest' runs-on: 'macos-latest'
if: | 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: steps:
- name: 'Checkout' - name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5 uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
@@ -223,8 +222,10 @@ jobs:
- 'merge_queue_skipper' - 'merge_queue_skipper'
- 'parse_run_context' - 'parse_run_context'
if: | 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' runs-on: 'gemini-cli-windows-16-core'
continue-on-error: true
steps: steps:
- name: 'Checkout' - name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5 uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
@@ -264,27 +265,6 @@ jobs:
run: 'npm run build' run: 'npm run build'
shell: 'pwsh' shell: 'pwsh'
- name: 'Ensure Chrome is available'
shell: 'pwsh'
run: |
$chromePaths = @(
"${env:ProgramFiles}\Google\Chrome\Application\chrome.exe",
"${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe"
)
$chromeExists = $chromePaths | Where-Object { Test-Path $_ } | Select-Object -First 1
if (-not $chromeExists) {
Write-Host 'Chrome not found, installing via Chocolatey...'
choco install googlechrome -y --no-progress --ignore-checksums
}
$installed = $chromePaths | Where-Object { Test-Path $_ } | Select-Object -First 1
if ($installed) {
Write-Host "Chrome found at: $installed"
& $installed --version
} else {
Write-Error 'Chrome installation failed'
exit 1
}
- name: 'Run E2E tests' - name: 'Run E2E tests'
env: env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}' GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
@@ -304,14 +284,13 @@ jobs:
- 'parse_run_context' - 'parse_run_context'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
if: | 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: steps:
- name: 'Checkout' - name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5 uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
with: with:
ref: '${{ needs.parse_run_context.outputs.sha }}' ref: '${{ needs.parse_run_context.outputs.sha }}'
repository: '${{ needs.parse_run_context.outputs.repository }}' repository: '${{ needs.parse_run_context.outputs.repository }}'
fetch-depth: 0
- name: 'Set up Node.js 20.x' - name: 'Set up Node.js 20.x'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4 uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
@@ -324,14 +303,7 @@ jobs:
- name: 'Build project' - name: 'Build project'
run: 'npm run build' run: 'npm run build'
- name: 'Check if evals should run'
id: 'check_evals'
run: |
SHOULD_RUN=$(node scripts/changed_prompt.js)
echo "should_run=$SHOULD_RUN" >> "$GITHUB_OUTPUT"
- name: 'Run Evals (Required to pass)' - name: 'Run Evals (Required to pass)'
if: "${{ steps.check_evals.outputs.should_run == 'true' }}"
env: env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}' GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
run: 'npm run test:always_passing_evals' run: 'npm run test:always_passing_evals'
@@ -339,42 +311,35 @@ jobs:
e2e: e2e:
name: 'E2E' name: 'E2E'
if: | 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: needs:
- 'e2e_linux' - 'e2e_linux'
- 'e2e_mac' - 'e2e_mac'
- 'e2e_windows'
- 'evals' - 'evals'
- 'merge_queue_skipper' - 'merge_queue_skipper'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
steps: steps:
- name: 'Check E2E test results' - name: 'Check E2E test results'
run: | run: |
if [[ ${NEEDS_E2E_LINUX_RESULT} != 'success' || \ if [[ ${{ needs.e2e_linux.result }} != 'success' || \
${NEEDS_E2E_MAC_RESULT} != 'success' || \ ${{ needs.e2e_mac.result }} != 'success' || \
${NEEDS_E2E_WINDOWS_RESULT} != 'success' || \ ${{ needs.evals.result }} != 'success' ]]; then
${NEEDS_EVALS_RESULT} != 'success' ]]; then
echo "One or more E2E jobs failed." echo "One or more E2E jobs failed."
exit 1 exit 1
fi fi
echo "All required E2E jobs passed!" 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: set_workflow_status:
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
permissions: 'write-all' permissions: 'write-all'
if: "github.repository == 'google-gemini/gemini-cli' && always()" if: 'always()'
needs: needs:
- 'parse_run_context' - 'parse_run_context'
- 'e2e' - 'e2e'
steps: steps:
- name: 'Set workflow status' - name: 'Set workflow status'
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master 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: with:
allowForks: 'true' allowForks: 'true'
repo: '${{ github.repository }}' repo: '${{ github.repository }}'
+17 -41
View File
@@ -37,7 +37,6 @@ jobs:
permissions: 'read-all' permissions: 'read-all'
name: 'Merge Queue Skipper' name: 'Merge Queue Skipper'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
outputs: outputs:
skip: '${{ steps.merge-queue-ci-skipper.outputs.skip-check }}' skip: '${{ steps.merge-queue-ci-skipper.outputs.skip-check }}'
steps: steps:
@@ -50,7 +49,7 @@ jobs:
name: 'Lint' name: 'Lint'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
needs: 'merge_queue_skipper' 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: env:
GEMINI_LINT_TEMP_DIR: '${{ github.workspace }}/.gemini-linters' GEMINI_LINT_TEMP_DIR: '${{ github.workspace }}/.gemini-linters'
steps: steps:
@@ -117,7 +116,6 @@ jobs:
link_checker: link_checker:
name: 'Link Checker' name: 'Link Checker'
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
if: "github.repository == 'google-gemini/gemini-cli'"
steps: steps:
- name: 'Checkout' - name: 'Checkout'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5 uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -131,7 +129,7 @@ jobs:
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
needs: needs:
- 'merge_queue_skipper' - '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: permissions:
contents: 'read' contents: 'read'
checks: 'write' checks: 'write'
@@ -169,7 +167,7 @@ jobs:
npm run test:ci --workspace @google/gemini-cli npm run test:ci --workspace @google/gemini-cli
else else
# Explicitly list non-cli packages to ensure they are sharded correctly # Explicitly list non-cli packages to ensure they are sharded correctly
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present
npm run test:scripts npm run test:scripts
fi fi
@@ -218,7 +216,7 @@ jobs:
runs-on: 'macos-latest' runs-on: 'macos-latest'
needs: needs:
- 'merge_queue_skipper' - '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: permissions:
contents: 'read' contents: 'read'
checks: 'write' checks: 'write'
@@ -313,7 +311,7 @@ jobs:
name: 'CodeQL' name: 'CodeQL'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
needs: 'merge_queue_skipper' 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: permissions:
actions: 'read' actions: 'read'
contents: 'read' contents: 'read'
@@ -336,7 +334,7 @@ jobs:
bundle_size: bundle_size:
name: 'Check Bundle Size' name: 'Check Bundle Size'
needs: 'merge_queue_skipper' 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' runs-on: 'gemini-cli-ubuntu-16-core'
permissions: permissions:
contents: 'read' # For checkout contents: 'read' # For checkout
@@ -358,16 +356,11 @@ jobs:
clean-script: 'clean' clean-script: 'clean'
test_windows: test_windows:
name: 'Slow Test - Win - ${{ matrix.shard }}' name: 'Slow Test - Win'
runs-on: 'gemini-cli-windows-16-core' runs-on: 'gemini-cli-windows-16-core'
needs: 'merge_queue_skipper' 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'}}"
timeout-minutes: 60 continue-on-error: true
strategy:
matrix:
shard:
- 'cli'
- 'others'
steps: steps:
- name: 'Checkout' - name: 'Checkout'
@@ -418,14 +411,7 @@ jobs:
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256' NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
UV_THREADPOOL_SIZE: '32' UV_THREADPOOL_SIZE: '32'
NODE_ENV: 'test' NODE_ENV: 'test'
run: | run: 'npm run test:ci -- --coverage.enabled=false'
if ("${{ matrix.shard }}" -eq "cli") {
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
} else {
# Explicitly list non-cli packages to ensure they are sharded correctly
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
npm run test:scripts
}
shell: 'pwsh' shell: 'pwsh'
- name: 'Bundle' - name: 'Bundle'
@@ -453,35 +439,25 @@ jobs:
ci: ci:
name: 'CI' name: 'CI'
if: "github.repository == 'google-gemini/gemini-cli' && always()" if: 'always()'
needs: needs:
- 'lint' - 'lint'
- 'link_checker' - 'link_checker'
- 'test_linux' - 'test_linux'
- 'test_mac' - 'test_mac'
- 'test_windows'
- 'codeql' - 'codeql'
- 'bundle_size' - 'bundle_size'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
steps: steps:
- name: 'Check all job results' - name: 'Check all job results'
run: | run: |
if [[ (${NEEDS_LINT_RESULT} != 'success' && ${NEEDS_LINT_RESULT} != 'skipped') || \ if [[ (${{ needs.lint.result }} != 'success' && ${{ needs.lint.result }} != 'skipped') || \
(${NEEDS_LINK_CHECKER_RESULT} != 'success' && ${NEEDS_LINK_CHECKER_RESULT} != 'skipped') || \ (${{ needs.link_checker.result }} != 'success' && ${{ needs.link_checker.result }} != 'skipped') || \
(${NEEDS_TEST_LINUX_RESULT} != 'success' && ${NEEDS_TEST_LINUX_RESULT} != 'skipped') || \ (${{ needs.test_linux.result }} != 'success' && ${{ needs.test_linux.result }} != 'skipped') || \
(${NEEDS_TEST_MAC_RESULT} != 'success' && ${NEEDS_TEST_MAC_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_CODEQL_RESULT} != 'success' && ${NEEDS_CODEQL_RESULT} != 'skipped') || \ (${{ needs.bundle_size.result }} != 'success' && ${{ needs.bundle_size.result }} != 'skipped') ]]; then
(${NEEDS_BUNDLE_SIZE_RESULT} != 'success' && ${NEEDS_BUNDLE_SIZE_RESULT} != 'skipped') ]]; then
echo "One or more CI jobs failed." echo "One or more CI jobs failed."
exit 1 exit 1
fi fi
echo "All CI jobs passed!" 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 }}'
+6 -8
View File
@@ -27,7 +27,6 @@ jobs:
deflake_e2e_linux: deflake_e2e_linux:
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}' name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -69,16 +68,15 @@ jobs:
VERBOSE: 'true' VERBOSE: 'true'
shell: 'bash' shell: 'bash'
run: | run: |
if [[ "${IS_DOCKER}" == "true" ]]; then if [[ "${{ env.IS_DOCKER }}" == "true" ]]; then
npm run deflake:test:integration:sandbox:docker -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'" npm run deflake:test:integration:sandbox:docker -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
else 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 fi
deflake_e2e_mac: deflake_e2e_mac:
name: 'E2E Test (macOS)' name: 'E2E Test (macOS)'
runs-on: 'macos-latest' runs-on: 'macos-latest'
if: "github.repository == 'google-gemini/gemini-cli'"
steps: steps:
- name: 'Checkout' - name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5 uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
@@ -111,12 +109,12 @@ jobs:
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}' TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
VERBOSE: 'true' VERBOSE: 'true'
run: | 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: deflake_e2e_windows:
name: 'Slow E2E - Win' name: 'Slow E2E - Win'
runs-on: 'gemini-cli-windows-16-core' runs-on: 'gemini-cli-windows-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
steps: steps:
- name: 'Checkout' - name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5 uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
@@ -169,4 +167,4 @@ jobs:
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}' TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
shell: 'pwsh' shell: 'pwsh'
run: | 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 }}'"
+2 -2
View File
@@ -19,7 +19,8 @@ concurrency:
jobs: jobs:
build: build:
if: "github.repository == 'google-gemini/gemini-cli' && !contains(github.ref_name, 'nightly')" if: |-
${{ !contains(github.ref_name, 'nightly') }}
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- name: 'Checkout' - name: 'Checkout'
@@ -38,7 +39,6 @@ jobs:
uses: 'actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa' # ratchet:actions/upload-pages-artifact@v3 uses: 'actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa' # ratchet:actions/upload-pages-artifact@v3
deploy: deploy:
if: "github.repository == 'google-gemini/gemini-cli'"
environment: environment:
name: 'github-pages' name: 'github-pages'
url: '${{ steps.deployment.outputs.page_url }}' url: '${{ steps.deployment.outputs.page_url }}'
-1
View File
@@ -7,7 +7,6 @@ on:
- 'docs/**' - 'docs/**'
jobs: jobs:
trigger-rebuild: trigger-rebuild:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- name: 'Trigger rebuild' - name: 'Trigger rebuild'
+1 -1
View File
@@ -44,5 +44,5 @@ jobs:
- name: 'Run evaluation' - name: 'Run evaluation'
working-directory: '/app' working-directory: '/app'
run: | 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 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
+2 -4
View File
@@ -23,12 +23,10 @@ jobs:
evals: evals:
name: 'Evals (USUALLY_PASSING) nightly run' name: 'Evals (USUALLY_PASSING) nightly run'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
model: model:
- 'gemini-3.1-pro-preview-customtools'
- 'gemini-3-pro-preview' - 'gemini-3-pro-preview'
- 'gemini-3-flash-preview' - 'gemini-3-flash-preview'
- 'gemini-2.5-pro' - 'gemini-2.5-pro'
@@ -63,7 +61,7 @@ jobs:
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}' TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
run: | run: |
CMD="npm run test:all_evals" CMD="npm run test:all_evals"
PATTERN="${TEST_NAME_PATTERN}" PATTERN="${{ env.TEST_NAME_PATTERN }}"
if [[ -n "$PATTERN" ]]; then if [[ -n "$PATTERN" ]]; then
if [[ "$PATTERN" == *.ts || "$PATTERN" == *.js || "$PATTERN" == */* ]]; then if [[ "$PATTERN" == *.ts || "$PATTERN" == *.js || "$PATTERN" == */* ]]; then
@@ -86,7 +84,7 @@ jobs:
aggregate-results: aggregate-results:
name: 'Aggregate Results' name: 'Aggregate Results'
needs: ['evals'] needs: ['evals']
if: "github.repository == 'google-gemini/gemini-cli' && always()" if: 'always()'
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
steps: steps:
- name: 'Checkout' - name: 'Checkout'
@@ -121,7 +121,6 @@ jobs:
'area/security', 'area/security',
'area/platform', 'area/platform',
'area/extensions', 'area/extensions',
'area/documentation',
'area/unknown' 'area/unknown'
]; ];
const labelNames = labels.map(label => label.name).filter(name => allowedLabels.includes(name)); const labelNames = labels.map(label => label.name).filter(name => allowedLabels.includes(name));
@@ -156,10 +155,7 @@ jobs:
"telemetry": { "telemetry": {
"enabled": true, "enabled": true,
"target": "gcp" "target": "gcp"
}, }
"coreTools": [
"run_shell_command(echo)"
]
} }
prompt: |- prompt: |-
## Role ## Role
@@ -256,14 +252,6 @@ jobs:
"Issues with a specific extension." "Issues with a specific extension."
"Feature request for the extension ecosystem." "Feature request for the extension ecosystem."
area/documentation
- Description: Issues related to user-facing documentation and other content on the documentation website.
- Example Issues:
"A typo in a README file."
"DOCS: A command is not working as described in the documentation."
"A request for a new documentation page."
"Instructions missing for skills feature"
area/unknown area/unknown
- Description: Issues that do not clearly fit into any other defined area/ category, or where information is too limited to make a determination. Use this when no other area is appropriate. - Description: Issues that do not clearly fit into any other defined area/ category, or where information is too limited to make a determination. Use this when no other area is appropriate.
@@ -296,21 +284,8 @@ jobs:
return; return;
} }
} else { } else {
// If no markdown block, try to find a raw JSON object in the output. core.setFailed(`Output is not valid JSON and does not contain a JSON markdown block.\nRaw output: ${rawOutput}`);
// The CLI may include debug/log lines (e.g. telemetry init, YOLO mode) return;
// 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;
}
} }
} }
@@ -63,7 +63,7 @@ jobs:
echo '🔍 Finding issues missing area labels...' echo '🔍 Finding issues missing area labels...'
NO_AREA_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \ NO_AREA_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
--search 'is:open is:issue -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 100 --json number,title,body)" --search 'is:open is:issue -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/unknown' --limit 100 --json number,title,body)"
echo '🔍 Finding issues missing kind labels...' echo '🔍 Finding issues missing kind labels...'
NO_KIND_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \ NO_KIND_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
@@ -204,7 +204,6 @@ jobs:
Categorization Guidelines (Area): Categorization Guidelines (Area):
area/agent: Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality area/agent: Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality
area/core: User Interface, OS Support, Core Functionality area/core: User Interface, OS Support, Core Functionality
area/documentation: End-user and contributor-facing documentation, website-related
area/enterprise: Telemetry, Policy, Quota / Licensing area/enterprise: Telemetry, Policy, Quota / Licensing
area/extensions: Gemini CLI extensions capability area/extensions: Gemini CLI extensions capability
area/non-interactive: GitHub Actions, SDK, 3P Integrations, Shell Scripting, Command line automation area/non-interactive: GitHub Actions, SDK, 3P Integrations, Shell Scripting, Command line automation
@@ -21,14 +21,13 @@ defaults:
jobs: jobs:
close-stale-issues: close-stale-issues:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
permissions: permissions:
issues: 'write' issues: 'write'
steps: steps:
- name: 'Generate GitHub App Token' - name: 'Generate GitHub App Token'
id: 'generate_token' id: 'generate_token'
uses: 'actions/create-github-app-token@v2' uses: 'actions/create-github-app-token@v1'
with: with:
app-id: '${{ secrets.APP_ID }}' app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}' private-key: '${{ secrets.PRIVATE_KEY }}'
@@ -23,21 +23,19 @@ jobs:
steps: steps:
- name: 'Generate GitHub App Token' - name: 'Generate GitHub App Token'
id: 'generate_token' id: 'generate_token'
env: uses: 'actions/create-github-app-token@v1'
APP_ID: '${{ secrets.APP_ID }}'
if: |-
${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@v2'
with: with:
app-id: '${{ secrets.APP_ID }}' app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}' private-key: '${{ secrets.PRIVATE_KEY }}'
owner: '${{ github.repository_owner }}'
repositories: 'gemini-cli'
- name: 'Process Stale PRs' - name: 'Process Stale PRs'
uses: 'actions/github-script@v7' uses: 'actions/github-script@v7'
env: env:
DRY_RUN: '${{ inputs.dry_run }}' DRY_RUN: '${{ inputs.dry_run }}'
with: with:
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}' github-token: '${{ steps.generate_token.outputs.token }}'
script: | script: |
const dryRun = process.env.DRY_RUN === 'true'; const dryRun = process.env.DRY_RUN === 'true';
const thirtyDaysAgo = new Date(); const thirtyDaysAgo = new Date();
@@ -45,56 +43,23 @@ jobs:
// 1. Fetch maintainers for verification // 1. Fetch maintainers for verification
let maintainerLogins = new Set(); let maintainerLogins = new Set();
const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs']; let teamFetchSucceeded = false;
try {
for (const team_slug of teams) { const members = await github.paginate(github.rest.teams.listMembersInOrg, {
try { org: context.repo.owner,
const members = await github.paginate(github.rest.teams.listMembersInOrg, { team_slug: 'gemini-cli-maintainers'
org: context.repo.owner, });
team_slug: team_slug maintainerLogins = new Set(members.map(m => m.login.toLowerCase()));
}); teamFetchSucceeded = true;
for (const m of members) maintainerLogins.add(m.login.toLowerCase()); core.info(`Successfully fetched ${maintainerLogins.size} team members from gemini-cli-maintainers`);
core.info(`Successfully fetched ${members.length} team members from ${team_slug}`); } catch (e) {
} catch (e) { core.warning(`Failed to fetch team members from gemini-cli-maintainers: ${e.message}. Falling back to author_association only.`);
core.warning(`Failed to fetch team members from ${team_slug}: ${e.message}`);
}
} }
const isGooglerCache = new Map(); const isMaintainer = (login, assoc) => {
const isGoogler = async (login) => {
if (isGooglerCache.has(login)) return isGooglerCache.get(login);
try {
// Check membership in 'googlers' or 'google' orgs
const orgs = ['googlers', 'google'];
for (const org of orgs) {
try {
await github.rest.orgs.checkMembershipForUser({
org: org,
username: login
});
core.info(`User ${login} is a member of ${org} organization.`);
isGooglerCache.set(login, true);
return true;
} catch (e) {
// 404 just means they aren't a member, which is fine
if (e.status !== 404) throw e;
}
}
} catch (e) {
core.warning(`Failed to check org membership for ${login}: ${e.message}`);
}
isGooglerCache.set(login, false);
return false;
};
const isMaintainer = async (login, assoc) => {
const isTeamMember = maintainerLogins.has(login.toLowerCase()); const isTeamMember = maintainerLogins.has(login.toLowerCase());
const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc); const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc);
if (isTeamMember || isRepoMaintainer) return true; return isTeamMember || isRepoMaintainer;
return await isGoogler(login);
}; };
// 2. Determine which PRs to check // 2. Determine which PRs to check
@@ -116,7 +81,7 @@ jobs:
} }
for (const pr of prs) { for (const pr of prs) {
const maintainerPr = await isMaintainer(pr.user.login, pr.author_association); const maintainerPr = isMaintainer(pr.user.login, pr.author_association);
const isBot = pr.user.type === 'Bot' || pr.user.login.endsWith('[bot]'); const isBot = pr.user.type === 'Bot' || pr.user.login.endsWith('[bot]');
// Detection Logic for Linked Issues // Detection Logic for Linked Issues
@@ -210,7 +175,7 @@ jobs:
pull_number: pr.number pull_number: pr.number
}); });
for (const r of reviews) { for (const r of reviews) {
if (await isMaintainer(r.user.login, r.author_association)) { if (isMaintainer(r.user.login, r.author_association)) {
const d = new Date(r.submitted_at || r.updated_at); const d = new Date(r.submitted_at || r.updated_at);
if (d > lastActivity) lastActivity = d; if (d > lastActivity) lastActivity = d;
} }
@@ -221,7 +186,7 @@ jobs:
issue_number: pr.number issue_number: pr.number
}); });
for (const c of comments) { for (const c of comments) {
if (await isMaintainer(c.user.login, c.author_association)) { if (isMaintainer(c.user.login, c.author_association)) {
const d = new Date(c.updated_at); const d = new Date(c.updated_at);
if (d > lastActivity) lastActivity = d; if (d > lastActivity) lastActivity = d;
} }
+8 -59
View File
@@ -25,7 +25,7 @@ jobs:
if: |- if: |-
github.repository == 'google-gemini/gemini-cli' && github.repository == 'google-gemini/gemini-cli' &&
github.event_name == 'issue_comment' && github.event_name == 'issue_comment' &&
(contains(github.event.comment.body, '/assign') || contains(github.event.comment.body, '/unassign')) contains(github.event.comment.body, '/assign')
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- name: 'Generate GitHub App Token' - name: 'Generate GitHub App Token'
@@ -38,7 +38,6 @@ jobs:
permission-issues: 'write' permission-issues: 'write'
- name: 'Assign issue to user' - name: 'Assign issue to user'
if: "contains(github.event.comment.body, '/assign')"
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with: with:
github-token: '${{ steps.generate_token.outputs.token }}' github-token: '${{ steps.generate_token.outputs.token }}'
@@ -49,24 +48,6 @@ jobs:
const repo = context.repo.repo; const repo = context.repo.repo;
const MAX_ISSUES_ASSIGNED = 3; 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 // Search for open issues already assigned to the commenter in this repo
const { data: assignedIssues } = await github.rest.search.issuesAndPullRequests({ const { data: assignedIssues } = await github.rest.search.issuesAndPullRequests({
q: `is:issue repo:${owner}/${repo} assignee:${commenter} is:open`, q: `is:issue repo:${owner}/${repo} assignee:${commenter} is:open`,
@@ -83,6 +64,13 @@ jobs:
return; // exit 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) { if (issue.data.assignees.length > 0) {
// Comment that it's already assigned // Comment that it's already assigned
await github.rest.issues.createComment({ await github.rest.issues.createComment({
@@ -109,42 +97,3 @@ jobs:
issue_number: issueNumber, issue_number: issueNumber,
body: `👋 @${commenter}, you've been assigned to this issue! Thank you for taking the time to contribute. Make sure to check out our [contributing guidelines](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md).` body: `👋 @${commenter}, you've been assigned to this issue! Thank you for taking the time to contribute. Make sure to check out our [contributing guidelines](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md).`
}); });
- name: 'Unassign issue from user'
if: "contains(github.event.comment.body, '/unassign')"
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with:
github-token: '${{ steps.generate_token.outputs.token }}'
script: |
const issueNumber = context.issue.number;
const commenter = context.actor;
const owner = context.repo.owner;
const repo = context.repo.repo;
const commentBody = context.payload.comment.body.trim();
if (commentBody !== '/unassign') {
return;
}
const issue = await github.rest.issues.get({
owner: owner,
repo: repo,
issue_number: issueNumber,
});
const isAssigned = issue.data.assignees.some(assignee => assignee.login === commenter);
if (isAssigned) {
await github.rest.issues.removeAssignees({
owner: owner,
repo: repo,
issue_number: issueNumber,
assignees: [commenter]
});
await github.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: issueNumber,
body: `👋 @${commenter}, you have been unassigned from this issue.`
});
}
@@ -14,7 +14,7 @@ permissions:
jobs: jobs:
# Event-based: Quick reaction to new/edited issues in THIS repo # Event-based: Quick reaction to new/edited issues in THIS repo
labeler: labeler:
if: "github.repository == 'google-gemini/gemini-cli' && github.event_name == 'issues'" if: "github.event_name == 'issues'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
steps: steps:
- name: 'Checkout' - name: 'Checkout'
@@ -36,7 +36,7 @@ jobs:
# Scheduled/Manual: Recursive sync across multiple repos # Scheduled/Manual: Recursive sync across multiple repos
sync-maintainer-labels: 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' runs-on: 'ubuntu-latest'
steps: steps:
- name: 'Checkout' - name: 'Checkout'
@@ -9,7 +9,6 @@ on:
jobs: jobs:
labeler: labeler:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
permissions: permissions:
issues: 'write' issues: 'write'
@@ -19,7 +19,7 @@ jobs:
APP_ID: '${{ secrets.APP_ID }}' APP_ID: '${{ secrets.APP_ID }}'
if: |- if: |-
${{ env.APP_ID != '' }} ${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@v2' uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
with: with:
app-id: '${{ secrets.APP_ID }}' app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}' private-key: '${{ secrets.PRIVATE_KEY }}'
@@ -35,59 +35,9 @@ jobs:
const pr_number = context.payload.pull_request.number; const pr_number = context.payload.pull_request.number;
// 1. Check if the PR author is a maintainer // 1. Check if the PR author is a maintainer
// Check team membership (most reliable for private org members)
let isTeamMember = false;
const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs'];
for (const team_slug of teams) {
try {
const members = await github.paginate(github.rest.teams.listMembersInOrg, {
org: org,
team_slug: team_slug
});
if (members.some(m => m.login.toLowerCase() === username.toLowerCase())) {
isTeamMember = true;
core.info(`${username} is a member of ${team_slug}. No notification needed.`);
break;
}
} catch (e) {
core.warning(`Failed to fetch team members from ${team_slug}: ${e.message}`);
}
}
if (isTeamMember) return;
// Check author_association from webhook payload
const authorAssociation = context.payload.pull_request.author_association; const authorAssociation = context.payload.pull_request.author_association;
const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(authorAssociation); if (['OWNER', 'MEMBER', 'COLLABORATOR'].includes(authorAssociation)) {
core.info(`${username} is a maintainer (Association: ${authorAssociation}). No notification needed.`);
if (isRepoMaintainer) {
core.info(`${username} is a maintainer (author_association: ${authorAssociation}). No notification needed.`);
return;
}
// Check if author is a Googler
const isGoogler = async (login) => {
try {
const orgs = ['googlers', 'google'];
for (const org of orgs) {
try {
await github.rest.orgs.checkMembershipForUser({
org: org,
username: login
});
return true;
} catch (e) {
if (e.status !== 404) throw e;
}
}
} catch (e) {
core.warning(`Failed to check org membership for ${login}: ${e.message}`);
}
return false;
};
if (await isGoogler(username)) {
core.info(`${username} is a Googler. No notification needed.`);
return; return;
} }
-29
View File
@@ -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: jobs:
change-tags: change-tags:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
environment: "${{ github.event.inputs.environment || 'prod' }}" environment: "${{ github.event.inputs.environment || 'prod' }}"
permissions: permissions:
-2
View File
@@ -47,7 +47,6 @@ on:
jobs: jobs:
release: release:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
environment: "${{ github.event.inputs.environment || 'prod' }}" environment: "${{ github.event.inputs.environment || 'prod' }}"
permissions: permissions:
@@ -111,7 +110,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}' wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}' wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}' github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}' dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ steps.release_info.outputs.PREVIOUS_TAG }}' previous-tag: '${{ steps.release_info.outputs.PREVIOUS_TAG }}'
skip-github-release: '${{ github.event.inputs.skip_github_release }}' skip-github-release: '${{ github.event.inputs.skip_github_release }}'
-1
View File
@@ -124,7 +124,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}' wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}' wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}' github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ steps.vars.outputs.is_dry_run }}' dry-run: '${{ steps.vars.outputs.is_dry_run }}'
previous-tag: '${{ steps.nightly_version.outputs.PREVIOUS_TAG }}' previous-tag: '${{ steps.nightly_version.outputs.PREVIOUS_TAG }}'
working-directory: './release' working-directory: './release'
-103
View File
@@ -1,103 +0,0 @@
# This workflow is triggered on every new release.
# It uses Gemini to generate release notes and creates a PR with the changes.
name: 'Generate Release Notes'
on:
release:
types: ['published']
workflow_dispatch:
inputs:
version:
description: 'New version (e.g., v1.2.3)'
required: true
type: 'string'
body:
description: 'Release notes body'
required: true
type: 'string'
time:
description: 'Release time'
required: true
type: 'string'
jobs:
generate-release-notes:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest'
permissions:
contents: 'write'
pull-requests: 'write'
steps:
- name: 'Checkout repository'
uses: 'actions/checkout@v4'
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'
with:
node-version: '20'
- name: 'Get release information'
id: 'release_info'
run: |
VERSION="${{ github.event.inputs.version || github.event.release.tag_name }}"
TIME="${{ github.event.inputs.time || github.event.release.created_at }}"
echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
echo "TIME=${TIME}" >> "$GITHUB_OUTPUT"
# Use a heredoc to preserve multiline release body
echo 'RAW_CHANGELOG<<EOF' >> "$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 }}'
prompt: |
Activate the 'docs-changelog' skill.
**Release Information:**
- New Version: ${{ steps.release_info.outputs.VERSION }}
- Release Date: ${{ steps.release_info.outputs.TIME }}
- Raw Changelog Data: ${{ steps.release_info.outputs.RAW_CHANGELOG }}
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 }}'
commit-message: 'docs(changelog): update for ${{ steps.release_info.outputs.VERSION }}'
title: 'Changelog for ${{ steps.release_info.outputs.VERSION }}'
body: |
This PR contains the auto-generated changelog for the ${{ steps.release_info.outputs.VERSION }} release.
Please review and merge.
Related to #18505
branch: 'changelog-${{ steps.release_info.outputs.VERSION }}'
base: 'main'
team-reviewers: 'gemini-cli-docs, gemini-cli-maintainers'
delete-branch: true
@@ -120,9 +120,6 @@ jobs:
if (recentRuns.length > 0) { if (recentRuns.length > 0) {
core.setOutput('dispatched_run_urls', recentRuns.map(r => r.html_url).join(',')); core.setOutput('dispatched_run_urls', recentRuns.map(r => r.html_url).join(','));
core.setOutput('dispatched_run_ids', recentRuns.map(r => r.id).join(',')); core.setOutput('dispatched_run_ids', recentRuns.map(r => r.id).join(','));
const markdownLinks = recentRuns.map(r => `- [View dispatched workflow run](${r.html_url})`).join('\n');
core.setOutput('dispatched_run_links', markdownLinks);
} }
- name: 'Comment on Failure' - name: 'Comment on Failure'
@@ -141,19 +138,16 @@ jobs:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
issue-number: '${{ github.event.issue.number }}' issue-number: '${{ github.event.issue.number }}'
body: | body: |
🚀 **[Step 1/4] Patch workflow(s) waiting for approval!** **Patch workflow(s) dispatched successfully!**
**📋 Details:** **📋 Details:**
- **Channels**: `${{ steps.dispatch_patch.outputs.dispatched_channels }}` - **Channels**: `${{ steps.dispatch_patch.outputs.dispatched_channels }}`
- **Commit**: `${{ steps.pr_status.outputs.MERGE_COMMIT_SHA }}` - **Commit**: `${{ steps.pr_status.outputs.MERGE_COMMIT_SHA }}`
- **Workflows Created**: ${{ steps.dispatch_patch.outputs.dispatched_run_count }} - **Workflows Created**: ${{ steps.dispatch_patch.outputs.dispatched_run_count }}
**⏳ Status:** The patch creation workflow has been triggered and is waiting for deployment approval. Please visit the specific workflow links below and approve the runs.
**🔗 Track Progress:** **🔗 Track Progress:**
${{ steps.dispatch_patch.outputs.dispatched_run_links }} - [View patch workflows](https://github.com/${{ github.repository }}/actions/workflows/release-patch-1-create-pr.yml)
- [View patch workflow history](https://github.com/${{ github.repository }}/actions/workflows/release-patch-1-create-pr.yml) - [This workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- [This trigger workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- name: 'Final Status Comment - Dispatch Success (No URL)' - name: 'Final Status Comment - Dispatch Success (No URL)'
if: "always() && startsWith(github.event.comment.body, '/patch') && steps.dispatch_patch.outcome == 'success' && !steps.dispatch_patch.outputs.dispatched_run_urls" if: "always() && startsWith(github.event.comment.body, '/patch') && steps.dispatch_patch.outcome == 'success' && !steps.dispatch_patch.outputs.dispatched_run_urls"
@@ -162,18 +156,16 @@ jobs:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
issue-number: '${{ github.event.issue.number }}' issue-number: '${{ github.event.issue.number }}'
body: | body: |
🚀 **[Step 1/4] Patch workflow(s) waiting for approval!** **Patch workflow(s) dispatched successfully!**
**📋 Details:** **📋 Details:**
- **Channels**: `${{ steps.dispatch_patch.outputs.dispatched_channels }}` - **Channels**: `${{ steps.dispatch_patch.outputs.dispatched_channels }}`
- **Commit**: `${{ steps.pr_status.outputs.MERGE_COMMIT_SHA }}` - **Commit**: `${{ steps.pr_status.outputs.MERGE_COMMIT_SHA }}`
- **Workflows Created**: ${{ steps.dispatch_patch.outputs.dispatched_run_count }} - **Workflows Created**: ${{ steps.dispatch_patch.outputs.dispatched_run_count }}
**⏳ Status:** The patch creation workflow has been triggered and is waiting for deployment approval. Please visit the workflow history link below and approve the runs.
**🔗 Track Progress:** **🔗 Track Progress:**
- [View patch workflow history](https://github.com/${{ github.repository }}/actions/workflows/release-patch-1-create-pr.yml) - [View patch workflows](https://github.com/${{ github.repository }}/actions/workflows/release-patch-1-create-pr.yml)
- [This trigger workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) - [This workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- name: 'Final Status Comment - Failure' - name: 'Final Status Comment - Failure'
if: "always() && startsWith(github.event.comment.body, '/patch') && (steps.dispatch_patch.outcome == 'failure' || steps.dispatch_patch.outcome == 'cancelled')" if: "always() && startsWith(github.event.comment.body, '/patch') && (steps.dispatch_patch.outcome == 'failure' || steps.dispatch_patch.outcome == 'cancelled')"
@@ -182,7 +174,7 @@ jobs:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
issue-number: '${{ github.event.issue.number }}' issue-number: '${{ github.event.issue.number }}'
body: | body: |
❌ **[Step 1/4] Patch workflow dispatch failed!** ❌ **Patch workflow dispatch failed!**
There was an error dispatching the patch creation workflow. There was an error dispatching the patch creation workflow.
+5 -12
View File
@@ -118,7 +118,6 @@ jobs:
ORIGINAL_RELEASE_VERSION: '${{ steps.patch_version.outputs.RELEASE_VERSION }}' ORIGINAL_RELEASE_VERSION: '${{ steps.patch_version.outputs.RELEASE_VERSION }}'
ORIGINAL_RELEASE_TAG: '${{ steps.patch_version.outputs.RELEASE_TAG }}' ORIGINAL_RELEASE_TAG: '${{ steps.patch_version.outputs.RELEASE_TAG }}'
ORIGINAL_PREVIOUS_TAG: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}' ORIGINAL_PREVIOUS_TAG: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
VARS_CLI_PACKAGE_NAME: '${{ vars.CLI_PACKAGE_NAME }}'
run: | run: |
echo "🔍 Verifying no concurrent patch releases have occurred..." echo "🔍 Verifying no concurrent patch releases have occurred..."
@@ -130,7 +129,7 @@ jobs:
# Re-run the same version calculation script # Re-run the same version calculation script
echo "Re-calculating version to check for changes..." 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_VERSION=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseVersion)
CURRENT_RELEASE_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseTag) CURRENT_RELEASE_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseTag)
CURRENT_PREVIOUS_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .previousReleaseTag) CURRENT_PREVIOUS_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .previousReleaseTag)
@@ -163,15 +162,10 @@ jobs:
- name: 'Print Calculated Version' - name: 'Print Calculated Version'
run: |- run: |-
echo "Patch Release Summary:" echo "Patch Release Summary:"
echo " Release Version: ${STEPS_PATCH_VERSION_OUTPUTS_RELEASE_VERSION}" echo " Release Version: ${{ steps.patch_version.outputs.RELEASE_VERSION }}"
echo " Release Tag: ${STEPS_PATCH_VERSION_OUTPUTS_RELEASE_TAG}" echo " Release Tag: ${{ steps.patch_version.outputs.RELEASE_TAG }}"
echo " NPM Tag: ${STEPS_PATCH_VERSION_OUTPUTS_NPM_TAG}" echo " NPM Tag: ${{ steps.patch_version.outputs.NPM_TAG }}"
echo " Previous Tag: ${STEPS_PATCH_VERSION_OUTPUTS_PREVIOUS_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 }}'
- name: 'Run Tests' - name: 'Run Tests'
if: "${{github.event.inputs.force_skip_tests != 'true'}}" if: "${{github.event.inputs.force_skip_tests != 'true'}}"
@@ -190,7 +184,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}' wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}' wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}' github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}' dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}' previous-tag: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}' gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
+3 -11
View File
@@ -239,7 +239,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}' wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}' wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}' github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}' dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_PREVIEW_TAG }}' previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_PREVIEW_TAG }}'
working-directory: './release' working-directory: './release'
@@ -306,7 +305,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}' wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}' wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}' github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}' dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_STABLE_TAG }}' previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_STABLE_TAG }}'
working-directory: './release' working-directory: './release'
@@ -335,7 +333,6 @@ jobs:
name: 'Create Nightly PR' name: 'Create Nightly PR'
needs: ['publish-stable', 'calculate-versions'] needs: ['publish-stable', 'calculate-versions']
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
environment: "${{ github.event.inputs.environment || 'prod' }}"
permissions: permissions:
contents: 'write' contents: 'write'
pull-requests: 'write' pull-requests: 'write'
@@ -363,28 +360,23 @@ jobs:
- name: 'Create and switch to a new branch' - name: 'Create and switch to a new branch'
id: 'release_branch' id: 'release_branch'
run: | 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}" git switch -c "${BRANCH_NAME}"
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}" 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' - name: 'Update package versions'
run: 'npm run release:version "${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"' 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 }}'
- name: 'Commit and Push package versions' - name: 'Commit and Push package versions'
env: env:
BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}' BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
DRY_RUN: '${{ github.event.inputs.dry_run }}' DRY_RUN: '${{ github.event.inputs.dry_run }}'
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
run: |- run: |-
git add package.json packages/*/package.json git add package.json packages/*/package.json
if [ -f package-lock.json ]; then if [ -f package-lock.json ]; then
git add package-lock.json git add package-lock.json
fi 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 if [[ "${DRY_RUN}" == "false" ]]; then
echo "Pushing release branch to remote..." echo "Pushing release branch to remote..."
git push --set-upstream origin "${BRANCH_NAME}" git push --set-upstream origin "${BRANCH_NAME}"
+1 -2
View File
@@ -42,7 +42,6 @@ on:
jobs: jobs:
change-tags: change-tags:
if: "github.repository == 'google-gemini/gemini-cli'"
environment: "${{ github.event.inputs.environment || 'prod' }}" environment: "${{ github.event.inputs.environment || 'prod' }}"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
permissions: permissions:
@@ -204,7 +203,7 @@ jobs:
run: | run: |
ROLLBACK_COMMIT=$(git rev-parse -q --verify "$TARGET_TAG") ROLLBACK_COMMIT=$(git rev-parse -q --verify "$TARGET_TAG")
if [ "$ROLLBACK_COMMIT" != "$TARGET_HASH" ]; then 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.' echo '❌ This means the tag was not added, and the workflow should fail.'
exit 1 exit 1
fi fi
-1
View File
@@ -16,7 +16,6 @@ on:
jobs: jobs:
build: build:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
permissions: permissions:
contents: 'read' contents: 'read'
-1
View File
@@ -20,7 +20,6 @@ on:
jobs: jobs:
smoke-test: smoke-test:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest' runs-on: 'ubuntu-latest'
permissions: permissions:
contents: 'write' contents: 'write'
-160
View File
@@ -1,160 +0,0 @@
name: 'Test Build Binary'
on:
workflow_dispatch:
permissions:
contents: 'read'
defaults:
run:
shell: 'bash'
jobs:
build-node-binary:
name: 'Build Binary (${{ matrix.os }})'
runs-on: '${{ matrix.os }}'
strategy:
fail-fast: false
matrix:
include:
- os: 'ubuntu-latest'
platform_name: 'linux-x64'
arch: 'x64'
- os: 'windows-latest'
platform_name: 'win32-x64'
arch: 'x64'
- os: 'macos-latest' # Apple Silicon (ARM64)
platform_name: 'darwin-arm64'
arch: 'arm64'
- os: 'macos-latest' # Intel (x64) running on ARM via Rosetta
platform_name: 'darwin-x64'
arch: 'x64'
steps:
- name: 'Checkout'
uses: 'actions/checkout@v4'
- name: 'Optimize Windows Performance'
if: "matrix.os == 'windows-latest'"
run: |
Set-MpPreference -DisableRealtimeMonitoring $true
Stop-Service -Name "wsearch" -Force -ErrorAction SilentlyContinue
Set-Service -Name "wsearch" -StartupType Disabled
Stop-Service -Name "SysMain" -Force -ErrorAction SilentlyContinue
Set-Service -Name "SysMain" -StartupType Disabled
shell: 'powershell'
- name: 'Set up Node.js'
uses: 'actions/setup-node@v4'
with:
node-version-file: '.nvmrc'
architecture: '${{ matrix.arch }}'
cache: 'npm'
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Check Secrets'
id: 'check_secrets'
run: |
echo "has_win_cert=${{ secrets.WINDOWS_PFX_BASE64 != '' }}" >> "$GITHUB_OUTPUT"
echo "has_mac_cert=${{ secrets.MACOS_CERT_P12_BASE64 != '' }}" >> "$GITHUB_OUTPUT"
- name: 'Setup Windows SDK (Windows)'
if: "matrix.os == 'windows-latest'"
uses: 'microsoft/setup-msbuild@v2'
- name: 'Add Signtool to Path (Windows)'
if: "matrix.os == 'windows-latest'"
run: |
$signtoolPath = Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin" -Recurse -Filter "signtool.exe" | Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty DirectoryName
echo "Found signtool at: $signtoolPath"
echo "$signtoolPath" >> $env:GITHUB_PATH
shell: 'pwsh'
- name: 'Setup macOS Keychain'
if: "startsWith(matrix.os, 'macos') && steps.check_secrets.outputs.has_mac_cert == 'true' && github.event_name != 'pull_request'"
env:
BUILD_CERTIFICATE_BASE64: '${{ secrets.MACOS_CERT_P12_BASE64 }}'
P12_PASSWORD: '${{ secrets.MACOS_CERT_PASSWORD }}'
KEYCHAIN_PASSWORD: 'temp-password'
run: |
# Create the P12 file
echo "$BUILD_CERTIFICATE_BASE64" | base64 --decode > certificate.p12
# Create a temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
# Import the certificate
security import certificate.p12 -k build.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
# Allow codesign to access it
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain
# Set Identity for build script
echo "APPLE_IDENTITY=${{ secrets.MACOS_CERT_IDENTITY }}" >> "$GITHUB_ENV"
- name: 'Setup Windows Certificate'
if: "matrix.os == 'windows-latest' && steps.check_secrets.outputs.has_win_cert == 'true' && github.event_name != 'pull_request'"
env:
PFX_BASE64: '${{ secrets.WINDOWS_PFX_BASE64 }}'
PFX_PASSWORD: '${{ secrets.WINDOWS_PFX_PASSWORD }}'
run: |
$pfx_cert_byte = [System.Convert]::FromBase64String("$env:PFX_BASE64")
$certPath = Join-Path (Get-Location) "cert.pfx"
[IO.File]::WriteAllBytes($certPath, $pfx_cert_byte)
echo "WINDOWS_PFX_FILE=$certPath" >> $env:GITHUB_ENV
echo "WINDOWS_PFX_PASSWORD=$env:PFX_PASSWORD" >> $env:GITHUB_ENV
shell: 'pwsh'
- name: 'Build Binary'
run: 'npm run build:binary'
- name: 'Build Core Package'
run: 'npm run build -w @google/gemini-cli-core'
- name: 'Verify Output Exists'
run: |
if [ -f "dist/${{ matrix.platform_name }}/gemini" ]; then
echo "Binary found at dist/${{ matrix.platform_name }}/gemini"
elif [ -f "dist/${{ matrix.platform_name }}/gemini.exe" ]; then
echo "Binary found at dist/${{ matrix.platform_name }}/gemini.exe"
else
echo "Error: Binary not found in dist/${{ matrix.platform_name }}/"
ls -R dist/
exit 1
fi
- name: 'Smoke Test Binary'
run: |
echo "Running binary smoke test..."
if [ -f "dist/${{ matrix.platform_name }}/gemini.exe" ]; then
"./dist/${{ matrix.platform_name }}/gemini.exe" --version
else
"./dist/${{ matrix.platform_name }}/gemini" --version
fi
- name: 'Run Integration Tests'
if: "github.event_name != 'pull_request'"
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
run: |
echo "Running integration tests with binary..."
if [[ "${{ matrix.os }}" == 'windows-latest' ]]; then
BINARY_PATH="$(cygpath -m "$(pwd)/dist/${{ matrix.platform_name }}/gemini.exe")"
else
BINARY_PATH="$(pwd)/dist/${{ matrix.platform_name }}/gemini"
fi
echo "Using binary at $BINARY_PATH"
export INTEGRATION_TEST_GEMINI_BINARY_PATH="$BINARY_PATH"
npm run test:integration:sandbox:none -- --testTimeout=600000
- name: 'Upload Artifact'
uses: 'actions/upload-artifact@v4'
with:
name: 'gemini-cli-${{ matrix.platform_name }}'
path: 'dist/${{ matrix.platform_name }}/'
retention-days: 5
+2 -4
View File
@@ -15,7 +15,6 @@ on:
jobs: jobs:
save_repo_name: save_repo_name:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
steps: steps:
- name: 'Save Repo name' - name: 'Save Repo name'
@@ -24,15 +23,14 @@ jobs:
HEAD_SHA: '${{ github.event.inputs.head_sha || github.event.pull_request.head.sha }}' HEAD_SHA: '${{ github.event.inputs.head_sha || github.event.pull_request.head.sha }}'
run: | run: |
mkdir -p ./pr mkdir -p ./pr
echo "${REPO_NAME}" > ./pr/repo_name echo '${{ env.REPO_NAME }}' > ./pr/repo_name
echo "${HEAD_SHA}" > ./pr/head_sha echo '${{ env.HEAD_SHA }}' > ./pr/head_sha
- uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4 - uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with: with:
name: 'repo_name' name: 'repo_name'
path: 'pr/' path: 'pr/'
trigger_e2e: trigger_e2e:
name: 'Trigger e2e' name: 'Trigger e2e'
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'gemini-cli-ubuntu-16-core' runs-on: 'gemini-cli-ubuntu-16-core'
steps: steps:
- id: 'trigger-e2e' - id: 'trigger-e2e'
@@ -1,315 +0,0 @@
name: 'Unassign Inactive Issue Assignees'
# This workflow runs daily and scans every open "help wanted" issue that has
# one or more assignees. For each assignee it checks whether they have a
# non-draft pull request (open and ready for review, or already merged) that
# is linked to the issue. Draft PRs are intentionally excluded so that
# contributors cannot reset the check by opening a no-op PR. If no
# qualifying PR is found within 7 days of assignment the assignee is
# automatically removed and a friendly comment is posted so that other
# contributors can pick up the work.
# Maintainers, org members, and collaborators (anyone with write access or
# above) are always exempted and will never be auto-unassigned.
on:
schedule:
- cron: '0 9 * * *' # Every day at 09:00 UTC
workflow_dispatch:
inputs:
dry_run:
description: 'Run in dry-run mode (no changes will be applied)'
required: false
default: false
type: 'boolean'
concurrency:
group: '${{ github.workflow }}'
cancel-in-progress: true
defaults:
run:
shell: 'bash'
jobs:
unassign-inactive-assignees:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest'
permissions:
issues: 'write'
steps:
- name: 'Generate GitHub App Token'
id: 'generate_token'
uses: 'actions/create-github-app-token@v2'
with:
app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}'
- name: 'Unassign inactive assignees'
uses: 'actions/github-script@v7'
env:
DRY_RUN: '${{ inputs.dry_run }}'
with:
github-token: '${{ steps.generate_token.outputs.token }}'
script: |
const dryRun = process.env.DRY_RUN === 'true';
if (dryRun) {
core.info('DRY RUN MODE ENABLED: No changes will be applied.');
}
const owner = context.repo.owner;
const repo = context.repo.repo;
const GRACE_PERIOD_DAYS = 7;
const now = new Date();
let maintainerLogins = new Set();
const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs'];
for (const team_slug of teams) {
try {
const members = await github.paginate(github.rest.teams.listMembersInOrg, {
org: owner,
team_slug,
});
for (const m of members) maintainerLogins.add(m.login.toLowerCase());
core.info(`Fetched ${members.length} members from team ${team_slug}.`);
} catch (e) {
core.warning(`Could not fetch team ${team_slug}: ${e.message}`);
}
}
const isGooglerCache = new Map();
const isGoogler = async (login) => {
if (isGooglerCache.has(login)) return isGooglerCache.get(login);
try {
for (const org of ['googlers', 'google']) {
try {
await github.rest.orgs.checkMembershipForUser({ org, username: login });
isGooglerCache.set(login, true);
return true;
} catch (e) {
if (e.status !== 404) throw e;
}
}
} catch (e) {
core.warning(`Could not check org membership for ${login}: ${e.message}`);
}
isGooglerCache.set(login, false);
return false;
};
const permissionCache = new Map();
const isPrivilegedUser = async (login) => {
if (maintainerLogins.has(login.toLowerCase())) return true;
if (permissionCache.has(login)) return permissionCache.get(login);
try {
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: login,
});
const privileged = ['admin', 'maintain', 'write', 'triage'].includes(data.permission);
permissionCache.set(login, privileged);
if (privileged) {
core.info(` @${login} is a repo collaborator (${data.permission}) — exempt.`);
return true;
}
} catch (e) {
if (e.status !== 404) {
core.warning(`Could not check permission for ${login}: ${e.message}`);
}
}
const googler = await isGoogler(login);
permissionCache.set(login, googler);
return googler;
};
core.info('Fetching open "help wanted" issues with assignees...');
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner,
repo,
state: 'open',
labels: 'help wanted',
per_page: 100,
});
const assignedIssues = issues.filter(
(issue) => !issue.pull_request && issue.assignees && issue.assignees.length > 0
);
core.info(`Found ${assignedIssues.length} assigned "help wanted" issues.`);
let totalUnassigned = 0;
let timelineEvents = [];
try {
timelineEvents = await github.paginate(github.rest.issues.listEventsForTimeline, {
owner,
repo,
issue_number: issue.number,
per_page: 100,
mediaType: { previews: ['mockingbird'] },
});
} catch (err) {
core.warning(`Could not fetch timeline for issue #${issue.number}: ${err.message}`);
continue;
}
const assignedAtMap = new Map();
for (const event of timelineEvents) {
if (event.event === 'assigned' && event.assignee) {
const login = event.assignee.login.toLowerCase();
const at = new Date(event.created_at);
assignedAtMap.set(login, at);
} else if (event.event === 'unassigned' && event.assignee) {
assignedAtMap.delete(event.assignee.login.toLowerCase());
}
}
const linkedPRAuthorSet = new Set();
const seenPRKeys = new Set();
for (const event of timelineEvents) {
if (
event.event !== 'cross-referenced' ||
!event.source ||
event.source.type !== 'pull_request' ||
!event.source.issue ||
!event.source.issue.user ||
!event.source.issue.number ||
!event.source.issue.repository
) continue;
const prOwner = event.source.issue.repository.owner.login;
const prRepo = event.source.issue.repository.name;
const prNumber = event.source.issue.number;
const prAuthor = event.source.issue.user.login.toLowerCase();
const prKey = `${prOwner}/${prRepo}#${prNumber}`;
if (seenPRKeys.has(prKey)) continue;
seenPRKeys.add(prKey);
try {
const { data: pr } = await github.rest.pulls.get({
owner: prOwner,
repo: prRepo,
pull_number: prNumber,
});
const isReady = (pr.state === 'open' && !pr.draft) ||
(pr.state === 'closed' && pr.merged_at !== null);
core.info(
` PR ${prKey} by @${prAuthor}: ` +
`state=${pr.state}, draft=${pr.draft}, merged=${!!pr.merged_at} → ` +
(isReady ? 'qualifies' : 'does NOT qualify (draft or closed without merge)')
);
if (isReady) linkedPRAuthorSet.add(prAuthor);
} catch (err) {
core.warning(`Could not fetch PR ${prKey}: ${err.message}`);
}
}
const assigneesToRemove = [];
for (const assignee of issue.assignees) {
const login = assignee.login.toLowerCase();
if (await isPrivilegedUser(assignee.login)) {
core.info(` @${assignee.login}: privileged user — skipping.`);
continue;
}
const assignedAt = assignedAtMap.get(login);
if (!assignedAt) {
core.warning(
`No 'assigned' event found for @${login} on issue #${issue.number}; ` +
`falling back to issue creation date (${issue.created_at}).`
);
assignedAtMap.set(login, new Date(issue.created_at));
}
const resolvedAssignedAt = assignedAtMap.get(login);
const daysSinceAssignment = (now - resolvedAssignedAt) / (1000 * 60 * 60 * 24);
core.info(
` @${login}: assigned ${daysSinceAssignment.toFixed(1)} day(s) ago, ` +
`ready-for-review PR: ${linkedPRAuthorSet.has(login) ? 'yes' : 'no'}`
);
if (daysSinceAssignment < GRACE_PERIOD_DAYS) {
core.info(` → within grace period, skipping.`);
continue;
}
if (linkedPRAuthorSet.has(login)) {
core.info(` → ready-for-review PR found, keeping assignment.`);
continue;
}
core.info(` → no ready-for-review PR after ${GRACE_PERIOD_DAYS} days, will unassign.`);
assigneesToRemove.push(assignee.login);
}
if (assigneesToRemove.length === 0) {
continue;
}
if (!dryRun) {
try {
await github.rest.issues.removeAssignees({
owner,
repo,
issue_number: issue.number,
assignees: assigneesToRemove,
});
} catch (err) {
core.warning(
`Failed to unassign ${assigneesToRemove.join(', ')} from issue #${issue.number}: ${err.message}`
);
continue;
}
const mentionList = assigneesToRemove.map((l) => `@${l}`).join(', ');
const commentBody =
`👋 ${mentionList} — it has been more than ${GRACE_PERIOD_DAYS} days since ` +
`you were assigned to this issue and we could not find a pull request ` +
`ready for review.\n\n` +
`To keep the backlog moving and ensure issues stay accessible to all ` +
`contributors, we require a PR that is open and ready for review (not a ` +
`draft) within ${GRACE_PERIOD_DAYS} days of assignment.\n\n` +
`We are automatically unassigning you so that other contributors can pick ` +
`this up. If you are still actively working on this, please:\n` +
`1. Re-assign yourself by commenting \`/assign\`.\n` +
`2. Open a PR (not a draft) linked to this issue (e.g. \`Fixes #${issue.number}\`) ` +
`within ${GRACE_PERIOD_DAYS} days so the automation knows real progress is being made.\n\n` +
`Thank you for your contribution — we hope to see a PR from you soon! 🙏`;
try {
await github.rest.issues.createComment({
owner,
repo,
issue_number: issue.number,
body: commentBody,
});
} catch (err) {
core.warning(
`Failed to post comment on issue #${issue.number}: ${err.message}`
);
}
}
totalUnassigned += assigneesToRemove.length;
core.info(
` ${dryRun ? '[DRY RUN] Would have unassigned' : 'Unassigned'}: ${assigneesToRemove.join(', ')}`
);
}
core.info(`\nDone. Total assignees ${dryRun ? 'that would be' : ''} unassigned: ${totalUnassigned}`);
+1 -6
View File
@@ -28,13 +28,8 @@ on:
jobs: jobs:
verify-release: verify-release:
if: "github.repository == 'google-gemini/gemini-cli'"
environment: "${{ github.event.inputs.environment || 'prod' }}" environment: "${{ github.event.inputs.environment || 'prod' }}"
strategy: runs-on: 'ubuntu-latest'
fail-fast: false
matrix:
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
runs-on: '${{ matrix.os }}'
permissions: permissions:
contents: 'read' contents: 'read'
packages: 'write' packages: 'write'
-3
View File
@@ -46,7 +46,6 @@ packages/*/coverage/
# Generated files # Generated files
packages/cli/src/generated/ packages/cli/src/generated/
packages/core/src/generated/ packages/core/src/generated/
packages/devtools/src/_client-assets.ts
.integration-tests/ .integration-tests/
packages/vscode-ide-companion/*.vsix packages/vscode-ide-companion/*.vsix
packages/cli/download-ripgrep*/ packages/cli/download-ripgrep*/
@@ -62,5 +61,3 @@ gemini-debug.log
.gemini-clipboard/ .gemini-clipboard/
.eslintcache .eslintcache
evals/logs/ evals/logs/
temp_agents/
-1
View File
@@ -21,4 +21,3 @@ junit.xml
Thumbs.db Thumbs.db
.pytest_cache .pytest_cache
**/SKILL.md **/SKILL.md
packages/sdk/test-data/*.json
-3
View File
@@ -7,9 +7,6 @@
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": { "[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
+34 -61
View File
@@ -60,54 +60,26 @@ All submissions, including submissions by project members, require review. We
use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests) use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests)
for this purpose. for this purpose.
To assist with the review process, we provide an automated review tool that If your pull request involves changes to `packages/cli` (the frontend), we
helps detect common anti-patterns, testing issues, and other best practices that recommend running our automated frontend review tool. **Note: This tool is
are easy to miss. currently experimental.** It helps detect common React anti-patterns, testing
issues, and other frontend-specific best practices that are easy to miss.
#### Using the automated review tool To run the review tool, enter the following command from within Gemini CLI:
You can run the review tool in two ways: ```text
/review-frontend <PR_NUMBER>
```
1. **Using the helper script (Recommended):** We provide a script that Replace `<PR_NUMBER>` with your pull request number. Authors are encouraged to
automatically handles checking out the PR into a separate worktree, run this on their own PRs for self-review, and reviewers should use it to
installing dependencies, building the project, and launching the review augment their manual review process.
tool.
```bash ### Self assigning issues
./scripts/review.sh <PR_NUMBER> [model]
```
**Warning:** If you run `scripts/review.sh`, you must have first verified To assign an issue to yourself, simply add a comment with the text `/assign`.
that the code for the PR being reviewed is safe to run and does not contain The comment must contain only that text and nothing else. This command will
data exfiltration attacks. assign the issue to you, provided it is not already assigned.
**Authors are strongly encouraged to run this script on their own PRs**
immediately after creation. This allows you to catch and fix simple issues
locally before a maintainer performs a full review.
**Note on Models:** By default, the script uses the latest Pro model
(`gemini-3.1-pro-preview`). If you do not have enough Pro quota, you can run
it with the latest Flash model instead:
`./scripts/review.sh <PR_NUMBER> gemini-3-flash-preview`.
2. **Manually from within Gemini CLI:** If you already have the PR checked out
and built, you can run the tool directly from the CLI prompt:
```text
/review-frontend <PR_NUMBER>
```
Replace `<PR_NUMBER>` with your pull request number. Reviewers should use this
tool to augment, not replace, their manual review process.
### Self-assigning and unassigning issues
To assign an issue to yourself, simply add a comment with the text `/assign`. To
unassign yourself from an issue, add a comment with the text `/unassign`.
The comment must contain only that text and nothing else. These commands will
assign or unassign the issue as requested, provided the conditions are met
(e.g., an issue must be unassigned to be assigned).
Please note that you can have a maximum of 3 issues assigned to you at any given Please note that you can have a maximum of 3 issues assigned to you at any given
time. time.
@@ -292,8 +264,7 @@ npm run test:e2e
``` ```
For more detailed information on the integration testing framework, please see For more detailed information on the integration testing framework, please see
the the [Integration Tests documentation](/docs/integration-tests.md).
[Integration Tests documentation](https://geminicli.com/docs/integration-tests).
### Linting and preflight checks ### Linting and preflight checks
@@ -346,9 +317,11 @@ npm run lint
- Please adhere to the coding style, patterns, and conventions used throughout - Please adhere to the coding style, patterns, and conventions used throughout
the existing codebase. the existing codebase.
- Consult [GEMINI.md](../GEMINI.md) (typically found in the project root) for - Consult
specific instructions related to AI-assisted development, including [GEMINI.md](https://github.com/google-gemini/gemini-cli/blob/main/GEMINI.md)
conventions for React, comments, and Git usage. (typically found in the project root) for specific instructions related to
AI-assisted development, including conventions for React, comments, and Git
usage.
- **Imports:** Pay special attention to import paths. The project uses ESLint to - **Imports:** Pay special attention to import paths. The project uses ESLint to
enforce restrictions on relative imports between packages. enforce restrictions on relative imports between packages.
@@ -399,7 +372,8 @@ specific debug settings.
### React DevTools ### 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:** 1. **Start the Gemini CLI in development mode:**
@@ -407,20 +381,20 @@ To debug the CLI's React-based UI, you can use React DevTools.
DEV=true npm start DEV=true npm start
``` ```
2. **Install and run React DevTools version 6 (which matches the CLI's 2. **Install and run React DevTools version 4.28.5 (or the latest compatible
`react-devtools-core`):** 4.x version):**
You can either install it globally: You can either install it globally:
```bash ```bash
npm install -g react-devtools@6 npm install -g react-devtools@4.28.5
react-devtools react-devtools
``` ```
Or run it directly using npx: Or run it directly using npx:
```bash ```bash
npx react-devtools@6 npx react-devtools@4.28.5
``` ```
Your running CLI application should then connect to React DevTools. Your running CLI application should then connect to React DevTools.
@@ -434,13 +408,12 @@ On macOS, `gemini` uses Seatbelt (`sandbox-exec`) under a `permissive-open`
profile (see `packages/cli/src/utils/sandbox-macos-permissive-open.sb`) that profile (see `packages/cli/src/utils/sandbox-macos-permissive-open.sb`) that
restricts writes to the project folder but otherwise allows all other operations restricts writes to the project folder but otherwise allows all other operations
and outbound network traffic ("open") by default. You can switch to a and outbound network traffic ("open") by default. You can switch to a
`strict-open` profile (see `restrictive-closed` profile (see
`packages/cli/src/utils/sandbox-macos-strict-open.sb`) that restricts both reads `packages/cli/src/utils/sandbox-macos-restrictive-closed.sb`) that declines all
and writes to the working directory while allowing outbound network traffic by operations and outbound network traffic ("closed") by default by setting
setting `SEATBELT_PROFILE=strict-open` in your environment or `.env` file. `SEATBELT_PROFILE=restrictive-closed` in your environment or `.env` file.
Available built-in profiles are `permissive-{open,proxied}`, Available built-in profiles are `{permissive,restrictive}-{open,closed,proxied}`
`restrictive-{open,proxied}`, and `strict-{open,proxied}` (see below for proxied (see below for proxied networking). You can also switch to a custom profile
networking). You can also switch to a custom profile
`SEATBELT_PROFILE=<profile>` if you also create a file `SEATBELT_PROFILE=<profile>` if you also create a file
`.gemini/sandbox-macos-<profile>.sb` under your project settings directory `.gemini/sandbox-macos-<profile>.sb` under your project settings directory
`.gemini`. `.gemini`.
@@ -572,7 +545,7 @@ Before submitting your documentation pull request, please:
If you have questions about contributing documentation: If you have questions about contributing documentation:
- Check our [FAQ](https://geminicli.com/docs/resources/faq). - Check our [FAQ](/docs/faq.md).
- Review existing documentation for examples. - Review existing documentation for examples.
- Open [an issue](https://github.com/google-gemini/gemini-cli/issues) to discuss - Open [an issue](https://github.com/google-gemini/gemini-cli/issues) to discuss
your proposed changes. your proposed changes.
+1 -4
View File
@@ -42,10 +42,7 @@ USER node
# install gemini-cli and clean up # install gemini-cli and clean up
COPY packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz 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 COPY packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz
RUN npm install -g /tmp/gemini-core.tgz \ RUN npm install -g /tmp/gemini-cli.tgz /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 \
&& npm cache clean --force \ && npm cache clean --force \
&& rm -f /tmp/gemini-{cli,core}.tgz && rm -f /tmp/gemini-{cli,core}.tgz
+1 -16
View File
@@ -47,35 +47,20 @@ powerful tool for developers.
be relative to the workspace root, e.g., be relative to the workspace root, e.g.,
`-w @google/gemini-cli-core -- src/routing/modelRouterService.test.ts`) `-w @google/gemini-cli-core -- src/routing/modelRouterService.test.ts`)
- **Full Validation:** `npm run preflight` (Heaviest check; runs clean, install, - **Full Validation:** `npm run preflight` (Heaviest check; runs clean, install,
build, lint, type check, and tests. Recommended before submitting PRs. Due to build, lint, type check, and tests. Recommended before submitting PRs.)
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.)
- **Individual Checks:** `npm run lint` / `npm run format` / `npm run typecheck` - **Individual Checks:** `npm run lint` / `npm run format` / `npm run typecheck`
## Development Conventions ## Development Conventions
- **Legacy Snippets:** `packages/core/src/prompts/snippets.legacy.ts` is a
snapshot of an older system prompt. Avoid changing the prompting verbiage to
preserve its historical behavior; however, structural changes to ensure
compilation or simplify the code are permitted.
- **Contributions:** Follow the process outlined in `CONTRIBUTING.md`. Requires - **Contributions:** Follow the process outlined in `CONTRIBUTING.md`. Requires
signing the Google CLA. signing the Google CLA.
- **Pull Requests:** Keep PRs small, focused, and linked to an existing issue. - **Pull Requests:** Keep PRs small, focused, and linked to an existing issue.
Always activate the `pr-creator` skill for PR generation, even when using the
`gh` CLI.
- **Commit Messages:** Follow the - **Commit Messages:** Follow the
[Conventional Commits](https://www.conventionalcommits.org/) standard. [Conventional Commits](https://www.conventionalcommits.org/) standard.
- **Coding Style:** Adhere to existing patterns in `packages/cli` (React/Ink) - **Coding Style:** Adhere to existing patterns in `packages/cli` (React/Ink)
and `packages/core` (Backend logic). and `packages/core` (Backend logic).
- **Imports:** Use specific imports and avoid restricted relative imports - **Imports:** Use specific imports and avoid restricted relative imports
between packages (enforced by ESLint). between packages (enforced by ESLint).
- **License Headers:** For all new source code files (`.ts`, `.tsx`, `.js`),
include the Apache-2.0 license header with the current year. (e.g.,
`Copyright 2026 Google LLC`). This is enforced by ESLint.
## Testing Conventions ## Testing Conventions
+21 -21
View File
@@ -6,7 +6,7 @@
[![License](https://img.shields.io/github/license/google-gemini/gemini-cli)](https://github.com/google-gemini/gemini-cli/blob/main/LICENSE) [![License](https://img.shields.io/github/license/google-gemini/gemini-cli)](https://github.com/google-gemini/gemini-cli/blob/main/LICENSE)
[![View Code Wiki](https://assets.codewiki.google/readme-badge/static.svg)](https://codewiki.google/github.com/google-gemini/gemini-cli?utm_source=badge&utm_medium=github&utm_campaign=github.com/google-gemini/gemini-cli) [![View Code Wiki](https://assets.codewiki.google/readme-badge/static.svg)](https://codewiki.google/github.com/google-gemini/gemini-cli?utm_source=badge&utm_medium=github&utm_campaign=github.com/google-gemini/gemini-cli)
![Gemini CLI Screenshot](/docs/assets/gemini-screenshot.png) ![Gemini CLI Screenshot](./docs/assets/gemini-screenshot.png)
Gemini CLI is an open-source AI agent that brings the power of Gemini directly Gemini CLI is an open-source AI agent that brings the power of Gemini directly
into your terminal. It provides lightweight access to Gemini, giving you the into your terminal. It provides lightweight access to Gemini, giving you the
@@ -29,9 +29,10 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
## 📦 Installation ## 📦 Installation
See ### Pre-requisites before installation
[Gemini CLI installation, execution, and releases](./docs/get-started/installation.md)
for recommended system specifications and a detailed installation guide. - Node.js version 20 or higher
- macOS, Linux, or Windows
### Quick Install ### Quick Install
@@ -77,7 +78,7 @@ See [Releases](./docs/releases.md) for more details.
### Preview ### Preview
New preview releases will be published each week at UTC 23:59 on Tuesdays. These New preview releases will be published each week at UTC 2359 on Tuesdays. These
releases will not have been fully vetted and may contain regressions or other releases will not have been fully vetted and may contain regressions or other
outstanding issues. Please help us test and install with `preview` tag. outstanding issues. Please help us test and install with `preview` tag.
@@ -87,7 +88,7 @@ npm install -g @google/gemini-cli@preview
### Stable ### Stable
- New stable releases will be published each week at UTC 20:00 on Tuesdays, this - New stable releases will be published each week at UTC 2000 on Tuesdays, this
will be the full promotion of last week's `preview` release + any bug fixes will be the full promotion of last week's `preview` release + any bug fixes
and validations. Use `latest` tag. and validations. Use `latest` tag.
@@ -97,7 +98,7 @@ npm install -g @google/gemini-cli@latest
### Nightly ### Nightly
- New releases will be published each day at UTC 00:00. This will be all changes - New releases will be published each day at UTC 0000. This will be all changes
from the main branch as represented at time of release. It should be assumed from the main branch as represented at time of release. It should be assumed
there are pending validations and issues. Use `nightly` tag. there are pending validations and issues. Use `nightly` tag.
@@ -147,7 +148,7 @@ Integrate Gemini CLI directly into your GitHub workflows with
Choose the authentication method that best fits your needs: Choose the authentication method that best fits your needs:
### Option 1: Sign in with Google (OAuth login using your Google Account) ### Option 1: Login with Google (OAuth login using your Google Account)
**✨ Best for:** Individual developers as well as anyone who has a Gemini Code **✨ Best for:** Individual developers as well as anyone who has a Gemini Code
Assist License. (see Assist License. (see
@@ -161,7 +162,7 @@ for details)
- **No API key management** - just sign in with your Google account - **No API key management** - just sign in with your Google account
- **Automatic updates** to latest models - **Automatic updates** to latest models
#### Start Gemini CLI, then choose _Sign in with Google_ and follow the browser authentication flow when prompted #### Start Gemini CLI, then choose _Login with Google_ and follow the browser authentication flow when prompted
```bash ```bash
gemini gemini
@@ -282,14 +283,14 @@ gemini
quickly. quickly.
- [**Authentication Setup**](./docs/get-started/authentication.md) - Detailed - [**Authentication Setup**](./docs/get-started/authentication.md) - Detailed
auth configuration. auth configuration.
- [**Configuration Guide**](./docs/reference/configuration.md) - Settings and - [**Configuration Guide**](./docs/get-started/configuration.md) - Settings and
customization. customization.
- [**Keyboard Shortcuts**](./docs/reference/keyboard-shortcuts.md) - - [**Keyboard Shortcuts**](./docs/cli/keyboard-shortcuts.md) - Productivity
Productivity tips. tips.
### Core Features ### Core Features
- [**Commands Reference**](./docs/reference/commands.md) - All slash commands - [**Commands Reference**](./docs/cli/commands.md) - All slash commands
(`/help`, `/chat`, etc). (`/help`, `/chat`, etc).
- [**Custom Commands**](./docs/cli/custom-commands.md) - Create your own - [**Custom Commands**](./docs/cli/custom-commands.md) - Create your own
reusable commands. reusable commands.
@@ -301,7 +302,7 @@ gemini
### Tools & Extensions ### Tools & Extensions
- [**Built-in Tools Overview**](./docs/reference/tools.md) - [**Built-in Tools Overview**](./docs/tools/index.md)
- [File System Operations](./docs/tools/file-system.md) - [File System Operations](./docs/tools/file-system.md)
- [Shell Commands](./docs/tools/shell.md) - [Shell Commands](./docs/tools/shell.md)
- [Web Fetch & Search](./docs/tools/web-fetch.md) - [Web Fetch & Search](./docs/tools/web-fetch.md)
@@ -323,15 +324,15 @@ gemini
- [**Enterprise Guide**](./docs/cli/enterprise.md) - Deploy and manage in a - [**Enterprise Guide**](./docs/cli/enterprise.md) - Deploy and manage in a
corporate environment. corporate environment.
- [**Telemetry & Monitoring**](./docs/cli/telemetry.md) - Usage tracking. - [**Telemetry & Monitoring**](./docs/cli/telemetry.md) - Usage tracking.
- [**Tools reference**](./docs/reference/tools.md) - Built-in tools overview. - [**Tools API Development**](./docs/core/tools-api.md) - Create custom tools.
- [**Local development**](./docs/local-development.md) - Local development - [**Local development**](./docs/local-development.md) - Local development
tooling. tooling.
### Troubleshooting & Support ### Troubleshooting & Support
- [**Troubleshooting Guide**](./docs/resources/troubleshooting.md) - Common - [**Troubleshooting Guide**](./docs/troubleshooting.md) - Common issues and
issues and solutions. solutions.
- [**FAQ**](./docs/resources/faq.md) - Frequently asked questions. - [**FAQ**](./docs/faq.md) - Frequently asked questions.
- Use `/bug` command to report issues directly from the CLI. - Use `/bug` command to report issues directly from the CLI.
### Using MCP Servers ### Using MCP Servers
@@ -377,13 +378,12 @@ for planned features and priorities.
### Uninstall ### Uninstall
See the [Uninstall Guide](./docs/resources/uninstall.md) for removal See the [Uninstall Guide](docs/cli/uninstall.md) for removal instructions.
instructions.
## 📄 Legal ## 📄 Legal
- **License**: [Apache License 2.0](LICENSE) - **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) - **Security**: [Security Policy](SECURITY.md)
--- ---
-115
View File
@@ -1,115 +0,0 @@
# Enterprise Admin Controls
Gemini CLI empowers enterprise administrators to manage and enforce security
policies and configuration settings across their entire organization. Secure
defaults are enabled automatically for all enterprise users, but can be
customized via the [Management Console](https://goo.gle/manage-gemini-cli).
**Enterprise Admin Controls are enforced globally and cannot be overridden by
users locally**, ensuring a consistent security posture.
## Admin Controls vs. System Settings
While [System-wide settings](../cli/settings.md) act as convenient configuration
overrides, they can still be modified by users with sufficient privileges. In
contrast, admin controls are immutable at the local level, making them the
preferred method for enforcing policy.
## Available Controls
### Strict Mode
**Enabled/Disabled** | Default: enabled
If enabled, users will not be able to enter yolo mode.
### Extensions
**Enabled/Disabled** | Default: disabled
If disabled, users will not be able to use or install extensions. See
[Extensions](../extensions/index.md) for more details.
### MCP
#### Enabled/Disabled
**Enabled/Disabled** | Default: disabled
If disabled, users will not be able to use MCP servers. See
[MCP Server Integration](../tools/mcp-server.md) for more details.
#### MCP Servers (preview)
**Default**: empty
Allows administrators to define an explicit allowlist of MCP servers. This
guarantees that users can only connect to trusted MCP servers defined by the
organization.
**Allowlist Format:**
```json
{
"mcpServers": {
"external-provider": {
"url": "https://api.mcp-provider.com",
"type": "sse",
"trust": true,
"includeTools": ["toolA", "toolB"],
"excludeTools": []
},
"internal-corp-tool": {
"url": "https://mcp.internal-tool.corp",
"type": "http",
"includeTools": [],
"excludeTools": ["adminTool"]
}
}
}
```
**Supported Fields:**
- `url`: (Required) The full URL of the MCP server endpoint.
- `type`: (Required) The connection type (e.g., `sse` or `http`).
- `trust`: (Optional) If set to `true`, the server is trusted and tool execution
will not require user approval.
- `includeTools`: (Optional) An explicit list of tool names to allow. If
specified, only these tools will be available.
- `excludeTools`: (Optional) A list of tool names to hide. These tools will be
blocked.
**Client Enforcement Logic:**
- **Empty Allowlist**: If the admin allowlist is empty, the client uses the
users local configuration as is (unless the MCP toggle above is disabled).
- **Active Allowlist**: If the allowlist contains one or more servers, **all
locally configured servers not present in the allowlist are ignored**.
- **Configuration Merging**: For a server to be active, it must exist in
**both** the admin allowlist and the users local configuration (matched by
name). The client merges these definitions as follows:
- **Override Fields**: The `url`, `type`, & `trust` are always taken from the
admin allowlist, overriding any local values.
- **Tools Filtering**: If `includeTools` or `excludeTools` are defined in the
allowlist, the admins rules are used exclusively. If both are undefined in
the admin allowlist, the client falls back to the users local tool
settings.
- **Cleared Fields**: To ensure security and consistency, the client
automatically clears local execution fields (`command`, `args`, `env`,
`cwd`, `httpUrl`, `tcp`). This prevents users from overriding the connection
method.
- **Other Fields**: All other MCP fields are pulled from the users local
configuration.
- **Missing Allowlisted Servers**: If a server appears in the admin allowlist
but is missing from the local configuration, it will not be initialized. This
ensures users maintain final control over which permitted servers are actually
active in their environment.
### Unmanaged Capabilities
**Enabled/Disabled** | Default: disabled
If disabled, users will not be able to use certain features. Currently, this
control disables Agent Skills. See [Agent Skills](../cli/skills.md) for more
details.
+80
View File
@@ -0,0 +1,80 @@
# Gemini CLI Architecture Overview
This document provides a high-level overview of the Gemini CLI's architecture.
## Core components
The Gemini CLI is primarily composed of two main packages, along with a suite of
tools that can be used by the system in the course of handling command-line
input:
1. **CLI package (`packages/cli`):**
- **Purpose:** This contains the user-facing portion of the Gemini CLI, such
as handling the initial user input, presenting the final output, and
managing the overall user experience.
- **Key functions contained in the package:**
- [Input processing](/docs/cli/commands)
- History management
- Display rendering
- [Theme and UI customization](/docs/cli/themes)
- [CLI configuration settings](/docs/get-started/configuration)
2. **Core package (`packages/core`):**
- **Purpose:** This acts as the backend for the Gemini CLI. It receives
requests sent from `packages/cli`, orchestrates interactions with the
Gemini API, and manages the execution of available tools.
- **Key functions contained in the package:**
- API client for communicating with the Google Gemini API
- Prompt construction and management
- Tool registration and execution logic
- State management for conversations or sessions
- Server-side configuration
3. **Tools (`packages/core/src/tools/`):**
- **Purpose:** These are individual modules that extend the capabilities of
the Gemini model, allowing it to interact with the local environment
(e.g., file system, shell commands, web fetching).
- **Interaction:** `packages/core` invokes these tools based on requests
from the Gemini model.
## Interaction flow
A typical interaction with the Gemini CLI follows this flow:
1. **User input:** The user types a prompt or command into the terminal, which
is managed by `packages/cli`.
2. **Request to core:** `packages/cli` sends the user's input to
`packages/core`.
3. **Request processed:** The core package:
- Constructs an appropriate prompt for the Gemini API, possibly including
conversation history and available tool definitions.
- Sends the prompt to the Gemini API.
4. **Gemini API response:** The Gemini API processes the prompt and returns a
response. This response might be a direct answer or a request to use one of
the available tools.
5. **Tool execution (if applicable):**
- When the Gemini API requests a tool, the core package prepares to execute
it.
- If the requested tool can modify the file system or execute shell
commands, the user is first given details of the tool and its arguments,
and the user must approve the execution.
- Read-only operations, such as reading files, might not require explicit
user confirmation to proceed.
- Once confirmed, or if confirmation is not required, the core package
executes the relevant action within the relevant tool, and the result is
sent back to the Gemini API by the core package.
- The Gemini API processes the tool result and generates a final response.
6. **Response to CLI:** The core package sends the final response back to the
CLI package.
7. **Display to user:** The CLI package formats and displays the response to
the user in the terminal.
## Key design principles
- **Modularity:** Separating the CLI (frontend) from the Core (backend) allows
for independent development and potential future extensions (e.g., different
frontends for the same backend).
- **Extensibility:** The tool system is designed to be extensible, allowing new
capabilities to be added.
- **User experience:** The CLI focuses on providing a rich and interactive
terminal experience.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 125 KiB

+3 -146
View File
@@ -18,147 +18,6 @@ on GitHub.
| [Preview](preview.md) | Experimental features ready for early feedback. | | [Preview](preview.md) | Experimental features ready for early feedback. |
| [Stable](latest.md) | Stable, recommended for general use. | | [Stable](latest.md) | Stable, recommended for general use. |
## Announcements: v0.33.0 - 2026-03-11
- **Agent Architecture Enhancements:** Introduced HTTP authentication for A2A
remote agents and authenticated A2A agent card discovery
([#20510](https://github.com/google-gemini/gemini-cli/pull/20510) by
@SandyTao520, [#20622](https://github.com/google-gemini/gemini-cli/pull/20622)
by @SandyTao520).
- **Plan Mode Updates:** Expanded Plan Mode with built-in research subagents,
annotation support for feedback, and a new `copy` subcommand
([#20972](https://github.com/google-gemini/gemini-cli/pull/20972) by @Adib234,
[#20988](https://github.com/google-gemini/gemini-cli/pull/20988) by
@ruomengz).
- **CLI UX & Admin Controls:** Redesigned the header to be compact with an ASCII
icon, inverted context window display to show usage, and enabled a 30-day
default retention for chat history
([#18713](https://github.com/google-gemini/gemini-cli/pull/18713) by
@keithguerin, [#20853](https://github.com/google-gemini/gemini-cli/pull/20853)
by @skeshive).
## Announcements: v0.32.0 - 2026-03-03
- **Generalist Agent:** The generalist agent is now enabled to improve task
delegation and routing
([#19665](https://github.com/google-gemini/gemini-cli/pull/19665) by
@joshualitt).
- **Model Steering in Workspace:** Added support for model steering directly in
the workspace
([#20343](https://github.com/google-gemini/gemini-cli/pull/20343) by
@joshualitt).
- **Plan Mode Enhancements:** Users can now open and modify plans in an external
editor, and the planning workflow has been adapted to handle complex tasks
more effectively with multi-select options
([#20348](https://github.com/google-gemini/gemini-cli/pull/20348) by @Adib234,
[#20465](https://github.com/google-gemini/gemini-cli/pull/20465) by @jerop).
- **Interactive Shell Autocompletion:** Introduced interactive shell
autocompletion for a more seamless experience
([#20082](https://github.com/google-gemini/gemini-cli/pull/20082) by
@mrpmohiburrahman).
- **Parallel Extension Loading:** Extensions are now loaded in parallel to
improve startup times
([#20229](https://github.com/google-gemini/gemini-cli/pull/20229) by
@scidomino).
## Announcements: v0.31.0 - 2026-02-27
- **Gemini 3.1 Pro Preview:** Gemini CLI now supports the new Gemini 3.1 Pro
Preview model
([#19676](https://github.com/google-gemini/gemini-cli/pull/19676) by
@sehoon38).
- **Experimental Browser Agent:** We've introduced a new experimental browser
agent to interact with web pages
([#19284](https://github.com/google-gemini/gemini-cli/pull/19284) by
@gsquared94).
- **Policy Engine Updates:** The policy engine now supports project-level
policies, MCP server wildcards, and tool annotation matching
([#18682](https://github.com/google-gemini/gemini-cli/pull/18682) by
@Abhijit-2592,
[#20024](https://github.com/google-gemini/gemini-cli/pull/20024) by @jerop).
- **Web Fetch Improvements:** We've implemented an experimental direct web fetch
feature and added rate limiting to mitigate DDoS risks
([#19557](https://github.com/google-gemini/gemini-cli/pull/19557) by @mbleigh,
[#19567](https://github.com/google-gemini/gemini-cli/pull/19567) by
@mattKorwel).
## 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
- **Slash Command:** We've added a new `/prompt-suggest` slash command to help
you generate prompt suggestions
([#17264](https://github.com/google-gemini/gemini-cli/pull/17264) by
@NTaylorMullen).
- **IDE Support:** Gemini CLI now supports the Positron IDE
([#15047](https://github.com/google-gemini/gemini-cli/pull/15047) by
@kapsner).
- **Customization:** You can now use custom themes in extensions, and we've
implemented automatic theme switching based on your terminal's background
([#17327](https://github.com/google-gemini/gemini-cli/pull/17327) by
@spencer426, [#17976](https://github.com/google-gemini/gemini-cli/pull/17976)
by @Abhijit-2592).
- **Authentication:** We've added interactive and non-interactive consent for
OAuth, and you can now include your auth method in bug reports
([#17699](https://github.com/google-gemini/gemini-cli/pull/17699) by
@ehedlund, [#17569](https://github.com/google-gemini/gemini-cli/pull/17569) by
@erikus).
## Announcements: v0.27.0 - 2026-02-03
- **Event-Driven Architecture:** The CLI now uses a new event-driven scheduler
for tool execution, resulting in a more responsive and performant experience
([#17078](https://github.com/google-gemini/gemini-cli/pull/17078) by
@abhipatel12).
- **Enhanced User Experience:** This release includes queued tool confirmations,
and expandable large text pastes for a smoother workflow.
- **New `/rewind` Command:** Easily navigate your session history with the new
`/rewind` command
([#15720](https://github.com/google-gemini/gemini-cli/pull/15720) by
@Adib234).
- **Linux Clipboard Support:** You can now paste images on Linux with Wayland
and X11 ([#17144](https://github.com/google-gemini/gemini-cli/pull/17144) by
@devr0306).
## Announcements: v0.26.0 - 2026-01-27 ## Announcements: v0.26.0 - 2026-01-27
- **Agents and Skills:** We've introduced a new `skill-creator` skill - **Agents and Skills:** We've introduced a new `skill-creator` skill
@@ -381,8 +240,7 @@ on GitHub.
- **Experimental permission improvements:** We are now experimenting with a new - **Experimental permission improvements:** We are now experimenting with a new
policy engine in Gemini CLI. This allows users and administrators to create policy engine in Gemini CLI. This allows users and administrators to create
fine-grained policy for tool calls. Currently behind a flag. See fine-grained policy for tool calls. Currently behind a flag. See
[policy engine documentation](../reference/policy-engine.md) for more [policy engine documentation](../core/policy-engine.md) for more information.
information.
- Blog: - Blog:
[https://allen.hutchison.org/2025/11/26/the-guardrails-of-autonomy/](https://allen.hutchison.org/2025/11/26/the-guardrails-of-autonomy/) [https://allen.hutchison.org/2025/11/26/the-guardrails-of-autonomy/](https://allen.hutchison.org/2025/11/26/the-guardrails-of-autonomy/)
- **Gemini 3 support for paid:** Gemini 3 support has been rolled out to all API - **Gemini 3 support for paid:** Gemini 3 support has been rolled out to all API
@@ -507,9 +365,8 @@ on GitHub.
page in their default browser directly from the CLI using the `/extension` page in their default browser directly from the CLI using the `/extension`
explore command. ([pr](https://github.com/google-gemini/gemini-cli/pull/11846) explore command. ([pr](https://github.com/google-gemini/gemini-cli/pull/11846)
by [@JayadityaGit](https://github.com/JayadityaGit)). by [@JayadityaGit](https://github.com/JayadityaGit)).
- **Configurable compression:** Users can modify the context compression - **Configurable compression:** Users can modify the compression threshold in
threshold in `/settings` (decimal with percentage display). The default has `/settings`. The default has been made more proactive
been made more proactive
([pr](https://github.com/google-gemini/gemini-cli/pull/12317) by ([pr](https://github.com/google-gemini/gemini-cli/pull/12317) by
[@scidomino](https://github.com/scidomino)). [@scidomino](https://github.com/scidomino)).
- **API key authentication:** Users can now securely enter and store their - **API key authentication:** Users can now securely enter and store their
+320 -216
View File
@@ -1,6 +1,6 @@
# Latest stable release: v0.33.1 # Latest stable release: v0.26.0
Released: March 12, 2026 Released: January 27, 2026
For most users, our latest stable release is the recommended release. Install For most users, our latest stable release is the recommended release. Install
the latest stable version with: the latest stable version with:
@@ -11,224 +11,328 @@ npm install -g @google/gemini-cli
## Highlights ## Highlights
- **Agent Architecture Enhancements:** Introduced HTTP authentication support - **Enhanced Agent and Skill Capabilities:** This release introduces the new
for A2A remote agents, authenticated A2A agent card discovery, and directly `skill-creator` built-in skill, enables Agent Skills by default, and adds a
indicated auth-required states. generalist agent to improve task routing. Security for skill installation has
- **Plan Mode Updates:** Expanded Plan Mode capabilities with built-in research also been enhanced with new consent prompts.
subagents, annotation support for feedback during iteration, and a new `copy` - **Improved UI and UX:** A new "Rewind" feature lets you walk back through
subcommand. conversation history. We've also added an `/introspect` command for debugging
- **CLI UX Improvements:** Redesigned the header to be compact with an ASCII and unified various shell confirmation dialogs for a more consistent user
icon, inverted the context window display to show usage, and allowed sub-agent experience.
confirmation requests in the UI while preventing background flicker. - **Core Stability and Performance:** This release includes significant
- **ACP & MCP Integrations:** Implemented slash command handling in ACP for performance improvements, including a fix for PDF token estimation,
`/memory`, `/init`, `/extensions`, and `/restore`, added an MCPOAuthProvider, optimizations for large inputs, and prevention of OOM crashes. Key memory
and introduced a `set models` interface for ACP. management components like `LRUCache` have also been updated.
- **Admin & Core Stability:** Enabled a 30-day default retention for chat - **Scheduler and Policy Refactoring:** The core tool scheduler has been
history, added tool name validation in TOML policy files, and improved tool decoupled into distinct orchestration, policy, and confirmation components,
parameter extraction. and we've added an experimental event-driven scheduler to improve performance
and reliability.
## What's Changed ## What's Changed
- fix(patch): cherry-pick 8432bce to release/v0.33.0-pr-22069 to patch version - fix: PDF token estimation (#16494) by @korade-krushna in
v0.33.0 and create version 0.33.1 by @gemini-cli-robot in [#16527](https://github.com/google-gemini/gemini-cli/pull/16527)
[#22206](https://github.com/google-gemini/gemini-cli/pull/22206) - chore(release): bump version to 0.26.0-nightly.20260114.bb6c57414 by
- Docs: Update model docs to remove Preview Features. by @jkcinouye in
[#20084](https://github.com/google-gemini/gemini-cli/pull/20084)
- docs: fix typo in installation documentation by @AdityaSharma-Git3207 in
[#20153](https://github.com/google-gemini/gemini-cli/pull/20153)
- docs: add Windows PowerShell equivalents for environments and scripting by
@scidomino in [#20333](https://github.com/google-gemini/gemini-cli/pull/20333)
- fix(core): parse raw ASCII buffer strings in Gaxios errors by @sehoon38 in
[#20626](https://github.com/google-gemini/gemini-cli/pull/20626)
- chore(release): bump version to 0.33.0-nightly.20260227.ba149afa0 by @galz10
in [#20637](https://github.com/google-gemini/gemini-cli/pull/20637)
- fix(github): use robot PAT for automated PRs to pass CLA check by @galz10 in
[#20641](https://github.com/google-gemini/gemini-cli/pull/20641)
- chore/release: bump version to 0.33.0-nightly.20260228.1ca5c05d0 by
@gemini-cli-robot in @gemini-cli-robot in
[#20644](https://github.com/google-gemini/gemini-cli/pull/20644) [#16604](https://github.com/google-gemini/gemini-cli/pull/16604)
- Changelog for v0.31.0 by @gemini-cli-robot in - docs: clarify F12 to open debug console by @jackwotherspoon in
[#20634](https://github.com/google-gemini/gemini-cli/pull/20634) [#16570](https://github.com/google-gemini/gemini-cli/pull/16570)
- fix: use full paths for ACP diff payloads by @JagjeevanAK in - docs: Remove .md extension from internal links in architecture.md by
[#19539](https://github.com/google-gemini/gemini-cli/pull/19539) @medic-code in
- Changelog for v0.32.0-preview.0 by @gemini-cli-robot in [#12899](https://github.com/google-gemini/gemini-cli/pull/12899)
[#20627](https://github.com/google-gemini/gemini-cli/pull/20627) - Add an experimental setting for extension config by @chrstnb in
- fix: acp/zed race condition between MCP initialisation and prompt by [#16506](https://github.com/google-gemini/gemini-cli/pull/16506)
@kartikangiras in - feat: add Rewind Confirmation dialog and Rewind Viewer component by @Adib234
[#20205](https://github.com/google-gemini/gemini-cli/pull/20205) in [#15717](https://github.com/google-gemini/gemini-cli/pull/15717)
- fix(cli): reset themeManager between tests to ensure isolation by - fix(a2a): Don't throw errors for GeminiEventType Retry and InvalidStream. by
@ehedlund in [#16541](https://github.com/google-gemini/gemini-cli/pull/16541)
- prefactor: add rootCommands as array so it can be used for policy parsing by
@abhipatel12 in
[#16640](https://github.com/google-gemini/gemini-cli/pull/16640)
- remove unnecessary \x7f key bindings by @scidomino in
[#16646](https://github.com/google-gemini/gemini-cli/pull/16646)
- docs(skills): use body-file in pr-creator skill for better reliability by
@abhipatel12 in
[#16642](https://github.com/google-gemini/gemini-cli/pull/16642)
- chore(automation): recursive labeling for workstream descendants by @bdmorgan
in [#16609](https://github.com/google-gemini/gemini-cli/pull/16609)
- feat: introduce 'skill-creator' built-in skill and CJS management tools by
@NTaylorMullen in @NTaylorMullen in
[#20598](https://github.com/google-gemini/gemini-cli/pull/20598) [#16394](https://github.com/google-gemini/gemini-cli/pull/16394)
- refactor(core): Extract tool parameter names as constants by @SandyTao520 in - chore(automation): remove automated PR size and complexity labeler by
[#20460](https://github.com/google-gemini/gemini-cli/pull/20460) @bdmorgan in [#16648](https://github.com/google-gemini/gemini-cli/pull/16648)
- fix(cli): resolve autoThemeSwitching when background hasn't changed but theme - refactor(skills): replace 'project' with 'workspace' scope by @NTaylorMullen
mismatches by @sehoon38 in in [#16380](https://github.com/google-gemini/gemini-cli/pull/16380)
[#20706](https://github.com/google-gemini/gemini-cli/pull/20706) - Docs: Update release notes for 1/13/2026 by @jkcinouye in
- feat(skills): add github-issue-creator skill by @sehoon38 in [#16583](https://github.com/google-gemini/gemini-cli/pull/16583)
[#20709](https://github.com/google-gemini/gemini-cli/pull/20709) - Simplify paste handling by @scidomino in
- fix(cli): allow sub-agent confirmation requests in UI while preventing [#16654](https://github.com/google-gemini/gemini-cli/pull/16654)
background flicker by @abhipatel12 in - chore(automation): improve scheduled issue triage discovery and throughput by
[#20722](https://github.com/google-gemini/gemini-cli/pull/20722) @bdmorgan in [#16652](https://github.com/google-gemini/gemini-cli/pull/16652)
- Merge User and Agent Card Descriptions #20849 by @adamfweidman in - fix(acp): run exit cleanup when stdin closes by @codefromthecrypt in
[#20850](https://github.com/google-gemini/gemini-cli/pull/20850) [#14953](https://github.com/google-gemini/gemini-cli/pull/14953)
- fix(core): reduce LLM-based loop detection false positives by @SandyTao520 in - feat(scheduler): add types needed for event driven scheduler by @abhipatel12
[#20701](https://github.com/google-gemini/gemini-cli/pull/20701) in [#16641](https://github.com/google-gemini/gemini-cli/pull/16641)
- fix(plan): deflake plan mode integration tests by @Adib234 in - Remove unused rewind key binding by @scidomino in
[#20477](https://github.com/google-gemini/gemini-cli/pull/20477) [#16659](https://github.com/google-gemini/gemini-cli/pull/16659)
- Add /unassign support by @scidomino in - Remove sequence binding by @scidomino in
[#20864](https://github.com/google-gemini/gemini-cli/pull/20864) [#16664](https://github.com/google-gemini/gemini-cli/pull/16664)
- feat(core): implement HTTP authentication support for A2A remote agents by - feat(cli): undeprecate the --prompt flag by @alexaustin007 in
@SandyTao520 in [#13981](https://github.com/google-gemini/gemini-cli/pull/13981)
[#20510](https://github.com/google-gemini/gemini-cli/pull/20510) - chore: update dependabot configuration by @cosmopax in
- feat(core): centralize read_file limits and update gemini-3 description by [#13507](https://github.com/google-gemini/gemini-cli/pull/13507)
@aishaneeshah in - feat(config): add 'auto' alias for default model selection by @sehoon38 in
[#20619](https://github.com/google-gemini/gemini-cli/pull/20619) [#16661](https://github.com/google-gemini/gemini-cli/pull/16661)
- Do not block CI on evals by @gundermanc in - Enable & disable agents by @sehoon38 in
[#20870](https://github.com/google-gemini/gemini-cli/pull/20870) [#16225](https://github.com/google-gemini/gemini-cli/pull/16225)
- document node limitation for shift+tab by @scidomino in - cleanup: Improve keybindings by @scidomino in
[#20877](https://github.com/google-gemini/gemini-cli/pull/20877) [#16672](https://github.com/google-gemini/gemini-cli/pull/16672)
- Add install as an option when extension is selected. by @DavidAPierce in - Add timeout for shell-utils to prevent hangs. by @jacob314 in
[#20358](https://github.com/google-gemini/gemini-cli/pull/20358) [#16667](https://github.com/google-gemini/gemini-cli/pull/16667)
- Update CODEOWNERS for README.md reviewers by @g-samroberts in - feat(plan): add experimental plan flag by @jerop in
[#20860](https://github.com/google-gemini/gemini-cli/pull/20860) [#16650](https://github.com/google-gemini/gemini-cli/pull/16650)
- feat(core): truncate large MCP tool output by @SandyTao520 in - feat(cli): add security consent prompts for skill installation by
[#19365](https://github.com/google-gemini/gemini-cli/pull/19365) @NTaylorMullen in
- Subagent activity UX. by @gundermanc in [#16549](https://github.com/google-gemini/gemini-cli/pull/16549)
[#17570](https://github.com/google-gemini/gemini-cli/pull/17570) - fix: replace 3 consecutive periods with ellipsis character by @Vist233 in
- style(cli) : Dialog pattern for /hooks Command by @AbdulTawabJuly in [#16587](https://github.com/google-gemini/gemini-cli/pull/16587)
[#17930](https://github.com/google-gemini/gemini-cli/pull/17930) - chore(automation): ensure status/need-triage is applied and never cleared
- feat: redesign header to be compact with ASCII icon by @keithguerin in automatically by @bdmorgan in
[#18713](https://github.com/google-gemini/gemini-cli/pull/18713) [#16657](https://github.com/google-gemini/gemini-cli/pull/16657)
- fix(core): ensure subagents use qualified MCP tool names by @abhipatel12 in - fix: Handle colons in skill description frontmatter by @maru0804 in
[#20801](https://github.com/google-gemini/gemini-cli/pull/20801) [#16345](https://github.com/google-gemini/gemini-cli/pull/16345)
- feat(core): support authenticated A2A agent card discovery by @SandyTao520 in - refactor(core): harden skill frontmatter parsing by @NTaylorMullen in
[#20622](https://github.com/google-gemini/gemini-cli/pull/20622) [#16705](https://github.com/google-gemini/gemini-cli/pull/16705)
- refactor(cli): fully remove React anti patterns, improve type safety and fix - feat(skills): add conflict detection and warnings for skill overrides by
UX oversights in SettingsDialog.tsx by @psinha40898 in @NTaylorMullen in
[#18963](https://github.com/google-gemini/gemini-cli/pull/18963) [#16709](https://github.com/google-gemini/gemini-cli/pull/16709)
- Adding MCPOAuthProvider implementing the MCPSDK OAuthClientProvider by - feat(scheduler): add SchedulerStateManager for reactive tool state by
@Nayana-Parameswarappa in @abhipatel12 in
[#20121](https://github.com/google-gemini/gemini-cli/pull/20121) [#16651](https://github.com/google-gemini/gemini-cli/pull/16651)
- feat(core): add tool name validation in TOML policy files by @allenhutchison - chore(automation): enforce 'help wanted' label permissions and update
in [#19281](https://github.com/google-gemini/gemini-cli/pull/19281) guidelines by @bdmorgan in
- docs: fix broken markdown links in main README.md by @Hamdanbinhashim in [#16707](https://github.com/google-gemini/gemini-cli/pull/16707)
[#20300](https://github.com/google-gemini/gemini-cli/pull/20300) - fix(core): resolve circular dependency via tsconfig paths by @sehoon38 in
- refactor(core): replace manual syncPlanModeTools with declarative policy rules [#16730](https://github.com/google-gemini/gemini-cli/pull/16730)
by @jerop in [#20596](https://github.com/google-gemini/gemini-cli/pull/20596) - chore/release: bump version to 0.26.0-nightly.20260115.6cb3ae4e0 by
- fix(core): increase default headers timeout to 5 minutes by @gundermanc in @gemini-cli-robot in
[#20890](https://github.com/google-gemini/gemini-cli/pull/20890) [#16738](https://github.com/google-gemini/gemini-cli/pull/16738)
- feat(admin): enable 30 day default retention for chat history & remove warning - fix(automation): correct status/need-issue label matching wildcard by
@bdmorgan in [#16727](https://github.com/google-gemini/gemini-cli/pull/16727)
- fix(automation): prevent label-enforcer loop by ignoring all bots by @bdmorgan
in [#16746](https://github.com/google-gemini/gemini-cli/pull/16746)
- Add links to supported locations and minor fixes by @g-samroberts in
[#16476](https://github.com/google-gemini/gemini-cli/pull/16476)
- feat(policy): add source tracking to policy rules by @allenhutchison in
[#16670](https://github.com/google-gemini/gemini-cli/pull/16670)
- feat(automation): enforce '🔒 maintainer only' and fix bot loop by @bdmorgan
in [#16751](https://github.com/google-gemini/gemini-cli/pull/16751)
- Make merged settings non-nullable and fix all lints related to that. by
@jacob314 in [#16647](https://github.com/google-gemini/gemini-cli/pull/16647)
- fix(core): prevent ModelInfo event emission on aborted signal by @sehoon38 in
[#16752](https://github.com/google-gemini/gemini-cli/pull/16752)
- Replace relative paths to fix website build by @chrstnb in
[#16755](https://github.com/google-gemini/gemini-cli/pull/16755)
- Restricting to localhost by @cocosheng-g in
[#16548](https://github.com/google-gemini/gemini-cli/pull/16548)
- fix(cli): add explicit dependency on color-convert by @sehoon38 in
[#16757](https://github.com/google-gemini/gemini-cli/pull/16757)
- fix(automation): robust label enforcement with permission checks by @bdmorgan
in [#16762](https://github.com/google-gemini/gemini-cli/pull/16762)
- fix(cli): prevent OOM crash by limiting file search traversal and adding
timeout by @galz10 in
[#16696](https://github.com/google-gemini/gemini-cli/pull/16696)
- fix(cli): safely handle /dev/tty access on macOS by @korade-krushna in
[#16531](https://github.com/google-gemini/gemini-cli/pull/16531)
- docs: clarify workspace test execution in GEMINI.md by @mattKorwel in
[#16764](https://github.com/google-gemini/gemini-cli/pull/16764)
- Add support for running available commands prior to MCP servers loading by
@Adib234 in [#15596](https://github.com/google-gemini/gemini-cli/pull/15596)
- feat(plan): add experimental 'plan' approval mode by @jerop in
[#16753](https://github.com/google-gemini/gemini-cli/pull/16753)
- feat(scheduler): add functional awaitConfirmation utility by @abhipatel12 in
[#16721](https://github.com/google-gemini/gemini-cli/pull/16721)
- fix(infra): update maintainer rollup label to 'workstream-rollup' by @bdmorgan
in [#16809](https://github.com/google-gemini/gemini-cli/pull/16809)
- fix(infra): use GraphQL to detect direct parents in rollup workflow by
@bdmorgan in [#16811](https://github.com/google-gemini/gemini-cli/pull/16811)
- chore(workflows): rename label-workstream-rollup workflow by @bdmorgan in
[#16818](https://github.com/google-gemini/gemini-cli/pull/16818)
- skip simple-mcp-server.test.ts by @scidomino in
[#16842](https://github.com/google-gemini/gemini-cli/pull/16842)
- Steer outer agent to use expert subagents when present by @gundermanc in
[#16763](https://github.com/google-gemini/gemini-cli/pull/16763)
- Fix race condition by awaiting scheduleToolCalls by @chrstnb in
[#16759](https://github.com/google-gemini/gemini-cli/pull/16759)
- cleanup: Organize key bindings by @scidomino in
[#16798](https://github.com/google-gemini/gemini-cli/pull/16798)
- feat(core): Add generalist agent. by @joshualitt in
[#16638](https://github.com/google-gemini/gemini-cli/pull/16638)
- perf(ui): optimize text buffer and highlighting for large inputs by
@NTaylorMullen in
[#16782](https://github.com/google-gemini/gemini-cli/pull/16782)
- fix(core): fix PTY descriptor shell leak by @galz10 in
[#16773](https://github.com/google-gemini/gemini-cli/pull/16773)
- feat(plan): enforce strict read-only policy and halt execution on violation by
@jerop in [#16849](https://github.com/google-gemini/gemini-cli/pull/16849)
- remove need-triage label from bug_report template by @sehoon38 in
[#16864](https://github.com/google-gemini/gemini-cli/pull/16864)
- fix(core): truncate large telemetry log entries by @sehoon38 in
[#16769](https://github.com/google-gemini/gemini-cli/pull/16769)
- docs(extensions): add Agent Skills support and mark feature as experimental by
@NTaylorMullen in
[#16859](https://github.com/google-gemini/gemini-cli/pull/16859)
- fix(core): surface warnings for invalid hook event names in configuration
(#16788) by @sehoon38 in
[#16873](https://github.com/google-gemini/gemini-cli/pull/16873)
- feat(plan): remove read_many_files from approval mode policies by @jerop in
[#16876](https://github.com/google-gemini/gemini-cli/pull/16876)
- feat(admin): implement admin controls polling and restart prompt by @skeshive
in [#16627](https://github.com/google-gemini/gemini-cli/pull/16627)
- Remove LRUCache class migrating to mnemoist by @jacob314 in
[#16872](https://github.com/google-gemini/gemini-cli/pull/16872)
- feat(settings): rename negative settings to positive naming (disable* ->
enable*) by @afarber in
[#14142](https://github.com/google-gemini/gemini-cli/pull/14142)
- refactor(cli): unify shell confirmation dialogs by @NTaylorMullen in
[#16828](https://github.com/google-gemini/gemini-cli/pull/16828)
- feat(agent): enable agent skills by default by @NTaylorMullen in
[#16736](https://github.com/google-gemini/gemini-cli/pull/16736)
- refactor(core): foundational truncation refactoring and token estimation
optimization by @NTaylorMullen in
[#16824](https://github.com/google-gemini/gemini-cli/pull/16824)
- fix(hooks): enable /hooks disable to reliably stop single hooks by
@abhipatel12 in
[#16804](https://github.com/google-gemini/gemini-cli/pull/16804)
- Don't commit unless user asks us to. by @gundermanc in
[#16902](https://github.com/google-gemini/gemini-cli/pull/16902)
- chore: remove a2a-adapter and bump @a2a-js/sdk to 0.3.8 by @adamfweidman in
[#16800](https://github.com/google-gemini/gemini-cli/pull/16800)
- fix: Show experiment values in settings UI for compressionThreshold by
@ishaanxgupta in
[#16267](https://github.com/google-gemini/gemini-cli/pull/16267)
- feat(cli): replace relative keyboard shortcuts link with web URL by
@imaliabbas in
[#16479](https://github.com/google-gemini/gemini-cli/pull/16479)
- fix(core): resolve PKCE length issue and stabilize OAuth redirect port by
@sehoon38 in [#16815](https://github.com/google-gemini/gemini-cli/pull/16815)
- Delete rewind documentation for now by @Adib234 in
[#16932](https://github.com/google-gemini/gemini-cli/pull/16932)
- Stabilize skill-creator CI and package format by @NTaylorMullen in
[#17001](https://github.com/google-gemini/gemini-cli/pull/17001)
- Stabilize the git evals by @gundermanc in
[#16989](https://github.com/google-gemini/gemini-cli/pull/16989)
- fix(core): attempt compression before context overflow check by @NTaylorMullen
in [#16914](https://github.com/google-gemini/gemini-cli/pull/16914)
- Fix inverted logic. by @gundermanc in
[#17007](https://github.com/google-gemini/gemini-cli/pull/17007)
- chore(scripts): add duplicate issue closer script and fix lint errors by
@bdmorgan in [#16997](https://github.com/google-gemini/gemini-cli/pull/16997)
- docs: update README and config guide to reference Gemini 3 by @JayadityaGit in
[#15806](https://github.com/google-gemini/gemini-cli/pull/15806)
- fix(cli): correct Homebrew installation detection by @kij in
[#14727](https://github.com/google-gemini/gemini-cli/pull/14727)
- Demote git evals to nightly run. by @gundermanc in
[#17030](https://github.com/google-gemini/gemini-cli/pull/17030)
- fix(cli): use OSC-52 clipboard copy in Windows Terminal by @Thomas-Shephard in
[#16920](https://github.com/google-gemini/gemini-cli/pull/16920)
- Fix: Process all parts in response chunks when thought is first by @pyrytakala
in [#13539](https://github.com/google-gemini/gemini-cli/pull/13539)
- fix(automation): fix jq quoting error in pr-triage.sh by @Kimsoo0119 in
[#16958](https://github.com/google-gemini/gemini-cli/pull/16958)
- refactor(core): decouple scheduler into orchestration, policy, and
confirmation by @abhipatel12 in
[#16895](https://github.com/google-gemini/gemini-cli/pull/16895)
- feat: add /introspect slash command by @NTaylorMullen in
[#17048](https://github.com/google-gemini/gemini-cli/pull/17048)
- refactor(cli): centralize tool mapping and decouple legacy scheduler by
@abhipatel12 in
[#17044](https://github.com/google-gemini/gemini-cli/pull/17044)
- fix(ui): ensure rationale renders before tool calls by @NTaylorMullen in
[#17043](https://github.com/google-gemini/gemini-cli/pull/17043)
- fix(workflows): use author_association for maintainer check by @bdmorgan in
[#17060](https://github.com/google-gemini/gemini-cli/pull/17060)
- fix return type of fireSessionStartEvent to defaultHookOutput by @ved015 in
[#16833](https://github.com/google-gemini/gemini-cli/pull/16833)
- feat(cli): add experiment gate for event-driven scheduler by @abhipatel12 in
[#17055](https://github.com/google-gemini/gemini-cli/pull/17055)
- feat(core): improve shell redirection transparency and security by
@NTaylorMullen in
[#16486](https://github.com/google-gemini/gemini-cli/pull/16486)
- fix(core): deduplicate ModelInfo emission in GeminiClient by @NTaylorMullen in
[#17075](https://github.com/google-gemini/gemini-cli/pull/17075)
- docs(themes): remove unsupported DiffModified color key by @jw409 in
[#17073](https://github.com/google-gemini/gemini-cli/pull/17073)
- fix: update currentSequenceModel when modelChanged by @adamfweidman in
[#17051](https://github.com/google-gemini/gemini-cli/pull/17051)
- feat(core): enhanced anchored iterative context compression with
self-verification by @rmedranollamas in
[#15710](https://github.com/google-gemini/gemini-cli/pull/15710)
- Fix mcp instructions by @chrstnb in
[#16439](https://github.com/google-gemini/gemini-cli/pull/16439)
- [A2A] Disable checkpointing if git is not installed by @cocosheng-g in
[#16896](https://github.com/google-gemini/gemini-cli/pull/16896)
- feat(admin): set admin.skills.enabled based on advancedFeaturesEnabled setting
by @skeshive in by @skeshive in
[#20853](https://github.com/google-gemini/gemini-cli/pull/20853) [#17095](https://github.com/google-gemini/gemini-cli/pull/17095)
- feat(plan): support annotating plans with feedback for iteration by @Adib234 - Test coverage for hook exit code cases by @gundermanc in
in [#20876](https://github.com/google-gemini/gemini-cli/pull/20876) [#17041](https://github.com/google-gemini/gemini-cli/pull/17041)
- Add some dos and don'ts to behavioral evals README. by @gundermanc in - Revert "Revert "Update extension examples"" by @chrstnb in
[#20629](https://github.com/google-gemini/gemini-cli/pull/20629) [#16445](https://github.com/google-gemini/gemini-cli/pull/16445)
- fix(core): skip telemetry logging for AbortError exceptions by @yunaseoul in - fix(core): Provide compact, actionable errors for agent delegation failures by
[#19477](https://github.com/google-gemini/gemini-cli/pull/19477) @SandyTao520 in
- fix(core): restrict "System: Please continue" invalid stream retry to Gemini 2 [#16493](https://github.com/google-gemini/gemini-cli/pull/16493)
models by @SandyTao520 in - fix: migrate BeforeModel and AfterModel hooks to HookSystem by @ved015 in
[#20897](https://github.com/google-gemini/gemini-cli/pull/20897) [#16599](https://github.com/google-gemini/gemini-cli/pull/16599)
- ci(evals): only run evals in CI if prompts or tools changed by @gundermanc in - feat(admin): apply admin settings to gemini skills/mcp/extensions commands by
[#20898](https://github.com/google-gemini/gemini-cli/pull/20898) @skeshive in [#17102](https://github.com/google-gemini/gemini-cli/pull/17102)
- Build binary by @aswinashok44 in - fix(core): update telemetry token count after session resume by @psinha40898
[#18933](https://github.com/google-gemini/gemini-cli/pull/18933) in [#15491](https://github.com/google-gemini/gemini-cli/pull/15491)
- Code review fixes as a pr by @jacob314 in - Demote the subagent test to nightly by @gundermanc in
[#20612](https://github.com/google-gemini/gemini-cli/pull/20612) [#17105](https://github.com/google-gemini/gemini-cli/pull/17105)
- fix(ci): handle empty APP_ID in stale PR closer by @bdmorgan in - feat(plan): telemetry to track adoption and usage of plan mode by @Adib234 in
[#20919](https://github.com/google-gemini/gemini-cli/pull/20919) [#16863](https://github.com/google-gemini/gemini-cli/pull/16863)
- feat(cli): invert context window display to show usage by @keithguerin in - feat: Add flash lite utility fallback chain by @adamfweidman in
[#20071](https://github.com/google-gemini/gemini-cli/pull/20071) [#17056](https://github.com/google-gemini/gemini-cli/pull/17056)
- fix(plan): clean up session directories and plans on deletion by @jerop in - Fixes Windows crash: "Cannot resize a pty that has already exited" by @dzammit
[#20914](https://github.com/google-gemini/gemini-cli/pull/20914) in [#15757](https://github.com/google-gemini/gemini-cli/pull/15757)
- fix(core): enforce optionality for API response fields in code_assist by - feat(core): Add initial eval for generalist agent. by @joshualitt in
@sehoon38 in [#20714](https://github.com/google-gemini/gemini-cli/pull/20714) [#16856](https://github.com/google-gemini/gemini-cli/pull/16856)
- feat(extensions): add support for plan directory in extension manifest by - feat(core): unify agent enabled and disabled flags by @SandyTao520 in
@mahimashanware in [#17127](https://github.com/google-gemini/gemini-cli/pull/17127)
[#20354](https://github.com/google-gemini/gemini-cli/pull/20354) - fix(core): resolve auto model in default strategy by @sehoon38 in
- feat(plan): enable built-in research subagents in plan mode by @Adib234 in [#17116](https://github.com/google-gemini/gemini-cli/pull/17116)
[#20972](https://github.com/google-gemini/gemini-cli/pull/20972) - docs: update project context and pr-creator workflow by @NTaylorMullen in
- feat(agents): directly indicate auth required state by @adamfweidman in [#17119](https://github.com/google-gemini/gemini-cli/pull/17119)
[#20986](https://github.com/google-gemini/gemini-cli/pull/20986) - fix(cli): send gemini-cli version as mcp client version by @dsp in
- fix(cli): wait for background auto-update before relaunching by @scidomino in [#13407](https://github.com/google-gemini/gemini-cli/pull/13407)
[#20904](https://github.com/google-gemini/gemini-cli/pull/20904) - fix(cli): resolve Ctrl+Enter and Ctrl+J newline issues by @imadraude in
- fix: pre-load @scripts/copy_files.js references from external editor prompts [#17021](https://github.com/google-gemini/gemini-cli/pull/17021)
by @kartikangiras in - Remove missing sidebar item by @chrstnb in
[#20963](https://github.com/google-gemini/gemini-cli/pull/20963) [#17145](https://github.com/google-gemini/gemini-cli/pull/17145)
- feat(evals): add behavioral evals for ask_user tool by @Adib234 in - feat(core): Ensure all properties in hooks object are event names. by
[#20620](https://github.com/google-gemini/gemini-cli/pull/20620) @joshualitt in
- refactor common settings logic for skills,agents by @ishaanxgupta in [#16870](https://github.com/google-gemini/gemini-cli/pull/16870)
[#17490](https://github.com/google-gemini/gemini-cli/pull/17490) - fix(cli): fix newline support broken in previous PR by @scidomino in
- Update docs-writer skill with new resource by @g-samroberts in [#17159](https://github.com/google-gemini/gemini-cli/pull/17159)
[#20917](https://github.com/google-gemini/gemini-cli/pull/20917) - Add interactive ValidationDialog for handling 403 VALIDATION_REQUIRED errors.
- fix(cli): pin clipboardy to ~5.2.x by @scidomino in by @gsquared94 in
[#21009](https://github.com/google-gemini/gemini-cli/pull/21009) [#16231](https://github.com/google-gemini/gemini-cli/pull/16231)
- feat: Implement slash command handling in ACP for - Add Esc-Esc to clear prompt when it's not empty by @Adib234 in
`/memory`,`/init`,`/extensions` and `/restore` by @sripasg in [#17131](https://github.com/google-gemini/gemini-cli/pull/17131)
[#20528](https://github.com/google-gemini/gemini-cli/pull/20528) - Avoid spurious warnings about unexpected renders triggered by appEvents and
- Docs/add hooks reference by @AadithyaAle in coreEvents. by @jacob314 in
[#20961](https://github.com/google-gemini/gemini-cli/pull/20961) [#17160](https://github.com/google-gemini/gemini-cli/pull/17160)
- feat(plan): add copy subcommand to plan (#20491) by @ruomengz in - fix(cli): resolve home/end keybinding conflict by @scidomino in
[#20988](https://github.com/google-gemini/gemini-cli/pull/20988) [#17124](https://github.com/google-gemini/gemini-cli/pull/17124)
- fix(core): sanitize and length-check MCP tool qualified names by @abhipatel12 - fix(cli): display 'http' type on mcp list by @pamanta in
in [#20987](https://github.com/google-gemini/gemini-cli/pull/20987) [#16915](https://github.com/google-gemini/gemini-cli/pull/16915)
- Format the quota/limit style guide. by @g-samroberts in - fix bad fallback logic external editor logic by @scidomino in
[#21017](https://github.com/google-gemini/gemini-cli/pull/21017) [#17166](https://github.com/google-gemini/gemini-cli/pull/17166)
- fix(core): send shell output to model on cancel by @devr0306 in - Fix bug where System scopes weren't migrated. by @jacob314 in
[#20501](https://github.com/google-gemini/gemini-cli/pull/20501) [#17174](https://github.com/google-gemini/gemini-cli/pull/17174)
- remove hardcoded tiername when missing tier by @sehoon38 in - Fix mcp tool lookup in tool registry by @werdnum in
[#21022](https://github.com/google-gemini/gemini-cli/pull/21022) [#17054](https://github.com/google-gemini/gemini-cli/pull/17054)
- feat(acp): add set models interface by @skeshive in
[#20991](https://github.com/google-gemini/gemini-cli/pull/20991)
- fix(patch): cherry-pick 0659ad1 to release/v0.33.0-preview.0-pr-21042 to patch
version v0.33.0-preview.0 and create version 0.33.0-preview.1 by
@gemini-cli-robot in
[#21047](https://github.com/google-gemini/gemini-cli/pull/21047)
- fix(patch): cherry-pick 173376b to release/v0.33.0-preview.1-pr-21157 to patch
version v0.33.0-preview.1 and create version 0.33.0-preview.2 by
@gemini-cli-robot in
[#21300](https://github.com/google-gemini/gemini-cli/pull/21300)
- fix(patch): cherry-pick 0135b03 to release/v0.33.0-preview.2-pr-21171
[CONFLICTS] by @gemini-cli-robot in
[#21336](https://github.com/google-gemini/gemini-cli/pull/21336)
- fix(patch): cherry-pick 7ec477d to release/v0.33.0-preview.3-pr-21305 to patch
version v0.33.0-preview.3 and create version 0.33.0-preview.4 by
@gemini-cli-robot in
[#21349](https://github.com/google-gemini/gemini-cli/pull/21349)
- fix(patch): cherry-pick 931e668 to release/v0.33.0-preview.4-pr-21425
[CONFLICTS] by @gemini-cli-robot in
[#21478](https://github.com/google-gemini/gemini-cli/pull/21478)
- fix(patch): cherry-pick 7837194 to release/v0.33.0-preview.5-pr-21487 to patch
version v0.33.0-preview.5 and create version 0.33.0-preview.6 by
@gemini-cli-robot in
[#21720](https://github.com/google-gemini/gemini-cli/pull/21720)
- fix(patch): cherry-pick 4f4431e to release/v0.33.0-preview.7-pr-21750 to patch
version v0.33.0-preview.7 and create version 0.33.0-preview.8 by
@gemini-cli-robot in
[#21782](https://github.com/google-gemini/gemini-cli/pull/21782)
- fix(patch): cherry-pick 9a74271 to release/v0.33.0-preview.8-pr-21236
[CONFLICTS] by @gemini-cli-robot in
[#21788](https://github.com/google-gemini/gemini-cli/pull/21788)
- fix(patch): cherry-pick 936f624 to release/v0.33.0-preview.9-pr-21702 to patch
version v0.33.0-preview.9 and create version 0.33.0-preview.10 by
@gemini-cli-robot in
[#21800](https://github.com/google-gemini/gemini-cli/pull/21800)
- fix(patch): cherry-pick 35ee2a8 to release/v0.33.0-preview.10-pr-21713 by
@gemini-cli-robot in
[#21859](https://github.com/google-gemini/gemini-cli/pull/21859)
- fix(patch): cherry-pick 5dd2dab to release/v0.33.0-preview.11-pr-21871 by
@gemini-cli-robot in
[#21876](https://github.com/google-gemini/gemini-cli/pull/21876)
- fix(patch): cherry-pick e5615f4 to release/v0.33.0-preview.12-pr-21037 to
patch version v0.33.0-preview.12 and create version 0.33.0-preview.13 by
@gemini-cli-robot in
[#21922](https://github.com/google-gemini/gemini-cli/pull/21922)
- fix(patch): cherry-pick 1b69637 to release/v0.33.0-preview.13-pr-21467
[CONFLICTS] by @gemini-cli-robot in
[#21930](https://github.com/google-gemini/gemini-cli/pull/21930)
- fix(patch): cherry-pick 3ff68a9 to release/v0.33.0-preview.14-pr-21884
[CONFLICTS] by @gemini-cli-robot in
[#21952](https://github.com/google-gemini/gemini-cli/pull/21952)
**Full Changelog**: **Full changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.32.1...v0.33.1 https://github.com/google-gemini/gemini-cli/compare/v0.25.2...v0.26.0
+413 -447
View File
@@ -1,6 +1,6 @@
# Preview release: v0.34.0-preview.1 # Preview release: Release v0.27.0-preview.0
Released: March 12, 2026 Released: January 27, 2026
Our preview release includes the latest, new, and experimental features. This Our preview release includes the latest, new, and experimental features. This
release may not be as stable as our [latest weekly release](latest.md). release may not be as stable as our [latest weekly release](latest.md).
@@ -13,459 +13,425 @@ npm install -g @google/gemini-cli@preview
## Highlights ## Highlights
- **Plan Mode Enabled by Default:** Plan Mode is now enabled out-of-the-box, - **Event-Driven Architecture:** The tool execution scheduler is now
providing a structured planning workflow and keeping approved plans during event-driven, improving performance and reliability.
chat compression. - **System Prompt Override:** Now supports dynamic variable substitution.
- **Sandboxing Enhancements:** Added experimental LXC container sandbox support - **Rewind Command:** The `/rewind` command has been implemented.
and native gVisor (`runsc`) sandboxing for improved security and isolation. - **Linux Clipboard:** Image pasting capabilities for Wayland and X11 on Linux.
- **Tracker Visualization and Tools:** Introduced CRUD tools and visualization
for trackers, along with task tracker strategy improvements.
- **Browser Agent Improvements:** Enhanced the browser agent with progress
emission, a new automation overlay, and additional integration tests.
- **CLI and UI Updates:** Standardized semantic focus colors, polished shell
autocomplete rendering, unified keybinding infrastructure, and added custom
footer configuration options.
## What's Changed ## What's Changed
- fix(patch): cherry-pick 45faf4d to release/v0.34.0-preview.0-pr-22148 - remove fireAgent and beforeAgent hook by @ishaanxgupta in
[CONFLICTS] by @gemini-cli-robot in [#16919](https://github.com/google-gemini/gemini-cli/pull/16919)
[#22174](https://github.com/google-gemini/gemini-cli/pull/22174) - Remove unused modelHooks and toolHooks by @ved015 in
- feat(cli): add chat resume footer on session quit by @lordshashank in [#17115](https://github.com/google-gemini/gemini-cli/pull/17115)
[#20667](https://github.com/google-gemini/gemini-cli/pull/20667) - feat(cli): sanitize ANSI escape sequences in non-interactive output by
- Support bold and other styles in svg snapshots by @jacob314 in @sehoon38 in [#17172](https://github.com/google-gemini/gemini-cli/pull/17172)
[#20937](https://github.com/google-gemini/gemini-cli/pull/20937) - Update Attempt text to Retry when showing the retry happening to the … by
- fix(core): increase A2A agent timeout to 30 minutes by @adamfweidman in @sehoon38 in [#17178](https://github.com/google-gemini/gemini-cli/pull/17178)
[#21028](https://github.com/google-gemini/gemini-cli/pull/21028) - chore(skills): update pr-creator skill workflow by @sehoon38 in
- Cleanup old branches. by @jacob314 in [#17180](https://github.com/google-gemini/gemini-cli/pull/17180)
[#19354](https://github.com/google-gemini/gemini-cli/pull/19354) - feat(cli): implement event-driven tool execution scheduler by @abhipatel12 in
- chore(release): bump version to 0.34.0-nightly.20260303.34f0c1538 by [#17078](https://github.com/google-gemini/gemini-cli/pull/17078)
- chore(release): bump version to 0.27.0-nightly.20260121.97aac696f by
@gemini-cli-robot in @gemini-cli-robot in
[#21034](https://github.com/google-gemini/gemini-cli/pull/21034) [#17181](https://github.com/google-gemini/gemini-cli/pull/17181)
- feat(ui): standardize semantic focus colors and enhance history visibility by - Remove other rewind reference in docs by @chrstnb in
@keithguerin in [#17149](https://github.com/google-gemini/gemini-cli/pull/17149)
[#20745](https://github.com/google-gemini/gemini-cli/pull/20745) - feat(skills): add code-reviewer skill by @sehoon38 in
- fix: merge duplicate imports in packages/core (3/4) by @Nixxx19 in [#17187](httpshttps://github.com/google-gemini/gemini-cli/pull/17187)
[#20928](https://github.com/google-gemini/gemini-cli/pull/20928) - feat(plan): Extend Shift+Tab Mode Cycling to include Plan Mode by @Adib234 in
- Add extra safety checks for proto pollution by @jacob314 in [#17177](https://github.com/google-gemini/gemini-cli/pull/17177)
[#20396](https://github.com/google-gemini/gemini-cli/pull/20396) - feat(plan): refactor TestRig and eval helper to support configurable approval
- feat(core): Add tracker CRUD tools & visualization by @anj-s in modes by @jerop in
[#19489](https://github.com/google-gemini/gemini-cli/pull/19489) [#17171](https://github.com/google-gemini/gemini-cli/pull/17171)
- Revert "fix(ui): persist expansion in AskUser dialog when navigating options" - feat(workflows): support recursive workstream labeling and new IDs by
by @jacob314 in @bdmorgan in [#17207](https://github.com/google-gemini/gemini-cli/pull/17207)
[#21042](https://github.com/google-gemini/gemini-cli/pull/21042) - Run evals for all models. by @gundermanc in
- Changelog for v0.33.0-preview.0 by @gemini-cli-robot in [#17123](https://github.com/google-gemini/gemini-cli/pull/17123)
[#21030](https://github.com/google-gemini/gemini-cli/pull/21030) - fix(github): improve label-workstream-rollup efficiency with GraphQL by
- fix: model persistence for all scenarios by @sripasg in @bdmorgan in [#17217](https://github.com/google-gemini/gemini-cli/pull/17217)
[#21051](https://github.com/google-gemini/gemini-cli/pull/21051) - Docs: Update changelogs for v.0.25.0 and v0.26.0-preview.0 releases. by
- chore/release: bump version to 0.34.0-nightly.20260304.28af4e127 by @g-samroberts in
@gemini-cli-robot in [#17215](https://github.com/google-gemini/gemini-cli/pull/17215)
[#21054](https://github.com/google-gemini/gemini-cli/pull/21054) - Migrate beforeTool and afterTool hooks to hookSystem by @ved015 in
- Consistently guard restarts against concurrent auto updates by @scidomino in [#17204](https://github.com/google-gemini/gemini-cli/pull/17204)
[#21016](https://github.com/google-gemini/gemini-cli/pull/21016) - fix(github): improve label-workstream-rollup efficiency and fix bugs by
- Defensive coding to reduce the risk of Maximum update depth errors by @bdmorgan in [#17219](https://github.com/google-gemini/gemini-cli/pull/17219)
@jacob314 in [#20940](https://github.com/google-gemini/gemini-cli/pull/20940) - feat(cli): improve skill enablement/disablement verbiage by @NTaylorMullen in
- fix(cli): Polish shell autocomplete rendering to be a little more shell native [#17192](https://github.com/google-gemini/gemini-cli/pull/17192)
feeling. by @jacob314 in - fix(admin): Ensure CLI commands run in non-interactive mode by @skeshive in
[#20931](https://github.com/google-gemini/gemini-cli/pull/20931) [#17218](https://github.com/google-gemini/gemini-cli/pull/17218)
- Docs: Update plan mode docs by @jkcinouye in - feat(core): support dynamic variable substitution in system prompt override by
[#19682](https://github.com/google-gemini/gemini-cli/pull/19682)
- fix(mcp): Notifications/tools/list_changed support not working by @jacob314 in
[#21050](https://github.com/google-gemini/gemini-cli/pull/21050)
- fix(cli): register extension lifecycle events in DebugProfiler by
@fayerman-source in
[#20101](https://github.com/google-gemini/gemini-cli/pull/20101)
- chore(dev): update vscode settings for typescriptreact by @rohit-4321 in
[#19907](https://github.com/google-gemini/gemini-cli/pull/19907)
- fix(cli): enable multi-arch docker builds for sandbox by @ru-aish in
[#19821](https://github.com/google-gemini/gemini-cli/pull/19821)
- Changelog for v0.32.0 by @gemini-cli-robot in
[#21033](https://github.com/google-gemini/gemini-cli/pull/21033)
- Changelog for v0.33.0-preview.1 by @gemini-cli-robot in
[#21058](https://github.com/google-gemini/gemini-cli/pull/21058)
- feat(core): improve @scripts/copy_files.js autocomplete to prioritize
filenames by @sehoon38 in
[#21064](https://github.com/google-gemini/gemini-cli/pull/21064)
- feat(sandbox): add experimental LXC container sandbox support by @h30s in
[#20735](https://github.com/google-gemini/gemini-cli/pull/20735)
- feat(evals): add overall pass rate row to eval nightly summary table by
@gundermanc in
[#20905](https://github.com/google-gemini/gemini-cli/pull/20905)
- feat(telemetry): include language in telemetry and fix accepted lines
computation by @gundermanc in
[#21126](https://github.com/google-gemini/gemini-cli/pull/21126)
- Changelog for v0.32.1 by @gemini-cli-robot in
[#21055](https://github.com/google-gemini/gemini-cli/pull/21055)
- feat(core): add robustness tests, logging, and metrics for CodeAssistServer
SSE parsing by @yunaseoul in
[#21013](https://github.com/google-gemini/gemini-cli/pull/21013)
- feat: add issue assignee workflow by @kartikangiras in
[#21003](https://github.com/google-gemini/gemini-cli/pull/21003)
- fix: improve error message when OAuth succeeds but project ID is required by
@Nixxx19 in [#21070](https://github.com/google-gemini/gemini-cli/pull/21070)
- feat(loop-reduction): implement iterative loop detection and model feedback by
@aishaneeshah in
[#20763](https://github.com/google-gemini/gemini-cli/pull/20763)
- chore(github): require prompt approvers for agent prompt files by @gundermanc
in [#20896](https://github.com/google-gemini/gemini-cli/pull/20896)
- Docs: Create tools reference by @jkcinouye in
[#19470](https://github.com/google-gemini/gemini-cli/pull/19470)
- fix(core, a2a-server): prevent hang during OAuth in non-interactive sessions
by @spencer426 in
[#21045](https://github.com/google-gemini/gemini-cli/pull/21045)
- chore(cli): enable deprecated settings removal by default by @yashodipmore in
[#20682](https://github.com/google-gemini/gemini-cli/pull/20682)
- feat(core): Disable fast ack helper for hints. by @joshualitt in
[#21011](https://github.com/google-gemini/gemini-cli/pull/21011)
- fix(ui): suppress redundant failure note when tool error note is shown by
@NTaylorMullen in @NTaylorMullen in
[#21078](https://github.com/google-gemini/gemini-cli/pull/21078) [#17042](https://github.com/google-gemini/gemini-cli/pull/17042)
- docs: document planning workflows with Conductor example by @jerop in - fix(core,cli): enable recursive directory access for by @galz10 in
[#21166](https://github.com/google-gemini/gemini-cli/pull/21166) [#17094](https://github.com/google-gemini/gemini-cli/pull/17094)
- feat(release): ship esbuild bundle in npm package by @genneth in - Docs: Marking for experimental features by @jkcinouye in
[#19171](https://github.com/google-gemini/gemini-cli/pull/19171) [#16760](https://github.com/google-gemini/gemini-cli/pull/16760)
- fix(extensions): preserve symlinks in extension source path while enforcing - Support command/ctrl/alt backspace correctly by @scidomino in
folder trust by @galz10 in [#17175](https://github.com/google-gemini/gemini-cli/pull/17175)
[#20867](https://github.com/google-gemini/gemini-cli/pull/20867) - feat(plan): add approval mode instructions to system prompt by @jerop in
- fix(cli): defer tool exclusions to policy engine in non-interactive mode by [#17151](https://github.com/google-gemini/gemini-cli/pull/17151)
@EricRahm in [#20639](https://github.com/google-gemini/gemini-cli/pull/20639) - feat(core): enable disableLLMCorrection by default by @SandyTao520 in
- fix(ui): removed double padding on rendered content by @devr0306 in [#17223](https://github.com/google-gemini/gemini-cli/pull/17223)
[#21029](https://github.com/google-gemini/gemini-cli/pull/21029) - Remove unused slug from sidebar by @chrstnb in
- fix(core): truncate excessively long lines in grep search output by [#17229](https://github.com/google-gemini/gemini-cli/pull/17229)
@gundermanc in - drain stdin on exit by @scidomino in
[#21147](https://github.com/google-gemini/gemini-cli/pull/21147) [#17241](https://github.com/google-gemini/gemini-cli/pull/17241)
- feat: add custom footer configuration via `/footer` by @jackwotherspoon in - refactor(cli): decouple UI from live tool execution via ToolActionsContext by
[#19001](https://github.com/google-gemini/gemini-cli/pull/19001)
- perf(core): fix OOM crash in long-running sessions by @WizardsForgeGames in
[#19608](https://github.com/google-gemini/gemini-cli/pull/19608)
- refactor(cli): categorize built-in themes into dark/ and light/ directories by
@JayadityaGit in
[#18634](https://github.com/google-gemini/gemini-cli/pull/18634)
- fix(core): explicitly allow codebase_investigator and cli_help in read-only
mode by @Adib234 in
[#21157](https://github.com/google-gemini/gemini-cli/pull/21157)
- test: add browser agent integration tests by @kunal-10-cloud in
[#21151](https://github.com/google-gemini/gemini-cli/pull/21151)
- fix(cli): fix enabling kitty codes on Windows Terminal by @scidomino in
[#21136](https://github.com/google-gemini/gemini-cli/pull/21136)
- refactor(core): extract shared OAuth flow primitives from MCPOAuthProvider by
@SandyTao520 in
[#20895](https://github.com/google-gemini/gemini-cli/pull/20895)
- fix(ui): add partial output to cancelled shell UI by @devr0306 in
[#21178](https://github.com/google-gemini/gemini-cli/pull/21178)
- fix(cli): replace hardcoded keybinding strings with dynamic formatters by
@scidomino in [#21159](https://github.com/google-gemini/gemini-cli/pull/21159)
- DOCS: Update quota and pricing page by @g-samroberts in
[#21194](https://github.com/google-gemini/gemini-cli/pull/21194)
- feat(telemetry): implement Clearcut logging for startup statistics by
@yunaseoul in [#21172](https://github.com/google-gemini/gemini-cli/pull/21172)
- feat(triage): add area/documentation to issue triage by @g-samroberts in
[#21222](https://github.com/google-gemini/gemini-cli/pull/21222)
- Fix so shell calls are formatted by @jacob314 in
[#21237](https://github.com/google-gemini/gemini-cli/pull/21237)
- feat(cli): add native gVisor (runsc) sandboxing support by @Zheyuan-Lin in
[#21062](https://github.com/google-gemini/gemini-cli/pull/21062)
- docs: use absolute paths for internal links in plan-mode.md by @jerop in
[#21299](https://github.com/google-gemini/gemini-cli/pull/21299)
- fix(core): prevent unhandled AbortError crash during stream loop detection by
@7hokerz in [#21123](https://github.com/google-gemini/gemini-cli/pull/21123)
- fix:reorder env var redaction checks to scan values first by @kartikangiras in
[#21059](https://github.com/google-gemini/gemini-cli/pull/21059)
- fix(acp): rename --experimental-acp to --acp & remove Zed-specific refrences
by @skeshive in
[#21171](https://github.com/google-gemini/gemini-cli/pull/21171)
- feat(core): fallback to 2.5 models with no access for toolcalls by @sehoon38
in [#21283](https://github.com/google-gemini/gemini-cli/pull/21283)
- test(core): improve testing for API request/response parsing by @sehoon38 in
[#21227](https://github.com/google-gemini/gemini-cli/pull/21227)
- docs(links): update docs-writer skill and fix broken link by @g-samroberts in
[#21314](https://github.com/google-gemini/gemini-cli/pull/21314)
- Fix code colorizer ansi escape bug. by @jacob314 in
[#21321](https://github.com/google-gemini/gemini-cli/pull/21321)
- remove wildcard behavior on keybindings by @scidomino in
[#21315](https://github.com/google-gemini/gemini-cli/pull/21315)
- feat(acp): Add support for AI Gateway auth by @skeshive in
[#21305](https://github.com/google-gemini/gemini-cli/pull/21305)
- fix(theme): improve theme color contrast for macOS Terminal.app by @clocky in
[#21175](https://github.com/google-gemini/gemini-cli/pull/21175)
- feat (core): Implement tracker related SI changes by @anj-s in
[#19964](https://github.com/google-gemini/gemini-cli/pull/19964)
- Changelog for v0.33.0-preview.2 by @gemini-cli-robot in
[#21333](https://github.com/google-gemini/gemini-cli/pull/21333)
- Changelog for v0.33.0-preview.3 by @gemini-cli-robot in
[#21347](https://github.com/google-gemini/gemini-cli/pull/21347)
- docs: format release times as HH:MM UTC by @pavan-sh in
[#20726](https://github.com/google-gemini/gemini-cli/pull/20726)
- fix(cli): implement --all flag for extensions uninstall by @sehoon38 in
[#21319](https://github.com/google-gemini/gemini-cli/pull/21319)
- docs: fix incorrect relative links to command reference by @kanywst in
[#20964](https://github.com/google-gemini/gemini-cli/pull/20964)
- documentiong ensures ripgrep by @Jatin24062005 in
[#21298](https://github.com/google-gemini/gemini-cli/pull/21298)
- fix(core): handle AbortError thrown during processTurn by @MumuTW in
[#21296](https://github.com/google-gemini/gemini-cli/pull/21296)
- docs(cli): clarify ! command output visibility in shell commands tutorial by
@MohammedADev in
[#21041](https://github.com/google-gemini/gemini-cli/pull/21041)
- fix: logic for task tracker strategy and remove tracker tools by @anj-s in
[#21355](https://github.com/google-gemini/gemini-cli/pull/21355)
- fix(partUtils): display media type and size for inline data parts by @Aboudjem
in [#21358](https://github.com/google-gemini/gemini-cli/pull/21358)
- Fix(accessibility): add screen reader support to RewindViewer by @Famous077 in
[#20750](https://github.com/google-gemini/gemini-cli/pull/20750)
- fix(hooks): propagate stopHookActive in AfterAgent retry path (#20426) by
@Aarchi-07 in [#20439](https://github.com/google-gemini/gemini-cli/pull/20439)
- fix(core): deduplicate GEMINI.md files by device/inode on case-insensitive
filesystems (#19904) by @Nixxx19 in
[#19915](https://github.com/google-gemini/gemini-cli/pull/19915)
- feat(core): add concurrency safety guidance for subagent delegation (#17753)
by @abhipatel12 in
[#21278](https://github.com/google-gemini/gemini-cli/pull/21278)
- feat(ui): dynamically generate all keybinding hints by @scidomino in
[#21346](https://github.com/google-gemini/gemini-cli/pull/21346)
- feat(core): implement unified KeychainService and migrate token storage by
@ehedlund in [#21344](https://github.com/google-gemini/gemini-cli/pull/21344)
- fix(cli): gracefully handle --resume when no sessions exist by @SandyTao520 in
[#21429](https://github.com/google-gemini/gemini-cli/pull/21429)
- fix(plan): keep approved plan during chat compression by @ruomengz in
[#21284](https://github.com/google-gemini/gemini-cli/pull/21284)
- feat(core): implement generic CacheService and optimize setupUser by @sehoon38
in [#21374](https://github.com/google-gemini/gemini-cli/pull/21374)
- Update quota and pricing documentation with subscription tiers by @srithreepo
in [#21351](https://github.com/google-gemini/gemini-cli/pull/21351)
- fix(core): append correct OTLP paths for HTTP exporters by
@sebastien-prudhomme in
[#16836](https://github.com/google-gemini/gemini-cli/pull/16836)
- Changelog for v0.33.0-preview.4 by @gemini-cli-robot in
[#21354](https://github.com/google-gemini/gemini-cli/pull/21354)
- feat(cli): implement dot-prefixing for slash command conflicts by @ehedlund in
[#20979](https://github.com/google-gemini/gemini-cli/pull/20979)
- refactor(core): standardize MCP tool naming to mcp\_ FQN format by
@abhipatel12 in @abhipatel12 in
[#21425](https://github.com/google-gemini/gemini-cli/pull/21425) [#17183](https://github.com/google-gemini/gemini-cli/pull/17183)
- feat(cli): hide gemma settings from display and mark as experimental by - fix(core): update token count and telemetry on /chat resume history load by
@psinha40898 in
[#16279](https://github.com/google-gemini/gemini-cli/pull/16279)
- fix: /policy to display policies according to mode by @ishaanxgupta in
[#16772](https://github.com/google-gemini/gemini-cli/pull/16772)
- fix(core): simplify replace tool error message by @SandyTao520 in
[#17246](https://github.com/google-gemini/gemini-cli/pull/17246)
- feat(cli): consolidate shell inactivity and redirection monitoring by
@NTaylorMullen in
[#17086](https://github.com/google-gemini/gemini-cli/pull/17086)
- fix(scheduler): prevent stale tool re-publication and fix stuck UI state by
@abhipatel12 in @abhipatel12 in
[#21471](https://github.com/google-gemini/gemini-cli/pull/21471) [#17227](https://github.com/google-gemini/gemini-cli/pull/17227)
- feat(skills): refine string-reviewer guidelines and description by @clocky in - feat(config): default enableEventDrivenScheduler to true by @abhipatel12 in
[#20368](https://github.com/google-gemini/gemini-cli/pull/20368) [#17211](https://github.com/google-gemini/gemini-cli/pull/17211)
- fix(core): whitelist TERM and COLORTERM in environment sanitization by - feat(hooks): enable hooks system by default by @abhipatel12 in
@deadsmash07 in [#17247](https://github.com/google-gemini/gemini-cli/pull/17247)
[#20514](https://github.com/google-gemini/gemini-cli/pull/20514) - feat(core): Enable AgentRegistry to track all discovered subagents by
- fix(billing): fix overage strategy lifecycle and settings integration by
@gsquared94 in
[#21236](https://github.com/google-gemini/gemini-cli/pull/21236)
- fix: expand paste placeholders in TextInput on submit by @Jefftree in
[#19946](https://github.com/google-gemini/gemini-cli/pull/19946)
- fix(core): add in-memory cache to ChatRecordingService to prevent OOM by
@SandyTao520 in @SandyTao520 in
[#21502](https://github.com/google-gemini/gemini-cli/pull/21502) [#17253](https://github.com/google-gemini/gemini-cli/pull/17253)
- feat(cli): overhaul thinking UI by @keithguerin in - feat(core): Have subagents use a JSON schema type for input. by @joshualitt in
[#18725](https://github.com/google-gemini/gemini-cli/pull/18725) [#17152](https://github.com/google-gemini/gemini-cli/pull/17152)
- fix(ui): unify Ctrl+O expansion hint experience across buffer modes by - feat: replace large text pastes with [Pasted Text: X lines] placeholder by
@jwhelangoog in @jackwotherspoon in
[#21474](https://github.com/google-gemini/gemini-cli/pull/21474) [#16422](https://github.com/google-gemini/gemini-cli/pull/16422)
- fix(cli): correct shell height reporting by @jacob314 in - security(hooks): Wrap hook-injected context in distinct XML tags by @yunaseoul
[#21492](https://github.com/google-gemini/gemini-cli/pull/21492) in [#17237](https://github.com/google-gemini/gemini-cli/pull/17237)
- Make test suite pass when the GEMINI_SYSTEM_MD env variable or - Enable the ability to queue specific nightly eval tests by @gundermanc in
GEMINI_WRITE_SYSTEM_MD variable happens to be set locally/ by @jacob314 in [#17262](https://github.com/google-gemini/gemini-cli/pull/17262)
[#21480](https://github.com/google-gemini/gemini-cli/pull/21480) - docs(hooks): comprehensive update of hook documentation and specs by
- Disallow underspecified types by @gundermanc in @abhipatel12 in
[#21485](https://github.com/google-gemini/gemini-cli/pull/21485) [#16816](https://github.com/google-gemini/gemini-cli/pull/16816)
- refactor(cli): standardize on 'reload' verb for all components by @keithguerin - refactor: improve large text paste placeholder by @jacob314 in
in [#20654](https://github.com/google-gemini/gemini-cli/pull/20654) [#17269](https://github.com/google-gemini/gemini-cli/pull/17269)
- feat(cli): Invert quota language to 'percent used' by @keithguerin in - feat: implement /rewind command by @Adib234 in
[#20100](https://github.com/google-gemini/gemini-cli/pull/20100) [#15720](https://github.com/google-gemini/gemini-cli/pull/15720)
- Docs: Add documentation for notifications (experimental)(macOS) by @jkcinouye - Feature/jetbrains ide detection by @SoLoHiC in
in [#21163](https://github.com/google-gemini/gemini-cli/pull/21163) [#16243](https://github.com/google-gemini/gemini-cli/pull/16243)
- Code review comments as a pr by @jacob314 in - docs: update typo in mcp-server.md file by @schifferl in
[#21209](https://github.com/google-gemini/gemini-cli/pull/21209) [#17099](https://github.com/google-gemini/gemini-cli/pull/17099)
- feat(cli): unify /chat and /resume command UX by @LyalinDotCom in - Sanitize command names and descriptions by @ehedlund in
[#20256](https://github.com/google-gemini/gemini-cli/pull/20256) [#17228](https://github.com/google-gemini/gemini-cli/pull/17228)
- docs: fix typo 'allowslisted' -> 'allowlisted' in mcp-server.md by - fix(auth): don't crash when initial auth fails by @skeshive in
@Gyanranjan-Priyam in [#17308](https://github.com/google-gemini/gemini-cli/pull/17308)
[#21665](https://github.com/google-gemini/gemini-cli/pull/21665) - Added image pasting capabilities for Wayland and X11 on Linux by @devr0306 in
- fix(core): display actual graph output in tracker_visualize tool by @anj-s in [#17144](https://github.com/google-gemini/gemini-cli/pull/17144)
[#21455](https://github.com/google-gemini/gemini-cli/pull/21455) - feat: add AskUser tool schema by @jackwotherspoon in
- fix(core): sanitize SSE-corrupted JSON and domain strings in error [#16988](https://github.com/google-gemini/gemini-cli/pull/16988)
classification by @gsquared94 in - fix cli settings: resolve layout jitter in settings bar by @Mag1ck in
[#21702](https://github.com/google-gemini/gemini-cli/pull/21702) [#16256](https://github.com/google-gemini/gemini-cli/pull/16256)
- Docs: Make documentation links relative by @diodesign in - fix: show whitespace changes in edit tool diffs by @Ujjiyara in
[#21490](https://github.com/google-gemini/gemini-cli/pull/21490) [#17213](https://github.com/google-gemini/gemini-cli/pull/17213)
- feat(cli): expose /tools desc as explicit subcommand for discoverability by - Remove redundant calls setting linuxClipboardTool. getUserLinuxClipboardTool()
@aworki in [#21241](https://github.com/google-gemini/gemini-cli/pull/21241) now handles the caching internally by @jacob314 in
- feat(cli): add /compact alias for /compress command by @jackwotherspoon in [#17320](https://github.com/google-gemini/gemini-cli/pull/17320)
[#21711](https://github.com/google-gemini/gemini-cli/pull/21711) - ci: allow failure in evals-nightly run step by @gundermanc in
- feat(plan): enable Plan Mode by default by @jerop in [#17319](https://github.com/google-gemini/gemini-cli/pull/17319)
[#21713](https://github.com/google-gemini/gemini-cli/pull/21713) - feat(cli): Add state management and plumbing for agent configuration dialog by
- feat(core): Introduce `AgentLoopContext`. by @joshualitt in
[#21198](https://github.com/google-gemini/gemini-cli/pull/21198)
- fix(core): resolve symlinks for non-existent paths during validation by
@Adib234 in [#21487](https://github.com/google-gemini/gemini-cli/pull/21487)
- docs: document tool exclusion from memory via deny policy by @Abhijit-2592 in
[#21428](https://github.com/google-gemini/gemini-cli/pull/21428)
- perf(core): cache loadApiKey to reduce redundant keychain access by @sehoon38
in [#21520](https://github.com/google-gemini/gemini-cli/pull/21520)
- feat(cli): implement /upgrade command by @sehoon38 in
[#21511](https://github.com/google-gemini/gemini-cli/pull/21511)
- Feat/browser agent progress emission by @kunal-10-cloud in
[#21218](https://github.com/google-gemini/gemini-cli/pull/21218)
- fix(settings): display objects as JSON instead of [object Object] by
@Zheyuan-Lin in
[#21458](https://github.com/google-gemini/gemini-cli/pull/21458)
- Unmarshall update by @DavidAPierce in
[#21721](https://github.com/google-gemini/gemini-cli/pull/21721)
- Update mcp's list function to check for disablement. by @DavidAPierce in
[#21148](https://github.com/google-gemini/gemini-cli/pull/21148)
- robustness(core): static checks to validate history is immutable by @jacob314
in [#21228](https://github.com/google-gemini/gemini-cli/pull/21228)
- refactor(cli): better react patterns for BaseSettingsDialog by @psinha40898 in
[#21206](https://github.com/google-gemini/gemini-cli/pull/21206)
- feat(security): implement robust IP validation and safeFetch foundation by
@alisa-alisa in
[#21401](https://github.com/google-gemini/gemini-cli/pull/21401)
- feat(core): improve subagent result display by @joshualitt in
[#20378](https://github.com/google-gemini/gemini-cli/pull/20378)
- docs: fix broken markdown syntax and anchor links in /tools by @campox747 in
[#20902](https://github.com/google-gemini/gemini-cli/pull/20902)
- feat(policy): support subagent-specific policies in TOML by @akh64bit in
[#21431](https://github.com/google-gemini/gemini-cli/pull/21431)
- Add script to speed up reviewing PRs adding a worktree. by @jacob314 in
[#21748](https://github.com/google-gemini/gemini-cli/pull/21748)
- fix(core): prevent infinite recursion in symlink resolution by @Adib234 in
[#21750](https://github.com/google-gemini/gemini-cli/pull/21750)
- fix(docs): fix headless mode docs by @ame2en in
[#21287](https://github.com/google-gemini/gemini-cli/pull/21287)
- feat/redesign header compact by @jacob314 in
[#20922](https://github.com/google-gemini/gemini-cli/pull/20922)
- refactor: migrate to useKeyMatchers hook by @scidomino in
[#21753](https://github.com/google-gemini/gemini-cli/pull/21753)
- perf(cli): cache loadSettings to reduce redundant disk I/O at startup by
@sehoon38 in [#21521](https://github.com/google-gemini/gemini-cli/pull/21521)
- fix(core): resolve Windows line ending and path separation bugs across CLI by
@muhammadusman586 in
[#21068](https://github.com/google-gemini/gemini-cli/pull/21068)
- docs: fix heading formatting in commands.md and phrasing in tools-api.md by
@campox747 in [#20679](https://github.com/google-gemini/gemini-cli/pull/20679)
- refactor(ui): unify keybinding infrastructure and support string
initialization by @scidomino in
[#21776](https://github.com/google-gemini/gemini-cli/pull/21776)
- Add support for updating extension sources and names by @chrstnb in
[#21715](https://github.com/google-gemini/gemini-cli/pull/21715)
- fix(core): handle GUI editor non-zero exit codes gracefully by @reyyanxahmed
in [#20376](https://github.com/google-gemini/gemini-cli/pull/20376)
- fix(core): destroy PTY on kill() and exception to prevent fd leak by @nbardy
in [#21693](https://github.com/google-gemini/gemini-cli/pull/21693)
- fix(docs): update theme screenshots and add missing themes by @ashmod in
[#20689](https://github.com/google-gemini/gemini-cli/pull/20689)
- refactor(cli): rename 'return' key to 'enter' internally by @scidomino in
[#21796](https://github.com/google-gemini/gemini-cli/pull/21796)
- build(release): restrict npm bundling to non-stable tags by @sehoon38 in
[#21821](https://github.com/google-gemini/gemini-cli/pull/21821)
- fix(core): override toolRegistry property for sub-agent schedulers by
@gsquared94 in
[#21766](https://github.com/google-gemini/gemini-cli/pull/21766)
- fix(cli): make footer items equally spaced by @jacob314 in
[#21843](https://github.com/google-gemini/gemini-cli/pull/21843)
- docs: clarify global policy rules application in plan mode by @jerop in
[#21864](https://github.com/google-gemini/gemini-cli/pull/21864)
- fix(core): ensure correct flash model steering in plan mode implementation
phase by @jerop in
[#21871](https://github.com/google-gemini/gemini-cli/pull/21871)
- fix(core): update @a2a-js/sdk to 0.3.11 by @adamfweidman in
[#21875](https://github.com/google-gemini/gemini-cli/pull/21875)
- refactor(core): improve API response error logging when retry by @yunaseoul in
[#21784](https://github.com/google-gemini/gemini-cli/pull/21784)
- fix(ui): handle headless execution in credits and upgrade dialogs by
@gsquared94 in
[#21850](https://github.com/google-gemini/gemini-cli/pull/21850)
- fix(core): treat retryable errors with >5 min delay as terminal quota errors
by @gsquared94 in
[#21881](https://github.com/google-gemini/gemini-cli/pull/21881)
- feat(telemetry): add specific PR, issue, and custom tracking IDs for GitHub
Actions by @cocosheng-g in
[#21129](https://github.com/google-gemini/gemini-cli/pull/21129)
- feat(core): add OAuth2 Authorization Code auth provider for A2A agents by
@SandyTao520 in @SandyTao520 in
[#21496](https://github.com/google-gemini/gemini-cli/pull/21496) [#17259](https://github.com/google-gemini/gemini-cli/pull/17259)
- feat(cli): give visibility to /tools list command in the TUI and follow the - bug: fix ide-client connection to ide-companion when inside docker via
subcommand pattern of other commands by @JayadityaGit in ssh/devcontainer by @kapsner in
[#21213](https://github.com/google-gemini/gemini-cli/pull/21213) [#15049](https://github.com/google-gemini/gemini-cli/pull/15049)
- Handle dirty worktrees better and warn about running scripts/review.sh on - Emit correct newline type return by @scidomino in
untrusted code. by @jacob314 in [#17331](https://github.com/google-gemini/gemini-cli/pull/17331)
[#21791](https://github.com/google-gemini/gemini-cli/pull/21791) - New skill: docs-writer by @g-samroberts in
- feat(policy): support auto-add to policy by default and scoped persistence by [#17268](https://github.com/google-gemini/gemini-cli/pull/17268)
- fix(core): Resolve AbortSignal MaxListenersExceededWarning (#5950) by
@spencer426 in @spencer426 in
[#20361](https://github.com/google-gemini/gemini-cli/pull/20361) [#16735](https://github.com/google-gemini/gemini-cli/pull/16735)
- fix(core): handle AbortError when ESC cancels tool execution by @PrasannaPal21 - Disable tips after 10 runs by @Adib234 in
in [#20863](https://github.com/google-gemini/gemini-cli/pull/20863) [#17101](https://github.com/google-gemini/gemini-cli/pull/17101)
- fix(release): Improve Patch Release Workflow Comments: Clearer Approval - Fix so rewind starts at the bottom and loadHistory refreshes static content.
Guidance by @jerop in by @jacob314 in
[#21894](https://github.com/google-gemini/gemini-cli/pull/21894) [#17335](https://github.com/google-gemini/gemini-cli/pull/17335)
- docs: clarify telemetry setup and comprehensive data map by @jerop in - feat(core): Remove legacy settings. by @joshualitt in
[#21879](https://github.com/google-gemini/gemini-cli/pull/21879) [#17244](https://github.com/google-gemini/gemini-cli/pull/17244)
- feat(core): add per-model token usage to stream-json output by @yongruilin in - feat(plan): add 'communicate' tool kind by @jerop in
[#21839](https://github.com/google-gemini/gemini-cli/pull/21839) [#17341](https://github.com/google-gemini/gemini-cli/pull/17341)
- docs: remove experimental badge from plan mode in sidebar by @jerop in - feat(routing): A/B Test Numerical Complexity Scoring for Gemini 3 by
[#21906](https://github.com/google-gemini/gemini-cli/pull/21906) @mattKorwel in
- fix(cli): prevent race condition in loop detection retry by @skyvanguard in [#16041](https://github.com/google-gemini/gemini-cli/pull/16041)
[#17916](https://github.com/google-gemini/gemini-cli/pull/17916) - feat(plan): update UI Theme for Plan Mode by @Adib234 in
- Add behavioral evals for tracker by @anj-s in [#17243](https://github.com/google-gemini/gemini-cli/pull/17243)
[#20069](https://github.com/google-gemini/gemini-cli/pull/20069) - fix(ui): stabilize rendering during terminal resize in alternate buffer by
- fix(auth): update terminology to 'sign in' and 'sign out' by @clocky in @lkk214 in [#15783](https://github.com/google-gemini/gemini-cli/pull/15783)
[#20892](https://github.com/google-gemini/gemini-cli/pull/20892) - feat(cli): add /agents config command and improve agent discovery by
- docs(mcp): standardize mcp tool fqn documentation by @abhipatel12 in @SandyTao520 in
[#21664](https://github.com/google-gemini/gemini-cli/pull/21664) [#17342](https://github.com/google-gemini/gemini-cli/pull/17342)
- fix(ui): prevent empty tool-group border stubs after filtering by @Aaxhirrr in - feat(mcp): add enable/disable commands for MCP servers (#11057) by @jasmeetsb
[#21852](https://github.com/google-gemini/gemini-cli/pull/21852) in [#16299](https://github.com/google-gemini/gemini-cli/pull/16299)
- make command names consistent by @scidomino in - fix(cli)!: Default to interactive mode for positional arguments by
[#21907](https://github.com/google-gemini/gemini-cli/pull/21907) @ishaanxgupta in
- refactor: remove agent_card_requires_auth config flag by @adamfweidman in [#16329](https://github.com/google-gemini/gemini-cli/pull/16329)
[#21914](https://github.com/google-gemini/gemini-cli/pull/21914) - Fix issue #17080 by @jacob314 in
- feat(a2a): implement standardized normalization and streaming reassembly by [#17100](https://github.com/google-gemini/gemini-cli/pull/17100)
@alisa-alisa in - feat(core): Refresh agents after loading an extension. by @joshualitt in
[#21402](https://github.com/google-gemini/gemini-cli/pull/21402) [#17355](https://github.com/google-gemini/gemini-cli/pull/17355)
- feat(cli): enable skill activation via slash commands by @NTaylorMullen in - fix(cli): include source in policy rule display by @allenhutchison in
[#21758](https://github.com/google-gemini/gemini-cli/pull/21758) [#17358](https://github.com/google-gemini/gemini-cli/pull/17358)
- docs(cli): mention per-model token usage in stream-json result event by - fix: remove obsolete CloudCode PerDay quota and 120s terminal threshold by
@yongruilin in @gsquared94 in
[#21908](https://github.com/google-gemini/gemini-cli/pull/21908) [#17236](https://github.com/google-gemini/gemini-cli/pull/17236)
- fix(plan): prevent plan truncation in approval dialog by supporting - Refactor subagent delegation to be one tool per agent by @gundermanc in
unconstrained heights by @Adib234 in [#17346](https://github.com/google-gemini/gemini-cli/pull/17346)
[#21037](https://github.com/google-gemini/gemini-cli/pull/21037) - fix(core): Include MCP server name in OAuth message by @jerop in
- feat(a2a): switch from callback-based to event-driven tool scheduler by [#17351](https://github.com/google-gemini/gemini-cli/pull/17351)
@cocosheng-g in - Fix pr-triage.sh script to update pull requests with tags "help wanted" and
[#21467](https://github.com/google-gemini/gemini-cli/pull/21467) "maintainer only" by @jacob314 in
- feat(voice): implement speech-friendly response formatter by @Solventerritory [#17324](https://github.com/google-gemini/gemini-cli/pull/17324)
in [#20989](https://github.com/google-gemini/gemini-cli/pull/20989) - feat(plan): implement simple workflow for planning in main agent by @jerop in
- feat: add pulsating blue border automation overlay to browser agent by [#17326](https://github.com/google-gemini/gemini-cli/pull/17326)
@kunal-10-cloud in - fix: exit with non-zero code when esbuild is missing by @yuvrajangadsingh in
[#21173](https://github.com/google-gemini/gemini-cli/pull/21173) [#16967](https://github.com/google-gemini/gemini-cli/pull/16967)
- Add extensionRegistryURI setting to change where the registry is read from by - fix: ensure @docs/cli/custom-commands.md UI message ordering and test by
@kevinjwang1 in @medic-code in
[#20463](https://github.com/google-gemini/gemini-cli/pull/20463) [#12038](https://github.com/google-gemini/gemini-cli/pull/12038)
- fix: patch gaxios v7 Array.toString() stream corruption by @gsquared94 in - fix(core): add alternative command names for Antigravity editor detec… by
[#21884](https://github.com/google-gemini/gemini-cli/pull/21884) @BaeSeokJae in
- fix: prevent hangs in non-interactive mode and improve agent guidance by [#16829](https://github.com/google-gemini/gemini-cli/pull/16829)
@cocosheng-g in - Refactor: Migrate CLI appEvents to Core coreEvents by @Adib234 in
[#20893](https://github.com/google-gemini/gemini-cli/pull/20893) [#15737](https://github.com/google-gemini/gemini-cli/pull/15737)
- Add ExtensionDetails dialog and support install by @chrstnb in - fix(core): await MCP initialization in non-interactive mode by @Ratish1 in
[#20845](https://github.com/google-gemini/gemini-cli/pull/20845) [#17390](https://github.com/google-gemini/gemini-cli/pull/17390)
- chore/release: bump version to 0.34.0-nightly.20260310.4653b126f by - Fix modifyOtherKeys enablement on unsupported terminals by @seekskyworld in
@gemini-cli-robot in [#16714](https://github.com/google-gemini/gemini-cli/pull/16714)
[#21816](https://github.com/google-gemini/gemini-cli/pull/21816) - fix(core): gracefully handle disk full errors in chat recording by
- Changelog for v0.33.0-preview.13 by @gemini-cli-robot in @godwiniheuwa in
[#21927](https://github.com/google-gemini/gemini-cli/pull/21927) [#17305](https://github.com/google-gemini/gemini-cli/pull/17305)
- fix(cli): stabilize prompt layout to prevent jumping when typing by - fix(oauth): update oauth to use 127.0.0.1 instead of localhost by @skeshive in
@NTaylorMullen in [#17388](https://github.com/google-gemini/gemini-cli/pull/17388)
[#21081](https://github.com/google-gemini/gemini-cli/pull/21081) - fix(core): use RFC 9728 compliant path-based OAuth protected resource
- fix: preserve prompt text when cancelling streaming by @Nixxx19 in discovery by @vrv in
[#21103](https://github.com/google-gemini/gemini-cli/pull/21103) [#15756](https://github.com/google-gemini/gemini-cli/pull/15756)
- fix: robust UX for remote agent errors by @Shyam-Raghuwanshi in - Update Code Wiki README badge by @PatoBeltran in
[#20307](https://github.com/google-gemini/gemini-cli/pull/20307) [#15229](https://github.com/google-gemini/gemini-cli/pull/15229)
- feat: implement background process logging and cleanup by @galz10 in - Add conda installation instructions for Gemini CLI by @ishaanxgupta in
[#21189](https://github.com/google-gemini/gemini-cli/pull/21189) [#16921](https://github.com/google-gemini/gemini-cli/pull/16921)
- Changelog for v0.33.0-preview.14 by @gemini-cli-robot in - chore(refactor): extract BaseSettingsDialog component by @SandyTao520 in
[#21938](https://github.com/google-gemini/gemini-cli/pull/21938) [#17369](https://github.com/google-gemini/gemini-cli/pull/17369)
- fix(cli): preserve input text when declining tool approval (#15624) by
@ManojINaik in
[#15659](https://github.com/google-gemini/gemini-cli/pull/15659)
- chore: upgrade dep: diff 7.0.0-> 8.0.3 by @scidomino in
[#17403](https://github.com/google-gemini/gemini-cli/pull/17403)
- feat: add AskUserDialog for UI component of AskUser tool by @jackwotherspoon
in [#17344](https://github.com/google-gemini/gemini-cli/pull/17344)
- feat(ui): display user tier in about command by @sehoon38 in
[#17400](https://github.com/google-gemini/gemini-cli/pull/17400)
- feat: add clearContext to AfterAgent hooks by @jackwotherspoon in
[#16574](https://github.com/google-gemini/gemini-cli/pull/16574)
- fix(cli): change image paste location to global temp directory (#17396) by
@devr0306 in [#17396](https://github.com/google-gemini/gemini-cli/pull/17396)
- Fix line endings issue with Notice file by @scidomino in
[#17417](https://github.com/google-gemini/gemini-cli/pull/17417)
- feat(plan): implement persistent approvalMode setting by @Adib234 in
[#17350](https://github.com/google-gemini/gemini-cli/pull/17350)
- feat(ui): Move keyboard handling into BaseSettingsDialog by @SandyTao520 in
[#17404](https://github.com/google-gemini/gemini-cli/pull/17404)
- Allow prompt queueing during MCP initialization by @Adib234 in
[#17395](https://github.com/google-gemini/gemini-cli/pull/17395)
- feat: implement AgentConfigDialog for /agents config command by @SandyTao520
in [#17370](https://github.com/google-gemini/gemini-cli/pull/17370)
- fix(agents): default to all tools when tool list is omitted in subagents by
@gundermanc in
[#17422](https://github.com/google-gemini/gemini-cli/pull/17422)
- feat(cli): Moves tool confirmations to a queue UX by @abhipatel12 in
[#17276](https://github.com/google-gemini/gemini-cli/pull/17276)
- fix(core): hide user tier name by @sehoon38 in
[#17418](https://github.com/google-gemini/gemini-cli/pull/17418)
- feat: Enforce unified folder trust for /directory add by @galz10 in
[#17359](https://github.com/google-gemini/gemini-cli/pull/17359)
- migrate fireToolNotificationHook to hookSystem by @ved015 in
[#17398](https://github.com/google-gemini/gemini-cli/pull/17398)
- Clean up dead code by @scidomino in
[#17443](https://github.com/google-gemini/gemini-cli/pull/17443)
- feat(workflow): add stale pull request closer with linked-issue enforcement by
@bdmorgan in [#17449](https://github.com/google-gemini/gemini-cli/pull/17449)
- feat(workflow): expand stale-exempt labels to include help wanted and Public
Roadmap by @bdmorgan in
[#17459](https://github.com/google-gemini/gemini-cli/pull/17459)
- chore(workflow): remove redundant label-enforcer workflow by @bdmorgan in
[#17460](https://github.com/google-gemini/gemini-cli/pull/17460)
- Resolves the confusing error message `ripgrep exited with code null that
occurs when a search operation is cancelled or aborted by @maximmasiutin in
[#14267](https://github.com/google-gemini/gemini-cli/pull/14267)
- fix: detect pnpm/pnpx in ~/.local by @rwakulszowa in
[#15254](https://github.com/google-gemini/gemini-cli/pull/15254)
- docs: Add instructions for MacPorts and uninstall instructions for Homebrew by
@breun in [#17412](https://github.com/google-gemini/gemini-cli/pull/17412)
- docs(hooks): clarify mandatory 'type' field and update hook schema
documentation by @abhipatel12 in
[#17499](https://github.com/google-gemini/gemini-cli/pull/17499)
- Improve error messages on failed onboarding by @gsquared94 in
[#17357](https://github.com/google-gemini/gemini-cli/pull/17357)
- Follow up to "enableInteractiveShell for external tooling relying on a2a
server" by @DavidAPierce in
[#17130](https://github.com/google-gemini/gemini-cli/pull/17130)
- Fix/issue 17070 by @alih552 in
[#17242](https://github.com/google-gemini/gemini-cli/pull/17242)
- fix(core): handle URI-encoded workspace paths in IdeClient by @dong-jun-shin
in [#17476](https://github.com/google-gemini/gemini-cli/pull/17476)
- feat(cli): add quick clear input shortcuts in vim mode by @harshanadim in
[#17470](https://github.com/google-gemini/gemini-cli/pull/17470)
- feat(core): optimize shell tool llmContent output format by @SandyTao520 in
[#17538](https://github.com/google-gemini/gemini-cli/pull/17538)
- Fix bug in detecting already added paths. by @jacob314 in
[#17430](https://github.com/google-gemini/gemini-cli/pull/17430)
- feat(scheduler): support multi-scheduler tool aggregation and nested call IDs
by @abhipatel12 in
[#17429](https://github.com/google-gemini/gemini-cli/pull/17429)
- feat(agents): implement first-run experience for project-level sub-agents by
@gundermanc in
[#17266](https://github.com/google-gemini/gemini-cli/pull/17266)
- Update extensions docs by @chrstnb in
[#16093](https://github.com/google-gemini/gemini-cli/pull/16093)
- Docs: Refactor left nav on the website by @jkcinouye in
[#17558](https://github.com/google-gemini/gemini-cli/pull/17558)
- fix(core): stream grep/ripgrep output to prevent OOM by @adamfweidman in
[#17146](https://github.com/google-gemini/gemini-cli/pull/17146)
- feat(plan): add persistent plan file storage by @jerop in
[#17563](https://github.com/google-gemini/gemini-cli/pull/17563)
- feat(agents): migrate subagents to event-driven scheduler by @abhipatel12 in
[#17567](https://github.com/google-gemini/gemini-cli/pull/17567)
- Fix extensions config error by @chrstnb in
[#17580](https://github.com/google-gemini/gemini-cli/pull/17580)
- fix(plan): remove subagent invocation from plan mode by @jerop in
[#17593](https://github.com/google-gemini/gemini-cli/pull/17593)
- feat(ui): add solid background color option for input prompt by @jacob314 in
[#16563](https://github.com/google-gemini/gemini-cli/pull/16563)
- feat(plan): refresh system prompt when approval mode changes (Shift+Tab) by
@jerop in [#17585](https://github.com/google-gemini/gemini-cli/pull/17585)
- feat(cli): add global setting to disable UI spinners by @galz10 in
[#17234](https://github.com/google-gemini/gemini-cli/pull/17234)
- fix(security): enforce strict policy directory permissions by @yunaseoul in
[#17353](https://github.com/google-gemini/gemini-cli/pull/17353)
- test(core): fix tests in windows by @scidomino in
[#17592](https://github.com/google-gemini/gemini-cli/pull/17592)
- feat(mcp/extensions): Allow users to selectively enable/disable MCP servers
included in an extension( Issue #11057 & #17402) by @jasmeetsb in
[#17434](https://github.com/google-gemini/gemini-cli/pull/17434)
- Always map mac keys, even on other platforms by @scidomino in
[#17618](https://github.com/google-gemini/gemini-cli/pull/17618)
- Ctrl-O by @jacob314 in
[#17617](https://github.com/google-gemini/gemini-cli/pull/17617)
- feat(plan): update cycling order of approval modes by @Adib234 in
[#17622](https://github.com/google-gemini/gemini-cli/pull/17622)
- fix(cli): restore 'Modify with editor' option in external terminals by
@abhipatel12 in
[#17621](https://github.com/google-gemini/gemini-cli/pull/17621)
- Slash command for helping in debugging by @gundermanc in
[#17609](https://github.com/google-gemini/gemini-cli/pull/17609)
- feat: add double-click to expand/collapse large paste placeholders by
@jackwotherspoon in
[#17471](https://github.com/google-gemini/gemini-cli/pull/17471)
- refactor(cli): migrate non-interactive flow to event-driven scheduler by
@abhipatel12 in
[#17572](https://github.com/google-gemini/gemini-cli/pull/17572)
- fix: loadcodeassist eligible tiers getting ignored for unlicensed users
(regression) by @gsquared94 in
[#17581](https://github.com/google-gemini/gemini-cli/pull/17581)
- chore(core): delete legacy nonInteractiveToolExecutor by @abhipatel12 in
[#17573](https://github.com/google-gemini/gemini-cli/pull/17573)
- feat(core): enforce server prefixes for MCP tools in agent definitions by
@abhipatel12 in
[#17574](https://github.com/google-gemini/gemini-cli/pull/17574)
- feat (mcp): Refresh MCP prompts on list changed notification by @MrLesk in
[#14863](https://github.com/google-gemini/gemini-cli/pull/14863)
- feat(ui): pretty JSON rendering tool outputs by @medic-code in
[#9767](https://github.com/google-gemini/gemini-cli/pull/9767)
- Fix iterm alternate buffer mode issue rendering backgrounds by @jacob314 in
[#17634](https://github.com/google-gemini/gemini-cli/pull/17634)
- feat(cli): add gemini extensions list --output-format=json by @AkihiroSuda in
[#14479](https://github.com/google-gemini/gemini-cli/pull/14479)
- fix(extensions): add .gitignore to extension templates by @godwiniheuwa in
[#17293](https://github.com/google-gemini/gemini-cli/pull/17293)
- paste transform followup by @jacob314 in
[#17624](https://github.com/google-gemini/gemini-cli/pull/17624)
- refactor: rename formatMemoryUsage to formatBytes by @Nubebuster in
[#14997](https://github.com/google-gemini/gemini-cli/pull/14997)
- chore: remove extra top margin from /hooks and /extensions by @jackwotherspoon
in [#17663](https://github.com/google-gemini/gemini-cli/pull/17663)
- feat(cli): add oncall command for issue triage by @sehoon38 in
[#17661](https://github.com/google-gemini/gemini-cli/pull/17661)
- Fix sidebar issue for extensions link by @chrstnb in
[#17668](https://github.com/google-gemini/gemini-cli/pull/17668)
- Change formatting to prevent UI redressing attacks by @scidomino in
[#17611](https://github.com/google-gemini/gemini-cli/pull/17611)
- Fix cluster of bugs in the settings dialog. by @jacob314 in
[#17628](https://github.com/google-gemini/gemini-cli/pull/17628)
- Update sidebar to resolve site build issues by @chrstnb in
[#17674](https://github.com/google-gemini/gemini-cli/pull/17674)
- fix(admin): fix a few bugs related to admin controls by @skeshive in
[#17590](https://github.com/google-gemini/gemini-cli/pull/17590)
- revert bad changes to tests by @scidomino in
[#17673](https://github.com/google-gemini/gemini-cli/pull/17673)
- feat(cli): show candidate issue state reason and duplicate status in triage by
@sehoon38 in [#17676](https://github.com/google-gemini/gemini-cli/pull/17676)
- Fix missing slash commands when Gemini CLI is in a project with a package.json
that doesn't follow semantic versioning by @Adib234 in
[#17561](https://github.com/google-gemini/gemini-cli/pull/17561)
- feat(core): Model family-specific system prompts by @joshualitt in
[#17614](https://github.com/google-gemini/gemini-cli/pull/17614)
- Sub-agents documentation. by @gundermanc in
[#16639](https://github.com/google-gemini/gemini-cli/pull/16639)
- feat: wire up AskUserTool with dialog by @jackwotherspoon in
[#17411](https://github.com/google-gemini/gemini-cli/pull/17411)
- Load extension settings for hooks, agents, skills by @chrstnb in
[#17245](https://github.com/google-gemini/gemini-cli/pull/17245)
- Fix issue where Gemini CLI can make changes when simply asked a question by
@gundermanc in
[#17608](https://github.com/google-gemini/gemini-cli/pull/17608)
- Update docs-writer skill for editing and add style guide for reference. by
@g-samroberts in
[#17669](https://github.com/google-gemini/gemini-cli/pull/17669)
- fix(ux): have user message display a short path for pasted images by @devr0306
in [#17613](https://github.com/google-gemini/gemini-cli/pull/17613)
- feat(plan): enable AskUser tool in Plan mode for clarifying questions by
@jerop in [#17694](https://github.com/google-gemini/gemini-cli/pull/17694)
- GEMINI.md polish by @jacob314 in
[#17680](https://github.com/google-gemini/gemini-cli/pull/17680)
- refactor(core): centralize path validation and allow temp dir access for tools
by @NTaylorMullen in
[#17185](https://github.com/google-gemini/gemini-cli/pull/17185)
- feat(skills): promote Agent Skills to stable by @abhipatel12 in
[#17693](https://github.com/google-gemini/gemini-cli/pull/17693)
- refactor(cli): keyboard handling and AskUserDialog by @jacob314 in
[#17414](https://github.com/google-gemini/gemini-cli/pull/17414)
- docs: Add Experimental Remote Agent Docs by @adamfweidman in
[#17697](https://github.com/google-gemini/gemini-cli/pull/17697)
- revert: promote Agent Skills to stable (#17693) by @abhipatel12 in
[#17712](https://github.com/google-gemini/gemini-cli/pull/17712)
- feat(ux) Expandable (ctrl-O) and scrollable approvals in alternate buffer
mode. by @jacob314 in
[#17640](https://github.com/google-gemini/gemini-cli/pull/17640)
- feat(skills): promote skills settings to stable by @abhipatel12 in
[#17713](https://github.com/google-gemini/gemini-cli/pull/17713)
- fix(cli): Preserve settings dialog focus when searching by @SandyTao520 in
[#17701](https://github.com/google-gemini/gemini-cli/pull/17701)
- feat(ui): add terminal cursor support by @jacob314 in
[#17711](https://github.com/google-gemini/gemini-cli/pull/17711)
- docs(skills): remove experimental labels and update tutorials by @abhipatel12
in [#17714](https://github.com/google-gemini/gemini-cli/pull/17714)
- docs: remove 'experimental' syntax for hooks in docs by @abhipatel12 in
[#17660](https://github.com/google-gemini/gemini-cli/pull/17660)
- Add support for an additional exclusion file besides .gitignore and
.geminiignore by @alisa-alisa in
[#16487](https://github.com/google-gemini/gemini-cli/pull/16487)
- feat: add review-frontend-and-fix command by @galz10 in
[#17707](https://github.com/google-gemini/gemini-cli/pull/17707)
**Full Changelog**: **Full changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.33.0-preview.15...v0.34.0-preview.1 https://github.com/google-gemini/gemini-cli/compare/v0.26.0-preview.5...v0.27.0-preview.0
+3
View File
@@ -0,0 +1,3 @@
# Authentication setup
See: [Getting Started - Authentication Setup](../get-started/authentication.md).
+3 -2
View File
@@ -2,8 +2,9 @@
The Gemini CLI includes a Checkpointing feature that automatically saves a The Gemini CLI includes a Checkpointing feature that automatically saves a
snapshot of your project's state before any file modifications are made by snapshot of your project's state before any file modifications are made by
AI-powered tools. This lets you safely experiment with and apply code changes, AI-powered tools. This allows you to safely experiment with and apply code
knowing you can instantly revert back to the state before the tool was run. changes, knowing you can instantly revert back to the state before the tool was
run.
## How it works ## How it works

Some files were not shown because too many files have changed in this diff Show More