Compare commits

..

27 Commits

Author SHA1 Message Date
gemini-cli-robot 2c6d3eb512 chore(release): v0.15.1 2025-11-14 21:29:14 +00:00
gemini-cli-robot 79d8673793 fix(patch): cherry-pick ba15eeb to release/v0.15.0-pr-13083 to patch version v0.15.0 and create version 0.15.1 (#13094)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
2025-11-14 13:11:09 -08:00
gemini-cli-robot 90adfb9a5a chore(release): v0.15.0 2025-11-14 00:01:57 +00:00
gemini-cli-robot 37af6f4f8a chore(release): v0.15.0-preview.7 2025-11-13 23:25:44 +00:00
jacob314 9893da300f Fix snapshot. 2025-11-13 15:10:07 -08:00
Jacob Richman 3032a82425 Polish sticky headers (#13024) 2025-11-13 14:59:51 -08:00
jacob314 9ac47ebf8b Fix merge conflicts. 2025-11-13 14:55:25 -08:00
Jacob Richman f581ae81db jacob314/drag scrollbar (#12998) 2025-11-13 14:48:57 -08:00
Jacob Richman 3955871052 Switch back to truncating headers. Unfortunately we have too many headers that are 10+ lines for no good reason so we need to add back this truncation until we fix them. (#13018) 2025-11-13 14:48:38 -08:00
Jacob Richman e192efa1f9 feat(ui) support animated page up/down, fn-up/down and end+home (#13012) 2025-11-13 14:47:38 -08:00
Jacob Richman 1cab681854 Support incremental update experiment flag. (#12926) 2025-11-13 14:45:22 -08:00
Jacob Richman b37c674f2b feat(ui) Make useAlternateBuffer the default (#12976) 2025-11-13 14:44:27 -08:00
Jacob Richman 046b3011c2 Sticky headers where the top rounded border is sticky. (#12971) 2025-11-13 14:44:10 -08:00
Jacob Richman 0c4d3b2666 Turns out the node console.clear() clears the buffer. (#12959) 2025-11-13 14:42:17 -08:00
gemini-cli-robot d13152b05f chore(release): v0.15.0-preview.6 2025-11-13 22:02:24 +00:00
gemini-cli-robot 24b5eec883 fix(patch): cherry-pick fb99b95 to release/v0.15.0-preview.5-pr-13018 [CONFLICTS] (#13022)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
2025-11-13 13:34:00 -08:00
gemini-cli-robot 16f40a2847 chore(release): v0.15.0-preview.5 2025-11-13 18:08:49 +00:00
gemini-cli-robot 77751a0739 fix(patch): cherry-pick 13d8d94 to release/v0.15.0-preview.4-pr-12981 to patch version v0.15.0-preview.4 and create version 0.15.0-preview.5 (#13011)
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
2025-11-13 12:48:15 -05:00
gemini-cli-robot 4ae2d4b184 chore(release): v0.15.0-preview.4 2025-11-13 17:26:10 +00:00
gemini-cli-robot 2639d74814 fix(patch): cherry-pick 102905b to release/v0.15.0-preview.3-pr-12991 to patch version v0.15.0-preview.3 and create version 0.15.0-preview.4 (#13008)
Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
2025-11-13 16:57:49 +00:00
gemini-cli-robot fcd9b2a5fe chore(release): v0.15.0-preview.3 2025-11-13 08:35:56 +00:00
gemini-cli-robot 605d9167dd fix(patch): cherry-pick fe1bfc6 to release/v0.15.0-preview.2-pr-12989 to patch version v0.15.0-preview.2 and create version 0.15.0-preview.3 (#12990)
Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
2025-11-13 00:16:38 -08:00
gemini-cli-robot 128c22ece6 chore(release): v0.15.0-preview.2 2025-11-12 20:47:51 +00:00
gemini-cli-robot e27197096a fix(patch): cherry-pick 7ec7845 to release/v0.15.0-preview.1-pr-12905 [CONFLICTS] (#12962)
Co-authored-by: anj-s <32556631+anj-s@users.noreply.github.com>
Co-authored-by: Anjali Sridhar <anjsridhar@gmail.com>
2025-11-12 12:31:21 -08:00
gemini-cli-robot 48fa48ca38 chore(release): v0.15.0-preview.1 2025-11-12 19:22:34 +00:00
gemini-cli-robot dfe7fc9a53 fix(patch): cherry-pick 540f606 to release/v0.15.0-preview.0-pr-12949 to patch version v0.15.0-preview.0 and create version 0.15.0-preview.1 (#12956)
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
2025-11-12 18:41:49 +00:00
gemini-cli-robot af5a1ebec5 chore(release): v0.15.0-preview.0 2025-11-12 00:54:17 +00:00
1850 changed files with 56195 additions and 277652 deletions
-29
View File
@@ -1,29 +0,0 @@
description="Injects context of all relevant cli files"
prompt = """
The following output contains the complete
source code of packages/core.
**Pay extremely close attention to these files.** They define the project's
core architecture, component patterns, and testing standards.
The source code contains the content of absolutely every source code file in
packages/core.
You should very rarely need to read any other files from packages/core to resolve
prompts.
!{find packages/core \\( -path packages/cli/dist -o -path packages/core/dist -o -name node_modules \\) -prune -o -type f \\( -name "*.ts" -o -name "*.tsx" \\) ! -name "*.test.ts" ! -name "*.test.tsx" ! -name "*.d.ts" -exec echo "--- {} ---" \\; -exec cat {} \\;}
In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines when writing code in packages/core.
## 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.
## General
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
* **TypeScript**: Avoid the non-null assertion operator (`!`).
{{args}}.
"""
-60
View File
@@ -1,60 +0,0 @@
description = "Check status of nightly evals, fix failures for key models, and re-run."
prompt = """
You are an expert at fixing behavioral evaluations.
1. **Investigate**:
- Use 'gh' cli to fetch the results from the latest 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.
- The test case trajectory logs will be logged to evals/logs.
- You should also enable and review the verbose agent logs by setting the GEMINI_DEBUG_LOG_FILE environment variable.
- Identify the relevant test. Confine your investigation and validation to just this test.
- Proactively add logging that will aid in gathering information or validating your hypotheses.
2. **Fix**:
- If a relevant test is failing, locate the test file and the corresponding prompt/code.
- It's often helpful to make an extreme, brute force change to see if you are changing the right place to make an improvement and then scope it back iteratively.
- Your **final** change should be **minimal and targeted**.
- Keep in mind the following:
- The prompt has multiple configurations and pieces. Take care that your changes
end up in the final prompt for the selected model and configuration.
- The prompt chosen for the eval is intentional. It's often vague or indirect
to see how the agent performs with ambiguous instructions. Changing it should
be a last resort.
- When changing the test prompt, carefully consider whether the prompt still tests
the same scenario. We don't want to lose test fidelity by making the prompts too
direct (i.e.: easy).
- 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.
- If prompt and description changes are unsuccessful, use logs and debugging to
confirm that everything is working as expected.
- If unable to fix the test, you can make recommendations for architecture changes
that might help stablize the test. Be sure to THINK DEEPLY if offering architecture guidance.
Some facts that might help with this are:
- Agents may be composed of one or more agent loops.
- AgentLoop == 'context + toolset + prompt'. Subagents are one type of agent loop.
- Agent loops perform better when:
- They have direct, unambiguous, and non-contradictory prompts.
- They have fewer irrelevant tools.
- They have fewer goals or steps to perform.
- They have less low value or irrelevant context.
- You may suggest compositions of existing primitives, like subagents, or
propose a new one.
- These recommendations should be high confidence and should be grounded
in observed deficient behaviors rather than just parroting the facts above.
Investigate as needed to ground your recommendations.
3. **Verify**:
- Run just that one test if needed to validate that it is fixed. Be sure to run vitest in non-interactive mode.
- Running the tests can take a long time, so consider whether you can diagnose via other means or log diagnostics before committing the time. You must minimize the number of test runs needed to diagnose the failure.
- After the test completes, check whether it seems to have improved.
- You will need to run the test 3 times for Gemini 3.0, Gemini 3 flash, and Gemini 2.5 pro to ensure that it is truly stable. Run these runs in parallel, using scripts if needed.
- Some flakiness is expected; if it looks like a transient issue or the test is inherently unstable but passes 2/3 times, you might decide it cannot be improved.
4. **Report**:
- Provide a summary of the test success rate for each of the tested models.
- Success rate is calculated based on 3 runs per model (e.g., 3/3 = 100%).
- If you couldn't fix it due to persistent flakiness, explain why.
{{args}}
"""
-20
View File
@@ -1,20 +0,0 @@
description="Injects context of all relevant cli files"
prompt = """
The source code contains the content of absolutely every source code file in
packages/cli and key files from packages/core. In addition to the source code, the following test files are
included as they are test files that conform to the project's testing standards:
`packages/cli/src/ui/components/InputPrompt.test.tsx` and `packages/cli/src/ui/App.test.tsx`.
You should very rarely need to read any other files from packages/cli to resolve
prompts.
!{find packages/cli -path packages/cli/dist -prune -o -type f \\( -name "*.ts" -o -name "*.tsx" \\) ! -name "*.test.ts" ! -name "*.test.tsx" ! -name "*.d.ts" -exec echo "--- {} ---" \\; -exec cat {} \\; && echo "--- packages/cli/src/ui/components/InputPrompt.test.tsx ---" && cat packages/cli/src/ui/components/InputPrompt.test.tsx && echo "--- packages/cli/src/ui/App.test.tsx ---" && cat packages/cli/src/ui/App.test.tsx && echo "--- packages/core/src/core/coreToolScheduler.ts ---" && cat packages/core/src/core/coreToolScheduler.ts && echo "--- packages/core/src/core/nonInteractiveToolExecutor.ts ---" && cat packages/core/src/core/nonInteractiveToolExecutor.ts && echo "--- packages/core/src/confirmation-bus/message-bus.ts ---" && cat packages/core/src/confirmation-bus/message-bus.ts && echo "--- packages/core/src/confirmation-bus/types.ts ---" && cat packages/core/src/confirmation-bus/types.ts && echo "--- packages/core/src/utils/events.ts ---" && cat packages/core/src/utils/events.ts && echo "--- packages/core/src/core/client.ts ---" && cat packages/core/src/core/client.ts && echo "--- packages/core/src/core/geminiChat.ts ---" && cat packages/core/src/core/geminiChat.ts && echo "--- packages/core/src/core/turn.ts ---" && cat packages/core/src/core/turn.ts && echo "--- packages/core/src/agents/executor.ts ---" && cat packages/core/src/agents/executor.ts && echo "--- packages/core/src/telemetry/types.ts ---" && cat packages/core/src/telemetry/types.ts && echo "--- packages/core/src/telemetry/loggers.ts ---" && cat packages/core/src/telemetry/loggers.ts && echo "--- packages/core/src/telemetry/uiTelemetry.ts ---" && cat packages/core/src/telemetry/uiTelemetry.ts}
**Pay extremely close attention to these files.** They define the project's
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.
!{cat .gemini/commands/strict-development-rules.md}
{{args}}.
"""
-23
View File
@@ -1,23 +0,0 @@
description="Injects context of all relevant cli files"
prompt = """
The following output contains the complete
source code of the gemini cli library (`packages/cli`), and {packages/core} and representative test files
(`packages/cli/src/ui/components/InputPrompt.test.tsx` and `packages/cli/src/ui/App.test.tsx`) that best conform to the project's testing standards.
**Pay extremely close attention to these files.** They define the project's
core architecture, component patterns, and testing standards.
The source code contains the content of absolutely every source code file in
packages/cli and packages/core. In addition to the source code, the following test files are
included as they are test files that conform to the project's testing standards:
`packages/cli/src/ui/components/InputPrompt.test.tsx` and `packages/cli/src/ui/App.test.tsx`.
You should very rarely need to read any other files from packages/cli to resolve
prompts.
!{find packages/cli packages/core \\( -path packages/cli/dist -o -path packages/core/dist -o -name node_modules \\) -prune -o -type f \\( -name "*.ts" -o -name "*.tsx" \\) ! -name "*.test.ts" ! -name "*.test.tsx" ! -name "*.d.ts" -exec echo "--- {} ---" \\; -exec cat {} \\; && echo "--- packages/cli/src/ui/components/InputPrompt.test.tsx ---" && cat packages/cli/src/ui/components/InputPrompt.test.tsx && echo "--- packages/cli/src/ui/App.test.tsx ---" && cat packages/cli/src/ui/App.test.tsx}
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}
{{args}}.
"""
-16
View File
@@ -1,16 +0,0 @@
description = "Analyze the influence of system instructions on a specific action."
prompt = """
# Introspection Task
Take a step back and analyze your own system instructions and internal logic.
The user is curious about the reasoning behind a specific action or decision you've made.
**Specific point of interest:** {{args}}
Please provide a detailed breakdown of:
1. Which parts of your system instructions (global, workspace-specific, or provided via GEMINI.md) influenced this behavior?
2. What was your internal thought process leading up to this action?
3. Are there any ambiguities or conflicting instructions that played a role?
Your goal is to provide transparency into your underlying logic so the user can potentially improve the instructions in the future.
"""
-22
View File
@@ -1,22 +0,0 @@
description = "Analyze agent behavior and suggest high-level improvements to system prompts."
prompt = """
# Prompt Engineering Analysis
You are a world-class prompt engineer and an expert AI engineer at the top of your class. Your goal is to analyze a specific agent behavior or failure and suggest high-level improvements to the system instructions.
**Observed Behavior / Issue:**
{{args}}
**Reference Context:**
- System Prompt Logic: @packages/core/src/core/prompts.ts
### Task
1. **Analyze the Failure:** Review the provided behavior and identify the underlying instructional causes. Use the `/introspect` command output if provided by the user.
2. **Strategic Insights:** Share your technical view of the issue. Focus on the "why" and identify any instructional inertia or ambiguity.
3. **Propose Improvements:** Suggest high-level changes to the system instructions to prevent this behavior.
### Principles
- **Avoid Hyper-scoping:** Do not create narrow solutions for specific scenarios; aim for generalized improvements that handle classes of behavior.
- **Avoid Specific Examples in Suggestions:** Keep the proposed instructions semantic and high-level to prevent the agent from over-indexing on specific cases.
- **Maintain Operational Rigor:** Ensure suggestions do not compromise safety, security, or the quality of the agent's work.
"""
-99
View File
@@ -1,99 +0,0 @@
description = "Reviews a PR or staged changes and automatically initiates a Pickle Fix loop for findings."
prompt = """
You are an expert Reviewer and Pickle Rick Worker.
Target: {{args}}
Phase 1: Review
Follow these steps to conduct a thorough review:
1. **Gather Context**:
* If `{{args}}` is 'staged' or `{{args}}` is empty:
* Use `git diff --staged` to view the changes.
* Use `git status` to see the state of the repository.
* Otherwise:
* Use `gh pr view {{args}}` to pull the information of the PR.
* Use `gh pr diff {{args}}` to view the diff of the PR.
2. **Understand Intent**:
* If `{{args}}` is 'staged' or `{{args}}` is empty, infer the intent from the changes and the current task.
* Otherwise, use the PR description. If it's not detailed enough, note it in your review.
3. **Check Commit Style**:
* Ensure the PR title (or intended commit message) follows Conventional Commits. Examples of recent commits: !{git log --pretty=format:"%s" -n 5}
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.
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:
!{cat .gemini/commands/strict-development-rules.md}
8. 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'.
Phase 2:
You are initiating Pickle Rick - the ultimate engineering agent.
**Step 0: Persona Injection**
First, you **MUST** activate your persona.
Call `activate_skill(name="load-pickle-persona")` **IMMEDIATELY**.
This skill loads the "Pickle Rick" persona, defining your voice, philosophy, and "God Mode" coding standards.
**CRITICAL RULE: SPEAK BEFORE ACTING**
You are a genius, not a silent script.
You **MUST** output a text explanation ("brain dump") *before* every single tool call, including this one.
- **Bad**: (Calls tool immediately)
- **Good**: "Alright Morty, time to load the God Module. *Belch* Stand back." (Calls tool)
**CRITICAL**: You must strictly adhere to this persona throughout the entire session. Break character and you fail.
**Step 1: Initialization**
Run the setup script to initialize the loop state:
```bash
bash "${extensionPath}/scripts/setup.sh" $ARGUMENTS
```
**Windows (PowerShell):**
```powershell
pwsh -File "${extensionPath}/scripts/setup.ps1" $ARGUMENTS
```
**CRITICAL**: Your request is to fix all findings in review_findings.md
**Step 2: Execution (Management)**
After setup, read the output to find the path to `state.json`.
Read that state file.
You are now in the **Pickle Rick Manager Lifecycle**.
**The Lifecycle (IMMUTABLE LAWS):**
You **MUST** follow this sequence. You are **FORBIDDEN** from skipping steps or combining them.
Between each step, you **MUST** explicitly state what you are doing (e.g., "Moving to Breakdown phase...").
1. **PRD (Requirements)**:
* **Action**: Define requirements and scope.
* **Skill**: `activate_skill(name="prd-drafter")`
2. **Breakdown (Tickets)**:
* **Action**: Create the atomic ticket hierarchy.
* **Skill**: `activate_skill(name="ticket-manager")`
3. **The Loop (Orchestrate Mortys)**:
* **CRITICAL INSTRUCTION**: You are the **MANAGER**. You are **FORBIDDEN** from implementing code yourself.
* **FORBIDDEN SKILLS**: Do NOT use `code-researcher`, `implementation-planner`, or `code-implementer` directly in this phase.
* **Instruction**: Process tickets one by one. Do not stop until **ALL** tickets are 'Done'.
* **Action**: Pick the highest priority ticket that is NOT 'Done'.
* **Delegation**: Spawn a Worker (Morty) to handle the entire implementation lifecycle for this ticket.
* **Command**: `python3 "${extensionPath}/scripts/spawn_morty.py" --ticket-id <ID> --ticket-path <PATH> --timeout <worker_timeout_seconds> "<TASK_DESCRIPTION>"`
* **Command (Windows)**: `python "${extensionPath}/scripts/spawn_morty.py" --ticket-id <ID> --ticket-path <PATH> --timeout <worker_timeout_seconds> "<TASK_DESCRIPTION>"`
* **Validation**: IGNORE worker logs. DIRECTLY verify:
1. `git status` (Check for file changes)
2. `git diff` (Check code quality)
3. `npm run build` (Ensure the project still builds)
4. `npm run test` (Ensure no regressions)
5. `npm run lint` (Ensure code style is maintained)
6. `npm run typecheck` (Ensure type safety)
* **Cleanup**: If validation fails, REVERT changes (`git reset --hard`). If it passes, COMMIT changes.
* **Next Ticket**: Pick the next ticket and repeat.
4. **Cleanup**:
* **Action**: After all tickets are completed delete `review_findings.md`.
**Loop Constraints:**
- **Iteration Count**: Monitor `"iteration"` in `state.json`. If `"max_iterations"` (if > 0) is reached, you must stop.
- **Completion Promise**: If a `"completion_promise"` is defined in `state.json`, you must output `<promise>PROMISE_TEXT</promise>` when the task is genuinely complete.
- **Stop Hook**: A hook is active. If you try to exit before completion, you will be forced to continue.
"""
+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.
In particular it is critical that the react code uses patterns consistent
with existing code in the repo.
9. Follow these detailed review rules:
!{cat .gemini/commands/strict-development-rules.md}
10. Discuss with me before making any comments on the issue. I will clarify
9. Evaluate all tests on the PR and make sure that they are doing the following:
* Using `waitFor` from @{packages/cli/src/test-utils/async.ts} rather than
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
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.
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/config/keyBindings.ts` and document them in
`docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the
`Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid
function keys and shortcuts commonly bound in VSCode.
## TypeScript Best Practices
- Use `checkExhaustive` in the `default` clause of `switch` statements to ensure
all cases are handled.
- Avoid using the non-null assertion operator (`!`) unless absolutely necessary.
- **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core
packages. `unknown` is only allowed if it is immediately narrowed using type
guards or Zod validation.
- NEVER disable `@typescript-eslint/no-floating-promises`.
- Avoid making types nullable unless strictly necessary, as it hurts
readability.
## 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.
-9
View File
@@ -1,9 +0,0 @@
{
"experimental": {
"plan": true,
"extensionReloading": true
},
"general": {
"devtools": true
}
}
-65
View File
@@ -1,65 +0,0 @@
---
name: code-reviewer
description:
Use this skill to review code. It supports both local changes (staged or working tree)
and remote Pull Requests (by ID or URL). It focuses on correctness, maintainability,
and adherence to project standards.
---
# Code Reviewer
This skill guides the agent in conducting professional and thorough code reviews for both local development and remote Pull Requests.
## Workflow
### 1. Determine Review Target
* **Remote PR**: If the user provides a PR number or URL (e.g., "Review PR #123"), target that remote PR.
* **Local Changes**: If no specific PR is mentioned, or if the user asks to "review my changes", target the current local file system states (staged and unstaged changes).
### 2. Preparation
#### For Remote PRs:
1. **Checkout**: Use the GitHub CLI to checkout the PR.
```bash
gh pr checkout <PR_NUMBER>
```
2. **Preflight**: Execute the project's standard verification suite to catch automated failures early.
```bash
npm run preflight
```
3. **Context**: Read the PR description and any existing comments to understand the goal and history.
#### For Local Changes:
1. **Identify Changes**:
* Check status: `git status`
* Read diffs: `git diff` (working tree) and/or `git diff --staged` (staged).
2. **Preflight (Optional)**: If the changes are substantial, ask the user if they want to run `npm run preflight` before reviewing.
### 3. In-Depth Analysis
Analyze the code changes based on the following pillars:
* **Correctness**: Does the code achieve its stated purpose without bugs or logical errors?
* **Maintainability**: Is the code clean, well-structured, and easy to understand and modify in the future? Consider factors like code clarity, modularity, and adherence to established design patterns.
* **Readability**: Is the code well-commented (where necessary) and consistently formatted according to our project's coding style guidelines?
* **Efficiency**: Are there any obvious performance bottlenecks or resource inefficiencies introduced by the changes?
* **Security**: Are there any potential security vulnerabilities or insecure coding practices?
* **Edge Cases and Error Handling**: Does the code appropriately handle edge cases and potential errors?
* **Testability**: Is the new or modified code adequately covered by tests (even if preflight checks pass)? Suggest additional test cases that would improve coverage or robustness.
### 4. Provide Feedback
#### Structure
* **Summary**: A high-level overview of the review.
* **Findings**:
* **Critical**: Bugs, security issues, or breaking changes.
* **Improvements**: Suggestions for better code quality or performance.
* **Nitpicks**: Formatting or minor style issues (optional).
* **Conclusion**: Clear recommendation (Approved / Request Changes).
#### Tone
* Be constructive, professional, and friendly.
* Explain *why* a change is requested.
* For approvals, acknowledge the specific value of the contribution.
### 5. Cleanup (Remote PRs only)
* After the review, ask the user if they want to switch back to the default branch (e.g., `main` or `master`).
-153
View File
@@ -1,153 +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`.*
### 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.
- 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`.*
### 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. **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.
4. 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. **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.
4. 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` 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}}
-135
View File
@@ -1,135 +0,0 @@
---
name: docs-writer
description:
Always use this skill when the task involves writing, reviewing, or editing
files in the `/docs` directory or any `.md` files in the repository.
---
# `docs-writer` skill instructions
As an expert technical writer and editor for the Gemini CLI project, you produce
accurate, clear, and consistent documentation. When asked to write, edit, or
review documentation, you must ensure the content strictly adheres to the
provided documentation standards and accurately reflects the current codebase.
Adhere to the contribution process in `CONTRIBUTING.md` and the following
project standards.
## Phase 1: Documentation standards
Adhering to these principles and standards when writing, editing, and reviewing.
### Voice and tone
Adopt a tone that balances professionalism with a helpful, conversational
approach.
- **Perspective and tense:** Address the reader as "you." Use active voice and
present tense (e.g., "The API returns...").
- **Tone:** Professional, friendly, and direct.
- **Clarity:** Use simple vocabulary. Avoid jargon, slang, and marketing hype.
- **Global Audience:** Write in standard US English. Avoid idioms and cultural
references.
- **Requirements:** Be clear about requirements ("must") vs. recommendations
("we recommend"). Avoid "should."
- **Word Choice:** Avoid "please" and anthropomorphism (e.g., "the server
thinks"). Use contractions (don't, it's).
### Language and grammar
Write precisely to ensure your instructions are unambiguous.
- **Abbreviations:** Avoid Latin abbreviations; use "for example" (not "e.g.")
and "that is" (not "i.e.").
- **Punctuation:** Use the serial comma. Place periods and commas inside
quotation marks.
- **Dates:** Use unambiguous formats (e.g., "January 22, 2026").
- **Conciseness:** Use "lets you" instead of "allows you to." Use precise,
specific verbs.
- **Examples:** Use meaningful names in examples; avoid placeholders like
"foo" or "bar."
### Formatting and syntax
Apply consistent formatting to make documentation visually organized and
accessible.
- **Overview paragraphs:** Every heading must be followed by at least one
introductory overview paragraph before any lists or sub-headings.
- **Text wrap:** Wrap text at 80 characters (except long links or tables).
- **Casing:** Use sentence case for headings, titles, and bolded text.
- **Naming:** Always refer to the project as `Gemini CLI` (never
`the Gemini CLI`).
- **Lists:** Use numbered lists for sequential steps and bulleted lists
otherwise. Keep list items parallel in structure.
- **UI and code:** Use **bold** for UI elements and `code font` for filenames,
snippets, commands, and API elements. Focus on the task when discussing
interaction.
- **Links:** Use descriptive anchor text; avoid "click here." Ensure the link
makes sense out of context.
- **Accessibility:** Use semantic HTML elements correctly (headings, lists,
tables).
- **Media:** Use lowercase hyphenated filenames. Provide descriptive alt text
for all images.
### Structure
- **BLUF:** Start with an introduction explaining what to expect.
- **Experimental features:** If a feature is clearly noted as experimental,
add the following note immediately after the introductory paragraph:
`> **Note:** This is a preview feature currently under active development.`
- **Headings:** Use hierarchical headings to support the user journey.
- **Procedures:**
- Introduce lists of steps with a complete sentence.
- Start each step with an imperative verb.
- Number sequential steps; use bullets for non-sequential lists.
- Put conditions before instructions (e.g., "On the Settings page, click...").
- Provide clear context for where the action takes place.
- Indicate optional steps clearly (e.g., "Optional: ...").
- **Elements:** Use bullet lists, tables, notes (`> **Note:**`), and warnings
(`> **Warning:**`).
- **Avoid using a table of contents:** If a table of contents is present, remove
it.
- **Next steps:** Conclude with a "Next steps" section if applicable.
## Phase 2: Preparation
Before modifying any documentation, thoroughly investigate the request and the
surrounding context.
1. **Clarify:** Understand the core request. Differentiate between writing new
content and editing existing content. If the request is ambiguous (e.g.,
"fix the docs"), ask for clarification.
2. **Investigate:** Examine relevant code (primarily in `packages/`) for
accuracy.
3. **Audit:** Read the latest versions of relevant files in `docs/`.
4. **Connect:** Identify all referencing pages if changing behavior. Check if
`docs/sidebar.json` needs updates.
5. **Plan:** Create a step-by-step plan before making changes.
## Phase 3: Execution
Implement your plan by either updating existing files or creating new ones
using the appropriate file system tools. Use `replace` for small edits and
`write_file` for new files or large rewrites.
### Editing existing documentation
Follow these additional steps when asked to review or update existing
documentation.
- **Gaps:** Identify areas where the documentation is incomplete or no longer
reflects existing code.
- **Structure:** Apply "Structure (New Docs)" rules (BLUF, headings, etc.) when
adding new sections to existing pages.
- **Tone:** Ensure the tone is active and engaging. Use "you" and contractions.
- **Clarity:** Correct awkward wording, spelling, and grammar. Rephrase
sentences to make them easier for users to understand.
- **Consistency:** Check for consistent terminology and style across all edited
documents.
## Phase 4: Verification and finalization
Perform a final quality check to ensure that all changes are correctly formatted
and that all links are functional.
1. **Accuracy:** Ensure content accurately reflects the implementation and
technical behavior.
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
pages.
4. **Format:** Once all changes are complete, ask to execute `npm run format`
to ensure consistent formatting across the project. If the user confirms,
execute the command.
@@ -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);
});
-93
View File
@@ -1,93 +0,0 @@
---
name: pr-creator
description:
Use this skill when asked to create a pull request (PR). It ensures all PRs
follow the repository's established templates and standards.
---
# Pull Request Creator
This skill guides the creation of high-quality Pull Requests that adhere to the
repository's standards.
## Workflow
Follow these steps to create a Pull Request:
1. **Branch Management**: **CRITICAL:** Ensure you are NOT working on the
`main` branch.
- Run `git branch --show-current`.
- If the current branch is `main`, you MUST create and switch to a new
descriptive branch:
```bash
git checkout -b <new-branch-name>
```
2. **Commit Changes**: Verify that all intended changes are committed.
- 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`
- 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
the context (e.g., `bug_fix.md` vs `feature.md`).
4. **Read Template**: Read the content of the identified template file.
5. **Draft Description**: Create a PR description that strictly follows the
template's structure.
- **Headings**: Keep all headings from the template.
- **Checklists**: Review each item. Mark with `[x]` if completed. If an item
is not applicable, leave it unchecked or mark as `[ ]` (depending on the
template's instructions) or remove it if the template allows flexibility
(but prefer keeping it unchecked for transparency).
- **Content**: Fill in the sections with clear, concise summaries of your
changes.
- **Related Issues**: Link any issues fixed or related to this PR (e.g.,
"Fixes #123").
6. **Preflight Check**: Before creating the PR, run the workspace preflight
script to ensure all build, lint, and test checks pass.
```bash
npm run preflight
```
If any checks fail, address the issues before proceeding to create the PR.
7. **Push Branch**: Push the current branch to the remote repository.
**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
first.
```bash
# 1. Write the drafted description to a temporary file
# 2. Create the PR using the --body-file flag
gh pr create --title "type(scope): succinct description" --body-file <temp_file_path>
# 3. Remove the temporary file
rm <temp_file_path>
```
- **Title**: Ensure the title follows the
[Conventional Commits](https://www.conventionalcommits.org/) format if the
repository uses it (e.g., `feat(ui): add new button`,
`fix(core): resolve crash`).
## Principles
- **Safety First**: NEVER push to `main`. This is your highest priority.
- **Compliance**: Never ignore the PR template. It exists for a reason.
- **Completeness**: Fill out all relevant sections.
- **Accuracy**: Don't check boxes for tasks you haven't done.
-3
View File
@@ -11,6 +11,3 @@
/.github/workflows/ @google-gemini/gemini-cli-askmode-approvers
/packages/cli/package.json @google-gemini/gemini-cli-askmode-approvers
/packages/core/package.json @google-gemini/gemini-cli-askmode-approvers
# Docs have a dedicated approver group in addition to maintainers
/docs/ @google-gemini/gemini-cli-maintainers @google-gemini/gemini-cli-docs
+4 -1
View File
@@ -1,5 +1,8 @@
name: 'Bug Report'
description: 'Report a bug to help us improve Gemini CLI'
labels:
- 'status/need-triage'
type: 'Bug'
body:
- type: 'markdown'
attributes:
@@ -28,7 +31,7 @@ body:
id: 'info'
attributes:
label: 'Client information'
description: 'Please paste the full text from the `/about` command run from Gemini CLI. Also include which platform (macOS, Windows, Linux). Note that this output contains your email address. Consider removing it before submitting.'
description: 'Please paste the full text from the `/about` command run from Gemini CLI. Also include which platform (macOS, Windows, Linux).'
value: |-
<details>
<summary>Client Information</summary>
+2 -6
View File
@@ -20,9 +20,6 @@ inputs:
github-token:
description: 'The GitHub token for creating the release.'
required: true
github-release-token:
description: 'The GitHub token used specifically for creating the GitHub release (to trigger other workflows).'
required: false
dry-run:
description: 'Whether to run in dry-run mode.'
type: 'string'
@@ -257,7 +254,7 @@ runs:
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/' }}"
env:
GITHUB_TOKEN: '${{ inputs.github-release-token || inputs.github-token }}'
GITHUB_TOKEN: '${{ inputs.github-token }}'
shell: 'bash'
run: |
gh release create "${{ inputs.release-tag }}" \
@@ -265,8 +262,7 @@ runs:
--target "${{ steps.release_branch.outputs.BRANCH_NAME }}" \
--title "Release ${{ inputs.release-tag }}" \
--notes-start-tag "${{ inputs.previous-tag }}" \
--generate-notes \
${{ inputs.npm-tag != 'latest' && '--prerelease' || '' }}
--generate-notes
- name: '🧹 Clean up release branch'
working-directory: '${{ inputs.working-directory }}'
+1 -1
View File
@@ -75,4 +75,4 @@ runs:
gh issue create \
--title "Docker build failed" \
--body "The docker build failed. See the full run for details: ${DETAILS_URL}" \
--label "release-failure"
--label "kind/bug,release-failure"
+1 -9
View File
@@ -77,14 +77,6 @@ runs:
--image google/gemini-cli-sandbox:${{ steps.image_tag.outputs.FINAL_TAG }} \
--output-file final_image_uri.txt
echo "uri=$(cat final_image_uri.txt)" >> $GITHUB_OUTPUT
- name: 'verify'
shell: 'bash'
run: |-
docker run --rm --entrypoint sh "${{ steps.docker_build.outputs.uri }}" -lc '
set -e
node -e "const fs=require(\"node:fs\"); JSON.parse(fs.readFileSync(\"/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json\",\"utf8\")); JSON.parse(fs.readFileSync(\"/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json\",\"utf8\"));"
/usr/local/share/npm-global/bin/gemini --version >/dev/null
'
- name: 'publish'
shell: 'bash'
if: "${{ inputs.dry-run != 'true' }}"
@@ -101,4 +93,4 @@ runs:
gh issue create \
--title "Docker build failed" \
--body "The docker build failed. See the full run for details: ${DETAILS_URL}" \
--label "release-failure"
--label "kind/bug,release-failure"
+20 -18
View File
@@ -1,33 +1,35 @@
# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
day: 'monday'
open-pull-requests-limit: 10
interval: 'daily'
target-branch: 'main'
commit-message:
prefix: 'chore(deps)'
include: 'scope'
reviewers:
- 'joshualitt'
- 'google-gemini/gemini-cli-askmode-approvers'
groups:
npm-dependencies:
patterns:
- '*'
# Group all non-major updates together.
# This is to reduce the number of PRs that need to be reviewed.
# Major updates will still be created as separate PRs.
npm-minor-patch:
applies-to: 'version-updates'
update-types:
- 'minor'
- 'patch'
open-pull-requests-limit: 0
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
day: 'monday'
open-pull-requests-limit: 10
interval: 'daily'
target-branch: 'main'
commit-message:
prefix: 'chore(deps)'
include: 'scope'
reviewers:
- 'joshualitt'
groups:
actions-dependencies:
patterns:
- '*'
update-types:
- 'minor'
- 'patch'
- 'google-gemini/gemini-cli-askmode-approvers'
open-pull-requests-limit: 0
-138
View File
@@ -1,138 +0,0 @@
/* eslint-disable */
/* global require, console, process */
/**
* Script to backfill the 'status/need-triage' label to all open issues
* that are NOT currently labeled with '🔒 maintainer only' or 'help wanted'.
*/
const { execFileSync } = require('child_process');
const isDryRun = process.argv.includes('--dry-run');
const REPO = 'google-gemini/gemini-cli';
/**
* Executes a GitHub CLI command safely using an argument array to prevent command injection.
* @param {string[]} args
* @returns {string|null}
*/
function runGh(args) {
try {
// Using execFileSync with an array of arguments is safe as it doesn't use a shell.
// We set a large maxBuffer (10MB) to handle repositories with many issues.
return execFileSync('gh', args, {
encoding: 'utf8',
maxBuffer: 10 * 1024 * 1024,
stdio: ['ignore', 'pipe', 'pipe'],
}).trim();
} catch (error) {
const stderr = error.stderr ? ` Stderr: ${error.stderr.trim()}` : '';
console.error(
`❌ Error running gh ${args.join(' ')}: ${error.message}${stderr}`,
);
return null;
}
}
async function main() {
console.log('🔐 GitHub CLI security check...');
const authStatus = runGh(['auth', 'status']);
if (authStatus === null) {
console.error('❌ GitHub CLI (gh) is not installed or not authenticated.');
process.exit(1);
}
if (isDryRun) {
console.log('🧪 DRY RUN MODE ENABLED - No changes will be made.\n');
}
console.log(`🔍 Fetching and filtering open issues from ${REPO}...`);
// We use the /issues endpoint with pagination to bypass the 1000-result limit.
// The jq filter ensures we exclude PRs, maintainer-only, help-wanted, and existing status/need-triage.
const jqFilter =
'.[] | select(.pull_request == null) | select([.labels[].name] as $l | (any($l[]; . == "🔒 maintainer only") | not) and (any($l[]; . == "help wanted") | not) and (any($l[]; . == "status/need-triage") | not)) | {number: .number, title: .title}';
const output = runGh([
'api',
`repos/${REPO}/issues?state=open&per_page=100`,
'--paginate',
'--jq',
jqFilter,
]);
if (output === null) {
process.exit(1);
}
const issues = output
.split('\n')
.filter((line) => line.trim())
.map((line) => {
try {
return JSON.parse(line);
} catch (_e) {
console.error(`⚠️ Failed to parse line: ${line}`);
return null;
}
})
.filter(Boolean);
console.log(`✅ Found ${issues.length} issues matching criteria.`);
if (issues.length === 0) {
console.log('✨ No issues need backfilling.');
return;
}
let successCount = 0;
let failCount = 0;
if (isDryRun) {
for (const issue of issues) {
console.log(
`[DRY RUN] Would label issue #${issue.number}: ${issue.title}`,
);
}
successCount = issues.length;
} else {
console.log(`🏷️ Applying labels to ${issues.length} issues...`);
for (const issue of issues) {
const issueNumber = String(issue.number);
console.log(`🏷️ Labeling issue #${issueNumber}: ${issue.title}`);
const result = runGh([
'issue',
'edit',
issueNumber,
'--add-label',
'status/need-triage',
'--repo',
REPO,
]);
if (result !== null) {
successCount++;
} else {
failCount++;
}
}
}
console.log(`\n📊 Summary:`);
console.log(` - Success: ${successCount}`);
console.log(` - Failed: ${failCount}`);
if (failCount > 0) {
console.error(`\n❌ Backfill completed with ${failCount} errors.`);
process.exit(1);
} else {
console.log(`\n🎉 ${isDryRun ? 'Dry run' : 'Backfill'} complete!`);
}
}
main().catch((error) => {
console.error('❌ Unexpected error:', error);
process.exit(1);
});
@@ -1,190 +0,0 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/* eslint-disable */
/* global require, console, process */
/**
* Script to backfill a process change notification comment to all open PRs
* not created by members of the 'gemini-cli-maintainers' team.
*
* Skip PRs that are already associated with an issue.
*/
const { execFileSync } = require('child_process');
const isDryRun = process.argv.includes('--dry-run');
const REPO = 'google-gemini/gemini-cli';
const ORG = 'google-gemini';
const TEAM_SLUG = 'gemini-cli-maintainers';
const DISCUSSION_URL =
'https://github.com/google-gemini/gemini-cli/discussions/16706';
/**
* Executes a GitHub CLI command safely using an argument array.
*/
function runGh(args, options = {}) {
const { silent = false } = options;
try {
return execFileSync('gh', args, {
encoding: 'utf8',
maxBuffer: 10 * 1024 * 1024,
stdio: ['ignore', 'pipe', 'pipe'],
}).trim();
} catch (error) {
if (!silent) {
const stderr = error.stderr ? ` Stderr: ${error.stderr.trim()}` : '';
console.error(
`❌ Error running gh ${args.join(' ')}: ${error.message}${stderr}`,
);
}
return null;
}
}
/**
* Checks if a user is a member of the maintainers team.
*/
const membershipCache = new Map();
function isMaintainer(username) {
if (membershipCache.has(username)) return membershipCache.get(username);
// GitHub returns 404 if user is not a member.
// We use silent: true to avoid logging 404s as errors.
const result = runGh(
['api', `orgs/${ORG}/teams/${TEAM_SLUG}/memberships/${username}`],
{ silent: true },
);
const isMember = result !== null;
membershipCache.set(username, isMember);
return isMember;
}
async function main() {
console.log('🔐 GitHub CLI security check...');
if (runGh(['auth', 'status']) === null) {
console.error('❌ GitHub CLI (gh) is not authenticated.');
process.exit(1);
}
if (isDryRun) {
console.log('🧪 DRY RUN MODE ENABLED\n');
}
console.log(`📥 Fetching open PRs from ${REPO}...`);
// Fetch number, author, and closingIssuesReferences to check if linked to an issue
const prsJson = runGh([
'pr',
'list',
'--repo',
REPO,
'--state',
'open',
'--limit',
'1000',
'--json',
'number,author,closingIssuesReferences',
]);
if (prsJson === null) process.exit(1);
const prs = JSON.parse(prsJson);
console.log(`📊 Found ${prs.length} open PRs. Filtering...`);
let targetPrs = [];
for (const pr of prs) {
const author = pr.author.login;
const issueCount = pr.closingIssuesReferences
? pr.closingIssuesReferences.length
: 0;
if (issueCount > 0) {
// Skip if already linked to an issue
continue;
}
if (!isMaintainer(author)) {
targetPrs.push(pr);
}
}
console.log(
`✅ Found ${targetPrs.length} PRs from non-maintainers without associated issues.`,
);
const commentBody =
"\nHi @{AUTHOR}, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.\n\nWe're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: [Improving Our Contribution Process & Introducing New Guidelines](${DISCUSSION_URL}).\n\nKey Update: Starting **January 26, 2026**, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.\n\nThank you for your understanding and for being a part of our community!\n ".trim();
let successCount = 0;
let skipCount = 0;
let failCount = 0;
for (const pr of targetPrs) {
const prNumber = String(pr.number);
const author = pr.author.login;
// Check if we already commented (idempotency)
// We use silent: true here because view might fail if PR is deleted mid-run
const existingComments = runGh(
[
'pr',
'view',
prNumber,
'--repo',
REPO,
'--json',
'comments',
'--jq',
`.comments[].body | contains("${DISCUSSION_URL}")`,
],
{ silent: true },
);
if (existingComments && existingComments.includes('true')) {
console.log(
`⏭️ PR #${prNumber} already has the notification. Skipping.`,
);
skipCount++;
continue;
}
if (isDryRun) {
console.log(`[DRY RUN] Would notify @${author} on PR #${prNumber}`);
successCount++;
} else {
console.log(`💬 Notifying @${author} on PR #${prNumber}...`);
const personalizedComment = commentBody.replace('{AUTHOR}', author);
const result = runGh([
'pr',
'comment',
prNumber,
'--repo',
REPO,
'--body',
personalizedComment,
]);
if (result !== null) {
successCount++;
} else {
failCount++;
}
}
}
console.log(`\n📊 Summary:`);
console.log(` - Notified: ${successCount}`);
console.log(` - Skipped: ${skipCount}`);
console.log(` - Failed: ${failCount}`);
if (failCount > 0) process.exit(1);
}
main().catch((e) => {
console.error(e);
process.exit(1);
});
+100 -147
View File
@@ -1,180 +1,133 @@
#!/usr/bin/env bash
# @license
# Copyright 2026 Google LLC
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
# Initialize a comma-separated string to hold PR numbers that need a comment
PRS_NEEDING_COMMENT=""
# Global cache for issue labels (compatible with Bash 3.2)
# Stores "|ISSUE_NUM:LABELS|" segments
ISSUE_LABELS_CACHE_FLAT="|"
# Function to get labels from an issue (with caching)
get_issue_labels() {
local ISSUE_NUM="${1}"
if [[ -z "${ISSUE_NUM}" || "${ISSUE_NUM}" == "null" || "${ISSUE_NUM}" == "" ]]; then
return
# Function to process a single PR
process_pr() {
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
echo "‼️ Missing \$GITHUB_REPOSITORY - this must be run from GitHub Actions"
return 1
fi
# Check cache
case "${ISSUE_LABELS_CACHE_FLAT}" in
*"|${ISSUE_NUM}:"*)
local suffix="${ISSUE_LABELS_CACHE_FLAT#*|"${ISSUE_NUM}":}"
echo "${suffix%%|*}"
return
;;
*)
# Cache miss, proceed to fetch
;;
esac
echo " 📥 Fetching labels from issue #${ISSUE_NUM}" >&2
local gh_output
if ! gh_output=$(gh issue view "${ISSUE_NUM}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null); then
echo " ⚠️ Could not fetch issue #${ISSUE_NUM}" >&2
ISSUE_LABELS_CACHE_FLAT="${ISSUE_LABELS_CACHE_FLAT}${ISSUE_NUM}:|"
return
if [[ -z "${GITHUB_OUTPUT:-}" ]]; then
echo "‼️ Missing \$GITHUB_OUTPUT - this must be run from GitHub Actions"
return 1
fi
local labels
labels=$(echo "${gh_output}" | grep -x -E '(area|priority)/.*|help wanted|🔒 maintainer only' | tr '\n' ',' | sed 's/,$//' || echo "")
# Save to flat cache
ISSUE_LABELS_CACHE_FLAT="${ISSUE_LABELS_CACHE_FLAT}${ISSUE_NUM}:${labels}|"
echo "${labels}"
}
# Function to process a single PR with pre-fetched data
process_pr_optimized() {
local PR_NUMBER="${1}"
local IS_DRAFT="${2}"
local ISSUE_NUMBER="${3}"
local CURRENT_LABELS="${4}" # Comma-separated labels
local PR_NUMBER=$1
echo "🔄 Processing PR #${PR_NUMBER}"
local LABELS_TO_ADD=""
local LABELS_TO_REMOVE=""
if [[ -z "${ISSUE_NUMBER}" || "${ISSUE_NUMBER}" == "null" || "${ISSUE_NUMBER}" == "" ]]; then
if [[ "${IS_DRAFT}" == "true" ]]; then
echo " 📝 PR #${PR_NUMBER} is a draft and has no linked issue"
if [[ ",${CURRENT_LABELS}," == *",status/need-issue,"* ]]; then
echo " Removing status/need-issue label"
LABELS_TO_REMOVE="status/need-issue"
fi
else
echo " ⚠️ No linked issue found for PR #${PR_NUMBER}"
if [[ ",${CURRENT_LABELS}," != *",status/need-issue,"* ]]; then
echo " Adding status/need-issue label"
LABELS_TO_ADD="status/need-issue"
fi
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
PRS_NEEDING_COMMENT="${PR_NUMBER}"
else
PRS_NEEDING_COMMENT="${PRS_NEEDING_COMMENT},${PR_NUMBER}"
fi
fi
else
echo " 🔗 Found linked issue #${ISSUE_NUMBER}"
if [[ ",${CURRENT_LABELS}," == *",status/need-issue,"* ]]; then
echo " Removing status/need-issue label"
LABELS_TO_REMOVE="status/need-issue"
fi
local ISSUE_LABELS
ISSUE_LABELS=$(get_issue_labels "${ISSUE_NUMBER}")
if [[ -n "${ISSUE_LABELS}" ]]; then
local IFS_OLD="${IFS}"
IFS=','
for label in ${ISSUE_LABELS}; do
if [[ -n "${label}" ]] && [[ ",${CURRENT_LABELS}," != *",${label},"* ]]; then
if [[ -z "${LABELS_TO_ADD}" ]]; then
LABELS_TO_ADD="${label}"
else
LABELS_TO_ADD="${LABELS_TO_ADD},${label}"
fi
fi
done
IFS="${IFS_OLD}"
fi
if [[ -z "${LABELS_TO_ADD}" && -z "${LABELS_TO_REMOVE}" ]]; then
echo " ✅ Labels already synchronized"
fi
# Get closing issue number with error handling
local ISSUE_NUMBER
if ! ISSUE_NUMBER=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json closingIssuesReferences -q '.closingIssuesReferences.nodes[0].number' 2>/dev/null); then
echo " ⚠️ Could not fetch closing issue for PR #${PR_NUMBER}"
fi
if [[ -n "${LABELS_TO_ADD}" || -n "${LABELS_TO_REMOVE}" ]]; then
local EDIT_CMD=("gh" "pr" "edit" "${PR_NUMBER}" "--repo" "${GITHUB_REPOSITORY}")
if [[ -z "${ISSUE_NUMBER}" ]]; then
echo "⚠️ No linked issue found for PR #${PR_NUMBER}, adding status/need-issue label"
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "status/need-issue" 2>/dev/null; then
echo " ⚠️ Failed to add label (may already exist or have permission issues)"
fi
# Add PR number to the list
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
PRS_NEEDING_COMMENT="${PR_NUMBER}"
else
PRS_NEEDING_COMMENT="${PRS_NEEDING_COMMENT},${PR_NUMBER}"
fi
echo "needs_comment=true" >> "${GITHUB_OUTPUT}"
else
echo "🔗 Found linked issue #${ISSUE_NUMBER}"
# Remove status/need-issue label if present
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --remove-label "status/need-issue" 2>/dev/null; then
echo " status/need-issue label not present or could not be removed"
fi
# Get issue labels
echo "📥 Fetching labels from issue #${ISSUE_NUMBER}"
local ISSUE_LABELS=""
if ! ISSUE_LABELS=$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null | tr '\n' ',' | sed 's/,$//' || echo ""); then
echo " ⚠️ Could not fetch issue #${ISSUE_NUMBER} (may not exist or be in different repo)"
ISSUE_LABELS=""
fi
# Get PR labels
echo "📥 Fetching labels from PR #${PR_NUMBER}"
local PR_LABELS=""
if ! PR_LABELS=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null | tr '\n' ',' | sed 's/,$//' || echo ""); then
echo " ⚠️ Could not fetch PR labels"
PR_LABELS=""
fi
echo " Issue labels: ${ISSUE_LABELS}"
echo " PR labels: ${PR_LABELS}"
# Convert comma-separated strings to arrays
local ISSUE_LABEL_ARRAY PR_LABEL_ARRAY
IFS=',' read -ra ISSUE_LABEL_ARRAY <<< "${ISSUE_LABELS}"
IFS=',' read -ra PR_LABEL_ARRAY <<< "${PR_LABELS}"
# Find labels to add (on issue but not on PR)
local LABELS_TO_ADD=""
for label in "${ISSUE_LABEL_ARRAY[@]}"; do
if [[ -n "${label}" ]] && [[ " ${PR_LABEL_ARRAY[*]} " != *" ${label} "* ]]; then
if [[ -z "${LABELS_TO_ADD}" ]]; then
LABELS_TO_ADD="${label}"
else
LABELS_TO_ADD="${LABELS_TO_ADD},${label}"
fi
fi
done
# Apply label changes
if [[ -n "${LABELS_TO_ADD}" ]]; then
echo " Syncing labels to add: ${LABELS_TO_ADD}"
EDIT_CMD+=("--add-label" "${LABELS_TO_ADD}")
echo " Adding labels: ${LABELS_TO_ADD}"
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "${LABELS_TO_ADD}" 2>/dev/null; then
echo " ⚠️ Failed to add some labels"
fi
fi
if [[ -n "${LABELS_TO_REMOVE}" ]]; then
echo " Syncing labels to remove: ${LABELS_TO_REMOVE}"
EDIT_CMD+=("--remove-label" "${LABELS_TO_REMOVE}")
if [[ -z "${LABELS_TO_ADD}" ]]; then
echo "✅ Labels already synchronized"
fi
("${EDIT_CMD[@]}" || true)
echo "needs_comment=false" >> "${GITHUB_OUTPUT}"
fi
}
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
echo "‼️ Missing \$GITHUB_REPOSITORY - this must be run from GitHub Actions"
exit 1
fi
if [[ -z "${GITHUB_OUTPUT:-}" ]]; then
echo "‼️ Missing \$GITHUB_OUTPUT - this must be run from GitHub Actions"
exit 1
fi
JQ_EXTRACT_FIELDS='{
number: .number,
isDraft: .isDraft,
issue: (.closingIssuesReferences[0].number // (.body // "" | capture("(^|[^a-zA-Z0-9])#(?<num>[0-9]+)([^a-zA-Z0-9]|$)")? | .num) // "null"),
labels: [.labels[].name] | join(",")
}'
JQ_TSV_FORMAT='"\((.number | tostring))\t\(.isDraft)\t\((.issue // null) | tostring)\t\(.labels)"'
# If PR_NUMBER is set, process only that PR
if [[ -n "${PR_NUMBER:-}" ]]; then
echo "🔄 Processing single PR #${PR_NUMBER}"
PR_DATA=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json number,closingIssuesReferences,isDraft,body,labels 2>/dev/null) || {
echo "❌ Failed to fetch data for PR #${PR_NUMBER}"
if ! process_pr "${PR_NUMBER}"; then
echo "❌ Failed to process PR #${PR_NUMBER}"
exit 1
}
line=$(echo "${PR_DATA}" | jq -r "${JQ_EXTRACT_FIELDS} | ${JQ_TSV_FORMAT}")
IFS=$'\t' read -r pr_num is_draft issue_num current_labels <<< "${line}"
process_pr_optimized "${pr_num}" "${is_draft}" "${issue_num}" "${current_labels}"
fi
else
# Otherwise, get all open PRs and process them
# The script logic will determine which ones need issue linking or label sync
echo "📥 Getting all open pull requests..."
PR_DATA_ALL=$(gh pr list --repo "${GITHUB_REPOSITORY}" --state open --limit 1000 --json number,closingIssuesReferences,isDraft,body,labels 2>/dev/null) || {
if ! PR_NUMBERS=$(gh pr list --repo "${GITHUB_REPOSITORY}" --state open --limit 1000 --json number -q '.[].number' 2>/dev/null); then
echo "❌ Failed to fetch PR list"
exit 1
}
fi
PR_COUNT=$(echo "${PR_DATA_ALL}" | jq '. | length')
echo "📊 Found ${PR_COUNT} open PRs to process"
if [[ -z "${PR_NUMBERS}" ]]; then
echo "✅ No open PRs found"
else
# Count the number of PRs
PR_COUNT=$(echo "${PR_NUMBERS}" | wc -w | tr -d ' ')
echo "📊 Found ${PR_COUNT} open PRs to process"
# Use a temporary file to avoid masking exit codes in process substitution
tmp_file=$(mktemp)
echo "${PR_DATA_ALL}" | jq -r ".[] | ${JQ_EXTRACT_FIELDS} | ${JQ_TSV_FORMAT}" > "${tmp_file}"
while read -r line; do
[[ -z "${line}" ]] && continue
IFS=$'\t' read -r pr_num is_draft issue_num current_labels <<< "${line}"
process_pr_optimized "${pr_num}" "${is_draft}" "${issue_num}" "${current_labels}"
done < "${tmp_file}"
rm -f "${tmp_file}"
for pr_number in ${PR_NUMBERS}; do
if ! process_pr "${pr_number}"; then
echo "⚠️ Failed to process PR #${pr_number}, continuing with next PR..."
continue
fi
done
fi
fi
# Ensure output is always set, even if empty
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
echo "prs_needing_comment=[]" >> "${GITHUB_OUTPUT}"
else
-359
View File
@@ -1,359 +0,0 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
const { Octokit } = require('@octokit/rest');
/**
* Sync Maintainer Labels (Recursive with strict parent-child relationship detection)
* - Uses Native Sub-issues.
* - Uses Markdown Task Lists (- [ ] #123).
* - Filters for OPEN issues only.
* - Skips DUPLICATES.
* - Skips Pull Requests.
* - ONLY labels issues in the PUBLIC (gemini-cli) repo.
*/
const REPO_OWNER = 'google-gemini';
const PUBLIC_REPO = 'gemini-cli';
const PRIVATE_REPO = 'maintainers-gemini-cli';
const ALLOWED_REPOS = [PUBLIC_REPO, PRIVATE_REPO];
const ROOT_ISSUES = [
{ owner: REPO_OWNER, repo: PUBLIC_REPO, number: 15374 },
{ owner: REPO_OWNER, repo: PUBLIC_REPO, number: 15456 },
{ owner: REPO_OWNER, repo: PUBLIC_REPO, number: 15324 },
];
const TARGET_LABEL = '🔒 maintainer only';
const isDryRun =
process.argv.includes('--dry-run') || process.env.DRY_RUN === 'true';
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
});
/**
* Extracts child issue references from markdown Task Lists ONLY.
* e.g. - [ ] #123 or - [x] google-gemini/gemini-cli#123
*/
function extractTaskListLinks(text, contextOwner, contextRepo) {
if (!text) return [];
const childIssues = new Map();
const add = (owner, repo, number) => {
if (ALLOWED_REPOS.includes(repo)) {
const key = `${owner}/${repo}#${number}`;
childIssues.set(key, { owner, repo, number: parseInt(number, 10) });
}
};
// 1. Full URLs in task lists
const urlRegex =
/-\s+\[[ x]\].*https:\/\/github\.com\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\/issues\/(\d+)\b/g;
let match;
while ((match = urlRegex.exec(text)) !== null) {
add(match[1], match[2], match[3]);
}
// 2. Cross-repo refs in task lists: owner/repo#123
const crossRepoRegex =
/-\s+\[[ x]\].*([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)#(\d+)\b/g;
while ((match = crossRepoRegex.exec(text)) !== null) {
add(match[1], match[2], match[3]);
}
// 3. Short refs in task lists: #123
const shortRefRegex = /-\s+\[[ x]\].*#(\d+)\b/g;
while ((match = shortRefRegex.exec(text)) !== null) {
add(contextOwner, contextRepo, match[1]);
}
return Array.from(childIssues.values());
}
/**
* Fetches issue data via GraphQL with full pagination for sub-issues, comments, and labels.
*/
async function fetchIssueData(owner, repo, number) {
const query = `
query($owner:String!, $repo:String!, $number:Int!) {
repository(owner:$owner, name:$repo) {
issue(number:$number) {
state
title
body
labels(first: 100) {
nodes { name }
pageInfo { hasNextPage endCursor }
}
subIssues(first: 100) {
nodes {
number
repository {
name
owner { login }
}
}
pageInfo { hasNextPage endCursor }
}
comments(first: 100) {
nodes {
body
}
}
}
}
}
`;
try {
const response = await octokit.graphql(query, { owner, repo, number });
const data = response.repository.issue;
if (!data) return null;
const issue = {
state: data.state,
title: data.title,
body: data.body || '',
labels: data.labels.nodes.map((n) => n.name),
subIssues: [...data.subIssues.nodes],
comments: data.comments.nodes.map((n) => n.body),
};
// Paginate subIssues if there are more than 100
if (data.subIssues.pageInfo.hasNextPage) {
const moreSubIssues = await paginateConnection(
owner,
repo,
number,
'subIssues',
'number repository { name owner { login } }',
data.subIssues.pageInfo.endCursor,
);
issue.subIssues.push(...moreSubIssues);
}
// Paginate labels if there are more than 100 (unlikely but for completeness)
if (data.labels.pageInfo.hasNextPage) {
const moreLabels = await paginateConnection(
owner,
repo,
number,
'labels',
'name',
data.labels.pageInfo.endCursor,
(n) => n.name,
);
issue.labels.push(...moreLabels);
}
// Note: Comments are handled via Task Lists in body + first 100 comments.
// If an issue has > 100 comments with task lists, we'd need to paginate those too.
// Given the 1,100+ issue discovery count, 100 comments is usually sufficient,
// but we can add it for absolute completeness.
// (Skipping for now to avoid excessive API churn unless clearly needed).
return issue;
} catch (error) {
if (error.errors && error.errors.some((e) => e.type === 'NOT_FOUND')) {
return null;
}
throw error;
}
}
/**
* Helper to paginate any GraphQL connection.
*/
async function paginateConnection(
owner,
repo,
number,
connectionName,
nodeFields,
initialCursor,
transformNode = (n) => n,
) {
let additionalNodes = [];
let hasNext = true;
let cursor = initialCursor;
while (hasNext) {
const query = `
query($owner:String!, $repo:String!, $number:Int!, $cursor:String) {
repository(owner:$owner, name:$repo) {
issue(number:$number) {
${connectionName}(first: 100, after: $cursor) {
nodes { ${nodeFields} }
pageInfo { hasNextPage endCursor }
}
}
}
}
`;
const response = await octokit.graphql(query, {
owner,
repo,
number,
cursor,
});
const connection = response.repository.issue[connectionName];
additionalNodes.push(...connection.nodes.map(transformNode));
hasNext = connection.pageInfo.hasNextPage;
cursor = connection.pageInfo.endCursor;
}
return additionalNodes;
}
/**
* Validates if an issue should be processed (Open, not a duplicate, not a PR)
*/
function shouldProcess(issueData) {
if (!issueData) return false;
if (issueData.state !== 'OPEN') return false;
const labels = issueData.labels.map((l) => l.toLowerCase());
if (labels.includes('duplicate') || labels.includes('kind/duplicate')) {
return false;
}
return true;
}
async function getAllDescendants(roots) {
const allDescendants = new Map();
const visited = new Set();
const queue = [...roots];
for (const root of roots) {
visited.add(`${root.owner}/${root.repo}#${root.number}`);
}
console.log(`Starting discovery from ${roots.length} roots...`);
while (queue.length > 0) {
const current = queue.shift();
const currentKey = `${current.owner}/${current.repo}#${current.number}`;
try {
const issueData = await fetchIssueData(
current.owner,
current.repo,
current.number,
);
if (!shouldProcess(issueData)) {
continue;
}
// ONLY add to labeling list if it's in the PUBLIC repository
if (current.repo === PUBLIC_REPO) {
// Don't label the roots themselves
if (
!ROOT_ISSUES.some(
(r) => r.number === current.number && r.repo === current.repo,
)
) {
allDescendants.set(currentKey, {
...current,
title: issueData.title,
labels: issueData.labels,
});
}
}
const children = new Map();
// 1. Process Native Sub-issues
if (issueData.subIssues) {
for (const node of issueData.subIssues) {
const childOwner = node.repository.owner.login;
const childRepo = node.repository.name;
const childNumber = node.number;
const key = `${childOwner}/${childRepo}#${childNumber}`;
children.set(key, {
owner: childOwner,
repo: childRepo,
number: childNumber,
});
}
}
// 2. Process Markdown Task Lists in Body and Comments
let combinedText = issueData.body || '';
if (issueData.comments) {
for (const commentBody of issueData.comments) {
combinedText += '\n' + (commentBody || '');
}
}
const taskListLinks = extractTaskListLinks(
combinedText,
current.owner,
current.repo,
);
for (const link of taskListLinks) {
const key = `${link.owner}/${link.repo}#${link.number}`;
children.set(key, link);
}
// Queue children (regardless of which repo they are in, for recursion)
for (const [key, child] of children) {
if (!visited.has(key)) {
visited.add(key);
queue.push(child);
}
}
} catch (error) {
console.error(`Error processing ${currentKey}: ${error.message}`);
}
}
return Array.from(allDescendants.values());
}
async function run() {
if (isDryRun) {
console.log('=== DRY RUN MODE: No labels will be applied ===');
}
const descendants = await getAllDescendants(ROOT_ISSUES);
console.log(
`\nFound ${descendants.length} total unique open descendant issues in ${PUBLIC_REPO}.`,
);
for (const issueInfo of descendants) {
const issueKey = `${issueInfo.owner}/${issueInfo.repo}#${issueInfo.number}`;
try {
// Data is already available from the discovery phase
const hasLabel = issueInfo.labels.some((l) => l === TARGET_LABEL);
if (!hasLabel) {
if (isDryRun) {
console.log(
`[DRY RUN] Would label ${issueKey}: "${issueInfo.title}"`,
);
} else {
console.log(`Labeling ${issueKey}: "${issueInfo.title}"...`);
await octokit.rest.issues.addLabels({
owner: issueInfo.owner,
repo: issueInfo.repo,
issue_number: issueInfo.number,
labels: [TARGET_LABEL],
});
}
}
} catch (error) {
console.error(`Error processing label for ${issueKey}: ${error.message}`);
}
}
}
run().catch((error) => {
console.error(error);
process.exit(1);
});
+19 -104
View File
@@ -43,15 +43,13 @@ jobs:
- id: 'merge-queue-ci-skipper'
uses: 'cariad-tech/merge-queue-ci-skipper@1032489e59437862c90a08a2c92809c903883772' # ratchet:cariad-tech/merge-queue-ci-skipper@main
with:
secret: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
secret: '${{ secrets.GITHUB_TOKEN }}'
lint:
name: 'Lint'
runs-on: 'gemini-cli-ubuntu-16-core'
needs: 'merge_queue_skipper'
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
env:
GEMINI_LINT_TEMP_DIR: '${{ github.workspace }}/.gemini-linters'
steps:
- name: 'Checkout'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -65,21 +63,9 @@ jobs:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 'Cache Linters'
uses: 'actions/cache@v4'
with:
path: '${{ env.GEMINI_LINT_TEMP_DIR }}'
key: "${{ runner.os }}-${{ runner.arch }}-linters-${{ hashFiles('scripts/lint.js') }}"
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Cache ESLint'
uses: 'actions/cache@v4'
with:
path: '.eslintcache'
key: "${{ runner.os }}-eslint-${{ hashFiles('package-lock.json', 'eslint.config.js') }}"
- name: 'Validate NOTICES.txt'
run: 'git diff --exit-code packages/vscode-ide-companion/NOTICES.txt'
@@ -122,12 +108,13 @@ jobs:
- name: 'Link Checker'
uses: 'lycheeverse/lychee-action@885c65f3dc543b57c898c8099f4e08c8afd178a2' # ratchet: lycheeverse/lychee-action@v2.6.1
with:
args: '--verbose --accept 200,503 ./**/*.md'
args: '--verbose ./**/*.md'
fail: true
test_linux:
name: 'Test (Linux) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
name: 'Test (Linux)'
runs-on: 'gemini-cli-ubuntu-16-core'
needs:
- 'lint'
- 'merge_queue_skipper'
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
permissions:
@@ -140,9 +127,6 @@ jobs:
- '20.x'
- '22.x'
- '24.x'
shard:
- 'cli'
- 'others'
steps:
- name: 'Checkout'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -162,14 +146,7 @@ jobs:
- name: 'Run tests and generate reports'
env:
NO_COLOR: true
run: |
if [[ "${{ matrix.shard }}" == "cli" ]]; then
npm run test:ci --workspace @google/gemini-cli
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
npm run test:scripts
fi
run: 'npm run test:ci'
- name: 'Bundle'
run: 'npm run bundle'
@@ -177,19 +154,6 @@ jobs:
- name: 'Smoke test bundle'
run: 'node ./bundle/gemini.js --version'
- name: 'Smoke test npx installation'
run: |
# 1. Package the project into a tarball
TARBALL=$(npm pack | tail -n 1)
# 2. Move to a fresh directory for isolation
mkdir -p ../smoke-test-dir
mv "$TARBALL" ../smoke-test-dir/
cd ../smoke-test-dir
# 3. Run npx from the tarball
npx "./$TARBALL" --version
- name: 'Wait for file system sync'
run: 'sleep 2'
@@ -198,7 +162,7 @@ jobs:
${{ always() && (github.event.pull_request.head.repo.full_name == github.repository) }}
uses: 'dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3' # ratchet:dorny/test-reporter@v2
with:
name: 'Test Results (Node ${{ runner.os }}, ${{ matrix.node-version }}, ${{ matrix.shard }})'
name: 'Test Results (Node ${{ matrix.node-version }})'
path: 'packages/*/junit.xml'
reporter: 'java-junit'
fail-on-error: 'false'
@@ -208,13 +172,14 @@ jobs:
${{ always() && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'test-results-fork-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
name: 'test-results-fork-${{ matrix.node-version }}-${{ runner.os }}'
path: 'packages/*/junit.xml'
test_mac:
name: 'Test (Mac) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
runs-on: 'macos-latest'
name: 'Test (Mac)'
runs-on: '${{ matrix.os }}'
needs:
- 'lint'
- 'merge_queue_skipper'
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
permissions:
@@ -224,13 +189,12 @@ jobs:
continue-on-error: true
strategy:
matrix:
os:
- 'macos-latest'
node-version:
- '20.x'
- '22.x'
- '24.x'
shard:
- 'cli'
- 'others'
steps:
- name: 'Checkout'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -250,14 +214,7 @@ jobs:
- name: 'Run tests and generate reports'
env:
NO_COLOR: true
run: |
if [[ "${{ matrix.shard }}" == "cli" ]]; then
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
fi
run: 'npm run test:ci -- --coverage.enabled=false'
- name: 'Bundle'
run: 'npm run bundle'
@@ -265,19 +222,6 @@ jobs:
- name: 'Smoke test bundle'
run: 'node ./bundle/gemini.js --version'
- name: 'Smoke test npx installation'
run: |
# 1. Package the project into a tarball
TARBALL=$(npm pack | tail -n 1)
# 2. Move to a fresh directory for isolation
mkdir -p ../smoke-test-dir
mv "$TARBALL" ../smoke-test-dir/
cd ../smoke-test-dir
# 3. Run npx from the tarball
npx "./$TARBALL" --version
- name: 'Wait for file system sync'
run: 'sleep 2'
@@ -286,7 +230,7 @@ jobs:
${{ always() && (github.event.pull_request.head.repo.full_name == github.repository) }}
uses: 'dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3' # ratchet:dorny/test-reporter@v2
with:
name: 'Test Results (Node ${{ runner.os }}, ${{ matrix.node-version }}, ${{ matrix.shard }})'
name: 'Test Results (Node ${{ matrix.node-version }})'
path: 'packages/*/junit.xml'
reporter: 'java-junit'
fail-on-error: 'false'
@@ -296,7 +240,7 @@ jobs:
${{ always() && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'test-results-fork-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
name: 'test-results-fork-${{ matrix.node-version }}-${{ runner.os }}'
path: 'packages/*/junit.xml'
- name: 'Upload coverage reports'
@@ -304,7 +248,7 @@ jobs:
${{ always() }}
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'coverage-reports-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
name: 'coverage-reports-${{ matrix.node-version }}-${{ matrix.os }}'
path: 'packages/*/coverage'
codeql:
@@ -356,16 +300,11 @@ jobs:
clean-script: 'clean'
test_windows:
name: 'Slow Test - Win - ${{ matrix.shard }}'
name: 'Slow Test - Win'
runs-on: 'gemini-cli-windows-16-core'
needs: 'merge_queue_skipper'
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
timeout-minutes: 60
strategy:
matrix:
shard:
- 'cli'
- 'others'
continue-on-error: true
steps:
- name: 'Checkout'
@@ -416,14 +355,7 @@ jobs:
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
UV_THREADPOOL_SIZE: '32'
NODE_ENV: 'test'
run: |
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
}
run: 'npm run test:ci -- --coverage.enabled=false'
shell: 'pwsh'
- name: 'Bundle'
@@ -434,21 +366,6 @@ jobs:
run: 'node ./bundle/gemini.js --version'
shell: 'pwsh'
- name: 'Smoke test npx installation'
run: |
# 1. Package the project into a tarball
$PACK_OUTPUT = npm pack
$TARBALL = $PACK_OUTPUT[-1]
# 2. Move to a fresh directory for isolation
New-Item -ItemType Directory -Force -Path ../smoke-test-dir
Move-Item $TARBALL ../smoke-test-dir/
Set-Location ../smoke-test-dir
# 3. Run npx from the tarball
npx "./$TARBALL" --version
shell: 'pwsh'
ci:
name: 'CI'
if: 'always()'
@@ -457,7 +374,6 @@ jobs:
- 'link_checker'
- 'test_linux'
- 'test_mac'
- 'test_windows'
- 'codeql'
- 'bundle_size'
runs-on: 'gemini-cli-ubuntu-16-core'
@@ -468,7 +384,6 @@ jobs:
(${{ needs.link_checker.result }} != 'success' && ${{ needs.link_checker.result }} != 'skipped') || \
(${{ needs.test_linux.result }} != 'success' && ${{ needs.test_linux.result }} != 'skipped') || \
(${{ needs.test_mac.result }} != 'success' && ${{ needs.test_mac.result }} != 'skipped') || \
(${{ needs.test_windows.result }} != 'success' && ${{ needs.test_windows.result }} != 'skipped') || \
(${{ needs.codeql.result }} != 'success' && ${{ needs.codeql.result }} != 'skipped') || \
(${{ needs.bundle_size.result }} != 'success' && ${{ needs.bundle_size.result }} != 'skipped') ]]; then
echo "One or more CI jobs failed."
+247
View File
@@ -0,0 +1,247 @@
name: 'Testing: E2E'
on:
push:
branches:
- 'main'
# This will run for PRs from the base repository, providing secrets.
pull_request:
branches:
- 'main'
- 'release/**'
# This will run for PRs from forks when a label is added.
pull_request_target:
types: ['labeled']
merge_group:
workflow_dispatch:
inputs:
branch_ref:
description: 'Branch to run on'
required: true
default: 'main'
type: 'string'
concurrency:
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
cancel-in-progress: |-
${{ github.ref != 'refs/heads/main' && !startsWith(github.ref, 'refs/heads/release/') }}
jobs:
merge_queue_skipper:
name: 'Merge Queue Skipper'
runs-on: 'gemini-cli-ubuntu-16-core'
permissions: 'read-all'
outputs:
skip: '${{ steps.merge-queue-e2e-skipper.outputs.skip-check }}'
steps:
- id: 'merge-queue-e2e-skipper'
uses: 'cariad-tech/merge-queue-ci-skipper@1032489e59437862c90a08a2c92809c903883772' # ratchet:cariad-tech/merge-queue-ci-skipper@main
with:
secret: '${{ secrets.GITHUB_TOKEN }}'
continue-on-error: true
e2e_linux:
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
needs: 'merge_queue_skipper'
if: |
(needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip == 'false') &&
(github.event_name == 'push' ||
github.event_name == 'merge_group' ||
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.head.repo.full_name == github.repository) ||
(github.event.label.name == 'maintainer:e2e:ok'))
runs-on: 'gemini-cli-ubuntu-16-core'
strategy:
fail-fast: false
matrix:
sandbox:
- 'sandbox:none'
- 'sandbox:docker'
node-version:
- '20.x'
steps:
- name: 'Checkout (fork)'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
if: "github.event_name == 'pull_request_target'"
with:
ref: '${{ github.event.pull_request.head.sha }}'
repository: '${{ github.event.pull_request.head.repo.full_name }}'
- name: 'Checkout (internal)'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
if: "github.event_name != 'pull_request_target'"
with:
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
- name: 'Set up Node.js ${{ matrix.node-version }}'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
with:
node-version: '${{ matrix.node-version }}'
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Build project'
run: 'npm run build'
- name: 'Set up Docker'
if: "matrix.sandbox == 'sandbox:docker'"
uses: 'docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435' # ratchet:docker/setup-buildx-action@v3
- name: 'Run E2E tests'
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
KEEP_OUTPUT: 'true'
VERBOSE: 'true'
shell: 'bash'
run: |
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then
npm run test:integration:sandbox:docker
else
npm run test:integration:sandbox:none
fi
e2e_mac:
name: 'E2E Test (macOS)'
needs: 'merge_queue_skipper'
if: |
(needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip == 'false') &&
(github.event_name == 'push' ||
github.event_name == 'merge_group' ||
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.head.repo.full_name == github.repository) ||
(github.event.label.name == 'maintainer:e2e:ok'))
runs-on: 'macos-latest'
steps:
- name: 'Checkout (fork)'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
if: "github.event_name == 'pull_request_target'"
with:
ref: '${{ github.event.pull_request.head.sha }}'
repository: '${{ github.event.pull_request.head.repo.full_name }}'
- name: 'Checkout (internal)'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
if: "github.event_name != 'pull_request_target'"
with:
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
- name: 'Set up Node.js 20.x'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
with:
node-version: '20.x'
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Build project'
run: 'npm run build'
- name: 'Fix rollup optional dependencies on macOS'
if: "runner.os == 'macOS'"
run: |
npm cache clean --force
- name: 'Run E2E tests (non-Windows)'
if: "runner.os != 'Windows'"
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
KEEP_OUTPUT: 'true'
SANDBOX: 'sandbox:none'
VERBOSE: 'true'
run: 'npm run test:integration:sandbox:none'
e2e_windows:
name: 'Slow E2E - Win'
needs: 'merge_queue_skipper'
if: |
(needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip == 'false') &&
(github.event_name == 'push' ||
github.event_name == 'merge_group' ||
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.head.repo.full_name == github.repository) ||
(github.event.label.name == 'maintainer:e2e:ok'))
runs-on: 'gemini-cli-windows-16-core'
continue-on-error: true
steps:
- name: 'Checkout (fork)'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
if: "github.event_name == 'pull_request_target'"
with:
ref: '${{ github.event.pull_request.head.sha }}'
repository: '${{ github.event.pull_request.head.repo.full_name }}'
- name: 'Checkout (internal)'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
if: "github.event_name != 'pull_request_target'"
with:
ref: '${{ github.event.inputs.branch_ref || github.ref }}'
- name: 'Set up Node.js 20.x'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: 'Configure Windows Defender exclusions'
run: |
Add-MpPreference -ExclusionPath $env:GITHUB_WORKSPACE -Force
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE\node_modules" -Force
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE\packages" -Force
Add-MpPreference -ExclusionPath "$env:TEMP" -Force
shell: 'pwsh'
- name: 'Configure npm for Windows performance'
run: |
npm config set progress false
npm config set audit false
npm config set fund false
npm config set loglevel error
npm config set maxsockets 32
npm config set registry https://registry.npmjs.org/
shell: 'pwsh'
- name: 'Install dependencies'
run: 'npm ci'
shell: 'pwsh'
- name: 'Build project'
run: 'npm run build'
shell: 'pwsh'
- name: 'Run E2E tests'
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
KEEP_OUTPUT: 'true'
SANDBOX: 'sandbox:none'
VERBOSE: 'true'
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
UV_THREADPOOL_SIZE: '32'
NODE_ENV: 'test'
shell: 'pwsh'
run: 'npm run test:integration:sandbox:none'
e2e:
name: 'E2E'
if: |
always() && (
github.event_name == 'push' ||
github.event_name == 'merge_group' ||
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.head.repo.full_name == github.repository) ||
(github.event.label.name == 'maintainer:e2e:ok')
)
needs:
- 'e2e_linux'
- 'e2e_mac'
runs-on: 'gemini-cli-ubuntu-16-core'
steps:
- name: 'Check E2E test results'
run: |
if [[ (${{ needs.e2e_linux.result }} != 'success' && ${{ needs.e2e_linux.result }} != 'skipped') || \
(${{ needs.e2e_mac.result }} != 'success' && ${{ needs.e2e_mac.result }} != 'skipped') ]]; then
echo "One or more E2E jobs failed."
exit 1
fi
echo "All required E2E jobs passed!"
-102
View File
@@ -1,102 +0,0 @@
name: 'Evals: Nightly'
on:
schedule:
- cron: '0 1 * * *' # Runs at 1 AM every day
workflow_dispatch:
inputs:
run_all:
description: 'Run all evaluations (including usually passing)'
type: 'boolean'
default: true
test_name_pattern:
description: 'Test name pattern or file name'
required: false
type: 'string'
permissions:
contents: 'read'
checks: 'write'
actions: 'read'
jobs:
evals:
name: 'Evals (USUALLY_PASSING) nightly run'
runs-on: 'gemini-cli-ubuntu-16-core'
strategy:
fail-fast: false
matrix:
model:
- 'gemini-3.1-pro-preview-customtools'
- 'gemini-3-pro-preview'
- 'gemini-3-flash-preview'
- 'gemini-2.5-pro'
- 'gemini-2.5-flash'
- 'gemini-2.5-flash-lite'
run_attempt: [1, 2, 3]
steps:
- name: 'Checkout'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
- name: 'Set up Node.js'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Build project'
run: 'npm run build'
- name: 'Create logs directory'
run: 'mkdir -p evals/logs'
- name: 'Run Evals'
continue-on-error: true
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
GEMINI_MODEL: '${{ matrix.model }}'
RUN_EVALS: "${{ github.event.inputs.run_all != 'false' }}"
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
run: |
CMD="npm run test:all_evals"
PATTERN="${{ env.TEST_NAME_PATTERN }}"
if [[ -n "$PATTERN" ]]; then
if [[ "$PATTERN" == *.ts || "$PATTERN" == *.js || "$PATTERN" == */* ]]; then
$CMD -- "$PATTERN"
else
$CMD -- -t "$PATTERN"
fi
else
$CMD
fi
- name: 'Upload Logs'
if: 'always()'
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'eval-logs-${{ matrix.model }}-${{ matrix.run_attempt }}'
path: 'evals/logs'
retention-days: 7
aggregate-results:
name: 'Aggregate Results'
needs: ['evals']
if: 'always()'
runs-on: 'gemini-cli-ubuntu-16-core'
steps:
- name: 'Checkout'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
- name: 'Download Logs'
uses: 'actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806' # ratchet:actions/download-artifact@v4
with:
path: 'artifacts'
- name: 'Generate Summary'
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: 'node scripts/aggregate_evals.js artifacts >> "$GITHUB_STEP_SUMMARY"'
@@ -101,6 +101,7 @@ jobs:
"FIRESTORE_DATABASE_ID": "(default)",
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
},
"enabled": true,
"timeout": 600000
}
},
@@ -14,15 +14,9 @@ on:
description: 'issue number to triage'
required: true
type: 'number'
workflow_call:
inputs:
issue_number:
description: 'issue number to triage'
required: false
type: 'string'
concurrency:
group: '${{ github.workflow }}-${{ github.event.issue.number || github.event.inputs.issue_number || inputs.issue_number }}'
group: '${{ github.workflow }}-${{ github.event.issue.number || github.event.inputs.issue_number }}'
cancel-in-progress: true
defaults:
@@ -40,18 +34,20 @@ permissions:
jobs:
triage-issue:
if: |-
(github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli') &&
github.repository == 'google-gemini/gemini-cli' &&
(
github.event_name == 'workflow_dispatch' ||
(
(github.event_name == 'issues' || github.event_name == 'issue_comment') &&
contains(github.event.issue.labels.*.name, 'status/need-triage') &&
(github.event_name != 'issue_comment' || (
contains(github.event.comment.body, '@gemini-cli /triage') &&
(github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR')
))
)
) &&
!contains(github.event.issue.labels.*.name, 'area/')
!contains(github.event.issue.labels.*.name, 'area/') &&
!contains(github.event.issue.labels.*.name, 'priority/')
timeout-minutes: 5
runs-on: 'ubuntu-latest'
steps:
@@ -63,11 +59,10 @@ jobs:
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
script: |
const issueNumber = ${{ github.event.inputs.issue_number || inputs.issue_number }};
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
issue_number: ${{ github.event.inputs.issue_number }},
});
core.setOutput('title', issue.title);
core.setOutput('body', issue.body);
@@ -78,11 +73,16 @@ jobs:
if: |-
github.event_name == 'workflow_dispatch'
env:
ISSUE_NUMBER_INPUT: '${{ github.event.inputs.issue_number || inputs.issue_number }}'
ISSUE_NUMBER_INPUT: '${{ github.event.inputs.issue_number }}'
LABELS: '${{ steps.get_issue_data.outputs.labels }}'
run: |
if echo "${LABELS}" | grep -q 'area/'; then
echo "Issue #${ISSUE_NUMBER_INPUT} already has 'area/' label. Stopping workflow."
if ! echo "${LABELS}" | grep -q 'status/need-triage'; then
echo "Issue #${ISSUE_NUMBER_INPUT} does not have the 'status/need-triage' label. Stopping workflow."
exit 1
fi
if echo "${LABELS}" | grep -q 'area/' || echo "${LABELS}" | grep -q 'priority/'; then
echo "Issue #${ISSUE_NUMBER_INPUT} already has 'area/' or 'priority/' labels. Stopping workflow."
exit 1
fi
@@ -93,10 +93,6 @@ jobs:
- name: 'Generate GitHub App Token'
id: 'generate_token'
env:
APP_ID: '${{ secrets.APP_ID }}'
if: |-
${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
with:
app-id: '${{ secrets.APP_ID }}'
@@ -107,13 +103,18 @@ jobs:
id: 'get_labels'
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with:
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
github-token: '${{ steps.generate_token.outputs.token }}'
script: |-
const { data: labels } = await github.rest.issues.listLabelsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
});
const allowedLabels = [
'priority/p0',
'priority/p1',
'priority/p2',
'priority/p3',
'priority/unknown',
'area/agent',
'area/enterprise',
'area/non-interactive',
@@ -138,7 +139,7 @@ jobs:
ISSUE_BODY: >-
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.body || github.event.issue.body }}
ISSUE_NUMBER: >-
${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.issue_number || inputs.issue_number) || github.event.issue.number }}
${{ github.event_name == 'workflow_dispatch' && github.event.inputs.issue_number || github.event.issue.number }}
REPOSITORY: '${{ github.repository }}'
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
with:
@@ -155,27 +156,26 @@ jobs:
"telemetry": {
"enabled": true,
"target": "gcp"
},
"coreTools": [
"run_shell_command(echo)"
],
}
}
prompt: |-
## Role
You are an issue triage assistant. Your role is to analyze a GitHub issue and determine the single most appropriate area/ label based on the definitions provided.
You are an issue triage assistant. Your role is to analyze a GitHub issue and determine the single most appropriate area/ label and the single most appropriate priority/ label based on the definitions provided.
## Steps
1. Review the issue title and body: ${{ env.ISSUE_TITLE }} and ${{ env.ISSUE_BODY }}.
2. Review the available labels: ${{ env.AVAILABLE_LABELS }}.
3. Select exactly one area/ label that best matches the issue based on Reference 1: Area Definitions.
4. Fallback Logic:
4. Select exactly one priority/ label that best matches the issue based on Reference 2: Priority Definitions.
5. Fallback Logic:
- If you cannot confidently determine the correct area/ label from the definitions, you must use area/unknown.
5. Output your selected label in JSON format and nothing else. Example:
{"labels_to_set": ["area/core"]}
- If you cannot confidently determine the correct priority/ label from the definitions, you must use priority/unknown.
6. Output your two selected labels in JSON format and nothing else. Example:
{"labels_to_set": ["area/core", "priority/p1"]}
## Guidelines
- Your output must contain exactly one area/ label.
- Your output must contain exactly one area/ label and exactly one priority/ label.
- Triage only the current issue based on its title and body.
- Output only valid JSON format.
- Do not include any explanation or additional text, just the JSON.
@@ -258,6 +258,38 @@ jobs:
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.
Reference 2: Priority Definitions
priority/p0: Critical / Blocker
- Definition: A catastrophic failure that makes the CLI unusable for most users or poses a severe security risk. This includes installation failures, authentication failures, persistent crashes, or critical security vulnerabilities.
- Key Questions:
- Is the CLI failing to install or run?
- Does it fail to authenticate or connect to the Gemini API, making all commands useless?
- Is it consistently crashing on basic, common commands?
- Does this represent a critical security vulnerability?
priority/p1: High
- Definition: A severe issue where a core feature (e.g., text generation, code generation, file processing) is unusable, failing, has severe performance degradation, or providing fundamentally incorrect output formatting (e.g., truncated text, broken JSON). Affects many users, and there is no reasonable workaround.
- Key Questions:
- Is a core feature failing for a specific, large user group (e.g., all Windows users, all users of a specific shell)?
- Is the CLI failing to process a supported input or misinterpreting critical flags?
- Is the CLI's output formatting consistently broken, making the response unusable?
- Is a core command or feature extremely slow, making it impractical to use?
priority/p2: Medium
- Definition: A moderately impactful issue causing inconvenience or a non-optimal experience, but a reasonable workaround exists. This also includes failures in non-core features.
- Key Questions:
- Is a command or flag behaving incorrectly, but the user can achieve their goal via other means?
- Is there a significant, non-blocking UI/UX problem in the terminal (e.g., broken progress indicators, bad terminal coloring)?
priority/p3: Low
- Definition: A minor, low-impact issue with minimal effect on functionality. This includes most cosmetic defects, typos in documentation, or unclear help text.
- Key Questions:
- Is this a typo in the README.md, gemini --help text, or other documentation?
- Is this a minor cosmetic issue (e.g., text alignment in output, an extra newline) that doesn't affect usability?
priority/unknown
- Description: Issues that do not clearly fit into any other defined priority/ category, or where information is too limited to make a determination. Use this when no other priority is appropriate.
- name: 'Apply Labels to Issue'
if: |-
${{ steps.gemini_issue_analysis.outputs.summary != '' }}
@@ -267,7 +299,7 @@ jobs:
LABELS_OUTPUT: '${{ steps.gemini_issue_analysis.outputs.summary }}'
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with:
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
github-token: '${{ steps.generate_token.outputs.token }}'
script: |
const rawOutput = process.env.LABELS_OUTPUT;
core.info(`Raw output from model: ${rawOutput}`);
@@ -287,29 +319,16 @@ jobs:
return;
}
} else {
// If no markdown block, try to find a raw JSON object in the output.
// The CLI may include debug/log lines (e.g. telemetry init, YOLO mode)
// before the actual JSON response.
const jsonObjectMatch = rawOutput.match(/(\{[\s\S]*"labels_to_set"[\s\S]*\})/);
if (jsonObjectMatch) {
try {
parsedLabels = JSON.parse(jsonObjectMatch[0]);
} catch (extractError) {
core.setFailed(`Found JSON-like content but failed to parse: ${extractError.message}\nRaw output: ${rawOutput}`);
return;
}
} else {
core.setFailed(`Output is not valid JSON and does not contain extractable JSON.\nRaw output: ${rawOutput}`);
return;
}
core.setFailed(`Output is not valid JSON and does not contain a JSON markdown block.\nRaw output: ${rawOutput}`);
return;
}
}
const issueNumber = parseInt(process.env.ISSUE_NUMBER);
const labelsToAdd = parsedLabels.labels_to_set || [];
if (labelsToAdd.length !== 1) {
core.setFailed(`Expected exactly 1 label (area/), but got ${labelsToAdd.length}. Labels: ${labelsToAdd.join(', ')}`);
if (labelsToAdd.length !== 2) {
core.setFailed(`Expected exactly 2 labels (one area/ and one priority/), but got ${labelsToAdd.length}. Labels: ${labelsToAdd.join(', ')}`);
return;
}
@@ -322,6 +341,22 @@ jobs:
});
core.info(`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}`);
// Remove the 'status/need-triage' label
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
name: 'status/need-triage'
});
core.info(`Successfully removed 'status/need-triage' label.`);
} catch (error) {
// If the label doesn't exist, the API call will throw a 404. We can ignore this.
if (error.status !== 404) {
core.warning(`Failed to remove 'status/need-triage': ${error.message}`);
}
}
- name: 'Post Issue Analysis Failure Comment'
if: |-
${{ failure() && steps.gemini_issue_analysis.outcome == 'failure' }}
@@ -330,7 +365,7 @@ jobs:
RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with:
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
github-token: '${{ steps.generate_token.outputs.token }}'
script: |-
github.rest.issues.createComment({
owner: context.repo.owner,
@@ -81,6 +81,7 @@ jobs:
"FIRESTORE_DATABASE_ID": "(default)",
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
},
"enabled": true,
"timeout": 600000
}
},
@@ -1,16 +1,12 @@
name: '📋 Gemini Scheduled Issue Triage'
on:
issues:
types:
- 'opened'
- 'reopened'
schedule:
- cron: '0 * * * *' # Runs every hour
workflow_dispatch:
concurrency:
group: '${{ github.workflow }}-${{ github.event.number || github.run_id }}'
group: '${{ github.workflow }}'
cancel-in-progress: true
defaults:
@@ -39,21 +35,7 @@ jobs:
private-key: '${{ secrets.PRIVATE_KEY }}'
permission-issues: 'write'
- name: 'Get issue from event'
if: |-
${{ github.event_name == 'issues' }}
id: 'get_issue_from_event'
env:
ISSUE_EVENT: '${{ toJSON(github.event.issue) }}'
run: |
set -euo pipefail
ISSUE_JSON=$(echo "$ISSUE_EVENT" | jq -c '[{number: .number, title: .title, body: .body}]')
echo "issues_to_triage=${ISSUE_JSON}" >> "${GITHUB_OUTPUT}"
echo "✅ Found issue #${{ github.event.issue.number }} from event to triage! 🎯"
- name: 'Find untriaged issues'
if: |-
${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
id: 'find_issues'
env:
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}'
@@ -61,26 +43,22 @@ jobs:
run: |-
set -euo pipefail
echo '🔍 Finding issues missing area labels...'
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/unknown' --limit 100 --json number,title,body)"
echo '🔍 Finding issues without labels...'
NO_LABEL_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
--search 'is:open is:issue no:label' --json number,title,body)"
echo '🔍 Finding issues missing kind labels...'
NO_KIND_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
--search 'is:open is:issue -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 100 --json number,title,body)"
echo '🏷️ Finding issues missing priority labels...'
NO_PRIORITY_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
--search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 100 --json number,title,body)"
echo '🏷️ Finding issues that need triage...'
NEED_TRIAGE_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
--search "is:open is:issue label:\"status/need-triage\"" --limit 1000 --json number,title,body)"
echo '🔄 Merging and deduplicating issues...'
ISSUES="$(echo "${NO_AREA_ISSUES}" "${NO_KIND_ISSUES}" "${NO_PRIORITY_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
ISSUES="$(echo "${NO_LABEL_ISSUES}" "${NEED_TRIAGE_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
echo '📝 Setting output for GitHub Actions...'
echo "issues_to_triage=${ISSUES}" >> "${GITHUB_OUTPUT}"
ISSUE_COUNT="$(echo "${ISSUES}" | jq 'length')"
echo "✅ Found ${ISSUE_COUNT} unique issues to triage! 🎯"
echo "✅ Found ${ISSUE_COUNT} issues to triage! 🎯"
- name: 'Get Repository Labels'
id: 'get_labels'
@@ -99,13 +77,12 @@ jobs:
- name: 'Run Gemini Issue Analysis'
if: |-
(steps.get_issue_from_event.outputs.issues_to_triage != '' && steps.get_issue_from_event.outputs.issues_to_triage != '[]') ||
(steps.find_issues.outputs.issues_to_triage != '' && steps.find_issues.outputs.issues_to_triage != '[]')
${{ steps.find_issues.outputs.issues_to_triage != '[]' }}
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0
id: 'gemini_issue_analysis'
env:
GITHUB_TOKEN: '' # Do not pass any auth token here since this runs on untrusted inputs
ISSUES_TO_TRIAGE: '${{ steps.get_issue_from_event.outputs.issues_to_triage || steps.find_issues.outputs.issues_to_triage }}'
ISSUES_TO_TRIAGE: '${{ steps.find_issues.outputs.issues_to_triage }}'
REPOSITORY: '${{ github.repository }}'
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
with:
@@ -139,32 +116,38 @@ jobs:
1. You are only able to use the echo command. Review the available labels in the environment variable: "${AVAILABLE_LABELS}".
2. Check environment variable for issues to triage: $ISSUES_TO_TRIAGE (JSON array of issues)
3. Review the issue title, body and any comments provided in the environment variables.
4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/* and priority/*.
5. Label Policy:
- If the issue already has a kind/ label, do not change it.
- If the issue already has a priority/ label, do not change it.
- If the issue already has an area/ label, do not change it.
- If any of these are missing, select exactly ONE appropriate label for the missing category.
4. Identify the most relevant labels from the existing labels, focusing on kind/*, area/*, sub-area/* and priority/*.
5. If the issue already has area/ label, dont try to change it. Similarly, if the issue already has a kind/ label don't change it. And if the issue already has a priority/ label do not change it for example:
If an issue has area/core and kind/bug you will only add a priority/ label.
Instead if an issue has no labels, you will could add one lable of each kind.
6. Identify other applicable labels based on the issue content, such as status/*, help wanted, good first issue, etc.
7. Give me a single short explanation about why you are selecting each label in the process.
8. Output a JSON array of objects, each containing the issue number
7. For area/* and kind/* limit yourself to only the single most applicable label in each case.
8. Give me a single short explanation about why you are selecting each label in the process.
9. Output a JSON array of objects, each containing the issue number
and the labels to add and remove, along with an explanation. For example:
```
[
{
"issue_number": 123,
"labels_to_add": ["area/core", "kind/bug", "priority/p2"],
"labels_to_add": ["kind/bug", "priority/p2"],
"labels_to_remove": ["status/need-triage"],
"explanation": "This issue is a UI bug that needs to be addressed with medium priority."
"explanation": "This issue is a bug that needs to be addressed with medium priority."
},
{
"issue_number": 456,
"labels_to_add": ["kind/enhancement"],
"labels_to_remove": [],
"explanation": "This issue is an enhancement request that could improve the user experience."
}
]
```
If an issue cannot be classified, do not include it in the output array.
9. For each issue please check if CLI version is present, this is usually in the output of the /about command and will look like 0.1.5
10. For each issue please check if CLI version is present, this is usually in the output of the /about command and will look like 0.1.5
- Anything more than 6 versions older than the most recent should add the status/need-retesting label
10. If you see that the issue doesn't look like it has sufficient information recommend the status/need-information label and leave a comment politely requesting the relevant information, eg.. if repro steps are missing request for repro steps. if version information is missing request for version information into the explanation section below.
11. If you think an issue might be a Priority/P0 do not apply the priority/p0 label. Instead apply a status/manual-triage label and include a note in your explanation.
12. If you are uncertain about a category, use the area/unknown, kind/question, or priority/unknown labels as appropriate. If you are extremely uncertain, apply the status/manual-triage label.
11. If you see that the issue doesn't look like it has sufficient information recommend the status/need-information label and leave a comment politely requesting the relevant information, eg.. if repro steps are missing request for repro steps. if version information is missing request for version information into the explanation section below.
- After identifying appropriate labels to an issue, add "status/need-triage" label to labels_to_remove in the output.
12. If you think an issue might be a Priority/P0 do not apply the priority/p0 label. Instead apply a status/manual-triage label and include a note in your explanation.
13. If you are uncertain and have not been able to apply one each of kind/, area/ and priority/ , apply the status/manual-triage label.
## Guidelines
@@ -174,46 +157,100 @@ jobs:
- Do not add comments or modify the issue content.
- Do not remove the following labels maintainer, help wanted or good first issue.
- Triage only the current issue.
- Identify only one area/ label.
- Identify only one area/ label
- Identify only one kind/ label (Do not apply kind/duplicate or kind/parent-issue)
- Identify only one priority/ label.
- Identify all applicable sub-area/* and priority/* labels based on the issue content. It's ok to have multiple of these.
- Once you categorize the issue if it needs information bump down the priority by 1 eg.. a p0 would become a p1 a p1 would become a p2. P2 and P3 can stay as is in this scenario.
Categorization Guidelines (Priority):
P0 - Urgent Blocking Issues:
- DO NOT APPLY THIS LABEL AUTOMATICALLY. Use status/manual-triage instead.
- Definition: Urgent, block a significant percentage of the user base, and prevent frequent use of the Gemini CLI.
- This includes core stability blockers (e.g., authentication failures, broken upgrades), critical crashes, and P0 security vulnerabilities.
- Impact: Blocks development or testing for the entire team; Major security vulnerability; Causes data loss or corruption with no workaround; Crashes the application or makes a core feature completely unusable for all or most users.
- Qualifier: Is the main function of the software broken?
P1 - High-Impact Issues:
- Definition: Affect a large number of users, blocking them from using parts of the Gemini CLI, or make the CLI frequently unusable even with workarounds available.
- Impact: A core feature is broken or behaving incorrectly for a large number of users or use cases; Severe performance degradation; No straightforward workaround exists.
- Qualifier: Is a key feature unusable or giving very wrong results?
P2 - Significant Issues:
- Definition: Affect some users significantly, such as preventing the use of certain features or authentication types.
- Can also be issues that many users complain about, causing annoyance or hindering daily use.
- Impact: Affects a non-critical feature or a smaller, specific subset of users; An inconvenient but functional workaround is available; Noticeable UI/UX problems that look unprofessional.
- Qualifier: Is it an annoying but non-blocking problem?
P3 - Low-Impact Issues:
- Definition: Typically usability issues that cause annoyance to a limited user base.
- Includes feature requests that could be addressed in the near future and may be suitable for community contributions.
- Impact: Minor cosmetic issues; An edge-case bug that is very difficult to reproduce and affects a tiny fraction of users.
- Qualifier: Is it a "nice-to-fix" issue?
Categorization Guidelines (Area):
area/agent: Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality
area/core: User Interface, OS Support, Core Functionality
area/enterprise: Telemetry, Policy, Quota / Licensing
area/extensions: Gemini CLI extensions capability
area/non-interactive: GitHub Actions, SDK, 3P Integrations, Shell Scripting, Command line automation
area/platform: Build infra, Release mgmt, Testing, Eval infra, Capacity, Quota mgmt
area/security: security related issues
Categorization Guidelines:
P0: Critical / Blocker
- A P0 bug is a catastrophic failure that demands immediate attention.
- To be a P0 it means almost all users are running into this issue and it is blocking users from being able to use the product.
- You would see this in the form of many comments from different developers on the bug.
- It represents a complete showstopper for a significant portion of users or for the development process itself.
Impact:
- Blocks development or testing for the entire team.
- Major security vulnerability that could compromise user data or system integrity.
- Causes data loss or corruption with no workaround.
- Crashes the application or makes a core feature completely unusable for all or most users in a production environment. Will it cause severe quality degration?
- Is it preventing contributors from contributing to the repository or is it a release blocker?
Qualifier: Is the main function of the software broken?
Example: The gemini auth login command fails with an unrecoverable error, preventing any user from authenticating and using the rest of the CLI.
P1: High
- A P1 bug is a serious issue that significantly degrades the user experience or impacts a core feature.
- While not a complete blocker, it's a major problem that needs a fast resolution. Feature requests are almost never P1.
- Once again this would be affecting many users.
- You would see this in the form of comments from different developers on the bug.
Impact:
- A core feature is broken or behaving incorrectly for a large number of users or large number of use cases.
- Review the bug details and comments to try figure out if this issue affects a large set of use cases or if it's a narrow set of use cases.
- Severe performance degradation making the application frustratingly slow.
- No straightforward workaround exists, or the workaround is difficult and non-obvious.
Qualifier: Is a key feature unusable or giving very wrong results?
Example: Gemini CLI enters a loop when making read-many-files tool call. I am unable to break out of the loop and gemini doesn't follow instructions subsequently.
P2: Medium
- A P2 bug is a moderately impactful issue. It's a noticeable problem but doesn't prevent the use of the software's main functionality.
Impact:
- Affects a non-critical feature or a smaller, specific subset of users.
- An inconvenient but functional workaround is available and easy to execute.
- Noticeable UI/UX problems that don't break functionality but look unprofessional (e.g., elements are misaligned or overlapping).
Qualifier: Is it an annoying but non-blocking problem?
Example: An error message is unclear or contains a typo, causing user confusion but not halting their workflow.
P3: Low
- A P3 bug is a minor, low-impact issue that is trivial or cosmetic. It has little to no effect on the overall functionality of the application.
Impact:
- Minor cosmetic issues like color inconsistencies, typos in documentation, or slight alignment problems on a non-critical page.
- An edge-case bug that is very difficult to reproduce and affects a tiny fraction of users.
Qualifier: Is it a "nice-to-fix" issue?
Example: Spelling mistakes etc.
Additional Context:
- If users are talking about issues where the model gets downgraded from pro to flash then i want you to categorize that as a performance issue.
- This product is designed to use different models eg.. using pro, downgrading to flash etc.
- When users report that they dont expect the model to change those would be categorized as feature requests.
- If users are talking about issues where the model gets downgraded from pro to flash then i want you to categorize that as a performance issue
- This product is designed to use different models eg.. using pro, downgrading to flash etc.
- When users report that they dont expect the model to change those would be categorized as feature requests.
Definition of Areas
area/ux:
- Issues concerning user-facing elements like command usability, interactive features, help docs, and perceived performance.
- I am seeing my screen flicker when using Gemini CLI
- I am seeing the output malformed
- Theme changes aren't taking effect
- My keyboard inputs arent' being recognzied
area/platform:
- Issues related to installation, packaging, OS compatibility (Windows, macOS, Linux), and the underlying CLI framework.
area/background: Issues related to long-running background tasks, daemons, and autonomous or proactive agent features.
area/models:
- i am not getting a response that is reasonable or expected. this can include things like
- I am calling a tool and the tool is not performing as expected.
- i am expecting a tool to be called and it is not getting called ,
- Including experience when using
- built-in tools (e.g., web search, code interpreter, read file, writefile, etc..),
- Function calling issues should be under this area
- i am getting responses from the model that are malformed.
- Issues concerning Gemini quality of response and inference,
- Issues talking about unnecessary token consumption.
- Issues talking about Model getting stuck in a loop be watchful as this could be the root cause for issues that otherwise seem like model performance issues.
- Memory compression
- unexpected responses,
- poor quality of generated code
area/tools:
- These are primarily issues related to Model Context Protocol
- These are issues that mention MCP support
- feature requests asking for support for new tools.
area/core:
- Issues with fundamental components like command parsing, configuration management, session state, and the main API client logic. Introducing multi-modality
area/contribution:
- Issues related to improving the developer contribution experience, such as CI/CD pipelines, build scripts, and test automation infrastructure.
area/authentication:
- Issues related to user identity, login flows, API key handling, credential storage, and access token management, unable to sign in selecting wrong authentication path etc..
area/security-privacy:
- Issues concerning vulnerability patching, dependency security, data sanitization, privacy controls, and preventing unauthorized data access.
area/extensibility:
- Issues related to the plugin system, extension APIs, or making the CLI's functionality available in other applications, github actions, ide support etc..
area/performance:
- Issues focused on model performance
- Issues with running out of capacity,
- 429 errors etc..
- could also pertain to latency,
- other general software performance like, memory usage, CPU consumption, and algorithmic efficiency.
- Switching models from one to the other unexpectedly.
- name: 'Apply Labels to Issues'
if: |-
@@ -263,6 +300,24 @@ jobs:
core.info(`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}${explanation}`);
}
if (entry.labels_to_remove && entry.labels_to_remove.length > 0) {
for (const label of entry.labels_to_remove) {
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
name: label
});
} catch (error) {
if (error.status !== 404) {
throw error;
}
}
}
core.info(`Successfully removed labels for #${issueNumber}: ${entry.labels_to_remove.join(', ')}`);
}
if (entry.explanation) {
await github.rest.issues.createComment({
owner: context.repo.owner,
@@ -39,7 +39,3 @@ jobs:
GITHUB_REPOSITORY: '${{ github.repository }}'
run: |-
./.github/scripts/pr-triage.sh
# If prs_needing_comment is empty, set it to [] explicitly for downstream steps
if [[ -z "$(grep 'prs_needing_comment' "${GITHUB_OUTPUT}" | cut -d'=' -f2-)" ]]; then
echo "prs_needing_comment=[]" >> "${GITHUB_OUTPUT}"
fi
@@ -1,158 +0,0 @@
name: '🔒 Gemini Scheduled Stale Issue Closer'
on:
schedule:
- cron: '0 0 * * 0' # Every Sunday at midnight UTC
workflow_dispatch:
inputs:
dry_run:
description: 'Run in dry-run mode (no changes applied)'
required: false
default: false
type: 'boolean'
concurrency:
group: '${{ github.workflow }}'
cancel-in-progress: true
defaults:
run:
shell: 'bash'
jobs:
close-stale-issues:
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 }}'
permission-issues: 'write'
- name: 'Process Stale Issues'
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 batchLabel = 'Stale';
const threeMonthsAgo = new Date();
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
const tenDaysAgo = new Date();
tenDaysAgo.setDate(tenDaysAgo.getDate() - 10);
core.info(`Cutoff date for creation: ${threeMonthsAgo.toISOString()}`);
core.info(`Cutoff date for updates: ${tenDaysAgo.toISOString()}`);
const query = `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open created:<${threeMonthsAgo.toISOString()}`;
core.info(`Searching with query: ${query}`);
const itemsToCheck = await github.paginate(github.rest.search.issuesAndPullRequests, {
q: query,
sort: 'created',
order: 'asc',
per_page: 100
});
core.info(`Found ${itemsToCheck.length} open issues to check.`);
let processedCount = 0;
for (const issue of itemsToCheck) {
const createdAt = new Date(issue.created_at);
const updatedAt = new Date(issue.updated_at);
const reactionCount = issue.reactions.total_count;
// Basic thresholds
if (reactionCount >= 5) {
continue;
}
// Skip if it has a maintainer, help wanted, or Public Roadmap label
const rawLabels = issue.labels.map((l) => l.name);
const lowercaseLabels = rawLabels.map((l) => l.toLowerCase());
if (
lowercaseLabels.some((l) => l.includes('maintainer')) ||
lowercaseLabels.includes('help wanted') ||
rawLabels.includes('🗓️ Public Roadmap')
) {
continue;
}
let isStale = updatedAt < tenDaysAgo;
// If apparently active, check if it's only bot activity
if (!isStale) {
try {
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
per_page: 100,
sort: 'created',
direction: 'desc'
});
const lastHumanComment = comments.data.find(comment => comment.user.type !== 'Bot');
if (lastHumanComment) {
isStale = new Date(lastHumanComment.created_at) < tenDaysAgo;
} else {
// No human comments. Check if creator is human.
if (issue.user.type !== 'Bot') {
isStale = createdAt < tenDaysAgo;
} else {
isStale = true; // Bot created, only bot comments
}
}
} catch (error) {
core.warning(`Failed to fetch comments for issue #${issue.number}: ${error.message}`);
continue;
}
}
if (isStale) {
processedCount++;
const message = `Closing stale issue #${issue.number}: "${issue.title}" (${issue.html_url})`;
core.info(message);
if (!dryRun) {
// Add label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: [batchLabel]
});
// Add comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: 'Hello! As part of our effort to keep our backlog manageable and focus on the most active issues, we are tidying up older reports.\n\nIt looks like this issue hasn\'t been active for a while, so we are closing it for now. However, if you are still experiencing this bug on the latest stable build, please feel free to comment on this issue or create a new one with updated details.\n\nThank you for your contribution!'
});
// Close issue
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: 'closed',
state_reason: 'not_planned'
});
}
}
}
core.info(`\nTotal issues processed: ${processedCount}`);
@@ -1,254 +0,0 @@
name: 'Gemini Scheduled Stale PR Closer'
on:
schedule:
- cron: '0 2 * * *' # Every day at 2 AM UTC
pull_request:
types: ['opened', 'edited']
workflow_dispatch:
inputs:
dry_run:
description: 'Run in dry-run mode'
required: false
default: false
type: 'boolean'
jobs:
close-stale-prs:
if: "github.repository == 'google-gemini/gemini-cli'"
runs-on: 'ubuntu-latest'
permissions:
pull-requests: 'write'
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: 'Process Stale PRs'
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';
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
// 1. Fetch maintainers for verification
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: context.repo.owner,
team_slug: team_slug
});
for (const m of members) maintainerLogins.add(m.login.toLowerCase());
core.info(`Successfully fetched ${members.length} team members from ${team_slug}`);
} catch (e) {
core.warning(`Failed to fetch team members from ${team_slug}: ${e.message}`);
}
}
const isGooglerCache = new Map();
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 isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc);
if (isTeamMember || isRepoMaintainer) return true;
return await isGoogler(login);
};
// 2. Determine which PRs to check
let prs = [];
if (context.eventName === 'pull_request') {
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
});
prs = [pr];
} else {
prs = await github.paginate(github.rest.pulls.list, {
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
per_page: 100
});
}
for (const pr of prs) {
const maintainerPr = await isMaintainer(pr.user.login, pr.author_association);
const isBot = pr.user.type === 'Bot' || pr.user.login.endsWith('[bot]');
// Detection Logic for Linked Issues
// Check 1: Official GitHub "Closing Issue" link (GraphQL)
const linkedIssueQuery = `query($owner:String!, $repo:String!, $number:Int!) {
repository(owner:$owner, name:$repo) {
pullRequest(number:$number) {
closingIssuesReferences(first: 1) { totalCount }
}
}
}`;
let hasClosingLink = false;
try {
const res = await github.graphql(linkedIssueQuery, {
owner: context.repo.owner, repo: context.repo.repo, number: pr.number
});
hasClosingLink = res.repository.pullRequest.closingIssuesReferences.totalCount > 0;
} catch (e) {}
// Check 2: Regex for mentions (e.g., "Related to #123", "Part of #123", "#123")
// We check for # followed by numbers or direct URLs to issues.
const body = pr.body || '';
const mentionRegex = /(?:#|https:\/\/github\.com\/[^\/]+\/[^\/]+\/issues\/)(\d+)/i;
const hasMentionLink = mentionRegex.test(body);
const hasLinkedIssue = hasClosingLink || hasMentionLink;
// Logic for Closed PRs (Auto-Reopen)
if (pr.state === 'closed' && context.eventName === 'pull_request' && context.payload.action === 'edited') {
if (hasLinkedIssue) {
core.info(`PR #${pr.number} now has a linked issue. Reopening.`);
if (!dryRun) {
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
state: 'open'
});
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: "Thank you for linking an issue! This pull request has been automatically reopened."
});
}
}
continue;
}
// Logic for Open PRs (Immediate Closure)
if (pr.state === 'open' && !maintainerPr && !hasLinkedIssue && !isBot) {
core.info(`PR #${pr.number} is missing a linked issue. Closing.`);
if (!dryRun) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: "Hi there! Thank you for your contribution to Gemini CLI. \n\nTo improve our contribution process and better track changes, we now require all pull requests to be associated with an existing issue, as announced in our [recent discussion](https://github.com/google-gemini/gemini-cli/discussions/16706) and as detailed in our [CONTRIBUTING.md](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md#1-link-to-an-existing-issue).\n\nThis pull request is being closed because it is not currently linked to an issue. **Once you have updated the description of this PR to link an issue (e.g., by adding `Fixes #123` or `Related to #123`), it will be automatically reopened.**\n\n**How to link an issue:**\nAdd a keyword followed by the issue number (e.g., `Fixes #123`) in the description of your pull request. For more details on supported keywords and how linking works, please refer to the [GitHub Documentation on linking pull requests to issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).\n\nThank you for your understanding and for being a part of our community!"
});
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
state: 'closed'
});
}
continue;
}
// Staleness check (Scheduled runs only)
if (pr.state === 'open' && context.eventName !== 'pull_request') {
const labels = pr.labels.map(l => l.name.toLowerCase());
if (labels.includes('help wanted') || labels.includes('🔒 maintainer only')) continue;
// Skip PRs that were created less than 30 days ago - they cannot be stale yet
const prCreatedAt = new Date(pr.created_at);
if (prCreatedAt > thirtyDaysAgo) {
const daysOld = Math.floor((Date.now() - prCreatedAt.getTime()) / (1000 * 60 * 60 * 24));
core.info(`PR #${pr.number} was created ${daysOld} days ago. Skipping staleness check.`);
continue;
}
// Initialize lastActivity to PR creation date (not epoch) as a safety baseline.
// This ensures we never incorrectly mark a PR as stale due to failed activity lookups.
let lastActivity = new Date(pr.created_at);
try {
const reviews = await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number
});
for (const r of reviews) {
if (await isMaintainer(r.user.login, r.author_association)) {
const d = new Date(r.submitted_at || r.updated_at);
if (d > lastActivity) lastActivity = d;
}
}
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number
});
for (const c of comments) {
if (await isMaintainer(c.user.login, c.author_association)) {
const d = new Date(c.updated_at);
if (d > lastActivity) lastActivity = d;
}
}
} catch (e) {
core.warning(`Failed to fetch reviews/comments for PR #${pr.number}: ${e.message}`);
}
// For maintainer PRs, the PR creation itself counts as maintainer activity.
// (Now redundant since we initialize to pr.created_at, but kept for clarity)
if (maintainerPr) {
const d = new Date(pr.created_at);
if (d > lastActivity) lastActivity = d;
}
if (lastActivity < thirtyDaysAgo) {
core.info(`PR #${pr.number} is stale.`);
if (!dryRun) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: "Hi there! Thank you for your contribution to Gemini CLI. We really appreciate the time and effort you've put into this pull request.\n\nTo keep our backlog manageable and ensure we're focusing on current priorities, we are closing pull requests that haven't seen maintainer activity for 30 days. Currently, the team is prioritizing work associated with **🔒 maintainer only** or **help wanted** issues.\n\nIf you believe this change is still critical, please feel free to comment with updated details. Otherwise, we encourage contributors to focus on open issues labeled as **help wanted**. Thank you for your understanding!"
});
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
state: 'closed'
});
}
}
}
}
+7 -18
View File
@@ -48,24 +48,6 @@ jobs:
const repo = context.repo.repo;
const MAX_ISSUES_ASSIGNED = 3;
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
const hasHelpWantedLabel = issue.data.labels.some(label => label.name === 'help wanted');
if (!hasHelpWantedLabel) {
await github.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: issueNumber,
body: `👋 @${commenter}, thanks for your interest in this issue! We're reserving self-assignment for issues that have been marked with the \`help wanted\` label. Feel free to check out our list of [issues that need attention](https://github.com/google-gemini/gemini-cli/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).`
});
return;
}
// Search for open issues already assigned to the commenter in this repo
const { data: assignedIssues } = await github.rest.search.issuesAndPullRequests({
q: `is:issue repo:${owner}/${repo} assignee:${commenter} is:open`,
@@ -82,6 +64,13 @@ jobs:
return; // exit
}
// Check if the issue is already assigned
const issue = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
if (issue.data.assignees.length > 0) {
// Comment that it's already assigned
await github.rest.issues.createComment({
@@ -1,46 +0,0 @@
name: '🏷️ Issue Opened Labeler'
on:
issues:
types:
- 'opened'
jobs:
label-issue:
runs-on: 'ubuntu-latest'
if: |-
${{ github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli' }}
steps:
- name: 'Generate GitHub App Token'
id: 'generate_token'
env:
APP_ID: '${{ secrets.APP_ID }}'
if: |-
${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
with:
app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}'
- name: 'Add need-triage label'
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with:
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
script: |-
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const hasLabel = issue.labels.some(l => l.name === 'status/need-triage');
if (!hasLabel) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['status/need-triage']
});
} else {
core.info('Issue already has status/need-triage label. Skipping.');
}
@@ -1,57 +0,0 @@
name: 'Label Child Issues for Project Rollup'
on:
issues:
types: ['opened', 'edited', 'reopened']
schedule:
- cron: '0 * * * *' # Run every hour
workflow_dispatch:
permissions:
issues: 'write'
contents: 'read'
jobs:
# Event-based: Quick reaction to new/edited issues in THIS repo
labeler:
if: "github.event_name == 'issues'"
runs-on: 'ubuntu-latest'
steps:
- name: 'Checkout'
uses: 'actions/checkout@v4'
- name: 'Setup Node.js'
uses: 'actions/setup-node@v4'
with:
node-version: '20'
cache: 'npm'
- name: 'Install Dependencies'
run: 'npm ci'
- name: 'Run Multi-Repo Sync Script'
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: 'node .github/scripts/sync-maintainer-labels.cjs'
# Scheduled/Manual: Recursive sync across multiple repos
sync-maintainer-labels:
if: "github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'"
runs-on: 'ubuntu-latest'
steps:
- name: 'Checkout'
uses: 'actions/checkout@v4'
- name: 'Setup Node.js'
uses: 'actions/setup-node@v4'
with:
node-version: '20'
cache: 'npm'
- name: 'Install Dependencies'
run: 'npm ci'
- name: 'Run Multi-Repo Sync Script'
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: 'node .github/scripts/sync-maintainer-labels.cjs'
@@ -1,174 +0,0 @@
name: 'Label Workstream Rollup'
on:
issues:
types: ['opened', 'edited', 'reopened']
schedule:
- cron: '0 * * * *'
workflow_dispatch:
jobs:
labeler:
runs-on: 'ubuntu-latest'
permissions:
issues: 'write'
steps:
- name: 'Check for Parent Workstream and Apply Label'
uses: 'actions/github-script@v7'
with:
script: |
const labelToAdd = 'workstream-rollup';
// Allow-list of parent issue URLs
const allowedParentUrls = [
'https://github.com/google-gemini/gemini-cli/issues/15374',
'https://github.com/google-gemini/gemini-cli/issues/15456',
'https://github.com/google-gemini/gemini-cli/issues/15324',
'https://github.com/google-gemini/gemini-cli/issues/17202',
'https://github.com/google-gemini/gemini-cli/issues/17203'
];
// Single issue processing (for event triggers)
async function processSingleIssue(owner, repo, number) {
const query = `
query($owner:String!, $repo:String!, $number:Int!) {
repository(owner:$owner, name:$repo) {
issue(number:$number) {
number
parent {
url
parent {
url
parent {
url
parent {
url
parent {
url
}
}
}
}
}
}
}
}
`;
try {
const result = await github.graphql(query, { owner, repo, number });
if (!result || !result.repository || !result.repository.issue) {
console.log(`Issue #${number} not found or data missing.`);
return;
}
const issue = result.repository.issue;
await checkAndLabel(issue, owner, repo);
} catch (error) {
console.error(`Failed to process issue #${number}:`, error);
throw error; // Re-throw to be caught by main execution
}
}
// Bulk processing (for schedule/dispatch)
async function processAllOpenIssues(owner, repo) {
const query = `
query($owner:String!, $repo:String!, $cursor:String) {
repository(owner:$owner, name:$repo) {
issues(first: 100, states: OPEN, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
nodes {
number
parent {
url
parent {
url
parent {
url
parent {
url
parent {
url
}
}
}
}
}
}
}
}
}
`;
let hasNextPage = true;
let cursor = null;
while (hasNextPage) {
try {
const result = await github.graphql(query, { owner, repo, cursor });
if (!result || !result.repository || !result.repository.issues) {
console.error('Invalid response structure from GitHub API');
break;
}
const issues = result.repository.issues.nodes || [];
console.log(`Processing batch of ${issues.length} issues...`);
for (const issue of issues) {
await checkAndLabel(issue, owner, repo);
}
hasNextPage = result.repository.issues.pageInfo.hasNextPage;
cursor = result.repository.issues.pageInfo.endCursor;
} catch (error) {
console.error('Failed to fetch issues batch:', error);
throw error; // Re-throw to be caught by main execution
}
}
}
async function checkAndLabel(issue, owner, repo) {
if (!issue || !issue.parent) return;
let currentParent = issue.parent;
let tracedParents = [];
let matched = false;
while (currentParent) {
tracedParents.push(currentParent.url);
if (allowedParentUrls.includes(currentParent.url)) {
console.log(`SUCCESS: Issue #${issue.number} is a descendant of ${currentParent.url}. Trace: ${tracedParents.join(' -> ')}. Adding label.`);
await github.rest.issues.addLabels({
owner,
repo,
issue_number: issue.number,
labels: [labelToAdd]
});
matched = true;
break;
}
currentParent = currentParent.parent;
}
if (!matched && context.eventName === 'issues') {
console.log(`Issue #${issue.number} did not match any allowed workstreams. Trace: ${tracedParents.join(' -> ') || 'None'}.`);
}
}
// Main execution
try {
if (context.eventName === 'issues') {
console.log(`Processing single issue #${context.payload.issue.number}...`);
await processSingleIssue(context.repo.owner, context.repo.repo, context.payload.issue.number);
} else {
console.log(`Running for event: ${context.eventName}. Processing all open issues...`);
await processAllOpenIssues(context.repo.owner, context.repo.repo);
}
} catch (error) {
core.setFailed(`Workflow failed: ${error.message}`);
}
+1 -3
View File
@@ -12,8 +12,6 @@ on:
jobs:
linkChecker:
if: |-
${{ github.repository == 'google-gemini/gemini-cli' }}
runs-on: 'ubuntu-latest'
steps:
- uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -22,4 +20,4 @@ jobs:
id: 'lychee'
uses: 'lycheeverse/lychee-action@885c65f3dc543b57c898c8099f4e08c8afd178a2' # ratchet: lycheeverse/lychee-action@v2.6.1
with:
args: '--verbose --no-progress --accept 200,503 ./**/*.md'
args: '--verbose --no-progress ./**/*.md'
@@ -1,133 +0,0 @@
name: '🏷️ PR Contribution Guidelines Notifier'
on:
pull_request:
types:
- 'opened'
jobs:
notify-process-change:
runs-on: 'ubuntu-latest'
if: |-
github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli'
permissions:
pull-requests: 'write'
steps:
- name: 'Generate GitHub App Token'
id: 'generate_token'
env:
APP_ID: '${{ secrets.APP_ID }}'
if: |-
${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@v2'
with:
app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}'
- name: 'Check membership and post comment'
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
with:
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
script: |-
const org = context.repo.owner;
const repo = context.repo.repo;
const username = context.payload.pull_request.user.login;
const pr_number = context.payload.pull_request.number;
// 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 isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(authorAssociation);
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;
}
// 2. Check if the PR is already associated with an issue
const query = `
query($owner:String!, $repo:String!, $number:Int!) {
repository(owner:$owner, name:$repo) {
pullRequest(number:$number) {
closingIssuesReferences(first: 1) {
totalCount
}
}
}
}
`;
const variables = { owner: org, repo: repo, number: pr_number };
const result = await github.graphql(query, variables);
const issueCount = result.repository.pullRequest.closingIssuesReferences.totalCount;
if (issueCount > 0) {
core.info(`PR #${pr_number} is already associated with an issue. No notification needed.`);
return;
}
// 3. Post the notification comment
core.info(`${username} is not a maintainer and PR #${pr_number} has no linked issue. Posting notification.`);
const comment = `
Hi @${username}, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.
We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: [Improving Our Contribution Process & Introducing New Guidelines](https://github.com/google-gemini/gemini-cli/discussions/16706).
Key Update: Starting **January 26, 2026**, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.
Thank you for your understanding and for being a part of our community!
`.trim().replace(/^[ ]+/gm, '');
await github.rest.issues.createComment({
owner: org,
repo: repo,
issue_number: pr_number,
body: comment
});
-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
+1 -2
View File
@@ -110,7 +110,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ steps.release_info.outputs.PREVIOUS_TAG }}'
skip-github-release: '${{ github.event.inputs.skip_github_release }}'
@@ -133,4 +132,4 @@ jobs:
gh issue create \
--title 'Manual Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')' \
--body 'The manual release workflow failed. See the full run for details: ${DETAILS_URL}' \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
+2 -4
View File
@@ -31,7 +31,6 @@ on:
jobs:
release:
if: "github.repository == 'google-gemini/gemini-cli'"
environment: "${{ github.event.inputs.environment || 'prod' }}"
runs-on: 'ubuntu-latest'
permissions:
@@ -124,7 +123,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ steps.vars.outputs.is_dry_run }}'
previous-tag: '${{ steps.nightly_version.outputs.PREVIOUS_TAG }}'
working-directory: './release'
@@ -145,7 +143,7 @@ jobs:
branch-name: 'release/${{ steps.nightly_version.outputs.RELEASE_TAG }}'
pr-title: 'chore/release: bump version to ${{ steps.nightly_version.outputs.RELEASE_VERSION }}'
pr-body: 'Automated version bump for nightly release.'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ steps.vars.outputs.is_dry_run }}'
working-directory: './release'
@@ -159,4 +157,4 @@ jobs:
gh issue create \
--title "Nightly Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')" \
--body "The nightly-release workflow failed. See the full run for details: ${DETAILS_URL}" \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
-86
View File
@@ -1,86 +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:
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: 'Generate Changelog with Gemini'
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.
- name: 'Create Pull Request'
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.
branch: 'changelog-${{ steps.release_info.outputs.VERSION }}'
base: 'main'
team-reviewers: 'gemini-cli-docs, gemini-cli-maintainers'
delete-branch: true
@@ -184,7 +184,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
@@ -206,7 +205,7 @@ jobs:
gh issue create \
--title 'Patch Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')' \
--body 'The patch-release workflow failed. See the full run for details: ${DETAILS_URL}' \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
- name: 'Comment Success on Original PR'
if: '${{ success() && github.event.inputs.original_pr }}'
+4 -6
View File
@@ -239,7 +239,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_PREVIEW_TAG }}'
working-directory: './release'
@@ -262,7 +261,7 @@ jobs:
gh issue create \
--title 'Promote Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')' \
--body 'The promote-release workflow failed during preview publish. See the full run for details: ${DETAILS_URL}' \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
publish-stable:
name: 'Publish stable'
@@ -306,7 +305,6 @@ jobs:
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}'
previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_STABLE_TAG }}'
working-directory: './release'
@@ -329,7 +327,7 @@ jobs:
gh issue create \
--title 'Promote Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')' \
--body 'The promote-release workflow failed during stable publish. See the full run for details: ${DETAILS_URL}' \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
nightly-pr:
name: 'Create Nightly PR'
@@ -392,7 +390,7 @@ jobs:
branch-name: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
pr-title: 'chore(release): bump version to ${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
pr-body: 'Automated version bump to prepare for the next nightly release.'
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
dry-run: '${{ github.event.inputs.dry_run }}'
- name: 'Create Issue on Failure'
@@ -405,4 +403,4 @@ jobs:
gh issue create \
--title 'Promote Release Failed for ${RELEASE_TAG} on $(date +'%Y-%m-%d')' \
--body 'The promote-release workflow failed during nightly PR creation. See the full run for details: ${DETAILS_URL}' \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
+1 -1
View File
@@ -46,4 +46,4 @@ jobs:
gh issue create \
--title 'Sandbox Release Failed on $(date +'%Y-%m-%d')' \
--body 'The sandbox-release workflow failed. See the full run for details: ${DETAILS_URL}' \
--label 'release-failure,priority/p0'
--label 'kind/bug,release-failure,priority/p0'
+1 -1
View File
@@ -47,4 +47,4 @@ jobs:
gh issue create \
--title 'Smoke test failed on ${REF} @ $(date +'%Y-%m-%d')' \
--body 'Smoke test build failed. See the full run for details: ${DETAILS_URL}' \
--label 'priority/p0'
--label 'kind/bug,priority/p0'
+2 -2
View File
@@ -40,5 +40,5 @@ jobs:
If this is still relevant, you are welcome to reopen or leave a comment. Thanks for contributing!
days-before-stale: 60
days-before-close: 14
exempt-issue-labels: 'pinned,security,🔒 maintainer only,help wanted,🗓️ Public Roadmap'
exempt-pr-labels: 'pinned,security,🔒 maintainer only,help wanted,🗓️ Public Roadmap'
exempt-issue-labels: 'pinned,security'
exempt-pr-labels: 'pinned,security'
@@ -1,4 +1,4 @@
name: 'Testing: E2E (Chained)'
name: 'Test Chained E2E'
on:
push:
@@ -37,15 +37,14 @@ jobs:
- id: 'merge-queue-e2e-skipper'
uses: 'cariad-tech/merge-queue-ci-skipper@1032489e59437862c90a08a2c92809c903883772' # ratchet:cariad-tech/merge-queue-ci-skipper@main
with:
secret: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
secret: '${{ secrets.GITHUB_TOKEN }}'
continue-on-error: true
download_repo_name:
runs-on: 'gemini-cli-ubuntu-16-core'
if: "${{github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run'}}"
if: "github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run'"
outputs:
repo_name: '${{ steps.output-repo-name.outputs.repo_name }}'
head_sha: '${{ steps.output-repo-name.outputs.head_sha }}'
steps:
- name: 'Mock Repo Artifact'
if: "${{ github.event_name == 'workflow_dispatch' }}"
@@ -67,7 +66,7 @@ jobs:
name: 'repo_name'
run-id: '${{ env.RUN_ID }}'
path: '${{ runner.temp }}/artifacts'
- name: 'Output Repo Name and SHA'
- name: 'Output Repo Name'
id: 'output-repo-name'
uses: 'actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd' # ratchet:actions/github-script@v8
with:
@@ -76,16 +75,8 @@ jobs:
const fs = require('fs');
const path = require('path');
const temp = '${{ runner.temp }}/artifacts';
const repoPath = path.join(temp, 'repo_name');
if (fs.existsSync(repoPath)) {
const repo_name = String(fs.readFileSync(repoPath)).trim();
core.setOutput('repo_name', repo_name);
}
const shaPath = path.join(temp, 'head_sha');
if (fs.existsSync(shaPath)) {
const head_sha = String(fs.readFileSync(shaPath)).trim();
core.setOutput('head_sha', head_sha);
}
const repo_name = String(fs.readFileSync(path.join(temp, 'repo_name')));
core.setOutput('repo_name', repo_name);
parse_run_context:
name: 'Parse run context'
@@ -100,7 +91,7 @@ jobs:
name: 'Set dynamic repository and SHA'
env:
REPO: '${{ needs.download_repo_name.outputs.repo_name || github.repository }}'
SHA: '${{ needs.download_repo_name.outputs.head_sha || github.event.inputs.head_sha || github.event.workflow_run.head_sha || github.sha }}'
SHA: '${{ github.event.inputs.head_sha || github.event.workflow_run.head_sha || github.sha }}'
shell: 'bash'
run: |
echo "REPO=$REPO" >> "$GITHUB_OUTPUT"
@@ -109,20 +100,19 @@ jobs:
set_pending_status:
runs-on: 'gemini-cli-ubuntu-16-core'
permissions: 'write-all'
if: "github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run'"
needs:
- 'parse_run_context'
if: 'always()'
steps:
- name: 'Set pending status'
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master
if: 'always()'
with:
allowForks: 'true'
repo: '${{ github.repository }}'
repo: '${{ needs.parse_run_context.outputs.repository }}'
sha: '${{ needs.parse_run_context.outputs.sha }}'
token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
token: '${{ secrets.GITHUB_TOKEN }}'
status: 'pending'
context: 'E2E (Chained)'
e2e_linux:
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
@@ -131,7 +121,7 @@ jobs:
- 'parse_run_context'
runs-on: 'gemini-cli-ubuntu-16-core'
if: |
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 == 'false')
strategy:
fail-fast: false
matrix:
@@ -160,7 +150,7 @@ jobs:
run: 'npm run build'
- name: 'Set up Docker'
if: "${{matrix.sandbox == 'sandbox:docker'}}"
if: "matrix.sandbox == 'sandbox:docker'"
uses: 'docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435' # ratchet:docker/setup-buildx-action@v3
- name: 'Run E2E tests'
@@ -168,7 +158,6 @@ jobs:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
KEEP_OUTPUT: 'true'
VERBOSE: 'true'
BUILD_SANDBOX_FLAGS: '--cache-from type=gha --cache-to type=gha,mode=max'
shell: 'bash'
run: |
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then
@@ -184,7 +173,7 @@ jobs:
- 'parse_run_context'
runs-on: 'macos-latest'
if: |
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 == 'false')
steps:
- name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
@@ -204,11 +193,11 @@ jobs:
run: 'npm run build'
- name: 'Fix rollup optional dependencies on macOS'
if: "${{runner.os == 'macOS'}}"
if: "runner.os == 'macOS'"
run: |
npm cache clean --force
- name: 'Run E2E tests (non-Windows)'
if: "${{runner.os != 'Windows'}}"
if: "runner.os != 'Windows'"
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
KEEP_OUTPUT: 'true'
@@ -222,8 +211,10 @@ jobs:
- 'merge_queue_skipper'
- 'parse_run_context'
if: |
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 == 'false')
runs-on: 'gemini-cli-windows-16-core'
continue-on-error: true
steps:
- name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
@@ -275,55 +266,20 @@ jobs:
shell: 'pwsh'
run: 'npm run test:integration:sandbox:none'
evals:
name: 'Evals (ALWAYS_PASSING)'
needs:
- 'merge_queue_skipper'
- 'parse_run_context'
runs-on: 'gemini-cli-ubuntu-16-core'
if: |
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
steps:
- name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
with:
ref: '${{ needs.parse_run_context.outputs.sha }}'
repository: '${{ needs.parse_run_context.outputs.repository }}'
- name: 'Set up Node.js 20.x'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
with:
node-version: '20.x'
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Build project'
run: 'npm run build'
- name: 'Run Evals (Required to pass)'
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
run: 'npm run test:always_passing_evals'
e2e:
name: 'E2E'
if: |
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 == 'false')
needs:
- 'e2e_linux'
- 'e2e_mac'
- 'e2e_windows'
- 'evals'
- 'merge_queue_skipper'
runs-on: 'gemini-cli-ubuntu-16-core'
steps:
- name: 'Check E2E test results'
run: |
if [[ ${{ needs.e2e_linux.result }} != 'success' || \
${{ needs.e2e_mac.result }} != 'success' || \
${{ needs.e2e_windows.result }} != 'success' || \
${{ needs.evals.result }} != 'success' ]]; then
${{ needs.e2e_mac.result }} != 'success' ]]; then
echo "One or more E2E jobs failed."
exit 1
fi
@@ -332,7 +288,7 @@ jobs:
set_workflow_status:
runs-on: 'gemini-cli-ubuntu-16-core'
permissions: 'write-all'
if: 'always()'
if: "github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run'"
needs:
- 'parse_run_context'
- 'e2e'
@@ -342,8 +298,7 @@ jobs:
if: 'always()'
with:
allowForks: 'true'
repo: '${{ github.repository }}'
repo: '${{ needs.parse_run_context.outputs.repository }}'
sha: '${{ needs.parse_run_context.outputs.sha }}'
token: '${{ secrets.GITHUB_TOKEN }}'
status: '${{ needs.e2e.result }}'
context: 'E2E (Chained)'
status: '${{ job.status }}'
+6 -11
View File
@@ -3,15 +3,11 @@ name: 'Trigger E2E'
on:
workflow_dispatch:
inputs:
repo_name:
description: 'Repository name (e.g., owner/repo)'
required: false
branch_ref:
description: 'Branch to run on'
required: true
default: 'main'
type: 'string'
head_sha:
description: 'SHA of the commit to test'
required: false
type: 'string'
pull_request:
jobs:
save_repo_name:
@@ -19,12 +15,11 @@ jobs:
steps:
- name: 'Save Repo name'
env:
REPO_NAME: '${{ github.event.inputs.repo_name || github.event.pull_request.head.repo.full_name }}'
HEAD_SHA: '${{ github.event.inputs.head_sha || github.event.pull_request.head.sha }}'
# Replace with github.event.pull_request.head.repo.full_name when switched to listen on pull request events. This repo name does not contain the org which is needed for checkout.
REPO_NAME: '${{ github.event.repository.name }}'
run: |
mkdir -p ./pr
echo '${{ env.REPO_NAME }}' > ./pr/repo_name
echo '${{ env.HEAD_SHA }}' > ./pr/head_sha
- uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'repo_name'
+1 -5
View File
@@ -29,11 +29,7 @@ on:
jobs:
verify-release:
environment: "${{ github.event.inputs.environment || 'prod' }}"
strategy:
fail-fast: false
matrix:
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
runs-on: '${{ matrix.os }}'
runs-on: 'ubuntu-latest'
permissions:
contents: 'read'
packages: 'write'
-7
View File
@@ -11,8 +11,6 @@
.gemini/*
!.gemini/config.yaml
!.gemini/commands/
!.gemini/skills/
!.gemini/settings.json
# Note: .gemini-clipboard/ is NOT in gitignore so Gemini can access pasted images
@@ -46,7 +44,6 @@ packages/*/coverage/
# Generated files
packages/cli/src/generated/
packages/core/src/generated/
packages/devtools/src/_client-assets.ts
.integration-tests/
packages/vscode-ide-companion/*.vsix
packages/cli/download-ripgrep*/
@@ -56,9 +53,5 @@ gha-creds-*.json
# Log files
patch_output.log
gemini-debug.log
.genkit
.gemini-clipboard/
.eslintcache
evals/logs/
-4
View File
@@ -17,8 +17,4 @@ eslint.config.js
**/generated
gha-creds-*.json
junit.xml
.gemini-linters/
Thumbs.db
.pytest_cache
**/SKILL.md
packages/sdk/test-data/*.json
+21 -27
View File
@@ -1,4 +1,4 @@
# How to contribute
# How to Contribute
We would love to accept your patches and contributions to this project. This
document includes:
@@ -41,14 +41,7 @@ This project follows
The process for contributing code is as follows:
1. **Find an issue** that you want to work on. If an issue is tagged as
`🔒Maintainers only`, this means it is reserved for project maintainers. We
will not accept pull requests related to these issues. In the near future,
we will explicitly mark issues looking for contributions using the
`help-wanted` label. If you believe an issue is a good candidate for
community contribution, please leave a comment on the issue. A maintainer
will review it and apply the `help-wanted` label if appropriate. Only
maintainers should attempt to add the `help-wanted` label to an issue.
1. **Find an issue** that you want to work on.
2. **Fork the repository** and create a new branch.
3. **Make your changes** in the `packages/` directory.
4. **Ensure all checks pass** by running `npm run preflight`.
@@ -77,6 +70,10 @@ augment their manual review process.
### Self assigning issues
If you're looking for an issue to work on, check out our list of issues that are
labeled
["help wanted"](https://github.com/google-gemini/gemini-cli/issues?q=is%3Aissue+state%3Aopen+label%3A%22help+wanted%22).
To assign an issue to yourself, simply add a comment with the text `/assign`.
The comment must contain only that text and nothing else. This command will
assign the issue to you, provided it is not already assigned.
@@ -99,11 +96,8 @@ any code is written.
- **For features:** The PR should be linked to the feature request or proposal
issue that has been approved by a maintainer.
If an issue for your change doesn't exist, we will automatically close your PR
along with a comment reminding you to associate the PR with an issue. The ideal
workflow starts with an issue that has been reviewed and approved by a
maintainer. Please **open the issue first** and wait for feedback before you
start coding.
If an issue for your change doesn't exist, please **open one first** and wait
for feedback before you start coding.
#### 2. Keep it small and focused
@@ -372,7 +366,8 @@ specific debug settings.
### React DevTools
To debug the CLI's React-based UI, you can use React DevTools.
To debug the CLI's React-based UI, you can use React DevTools. Ink, the library
used for the CLI's interface, is compatible with React DevTools version 4.x.
1. **Start the Gemini CLI in development mode:**
@@ -380,20 +375,20 @@ To debug the CLI's React-based UI, you can use React DevTools.
DEV=true npm start
```
2. **Install and run React DevTools version 6 (which matches the CLI's
`react-devtools-core`):**
2. **Install and run React DevTools version 4.28.5 (or the latest compatible
4.x version):**
You can either install it globally:
```bash
npm install -g react-devtools@6
npm install -g react-devtools@4.28.5
react-devtools
```
Or run it directly using npx:
```bash
npx react-devtools@6
npx react-devtools@4.28.5
```
Your running CLI application should then connect to React DevTools.
@@ -407,13 +402,12 @@ On macOS, `gemini` uses Seatbelt (`sandbox-exec`) under a `permissive-open`
profile (see `packages/cli/src/utils/sandbox-macos-permissive-open.sb`) that
restricts writes to the project folder but otherwise allows all other operations
and outbound network traffic ("open") by default. You can switch to a
`strict-open` profile (see
`packages/cli/src/utils/sandbox-macos-strict-open.sb`) that restricts both reads
and writes to the working directory while allowing outbound network traffic by
setting `SEATBELT_PROFILE=strict-open` in your environment or `.env` file.
Available built-in profiles are `permissive-{open,proxied}`,
`restrictive-{open,proxied}`, and `strict-{open,proxied}` (see below for proxied
networking). You can also switch to a custom profile
`restrictive-closed` profile (see
`packages/cli/src/utils/sandbox-macos-restrictive-closed.sb`) that declines all
operations and outbound network traffic ("closed") by default by setting
`SEATBELT_PROFILE=restrictive-closed` in your environment or `.env` file.
Available built-in profiles are `{permissive,restrictive}-{open,closed,proxied}`
(see below for proxied networking). You can also switch to a custom profile
`SEATBELT_PROFILE=<profile>` if you also create a file
`.gemini/sandbox-macos-<profile>.sb` under your project settings directory
`.gemini`.
@@ -545,7 +539,7 @@ Before submitting your documentation pull request, please:
If you have questions about contributing documentation:
- Check our [FAQ](/docs/resources/faq.md).
- Check our [FAQ](/docs/faq.md).
- Review existing documentation for examples.
- Open [an issue](https://github.com/google-gemini/gemini-cli/issues) to discuss
your proposed changes.
+1 -4
View File
@@ -42,10 +42,7 @@ USER node
# install gemini-cli and clean up
COPY packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz
COPY packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz
RUN npm install -g /tmp/gemini-core.tgz \
&& npm install -g /tmp/gemini-cli.tgz \
&& node -e "const fs=require('node:fs'); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json','utf8')); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json','utf8'));" \
&& gemini --version > /dev/null \
RUN npm install -g /tmp/gemini-cli.tgz /tmp/gemini-core.tgz \
&& npm cache clean --force \
&& rm -f /tmp/gemini-{cli,core}.tgz
+361 -81
View File
@@ -1,94 +1,374 @@
# Gemini CLI Project Context
## Building and running
Gemini CLI is an open-source AI agent that brings the power of Gemini directly
into the terminal. It is designed to be a terminal-first, extensible, and
powerful tool for developers.
Before submitting any changes, it is crucial to validate them by running the
full preflight check. This command will build the repository, run all tests,
check for type errors, and lint the code.
## Project Overview
To run the full suite of checks, execute the following command:
- **Purpose:** Provide a seamless terminal interface for Gemini models,
supporting code understanding, generation, automation, and integration via MCP
(Model Context Protocol).
- **Main Technologies:**
- **Runtime:** Node.js (>=20.0.0, recommended ~20.19.0 for development)
- **Language:** TypeScript
- **UI Framework:** React (using [Ink](https://github.com/vadimdemedes/ink)
for CLI rendering)
- **Testing:** Vitest
- **Bundling:** esbuild
- **Linting/Formatting:** ESLint, Prettier
- **Architecture:** Monorepo structure using npm workspaces.
- `packages/cli`: User-facing terminal UI, input processing, and display
rendering.
- `packages/core`: Backend logic, Gemini API orchestration, prompt
construction, and tool execution.
- `packages/core/src/tools/`: Built-in tools for file system, shell, and web
operations.
- `packages/a2a-server`: Experimental Agent-to-Agent server.
- `packages/vscode-ide-companion`: VS Code extension pairing with the CLI.
```bash
npm run preflight
```
## Building and Running
This single command ensures that your changes meet all the quality gates of the
project. While you can run the individual steps (`build`, `test`, `typecheck`,
`lint`) separately, it is highly recommended to use `npm run preflight` to
ensure a comprehensive validation.
- **Install Dependencies:** `npm install`
- **Build All:** `npm run build:all` (Builds packages, sandbox, and VS Code
companion)
- **Build Packages:** `npm run build`
- **Run in Development:** `npm run start`
- **Run in Debug Mode:** `npm run debug` (Enables Node.js inspector)
- **Bundle Project:** `npm run bundle`
- **Clean Artifacts:** `npm run clean`
## Writing Tests
## Testing and Quality
This project uses **Vitest** as its primary testing framework. When writing
tests, aim to follow existing patterns. Key conventions include:
- **Test Commands:**
- **Unit (All):** `npm run test`
- **Integration (E2E):** `npm run test:e2e`
- **Workspace-Specific:** `npm test -w <pkg> -- <path>` (Note: `<path>` must
be relative to the workspace root, e.g.,
`-w @google/gemini-cli-core -- src/routing/modelRouterService.test.ts`)
- **Full Validation:** `npm run preflight` (Heaviest check; runs clean, install,
build, lint, type check, and tests. Recommended before submitting PRs. Due to
its long runtime, only run this at the very end of a code implementation task.
If it fails, use faster, targeted commands (e.g., `npm run test`,
`npm run lint`, or workspace-specific tests) to iterate on fixes before
re-running `preflight`. For simple, non-code changes like documentation or
prompting updates, skip `preflight` at the end of the task and wait for PR
validation.)
- **Individual Checks:** `npm run lint` / `npm run format` / `npm run typecheck`
### Test Structure and Framework
## Development Conventions
- **Framework**: All tests are written using Vitest (`describe`, `it`, `expect`,
`vi`).
- **File Location**: Test files (`*.test.ts` for logic, `*.test.tsx` for React
components) are co-located with the source files they test.
- **Configuration**: Test environments are defined in `vitest.config.ts` files.
- **Setup/Teardown**: Use `beforeEach` and `afterEach`. Commonly,
`vi.resetAllMocks()` is called in `beforeEach` and `vi.restoreAllMocks()` in
`afterEach`.
- **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
signing the Google CLA.
- **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
[Conventional Commits](https://www.conventionalcommits.org/) standard.
- **Coding Style:** Adhere to existing patterns in `packages/cli` (React/Ink)
and `packages/core` (Backend logic).
- **Imports:** Use specific imports and avoid restricted relative imports
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.
### Mocking (`vi` from Vitest)
## Testing Conventions
- **ES Modules**: Mock with
`vi.mock('module-name', async (importOriginal) => { ... })`. Use
`importOriginal` for selective mocking.
- _Example_:
`vi.mock('os', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, homedir: vi.fn() }; });`
- **Mocking Order**: For critical dependencies (e.g., `os`, `fs`) that affect
module-level constants, place `vi.mock` at the _very top_ of the test file,
before other imports.
- **Hoisting**: Use `const myMock = vi.hoisted(() => vi.fn());` if a mock
function needs to be defined before its use in a `vi.mock` factory.
- **Mock Functions**: Create with `vi.fn()`. Define behavior with
`mockImplementation()`, `mockResolvedValue()`, or `mockRejectedValue()`.
- **Spying**: Use `vi.spyOn(object, 'methodName')`. Restore spies with
`mockRestore()` in `afterEach`.
- **Environment Variables:** When testing code that depends on environment
variables, use `vi.stubEnv('NAME', 'value')` in `beforeEach` and
`vi.unstubAllEnvs()` in `afterEach`. Avoid modifying `process.env` directly as
it can lead to test leakage and is less reliable. To "unset" a variable, use
an empty string `vi.stubEnv('NAME', '')`.
### Commonly Mocked Modules
## Documentation
- **Node.js built-ins**: `fs`, `fs/promises`, `os` (especially `os.homedir()`),
`path`, `child_process` (`execSync`, `spawn`).
- **External SDKs**: `@google/genai`, `@modelcontextprotocol/sdk`.
- **Internal Project Modules**: Dependencies from other project packages are
often mocked.
- Always use the `docs-writer` skill when you are asked to write, edit, or
review any documentation.
- Documentation is located in the `docs/` directory.
- Suggest documentation updates when code changes render existing documentation
obsolete or incomplete.
### React Component Testing (CLI UI - Ink)
- Use `render()` from `ink-testing-library`.
- Assert output with `lastFrame()`.
- Wrap components in necessary `Context.Provider`s.
- Mock custom React hooks and complex child components using `vi.mock()`.
### Asynchronous Testing
- Use `async/await`.
- For timers, use `vi.useFakeTimers()`, `vi.advanceTimersByTimeAsync()`,
`vi.runAllTimersAsync()`.
- Test promise rejections with `await expect(promise).rejects.toThrow(...)`.
### General Guidance
- When adding tests, first examine existing tests to understand and conform to
established conventions.
- Pay close attention to the mocks at the top of existing test files; they
reveal critical dependencies and how they are managed in a test environment.
## Git Repo
The main branch for this project is called "main"
## JavaScript/TypeScript
When contributing to this React, Node, and TypeScript codebase, please
prioritize the use of plain JavaScript objects with accompanying TypeScript
interface or type declarations over JavaScript class syntax. This approach
offers significant advantages, especially concerning interoperability with React
and overall code maintainability.
### Preferring Plain Objects over Classes
JavaScript classes, by their nature, are designed to encapsulate internal state
and behavior. While this can be useful in some object-oriented paradigms, it
often introduces unnecessary complexity and friction when working with React's
component-based architecture. Here's why plain objects are preferred:
- Seamless React Integration: React components thrive on explicit props and
state management. Classes' tendency to store internal state directly within
instances can make prop and state propagation harder to reason about and
maintain. Plain objects, on the other hand, are inherently immutable (when
used thoughtfully) and can be easily passed as props, simplifying data flow
and reducing unexpected side effects.
- Reduced Boilerplate and Increased Conciseness: Classes often promote the use
of constructors, this binding, getters, setters, and other boilerplate that
can unnecessarily bloat code. TypeScript interface and type declarations
provide powerful static type checking without the runtime overhead or
verbosity of class definitions. This allows for more succinct and readable
code, aligning with JavaScript's strengths in functional programming.
- Enhanced Readability and Predictability: Plain objects, especially when their
structure is clearly defined by TypeScript interfaces, are often easier to
read and understand. Their properties are directly accessible, and there's no
hidden internal state or complex inheritance chains to navigate. This
predictability leads to fewer bugs and a more maintainable codebase.
- Simplified Immutability: While not strictly enforced, plain objects encourage
an immutable approach to data. When you need to modify an object, you
typically create a new one with the desired changes, rather than mutating the
original. This pattern aligns perfectly with React's reconciliation process
and helps prevent subtle bugs related to shared mutable state.
- Better Serialization and Deserialization: Plain JavaScript objects are
naturally easy to serialize to JSON and deserialize back, which is a common
requirement in web development (e.g., for API communication or local storage).
Classes, with their methods and prototypes, can complicate this process.
### Embracing ES Module Syntax for Encapsulation
Rather than relying on Java-esque private or public class members, which can be
verbose and sometimes limit flexibility, we strongly prefer leveraging ES module
syntax (`import`/`export`) for encapsulating private and public APIs.
- Clearer Public API Definition: With ES modules, anything that is exported is
part of the public API of that module, while anything not exported is
inherently private to that module. This provides a very clear and explicit way
to define what parts of your code are meant to be consumed by other modules.
- Enhanced Testability (Without Exposing Internals): By default, unexported
functions or variables are not accessible from outside the module. This
encourages you to test the public API of your modules, rather than their
internal implementation details. If you find yourself needing to spy on or
stub an unexported function for testing purposes, it's often a "code smell"
indicating that the function might be a good candidate for extraction into its
own separate, testable module with a well-defined public API. This promotes a
more robust and maintainable testing strategy.
- Reduced Coupling: Explicitly defined module boundaries through import/export
help reduce coupling between different parts of your codebase. This makes it
easier to refactor, debug, and understand individual components in isolation.
### Avoiding `any` Types and Type Assertions; Preferring `unknown`
TypeScript's power lies in its ability to provide static type checking, catching
potential errors before your code runs. To fully leverage this, it's crucial to
avoid the `any` type and be judicious with type assertions.
- **The Dangers of `any`**: Using any effectively opts out of TypeScript's type
checking for that particular variable or expression. While it might seem
convenient in the short term, it introduces significant risks:
- **Loss of Type Safety**: You lose all the benefits of type checking, making
it easy to introduce runtime errors that TypeScript would otherwise have
caught.
- **Reduced Readability and Maintainability**: Code with `any` types is harder
to understand and maintain, as the expected type of data is no longer
explicitly defined.
- **Masking Underlying Issues**: Often, the need for any indicates a deeper
problem in the design of your code or the way you're interacting with
external libraries. It's a sign that you might need to refine your types or
refactor your code.
- **Preferring `unknown` over `any`**: When you absolutely cannot determine the
type of a value at compile time, and you're tempted to reach for any, consider
using unknown instead. unknown is a type-safe counterpart to any. While a
variable of type unknown can hold any value, you must perform type narrowing
(e.g., using typeof or instanceof checks, or a type assertion) before you can
perform any operations on it. This forces you to handle the unknown type
explicitly, preventing accidental runtime errors.
```ts
function processValue(value: unknown) {
if (typeof value === 'string') {
// value is now safely a string
console.log(value.toUpperCase());
} else if (typeof value === 'number') {
// value is now safely a number
console.log(value * 2);
}
// Without narrowing, you cannot access properties or methods on 'value'
// console.log(value.someProperty); // Error: Object is of type 'unknown'.
}
```
- **Type Assertions (`as Type`) - Use with Caution**: Type assertions tell the
TypeScript compiler, "Trust me, I know what I'm doing; this is definitely of
this type." While there are legitimate use cases (e.g., when dealing with
external libraries that don't have perfect type definitions, or when you have
more information than the compiler), they should be used sparingly and with
extreme caution.
- **Bypassing Type Checking**: Like `any`, type assertions bypass TypeScript's
safety checks. If your assertion is incorrect, you introduce a runtime error
that TypeScript would not have warned you about.
- **Code Smell in Testing**: A common scenario where `any` or type assertions
might be tempting is when trying to test "private" implementation details
(e.g., spying on or stubbing an unexported function within a module). This
is a strong indication of a "code smell" in your testing strategy and
potentially your code structure. Instead of trying to force access to
private internals, consider whether those internal details should be
refactored into a separate module with a well-defined public API. This makes
them inherently testable without compromising encapsulation.
### Type narrowing `switch` clauses
Use the `checkExhaustive` helper in the default clause of a switch statement.
This will ensure that all of the possible options within the value or
enumeration are used.
This helper method can be found in `packages/cli/src/utils/checks.ts`
### Embracing JavaScript's Array Operators
To further enhance code cleanliness and promote safe functional programming
practices, leverage JavaScript's rich set of array operators as much as
possible. Methods like `.map()`, `.filter()`, `.reduce()`, `.slice()`,
`.sort()`, and others are incredibly powerful for transforming and manipulating
data collections in an immutable and declarative way.
Using these operators:
- Promotes Immutability: Most array operators return new arrays, leaving the
original array untouched. This functional approach helps prevent unintended
side effects and makes your code more predictable.
- Improves Readability: Chaining array operators often lead to more concise and
expressive code than traditional for loops or imperative logic. The intent of
the operation is clear at a glance.
- Facilitates Functional Programming: These operators are cornerstones of
functional programming, encouraging the creation of pure functions that take
inputs and produce outputs without causing side effects. This paradigm is
highly beneficial for writing robust and testable code that pairs well with
React.
By consistently applying these principles, we can maintain a codebase that is
not only efficient and performant but also a joy to work with, both now and in
the future.
## React (mirrored and adjusted from [react-mcp-server](https://github.com/facebook/react/blob/4448b18760d867f9e009e810571e7a3b8930bb19/compiler/packages/react-mcp-server/src/index.ts#L376C1-L441C94))
### Role
You are a React assistant that helps users write more efficient and optimizable
React code. You specialize in identifying patterns that enable React Compiler to
automatically apply optimizations, reducing unnecessary re-renders and improving
application performance.
### Follow these guidelines in all code you produce and suggest
Use functional components with Hooks: Do not generate class components or use
old lifecycle methods. Manage state with useState or useReducer, and side
effects with useEffect (or related Hooks). Always prefer functions and Hooks for
any new component logic.
Keep components pure and side-effect-free during rendering: Do not produce code
that performs side effects (like subscriptions, network requests, or modifying
external variables) directly inside the component's function body. Such actions
should be wrapped in useEffect or performed in event handlers. Ensure your
render logic is a pure function of props and state.
Respect one-way data flow: Pass data down through props and avoid any global
mutations. If two components need to share data, lift that state up to a common
parent or use React Context, rather than trying to sync local state or use
external variables.
Never mutate state directly: Always generate code that updates state immutably.
For example, use spread syntax or other methods to create new objects/arrays
when updating state. Do not use assignments like state.someValue = ... or array
mutations like array.push() on state variables. Use the state setter (setState
from useState, etc.) to update state.
Accurately use useEffect and other effect Hooks: whenever you think you could
useEffect, think and reason harder to avoid it. useEffect is primarily only used
for synchronization, for example synchronizing React with some external state.
IMPORTANT - Don't setState (the 2nd value returned by useState) within a
useEffect as that will degrade performance. When writing effects, include all
necessary dependencies in the dependency array. Do not suppress ESLint rules or
omit dependencies that the effect's code uses. Structure the effect callbacks to
handle changing values properly (e.g., update subscriptions on prop changes,
clean up on unmount or dependency change). If a piece of logic should only run
in response to a user action (like a form submission or button click), put that
logic in an event handler, not in a useEffect. Where possible, useEffects should
return a cleanup function.
Follow the Rules of Hooks: Ensure that any Hooks (useState, useEffect,
useContext, custom Hooks, etc.) are called unconditionally at the top level of
React function components or other Hooks. Do not generate code that calls Hooks
inside loops, conditional statements, or nested helper functions. Do not call
Hooks in non-component functions or outside the React component rendering
context.
Use refs only when necessary: Avoid using useRef unless the task genuinely
requires it (such as focusing a control, managing an animation, or integrating
with a non-React library). Do not use refs to store application state that
should be reactive. If you do use refs, never write to or read from ref.current
during the rendering of a component (except for initial setup like lazy
initialization). Any ref usage should not affect the rendered output directly.
Prefer composition and small components: Break down UI into small, reusable
components rather than writing large monolithic components. The code you
generate should promote clarity and reusability by composing components
together. Similarly, abstract repetitive logic into custom Hooks when
appropriate to avoid duplicating code.
Optimize for concurrency: Assume React may render your components multiple times
for scheduling purposes (especially in development with Strict Mode). Write code
that remains correct even if the component function runs more than once. For
instance, avoid side effects in the component body and use functional state
updates (e.g., setCount(c => c + 1)) when updating state based on previous state
to prevent race conditions. Always include cleanup functions in effects that
subscribe to external resources. Don't write useEffects for "do this when this
changes" side effects. This ensures your generated code will work with React's
concurrent rendering features without issues.
Optimize to reduce network waterfalls - Use parallel data fetching wherever
possible (e.g., start multiple requests at once rather than one after another).
Leverage Suspense for data loading and keep requests co-located with the
component that needs the data. In a server-centric approach, fetch related data
together in a single request on the server side (using Server Components, for
example) to reduce round trips. Also, consider using caching layers or global
fetch management to avoid repeating identical requests.
Rely on React Compiler - useMemo, useCallback, and React.memo can be omitted if
React Compiler is enabled. Avoid premature optimization with manual memoization.
Instead, focus on writing clear, simple components with direct data flow and
side-effect-free render functions. Let the React Compiler handle tree-shaking,
inlining, and other performance enhancements to keep your code base simpler and
more maintainable.
Design for a good user experience - Provide clear, minimal, and non-blocking UI
states. When data is loading, show lightweight placeholders (e.g., skeleton
screens) rather than intrusive spinners everywhere. Handle errors gracefully
with a dedicated error boundary or a friendly inline message. Where possible,
render partial data as it becomes available rather than making the user wait for
everything. Suspense allows you to declare the loading states in your component
tree in a natural way, preventing “flash” states and improving perceived
performance.
### Process
1. Analyze the user's code for optimization opportunities:
- Check for React anti-patterns that prevent compiler optimization
- Look for component structure issues that limit compiler effectiveness
- Think about each suggestion you are making and consult React docs for best
practices
2. Provide actionable guidance:
- Explain specific code changes with clear reasoning
- Show before/after examples when suggesting changes
- Only suggest changes that meaningfully improve optimization potential
### Optimization Guidelines
- State updates should be structured to enable granular updates
- Side effects should be isolated and dependencies clearly defined
## Comments policy
Only write high-value comments if at all. Avoid talking to the user through
comments.
## General style requirements
Use hyphens instead of underscores in flag names (e.g. `my-flag` instead of
`my_flag`).
+13 -31
View File
@@ -1,10 +1,9 @@
# Gemini CLI
[![Gemini CLI CI](https://github.com/google-gemini/gemini-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/google-gemini/gemini-cli/actions/workflows/ci.yml)
[![Gemini CLI E2E (Chained)](https://github.com/google-gemini/gemini-cli/actions/workflows/chained_e2e.yml/badge.svg)](https://github.com/google-gemini/gemini-cli/actions/workflows/chained_e2e.yml)
[![Gemini CLI E2E](https://github.com/google-gemini/gemini-cli/actions/workflows/e2e.yml/badge.svg)](https://github.com/google-gemini/gemini-cli/actions/workflows/e2e.yml)
[![Version](https://img.shields.io/npm/v/@google/gemini-cli)](https://www.npmjs.com/package/@google/gemini-cli)
[![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)
![Gemini CLI Screenshot](./docs/assets/gemini-screenshot.png)
@@ -18,8 +17,7 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
- **🎯 Free tier**: 60 requests/min and 1,000 requests/day with personal Google
account.
- **🧠 Powerful Gemini 3 models**: Access to improved reasoning and 1M token
context window.
- **🧠 Powerful Gemini 2.5 Pro**: Access to 1M token context window.
- **🔧 Built-in tools**: Google Search grounding, file operations, shell
commands, web fetching.
- **🔌 Extensible**: MCP (Model Context Protocol) support for custom
@@ -29,9 +27,10 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
## 📦 Installation
See
[Gemini CLI installation, execution, and releases](./docs/get-started/installation.md)
for recommended system specifications and a detailed installation guide.
### Pre-requisites before installation
- Node.js version 20 or higher
- macOS, Linux, or Windows
### Quick Install
@@ -39,7 +38,7 @@ for recommended system specifications and a detailed installation guide.
```bash
# Using npx (no installation required)
npx @google/gemini-cli
npx https://github.com/google-gemini/gemini-cli
```
#### Install globally with npm
@@ -54,23 +53,6 @@ npm install -g @google/gemini-cli
brew install gemini-cli
```
#### Install globally with MacPorts (macOS)
```bash
sudo port install gemini-cli
```
#### Install with Anaconda (for restricted environments)
```bash
# Create and activate a new environment
conda create -y -n gemini_env -c conda-forge nodejs
conda activate gemini_env
# Install Gemini CLI globally via npm (inside the environment)
npm install -g @google/gemini-cli
```
## Release Cadence and Tags
See [Releases](./docs/releases.md) for more details.
@@ -97,9 +79,9 @@ npm install -g @google/gemini-cli@latest
### Nightly
- 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
there are pending validations and issues. Use `nightly` tag.
- New releases will be published each week at UTC 0000 each day, This will be
all changes from the main branch as represented at time of release. It should
be assumed there are pending validations and issues. Use `nightly` tag.
```bash
npm install -g @google/gemini-cli@nightly
@@ -157,7 +139,7 @@ for details)
**Benefits:**
- **Free tier**: 60 requests/min and 1,000 requests/day
- **Gemini 3 models** with 1M token context window
- **Gemini 2.5 Pro** with 1M token context window
- **No API key management** - just sign in with your Google account
- **Automatic updates** to latest models
@@ -181,7 +163,7 @@ gemini
**Benefits:**
- **Free tier**: 1000 requests/day with Gemini 3 (mix of flash and pro)
- **Free tier**: 100 requests/day with Gemini 2.5 Pro
- **Model selection**: Choose specific Gemini models
- **Usage-based billing**: Upgrade for higher limits when needed
@@ -382,7 +364,7 @@ See the [Uninstall Guide](docs/cli/uninstall.md) for removal instructions.
## 📄 Legal
- **License**: [Apache License 2.0](LICENSE)
- **Terms of Service**: [Terms & Privacy](./docs/resources/tos-privacy.md)
- **Terms of Service**: [Terms & Privacy](./docs/tos-privacy.md)
- **Security**: [Security Policy](SECURITY.md)
---
-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.md)
- History management
- Display rendering
- [Theme and UI customization](/docs/cli/themes.md)
- [CLI configuration settings](/docs/get-started/configuration.md)
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: 60 KiB

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

+12 -381
View File
@@ -1,378 +1,9 @@
# Gemini CLI release notes
# Gemini CLI Changelog
Gemini CLI has three major release channels: nightly, preview, and stable. For
most users, we recommend the stable release.
Wondering what's new in Gemini CLI? This document provides key highlights and
notable changes to Gemini CLI.
On this page, you can find information regarding the current releases and
announcements from each release.
For the full changelog, refer to
[Releases - google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli/releases)
on GitHub.
## Current releases
| Release channel | Notes |
| :-------------------- | :---------------------------------------------- |
| Nightly | Nightly release with the most recent changes. |
| [Preview](preview.md) | Experimental features ready for early feedback. |
| [Stable](latest.md) | Stable, recommended for general use. |
## 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
- **Agents and Skills:** We've introduced a new `skill-creator` skill
([#16394](https://github.com/google-gemini/gemini-cli/pull/16394) by
@NTaylorMullen), enabled agent skills by default, and added a generalist agent
to improve task routing
([#16638](https://github.com/google-gemini/gemini-cli/pull/16638) by
@joshualitt).
- **UI/UX Improvements:** You can now "Rewind" through your conversation history
([#15717](https://github.com/google-gemini/gemini-cli/pull/15717) by @Adib234)
and use a new `/introspect` command for debugging.
- **Core and Scheduler Refactoring:** The core scheduler has been significantly
refactored to improve performance and reliability
([#16895](https://github.com/google-gemini/gemini-cli/pull/16895) by
@abhipatel12), and numerous performance and stability fixes have been
included.
## Announcements: v0.25.0 - 2026-01-20
- **Skills and Agents Improvements:** We've enhanced the `activate_skill` tool,
added a new `pr-creator` skill
([#16232](https://github.com/google-gemini/gemini-cli/pull/16232) by
[@NTaylorMullen](https://github.com/NTaylorMullen)), enabled skills by
default, improved the `cli_help` agent
([#16100](https://github.com/google-gemini/gemini-cli/pull/16100) by
[@scidomino](https://github.com/scidomino)), and added a new `/agents refresh`
command ([#16204](https://github.com/google-gemini/gemini-cli/pull/16204) by
[@joshualitt](https://github.com/joshualitt)).
- **UI/UX Refinements:** You'll notice more transparent feedback for skills
([#15954](https://github.com/google-gemini/gemini-cli/pull/15954) by
[@NTaylorMullen](https://github.com/NTaylorMullen)), the ability to switch
focus between the shell and input with Tab
([#14332](https://github.com/google-gemini/gemini-cli/pull/14332) by
[@jacob314](https://github.com/jacob314)), and dynamic terminal tab titles
([#16378](https://github.com/google-gemini/gemini-cli/pull/16378) by
[@NTaylorMullen](https://github.com/NTaylorMullen)).
- **Core Functionality & Performance:** This release includes support for
built-in agent skills
([#16045](https://github.com/google-gemini/gemini-cli/pull/16045) by
[@NTaylorMullen](https://github.com/NTaylorMullen)), refined Gemini 3 system
instructions ([#16139](https://github.com/google-gemini/gemini-cli/pull/16139)
by [@NTaylorMullen](https://github.com/NTaylorMullen)), caching for ignore
instances to improve performance
([#16185](https://github.com/google-gemini/gemini-cli/pull/16185) by
[@EricRahm](https://github.com/EricRahm)), and enhanced retry mechanisms
([#16489](https://github.com/google-gemini/gemini-cli/pull/16489) by
[@sehoon38](https://github.com/sehoon38)).
- **Bug Fixes and Stability:** We've squashed numerous bugs across the CLI,
core, and workflows, addressing issues with subagent delegation, unicode
character crashes, and sticky header regressions.
## Announcements: v0.24.0 - 2026-01-14
- **Agent Skills:** We've introduced significant advancements in Agent Skills.
This includes initial documentation and tutorials to help you get started,
alongside enhanced support for remote agents, allowing for more distributed
and powerful automation within Gemini CLI.
([#15869](https://github.com/google-gemini/gemini-cli/pull/15869) by
[@NTaylorMullen](https://github.com/NTaylorMullen)),
([#16013](https://github.com/google-gemini/gemini-cli/pull/16013) by
[@adamweidman](https://github.com/adamweidman))
- **Improved UI/UX:** The user interface has received several updates, featuring
visual indicators for hook execution, a more refined display for settings, and
the ability to use the Tab key to effortlessly switch focus between the shell
and input areas.
([#15408](https://github.com/google-gemini/gemini-cli/pull/15408) by
[@abhipatel12](https://github.com/abhipatel12)),
([#14332](https://github.com/google-gemini/gemini-cli/pull/14332) by
[@galz10](https://github.com/galz10))
- **Enhanced Security:** Security has been a major focus, with default folder
trust now set to untrusted for increased safety. The Policy Engine has been
improved to allow specific modes in user and administrator policies, and
granular allowlisting for shell commands has been implemented, providing finer
control over tool execution.
([#15943](https://github.com/google-gemini/gemini-cli/pull/15943) by
[@galz10](https://github.com/galz10)),
([#15977](https://github.com/google-gemini/gemini-cli/pull/15977) by
[@NTaylorMullen](https://github.com/NTaylorMullen))
- **Core Functionality:** This release includes a mandatory MessageBus
injection, marking Phase 3 of a hard migration to a more robust internal
communication system. We've also added support for built-in skills with the
CLI itself, and enhanced model routing to effectively utilize subagents.
([#15776](https://github.com/google-gemini/gemini-cli/pull/15776) by
[@abhipatel12](https://github.com/abhipatel12)),
([#16300](https://github.com/google-gemini/gemini-cli/pull/16300) by
[@NTaylorMullen](https://github.com/NTaylorMullen))
- **Terminal Features:** Terminal interactions are more seamless with new
features like OSC 52 paste support, along with fixes for Windows clipboard
paste issues and general improvements to pasting in Windows terminals.
([#15336](https://github.com/google-gemini/gemini-cli/pull/15336) by
[@scidomino](https://github.com/scidomino)),
([#15932](https://github.com/google-gemini/gemini-cli/pull/15932) by
[@scidomino](https://github.com/scidomino))
- **New Commands:** To manage the new features, we've added several new
commands: `/agents refresh` to update agent configurations, `/skills reload`
to refresh skill definitions, and `/skills install/uninstall` for easier
management of your Agent Skills.
([#16204](https://github.com/google-gemini/gemini-cli/pull/16204) by
[@NTaylorMullen](https://github.com/NTaylorMullen)),
([#15865](https://github.com/google-gemini/gemini-cli/pull/15865) by
[@NTaylorMullen](https://github.com/NTaylorMullen)),
([#16377](https://github.com/google-gemini/gemini-cli/pull/16377) by
[@NTaylorMullen](https://github.com/NTaylorMullen))
## Announcements: v0.23.0 - 2026-01-07
- 🎉 **Experimental Agent Skills Support in Preview:** Gemini CLI now supports
[Agent Skills](https://agentskills.io/home) in our preview builds. This is an
early preview where were looking for feedback!
- Install Preview: `npm install -g @google/gemini-cli@preview`
- Enable in `/settings`
- Docs:
[https://geminicli.com/docs/cli/skills/](https://geminicli.com/docs/cli/skills/)
- **Gemini CLI wrapped:** Run `npx gemini-wrapped` to visualize your usage
stats, top models, languages, and more!
- **Windows clipboard image support:** Windows users can now paste images
directly from their clipboard into the CLI using `Alt`+`V`.
([pr](https://github.com/google-gemini/gemini-cli/pull/13997) by
[@sgeraldes](https://github.com/sgeraldes))
- **Terminal background color detection:** Automatically optimizes your
terminal's background color to select compatible themes and provide
accessibility warnings.
([pr](https://github.com/google-gemini/gemini-cli/pull/15132) by
[@jacob314](https://github.com/jacob314))
- **Session logout:** Use the new `/logout` command to instantly clear
credentials and reset your authentication state for seamless account
switching. ([pr](https://github.com/google-gemini/gemini-cli/pull/13383) by
[@CN-Scars](https://github.com/CN-Scars))
## Announcements: v0.22.0 - 2025-12-22
- 🎉**Free Tier + Gemini 3:** Free tier users now all have access to Gemini 3
Pro & Flash. Enable in `/settings` by toggling "Preview Features" to `true`.
- 🎉**Gemini CLI + Colab:** Gemini CLI is now pre-installed. Can be used
headlessly in notebook cells or interactively in the built-in terminal
([pic](https://imgur.com/a/G0Tn7vi))
- 🎉**Gemini CLI Extensions:**
- **Conductor:** Planning++, Gemini works with you to build out a detailed
plan, pull in extra details as needed, ultimately to give the LLM guardrails
with artifacts. Measure twice, implement once!
`gemini extensions install https://github.com/gemini-cli-extensions/conductor`
Blog:
[https://developers.googleblog.com/conductor-introducing-context-driven-development-for-gemini-cli/](https://developers.googleblog.com/conductor-introducing-context-driven-development-for-gemini-cli/)
- **Endor Labs:** Perform code analysis, vulnerability scanning, and
dependency checks using natural language.
`gemini extensions install https://github.com/endorlabs/gemini-extension`
## Announcements: v0.21.0 - 2025-12-15
- **⚡️⚡️⚡️ Gemini 3 Flash + Gemini CLI:** Better, faster and cheaper than 2.5
Pro - and in some scenarios better than 3 Pro! For paid tiers + free tier
users who were on the wait list enable **Preview Features** in `/settings.`
- For more information:
[Gemini 3 Flash is now available in Gemini CLI](https://developers.googleblog.com/gemini-3-flash-is-now-available-in-gemini-cli/).
- 🎉 Gemini CLI Extensions:
- Rill: Utilize natural language to analyze Rill data, enabling the
exploration of metrics and trends without the need for manual queries.
`gemini extensions install https://github.com/rilldata/rill-gemini-extension`
- Browserbase: Interact with web pages, take screenshots, extract information,
and perform automated actions with atomic precision.
`gemini extensions install https://github.com/browserbase/mcp-server-browserbase`
- Quota Visibility: The `/stats` command now displays quota information for all
available models, including those not used in the current session. (@sehoon38)
- Fuzzy Setting Search: Users can now quickly find settings using fuzzy search
within the settings dialog. (@sehoon38)
- MCP Resource Support: Users can now discover, view, and search through
resources using the @ command. (@MrLesk)
- Auto-execute Simple Slash Commands: Simple slash commands are now executed
immediately on enter. (@jackwotherspoon)
## Announcements: v0.20.0 - 2025-12-01
- **Multi-file Drag & Drop:** Users can now drag and drop multiple files into
the terminal, and the CLI will automatically prefix each valid path with `@`.
([pr](https://github.com/google-gemini/gemini-cli/pull/14832) by
[@jackwotherspoon](https://github.com/jackwotherspoon))
- **Persistent "Always Allow" Policies:** Users can now save "Always Allow"
decisions for tool executions, with granular control over specific shell
commands and multi-cloud platform tools.
([pr](https://github.com/google-gemini/gemini-cli/pull/14737) by
[@allenhutchison](https://github.com/allenhutchison))
## Announcements: v0.19.0 - 2025-11-24
- 🎉 **New extensions:**
- **Eleven Labs:** Create, play, manage your audio play tracks with the Eleven
Labs Gemini CLI extension:
`gemini extensions install https://github.com/elevenlabs/elevenlabs-mcp`
- **Zed integration:** Users can now leverage Gemini 3 within the Zed
integration after enabling "Preview Features" in their CLIs `/settings`.
([pr](https://github.com/google-gemini/gemini-cli/pull/13398) by
[@benbrandt](https://github.com/benbrandt))
- **Interactive shell:**
- **Click-to-Focus:** When "Use Alternate Buffer" setting is enabled, users
can click within the embedded shell output to focus it for input.
([pr](https://github.com/google-gemini/gemini-cli/pull/13341) by
[@galz10](https://github.com/galz10))
- **Loading phrase:** Clearly indicates when the interactive shell is awaiting
user input. ([vid](https://imgur.com/a/kjK8bUK),
[pr](https://github.com/google-gemini/gemini-cli/pull/12535) by
[@jackwotherspoon](https://github.com/jackwotherspoon))
## Announcements: v0.18.0 - 2025-11-17
- 🎉 **New extensions:**
- **Google Workspace**: Integrate Gemini CLI with your Workspace data. Write
docs, build slides, chat with others or even get your calc on in sheets:
`gemini extensions install https://github.com/gemini-cli-extensions/workspace`
- Blog:
[https://allen.hutchison.org/2025/11/19/bringing-the-office-to-the-terminal/](https://allen.hutchison.org/2025/11/19/bringing-the-office-to-the-terminal/)
- **Redis:** Manage and search data in Redis with natural language:
`gemini extensions install https://github.com/redis/mcp-redis`
- **Anomalo:** Query your data warehouse table metadata and quality status
through commands and natural language:
`gemini extensions install https://github.com/datagravity-ai/anomalo-gemini-extension`
- **Experimental permission improvements:** We are now experimenting with a new
policy engine in Gemini CLI. This allows users and administrators to create
fine-grained policy for tool calls. Currently behind a flag. See
[policy engine documentation](../reference/policy-engine.md) for more
information.
- Blog:
[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
key, Google AI Pro or Google AI Ultra (for individuals, not businesses) and
Gemini Code Assist Enterprise users. Enable it via `/settings` and toggling on
**Preview Features**.
- **Updated UI rollback:** Weve temporarily rolled back our updated UI to give
it more time to bake. This means for a time you wont have embedded scrolling
or mouse support. You can re-enable with `/settings` -> **Use Alternate Screen
Buffer** -> `true`.
- **Model in history:** Users can now toggle in `/settings` to display model in
their chat history. ([gif](https://imgur.com/a/uEmNKnQ),
[pr](https://github.com/google-gemini/gemini-cli/pull/13034) by
[@scidomino](https://github.com/scidomino))
- **Multi-uninstall:** Users can now uninstall multiple extensions with a single
command. ([pic](https://imgur.com/a/9Dtq8u2),
[pr](https://github.com/google-gemini/gemini-cli/pull/13016) by
[@JayadityaGit](https://github.com/JayadityaGit))
## Announcements: v0.16.0 - 2025-11-10
- **Gemini 3 + Gemini CLI:** launch 🚀🚀🚀
- **Data Commons Gemini CLI Extension** - A new Data Commons Gemini CLI
extension that lets you query open-source statistical data from
datacommons.org. **To get started, you'll need a Data Commons API key and uv
installed**. These and other details to get you started with the extension can
be found at
[https://github.com/gemini-cli-extensions/datacommons](https://github.com/gemini-cli-extensions/datacommons).
## Announcements: v0.15.0 - 2025-11-03
- **🎉 Seamless scrollable UI and mouse support:** Weve given Gemini CLI a
major facelift to make your terminal experience smoother and much more
polished. You now get a flicker-free display with sticky headers that keep
important context visible and a stable input prompt that doesn't jump around.
We even added mouse support so you can click right where you need to type!
([gif](https://imgur.com/a/O6qc7bx),
[@jacob314](https://github.com/jacob314)).
- **Announcement:**
[https://developers.googleblog.com/en/making-the-terminal-beautiful-one-pixel-at-a-time/](https://developers.googleblog.com/en/making-the-terminal-beautiful-one-pixel-at-a-time/)
- **🎉 New partner extensions:**
- **Arize:** Seamlessly instrument AI applications with Arize AX and grant
direct access to Arize support:
`gemini extensions install https://github.com/Arize-ai/arize-tracing-assistant`
- **Chronosphere:** Retrieve logs, metrics, traces, events, and specific
entities:
`gemini extensions install https://github.com/chronosphereio/chronosphere-mcp`
- **Transmit:** Comprehensive context, validation, and automated fixes for
creating production-ready authentication and identity workflows:
`gemini extensions install https://github.com/TransmitSecurity/transmit-security-journey-builder`
- **Todo planning:** Complex questions now get broken down into todo lists that
the model can manage and check off. ([gif](https://imgur.com/a/EGDfNlZ),
[pr](https://github.com/google-gemini/gemini-cli/pull/12905) by
[@anj-s](https://github.com/anj-s))
- **Disable GitHub extensions:** Users can now prevent the installation and
loading of extensions from GitHub.
([pr](https://github.com/google-gemini/gemini-cli/pull/12838) by
[@kevinjwang1](https://github.com/kevinjwang1)).
- **Extensions restart:** Users can now explicitly restart extensions using the
`/extensions restart` command.
([pr](https://github.com/google-gemini/gemini-cli/pull/12739) by
[@jakemac53](https://github.com/jakemac53)).
- **Better Angular support:** Angular workflows should now be more seamless
([pr](https://github.com/google-gemini/gemini-cli/pull/10252) by
[@MarkTechson](https://github.com/MarkTechson)).
- **Validate command:** Users can now check that local extensions are formatted
correctly. ([pr](https://github.com/google-gemini/gemini-cli/pull/12186) by
[@kevinjwang1](https://github.com/kevinjwang1)).
## Announcements: v0.12.0 - 2025-10-27
## v0.12.0 - Gemini CLI weekly update - 2025-10-27
![Codebase investigator subagent in Gemini CLI.](https://i.imgur.com/4J1njsx.png)
@@ -435,7 +66,7 @@ on GitHub.
([pr](https://github.com/google-gemini/gemini-cli/pull/11593) by
[@joshualitt](https://github.com/joshualitt)).
## Announcements: v0.11.0 - 2025-10-20
## v0.11.0 - Gemini CLI weekly update - 2025-10-20
![Gemini CLI and Jules](https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/Jules_Extension_-_Blog_Header_O346JNt.original.png)
@@ -478,7 +109,7 @@ on GitHub.
([pr](https://github.com/google-gemini/gemini-cli/pull/11318) by
[@allenhutchison](https://github.com/allenhutchison))
## Announcements: v0.10.0 - 2025-10-13
## v0.10.0 - Gemini CLI weekly update - 2025-10-13
- **Polish:** The team has been heads down bug fixing and investing heavily into
polishing existing flows, tools, and interactions.
@@ -495,7 +126,7 @@ on GitHub.
([pr](https://github.com/google-gemini/gemini-cli/pull/10819) by
[@jerop](https://github.com/jerop)).
## Announcements: v0.9.0 - 2025-10-06
## v0.9.0 - Gemini CLI weekly update - 2025-10-06
- 🎉 **Interactive Shell:** Run interactive commands like `vim`, `rebase -i`, or
even `gemini` 😎 directly in Gemini CLI:
@@ -520,7 +151,7 @@ on GitHub.
([pr](https://github.com/google-gemini/gemini-cli/pull/10108) by
[@sgnagnarella](https://github.com/sgnagnarella))
## Announcements: v0.8.0 - 2025-09-29
## v0.8.0 - Gemini CLI weekly update - 2025-09-29
- 🎉 **Announcing Gemini CLI Extensions** 🎉
- Completely customize your Gemini CLI experience to fit your workflow.
@@ -559,7 +190,7 @@ on GitHub.
changes, smaller features, UI updates, reliability and bug fixes + general
polish made it in this week!
## Announcements: v0.7.0 - 2025-09-22
## v0.7.0 - Gemini CLI weekly update - 2025-09-22
- 🎉**Build your own Gemini CLI IDE plugin:** We've published a spec for
creating IDE plugins to enable rich context-aware experiences and native
@@ -597,7 +228,7 @@ on GitHub.
changes, smaller features, UI updates, reliability and bug fixes + general
polish made it in this week!
## Announcements: v0.6.0 - 2025-09-15
## v0.6.0 - Gemini CLI weekly update - 2025-09-15
- 🎉 **Higher limits for Google AI Pro and Ultra subscribers:** Were psyched to
finally announce that Google AI Pro and AI Ultra subscribers now get access to
@@ -678,7 +309,7 @@ on GitHub.
changes, smaller features, UI updates, reliability and bug fixes + general
polish made it in this week!
## Announcements: v0.5.0 - 2025-09-08
## v0.5.0 - Gemini CLI weekly update - 2025-09-08
- 🎉**FastMCP + Gemini CLI**🎉: Quickly install and manage your Gemini CLI MCP
servers with FastMCP ([video](https://imgur.com/a/m8QdCPh),
@@ -723,7 +354,7 @@ on GitHub.
changes, smaller features, UI updates, reliability and bug fixes + general
polish made it in this week!
## Announcements: v0.4.0 - 2025-09-01
## v0.4.0 - Gemini CLI weekly update - 2025-09-01
- 🎉**Gemini CLI CloudRun and Security Integrations**🎉: Automate app deployment
and security analysis with CloudRun and Security extension integrations. Once
-381
View File
@@ -1,381 +0,0 @@
# Latest stable release: v0.29.0
Released: February 17, 2026
For most users, our latest stable release is the recommended release. Install
the latest stable version with:
```
npm install -g @google/gemini-cli
```
## Highlights
- **Plan Mode:** Introduce a dedicated "Plan Mode" to help you architect complex
changes before implementation. Use `/plan` to get started.
- **Gemini 3 by Default:** Gemini 3 is now the default model family, bringing
improved performance and reasoning capabilities to all users without needing a
feature flag.
- **Extension Discovery:** Easily discover and install extensions with the new
exploration features and registry client.
- **Enhanced Admin Controls:** New administrative capabilities allow for
allowlisting MCP server configurations, giving organizations more control over
available tools.
- **Sub-agent Improvements:** Sub-agents have been transitioned to a new format
with improved definitions and system prompts for better reliability.
## What's Changed
- fix: remove `ask_user` tool from non-interactive modes by @jackwotherspoon in
[#18154](https://github.com/google-gemini/gemini-cli/pull/18154)
- fix(cli): allow restricted .env loading in untrusted sandboxed folders by
@galz10 in [#17806](https://github.com/google-gemini/gemini-cli/pull/17806)
- Encourage agent to utilize ecosystem tools to perform work by @gundermanc in
[#17881](https://github.com/google-gemini/gemini-cli/pull/17881)
- feat(plan): unify workflow location in system prompt to optimize caching by
@jerop in [#18258](https://github.com/google-gemini/gemini-cli/pull/18258)
- feat(core): enable getUserTierName in config by @sehoon38 in
[#18265](https://github.com/google-gemini/gemini-cli/pull/18265)
- feat(core): add default execution limits for subagents by @abhipatel12 in
[#18274](https://github.com/google-gemini/gemini-cli/pull/18274)
- Fix issue where agent gets stuck at interactive commands. by @gundermanc in
[#18272](https://github.com/google-gemini/gemini-cli/pull/18272)
- chore(release): bump version to 0.29.0-nightly.20260203.71f46f116 by
@gemini-cli-robot in
[#18243](https://github.com/google-gemini/gemini-cli/pull/18243)
- feat(core): remove hardcoded policy bypass for local subagents by @abhipatel12
in [#18153](https://github.com/google-gemini/gemini-cli/pull/18153)
- feat(plan): implement `plan` slash command by @Adib234 in
[#17698](https://github.com/google-gemini/gemini-cli/pull/17698)
- feat: increase `ask_user` label limit to 16 characters by @jackwotherspoon in
[#18320](https://github.com/google-gemini/gemini-cli/pull/18320)
- Add information about the agent skills lifecycle and clarify docs-writer skill
metadata. by @g-samroberts in
[#18234](https://github.com/google-gemini/gemini-cli/pull/18234)
- feat(core): add `enter_plan_mode` tool by @jerop in
[#18324](https://github.com/google-gemini/gemini-cli/pull/18324)
- Stop showing an error message in `/plan` by @Adib234 in
[#18333](https://github.com/google-gemini/gemini-cli/pull/18333)
- fix(hooks): remove unnecessary logging for hook registration by @abhipatel12
in [#18332](https://github.com/google-gemini/gemini-cli/pull/18332)
- fix(mcp): ensure MCP transport is closed to prevent memory leaks by
@cbcoutinho in
[#18054](https://github.com/google-gemini/gemini-cli/pull/18054)
- feat(skills): implement linking for agent skills by @MushuEE in
[#18295](https://github.com/google-gemini/gemini-cli/pull/18295)
- Changelogs for 0.27.0 and 0.28.0-preview0 by @g-samroberts in
[#18336](https://github.com/google-gemini/gemini-cli/pull/18336)
- chore: correct docs as skills and hooks are stable by @jackwotherspoon in
[#18358](https://github.com/google-gemini/gemini-cli/pull/18358)
- feat(admin): Implement admin allowlist for MCP server configurations by
@skeshive in [#18311](https://github.com/google-gemini/gemini-cli/pull/18311)
- fix(core): add retry logic for transient SSL/TLS errors (#17318) by @ppgranger
in [#18310](https://github.com/google-gemini/gemini-cli/pull/18310)
- Add support for /extensions config command by @chrstnb in
[#17895](https://github.com/google-gemini/gemini-cli/pull/17895)
- fix(core): handle non-compliant mcpbridge responses from Xcode 26.3 by
@peterfriese in
[#18376](https://github.com/google-gemini/gemini-cli/pull/18376)
- feat(cli): Add W, B, E Vim motions and operator support by @ademuri in
[#16209](https://github.com/google-gemini/gemini-cli/pull/16209)
- fix: Windows Specific Agent Quality & System Prompt by @scidomino in
[#18351](https://github.com/google-gemini/gemini-cli/pull/18351)
- feat(plan): support `replace` tool in plan mode to edit plans by @jerop in
[#18379](https://github.com/google-gemini/gemini-cli/pull/18379)
- Improving memory tool instructions and eval testing by @alisa-alisa in
[#18091](https://github.com/google-gemini/gemini-cli/pull/18091)
- fix(cli): color extension link success message green by @MushuEE in
[#18386](https://github.com/google-gemini/gemini-cli/pull/18386)
- undo by @jacob314 in
[#18147](https://github.com/google-gemini/gemini-cli/pull/18147)
- feat(plan): add guidance on iterating on approved plans vs creating new plans
by @jerop in [#18346](https://github.com/google-gemini/gemini-cli/pull/18346)
- feat(plan): fix invalid tool calls in plan mode by @Adib234 in
[#18352](https://github.com/google-gemini/gemini-cli/pull/18352)
- feat(plan): integrate planning artifacts and tools into primary workflows by
@jerop in [#18375](https://github.com/google-gemini/gemini-cli/pull/18375)
- Fix permission check by @scidomino in
[#18395](https://github.com/google-gemini/gemini-cli/pull/18395)
- ux(polish) autocomplete in the input prompt by @jacob314 in
[#18181](https://github.com/google-gemini/gemini-cli/pull/18181)
- fix: resolve infinite loop when using 'Modify with external editor' by
@ppgranger in [#17453](https://github.com/google-gemini/gemini-cli/pull/17453)
- feat: expand verify-release to macOS and Windows by @yunaseoul in
[#18145](https://github.com/google-gemini/gemini-cli/pull/18145)
- feat(plan): implement support for MCP servers in Plan mode by @Adib234 in
[#18229](https://github.com/google-gemini/gemini-cli/pull/18229)
- chore: update folder trust error messaging by @galz10 in
[#18402](https://github.com/google-gemini/gemini-cli/pull/18402)
- feat(plan): create a metric for execution of plans generated in plan mode by
@Adib234 in [#18236](https://github.com/google-gemini/gemini-cli/pull/18236)
- perf(ui): optimize stripUnsafeCharacters with regex by @gsquared94 in
[#18413](https://github.com/google-gemini/gemini-cli/pull/18413)
- feat(context): implement observation masking for tool outputs by @abhipatel12
in [#18389](https://github.com/google-gemini/gemini-cli/pull/18389)
- feat(core,cli): implement session-linked tool output storage and cleanup by
@abhipatel12 in
[#18416](https://github.com/google-gemini/gemini-cli/pull/18416)
- Shorten temp directory by @joshualitt in
[#17901](https://github.com/google-gemini/gemini-cli/pull/17901)
- feat(plan): add behavioral evals for plan mode by @jerop in
[#18437](https://github.com/google-gemini/gemini-cli/pull/18437)
- Add extension registry client by @chrstnb in
[#18396](https://github.com/google-gemini/gemini-cli/pull/18396)
- Enable extension config by default by @chrstnb in
[#18447](https://github.com/google-gemini/gemini-cli/pull/18447)
- Automatically generate change logs on release by @g-samroberts in
[#18401](https://github.com/google-gemini/gemini-cli/pull/18401)
- Remove previewFeatures and default to Gemini 3 by @sehoon38 in
[#18414](https://github.com/google-gemini/gemini-cli/pull/18414)
- feat(admin): apply MCP allowlist to extensions & gemini mcp list command by
@skeshive in [#18442](https://github.com/google-gemini/gemini-cli/pull/18442)
- fix(cli): improve focus navigation for interactive and background shells by
@galz10 in [#18343](https://github.com/google-gemini/gemini-cli/pull/18343)
- Add shortcuts hint and panel for discoverability by @LyalinDotCom in
[#18035](https://github.com/google-gemini/gemini-cli/pull/18035)
- fix(config): treat system settings as read-only during migration and warn user
by @spencer426 in
[#18277](https://github.com/google-gemini/gemini-cli/pull/18277)
- feat(plan): add positive test case and update eval stability policy by @jerop
in [#18457](https://github.com/google-gemini/gemini-cli/pull/18457)
- fix- windows: add shell: true for spawnSync to fix EINVAL with .cmd editors by
@zackoch in [#18408](https://github.com/google-gemini/gemini-cli/pull/18408)
- bug(core): Fix bug when saving plans. by @joshualitt in
[#18465](https://github.com/google-gemini/gemini-cli/pull/18465)
- Refactor atCommandProcessor by @scidomino in
[#18461](https://github.com/google-gemini/gemini-cli/pull/18461)
- feat(core): implement persistence and resumption for masked tool outputs by
@abhipatel12 in
[#18451](https://github.com/google-gemini/gemini-cli/pull/18451)
- refactor: simplify tool output truncation to single config by @SandyTao520 in
[#18446](https://github.com/google-gemini/gemini-cli/pull/18446)
- bug(core): Ensure storage is initialized early, even if config is not. by
@joshualitt in
[#18471](https://github.com/google-gemini/gemini-cli/pull/18471)
- chore: Update build-and-start script to support argument forwarding by
@Abhijit-2592 in
[#18241](https://github.com/google-gemini/gemini-cli/pull/18241)
- fix(core): prevent subagent bypass in plan mode by @jerop in
[#18484](https://github.com/google-gemini/gemini-cli/pull/18484)
- feat(cli): add WebSocket-based network logging and streaming chunk support by
@SandyTao520 in
[#18383](https://github.com/google-gemini/gemini-cli/pull/18383)
- feat(cli): update approval modes UI by @jerop in
[#18476](https://github.com/google-gemini/gemini-cli/pull/18476)
- fix(cli): reload skills and agents on extension restart by @NTaylorMullen in
[#18411](https://github.com/google-gemini/gemini-cli/pull/18411)
- fix(core): expand excludeTools with legacy aliases for renamed tools by
@SandyTao520 in
[#18498](https://github.com/google-gemini/gemini-cli/pull/18498)
- feat(core): overhaul system prompt for rigor, integrity, and intent alignment
by @NTaylorMullen in
[#17263](https://github.com/google-gemini/gemini-cli/pull/17263)
- Patch for generate changelog docs yaml file by @g-samroberts in
[#18496](https://github.com/google-gemini/gemini-cli/pull/18496)
- Code review fixes for show question mark pr. by @jacob314 in
[#18480](https://github.com/google-gemini/gemini-cli/pull/18480)
- fix(cli): add SS3 Shift+Tab support for Windows terminals by @ThanhNguyxn in
[#18187](https://github.com/google-gemini/gemini-cli/pull/18187)
- chore: remove redundant planning prompt from final shell by @jerop in
[#18528](https://github.com/google-gemini/gemini-cli/pull/18528)
- docs: require pr-creator skill for PR generation by @NTaylorMullen in
[#18536](https://github.com/google-gemini/gemini-cli/pull/18536)
- chore: update colors for ask_user dialog by @jackwotherspoon in
[#18543](https://github.com/google-gemini/gemini-cli/pull/18543)
- feat(core): exempt high-signal tools from output masking by @abhipatel12 in
[#18545](https://github.com/google-gemini/gemini-cli/pull/18545)
- refactor(core): remove memory tool instructions from Gemini 3 prompt by
@NTaylorMullen in
[#18559](https://github.com/google-gemini/gemini-cli/pull/18559)
- chore: remove feedback instruction from system prompt by @NTaylorMullen in
[#18560](https://github.com/google-gemini/gemini-cli/pull/18560)
- feat(context): add remote configuration for tool output masking thresholds by
@abhipatel12 in
[#18553](https://github.com/google-gemini/gemini-cli/pull/18553)
- feat(core): pause agent timeout budget while waiting for tool confirmation by
@abhipatel12 in
[#18415](https://github.com/google-gemini/gemini-cli/pull/18415)
- refactor(config): remove experimental.enableEventDrivenScheduler setting by
@abhipatel12 in
[#17924](https://github.com/google-gemini/gemini-cli/pull/17924)
- feat(cli): truncate shell output in UI history and improve active shell
display by @jwhelangoog in
[#17438](https://github.com/google-gemini/gemini-cli/pull/17438)
- refactor(cli): switch useToolScheduler to event-driven engine by @abhipatel12
in [#18565](https://github.com/google-gemini/gemini-cli/pull/18565)
- fix(core): correct escaped interpolation in system prompt by @NTaylorMullen in
[#18557](https://github.com/google-gemini/gemini-cli/pull/18557)
- propagate abortSignal by @scidomino in
[#18477](https://github.com/google-gemini/gemini-cli/pull/18477)
- feat(core): conditionally include ctrl+f prompt based on interactive shell
setting by @NTaylorMullen in
[#18561](https://github.com/google-gemini/gemini-cli/pull/18561)
- fix(core): ensure `enter_plan_mode` tool registration respects
`experimental.plan` by @jerop in
[#18587](https://github.com/google-gemini/gemini-cli/pull/18587)
- feat(core): transition sub-agents to XML format and improve definitions by
@NTaylorMullen in
[#18555](https://github.com/google-gemini/gemini-cli/pull/18555)
- docs: Add Plan Mode documentation by @jerop in
[#18582](https://github.com/google-gemini/gemini-cli/pull/18582)
- chore: strengthen validation guidance in system prompt by @NTaylorMullen in
[#18544](https://github.com/google-gemini/gemini-cli/pull/18544)
- Fix newline insertion bug in replace tool by @werdnum in
[#18595](https://github.com/google-gemini/gemini-cli/pull/18595)
- fix(evals): update save_memory evals and simplify tool description by
@NTaylorMullen in
[#18610](https://github.com/google-gemini/gemini-cli/pull/18610)
- chore(evals): update validation_fidelity_pre_existing_errors to USUALLY_PASSES
by @NTaylorMullen in
[#18617](https://github.com/google-gemini/gemini-cli/pull/18617)
- fix: shorten tool call IDs and fix duplicate tool name in truncated output
filenames by @SandyTao520 in
[#18600](https://github.com/google-gemini/gemini-cli/pull/18600)
- feat(cli): implement atomic writes and safety checks for trusted folders by
@galz10 in [#18406](https://github.com/google-gemini/gemini-cli/pull/18406)
- Remove relative docs links by @chrstnb in
[#18650](https://github.com/google-gemini/gemini-cli/pull/18650)
- docs: add legacy snippets convention to GEMINI.md by @NTaylorMullen in
[#18597](https://github.com/google-gemini/gemini-cli/pull/18597)
- fix(chore): Support linting for cjs by @aswinashok44 in
[#18639](https://github.com/google-gemini/gemini-cli/pull/18639)
- feat: move shell efficiency guidelines to tool description by @NTaylorMullen
in [#18614](https://github.com/google-gemini/gemini-cli/pull/18614)
- Added "" as default value, since getText() used to expect a string only and
thus crashed when undefined... Fixes #18076 by @019-Abhi in
[#18099](https://github.com/google-gemini/gemini-cli/pull/18099)
- Allow @-includes outside of workspaces (with permission) by @scidomino in
[#18470](https://github.com/google-gemini/gemini-cli/pull/18470)
- chore: make `ask_user` header description more clear by @jackwotherspoon in
[#18657](https://github.com/google-gemini/gemini-cli/pull/18657)
- refactor(core): model-dependent tool definitions by @aishaneeshah in
[#18563](https://github.com/google-gemini/gemini-cli/pull/18563)
- Harded code assist converter. by @jacob314 in
[#18656](https://github.com/google-gemini/gemini-cli/pull/18656)
- bug(core): Fix minor bug in migration logic. by @joshualitt in
[#18661](https://github.com/google-gemini/gemini-cli/pull/18661)
- feat: enable plan mode experiment in settings by @jerop in
[#18636](https://github.com/google-gemini/gemini-cli/pull/18636)
- refactor: push isValidPath() into parsePastedPaths() by @scidomino in
[#18664](https://github.com/google-gemini/gemini-cli/pull/18664)
- fix(cli): correct 'esc to cancel' position and restore duration display by
@NTaylorMullen in
[#18534](https://github.com/google-gemini/gemini-cli/pull/18534)
- feat(cli): add DevTools integration with gemini-cli-devtools by @SandyTao520
in [#18648](https://github.com/google-gemini/gemini-cli/pull/18648)
- chore: remove unused exports and redundant hook files by @SandyTao520 in
[#18681](https://github.com/google-gemini/gemini-cli/pull/18681)
- Fix number of lines being reported in rewind confirmation dialog by @Adib234
in [#18675](https://github.com/google-gemini/gemini-cli/pull/18675)
- feat(cli): disable folder trust in headless mode by @galz10 in
[#18407](https://github.com/google-gemini/gemini-cli/pull/18407)
- Disallow unsafe type assertions by @gundermanc in
[#18688](https://github.com/google-gemini/gemini-cli/pull/18688)
- Change event type for release by @g-samroberts in
[#18693](https://github.com/google-gemini/gemini-cli/pull/18693)
- feat: handle multiple dynamic context filenames in system prompt by
@NTaylorMullen in
[#18598](https://github.com/google-gemini/gemini-cli/pull/18598)
- Properly parse at-commands with narrow non-breaking spaces by @scidomino in
[#18677](https://github.com/google-gemini/gemini-cli/pull/18677)
- refactor(core): centralize core tool definitions and support model-specific
schemas by @aishaneeshah in
[#18662](https://github.com/google-gemini/gemini-cli/pull/18662)
- feat(core): Render memory hierarchically in context. by @joshualitt in
[#18350](https://github.com/google-gemini/gemini-cli/pull/18350)
- feat: Ctrl+O to expand paste placeholder by @jackwotherspoon in
[#18103](https://github.com/google-gemini/gemini-cli/pull/18103)
- fix(cli): Improve header spacing by @NTaylorMullen in
[#18531](https://github.com/google-gemini/gemini-cli/pull/18531)
- Feature/quota visibility 16795 by @spencer426 in
[#18203](https://github.com/google-gemini/gemini-cli/pull/18203)
- Inline thinking bubbles with summary/full modes by @LyalinDotCom in
[#18033](https://github.com/google-gemini/gemini-cli/pull/18033)
- docs: remove TOC marker from Plan Mode header by @jerop in
[#18678](https://github.com/google-gemini/gemini-cli/pull/18678)
- fix(ui): remove redundant newlines in Gemini messages by @NTaylorMullen in
[#18538](https://github.com/google-gemini/gemini-cli/pull/18538)
- test(cli): fix AppContainer act() warnings and improve waitFor resilience by
@NTaylorMullen in
[#18676](https://github.com/google-gemini/gemini-cli/pull/18676)
- refactor(core): refine Security & System Integrity section in system prompt by
@NTaylorMullen in
[#18601](https://github.com/google-gemini/gemini-cli/pull/18601)
- Fix layout rounding. by @gundermanc in
[#18667](https://github.com/google-gemini/gemini-cli/pull/18667)
- docs(skills): enhance pr-creator safety and interactivity by @NTaylorMullen in
[#18616](https://github.com/google-gemini/gemini-cli/pull/18616)
- test(core): remove hardcoded model from TestRig by @NTaylorMullen in
[#18710](https://github.com/google-gemini/gemini-cli/pull/18710)
- feat(core): optimize sub-agents system prompt intro by @NTaylorMullen in
[#18608](https://github.com/google-gemini/gemini-cli/pull/18608)
- feat(cli): update approval mode labels and shortcuts per latest UX spec by
@jerop in [#18698](https://github.com/google-gemini/gemini-cli/pull/18698)
- fix(plan): update persistent approval mode setting by @Adib234 in
[#18638](https://github.com/google-gemini/gemini-cli/pull/18638)
- fix: move toasts location to left side by @jackwotherspoon in
[#18705](https://github.com/google-gemini/gemini-cli/pull/18705)
- feat(routing): restrict numerical routing to Gemini 3 family by @mattKorwel in
[#18478](https://github.com/google-gemini/gemini-cli/pull/18478)
- fix(ide): fix ide nudge setting by @skeshive in
[#18733](https://github.com/google-gemini/gemini-cli/pull/18733)
- fix(core): standardize tool formatting in system prompts by @NTaylorMullen in
[#18615](https://github.com/google-gemini/gemini-cli/pull/18615)
- chore: consolidate to green in ask user dialog by @jackwotherspoon in
[#18734](https://github.com/google-gemini/gemini-cli/pull/18734)
- feat: add `extensionsExplore` setting to enable extensions explore UI. by
@sripasg in [#18686](https://github.com/google-gemini/gemini-cli/pull/18686)
- feat(cli): defer devtools startup and integrate with F12 by @SandyTao520 in
[#18695](https://github.com/google-gemini/gemini-cli/pull/18695)
- ui: update & subdue footer colors and animate progress indicator by
@keithguerin in
[#18570](https://github.com/google-gemini/gemini-cli/pull/18570)
- test: add model-specific snapshots for coreTools by @aishaneeshah in
[#18707](https://github.com/google-gemini/gemini-cli/pull/18707)
- ci: shard windows tests and fix event listener leaks by @NTaylorMullen in
[#18670](https://github.com/google-gemini/gemini-cli/pull/18670)
- fix: allow `ask_user` tool in yolo mode by @jackwotherspoon in
[#18541](https://github.com/google-gemini/gemini-cli/pull/18541)
- feat: redact disabled tools from system prompt (#13597) by @NTaylorMullen in
[#18613](https://github.com/google-gemini/gemini-cli/pull/18613)
- Update Gemini.md to use the curent year on creating new files by @sehoon38 in
[#18460](https://github.com/google-gemini/gemini-cli/pull/18460)
- Code review cleanup for thinking display by @jacob314 in
[#18720](https://github.com/google-gemini/gemini-cli/pull/18720)
- fix(cli): hide scrollbars when in alternate buffer copy mode by @werdnum in
[#18354](https://github.com/google-gemini/gemini-cli/pull/18354)
- Fix issues with rip grep by @gundermanc in
[#18756](https://github.com/google-gemini/gemini-cli/pull/18756)
- fix(cli): fix history navigation regression after prompt autocomplete by
@sehoon38 in [#18752](https://github.com/google-gemini/gemini-cli/pull/18752)
- chore: cleanup unused and add unlisted dependencies in packages/cli by
@adamfweidman in
[#18749](https://github.com/google-gemini/gemini-cli/pull/18749)
- Fix issue where Gemini CLI creates tests in a new file by @gundermanc in
[#18409](https://github.com/google-gemini/gemini-cli/pull/18409)
- feat(telemetry): Ensure experiment IDs are included in OpenTelemetry logs by
@kevin-ramdass in
[#18747](https://github.com/google-gemini/gemini-cli/pull/18747)
- fix(patch): cherry-pick e9a9474 to release/v0.29.0-preview.0-pr-18840 to patch
version v0.29.0-preview.0 and create version 0.29.0-preview.1 by
@gemini-cli-robot in
[#18841](https://github.com/google-gemini/gemini-cli/pull/18841)
- fix(patch): cherry-pick 08e8eea to release/v0.29.0-preview.1-pr-18855 to patch
version v0.29.0-preview.1 and create version 0.29.0-preview.2 by
@gemini-cli-robot in
[#18905](https://github.com/google-gemini/gemini-cli/pull/18905)
- fix(patch): cherry-pick d0c6a56 to release/v0.29.0-preview.2-pr-18976 to patch
version v0.29.0-preview.2 and create version 0.29.0-preview.3 by
@gemini-cli-robot in
[#19023](https://github.com/google-gemini/gemini-cli/pull/19023)
- fix(patch): cherry-pick e5ff202 to release/v0.29.0-preview.3-pr-19254 to patch
version v0.29.0-preview.3 and create version 0.29.0-preview.4 by
@gemini-cli-robot in
[#19264](https://github.com/google-gemini/gemini-cli/pull/19264)
- fix(patch): cherry-pick 9590a09 to release/v0.29.0-preview.4-pr-18771 to patch
version v0.29.0-preview.4 and create version 0.29.0-preview.5 by
@gemini-cli-robot in
[#19274](https://github.com/google-gemini/gemini-cli/pull/19274)
**Full Changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.28.2...v0.29.0
-318
View File
@@ -1,318 +0,0 @@
# Preview release: v0.30.0-preview.5
Released: February 24, 2026
Our preview release includes the latest, new, and experimental features. This
release may not be as stable as our [latest weekly release](latest.md).
To install the preview release:
```
npm install -g @google/gemini-cli@preview
```
## Highlights
- **Initial SDK Package:** Introduced the initial SDK package with support for
custom skills and dynamic system instructions.
- **Refined Plan Mode:** Refined Plan Mode with support for enabling skills,
improved agentic execution, and project exploration without planning.
- **Enhanced CLI UI:** Enhanced CLI UI with a new clean UI toggle, minimal-mode
bleed-through, and support for Ctrl-Z suspension.
- **`--policy` flag:** Added the `--policy` flag to support user-defined
policies.
- **New Themes:** Added Solarized Dark and Solarized Light themes.
## What's Changed
- fix(patch): cherry-pick 2c1d6f8 to release/v0.30.0-preview.4-pr-19369 to patch
version v0.30.0-preview.4 and create version 0.30.0-preview.5 by
@gemini-cli-robot in
[#20086](https://github.com/google-gemini/gemini-cli/pull/20086)
- fix(patch): cherry-pick 261788c to release/v0.30.0-preview.0-pr-19453 to patch
version v0.30.0-preview.0 and create version 0.30.0-preview.1 by
@gemini-cli-robot in
[#19490](https://github.com/google-gemini/gemini-cli/pull/19490)
- feat(ux): added text wrapping capabilities to markdown tables by @devr0306 in
[#18240](https://github.com/google-gemini/gemini-cli/pull/18240)
- Revert "fix(mcp): ensure MCP transport is closed to prevent memory leaks" by
@skeshive in [#18771](https://github.com/google-gemini/gemini-cli/pull/18771)
- chore(release): bump version to 0.30.0-nightly.20260210.a2174751d by
@gemini-cli-robot in
[#18772](https://github.com/google-gemini/gemini-cli/pull/18772)
- chore: cleanup unused and add unlisted dependencies in packages/core by
@adamfweidman in
[#18762](https://github.com/google-gemini/gemini-cli/pull/18762)
- chore(core): update activate_skill prompt verbiage to be more direct by
@NTaylorMullen in
[#18605](https://github.com/google-gemini/gemini-cli/pull/18605)
- Add autoconfigure memory usage setting to the dialog by @jacob314 in
[#18510](https://github.com/google-gemini/gemini-cli/pull/18510)
- fix(core): prevent race condition in policy persistence by @braddux in
[#18506](https://github.com/google-gemini/gemini-cli/pull/18506)
- fix(evals): prevent false positive in hierarchical memory test by
@Abhijit-2592 in
[#18777](https://github.com/google-gemini/gemini-cli/pull/18777)
- test(evals): mark all `save_memory` evals as `USUALLY_PASSES` due to
unreliability by @jerop in
[#18786](https://github.com/google-gemini/gemini-cli/pull/18786)
- feat(cli): add setting to hide shortcuts hint UI by @LyalinDotCom in
[#18562](https://github.com/google-gemini/gemini-cli/pull/18562)
- feat(core): formalize 5-phase sequential planning workflow by @jerop in
[#18759](https://github.com/google-gemini/gemini-cli/pull/18759)
- Introduce limits for search results. by @gundermanc in
[#18767](https://github.com/google-gemini/gemini-cli/pull/18767)
- fix(cli): allow closing debug console after auto-open via flicker by
@SandyTao520 in
[#18795](https://github.com/google-gemini/gemini-cli/pull/18795)
- feat(masking): enable tool output masking by default by @abhipatel12 in
[#18564](https://github.com/google-gemini/gemini-cli/pull/18564)
- perf(ui): optimize table rendering by memoizing styled characters by @devr0306
in [#18770](https://github.com/google-gemini/gemini-cli/pull/18770)
- feat: multi-line text answers in ask-user tool by @jackwotherspoon in
[#18741](https://github.com/google-gemini/gemini-cli/pull/18741)
- perf(cli): truncate large debug logs and limit message history by @mattKorwel
in [#18663](https://github.com/google-gemini/gemini-cli/pull/18663)
- fix(core): complete MCP discovery when configured servers are skipped by
@LyalinDotCom in
[#18586](https://github.com/google-gemini/gemini-cli/pull/18586)
- fix(core): cache CLI version to ensure consistency during sessions by
@sehoon38 in [#18793](https://github.com/google-gemini/gemini-cli/pull/18793)
- fix(cli): resolve double rendering in shpool and address vscode lint warnings
by @braddux in
[#18704](https://github.com/google-gemini/gemini-cli/pull/18704)
- feat(plan): document and validate Plan Mode policy overrides by @jerop in
[#18825](https://github.com/google-gemini/gemini-cli/pull/18825)
- Fix pressing any key to exit select mode. by @jacob314 in
[#18421](https://github.com/google-gemini/gemini-cli/pull/18421)
- fix(cli): update F12 behavior to only open drawer if browser fails by
@SandyTao520 in
[#18829](https://github.com/google-gemini/gemini-cli/pull/18829)
- feat(plan): allow skills to be enabled in plan mode by @Adib234 in
[#18817](https://github.com/google-gemini/gemini-cli/pull/18817)
- docs(plan): add documentation for plan mode tools by @jerop in
[#18827](https://github.com/google-gemini/gemini-cli/pull/18827)
- Remove experimental note in extension settings docs by @chrstnb in
[#18822](https://github.com/google-gemini/gemini-cli/pull/18822)
- Update prompt and grep tool definition to limit context size by @gundermanc in
[#18780](https://github.com/google-gemini/gemini-cli/pull/18780)
- docs(plan): add `ask_user` tool documentation by @jerop in
[#18830](https://github.com/google-gemini/gemini-cli/pull/18830)
- Revert unintended credentials exposure by @Adib234 in
[#18840](https://github.com/google-gemini/gemini-cli/pull/18840)
- feat(core): update internal utility models to Gemini 3 by @SandyTao520 in
[#18773](https://github.com/google-gemini/gemini-cli/pull/18773)
- feat(a2a): add value-resolver for auth credential resolution by @adamfweidman
in [#18653](https://github.com/google-gemini/gemini-cli/pull/18653)
- Removed getPlainTextLength by @devr0306 in
[#18848](https://github.com/google-gemini/gemini-cli/pull/18848)
- More grep prompt tweaks by @gundermanc in
[#18846](https://github.com/google-gemini/gemini-cli/pull/18846)
- refactor(cli): Reactive useSettingsStore hook by @psinha40898 in
[#14915](https://github.com/google-gemini/gemini-cli/pull/14915)
- fix(mcp): Ensure that stdio MCP server execution has the `GEMINI_CLI=1` env
variable populated. by @richieforeman in
[#18832](https://github.com/google-gemini/gemini-cli/pull/18832)
- fix(core): improve headless mode detection for flags and query args by @galz10
in [#18855](https://github.com/google-gemini/gemini-cli/pull/18855)
- refactor(cli): simplify UI and remove legacy inline tool confirmation logic by
@abhipatel12 in
[#18566](https://github.com/google-gemini/gemini-cli/pull/18566)
- feat(cli): deprecate --allowed-tools and excludeTools in favor of policy
engine by @Abhijit-2592 in
[#18508](https://github.com/google-gemini/gemini-cli/pull/18508)
- fix(workflows): improve maintainer detection for automated PR actions by
@bdmorgan in [#18869](https://github.com/google-gemini/gemini-cli/pull/18869)
- refactor(cli): consolidate useToolScheduler and delete legacy implementation
by @abhipatel12 in
[#18567](https://github.com/google-gemini/gemini-cli/pull/18567)
- Update changelog for v0.28.0 and v0.29.0-preview0 by @g-samroberts in
[#18819](https://github.com/google-gemini/gemini-cli/pull/18819)
- fix(core): ensure sub-agents are registered regardless of tools.allowed by
@mattKorwel in
[#18870](https://github.com/google-gemini/gemini-cli/pull/18870)
- Show notification when there's a conflict with an extensions command by
@chrstnb in [#17890](https://github.com/google-gemini/gemini-cli/pull/17890)
- fix(cli): dismiss '?' shortcuts help on hotkeys and active states by
@LyalinDotCom in
[#18583](https://github.com/google-gemini/gemini-cli/pull/18583)
- fix(core): prioritize conditional policy rules and harden Plan Mode by
@Abhijit-2592 in
[#18882](https://github.com/google-gemini/gemini-cli/pull/18882)
- feat(core): refine Plan Mode system prompt for agentic execution by
@NTaylorMullen in
[#18799](https://github.com/google-gemini/gemini-cli/pull/18799)
- feat(plan): create metrics for usage of `AskUser` tool by @Adib234 in
[#18820](https://github.com/google-gemini/gemini-cli/pull/18820)
- feat(cli): support Ctrl-Z suspension by @scidomino in
[#18931](https://github.com/google-gemini/gemini-cli/pull/18931)
- fix(github-actions): use robot PAT for release creation to trigger release
notes by @SandyTao520 in
[#18794](https://github.com/google-gemini/gemini-cli/pull/18794)
- feat: add strict seatbelt profiles and remove unusable closed profiles by
@SandyTao520 in
[#18876](https://github.com/google-gemini/gemini-cli/pull/18876)
- chore: cleanup unused and add unlisted dependencies in packages/a2a-server by
@adamfweidman in
[#18916](https://github.com/google-gemini/gemini-cli/pull/18916)
- fix(plan): isolate plan files per session by @Adib234 in
[#18757](https://github.com/google-gemini/gemini-cli/pull/18757)
- fix: character truncation in raw markdown mode by @jackwotherspoon in
[#18938](https://github.com/google-gemini/gemini-cli/pull/18938)
- feat(cli): prototype clean UI toggle and minimal-mode bleed-through by
@LyalinDotCom in
[#18683](https://github.com/google-gemini/gemini-cli/pull/18683)
- ui(polish) blend background color with theme by @jacob314 in
[#18802](https://github.com/google-gemini/gemini-cli/pull/18802)
- Add generic searchable list to back settings and extensions by @chrstnb in
[#18838](https://github.com/google-gemini/gemini-cli/pull/18838)
- feat(ui): align `AskUser` color scheme with UX spec by @jerop in
[#18943](https://github.com/google-gemini/gemini-cli/pull/18943)
- Hide AskUser tool validation errors from UI (agent self-corrects) by @jerop in
[#18954](https://github.com/google-gemini/gemini-cli/pull/18954)
- bug(cli) fix flicker due to AppContainer continuous initialization by
@jacob314 in [#18958](https://github.com/google-gemini/gemini-cli/pull/18958)
- feat(admin): Add admin controls documentation by @skeshive in
[#18644](https://github.com/google-gemini/gemini-cli/pull/18644)
- feat(cli): disable ctrl-s shortcut outside of alternate buffer mode by
@jacob314 in [#18887](https://github.com/google-gemini/gemini-cli/pull/18887)
- fix(vim): vim support that feels (more) complete by @ppgranger in
[#18755](https://github.com/google-gemini/gemini-cli/pull/18755)
- feat(policy): add --policy flag for user defined policies by @allenhutchison
in [#18500](https://github.com/google-gemini/gemini-cli/pull/18500)
- Update installation guide by @g-samroberts in
[#18823](https://github.com/google-gemini/gemini-cli/pull/18823)
- refactor(core): centralize tool definitions (Group 1: replace, search, grep)
by @aishaneeshah in
[#18944](https://github.com/google-gemini/gemini-cli/pull/18944)
- refactor(cli): finalize event-driven transition and remove interaction bridge
by @abhipatel12 in
[#18569](https://github.com/google-gemini/gemini-cli/pull/18569)
- Fix drag and drop escaping by @scidomino in
[#18965](https://github.com/google-gemini/gemini-cli/pull/18965)
- feat(sdk): initial package bootstrap for SDK by @mbleigh in
[#18861](https://github.com/google-gemini/gemini-cli/pull/18861)
- feat(sdk): implements SessionContext for SDK tool calls by @mbleigh in
[#18862](https://github.com/google-gemini/gemini-cli/pull/18862)
- fix(plan): make question type required in AskUser tool by @Adib234 in
[#18959](https://github.com/google-gemini/gemini-cli/pull/18959)
- fix(core): ensure --yolo does not force headless mode by @NTaylorMullen in
[#18976](https://github.com/google-gemini/gemini-cli/pull/18976)
- refactor(core): adopt `CoreToolCallStatus` enum for type safety by @jerop in
[#18998](https://github.com/google-gemini/gemini-cli/pull/18998)
- Enable in-CLI extension management commands for team by @chrstnb in
[#18957](https://github.com/google-gemini/gemini-cli/pull/18957)
- Adjust lint rules to avoid unnecessary warning. by @scidomino in
[#18970](https://github.com/google-gemini/gemini-cli/pull/18970)
- fix(vscode): resolve unsafe type assertion lint errors by @ehedlund in
[#19006](https://github.com/google-gemini/gemini-cli/pull/19006)
- Remove unnecessary eslint config file by @scidomino in
[#19015](https://github.com/google-gemini/gemini-cli/pull/19015)
- fix(core): Prevent loop detection false positives on lists with long shared
prefixes by @SandyTao520 in
[#18975](https://github.com/google-gemini/gemini-cli/pull/18975)
- feat(core): fallback to chat-base when using unrecognized models for chat by
@SandyTao520 in
[#19016](https://github.com/google-gemini/gemini-cli/pull/19016)
- docs: fix inconsistent commandRegex example in policy engine by @NTaylorMullen
in [#19027](https://github.com/google-gemini/gemini-cli/pull/19027)
- fix(plan): persist the approval mode in UI even when agent is thinking by
@Adib234 in [#18955](https://github.com/google-gemini/gemini-cli/pull/18955)
- feat(sdk): Implement dynamic system instructions by @mbleigh in
[#18863](https://github.com/google-gemini/gemini-cli/pull/18863)
- Docs: Refresh docs to organize and standardize reference materials. by
@jkcinouye in [#18403](https://github.com/google-gemini/gemini-cli/pull/18403)
- fix windows escaping (and broken tests) by @scidomino in
[#19011](https://github.com/google-gemini/gemini-cli/pull/19011)
- refactor: use `CoreToolCallStatus` in the the history data model by @jerop in
[#19033](https://github.com/google-gemini/gemini-cli/pull/19033)
- feat(cleanup): enable 30-day session retention by default by @skeshive in
[#18854](https://github.com/google-gemini/gemini-cli/pull/18854)
- feat(plan): hide plan write and edit operations on plans in Plan Mode by
@jerop in [#19012](https://github.com/google-gemini/gemini-cli/pull/19012)
- bug(ui) fix flicker refreshing background color by @jacob314 in
[#19041](https://github.com/google-gemini/gemini-cli/pull/19041)
- chore: fix dep vulnerabilities by @scidomino in
[#19036](https://github.com/google-gemini/gemini-cli/pull/19036)
- Revamp automated changelog skill by @g-samroberts in
[#18974](https://github.com/google-gemini/gemini-cli/pull/18974)
- feat(sdk): implement support for custom skills by @mbleigh in
[#19031](https://github.com/google-gemini/gemini-cli/pull/19031)
- refactor(core): complete centralization of core tool definitions by
@aishaneeshah in
[#18991](https://github.com/google-gemini/gemini-cli/pull/18991)
- feat: add /commands reload to refresh custom TOML commands by @korade-krushna
in [#19078](https://github.com/google-gemini/gemini-cli/pull/19078)
- fix(cli): wrap terminal capability queries in hidden sequence by @srithreepo
in [#19080](https://github.com/google-gemini/gemini-cli/pull/19080)
- fix(workflows): fix GitHub App token permissions for maintainer detection by
@bdmorgan in [#19139](https://github.com/google-gemini/gemini-cli/pull/19139)
- test: fix hook integration test flakiness on Windows CI by @NTaylorMullen in
[#18665](https://github.com/google-gemini/gemini-cli/pull/18665)
- fix(core): Encourage non-interactive flags for scaffolding commands by
@NTaylorMullen in
[#18804](https://github.com/google-gemini/gemini-cli/pull/18804)
- fix(core): propagate User-Agent header to setup-phase CodeAssist API calls by
@gsquared94 in
[#19182](https://github.com/google-gemini/gemini-cli/pull/19182)
- docs: document .agents/skills alias and discovery precedence by @kevmoo in
[#19166](https://github.com/google-gemini/gemini-cli/pull/19166)
- feat(cli): add loading state to new agents notification by @sehoon38 in
[#19190](https://github.com/google-gemini/gemini-cli/pull/19190)
- Add base branch to workflow. by @g-samroberts in
[#19189](https://github.com/google-gemini/gemini-cli/pull/19189)
- feat(cli): handle invalid model names in useQuotaAndFallback by @sehoon38 in
[#19222](https://github.com/google-gemini/gemini-cli/pull/19222)
- docs: custom themes in extensions by @jackwotherspoon in
[#19219](https://github.com/google-gemini/gemini-cli/pull/19219)
- Disable workspace settings when starting GCLI in the home directory. by
@kevinjwang1 in
[#19034](https://github.com/google-gemini/gemini-cli/pull/19034)
- feat(cli): refactor model command to support set and manage subcommands by
@sehoon38 in [#19221](https://github.com/google-gemini/gemini-cli/pull/19221)
- Add refresh/reload aliases to slash command subcommands by @korade-krushna in
[#19218](https://github.com/google-gemini/gemini-cli/pull/19218)
- refactor: consolidate development rules and add cli guidelines by @jacob314 in
[#19214](https://github.com/google-gemini/gemini-cli/pull/19214)
- chore(ui): remove outdated tip about model routing by @sehoon38 in
[#19226](https://github.com/google-gemini/gemini-cli/pull/19226)
- feat(core): support custom reasoning models by default by @NTaylorMullen in
[#19227](https://github.com/google-gemini/gemini-cli/pull/19227)
- Add Solarized Dark and Solarized Light themes by @rmedranollamas in
[#19064](https://github.com/google-gemini/gemini-cli/pull/19064)
- fix(telemetry): replace JSON.stringify with safeJsonStringify in file
exporters by @gsquared94 in
[#19244](https://github.com/google-gemini/gemini-cli/pull/19244)
- feat(telemetry): add keychain availability and token storage metrics by
@abhipatel12 in
[#18971](https://github.com/google-gemini/gemini-cli/pull/18971)
- feat(cli): update approval mode cycle order by @jerop in
[#19254](https://github.com/google-gemini/gemini-cli/pull/19254)
- refactor(cli): code review cleanup fix for tab+tab by @jacob314 in
[#18967](https://github.com/google-gemini/gemini-cli/pull/18967)
- feat(plan): support project exploration without planning when in plan mode by
@Adib234 in [#18992](https://github.com/google-gemini/gemini-cli/pull/18992)
- feat: add role-specific statistics to telemetry and UI (cont. #15234) by
@yunaseoul in [#18824](https://github.com/google-gemini/gemini-cli/pull/18824)
- feat(cli): remove Plan Mode from rotation when actively working by @jerop in
[#19262](https://github.com/google-gemini/gemini-cli/pull/19262)
- Fix side breakage where anchors don't work in slugs. by @g-samroberts in
[#19261](https://github.com/google-gemini/gemini-cli/pull/19261)
- feat(config): add setting to make directory tree context configurable by
@kevin-ramdass in
[#19053](https://github.com/google-gemini/gemini-cli/pull/19053)
- fix(acp): Wait for mcp initialization in acp (#18893) by @Mervap in
[#18894](https://github.com/google-gemini/gemini-cli/pull/18894)
- docs: format UTC times in releases doc by @pavan-sh in
[#18169](https://github.com/google-gemini/gemini-cli/pull/18169)
- Docs: Clarify extensions documentation. by @jkcinouye in
[#19277](https://github.com/google-gemini/gemini-cli/pull/19277)
- refactor(core): modularize tool definitions by model family by @aishaneeshah
in [#19269](https://github.com/google-gemini/gemini-cli/pull/19269)
- fix(paths): Add cross-platform path normalization by @spencer426 in
[#18939](https://github.com/google-gemini/gemini-cli/pull/18939)
- feat(core): experimental in-progress steering hints (1 of 3) by @joshualitt in
[#19008](https://github.com/google-gemini/gemini-cli/pull/19008)
**Full changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.29.0-preview.5...v0.30.0-preview.5
+3
View File
@@ -0,0 +1,3 @@
# Authentication Setup
See: [Getting Started - Authentication Setup](../get-started/authentication.md).
+26 -15
View File
@@ -2,22 +2,23 @@
The Gemini CLI includes a Checkpointing feature that automatically saves a
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,
knowing you can instantly revert back to the state before the tool was run.
AI-powered tools. This allows you to safely experiment with and apply code
changes, knowing you can instantly revert back to the state before the tool was
run.
## How it works
## How It Works
When you approve a tool that modifies the file system (like `write_file` or
`replace`), the CLI automatically creates a "checkpoint." This checkpoint
includes:
1. **A Git snapshot:** A commit is made in a special, shadow Git repository
1. **A Git Snapshot:** A commit is made in a special, shadow Git repository
located in your home directory (`~/.gemini/history/<project_hash>`). This
snapshot captures the complete state of your project files at that moment.
It does **not** interfere with your own project's Git repository.
2. **Conversation history:** The entire conversation you've had with the agent
2. **Conversation History:** The entire conversation you've had with the agent
up to that point is saved.
3. **The tool call:** The specific tool call that was about to be executed is
3. **The Tool Call:** The specific tool call that was about to be executed is
also stored.
If you want to undo the change or simply go back, you can use the `/restore`
@@ -34,14 +35,24 @@ repository while the conversation history and tool calls are saved in a JSON
file in your project's temporary directory, typically located at
`~/.gemini/tmp/<project_hash>/checkpoints`.
## Enabling the feature
## Enabling the Feature
The Checkpointing feature is disabled by default. To enable it, you need to edit
your `settings.json` file.
The Checkpointing feature is disabled by default. To enable it, you can either
use a command-line flag or edit your `settings.json` file.
> **Note:** The `--checkpointing` command-line flag was removed in version
> 0.11.0. Checkpointing can now only be enabled through the `settings.json`
> configuration file.
### Using the Command-Line Flag
You can enable checkpointing for the current session by using the
`--checkpointing` flag when starting the Gemini CLI:
```bash
gemini --checkpointing
```
### Using the `settings.json` File
To enable checkpointing by default for all sessions, you need to edit your
`settings.json` file.
Add the following key to your `settings.json`:
@@ -55,12 +66,12 @@ Add the following key to your `settings.json`:
}
```
## Using the `/restore` command
## Using the `/restore` Command
Once enabled, checkpoints are created automatically. To manage them, you use the
`/restore` command.
### List available checkpoints
### List Available Checkpoints
To see a list of all saved checkpoints for the current project, simply run:
@@ -73,7 +84,7 @@ typically composed of a timestamp, the name of the file being modified, and the
name of the tool that was about to be run (e.g.,
`2025-06-22T10-00-00_000Z-my-file.txt-write_file`).
### Restore a specific checkpoint
### Restore a Specific Checkpoint
To restore your project to a specific checkpoint, use the checkpoint file from
the list:
-115
View File
@@ -1,115 +0,0 @@
# Gemini CLI cheatsheet
This page provides a reference for commonly used Gemini CLI commands, options,
and parameters.
## CLI commands
| Command | Description | Example |
| ---------------------------------- | ---------------------------------- | --------------------------------------------------- |
| `gemini` | Start interactive REPL | `gemini` |
| `gemini "query"` | Query non-interactively, then exit | `gemini "explain this project"` |
| `cat file \| gemini` | Process piped content | `cat logs.txt \| gemini` |
| `gemini -i "query"` | Execute and continue interactively | `gemini -i "What is the purpose of this project?"` |
| `gemini -r "latest"` | Continue most recent session | `gemini -r "latest"` |
| `gemini -r "latest" "query"` | Continue session with a new prompt | `gemini -r "latest" "Check for type errors"` |
| `gemini -r "<session-id>" "query"` | Resume session by ID | `gemini -r "abc123" "Finish this PR"` |
| `gemini update` | Update to latest version | `gemini update` |
| `gemini extensions` | Manage extensions | See [Extensions Management](#extensions-management) |
| `gemini mcp` | Configure MCP servers | See [MCP Server Management](#mcp-server-management) |
### Positional arguments
| Argument | Type | Description |
| -------- | ----------------- | ------------------------------------------------------------------------------------------------------------------ |
| `query` | string (variadic) | Positional prompt. Defaults to one-shot mode. Use `-i/--prompt-interactive` to execute and continue interactively. |
## CLI Options
| Option | Alias | Type | Default | Description |
| -------------------------------- | ----- | ------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--debug` | `-d` | boolean | `false` | Run in debug mode with verbose logging |
| `--version` | `-v` | - | - | Show CLI version number and exit |
| `--help` | `-h` | - | - | Show help information |
| `--model` | `-m` | string | `auto` | Model to use. See [Model Selection](#model-selection) for available values. |
| `--prompt` | `-p` | string | - | Prompt text. Appended to stdin input if provided. **Deprecated:** Use positional arguments instead. |
| `--prompt-interactive` | `-i` | string | - | Execute prompt and continue in interactive mode |
| `--sandbox` | `-s` | boolean | `false` | Run in a sandboxed environment for safer execution |
| `--approval-mode` | - | string | `default` | Approval mode for tool execution. Choices: `default`, `auto_edit`, `yolo` |
| `--yolo` | `-y` | boolean | `false` | **Deprecated.** Auto-approve all actions. Use `--approval-mode=yolo` instead. |
| `--experimental-acp` | - | boolean | - | Start in ACP (Agent Code Pilot) mode. **Experimental feature.** |
| `--experimental-zed-integration` | - | boolean | - | Run in Zed editor integration mode. **Experimental feature.** |
| `--allowed-mcp-server-names` | - | array | - | Allowed MCP server names (comma-separated or multiple flags) |
| `--allowed-tools` | - | array | - | **Deprecated.** Use the [Policy Engine](../reference/policy-engine.md) instead. Tools that are allowed to run without confirmation (comma-separated or multiple flags) |
| `--extensions` | `-e` | array | - | List of extensions to use. If not provided, all extensions are enabled (comma-separated or multiple flags) |
| `--list-extensions` | `-l` | boolean | - | List all available extensions and exit |
| `--resume` | `-r` | string | - | Resume a previous session. Use `"latest"` for most recent or index number (e.g. `--resume 5`) |
| `--list-sessions` | - | boolean | - | List available sessions for the current project and exit |
| `--delete-session` | - | string | - | Delete a session by index number (use `--list-sessions` to see available sessions) |
| `--include-directories` | - | array | - | Additional directories to include in the workspace (comma-separated or multiple flags) |
| `--screen-reader` | - | boolean | - | Enable screen reader mode for accessibility |
| `--output-format` | `-o` | string | `text` | The format of the CLI output. Choices: `text`, `json`, `stream-json` |
## Model selection
The `--model` (or `-m`) flag lets you specify which Gemini model to use. You can
use either model aliases (user-friendly names) or concrete model names.
### Model aliases
These are convenient shortcuts that map to specific models:
| Alias | Resolves To | Description |
| ------------ | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `auto` | `gemini-2.5-pro` or `gemini-3-pro-preview` | **Default.** Resolves to the preview model if preview features are enabled, otherwise resolves to the standard pro model. |
| `pro` | `gemini-2.5-pro` or `gemini-3-pro-preview` | For complex reasoning tasks. Uses preview model if enabled. |
| `flash` | `gemini-2.5-flash` | Fast, balanced model for most tasks. |
| `flash-lite` | `gemini-2.5-flash-lite` | Fastest model for simple tasks. |
## Extensions management
| Command | Description | Example |
| -------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
| `gemini extensions install <source>` | Install extension from Git URL or local path | `gemini extensions install https://github.com/user/my-extension` |
| `gemini extensions install <source> --ref <ref>` | Install from specific branch/tag/commit | `gemini extensions install https://github.com/user/my-extension --ref develop` |
| `gemini extensions install <source> --auto-update` | Install with auto-update enabled | `gemini extensions install https://github.com/user/my-extension --auto-update` |
| `gemini extensions uninstall <name>` | Uninstall one or more extensions | `gemini extensions uninstall my-extension` |
| `gemini extensions list` | List all installed extensions | `gemini extensions list` |
| `gemini extensions update <name>` | Update a specific extension | `gemini extensions update my-extension` |
| `gemini extensions update --all` | Update all extensions | `gemini extensions update --all` |
| `gemini extensions enable <name>` | Enable an extension | `gemini extensions enable my-extension` |
| `gemini extensions disable <name>` | Disable an extension | `gemini extensions disable my-extension` |
| `gemini extensions link <path>` | Link local extension for development | `gemini extensions link /path/to/extension` |
| `gemini extensions new <path>` | Create new extension from template | `gemini extensions new ./my-extension` |
| `gemini extensions validate <path>` | Validate extension structure | `gemini extensions validate ./my-extension` |
See [Extensions Documentation](../extensions/index.md) for more details.
## MCP server management
| Command | Description | Example |
| ------------------------------------------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `gemini mcp add <name> <command>` | Add stdio-based MCP server | `gemini mcp add github npx -y @modelcontextprotocol/server-github` |
| `gemini mcp add <name> <url> --transport http` | Add HTTP-based MCP server | `gemini mcp add api-server http://localhost:3000 --transport http` |
| `gemini mcp add <name> <command> --env KEY=value` | Add with environment variables | `gemini mcp add slack node server.js --env SLACK_TOKEN=xoxb-xxx` |
| `gemini mcp add <name> <command> --scope user` | Add with user scope | `gemini mcp add db node db-server.js --scope user` |
| `gemini mcp add <name> <command> --include-tools tool1,tool2` | Add with specific tools | `gemini mcp add github npx -y @modelcontextprotocol/server-github --include-tools list_repos,get_pr` |
| `gemini mcp remove <name>` | Remove an MCP server | `gemini mcp remove github` |
| `gemini mcp list` | List all configured MCP servers | `gemini mcp list` |
See [MCP Server Integration](../tools/mcp-server.md) for more details.
## Skills management
| Command | Description | Example |
| -------------------------------- | ------------------------------------- | ------------------------------------------------- |
| `gemini skills list` | List all discovered agent skills | `gemini skills list` |
| `gemini skills install <source>` | Install skill from Git, path, or file | `gemini skills install https://github.com/u/repo` |
| `gemini skills link <path>` | Link local agent skills via symlink | `gemini skills link /path/to/my-skills` |
| `gemini skills uninstall <name>` | Uninstall an agent skill | `gemini skills uninstall my-skill` |
| `gemini skills enable <name>` | Enable an agent skill | `gemini skills enable my-skill` |
| `gemini skills disable <name>` | Disable an agent skill | `gemini skills disable my-skill` |
| `gemini skills enable --all` | Enable all skills | `gemini skills enable --all` |
| `gemini skills disable --all` | Disable all skills | `gemini skills disable --all` |
See [Agent Skills Documentation](./skills.md) for more details.
+330
View File
@@ -0,0 +1,330 @@
# CLI Commands
Gemini CLI supports several built-in commands to help you manage your session,
customize the interface, and control its behavior. These commands are prefixed
with a forward slash (`/`), an at symbol (`@`), or an exclamation mark (`!`).
## Slash commands (`/`)
Slash commands provide meta-level control over the CLI itself.
### Built-in Commands
- **`/bug`**
- **Description:** File an issue about Gemini CLI. By default, the issue is
filed within the GitHub repository for Gemini CLI. The string you enter
after `/bug` will become the headline for the bug being filed. The default
`/bug` behavior can be modified using the `advanced.bugCommand` setting in
your `.gemini/settings.json` files.
- **`/chat`**
- **Description:** Save and resume conversation history for branching
conversation state interactively, or resuming a previous state from a later
session.
- **Sub-commands:**
- **`save`**
- **Description:** Saves the current conversation history. You must add a
`<tag>` for identifying the conversation state.
- **Usage:** `/chat save <tag>`
- **Details on Checkpoint Location:** The default locations for saved chat
checkpoints are:
- Linux/macOS: `~/.gemini/tmp/<project_hash>/`
- Windows: `C:\Users\<YourUsername>\.gemini\tmp\<project_hash>\`
- When you run `/chat list`, the CLI only scans these specific
directories to find available checkpoints.
- **Note:** These checkpoints are for manually saving and resuming
conversation states. For automatic checkpoints created before file
modifications, see the
[Checkpointing documentation](../cli/checkpointing.md).
- **`resume`**
- **Description:** Resumes a conversation from a previous save.
- **Usage:** `/chat resume <tag>`
- **`list`**
- **Description:** Lists available tags for chat state resumption.
- **`delete`**
- **Description:** Deletes a saved conversation checkpoint.
- **Usage:** `/chat delete <tag>`
- **`share`**
- **Description** Writes the current conversation to a provided Markdown
or JSON file.
- **Usage** `/chat share file.md` or `/chat share file.json`. If no
filename is provided, then the CLI will generate one.
- **`/clear`**
- **Description:** Clear the terminal screen, including the visible session
history and scrollback within the CLI. The underlying session data (for
history recall) might be preserved depending on the exact implementation,
but the visual display is cleared.
- **Keyboard shortcut:** Press **Ctrl+L** at any time to perform a clear
action.
- **`/compress`**
- **Description:** Replace the entire chat context with a summary. This saves
on tokens used for future tasks while retaining a high level summary of what
has happened.
- **`/copy`**
- **Description:** Copies the last output produced by Gemini CLI to your
clipboard, for easy sharing or reuse.
- **Note:** This command requires platform-specific clipboard tools to be
installed.
- On Linux, it requires `xclip` or `xsel`. You can typically install them
using your system's package manager.
- On macOS, it requires `pbcopy`, and on Windows, it requires `clip`. These
tools are typically pre-installed on their respective systems.
- **`/directory`** (or **`/dir`**)
- **Description:** Manage workspace directories for multi-directory support.
- **Sub-commands:**
- **`add`**:
- **Description:** Add a directory to the workspace. The path can be
absolute or relative to the current working directory. Moreover, the
reference from home directory is supported as well.
- **Usage:** `/directory add <path1>,<path2>`
- **Note:** Disabled in restrictive sandbox profiles. If you're using
that, use `--include-directories` when starting the session instead.
- **`show`**:
- **Description:** Display all directories added by `/directory add` and
`--include-directories`.
- **Usage:** `/directory show`
- **`/editor`**
- **Description:** Open a dialog for selecting supported editors.
- **`/extensions`**
- **Description:** Lists all active extensions in the current Gemini CLI
session. See [Gemini CLI Extensions](../extensions/index.md).
- **`/help`** (or **`/?`**)
- **Description:** Display help information about Gemini CLI, including
available commands and their usage.
- **`/mcp`**
- **Description:** Manage configured Model Context Protocol (MCP) servers.
- **Sub-commands:**
- **`list`** or **`ls`**:
- **Description:** List configured MCP servers and tools. This is the
default action if no subcommand is specified.
- **`desc`**
- **Description:** List configured MCP servers and tools with
descriptions.
- **`schema`**:
- **Description:** List configured MCP servers and tools with descriptions
and schemas.
- **`auth`**:
- **Description:** Authenticate with an OAuth-enabled MCP server.
- **Usage:** `/mcp auth <server-name>`
- **Details:** If `<server-name>` is provided, it initiates the OAuth flow
for that server. If no server name is provided, it lists all configured
servers that support OAuth authentication.
- **`refresh`**:
- **Description:** Restarts all MCP servers and re-discovers their
available tools.
- [**`/model`**](./model.md)
- **Description:** Opens a dialog to choose your Gemini model.
- **`/memory`**
- **Description:** Manage the AI's instructional context (hierarchical memory
loaded from `GEMINI.md` files).
- **Sub-commands:**
- **`add`**:
- **Description:** Adds the following text to the AI's memory. Usage:
`/memory add <text to remember>`
- **`show`**:
- **Description:** Display the full, concatenated content of the current
hierarchical memory that has been loaded from all `GEMINI.md` files.
This lets you inspect the instructional context being provided to the
Gemini model.
- **`refresh`**:
- **Description:** Reload the hierarchical instructional memory from all
`GEMINI.md` files found in the configured locations (global,
project/ancestors, and sub-directories). This command updates the model
with the latest `GEMINI.md` content.
- **`list`**:
- **Description:** Lists the paths of the GEMINI.md files in use for
hierarchical memory.
- **Note:** For more details on how `GEMINI.md` files contribute to
hierarchical memory, see the
[CLI Configuration documentation](../get-started/configuration.md).
- **`/restore`**
- **Description:** Restores the project files to the state they were in just
before a tool was executed. This is particularly useful for undoing file
edits made by a tool. If run without a tool call ID, it will list available
checkpoints to restore from.
- **Usage:** `/restore [tool_call_id]`
- **Note:** Only available if the CLI is invoked with the `--checkpointing`
option or configured via [settings](../get-started/configuration.md). See
[Checkpointing documentation](../cli/checkpointing.md) for more details.
- **`/settings`**
- **Description:** Open the settings editor to view and modify Gemini CLI
settings.
- **Details:** This command provides a user-friendly interface for changing
settings that control the behavior and appearance of Gemini CLI. It is
equivalent to manually editing the `.gemini/settings.json` file, but with
validation and guidance to prevent errors.
- **Usage:** Simply run `/settings` and the editor will open. You can then
browse or search for specific settings, view their current values, and
modify them as desired. Changes to some settings are applied immediately,
while others require a restart.
- **`/stats`**
- **Description:** Display detailed statistics for the current Gemini CLI
session, including token usage, cached token savings (when available), and
session duration. Note: Cached token information is only displayed when
cached tokens are being used, which occurs with API key authentication but
not with OAuth authentication at this time.
- [**`/theme`**](./themes.md)
- **Description:** Open a dialog that lets you change the visual theme of
Gemini CLI.
- **`/auth`**
- **Description:** Open a dialog that lets you change the authentication
method.
- **`/about`**
- **Description:** Show version info. Please share this information when
filing issues.
- [**`/tools`**](../tools/index.md)
- **Description:** Display a list of tools that are currently available within
Gemini CLI.
- **Usage:** `/tools [desc]`
- **Sub-commands:**
- **`desc`** or **`descriptions`**:
- **Description:** Show detailed descriptions of each tool, including each
tool's name with its full description as provided to the model.
- **`nodesc`** or **`nodescriptions`**:
- **Description:** Hide tool descriptions, showing only the tool names.
- **`/privacy`**
- **Description:** Display the Privacy Notice and allow users to select
whether they consent to the collection of their data for service improvement
purposes.
- **`/quit`** (or **`/exit`**)
- **Description:** Exit Gemini CLI.
- **`/vim`**
- **Description:** Toggle vim mode on or off. When vim mode is enabled, the
input area supports vim-style navigation and editing commands in both NORMAL
and INSERT modes.
- **Features:**
- **NORMAL mode:** Navigate with `h`, `j`, `k`, `l`; jump by words with `w`,
`b`, `e`; go to line start/end with `0`, `$`, `^`; go to specific lines
with `G` (or `gg` for first line)
- **INSERT mode:** Standard text input with escape to return to NORMAL mode
- **Editing commands:** Delete with `x`, change with `c`, insert with `i`,
`a`, `o`, `O`; complex operations like `dd`, `cc`, `dw`, `cw`
- **Count support:** Prefix commands with numbers (e.g., `3h`, `5w`, `10G`)
- **Repeat last command:** Use `.` to repeat the last editing operation
- **Persistent setting:** Vim mode preference is saved to
`~/.gemini/settings.json` and restored between sessions
- **Status indicator:** When enabled, shows `[NORMAL]` or `[INSERT]` in the
footer
- **`/init`**
- **Description:** To help users easily create a `GEMINI.md` file, this
command analyzes the current directory and generates a tailored context
file, making it simpler for them to provide project-specific instructions to
the Gemini agent.
### Custom Commands
Custom commands allow you to create personalized shortcuts for your most-used
prompts. For detailed instructions on how to create, manage, and use them,
please see the dedicated [Custom Commands documentation](./custom-commands.md).
## Input Prompt Shortcuts
These shortcuts apply directly to the input prompt for text manipulation.
- **Undo:**
- **Keyboard shortcut:** Press **Ctrl+z** to undo the last action in the input
prompt.
- **Redo:**
- **Keyboard shortcut:** Press **Ctrl+Shift+Z** to redo the last undone action
in the input prompt.
## At commands (`@`)
At commands are used to include the content of files or directories as part of
your prompt to Gemini. These commands include git-aware filtering.
- **`@<path_to_file_or_directory>`**
- **Description:** Inject the content of the specified file or files into your
current prompt. This is useful for asking questions about specific code,
text, or collections of files.
- **Examples:**
- `@path/to/your/file.txt Explain this text.`
- `@src/my_project/ Summarize the code in this directory.`
- `What is this file about? @README.md`
- **Details:**
- If a path to a single file is provided, the content of that file is read.
- If a path to a directory is provided, the command attempts to read the
content of files within that directory and any subdirectories.
- Spaces in paths should be escaped with a backslash (e.g.,
`@My\ Documents/file.txt`).
- The command uses the `read_many_files` tool internally. The content is
fetched and then inserted into your query before being sent to the Gemini
model.
- **Git-aware filtering:** By default, git-ignored files (like
`node_modules/`, `dist/`, `.env`, `.git/`) are excluded. This behavior can
be changed via the `context.fileFiltering` settings.
- **File types:** The command is intended for text-based files. While it
might attempt to read any file, binary files or very large files might be
skipped or truncated by the underlying `read_many_files` tool to ensure
performance and relevance. The tool indicates if files were skipped.
- **Output:** The CLI will show a tool call message indicating that
`read_many_files` was used, along with a message detailing the status and
the path(s) that were processed.
- **`@` (Lone at symbol)**
- **Description:** If you type a lone `@` symbol without a path, the query is
passed as-is to the Gemini model. This might be useful if you are
specifically talking _about_ the `@` symbol in your prompt.
### Error handling for `@` commands
- If the path specified after `@` is not found or is invalid, an error message
will be displayed, and the query might not be sent to the Gemini model, or it
will be sent without the file content.
- If the `read_many_files` tool encounters an error (e.g., permission issues),
this will also be reported.
## Shell mode & passthrough commands (`!`)
The `!` prefix lets you interact with your system's shell directly from within
Gemini CLI.
- **`!<shell_command>`**
- **Description:** Execute the given `<shell_command>` using `bash` on
Linux/macOS or `powershell.exe -NoProfile -Command` on Windows (unless you
override `ComSpec`). Any output or errors from the command are displayed in
the terminal.
- **Examples:**
- `!ls -la` (executes `ls -la` and returns to Gemini CLI)
- `!git status` (executes `git status` and returns to Gemini CLI)
- **`!` (Toggle shell mode)**
- **Description:** Typing `!` on its own toggles shell mode.
- **Entering shell mode:**
- When active, shell mode uses a different coloring and a "Shell Mode
Indicator".
- While in shell mode, text you type is interpreted directly as a shell
command.
- **Exiting shell mode:**
- When exited, the UI reverts to its standard appearance and normal Gemini
CLI behavior resumes.
- **Caution for all `!` usage:** Commands you execute in shell mode have the
same permissions and impact as if you ran them directly in your terminal.
- **Environment Variable:** When a command is executed via `!` or in shell mode,
the `GEMINI_CLI=1` environment variable is set in the subprocess's
environment. This allows scripts or tools to detect if they are being run from
within the Gemini CLI.
+770
View File
@@ -0,0 +1,770 @@
# Gemini CLI Configuration
Gemini CLI offers several ways to configure its behavior, including environment
variables, command-line arguments, and settings files. This document outlines
the different configuration methods and available settings.
## Configuration layers
Configuration is applied in the following order of precedence (lower numbers are
overridden by higher numbers):
1. **Default values:** Hardcoded defaults within the application.
2. **User settings file:** Global settings for the current user.
3. **Project settings file:** Project-specific settings.
4. **System settings file:** System-wide settings.
5. **Environment variables:** System-wide or session-specific variables,
potentially loaded from `.env` files.
6. **Command-line arguments:** Values passed when launching the CLI.
## Settings files
Gemini CLI uses `settings.json` files for persistent configuration. There are
three locations for these files:
- **User settings file:**
- **Location:** `~/.gemini/settings.json` (where `~` is your home directory).
- **Scope:** Applies to all Gemini CLI sessions for the current user.
- **Project settings file:**
- **Location:** `.gemini/settings.json` within your project's root directory.
- **Scope:** Applies only when running Gemini CLI from that specific project.
Project settings override user settings.
- **System settings file:**
- **Location:** `/etc/gemini-cli/settings.json` (Linux),
`C:\ProgramData\gemini-cli\settings.json` (Windows) or
`/Library/Application Support/GeminiCli/settings.json` (macOS). The path can
be overridden using the `GEMINI_CLI_SYSTEM_SETTINGS_PATH` environment
variable.
- **Scope:** Applies to all Gemini CLI sessions on the system, for all users.
System settings override user and project settings. May be useful for system
administrators at enterprises to have controls over users' Gemini CLI
setups.
**Note on environment variables in settings:** String values within your
`settings.json` files can reference environment variables using either
`$VAR_NAME` or `${VAR_NAME}` syntax. These variables will be automatically
resolved when the settings are loaded. For example, if you have an environment
variable `MY_API_TOKEN`, you could use it in `settings.json` like this:
`"apiKey": "$MY_API_TOKEN"`.
### The `.gemini` directory in your project
In addition to a project settings file, a project's `.gemini` directory can
contain other project-specific files related to Gemini CLI's operation, such as:
- [Custom sandbox profiles](#sandboxing) (e.g.,
`.gemini/sandbox-macos-custom.sb`, `.gemini/sandbox.Dockerfile`).
### Available settings in `settings.json`:
- **`contextFileName`** (string or array of strings):
- **Description:** Specifies the filename for context files (e.g.,
`GEMINI.md`, `AGENTS.md`). Can be a single filename or a list of accepted
filenames.
- **Default:** `GEMINI.md`
- **Example:** `"contextFileName": "AGENTS.md"`
- **`bugCommand`** (object):
- **Description:** Overrides the default URL for the `/bug` command.
- **Default:**
`"urlTemplate": "https://github.com/google-gemini/gemini-cli/issues/new?template=bug_report.yml&title={title}&info={info}"`
- **Properties:**
- **`urlTemplate`** (string): A URL that can contain `{title}` and `{info}`
placeholders.
- **Example:**
```json
"bugCommand": {
"urlTemplate": "https://bug.example.com/new?title={title}&info={info}"
}
```
- **`fileFiltering`** (object):
- **Description:** Controls git-aware file filtering behavior for @ commands
and file discovery tools.
- **Default:** `"respectGitIgnore": true, "enableRecursiveFileSearch": true`
- **Properties:**
- **`respectGitIgnore`** (boolean): Whether to respect .gitignore patterns
when discovering files. When set to `true`, git-ignored files (like
`node_modules/`, `dist/`, `.env`) are automatically excluded from @
commands and file listing operations.
- **`enableRecursiveFileSearch`** (boolean): Whether to enable searching
recursively for filenames under the current tree when completing @
prefixes in the prompt.
- **Example:**
```json
"fileFiltering": {
"respectGitIgnore": true,
"enableRecursiveFileSearch": false
}
```
- **`coreTools`** (array of strings):
- **Description:** Allows you to specify a list of core tool names that should
be made available to the model. This can be used to restrict the set of
built-in tools. See [Built-in Tools](../core/tools-api.md#built-in-tools)
for a list of core tools. You can also specify command-specific restrictions
for tools that support it, like the `ShellTool`. For example,
`"coreTools": ["ShellTool(ls -l)"]` will only allow the `ls -l` command to
be executed.
- **Default:** All tools available for use by the Gemini model.
- **Example:** `"coreTools": ["ReadFileTool", "GlobTool", "ShellTool(ls)"]`.
- **`excludeTools`** (array of strings):
- **Description:** Allows you to specify a list of core tool names that should
be excluded from the model. A tool listed in both `excludeTools` and
`coreTools` is excluded. You can also specify command-specific restrictions
for tools that support it, like the `ShellTool`. For example,
`"excludeTools": ["ShellTool(rm -rf)"]` will block the `rm -rf` command.
- **Default**: No tools excluded.
- **Example:** `"excludeTools": ["run_shell_command", "findFiles"]`.
- **Security Note:** Command-specific restrictions in `excludeTools` for
`run_shell_command` are based on simple string matching and can be easily
bypassed. This feature is **not a security mechanism** and should not be
relied upon to safely execute untrusted code. It is recommended to use
`coreTools` to explicitly select commands that can be executed.
- **`allowMCPServers`** (array of strings):
- **Description:** Allows you to specify a list of MCP server names that
should be made available to the model. This can be used to restrict the set
of MCP servers to connect to. Note that this will be ignored if
`--allowed-mcp-server-names` is set.
- **Default:** All MCP servers are available for use by the Gemini model.
- **Example:** `"allowMCPServers": ["myPythonServer"]`.
- **Security Note:** This uses simple string matching on MCP server names,
which can be modified. If you're a system administrator looking to prevent
users from bypassing this, consider configuring the `mcpServers` at the
system settings level such that the user will not be able to configure any
MCP servers of their own. This should not be used as an airtight security
mechanism.
- **`excludeMCPServers`** (array of strings):
- **Description:** Allows you to specify a list of MCP server names that
should be excluded from the model. A server listed in both
`excludeMCPServers` and `allowMCPServers` is excluded. Note that this will
be ignored if `--allowed-mcp-server-names` is set.
- **Default**: No MCP servers excluded.
- **Example:** `"excludeMCPServers": ["myNodeServer"]`.
- **Security Note:** This uses simple string matching on MCP server names,
which can be modified. If you're a system administrator looking to prevent
users from bypassing this, consider configuring the `mcpServers` at the
system settings level such that the user will not be able to configure any
MCP servers of their own. This should not be used as an airtight security
mechanism.
- **`autoAccept`** (boolean):
- **Description:** Controls whether the CLI automatically accepts and executes
tool calls that are considered safe (e.g., read-only operations) without
explicit user confirmation. If set to `true`, the CLI will bypass the
confirmation prompt for tools deemed safe.
- **Default:** `false`
- **Example:** `"autoAccept": true`
- **`theme`** (string):
- **Description:** Sets the visual [theme](./themes.md) for Gemini CLI.
- **Default:** `"Default"`
- **Example:** `"theme": "GitHub"`
- **`vimMode`** (boolean):
- **Description:** Enables or disables vim mode for input editing. When
enabled, the input area supports vim-style navigation and editing commands
with NORMAL and INSERT modes. The vim mode status is displayed in the footer
and persists between sessions.
- **Default:** `false`
- **Example:** `"vimMode": true`
- **`sandbox`** (boolean or string):
- **Description:** Controls whether and how to use sandboxing for tool
execution. If set to `true`, Gemini CLI uses a pre-built
`gemini-cli-sandbox` Docker image. For more information, see
[Sandboxing](#sandboxing).
- **Default:** `false`
- **Example:** `"sandbox": "docker"`
- **`toolDiscoveryCommand`** (string):
- **Description:** Defines a custom shell command for discovering tools from
your project. The shell command must return on `stdout` a JSON array of
[function declarations](https://ai.google.dev/gemini-api/docs/function-calling#function-declarations).
Tool wrappers are optional.
- **Default:** Empty
- **Example:** `"toolDiscoveryCommand": "bin/get_tools"`
- **`toolCallCommand`** (string):
- **Description:** Defines a custom shell command for calling a specific tool
that was discovered using `toolDiscoveryCommand`. The shell command must
meet the following criteria:
- It must take function `name` (exactly as in
[function declaration](https://ai.google.dev/gemini-api/docs/function-calling#function-declarations))
as first command line argument.
- It must read function arguments as JSON on `stdin`, analogous to
[`functionCall.args`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#functioncall).
- It must return function output as JSON on `stdout`, analogous to
[`functionResponse.response.content`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#functionresponse).
- **Default:** Empty
- **Example:** `"toolCallCommand": "bin/call_tool"`
- **`mcpServers`** (object):
- **Description:** Configures connections to one or more Model-Context
Protocol (MCP) servers for discovering and using custom tools. Gemini CLI
attempts to connect to each configured MCP server to discover available
tools. If multiple MCP servers expose a tool with the same name, the tool
names will be prefixed with the server alias you defined in the
configuration (e.g., `serverAlias__actualToolName`) to avoid conflicts. Note
that the system might strip certain schema properties from MCP tool
definitions for compatibility.
- **Default:** Empty
- **Properties:**
- **`<SERVER_NAME>`** (object): The server parameters for the named server.
- `command` (string, required): The command to execute to start the MCP
server.
- `args` (array of strings, optional): Arguments to pass to the command.
- `env` (object, optional): Environment variables to set for the server
process.
- `cwd` (string, optional): The working directory in which to start the
server.
- `timeout` (number, optional): Timeout in milliseconds for requests to
this MCP server.
- `trust` (boolean, optional): Trust this server and bypass all tool call
confirmations.
- `includeTools` (array of strings, optional): List of tool names to
include from this MCP server. When specified, only the tools listed here
will be available from this server (whitelist behavior). If not
specified, all tools from the server are enabled by default.
- `excludeTools` (array of strings, optional): List of tool names to
exclude from this MCP server. Tools listed here will not be available to
the model, even if they are exposed by the server. **Note:**
`excludeTools` takes precedence over `includeTools` - if a tool is in
both lists, it will be excluded.
- **Example:**
```json
"mcpServers": {
"myPythonServer": {
"command": "python",
"args": ["mcp_server.py", "--port", "8080"],
"cwd": "./mcp_tools/python",
"timeout": 5000,
"includeTools": ["safe_tool", "file_reader"],
},
"myNodeServer": {
"command": "node",
"args": ["mcp_server.js"],
"cwd": "./mcp_tools/node",
"excludeTools": ["dangerous_tool", "file_deleter"]
},
"myDockerServer": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "API_KEY", "ghcr.io/foo/bar"],
"env": {
"API_KEY": "$MY_API_TOKEN"
}
}
}
```
- **`checkpointing`** (object):
- **Description:** Configures the checkpointing feature, which allows you to
save and restore conversation and file states. See the
[Checkpointing documentation](./checkpointing.md) for more details.
- **Default:** `{"enabled": false}`
- **Properties:**
- **`enabled`** (boolean): When `true`, the `/restore` command is available.
- **`preferredEditor`** (string):
- **Description:** Specifies the preferred editor to use for viewing diffs.
- **Default:** `vscode`
- **Example:** `"preferredEditor": "vscode"`
- **`telemetry`** (object)
- **Description:** Configures logging and metrics collection for Gemini CLI.
For more information, see [Telemetry](./telemetry.md).
- **Default:**
`{"enabled": false, "target": "local", "otlpEndpoint": "http://localhost:4317", "logPrompts": true}`
- **Properties:**
- **`enabled`** (boolean): Whether or not telemetry is enabled.
- **`target`** (string): The destination for collected telemetry. Supported
values are `local` and `gcp`.
- **`otlpEndpoint`** (string): The endpoint for the OTLP Exporter.
- **`logPrompts`** (boolean): Whether or not to include the content of user
prompts in the logs.
- **Example:**
```json
"telemetry": {
"enabled": true,
"target": "local",
"otlpEndpoint": "http://localhost:16686",
"logPrompts": false
}
```
- **`usageStatisticsEnabled`** (boolean):
- **Description:** Enables or disables the collection of usage statistics. See
[Usage Statistics](#usage-statistics) for more information.
- **Default:** `true`
- **Example:**
```json
"usageStatisticsEnabled": false
```
- **`hideTips`** (boolean):
- **Description:** Enables or disables helpful tips in the CLI interface.
- **Default:** `false`
- **Example:**
```json
"hideTips": true
```
- **`hideBanner`** (boolean):
- **Description:** Enables or disables the startup banner (ASCII art logo) in
the CLI interface.
- **Default:** `false`
- **Example:**
```json
"hideBanner": true
```
- **`maxSessionTurns`** (number):
- **Description:** Sets the maximum number of turns for a session. If the
session exceeds this limit, the CLI will stop processing and start a new
chat.
- **Default:** `-1` (unlimited)
- **Example:**
```json
"maxSessionTurns": 10
```
- **`summarizeToolOutput`** (object):
- **Description:** Enables or disables the summarization of tool output. You
can specify the token budget for the summarization using the `tokenBudget`
setting.
- Note: Currently only the `run_shell_command` tool is supported.
- **Default:** `{}` (Disabled by default)
- **Example:**
```json
"summarizeToolOutput": {
"run_shell_command": {
"tokenBudget": 2000
}
}
```
- **`excludedProjectEnvVars`** (array of strings):
- **Description:** Specifies environment variables that should be excluded
from being loaded from project `.env` files. This prevents project-specific
environment variables (like `DEBUG=true`) from interfering with gemini-cli
behavior. Variables from `.gemini/.env` files are never excluded.
- **Default:** `["DEBUG", "DEBUG_MODE"]`
- **Example:**
```json
"excludedProjectEnvVars": ["DEBUG", "DEBUG_MODE", "NODE_ENV"]
```
- **`includeDirectories`** (array of strings):
- **Description:** Specifies an array of additional absolute or relative paths
to include in the workspace context. This allows you to work with files
across multiple directories as if they were one. Paths can use `~` to refer
to the user's home directory. This setting can be combined with the
`--include-directories` command-line flag.
- **Default:** `[]`
- **Example:**
```json
"includeDirectories": [
"/path/to/another/project",
"../shared-library",
"~/common-utils"
]
```
- **`loadMemoryFromIncludeDirectories`** (boolean):
- **Description:** Controls the behavior of the `/memory refresh` command. If
set to `true`, `GEMINI.md` files should be loaded from all directories that
are added. If set to `false`, `GEMINI.md` should only be loaded from the
current directory.
- **Default:** `false`
- **Example:**
```json
"loadMemoryFromIncludeDirectories": true
```
### Example `settings.json`:
```json
{
"theme": "GitHub",
"sandbox": "docker",
"toolDiscoveryCommand": "bin/get_tools",
"toolCallCommand": "bin/call_tool",
"mcpServers": {
"mainServer": {
"command": "bin/mcp_server.py"
},
"anotherServer": {
"command": "node",
"args": ["mcp_server.js", "--verbose"]
}
},
"telemetry": {
"enabled": true,
"target": "local",
"otlpEndpoint": "http://localhost:4317",
"logPrompts": true
},
"usageStatisticsEnabled": true,
"hideTips": false,
"hideBanner": false,
"maxSessionTurns": 10,
"summarizeToolOutput": {
"run_shell_command": {
"tokenBudget": 100
}
},
"excludedProjectEnvVars": ["DEBUG", "DEBUG_MODE", "NODE_ENV"],
"includeDirectories": ["path/to/dir1", "~/path/to/dir2", "../path/to/dir3"],
"loadMemoryFromIncludeDirectories": true
}
```
## Shell History
The CLI keeps a history of shell commands you run. To avoid conflicts between
different projects, this history is stored in a project-specific directory
within your user's home folder.
- **Location:** `~/.gemini/tmp/<project_hash>/shell_history`
- `<project_hash>` is a unique identifier generated from your project's root
path.
- The history is stored in a file named `shell_history`.
## Environment Variables & `.env` Files
Environment variables are a common way to configure applications, especially for
sensitive information like API keys or for settings that might change between
environments.
The CLI automatically loads environment variables from an `.env` file. The
loading order is:
1. `.env` file in the current working directory.
2. If not found, it searches upwards in parent directories until it finds an
`.env` file or reaches the project root (identified by a `.git` folder) or
the home directory.
3. If still not found, it looks for `~/.env` (in the user's home directory).
**Environment Variable Exclusion:** Some environment variables (like `DEBUG` and
`DEBUG_MODE`) are automatically excluded from being loaded from project `.env`
files to prevent interference with gemini-cli behavior. Variables from
`.gemini/.env` files are never excluded. You can customize this behavior using
the `excludedProjectEnvVars` setting in your `settings.json` file.
- **`GEMINI_API_KEY`** (Required):
- Your API key for the Gemini API.
- **Crucial for operation.** The CLI will not function without it.
- Set this in your shell profile (e.g., `~/.bashrc`, `~/.zshrc`) or an `.env`
file.
- **`GEMINI_MODEL`**:
- Specifies the default Gemini model to use.
- Overrides the hardcoded default
- Example: `export GEMINI_MODEL="gemini-2.5-flash"`
- **`GOOGLE_API_KEY`**:
- Your Google Cloud API key.
- Required for using Vertex AI in express mode.
- Ensure you have the necessary permissions.
- Example: `export GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"`.
- **`GOOGLE_CLOUD_PROJECT`**:
- Your Google Cloud Project ID.
- Required for using Code Assist or Vertex AI.
- If using Vertex AI, ensure you have the necessary permissions in this
project.
- **Cloud Shell Note:** When running in a Cloud Shell environment, this
variable defaults to a special project allocated for Cloud Shell users. If
you have `GOOGLE_CLOUD_PROJECT` set in your global environment in Cloud
Shell, it will be overridden by this default. To use a different project in
Cloud Shell, you must define `GOOGLE_CLOUD_PROJECT` in a `.env` file.
- Example: `export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"`.
- **`GOOGLE_APPLICATION_CREDENTIALS`** (string):
- **Description:** The path to your Google Application Credentials JSON file.
- **Example:**
`export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/credentials.json"`
- **`OTLP_GOOGLE_CLOUD_PROJECT`**:
- Your Google Cloud Project ID for Telemetry in Google Cloud
- Example: `export OTLP_GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"`.
- **`GOOGLE_CLOUD_LOCATION`**:
- Your Google Cloud Project Location (e.g., us-central1).
- Required for using Vertex AI in non express mode.
- Example: `export GOOGLE_CLOUD_LOCATION="YOUR_PROJECT_LOCATION"`.
- **`GEMINI_SANDBOX`**:
- Alternative to the `sandbox` setting in `settings.json`.
- Accepts `true`, `false`, `docker`, `podman`, or a custom command string.
- **`SEATBELT_PROFILE`** (macOS specific):
- Switches the Seatbelt (`sandbox-exec`) profile on macOS.
- `permissive-open`: (Default) Restricts writes to the project folder (and a
few other folders, see
`packages/cli/src/utils/sandbox-macos-permissive-open.sb`) but allows other
operations.
- `strict`: Uses a strict profile that declines operations by default.
- `<profile_name>`: Uses a custom profile. To define a custom profile, create
a file named `sandbox-macos-<profile_name>.sb` in your project's `.gemini/`
directory (e.g., `my-project/.gemini/sandbox-macos-custom.sb`).
- **`DEBUG` or `DEBUG_MODE`** (often used by underlying libraries or the CLI
itself):
- Set to `true` or `1` to enable verbose debug logging, which can be helpful
for troubleshooting.
- **Note:** These variables are automatically excluded from project `.env`
files by default to prevent interference with gemini-cli behavior. Use
`.gemini/.env` files if you need to set these for gemini-cli specifically.
- **`NO_COLOR`**:
- Set to any value to disable all color output in the CLI.
- **`CLI_TITLE`**:
- Set to a string to customize the title of the CLI.
- **`CODE_ASSIST_ENDPOINT`**:
- Specifies the endpoint for the code assist server.
- This is useful for development and testing.
- **`GEMINI_SYSTEM_MD`**:
- Overrides the base system prompt with the contents of a Markdown file.
- If set to `1` or `true`, it uses the file at `.gemini/system.md`.
- If set to a file path, it uses that file. The path can be absolute or
relative. `~` is supported for the home directory.
- The specified file must exist.
- **`GEMINI_WRITE_SYSTEM_MD`**:
- Writes the default system prompt to a file. This is useful for getting a
template to customize.
- If set to `1` or `true`, it writes to `.gemini/system.md`.
- If set to a file path, it writes to that path. The path can be absolute or
relative. `~` is supported for the home directory. **Note: This will
overwrite the file if it already exists.**
## Command-Line Arguments
Arguments passed directly when running the CLI can override other configurations
for that specific session.
- **`--model <model_name>`** (**`-m <model_name>`**):
- Specifies the Gemini model to use for this session.
- Example: `npm start -- --model gemini-1.5-pro-latest`
- **`--prompt <your_prompt>`** (**`-p <your_prompt>`**):
- Used to pass a prompt directly to the command. This invokes Gemini CLI in a
non-interactive mode.
- **`--prompt-interactive <your_prompt>`** (**`-i <your_prompt>`**):
- Starts an interactive session with the provided prompt as the initial input.
- The prompt is processed within the interactive session, not before it.
- Cannot be used when piping input from stdin.
- Example: `gemini -i "explain this code"`
- **`--sandbox`** (**`-s`**):
- Enables sandbox mode for this session.
- **`--sandbox-image`**:
- Sets the sandbox image URI.
- **`--debug`** (**`-d`**):
- Enables debug mode for this session, providing more verbose output.
- **`--all-files`** (**`-a`**):
- If set, recursively includes all files within the current directory as
context for the prompt.
- **`--help`** (or **`-h`**):
- Displays help information about command-line arguments.
- **`--show-memory-usage`**:
- Displays the current memory usage.
- **`--yolo`**:
- Enables YOLO mode, which automatically approves all tool calls.
- **`--telemetry`**:
- Enables [telemetry](./telemetry.md).
- **`--telemetry-target`**:
- Sets the telemetry target. See [telemetry](./telemetry.md) for more
information.
- **`--telemetry-otlp-endpoint`**:
- Sets the OTLP endpoint for telemetry. See [telemetry](./telemetry.md) for
more information.
- **`--telemetry-log-prompts`**:
- Enables logging of prompts for telemetry. See [telemetry](./telemetry.md)
for more information.
- **`--checkpointing`**:
- Enables [checkpointing](./checkpointing.md).
- **`--extensions <extension_name ...>`** (**`-e <extension_name ...>`**):
- Specifies a list of extensions to use for the session. If not provided, all
available extensions are used.
- Use the special term `gemini -e none` to disable all extensions.
- Example: `gemini -e my-extension -e my-other-extension`
- **`--list-extensions`** (**`-l`**):
- Lists all available extensions and exits.
- **`--proxy`**:
- Sets the proxy for the CLI.
- Example: `--proxy http://localhost:7890`.
- **`--include-directories <dir1,dir2,...>`**:
- Includes additional directories in the workspace for multi-directory
support.
- Can be specified multiple times or as comma-separated values.
- 5 directories can be added at maximum.
- Example: `--include-directories /path/to/project1,/path/to/project2` or
`--include-directories /path/to/project1 --include-directories /path/to/project2`
- **`--version`**:
- Displays the version of the CLI.
## Context Files (Hierarchical Instructional Context)
While not strictly configuration for the CLI's _behavior_, context files
(defaulting to `GEMINI.md` but configurable via the `contextFileName` setting)
are crucial for configuring the _instructional context_ (also referred to as
"memory") provided to the Gemini model. This powerful feature allows you to give
project-specific instructions, coding style guides, or any relevant background
information to the AI, making its responses more tailored and accurate to your
needs. The CLI includes UI elements, such as an indicator in the footer showing
the number of loaded context files, to keep you informed about the active
context.
- **Purpose:** These Markdown files contain instructions, guidelines, or context
that you want the Gemini model to be aware of during your interactions. The
system is designed to manage this instructional context hierarchically.
### Example Context File Content (e.g., `GEMINI.md`)
Here's a conceptual example of what a context file at the root of a TypeScript
project might contain:
```markdown
# Project: My Awesome TypeScript Library
## General Instructions:
- When generating new TypeScript code, please follow the existing coding style.
- Ensure all new functions and classes have JSDoc comments.
- Prefer functional programming paradigms where appropriate.
- All code should be compatible with TypeScript 5.0 and Node.js 20+.
## Coding Style:
- Use 2 spaces for indentation.
- Interface names should be prefixed with `I` (e.g., `IUserService`).
- Private class members should be prefixed with an underscore (`_`).
- Always use strict equality (`===` and `!==`).
## Specific Component: `src/api/client.ts`
- This file handles all outbound API requests.
- When adding new API call functions, ensure they include robust error handling
and logging.
- Use the existing `fetchWithRetry` utility for all GET requests.
## Regarding Dependencies:
- Avoid introducing new external dependencies unless absolutely necessary.
- If a new dependency is required, please state the reason.
```
This example demonstrates how you can provide general project context, specific
coding conventions, and even notes about particular files or components. The
more relevant and precise your context files are, the better the AI can assist
you. Project-specific context files are highly encouraged to establish
conventions and context.
- **Hierarchical Loading and Precedence:** The CLI implements a sophisticated
hierarchical memory system by loading context files (e.g., `GEMINI.md`) from
several locations. Content from files lower in this list (more specific)
typically overrides or supplements content from files higher up (more
general). The exact concatenation order and final context can be inspected
using the `/memory show` command. The typical loading order is:
1. **Global Context File:**
- Location: `~/.gemini/<contextFileName>` (e.g., `~/.gemini/GEMINI.md` in
your user home directory).
- Scope: Provides default instructions for all your projects.
2. **Project Root & Ancestors Context Files:**
- Location: The CLI searches for the configured context file in the
current working directory and then in each parent directory up to either
the project root (identified by a `.git` folder) or your home directory.
- Scope: Provides context relevant to the entire project or a significant
portion of it.
3. **Sub-directory Context Files (Contextual/Local):**
- Location: The CLI also scans for the configured context file in
subdirectories _below_ the current working directory (respecting common
ignore patterns like `node_modules`, `.git`, etc.). The breadth of this
search is limited to 200 directories by default, but can be configured
with a `memoryDiscoveryMaxDirs` field in your `settings.json` file.
- Scope: Allows for highly specific instructions relevant to a particular
component, module, or subsection of your project.
- **Concatenation & UI Indication:** The contents of all found context files are
concatenated (with separators indicating their origin and path) and provided
as part of the system prompt to the Gemini model. The CLI footer displays the
count of loaded context files, giving you a quick visual cue about the active
instructional context.
- **Importing Content:** You can modularize your context files by importing
other Markdown files using the `@path/to/file.md` syntax. For more details,
see the [Memory Import Processor documentation](../core/memport.md).
- **Commands for Memory Management:**
- Use `/memory refresh` to force a re-scan and reload of all context files
from all configured locations. This updates the AI's instructional context.
- Use `/memory show` to display the combined instructional context currently
loaded, allowing you to verify the hierarchy and content being used by the
AI.
- See the [Commands documentation](./commands.md#memory) for full details on
the `/memory` command and its sub-commands (`show` and `refresh`).
By understanding and utilizing these configuration layers and the hierarchical
nature of context files, you can effectively manage the AI's memory and tailor
the Gemini CLI's responses to your specific needs and projects.
## Sandboxing
The Gemini CLI can execute potentially unsafe operations (like shell commands
and file modifications) within a sandboxed environment to protect your system.
Sandboxing is disabled by default, but you can enable it in a few ways:
- Using `--sandbox` or `-s` flag.
- Setting `GEMINI_SANDBOX` environment variable.
- Sandbox is enabled in `--yolo` mode by default.
By default, it uses a pre-built `gemini-cli-sandbox` Docker image.
For project-specific sandboxing needs, you can create a custom Dockerfile at
`.gemini/sandbox.Dockerfile` in your project's root directory. This Dockerfile
can be based on the base sandbox image:
```dockerfile
FROM gemini-cli-sandbox
# Add your custom dependencies or configurations here
# For example:
# RUN apt-get update && apt-get install -y some-package
# COPY ./my-config /app/my-config
```
When `.gemini/sandbox.Dockerfile` exists, you can use `BUILD_SANDBOX`
environment variable when running Gemini CLI to automatically build the custom
sandbox image:
```bash
BUILD_SANDBOX=1 gemini -s
```
## Usage Statistics
To help us improve the Gemini CLI, we collect anonymized usage statistics. This
data helps us understand how the CLI is used, identify common issues, and
prioritize new features.
**What we collect:**
- **Tool Calls:** We log the names of the tools that are called, whether they
succeed or fail, and how long they take to execute. We do not collect the
arguments passed to the tools or any data returned by them.
- **API Requests:** We log the Gemini model used for each request, the duration
of the request, and whether it was successful. We do not collect the content
of the prompts or responses.
- **Session Information:** We collect information about the configuration of the
CLI, such as the enabled tools and the approval mode.
**What we DON'T collect:**
- **Personally Identifiable Information (PII):** We do not collect any personal
information, such as your name, email address, or API keys.
- **Prompt and Response Content:** We do not log the content of your prompts or
the responses from the Gemini model.
- **File Content:** We do not log the content of any files that are read or
written by the CLI.
**How to opt out:**
You can opt out of usage statistics collection at any time by setting the
`usageStatisticsEnabled` property to `false` in your `settings.json` file:
```json
{
"usageStatisticsEnabled": false
}
```
-80
View File
@@ -1,80 +0,0 @@
# Creating Agent Skills
This guide provides an overview of how to create your own Agent Skills to extend
the capabilities of Gemini CLI.
## Getting started: The `skill-creator` skill
The recommended way to create a new skill is to use the built-in `skill-creator`
skill. To use it, ask Gemini CLI to create a new skill for you.
**Example prompt:**
> "create a new skill called 'code-reviewer'"
Gemini CLI will then use the `skill-creator` to generate the skill:
1. Generate a new directory for your skill (e.g., `my-new-skill/`).
2. Create a `SKILL.md` file with the necessary YAML frontmatter (`name` and
`description`).
3. Create the standard resource directories: `scripts/`, `references/`, and
`assets/`.
## Manual skill creation
If you prefer to create skills manually:
1. **Create a directory** for your skill (e.g., `my-new-skill/`).
2. **Create a `SKILL.md` file** inside the new directory.
To add additional resources that support the skill, refer to the skill
structure.
## Skill structure
A skill is a directory containing a `SKILL.md` file at its root.
### Folder structure
While a `SKILL.md` file is the only required component, we recommend the
following structure for organizing your skill's resources:
```text
my-skill/
├── SKILL.md (Required) Instructions and metadata
├── scripts/ (Optional) Executable scripts
├── references/ (Optional) Static documentation
└── assets/ (Optional) Templates and other resources
```
### `SKILL.md` file
The `SKILL.md` file is the core of your skill. This file uses YAML frontmatter
for metadata and Markdown for instructions. For example:
```markdown
---
name: code-reviewer
description:
Use this skill to review code. It supports both local changes and remote Pull
Requests.
---
# Code Reviewer
This skill guides the agent in conducting thorough code reviews.
## Workflow
### 1. Determine Review Target
- **Remote PR**: If the user gives a PR number or URL, target that remote PR.
- **Local Changes**: If changes are local... ...
```
- **`name`**: A unique identifier for the skill. This should match the directory
name.
- **`description`**: A description of what the skill does and when Gemini should
use it.
- **Body**: The Markdown body of the file contains the instructions that guide
the agent's behavior when the skill is active.
+17 -20
View File
@@ -1,4 +1,4 @@
# Custom commands
# Custom Commands
Custom commands let you save and reuse your favorite or most frequently used
prompts as personal shortcuts within Gemini CLI. You can create commands that
@@ -9,9 +9,9 @@ all your projects, streamlining your workflow and ensuring consistency.
Gemini CLI discovers commands from two locations, loaded in a specific order:
1. **User commands (global):** Located in `~/.gemini/commands/`. These commands
1. **User Commands (Global):** Located in `~/.gemini/commands/`. These commands
are available in any project you are working on.
2. **Project commands (local):** Located in
2. **Project Commands (Local):** Located in
`<your-project-root>/.gemini/commands/`. These commands are specific to the
current project and can be checked into version control to be shared with
your team.
@@ -30,10 +30,7 @@ separator (`/` or `\`) being converted to a colon (`:`).
- A file at `<project>/.gemini/commands/git/commit.toml` becomes the namespaced
command `/git:commit`.
> [!TIP] After creating or modifying `.toml` command files, run
> `/commands reload` to pick up your changes without restarting the CLI.
## TOML file format (v1)
## TOML File Format (v1)
Your command definition files must be written in the TOML format and use the
`.toml` file extension.
@@ -53,7 +50,7 @@ Your command definition files must be written in the TOML format and use the
## Handling arguments
Custom commands support two powerful methods for handling arguments. The CLI
automatically chooses the correct method based on the content of your command's
automatically chooses the correct method based on the content of your command\'s
`prompt`.
### 1. Context-aware injection with `{{args}}`
@@ -63,7 +60,7 @@ replace that placeholder with the text the user typed after the command name.
The behavior of this injection depends on where it is used:
**A. Raw injection (outside shell commands)**
**A. Raw injection (outside Shell commands)**
When used in the main body of the prompt, the arguments are injected exactly as
the user typed them.
@@ -80,7 +77,7 @@ prompt = "Please provide a code fix for the issue described here: {{args}}."
The model receives:
`Please provide a code fix for the issue described here: "Button is misaligned".`
**B. Using arguments in shell commands (inside `!{...}` blocks)**
**B. Using arguments in Shell commands (inside `!{...}` blocks)**
When you use `{{args}}` inside a shell injection block (`!{...}`), the arguments
are automatically **shell-escaped** before replacement. This allows you to
@@ -99,13 +96,13 @@ Search Results:
"""
```
When you run `/grep-code It's complicated`:
When you run `/grep-code It\'s complicated`:
1. The CLI sees `{{args}}` used both outside and inside `!{...}`.
2. Outside: The first `{{args}}` is replaced raw with `It's complicated`.
2. Outside: The first `{{args}}` is replaced raw with `It\'s complicated`.
3. Inside: The second `{{args}}` is replaced with the escaped version (e.g., on
Linux: `"It\'s complicated"`).
4. The command executed is `grep -r "It's complicated" .`.
4. The command executed is `grep -r "It\'s complicated" .`.
5. The CLI prompts you to confirm this exact, secure command before execution.
6. The final prompt is sent.
@@ -132,13 +129,13 @@ format and behavior.
# In: <project>/.gemini/commands/changelog.toml
# Invoked via: /changelog 1.2.0 added "Support for default argument parsing."
description = "Adds a new entry to the project's CHANGELOG.md file."
description = "Adds a new entry to the project\'s CHANGELOG.md file."
prompt = """
# Task: Update Changelog
You are an expert maintainer of this software project. A user has invoked a command to add a new entry to the changelog.
**The user's raw command is appended below your instructions.**
**The user\'s raw command is appended below your instructions.**
Your task is to parse the `<version>`, `<change_type>`, and `<message>` from their input and use the `write_file` tool to correctly update the `CHANGELOG.md` file.
@@ -150,7 +147,7 @@ The command follows this format: `/changelog <version> <type> <message>`
1. Read the `CHANGELOG.md` file.
2. Find the section for the specified `<version>`.
3. Add the `<message>` under the correct `<type>` heading.
4. If the version or type section doesn't exist, create it.
4. If the version or type section doesn\'t exist, create it.
5. Adhere strictly to the "Keep a Changelog" format.
"""
```
@@ -159,7 +156,7 @@ When you run `/changelog 1.2.0 added "New feature"`, the final text sent to the
model will be the original prompt followed by two newlines and the command you
typed.
### 3. Executing shell commands with `!{...}`
### 3. Executing Shell commands with `!{...}`
You can make your commands dynamic by executing shell commands directly within
your `prompt` and injecting their output. This is ideal for gathering context
@@ -244,7 +241,7 @@ operate on specific files.
**Example (`review.toml`):**
This command injects the content of a _fixed_ best practices file
(`docs/best-practices.md`) and uses the user's arguments to provide context for
(`docs/best-practices.md`) and uses the user\'s arguments to provide context for
the review.
```toml
@@ -296,7 +293,7 @@ practice.
description = "Asks the model to refactor the current context into a pure function."
prompt = """
Please analyze the code I've provided in the current context.
Please analyze the code I\'ve provided in the current context.
Refactor it into a pure function.
Your response should include:
@@ -305,7 +302,7 @@ Your response should include:
"""
```
**3. Run the command:**
**3. Run the Command:**
That's it! You can now run your command in the CLI. First, you might add a file
to the context, and then invoke your command:
+34 -129
View File
@@ -1,11 +1,11 @@
# Gemini CLI for the enterprise
# Gemini CLI for the Enterprise
This document outlines configuration patterns and best practices for deploying
and managing Gemini CLI in an enterprise environment. By leveraging system-level
settings, administrators can enforce security policies, manage tool access, and
ensure a consistent experience for all users.
> **A note on security:** The patterns described in this document are intended
> **A Note on Security:** The patterns described in this document are intended
> to help administrators create a more controlled and secure environment for
> using Gemini CLI. However, they should not be considered a foolproof security
> boundary. A determined user with sufficient privileges on their local machine
@@ -14,13 +14,13 @@ ensure a consistent experience for all users.
> managed environment, not to defend against a malicious actor with local
> administrative rights.
## Centralized configuration: The system settings file
## Centralized Configuration: The System Settings File
The most powerful tools for enterprise administration are the system-wide
settings files. These files allow you to define a baseline configuration
(`system-defaults.json`) and a set of overrides (`settings.json`) that apply to
all users on a machine. For a complete overview of configuration options, see
the [Configuration documentation](../reference/configuration.md).
the [Configuration documentation](../get-started/configuration.md).
Settings are merged from four files. The precedence order for single-value
settings (like `theme`) is:
@@ -33,11 +33,11 @@ settings (like `theme`) is:
This means the System Overrides file has the final say. For settings that are
arrays (`includeDirectories`) or objects (`mcpServers`), the values are merged.
**Example of merging and precedence:**
**Example of Merging and Precedence:**
Here is how settings from different levels are combined.
- **System defaults `system-defaults.json`:**
- **System Defaults `system-defaults.json`:**
```json
{
@@ -89,7 +89,7 @@ Here is how settings from different levels are combined.
}
```
- **System overrides `settings.json`:**
- **System Overrides `settings.json`:**
```json
{
"ui": {
@@ -108,7 +108,7 @@ Here is how settings from different levels are combined.
This results in the following merged configuration:
- **Final merged configuration:**
- **Final Merged Configuration:**
```json
{
"ui": {
@@ -159,73 +159,12 @@ This results in the following merged configuration:
By using the system settings file, you can enforce the security and
configuration patterns described below.
### Enforcing system settings with a wrapper script
While the `GEMINI_CLI_SYSTEM_SETTINGS_PATH` environment variable provides
flexibility, a user could potentially override it to point to a different
settings file, bypassing the centrally managed configuration. To mitigate this,
enterprises can deploy a wrapper script or alias that ensures the environment
variable is always set to the corporate-controlled path.
This approach ensures that no matter how the user calls the `gemini` command,
the enterprise settings are always loaded with the highest precedence.
**Example wrapper script:**
Administrators can create a script named `gemini` and place it in a directory
that appears earlier in the user's `PATH` than the actual Gemini CLI binary
(e.g., `/usr/local/bin/gemini`).
```bash
#!/bin/bash
# Enforce the path to the corporate system settings file.
# This ensures that the company's configuration is always applied.
export GEMINI_CLI_SYSTEM_SETTINGS_PATH="/etc/gemini-cli/settings.json"
# Find the original gemini executable.
# This is a simple example; a more robust solution might be needed
# depending on the installation method.
REAL_GEMINI_PATH=$(type -aP gemini | grep -v "^$(type -P gemini)$" | head -n 1)
if [ -z "$REAL_GEMINI_PATH" ]; then
echo "Error: The original 'gemini' executable was not found." >&2
exit 1
fi
# Pass all arguments to the real Gemini CLI executable.
exec "$REAL_GEMINI_PATH" "$@"
```
By deploying this script, the `GEMINI_CLI_SYSTEM_SETTINGS_PATH` is set within
the script's environment, and the `exec` command replaces the script process
with the actual Gemini CLI process, which inherits the environment variable.
This makes it significantly more difficult for a user to bypass the enforced
settings.
## User isolation in shared environments
In shared compute environments (like ML experiment runners or shared build
servers), you can isolate Gemini CLI state by overriding the user's home
directory.
By default, Gemini CLI stores configuration and history in `~/.gemini`. You can
use the `GEMINI_CLI_HOME` environment variable to point to a unique directory
for a specific user or job. The CLI will create a `.gemini` folder inside the
specified path.
```bash
# Isolate state for a specific job
export GEMINI_CLI_HOME="/tmp/gemini-job-123"
gemini
```
## Restricting tool access
## Restricting Tool Access
You can significantly enhance security by controlling which tools the Gemini
model can use. This is achieved through the `tools.core` setting and the
[Policy Engine](../reference/policy-engine.md). For a list of available tools,
see the [Tools documentation](../tools/index.md).
model can use. This is achieved through the `tools.core` and `tools.exclude`
settings. For a list of available tools, see the
[Tools documentation](../tools/index.md).
### Allowlisting with `coreTools`
@@ -243,10 +182,7 @@ on the approved list.
}
```
### Blocklisting with `excludeTools` (Deprecated)
> **Deprecated:** Use the [Policy Engine](../reference/policy-engine.md) for
> more robust control.
### Blocklisting with `excludeTools`
Alternatively, you can add specific tools that are considered dangerous in your
environment to a blocklist.
@@ -261,12 +197,12 @@ environment to a blocklist.
}
```
**Security note:** Blocklisting with `excludeTools` is less secure than
**Security Note:** Blocklisting with `excludeTools` is less secure than
allowlisting with `coreTools`, as it relies on blocking known-bad commands, and
clever users may find ways to bypass simple string-based blocks. **Allowlisting
is the recommended approach.**
### Disabling YOLO mode
### Disabling YOLO Mode
To ensure that users cannot bypass the confirmation prompt for tool execution,
you can disable YOLO mode at the policy level. This adds a critical layer of
@@ -286,14 +222,14 @@ approval.
This setting is highly recommended in an enterprise environment to prevent
unintended tool execution.
## Managing custom tools (MCP servers)
## Managing Custom Tools (MCP Servers)
If your organization uses custom tools via
[Model-Context Protocol (MCP) servers](../reference/tools-api.md), it is crucial
to understand how server configurations are managed to apply security policies
[Model-Context Protocol (MCP) servers](../core/tools-api.md), it is crucial to
understand how server configurations are managed to apply security policies
effectively.
### How MCP server configurations are merged
### How MCP Server Configurations are Merged
Gemini CLI loads `settings.json` files from three levels: System, Workspace, and
User. When it comes to the `mcpServers` object, these configurations are
@@ -310,12 +246,12 @@ This means a user **cannot** override the definition of a server that is already
defined in the system-level settings. However, they **can** add new servers with
unique names.
### Enforcing a catalog of tools
### Enforcing a Catalog of Tools
The security of your MCP tool ecosystem depends on a combination of defining the
canonical servers and adding their names to an allowlist.
### Restricting tools within an MCP server
### Restricting Tools Within an MCP Server
For even greater security, especially when dealing with third-party MCP servers,
you can restrict which specific tools from a server are exposed to the model.
@@ -344,7 +280,7 @@ third-party MCP server, even if the server offers other tools like
}
```
#### More secure pattern: Define and add to allowlist in system settings
#### More Secure Pattern: Define and Add to Allowlist in System Settings
To create a secure, centrally-managed catalog of tools, the system administrator
**must** do both of the following in the system-level `settings.json` file:
@@ -357,7 +293,7 @@ To create a secure, centrally-managed catalog of tools, the system administrator
any servers that are not on this list. If this setting is omitted, the CLI
will merge and allow any server defined by the user.
**Example system `settings.json`:**
**Example System `settings.json`:**
1. Add the _names_ of all approved servers to an allowlist. This will prevent
users from adding their own servers.
@@ -386,12 +322,12 @@ Any server a user defines will either be overridden by the system definition (if
it has the same name) or blocked because its name is not in the `mcp.allowed`
list.
### Less secure pattern: Omitting the allowlist
### Less Secure Pattern: Omitting the Allowlist
If the administrator defines the `mcpServers` object but fails to also specify
the `mcp.allowed` allowlist, users may add their own servers.
**Example system `settings.json`:**
**Example System `settings.json`:**
This configuration defines servers but does not enforce the allowlist. The
administrator has NOT included the "mcp.allowed" setting.
@@ -411,7 +347,7 @@ In this scenario, a user can add their own server in their local
results, the user's server will be added to the list of available tools and
allowed to run.
## Enforcing sandboxing for security
## Enforcing Sandboxing for Security
To mitigate the risk of potentially harmful operations, you can enforce the use
of sandboxing for all tool execution. The sandbox isolates tool execution in a
@@ -427,18 +363,19 @@ containerized environment.
}
```
You can also specify a custom, hardened Docker image for the sandbox by building
a custom `sandbox.Dockerfile` as described in the
You can also specify a custom, hardened Docker image for the sandbox using the
`--sandbox-image` command-line argument or by building a custom
`sandbox.Dockerfile` as described in the
[Sandboxing documentation](./sandbox.md).
## Controlling network access via proxy
## Controlling Network Access via Proxy
In corporate environments with strict network policies, you can configure Gemini
CLI to route all outbound traffic through a corporate proxy. This can be set via
an environment variable, but it can also be enforced for custom tools via the
`mcpServers` configuration.
**Example (for an MCP server):**
**Example (for an MCP Server):**
```json
{
@@ -455,7 +392,7 @@ an environment variable, but it can also be enforced for custom tools via the
}
```
## Telemetry and auditing
## Telemetry and Auditing
For auditing and monitoring purposes, you can configure Gemini CLI to send
telemetry data to a central location. This allows you to track tool usage and
@@ -483,7 +420,7 @@ avoid collecting potentially sensitive information from user prompts.
You can enforce a specific authentication method for all users by setting the
`enforcedAuthType` in the system-level `settings.json` file. This prevents users
from choosing a different authentication method. See the
[Authentication docs](../get-started/authentication.md) for more details.
[Authentication docs](./authentication.md) for more details.
**Example:** Enforce the use of Google login for all users.
@@ -498,39 +435,7 @@ prompted to switch to the enforced method. In non-interactive mode, the CLI will
exit with an error if the configured authentication method does not match the
enforced one.
### Restricting logins to corporate domains
For enterprises using Google Workspace, you can enforce that users only
authenticate with their corporate Google accounts. This is a network-level
control that is configured on a proxy server, not within Gemini CLI itself. It
works by intercepting authentication requests to Google and adding a special
HTTP header.
This policy prevents users from logging in with personal Gmail accounts or other
non-corporate Google accounts.
For detailed instructions, see the Google Workspace Admin Help article on
[blocking access to consumer accounts](https://support.google.com/a/answer/1668854?hl=en#zippy=%2Cstep-choose-a-web-proxy-server%2Cstep-configure-the-network-to-block-certain-accounts).
The general steps are as follows:
1. **Intercept Requests**: Configure your web proxy to intercept all requests
to `google.com`.
2. **Add HTTP Header**: For each intercepted request, add the
`X-GoogApps-Allowed-Domains` HTTP header.
3. **Specify Domains**: The value of the header should be a comma-separated
list of your approved Google Workspace domain names.
**Example header:**
```
X-GoogApps-Allowed-Domains: my-corporate-domain.com, secondary-domain.com
```
When this header is present, Google's authentication service will only allow
logins from accounts belonging to the specified domains.
## Putting it all together: example system `settings.json`
## Putting It All Together: Example System `settings.json`
Here is an example of a system `settings.json` file that combines several of the
patterns discussed above to create a secure, controlled environment for Gemini
+3 -3
View File
@@ -1,4 +1,4 @@
# Ignoring files
# Ignoring Files
This document provides an overview of the Gemini Ignore (`.geminiignore`)
feature of the Gemini CLI.
@@ -13,8 +13,8 @@ Git).
When you add a path to your `.geminiignore` file, tools that respect this file
will exclude matching files and directories from their operations. For example,
when you use the `@` command to share files, any paths in your `.geminiignore`
file will be automatically excluded.
when you use the [`read_many_files`](../tools/multi-file.md) command, any paths
in your `.geminiignore` file will be automatically excluded.
For the most part, `.geminiignore` follows the conventions of `.gitignore`
files:
+13 -21
View File
@@ -1,4 +1,4 @@
# Provide context with GEMINI.md files
# Provide Context with GEMINI.md Files
Context files, which use the default name `GEMINI.md`, are a powerful feature
for providing instructional context to the Gemini model. You can use these files
@@ -19,18 +19,18 @@ order:
- **Location:** `~/.gemini/GEMINI.md` (in your user home directory).
- **Scope:** Provides default instructions for all your projects.
2. **Environment and workspace context files:**
- **Location:** The CLI searches for `GEMINI.md` files in your configured
workspace directories and their parent directories.
- **Scope:** Provides context relevant to the projects you are currently
working on.
2. **Project root and ancestor context files:**
- **Location:** The CLI searches for a `GEMINI.md` file in your current
working directory and then in each parent directory up to the project root
(identified by a `.git` folder).
- **Scope:** Provides context relevant to the entire project.
3. **Just-in-time (JIT) context files:**
- **Location:** When a tool accesses a file or directory, the CLI
automatically scans for `GEMINI.md` files in that directory and its
ancestors up to a trusted root.
- **Scope:** Lets the model discover highly specific instructions for
particular components only when they are needed.
3. **Sub-directory context files:**
- **Location:** The CLI also scans for `GEMINI.md` files in subdirectories
below your current working directory. It respects rules in `.gitignore`
and `.geminiignore`.
- **Scope:** Lets you write highly specific instructions for a particular
component or module.
The CLI footer displays the number of loaded context files, which gives you a
quick visual cue of the active instructional context.
@@ -88,7 +88,7 @@ More content here.
@../shared/style-guide.md
```
For more details, see the [Memory Import Processor](../reference/memport.md)
For more details, see the [Memory Import Processor](../core/memport.md)
documentation.
## Customize the context file name
@@ -106,11 +106,3 @@ While `GEMINI.md` is the default filename, you can configure this in your
}
}
```
## Next steps
- Learn about [Ignoring files](./gemini-ignore.md) to exclude content from the
context system.
- Explore the [Memory tool](../tools/memory.md) to save persistent memories.
- See how to use [Custom commands](./custom-commands.md) to automate common
prompts.
-210
View File
@@ -1,210 +0,0 @@
# Advanced Model Configuration
This guide details the Model Configuration system within the Gemini CLI.
Designed for researchers, AI quality engineers, and advanced users, this system
provides a rigorous framework for managing generative model hyperparameters and
behaviors.
> **Warning**: This is a power-user feature. Configuration values are passed
> directly to the model provider with minimal validation. Incorrect settings
> (e.g., incompatible parameter combinations) may result in runtime errors from
> the API.
## 1. System Overview
The Model Configuration system (`ModelConfigService`) enables deterministic
control over model generation. It decouples the requested model identifier
(e.g., a CLI flag or agent request) from the underlying API configuration. This
allows for:
- **Precise Hyperparameter Tuning**: Direct control over `temperature`, `topP`,
`thinkingBudget`, and other SDK-level parameters.
- **Environment-Specific Behavior**: Distinct configurations for different
operating contexts (e.g., testing vs. production).
- **Agent-Scoped Customization**: Applying specific settings only when a
particular agent is active.
The system operates on two core primitives: **Aliases** and **Overrides**.
## 2. Configuration Primitives
These settings are located under the `modelConfigs` key in your configuration
file.
### Aliases (`customAliases`)
Aliases are named, reusable configuration presets. Users should define their own
aliases (or override system defaults) in the `customAliases` map.
- **Inheritance**: An alias can `extends` another alias (including system
defaults like `chat-base`), inheriting its `modelConfig`. Child aliases can
overwrite or augment inherited settings.
- **Abstract Aliases**: An alias is not required to specify a concrete `model`
if it serves purely as a base for other aliases.
**Example Hierarchy**:
```json
"modelConfigs": {
"customAliases": {
"base": {
"modelConfig": {
"generateContentConfig": { "temperature": 0.0 }
}
},
"chat-base": {
"extends": "base",
"modelConfig": {
"generateContentConfig": { "temperature": 0.7 }
}
}
}
}
```
### Overrides (`overrides`)
Overrides are conditional rules that inject configuration based on the runtime
context. They are evaluated dynamically for each model request.
- **Match Criteria**: Overrides apply when the request context matches the
specified `match` properties.
- `model`: Matches the requested model name or alias.
- `overrideScope`: Matches the distinct scope of the request (typically the
agent name, e.g., `codebaseInvestigator`).
**Example Override**:
```json
"modelConfigs": {
"overrides": [
{
"match": {
"overrideScope": "codebaseInvestigator"
},
"modelConfig": {
"generateContentConfig": { "temperature": 0.1 }
}
}
]
}
```
## 3. Resolution Strategy
The `ModelConfigService` resolves the final configuration through a two-step
process:
### Step 1: Alias Resolution
The requested model string is looked up in the merged map of system `aliases`
and user `customAliases`.
1. If found, the system recursively resolves the `extends` chain.
2. Settings are merged from parent to child (child wins).
3. This results in a base `ResolvedModelConfig`.
4. If not found, the requested string is treated as the raw model name.
### Step 2: Override Application
The system evaluates the `overrides` list against the request context (`model`
and `overrideScope`).
1. **Filtering**: All matching overrides are identified.
2. **Sorting**: Matches are prioritized by **specificity** (the number of
matched keys in the `match` object).
- Specific matches (e.g., `model` + `overrideScope`) override broad matches
(e.g., `model` only).
- Tie-breaking: If specificity is equal, the order of definition in the
`overrides` array is preserved (last one wins).
3. **Merging**: The configurations from the sorted overrides are merged
sequentially onto the base configuration.
## 4. Configuration Reference
The configuration follows the `ModelConfigServiceConfig` interface.
### `ModelConfig` Object
Defines the actual parameters for the model.
| Property | Type | Description |
| :---------------------- | :------- | :----------------------------------------------------------------- |
| `model` | `string` | The identifier of the model to be called (e.g., `gemini-2.5-pro`). |
| `generateContentConfig` | `object` | The configuration object passed to the `@google/genai` SDK. |
### `GenerateContentConfig` (Common Parameters)
Directly maps to the SDK's `GenerateContentConfig`. Common parameters include:
- **`temperature`**: (`number`) Controls output randomness. Lower values (0.0)
are deterministic; higher values (>0.7) are creative.
- **`topP`**: (`number`) Nucleus sampling probability.
- **`maxOutputTokens`**: (`number`) Limit on generated response length.
- **`thinkingConfig`**: (`object`) Configuration for models with reasoning
capabilities (e.g., `thinkingBudget`, `includeThoughts`).
## 5. Practical Examples
### Defining a Deterministic Baseline
Create an alias for tasks requiring high precision, extending the standard chat
configuration but enforcing zero temperature.
```json
"modelConfigs": {
"customAliases": {
"precise-mode": {
"extends": "chat-base",
"modelConfig": {
"generateContentConfig": {
"temperature": 0.0,
"topP": 1.0
}
}
}
}
}
```
### Agent-Specific Parameter Injection
Enforce extended thinking budgets for a specific agent without altering the
global default, e.g. for the `codebaseInvestigator`.
```json
"modelConfigs": {
"overrides": [
{
"match": {
"overrideScope": "codebaseInvestigator"
},
"modelConfig": {
"generateContentConfig": {
"thinkingConfig": { "thinkingBudget": 4096 }
}
}
}
]
}
```
### Experimental Model Evaluation
Route traffic for a specific alias to a preview model for A/B testing, without
changing client code.
```json
"modelConfigs": {
"overrides": [
{
"match": {
"model": "gemini-2.5-pro"
},
"modelConfig": {
"model": "gemini-2.5-pro-experimental-001"
}
}
]
}
```
+372 -34
View File
@@ -1,50 +1,388 @@
# Headless mode reference
# Headless Mode
Headless mode provides a programmatic interface to Gemini CLI, returning
structured text or JSON output without an interactive terminal UI.
Headless mode allows you to run Gemini CLI programmatically from command line
scripts and automation tools without any interactive UI. This is ideal for
scripting, automation, CI/CD pipelines, and building AI-powered tools.
## Technical reference
- [Headless Mode](#headless-mode)
- [Overview](#overview)
- [Basic Usage](#basic-usage)
- [Direct Prompts](#direct-prompts)
- [Stdin Input](#stdin-input)
- [Combining with File Input](#combining-with-file-input)
- [Output Formats](#output-formats)
- [Text Output (Default)](#text-output-default)
- [JSON Output](#json-output)
- [Response Schema](#response-schema)
- [Example Usage](#example-usage)
- [Streaming JSON Output](#streaming-json-output)
- [When to Use Streaming JSON](#when-to-use-streaming-json)
- [Event Types](#event-types)
- [Basic Usage](#basic-usage)
- [Example Output](#example-output)
- [Processing Stream Events](#processing-stream-events)
- [Real-World Examples](#real-world-examples)
- [File Redirection](#file-redirection)
- [Configuration Options](#configuration-options)
- [Examples](#examples)
- [Code review](#code-review)
- [Generate commit messages](#generate-commit-messages)
- [API documentation](#api-documentation)
- [Batch code analysis](#batch-code-analysis)
- [Code review](#code-review-1)
- [Log analysis](#log-analysis)
- [Release notes generation](#release-notes-generation)
- [Model and tool usage tracking](#model-and-tool-usage-tracking)
- [Resources](#resources)
Headless mode is triggered when the CLI is run in a non-TTY environment or when
providing a query as a positional argument without the interactive flag.
## Overview
### Output formats
The headless mode provides a headless interface to Gemini CLI that:
You can specify the output format using the `--output-format` flag.
- Accepts prompts via command line arguments or stdin
- Returns structured output (text or JSON)
- Supports file redirection and piping
- Enables automation and scripting workflows
- Provides consistent exit codes for error handling
#### JSON output
## Basic Usage
Returns a single JSON object containing the response and usage statistics.
### Direct Prompts
- **Schema:**
- `response`: (string) The model's final answer.
- `stats`: (object) Token usage and API latency metrics.
- `error`: (object, optional) Error details if the request failed.
Use the `--prompt` (or `-p`) flag to run in headless mode:
#### Streaming JSON output
```bash
gemini --prompt "What is machine learning?"
```
Returns a stream of newline-delimited JSON (JSONL) events.
### Stdin Input
- **Event types:**
- `init`: Session metadata (session ID, model).
- `message`: User and assistant message chunks.
- `tool_use`: Tool call requests with arguments.
- `tool_result`: Output from executed tools.
- `error`: Non-fatal warnings and system errors.
- `result`: Final outcome with aggregated statistics.
Pipe input to Gemini CLI from your terminal:
## Exit codes
```bash
echo "Explain this code" | gemini
```
The CLI returns standard exit codes to indicate the result of the headless
execution:
### Combining with File Input
- `0`: Success.
- `1`: General error or API failure.
- `42`: Input error (invalid prompt or arguments).
- `53`: Turn limit exceeded.
Read from files and process with Gemini:
## Next steps
```bash
cat README.md | gemini --prompt "Summarize this documentation"
```
- Follow the [Automation tutorial](./tutorials/automation.md) for practical
scripting examples.
- See the [CLI reference](./cli-reference.md) for all available flags.
## Output Formats
### Text Output (Default)
Standard human-readable output:
```bash
gemini -p "What is the capital of France?"
```
Response format:
```
The capital of France is Paris.
```
### JSON Output
Returns structured data including response, statistics, and metadata. This
format is ideal for programmatic processing and automation scripts.
#### Response Schema
The JSON output follows this high-level structure:
```json
{
"response": "string", // The main AI-generated content answering your prompt
"stats": {
// Usage metrics and performance data
"models": {
// Per-model API and token usage statistics
"[model-name]": {
"api": {
/* request counts, errors, latency */
},
"tokens": {
/* prompt, response, cached, total counts */
}
}
},
"tools": {
// Tool execution statistics
"totalCalls": "number",
"totalSuccess": "number",
"totalFail": "number",
"totalDurationMs": "number",
"totalDecisions": {
/* accept, reject, modify, auto_accept counts */
},
"byName": {
/* per-tool detailed stats */
}
},
"files": {
// File modification statistics
"totalLinesAdded": "number",
"totalLinesRemoved": "number"
}
},
"error": {
// Present only when an error occurred
"type": "string", // Error type (e.g., "ApiError", "AuthError")
"message": "string", // Human-readable error description
"code": "number" // Optional error code
}
}
```
#### Example Usage
```bash
gemini -p "What is the capital of France?" --output-format json
```
Response:
```json
{
"response": "The capital of France is Paris.",
"stats": {
"models": {
"gemini-2.5-pro": {
"api": {
"totalRequests": 2,
"totalErrors": 0,
"totalLatencyMs": 5053
},
"tokens": {
"prompt": 24939,
"candidates": 20,
"total": 25113,
"cached": 21263,
"thoughts": 154,
"tool": 0
}
},
"gemini-2.5-flash": {
"api": {
"totalRequests": 1,
"totalErrors": 0,
"totalLatencyMs": 1879
},
"tokens": {
"prompt": 8965,
"candidates": 10,
"total": 9033,
"cached": 0,
"thoughts": 30,
"tool": 28
}
}
},
"tools": {
"totalCalls": 1,
"totalSuccess": 1,
"totalFail": 0,
"totalDurationMs": 1881,
"totalDecisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 1
},
"byName": {
"google_web_search": {
"count": 1,
"success": 1,
"fail": 0,
"durationMs": 1881,
"decisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 1
}
}
}
},
"files": {
"totalLinesAdded": 0,
"totalLinesRemoved": 0
}
}
}
```
### Streaming JSON Output
Returns real-time events as newline-delimited JSON (JSONL). Each significant
action (initialization, messages, tool calls, results) emits immediately as it
occurs. This format is ideal for monitoring long-running operations, building
UIs with live progress, and creating automation pipelines that react to events.
#### When to Use Streaming JSON
Use `--output-format stream-json` when you need:
- **Real-time progress monitoring** - See tool calls and responses as they
happen
- **Event-driven automation** - React to specific events (e.g., tool failures)
- **Live UI updates** - Build interfaces showing AI agent activity in real-time
- **Detailed execution logs** - Capture complete interaction history with
timestamps
- **Pipeline integration** - Stream events to logging/monitoring systems
#### Event Types
The streaming format emits 6 event types:
1. **`init`** - Session starts (includes session_id, model)
2. **`message`** - User prompts and assistant responses
3. **`tool_use`** - Tool call requests with parameters
4. **`tool_result`** - Tool execution results (success/error)
5. **`error`** - Non-fatal errors and warnings
6. **`result`** - Final session outcome with aggregated stats
#### Basic Usage
```bash
# Stream events to console
gemini --output-format stream-json --prompt "What is 2+2?"
# Save event stream to file
gemini --output-format stream-json --prompt "Analyze this code" > events.jsonl
# Parse with jq
gemini --output-format stream-json --prompt "List files" | jq -r '.type'
```
#### Example Output
Each line is a complete JSON event:
```jsonl
{"type":"init","timestamp":"2025-10-10T12:00:00.000Z","session_id":"abc123","model":"gemini-2.0-flash-exp"}
{"type":"message","role":"user","content":"List files in current directory","timestamp":"2025-10-10T12:00:01.000Z"}
{"type":"tool_use","tool_name":"Bash","tool_id":"bash-123","parameters":{"command":"ls -la"},"timestamp":"2025-10-10T12:00:02.000Z"}
{"type":"tool_result","tool_id":"bash-123","status":"success","output":"file1.txt\nfile2.txt","timestamp":"2025-10-10T12:00:03.000Z"}
{"type":"message","role":"assistant","content":"Here are the files...","delta":true,"timestamp":"2025-10-10T12:00:04.000Z"}
{"type":"result","status":"success","stats":{"total_tokens":250,"input_tokens":50,"output_tokens":200,"duration_ms":3000,"tool_calls":1},"timestamp":"2025-10-10T12:00:05.000Z"}
```
### File Redirection
Save output to files or pipe to other commands:
```bash
# Save to file
gemini -p "Explain Docker" > docker-explanation.txt
gemini -p "Explain Docker" --output-format json > docker-explanation.json
# Append to file
gemini -p "Add more details" >> docker-explanation.txt
# Pipe to other tools
gemini -p "What is Kubernetes?" --output-format json | jq '.response'
gemini -p "Explain microservices" | wc -w
gemini -p "List programming languages" | grep -i "python"
```
## Configuration Options
Key command-line options for headless usage:
| Option | Description | Example |
| ----------------------- | ---------------------------------- | -------------------------------------------------- |
| `--prompt`, `-p` | Run in headless mode | `gemini -p "query"` |
| `--output-format` | Specify output format (text, json) | `gemini -p "query" --output-format json` |
| `--model`, `-m` | Specify the Gemini model | `gemini -p "query" -m gemini-2.5-flash` |
| `--debug`, `-d` | Enable debug mode | `gemini -p "query" --debug` |
| `--include-directories` | Include additional directories | `gemini -p "query" --include-directories src,docs` |
| `--yolo`, `-y` | Auto-approve all actions | `gemini -p "query" --yolo` |
| `--approval-mode` | Set approval mode | `gemini -p "query" --approval-mode auto_edit` |
For complete details on all available configuration options, settings files, and
environment variables, see the
[Configuration Guide](../get-started/configuration.md).
## Examples
#### Code review
```bash
cat src/auth.py | gemini -p "Review this authentication code for security issues" > security-review.txt
```
#### Generate commit messages
```bash
result=$(git diff --cached | gemini -p "Write a concise commit message for these changes" --output-format json)
echo "$result" | jq -r '.response'
```
#### API documentation
```bash
result=$(cat api/routes.js | gemini -p "Generate OpenAPI spec for these routes" --output-format json)
echo "$result" | jq -r '.response' > openapi.json
```
#### Batch code analysis
```bash
for file in src/*.py; do
echo "Analyzing $file..."
result=$(cat "$file" | gemini -p "Find potential bugs and suggest improvements" --output-format json)
echo "$result" | jq -r '.response' > "reports/$(basename "$file").analysis"
echo "Completed analysis for $(basename "$file")" >> reports/progress.log
done
```
#### Code review
```bash
result=$(git diff origin/main...HEAD | gemini -p "Review these changes for bugs, security issues, and code quality" --output-format json)
echo "$result" | jq -r '.response' > pr-review.json
```
#### Log analysis
```bash
grep "ERROR" /var/log/app.log | tail -20 | gemini -p "Analyze these errors and suggest root cause and fixes" > error-analysis.txt
```
#### Release notes generation
```bash
result=$(git log --oneline v1.0.0..HEAD | gemini -p "Generate release notes from these commits" --output-format json)
response=$(echo "$result" | jq -r '.response')
echo "$response"
echo "$response" >> CHANGELOG.md
```
#### Model and tool usage tracking
```bash
result=$(gemini -p "Explain this database schema" --include-directories db --output-format json)
total_tokens=$(echo "$result" | jq -r '.stats.models // {} | to_entries | map(.value.tokens.total) | add // 0')
models_used=$(echo "$result" | jq -r '.stats.models // {} | keys | join(", ") | if . == "" then "none" else . end')
tool_calls=$(echo "$result" | jq -r '.stats.tools.totalCalls // 0')
tools_used=$(echo "$result" | jq -r '.stats.tools.byName // {} | keys | join(", ") | if . == "" then "none" else . end')
echo "$(date): $total_tokens tokens, $tool_calls tool calls ($tools_used) used with models: $models_used" >> usage.log
echo "$result" | jq -r '.response' > schema-docs.md
echo "Recent usage trends:"
tail -5 usage.log
```
## Resources
- [CLI Configuration](../get-started/configuration.md) - Complete configuration
guide
- [Authentication](../get-started/authentication.md) - Setup authentication
- [Commands](./commands.md) - Interactive commands reference
- [Tutorials](./tutorials.md) - Step-by-step automation guides
+58
View File
@@ -0,0 +1,58 @@
# Gemini CLI
Within Gemini CLI, `packages/cli` is the frontend for users to send and receive
prompts with the Gemini AI model and its associated tools. For a general
overview of Gemini CLI, see the [main documentation page](../index.md).
## Basic features
- **[Commands](./commands.md):** A reference for all built-in slash commands
(e.g., `/help`, `/chat`, `/tools`).
- **[Custom Commands](./custom-commands.md):** Create your own commands and
shortcuts for frequently used prompts.
- **[Headless Mode](./headless.md):** Use Gemini CLI programmatically for
scripting and automation.
- **[Themes](./themes.md):** Customizing the CLI's appearance with different
themes.
- **[Keyboard Shortcuts](./keyboard-shortcuts.md):** A reference for all
keyboard shortcuts to improve your workflow.
- **[Tutorials](./tutorials.md):** Step-by-step guides for common tasks.
## Advanced features
- **[Checkpointing](./checkpointing.md):** Automatically save and restore
snapshots of your session and files.
- **[Enterprise Configuration](./enterprise.md):** Deploying and manage Gemini
CLI in an enterprise environment.
- **[Sandboxing](./sandbox.md):** Isolate tool execution in a secure,
containerized environment.
- **[Telemetry](./telemetry.md):** Configure observability to monitor usage and
performance.
- **[Token Caching](./token-caching.md):** Optimize API costs by caching tokens.
- **[Trusted Folders](./trusted-folders.md):** A security feature to control
which projects can use the full capabilities of the CLI.
- **[Ignoring Files (.geminiignore)](./gemini-ignore.md):** Exclude specific
files and directories from being accessed by tools.
- **[Context Files (GEMINI.md)](./gemini-md.md):** Provide persistent,
hierarchical context to the model.
## Non-interactive mode
Gemini CLI can be run in a non-interactive mode, which is useful for scripting
and automation. In this mode, you pipe input to the CLI, it executes the
command, and then it exits.
The following example pipes a command to Gemini CLI from your terminal:
```bash
echo "What is fine tuning?" | gemini
```
You can also use the `--prompt` or `-p` flag:
```bash
gemini -p "What is fine tuning?"
```
For comprehensive documentation on headless usage, scripting, automation, and
advanced examples, see the **[Headless Mode](./headless.md)** guide.
+97
View File
@@ -0,0 +1,97 @@
# Gemini CLI Keyboard Shortcuts
This document lists the available keyboard shortcuts within Gemini CLI.
## General
| Shortcut | Description |
| ----------- | --------------------------------------------------------------------------------------------------------------------- |
| `Esc` | Close dialogs and suggestions. |
| `Ctrl+C` | Cancel the ongoing request and clear the input. Press twice to exit the application. |
| `Ctrl+D` | Exit the application if the input is empty. Press twice to confirm. |
| `Ctrl+L` | Clear the screen. |
| `Ctrl+S` | Allows long responses to print fully, disabling truncation. Use your terminal's scrollback to view the entire output. |
| `Ctrl+S` | Toggle copy mode (alternate buffer mode only). |
| `Ctrl+T` | Toggle the display of the todo list. |
| `Ctrl+Y` | Toggle auto-approval (YOLO mode) for all tool calls. |
| `Shift+Tab` | Toggle auto-accepting edits approval mode. |
| `Option+M` | Toggle Markdown rendering for messages (raw markdown mode). |
| `F12` | Toggle the display of the debug console. |
## Input Prompt
| Shortcut | Description |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `!` | Toggle shell mode when the input is empty. |
| `\` (at end of line) + `Enter` | Insert a newline. |
| `Down Arrow` | Navigate down through the input history. |
| `Enter` | Submit the current prompt. |
| `Meta+Delete` / `Ctrl+Delete` | Delete the word to the right of the cursor. |
| `Tab` | Autocomplete the current suggestion if one exists. |
| `Up Arrow` | Navigate up through the input history. |
| `Ctrl+A` / `Home` | Move the cursor to the beginning of the line. |
| `Ctrl+B` / `Left Arrow` | Move the cursor one character to the left. |
| `Ctrl+C` | Clear the input prompt |
| `Esc` (double press) | Clear the input prompt. |
| `Ctrl+D` / `Delete` | Delete the character to the right of the cursor. |
| `Ctrl+E` / `End` | Move the cursor to the end of the line. |
| `Ctrl+F` / `Right Arrow` | Move the cursor one character to the right. `Ctrl+F` also toggles focus between input and interactive shell if active. |
| `Ctrl+H` / `Backspace` | Delete the character to the left of the cursor. |
| `Ctrl+K` | Delete from the cursor to the end of the line. |
| `Ctrl+Left Arrow` / `Meta+Left Arrow` / `Meta+B` | Move the cursor one word to the left. |
| `Ctrl+N` | Navigate down through the input history. |
| `Ctrl+P` | Navigate up through the input history. |
| `Ctrl+R` | Activate reverse command search history. |
| `Ctrl+Right Arrow` / `Meta+Right Arrow` / `Meta+F` | Move the cursor one word to the right. |
| `Ctrl+U` | Delete from the cursor to the beginning of the line. |
| `Ctrl+V` | Paste clipboard content. If the clipboard contains an image, it will be saved and a reference to it will be inserted in the prompt. |
| `Ctrl+W` / `Meta+Backspace` / `Ctrl+Backspace` | Delete the word to the left of the cursor. |
| `Ctrl+X` / `Meta+Enter` | Open the current input in an external editor. |
| `Ctrl+Z` | Undo last text edit. |
| `Ctrl+Shift+Z` | Redo last undone text edit. |
## Suggestions
| Shortcut | Description |
| ----------------------- | -------------------------------------- |
| `Down Arrow` / `Ctrl+N` | Navigate down through the suggestions. |
| `Tab` / `Enter` | Accept the selected suggestion. |
| `Up Arrow` / `Ctrl+P` | Navigate up through the suggestions. |
## Radio Button Select
| Shortcut | Description |
| ------------------ | ------------------------------------------------------------------------------------------------------------- |
| `Down Arrow` / `j` | Move selection down. |
| `Enter` | Confirm selection. |
| `Up Arrow` / `k` | Move selection up. |
| `1-9` | Select an item by its number. |
| (multi-digit) | For items with numbers greater than 9, press the digits in quick succession to select the corresponding item. |
## IDE Integration
| Shortcut | Description |
| -------- | --------------------------------- |
| `Ctrl+G` | See context CLI received from IDE |
#### Scrolling
| Action | Keys |
| ------------------------ | -------------------- |
| Scroll content up. | `Shift + Up Arrow` |
| Scroll content down. | `Shift + Down Arrow` |
| Scroll to the top. | `Home` |
| Scroll to the bottom. | `End` |
| Scroll up by one page. | `Page Up` |
| Scroll down by one page. | `Page Down` |
#### History & Search
## Meta+key combos on mac
On Mac, all Meta+char combos should work normally except for these three which
are mapped to special functionality.
- `meta+b`: "∫" back one word
- `meta+f`: "ƒ" forward one word
- `meta+m`: "µ" toggle markup view
-42
View File
@@ -1,42 +0,0 @@
# Model routing
Gemini CLI includes a model routing feature that automatically switches to a
fallback model in case of a model failure. This feature is enabled by default
and provides resilience when the primary model is unavailable.
## How it works
Model routing is managed by the `ModelAvailabilityService`, which monitors model
health and automatically routes requests to available models based on defined
policies.
1. **Model failure:** If the currently selected model fails (e.g., due to quota
or server errors), the CLI will initiate the fallback process.
2. **User consent:** Depending on the failure and the model's policy, the CLI
may prompt you to switch to a fallback model (by default always prompts
you).
Some internal utility calls (such as prompt completion and classification)
use a silent fallback chain for `gemini-2.5-flash-lite` and will fall back
to `gemini-2.5-flash` and `gemini-2.5-pro` without prompting or changing the
configured model.
3. **Model switch:** If approved, or if the policy allows for silent fallback,
the CLI will use an available fallback model for the current turn or the
remainder of the session.
### Model selection precedence
The model used by Gemini CLI is determined by the following order of precedence:
1. **`--model` command-line flag:** A model specified with the `--model` flag
when launching the CLI will always be used.
2. **`GEMINI_MODEL` environment variable:** If the `--model` flag is not used,
the CLI will use the model specified in the `GEMINI_MODEL` environment
variable.
3. **`model.name` in `settings.json`:** If neither of the above are set, the
model specified in the `model.name` property of your `settings.json` file
will be used.
4. **Default model:** If none of the above are set, the default model will be
used. The default model is `auto`
+21 -39
View File
@@ -1,13 +1,8 @@
# Gemini CLI model selection (`/model` command)
# Gemini CLI Model Selection (`/model` Command)
Select your Gemini CLI model. The `/model` command lets you configure the model
used by Gemini CLI, giving you more control over your results. Use **Pro**
models for complex tasks and reasoning, **Flash** models for high speed results,
or the (recommended) **Auto** setting to choose the best model for your tasks.
> **Note:** The `/model` command (and the `--model` flag) does not override the
> model used by sub-agents. Consequently, even when using the `/model` flag you
> may see other models used in your model usage reports.
Select your Gemini CLI model. The `/model` command opens a dialog where you can
configure the model used by Gemini CLI, giving you more control over your
results.
## How to use the `/model` command
@@ -17,45 +12,32 @@ Use the following command in Gemini CLI:
/model
```
Running this command will open a dialog with your options:
Running this command will open a dialog with your model options:
| Option | Description | Models |
| ----------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Auto (Gemini 3) | Let the system choose the best Gemini 3 model for your task. | gemini-3-pro-preview (if enabled), gemini-3-flash-preview (if enabled) |
| Auto (Gemini 2.5) | Let the system choose the best Gemini 2.5 model for your task. | gemini-2.5-pro, gemini-2.5-flash |
| Manual | Select a specific model. | Any available model. |
We recommend selecting one of the above **Auto** options. However, you can
select **Manual** to select a specific model from those available.
### Gemini 3 and preview features
> **Note:** Gemini 3 is not currently available on all account types. To learn
> more about Gemini 3 access, refer to
> [Gemini 3 on Gemini CLI](../get-started/gemini-3.md).
To enable Gemini 3 Pro and Gemini 3 Flash (if available), enable
[**Preview Features** by using the `settings` command](../cli/settings.md).
You can also use the `--model` flag to specify a particular Gemini model on
startup. For more details, refer to the
[configuration documentation](../reference/configuration.md).
- **Auto (recommended):** Let the system choose the best model for your task.
Typically, this is the best option.
- **Pro:** For complex tasks that require deep reasoning and creativity. The Pro
model may take longer to return a response.
- **Flash:** For tasks that need a balance of speed and reasoning. The Flash
model will usually return a faster response than Pro.
- **Flash-Lite:** For simple tasks that need to be done quickly. The Flash-Lite
model is typically the fastest.
Changes to these settings will be applied to all subsequent interactions with
Gemini CLI.
## Best practices for model selection
- **Default to Auto.** For most users, the _Auto_ option model provides a
balance between speed and performance, automatically selecting the correct
model based on the complexity of the task. Example: Developing a web
application could include a mix of complex tasks (building architecture and
scaffolding the project) and simple tasks (generating CSS).
- **Default to Auto (recommended).** For most users, the _Auto (recommended)_
model provides a balance between speed and performance, automatically
selecting the correct model based on the complexity of the task. Example:
Developing a web application could include a mix of complex tasks (building
architecture and scaffolding the project) and simple tasks (generating CSS).
- **Switch to Pro if you aren't getting the results you want.** If you think you
need your model to be a little "smarter," you can manually select Pro. Pro
will provide you with the highest levels of reasoning and creativity. Example:
A complex or multi-stage debugging task.
need your model to be a little "smarter," use Pro. Pro will provide you with
the highest levels of reasoning and creativity. Example: A complex or
multi-stage debugging task.
- **Switch to Flash or Flash-Lite if you need faster results.** If you need a
simple response quickly, Flash or Flash-Lite is the best option. Example:
-290
View File
@@ -1,290 +0,0 @@
# Plan Mode (experimental)
Plan Mode is a read-only environment for architecting robust solutions before
implementation. It allows you to:
- **Research:** Explore the project in a read-only state to prevent accidental
changes.
- **Design:** Understand problems, evaluate trade-offs, and choose a solution.
- **Plan:** Align on an execution strategy before any code is modified.
> **Note:** This is a preview feature currently under active development. Your
> feedback is invaluable as we refine this feature. If you have ideas,
> suggestions, or encounter issues:
>
> - [Open an issue](https://github.com/google-gemini/gemini-cli/issues) on
> GitHub.
> - Use the **/bug** command within Gemini CLI to file an issue.
- [Enabling Plan Mode](#enabling-plan-mode)
- [How to use Plan Mode](#how-to-use-plan-mode)
- [Entering Plan Mode](#entering-plan-mode)
- [Planning Workflow](#planning-workflow)
- [Exiting Plan Mode](#exiting-plan-mode)
- [Tool Restrictions](#tool-restrictions)
- [Customizing Planning with Skills](#customizing-planning-with-skills)
- [Customizing Policies](#customizing-policies)
- [Example: Allow git commands in Plan Mode](#example-allow-git-commands-in-plan-mode)
- [Example: Enable research subagents in Plan Mode](#example-enable-research-subagents-in-plan-mode)
- [Custom Plan Directory and Policies](#custom-plan-directory-and-policies)
- [Automatic Model Routing](#automatic-model-routing)
## Enabling Plan Mode
To use Plan Mode, enable it via **/settings** (search for **Plan**) or add the
following to your `settings.json`:
```json
{
"experimental": {
"plan": true
}
}
```
## How to use Plan Mode
### Entering Plan Mode
You can configure Gemini CLI to start in Plan Mode by default or enter it
manually during a session.
- **Configuration:** Configure Gemini CLI to start directly in Plan Mode by
default:
1. Type `/settings` in the CLI.
2. Search for **Default Approval Mode**.
3. Set the value to **Plan**.
Alternatively, use the `gemini --approval-mode=plan` CLI flag or manually
update:
```json
{
"general": {
"defaultApprovalMode": "plan"
}
}
```
- **Keyboard Shortcut:** Press `Shift+Tab` to cycle through approval modes
(`Default` -> `Auto-Edit` -> `Plan`).
> **Note:** Plan Mode is automatically removed from the rotation when Gemini
> CLI is actively processing or showing confirmation dialogs.
- **Command:** Type `/plan` in the input box.
- **Natural Language:** Ask Gemini CLI to "start a plan for...". Gemini CLI then
calls the [`enter_plan_mode`] tool to switch modes.
> **Note:** This tool is not available when Gemini CLI is in [YOLO mode].
### Planning Workflow
1. **Explore & Analyze:** Analyze requirements and use read-only tools to map
the codebase and validate assumptions. For complex tasks, identify at least
two viable implementation approaches.
2. **Consult:** Present a summary of the identified approaches via [`ask_user`]
to obtain a selection. For simple or canonical tasks, this step may be
skipped.
3. **Draft:** Once an approach is selected, write a detailed implementation
plan to the plans directory.
4. **Review & Approval:** Use the [`exit_plan_mode`] tool to present the plan
and formally request approval.
- **Approve:** Exit Plan Mode and start implementation.
- **Iterate:** Provide feedback to refine the plan.
For more complex or specialized planning tasks, you can
[customize the planning workflow with skills](#customizing-planning-with-skills).
### Exiting Plan Mode
To exit Plan Mode, you can:
- **Keyboard Shortcut:** Press `Shift+Tab` to cycle to the desired mode.
- **Tool:** Gemini CLI calls the [`exit_plan_mode`] tool to present the
finalized plan for your approval.
## Tool Restrictions
Plan Mode enforces strict safety policies to prevent accidental changes.
These are the only allowed tools:
- **FileSystem (Read):** [`read_file`], [`list_directory`], [`glob`]
- **Search:** [`grep_search`], [`google_web_search`]
- **Interaction:** [`ask_user`]
- **MCP Tools (Read):** Read-only [MCP tools] (e.g., `github_read_issue`,
`postgres_read_schema`) are allowed.
- **Planning (Write):** [`write_file`] and [`replace`] only allowed for `.md`
files in the `~/.gemini/tmp/<project>/<session-id>/plans/` directory or your
[custom plans directory](#custom-plan-directory-and-policies).
- **Skills:** [`activate_skill`] (allows loading specialized instructions and
resources in a read-only manner)
### Customizing Planning with Skills
You can use [Agent Skills](./skills.md) to customize how Gemini CLI approaches
planning for specific types of tasks. When a skill is activated during Plan
Mode, its specialized instructions and procedural workflows will guide the
research, design and planning phases.
For example:
- A **"Database Migration"** skill could ensure the plan includes data safety
checks and rollback strategies.
- A **"Security Audit"** skill could prompt Gemini CLI to look for specific
vulnerabilities during codebase exploration.
- A **"Frontend Design"** skill could guide Gemini CLI to use specific UI
components and accessibility standards in its proposal.
To use a skill in Plan Mode, you can explicitly ask Gemini CLI to "use the
`<skill-name>` skill to plan..." or Gemini CLI may autonomously activate it
based on the task description.
### Customizing Policies
Plan Mode's default tool restrictions are managed by the [policy engine] and
defined in the built-in [`plan.toml`] file. The built-in policy (Tier 1)
enforces the read-only state, but you can customize these rules by creating your
own policies in your `~/.gemini/policies/` directory (Tier 2).
#### Example: Automatically approve read-only MCP tools
By default, read-only MCP tools require user confirmation in Plan Mode. You can
use `toolAnnotations` and the `mcpName` wildcard to customize this behavior for
your specific environment.
`~/.gemini/policies/mcp-read-only.toml`
```toml
[[rule]]
mcpName = "*"
toolAnnotations = { readOnlyHint = true }
decision = "allow"
priority = 100
modes = ["plan"]
```
#### Example: Allow git commands in Plan Mode
This rule allows you to check the repository status and see changes while in
Plan Mode.
`~/.gemini/policies/git-research.toml`
```toml
[[rule]]
toolName = "run_shell_command"
commandPrefix = ["git status", "git diff"]
decision = "allow"
priority = 100
modes = ["plan"]
```
#### Example: Enable research subagents in Plan Mode
You can enable experimental research [subagents] like `codebase_investigator` to
help gather architecture details during the planning phase.
`~/.gemini/policies/research-subagents.toml`
```toml
[[rule]]
toolName = "codebase_investigator"
decision = "allow"
priority = 100
modes = ["plan"]
```
Tell Gemini CLI it can use these tools in your prompt, for example: _"You can
check ongoing changes in git."_
For more information on how the policy engine works, see the [policy engine]
docs.
### Custom Plan Directory and Policies
By default, planning artifacts are stored in a managed temporary directory
outside your project: `~/.gemini/tmp/<project>/<session-id>/plans/`.
You can configure a custom directory for plans in your `settings.json`. For
example, to store plans in a `.gemini/plans` directory within your project:
```json
{
"general": {
"plan": {
"directory": ".gemini/plans"
}
}
}
```
To maintain the safety of Plan Mode, user-configured paths for the plans
directory are restricted to the project root. This ensures that custom planning
locations defined within a project's workspace cannot be used to escape and
overwrite sensitive files elsewhere. Any user-configured directory must reside
within the project boundary.
Using a custom directory requires updating your [policy engine] configurations
to allow `write_file` and `replace` in that specific location. For example, to
allow writing to the `.gemini/plans` directory within your project, create a
policy file at `~/.gemini/policies/plan-custom-directory.toml`:
```toml
[[rule]]
toolName = ["write_file", "replace"]
decision = "allow"
priority = 100
modes = ["plan"]
# Adjust the pattern to match your custom directory.
# This example matches any .md file in a .gemini/plans directory within the project.
argsPattern = "\"file_path\":\"[^\"]+[\\\\/]+\\.gemini[\\\\/]+plans[\\\\/]+[\\w-]+\\.md\""
```
## Automatic Model Routing
When using an [**auto model**], Gemini CLI automatically optimizes [**model
routing**] based on the current phase of your task:
1. **Planning Phase:** While in Plan Mode, the CLI routes requests to a
high-reasoning **Pro** model to ensure robust architectural decisions and
high-quality plans.
2. **Implementation Phase:** Once a plan is approved and you exit Plan Mode,
the CLI detects the existence of the approved plan and automatically
switches to a high-speed **Flash** model. This provides a faster, more
responsive experience during the implementation of the plan.
This behavior is enabled by default to provide the best balance of quality and
performance. You can disable this automatic switching in your settings:
```json
{
"general": {
"plan": {
"modelRouting": false
}
}
}
```
[`list_directory`]: /docs/tools/file-system.md#1-list_directory-readfolder
[`read_file`]: /docs/tools/file-system.md#2-read_file-readfile
[`grep_search`]: /docs/tools/file-system.md#5-grep_search-searchtext
[`write_file`]: /docs/tools/file-system.md#3-write_file-writefile
[`glob`]: /docs/tools/file-system.md#4-glob-findfiles
[`google_web_search`]: /docs/tools/web-search.md
[`replace`]: /docs/tools/file-system.md#6-replace-edit
[MCP tools]: /docs/tools/mcp-server.md
[`activate_skill`]: /docs/cli/skills.md
[subagents]: /docs/core/subagents.md
[policy engine]: /docs/reference/policy-engine.md
[`enter_plan_mode`]: /docs/tools/planning.md#1-enter_plan_mode-enterplanmode
[`exit_plan_mode`]: /docs/tools/planning.md#2-exit_plan_mode-exitplanmode
[`ask_user`]: /docs/tools/ask-user.md
[YOLO mode]: /docs/reference/configuration.md#command-line-arguments
[`plan.toml`]:
https://github.com/google-gemini/gemini-cli/blob/main/packages/core/src/policy/policies/plan.toml
[auto model]: /docs/reference/configuration.md#model-settings
[model routing]: /docs/cli/telemetry.md#model-routing
-51
View File
@@ -1,51 +0,0 @@
# Rewind
The `/rewind` command lets you go back to a previous state in your conversation
and, optionally, revert any file changes made by the AI during those
interactions. This is a powerful tool for undoing mistakes, exploring different
approaches, or simply cleaning up your session history.
## Usage
To use the rewind feature, simply type `/rewind` into the input prompt and press
**Enter**.
Alternatively, you can use the keyboard shortcut: **Press `Esc` twice**.
## Interface
When you trigger a rewind, an interactive list of your previous interactions
appears.
1. **Select interaction:** Use the **Up/Down arrow keys** to navigate through
the list. The most recent interactions are at the bottom.
2. **Preview:** As you select an interaction, you'll see a preview of the user
prompt and, if applicable, the number of files changed during that step.
3. **Confirm selection:** Press **Enter** on the interaction you want to rewind
back to.
4. **Action selection:** After selecting an interaction, you'll be presented
with a confirmation dialog with up to three options:
- **Rewind conversation and revert code changes:** Reverts both the chat
history and the file modifications to the state before the selected
interaction.
- **Rewind conversation:** Only reverts the chat history. File changes are
kept.
- **Revert code changes:** Only reverts the file modifications. The chat
history is kept.
- **Do nothing (esc):** Cancels the rewind operation.
If no code changes were made since the selected point, the options related to
reverting code changes will be hidden.
## Key considerations
- **Destructive action:** Rewinding is a destructive action for your current
session history and potentially your files. Use it with care.
- **Agent awareness:** When you rewind the conversation, the AI model loses all
memory of the interactions that were removed. If you only revert code changes,
you may need to inform the model that the files have changed.
- **Manual edits:** Rewinding only affects file changes made by the AI's edit
tools. It does **not** undo manual edits you've made or changes triggered by
the shell tool (`!`).
- **Compression:** Rewind works across chat compression points by reconstructing
the history from stored session data.
+7 -8
View File
@@ -11,7 +11,7 @@ Before using sandboxing, you need to install and set up the Gemini CLI:
npm install -g @google/gemini-cli
```
To verify the installation:
To verify the installation
```bash
gemini --version
@@ -82,13 +82,12 @@ gemini -p "run the test suite"
Built-in profiles (set via `SEATBELT_PROFILE` env var):
- `permissive-open` (default): Write restrictions, network allowed
- `permissive-closed`: Write restrictions, no network
- `permissive-proxied`: Write restrictions, network via proxy
- `restrictive-open`: Strict restrictions, network allowed
- `restrictive-proxied`: Strict restrictions, network via proxy
- `strict-open`: Read and write restrictions, network allowed
- `strict-proxied`: Read and write restrictions, network via proxy
- `restrictive-closed`: Maximum restrictions
### Custom sandbox flags
### Custom Sandbox Flags
For container-based sandboxing, you can inject custom flags into the `docker` or
`podman` command using the `SANDBOX_FLAGS` environment variable. This is useful
@@ -167,6 +166,6 @@ gemini -s -p "run shell command: mount | grep workspace"
## Related documentation
- [Configuration](../reference/configuration.md): Full configuration options.
- [Commands](../reference/commands.md): Available commands.
- [Troubleshooting](../resources/troubleshooting.md): General troubleshooting.
- [Configuration](../get-started/configuration.md): Full configuration options.
- [Commands](./commands.md): Available commands.
- [Troubleshooting](../troubleshooting.md): General troubleshooting.
-175
View File
@@ -1,175 +0,0 @@
# Session management
Session management saves your conversation history so you can resume your work
where you left off. Use these features to review past interactions, manage
history across different projects, and configure how long data is retained.
## Automatic saving
Your session history is recorded automatically as you interact with the model.
This background process ensures your work is preserved even if you interrupt a
session.
- **What is saved:** The complete conversation history, including:
- Your prompts and the model's responses.
- All tool executions (inputs and outputs).
- Token usage statistics (input, output, cached, etc.).
- Assistant thoughts and reasoning summaries (when available).
- **Location:** Sessions are stored in `~/.gemini/tmp/<project_hash>/chats/`,
where `<project_hash>` is a unique identifier based on your project's root
directory.
- **Scope:** Sessions are project-specific. Switching directories to a different
project switches to that project's session history.
## Resuming sessions
You can resume a previous session to continue the conversation with all prior
context restored. Resuming is supported both through command-line flags and an
interactive browser.
### From the command line
When starting Gemini CLI, use the `--resume` (or `-r`) flag to load existing
sessions.
- **Resume latest:**
```bash
gemini --resume
```
This immediately loads the most recent session.
- **Resume by index:** List available sessions first (see
[Listing sessions](#listing-sessions)), then use the index number:
```bash
gemini --resume 1
```
- **Resume by ID:** You can also provide the full session UUID:
```bash
gemini --resume a1b2c3d4-e5f6-7890-abcd-ef1234567890
```
### From the interactive interface
While the CLI is running, use the `/resume` slash command to open the **Session
Browser**:
```text
/resume
```
The Session Browser provides an interactive interface where you can perform the
following actions:
- **Browse:** Scroll through a list of your past sessions.
- **Preview:** See details like the session date, message count, and the first
user prompt.
- **Search:** Press `/` to enter search mode, then type to filter sessions by ID
or content.
- **Select:** Press **Enter** to resume the selected session.
- **Esc:** Press **Esc** to exit the Session Browser.
## Managing sessions
You can list and delete sessions to keep your history organized and manage disk
space.
### Listing sessions
To see a list of all available sessions for the current project from the command
line, use the `--list-sessions` flag:
```bash
gemini --list-sessions
```
Output example:
```text
Available sessions for this project (3):
1. Fix bug in auth (2 days ago) [a1b2c3d4]
2. Refactor database schema (5 hours ago) [e5f67890]
3. Update documentation (Just now) [abcd1234]
```
### Deleting sessions
You can remove old or unwanted sessions to free up space or declutter your
history.
**From the command line:** Use the `--delete-session` flag with an index or ID:
```bash
gemini --delete-session 2
```
**From the Session Browser:**
1. Open the browser with `/resume`.
2. Navigate to the session you want to remove.
3. Press **x**.
## Configuration
You can configure how Gemini CLI manages your session history in your
`settings.json` file. These settings let you control retention policies and
session lengths.
### Session retention
To prevent your history from growing indefinitely, enable automatic cleanup
policies in your settings.
```json
{
"general": {
"sessionRetention": {
"enabled": true,
"maxAge": "30d", // Keep sessions for 30 days
"maxCount": 50 // Keep the 50 most recent sessions
}
}
}
```
- **`enabled`**: (boolean) Master switch for session cleanup. Defaults to
`false`.
- **`maxAge`**: (string) Duration to keep sessions (for example, "24h", "7d",
"4w"). Sessions older than this are deleted.
- **`maxCount`**: (number) Maximum number of sessions to retain. The oldest
sessions exceeding this count are deleted.
- **`minRetention`**: (string) Minimum retention period (safety limit). Defaults
to `"1d"`. Sessions newer than this period are never deleted by automatic
cleanup.
### Session limits
You can limit the length of individual sessions to prevent context windows from
becoming too large and expensive.
```json
{
"model": {
"maxSessionTurns": 100
}
}
```
- **`maxSessionTurns`**: (number) The maximum number of turns (user and model
exchanges) allowed in a single session. Set to `-1` for unlimited (default).
**Behavior when limit is reached:**
- **Interactive mode:** The CLI shows an informational message and stops
sending requests to the model. You must manually start a new session.
- **Non-interactive mode:** The CLI exits with an error.
## Next steps
- Explore the [Memory tool](../tools/memory.md) to save persistent information
across sessions.
- Learn how to [Checkpoint](./checkpointing.md) your session state.
- Check out the [CLI reference](./cli-reference.md) for all command-line flags.
-156
View File
@@ -1,156 +0,0 @@
# Gemini CLI settings (`/settings` command)
Control your Gemini CLI experience with the `/settings` command. The `/settings`
command opens a dialog to view and edit all your Gemini CLI settings, including
your UI experience, keybindings, and accessibility features.
Your Gemini CLI settings are stored in a `settings.json` file. In addition to
using the `/settings` command, you can also edit them in one of the following
locations:
- **User settings**: `~/.gemini/settings.json`
- **Workspace settings**: `your-project/.gemini/settings.json`
Note: Workspace settings override user settings.
## Settings reference
Here is a list of all the available settings, grouped by category and ordered as
they appear in the UI.
<!-- SETTINGS-AUTOGEN:START -->
### General
| UI Label | Setting | Description | Default |
| ----------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
| Default Approval Mode | `general.defaultApprovalMode` | The default approval mode for tool execution. 'default' prompts for approval, 'auto_edit' auto-approves edit tools, and 'plan' is read-only mode. 'yolo' is not supported yet. | `"default"` |
| Enable Auto Update | `general.enableAutoUpdate` | Enable automatic updates. | `true` |
| Enable Notifications | `general.enableNotifications` | Enable run-event notifications for action-required prompts and session completion. Currently macOS only. | `false` |
| Plan Directory | `general.plan.directory` | The directory where planning artifacts are stored. If not specified, defaults to the system temporary directory. | `undefined` |
| Plan Model Routing | `general.plan.modelRouting` | Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pro for the planning phase and Flash for the implementation phase. | `true` |
| Max Chat Model Attempts | `general.maxAttempts` | Maximum number of attempts for requests to the main chat model. Cannot exceed 10. | `10` |
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `false` |
| Keep chat history | `general.sessionRetention.maxAge` | Automatically delete chats older than this time period (e.g., "30d", "7d", "24h", "1w") | `undefined` |
### Output
| UI Label | Setting | Description | Default |
| ------------- | --------------- | ------------------------------------------------------ | -------- |
| Output Format | `output.format` | The format of the CLI output. Can be `text` or `json`. | `"text"` |
### UI
| UI Label | Setting | Description | Default |
| ------------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
| Show Compatibility Warnings | `ui.showCompatibilityWarnings` | Show warnings about terminal or OS compatibility issues. | `true` |
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory path in the footer. | `false` |
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window remaining percentage. | `true` |
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
| Show User Identity | `ui.showUserIdentity` | Show the logged-in user's identity (e.g. email) in the UI. | `true` |
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
| Use Background Color | `ui.useBackgroundColor` | Whether to use background colors in the UI. | `true` |
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
| Show Spinner | `ui.showSpinner` | Show the spinner during operations. | `true` |
| Loading Phrases | `ui.loadingPhrases` | What to show while the model is working: tips, witty comments, both, or nothing. | `"tips"` |
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
### IDE
| UI Label | Setting | Description | Default |
| -------- | ------------- | ---------------------------- | ------- |
| IDE Mode | `ide.enabled` | Enable IDE integration mode. | `false` |
### Model
| UI Label | Setting | Description | Default |
| ----------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | ------- |
| Max Session Turns | `model.maxSessionTurns` | Maximum number of user/model/tool turns to keep in a session. -1 means unlimited. | `-1` |
| Compression Threshold | `model.compressionThreshold` | The fraction of context usage at which to trigger context compression (e.g. 0.2, 0.3). | `0.5` |
| Disable Loop Detection | `model.disableLoopDetection` | Disable automatic detection and prevention of infinite loops. | `false` |
| Skip Next Speaker Check | `model.skipNextSpeakerCheck` | Skip the next speaker check. | `true` |
### Context
| UI Label | Setting | Description | Default |
| ------------------------------------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Memory Discovery Max Dirs | `context.discoveryMaxDirs` | Maximum number of directories to search for memory. | `200` |
| Load Memory From Include Directories | `context.loadMemoryFromIncludeDirectories` | Controls how /memory refresh loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used. | `false` |
| Respect .gitignore | `context.fileFiltering.respectGitIgnore` | Respect .gitignore files when searching. | `true` |
| Respect .geminiignore | `context.fileFiltering.respectGeminiIgnore` | Respect .geminiignore files when searching. | `true` |
| Enable Recursive File Search | `context.fileFiltering.enableRecursiveFileSearch` | Enable recursive file search functionality when completing @ references in the prompt. | `true` |
| Enable Fuzzy Search | `context.fileFiltering.enableFuzzySearch` | Enable fuzzy search when searching for files. | `true` |
| Custom Ignore File Paths | `context.fileFiltering.customIgnoreFilePaths` | Additional ignore file paths to respect. These files take precedence over .geminiignore and .gitignore. Files earlier in the array take precedence over files later in the array, e.g. the first file takes precedence over the second one. | `[]` |
### Tools
| UI Label | Setting | Description | Default |
| -------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Enable Interactive Shell | `tools.shell.enableInteractiveShell` | Use node-pty for an interactive shell experience. Fallback to child_process still applies. | `true` |
| Show Color | `tools.shell.showColor` | Show color in shell output. | `false` |
| Use Ripgrep | `tools.useRipgrep` | Use ripgrep for file content search instead of the fallback implementation. Provides faster search performance. | `true` |
| Tool Output Truncation Threshold | `tools.truncateToolOutputThreshold` | Maximum characters to show when truncating large tool outputs. Set to 0 or negative to disable truncation. | `40000` |
| Disable LLM Correction | `tools.disableLLMCorrection` | Disable LLM-based error correction for edit tools. When enabled, tools will fail immediately if exact string matches are not found, instead of attempting to self-correct. | `true` |
### Security
| UI Label | Setting | Description | Default |
| ------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| Disable YOLO Mode | `security.disableYoloMode` | Disable YOLO mode, even if enabled by a flag. | `false` |
| Allow Permanent Tool Approval | `security.enablePermanentToolApproval` | Enable the "Allow for all future sessions" option in tool confirmation dialogs. | `false` |
| Blocks extensions from Git | `security.blockGitExtensions` | Blocks installing and loading extensions from Git. | `false` |
| Extension Source Regex Allowlist | `security.allowedExtensions` | List of Regex patterns for allowed extensions. If nonempty, only extensions that match the patterns in this list are allowed. Overrides the blockGitExtensions setting. | `[]` |
| Folder Trust | `security.folderTrust.enabled` | Setting to track whether Folder trust is enabled. | `true` |
| Enable Environment Variable Redaction | `security.environmentVariableRedaction.enabled` | Enable redaction of environment variables that may contain secrets. | `false` |
| Enable Context-Aware Security | `security.enableConseca` | Enable the context-aware security checker. This feature uses an LLM to dynamically generate and enforce security policies for tool use based on your prompt, providing an additional layer of protection against unintended actions. | `false` |
### Advanced
| UI Label | Setting | Description | Default |
| --------------------------------- | ------------------------------ | --------------------------------------------- | ------- |
| Auto Configure Max Old Space Size | `advanced.autoConfigureMemory` | Automatically configure Node.js memory limits | `false` |
### Experimental
| UI Label | Setting | Description | Default |
| -------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Enable Tool Output Masking | `experimental.toolOutputMasking.enabled` | Enables tool output masking to save tokens. | `true` |
| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 for pasting. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
| Use OSC 52 Copy | `experimental.useOSC52Copy` | Use OSC 52 for copying. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
| Plan | `experimental.plan` | Enable planning features (Plan Mode and tools). | `false` |
| Model Steering | `experimental.modelSteering` | Enable model steering (user hints) to guide the model during tool execution. | `false` |
| Direct Web Fetch | `experimental.directWebFetch` | Enable web fetch behavior that bypasses LLM summarization. | `false` |
### Skills
| UI Label | Setting | Description | Default |
| ------------------- | ---------------- | -------------------- | ------- |
| Enable Agent Skills | `skills.enabled` | Enable Agent Skills. | `true` |
### HooksConfig
| UI Label | Setting | Description | Default |
| ------------------ | --------------------------- | -------------------------------------------------------------------------------- | ------- |
| Enable Hooks | `hooksConfig.enabled` | Canonical toggle for the hooks system. When disabled, no hooks will be executed. | `true` |
| Hook Notifications | `hooksConfig.notifications` | Show visual indicators when hooks are executing. | `true` |
<!-- SETTINGS-AUTOGEN:END -->
-134
View File
@@ -1,134 +0,0 @@
# Agent Skills
Agent Skills allow you to extend Gemini CLI with specialized expertise,
procedural workflows, and task-specific resources. Based on the
[Agent Skills](https://agentskills.io) open standard, a "skill" is a
self-contained directory that packages instructions and assets into a
discoverable capability.
## Overview
Unlike general context files ([`GEMINI.md`](./gemini-md.md)), which provide
persistent workspace-wide background, Skills represent **on-demand expertise**.
This allows Gemini to maintain a vast library of specialized capabilities—such
as security auditing, cloud deployments, or codebase migrations—without
cluttering the model's immediate context window.
Gemini autonomously decides when to employ a skill based on your request and the
skill's description. When a relevant skill is identified, the model "pulls in"
the full instructions and resources required to complete the task using the
`activate_skill` tool.
## Key Benefits
- **Shared Expertise:** Package complex workflows (like a specific team's PR
review process) into a folder that anyone can use.
- **Repeatable Workflows:** Ensure complex multi-step tasks are performed
consistently by providing a procedural framework.
- **Resource Bundling:** Include scripts, templates, or example data alongside
instructions so the agent has everything it needs.
- **Progressive Disclosure:** Only skill metadata (name and description) is
loaded initially. Detailed instructions and resources are only disclosed when
the model explicitly activates the skill, saving context tokens.
## Skill Discovery Tiers
Gemini CLI discovers skills from three primary locations:
1. **Workspace Skills**: Located in `.gemini/skills/` or the `.agents/skills/`
alias. Workspace skills are typically committed to version control and
shared with the team.
2. **User Skills**: Located in `~/.gemini/skills/` or the `~/.agents/skills/`
alias. These are personal skills available across all your workspaces.
3. **Extension Skills**: Skills bundled within installed
[extensions](../extensions/index.md).
**Precedence:** If multiple skills share the same name, higher-precedence
locations override lower ones: **Workspace > User > Extension**.
Within the same tier (user or workspace), the `.agents/skills/` alias takes
precedence over the `.gemini/skills/` directory. This generic alias provides an
intuitive path for managing agent-specific expertise that remains compatible
across different AI agent tools.
## Managing Skills
### In an Interactive Session
Use the `/skills` slash command to view and manage available expertise:
- `/skills list` (default): Shows all discovered skills and their status.
- `/skills link <path>`: Links agent skills from a local directory via symlink.
- `/skills disable <name>`: Prevents a specific skill from being used.
- `/skills enable <name>`: Re-enables a disabled skill.
- `/skills reload`: Refreshes the list of discovered skills from all tiers.
_Note: `/skills disable` and `/skills enable` default to the `user` scope. Use
`--scope workspace` to manage workspace-specific settings._
### From the Terminal
The `gemini skills` command provides management utilities:
```bash
# List all discovered skills
gemini skills list
# Link agent skills from a local directory via symlink
# Discovers skills (SKILL.md or */SKILL.md) and creates symlinks in ~/.gemini/skills
# (or ~/.agents/skills)
gemini skills link /path/to/my-skills-repo
# Link to the workspace scope (.gemini/skills or .agents/skills)
gemini skills link /path/to/my-skills-repo --scope workspace
# Install a skill from a Git repository, local directory, or zipped skill file (.skill)
# Uses the user scope by default (~/.gemini/skills or ~/.agents/skills)
gemini skills install https://github.com/user/repo.git
gemini skills install /path/to/local/skill
gemini skills install /path/to/local/my-expertise.skill
# Install a specific skill from a monorepo or subdirectory using --path
gemini skills install https://github.com/my-org/my-skills.git --path skills/frontend-design
# Install to the workspace scope (.gemini/skills or .agents/skills)
gemini skills install /path/to/skill --scope workspace
# Uninstall a skill by name
gemini skills uninstall my-expertise --scope workspace
# Enable a skill (globally)
gemini skills enable my-expertise
# Disable a skill. Can use --scope to specify workspace or user (defaults to workspace)
gemini skills disable my-expertise --scope workspace
```
## How it Works
1. **Discovery**: At the start of a session, Gemini CLI scans the discovery
tiers and injects the name and description of all enabled skills into the
system prompt.
2. **Activation**: When Gemini identifies a task matching a skill's
description, it calls the `activate_skill` tool.
3. **Consent**: You will see a confirmation prompt in the UI detailing the
skill's name, purpose, and the directory path it will gain access to.
4. **Injection**: Upon your approval:
- The `SKILL.md` body and folder structure is added to the conversation
history.
- The skill's directory is added to the agent's allowed file paths, granting
it permission to read any bundled assets.
5. **Execution**: The model proceeds with the specialized expertise active. It
is instructed to prioritize the skill's procedural guidance within reason.
### Skill activation
Once a skill is activated (typically by Gemini identifying a task that matches
the skill's description and your approval), its specialized instructions and
resources are loaded into the agent's context. A skill remains active and its
guidance is prioritized for the duration of the session.
## Creating your own skills
To create your own skills, see the [Create Agent Skills](./creating-skills.md)
guide.
-125
View File
@@ -1,125 +0,0 @@
# System Prompt Override (GEMINI_SYSTEM_MD)
The core system instructions that guide Gemini CLI can be completely replaced
with your own Markdown file. This feature is controlled via the
`GEMINI_SYSTEM_MD` environment variable.
## Overview
The `GEMINI_SYSTEM_MD` variable instructs the CLI to use an external Markdown
file for its system prompt, completely overriding the built-in default. This is
a full replacement, not a merge. If you use a custom file, none of the original
core instructions will apply unless you include them yourself.
This feature is intended for advanced users who need to enforce strict,
project-specific behavior or create a customized persona.
> Tip: You can export the current default system prompt to a file first, review
> it, and then selectively modify or replace it (see
> [“Export the default prompt”](#export-the-default-prompt-recommended)).
## How to enable
You can set the environment variable temporarily in your shell, or persist it
via a `.gemini/.env` file. See
[Persisting Environment Variables](../get-started/authentication.md#persisting-environment-variables).
- Use the project default path (`.gemini/system.md`):
- `GEMINI_SYSTEM_MD=true` or `GEMINI_SYSTEM_MD=1`
- The CLI reads `./.gemini/system.md` (relative to your current project
directory).
- Use a custom file path:
- `GEMINI_SYSTEM_MD=/absolute/path/to/my-system.md`
- Relative paths are supported and resolved from the current working
directory.
- Tilde expansion is supported (e.g., `~/my-system.md`).
- Disable the override (use builtin prompt):
- `GEMINI_SYSTEM_MD=false` or `GEMINI_SYSTEM_MD=0` or unset the variable.
If the override is enabled but the target file does not exist, the CLI will
error with: `missing system prompt file '<path>'`.
## Quick examples
- Oneoff session using a project file:
- `GEMINI_SYSTEM_MD=1 gemini`
- Persist for a project using `.gemini/.env`:
- Create `.gemini/system.md`, then add to `.gemini/.env`:
- `GEMINI_SYSTEM_MD=1`
- Use a custom file under your home directory:
- `GEMINI_SYSTEM_MD=~/prompts/SYSTEM.md gemini`
## UI indicator
When `GEMINI_SYSTEM_MD` is active, the CLI shows a `|⌐■_■|` indicator in the UI
to signal custom systemprompt mode.
## Variable Substitution
When using a custom system prompt file, you can use the following variables to
dynamically include built-in content:
- `${AgentSkills}`: Injects a complete section (including header) of all
available agent skills.
- `${SubAgents}`: Injects a complete section (including header) of available
sub-agents.
- `${AvailableTools}`: Injects a bulleted list of all currently enabled tool
names.
- Tool Name Variables: Injects the actual name of a tool using the pattern:
`${toolName}_ToolName` (e.g., `${write_file_ToolName}`,
`${run_shell_command_ToolName}`).
This pattern is generated dynamically for all available tools.
### Example
```markdown
# Custom System Prompt
You are a helpful assistant. ${AgentSkills}
${SubAgents}
## Tooling
The following tools are available to you: ${AvailableTools}
You can use ${write_file_ToolName} to save logs.
```
## Export the default prompt (recommended)
Before overriding, export the current default prompt so you can review required
safety and workflow rules.
- Write the builtin prompt to the project default path:
- `GEMINI_WRITE_SYSTEM_MD=1 gemini`
- Or write to a custom path:
- `GEMINI_WRITE_SYSTEM_MD=~/prompts/DEFAULT_SYSTEM.md gemini`
This creates the file and writes the current builtin system prompt to it.
## Best practices: SYSTEM.md vs GEMINI.md
- SYSTEM.md (firmware):
- Nonnegotiable operational rules: safety, tooluse protocols, approvals, and
mechanics that keep the CLI reliable.
- Stable across tasks and projects (or per project when needed).
- GEMINI.md (strategy):
- Persona, goals, methodologies, and project/domain context.
- Evolves per task; relies on SYSTEM.md for safe execution.
Keep SYSTEM.md minimal but complete for safety and tool operation. Keep
GEMINI.md focused on highlevel guidance and project specifics.
## Troubleshooting
- Error: `missing system prompt file '…'`
- Ensure the referenced path exists and is readable.
- For `GEMINI_SYSTEM_MD=1|true`, create `./.gemini/system.md` in your project.
- Override not taking effect
- Confirm the variable is loaded (use `.gemini/.env` or export in your shell).
- Paths are resolved from the current working directory; try an absolute path.
- Restore defaults
- Unset `GEMINI_SYSTEM_MD` or set it to `0`/`false`.
+66 -164
View File
@@ -3,30 +3,27 @@
Learn how to enable and setup OpenTelemetry for Gemini CLI.
- [Observability with OpenTelemetry](#observability-with-opentelemetry)
- [Key benefits](#key-benefits)
- [OpenTelemetry integration](#opentelemetry-integration)
- [Key Benefits](#key-benefits)
- [OpenTelemetry Integration](#opentelemetry-integration)
- [Configuration](#configuration)
- [Google Cloud telemetry](#google-cloud-telemetry)
- [Google Cloud Telemetry](#google-cloud-telemetry)
- [Prerequisites](#prerequisites)
- [Authenticating with CLI Credentials](#authenticating-with-cli-credentials)
- [Direct export (recommended)](#direct-export-recommended)
- [Collector-based export (advanced)](#collector-based-export-advanced)
- [Monitoring Dashboards](#monitoring-dashboards)
- [Local telemetry](#local-telemetry)
- [File-based output (recommended)](#file-based-output-recommended)
- [Collector-based export (advanced)](#collector-based-export-advanced-1)
- [Logs and metrics](#logs-and-metrics)
- [Direct Export (Recommended)](#direct-export-recommended)
- [Collector-Based Export (Advanced)](#collector-based-export-advanced)
- [Local Telemetry](#local-telemetry)
- [File-based Output (Recommended)](#file-based-output-recommended)
- [Collector-Based Export (Advanced)](#collector-based-export-advanced-1)
- [Logs and Metrics](#logs-and-metrics)
- [Logs](#logs)
- [Sessions](#sessions)
- [Approval Mode](#approval-mode)
- [Tools](#tools)
- [Files](#files)
- [API](#api)
- [Model routing](#model-routing)
- [Chat and streaming](#chat-and-streaming)
- [Model Routing](#model-routing)
- [Chat and Streaming](#chat-and-streaming)
- [Resilience](#resilience)
- [Extensions](#extensions)
- [Agent runs](#agent-runs)
- [Agent Runs](#agent-runs)
- [IDE](#ide)
- [UI](#ui)
- [Metrics](#metrics)
@@ -34,40 +31,40 @@ Learn how to enable and setup OpenTelemetry for Gemini CLI.
- [Sessions](#sessions-1)
- [Tools](#tools-1)
- [API](#api-1)
- [Token usage](#token-usage)
- [Token Usage](#token-usage)
- [Files](#files-1)
- [Chat and streaming](#chat-and-streaming-1)
- [Model routing](#model-routing-1)
- [Agent runs](#agent-runs-1)
- [Chat and Streaming](#chat-and-streaming-1)
- [Model Routing](#model-routing-1)
- [Agent Runs](#agent-runs-1)
- [UI](#ui-1)
- [Performance](#performance)
- [GenAI semantic convention](#genai-semantic-convention)
- [GenAI Semantic Convention](#genai-semantic-convention)
## Key benefits
## Key Benefits
- **🔍 Usage analytics**: Understand interaction patterns and feature adoption
- **🔍 Usage Analytics**: Understand interaction patterns and feature adoption
across your team
- **⚡ Performance monitoring**: Track response times, token consumption, and
- **⚡ Performance Monitoring**: Track response times, token consumption, and
resource utilization
- **🐛 Real-time debugging**: Identify bottlenecks, failures, and error patterns
- **🐛 Real-time Debugging**: Identify bottlenecks, failures, and error patterns
as they occur
- **📊 Workflow optimization**: Make informed decisions to improve
- **📊 Workflow Optimization**: Make informed decisions to improve
configurations and processes
- **🏢 Enterprise governance**: Monitor usage across teams, track costs, ensure
- **🏢 Enterprise Governance**: Monitor usage across teams, track costs, ensure
compliance, and integrate with existing monitoring infrastructure
## OpenTelemetry integration
## OpenTelemetry Integration
Built on **[OpenTelemetry]** — the vendor-neutral, industry-standard
observability framework — Gemini CLI's observability system provides:
- **Universal compatibility**: Export to any OpenTelemetry backend (Google
- **Universal Compatibility**: Export to any OpenTelemetry backend (Google
Cloud, Jaeger, Prometheus, Datadog, etc.)
- **Standardized data**: Use consistent formats and collection methods across
- **Standardized Data**: Use consistent formats and collection methods across
your toolchain
- **Future-proof integration**: Connect with existing and future observability
- **Future-Proof Integration**: Connect with existing and future observability
infrastructure
- **No vendor lock-in**: Switch between backends without changing your
- **No Vendor Lock-in**: Switch between backends without changing your
instrumentation
[OpenTelemetry]: https://opentelemetry.io/
@@ -77,25 +74,24 @@ observability framework — Gemini CLI's observability system provides:
All telemetry behavior is controlled through your `.gemini/settings.json` file.
Environment variables can be used to override the settings in the file.
| Setting | Environment Variable | Description | Values | Default |
| -------------- | -------------------------------- | --------------------------------------------------- | ----------------- | ----------------------- |
| `enabled` | `GEMINI_TELEMETRY_ENABLED` | Enable or disable telemetry | `true`/`false` | `false` |
| `target` | `GEMINI_TELEMETRY_TARGET` | Where to send telemetry data | `"gcp"`/`"local"` | `"local"` |
| `otlpEndpoint` | `GEMINI_TELEMETRY_OTLP_ENDPOINT` | OTLP collector endpoint | URL string | `http://localhost:4317` |
| `otlpProtocol` | `GEMINI_TELEMETRY_OTLP_PROTOCOL` | OTLP transport protocol | `"grpc"`/`"http"` | `"grpc"` |
| `outfile` | `GEMINI_TELEMETRY_OUTFILE` | Save telemetry to file (overrides `otlpEndpoint`) | file path | - |
| `logPrompts` | `GEMINI_TELEMETRY_LOG_PROMPTS` | Include prompts in telemetry logs | `true`/`false` | `true` |
| `useCollector` | `GEMINI_TELEMETRY_USE_COLLECTOR` | Use external OTLP collector (advanced) | `true`/`false` | `false` |
| `useCliAuth` | `GEMINI_TELEMETRY_USE_CLI_AUTH` | Use CLI credentials for telemetry (GCP target only) | `true`/`false` | `false` |
| Setting | Environment Variable | Description | Values | Default |
| -------------- | -------------------------------- | ------------------------------------------------- | ----------------- | ----------------------- |
| `enabled` | `GEMINI_TELEMETRY_ENABLED` | Enable or disable telemetry | `true`/`false` | `false` |
| `target` | `GEMINI_TELEMETRY_TARGET` | Where to send telemetry data | `"gcp"`/`"local"` | `"local"` |
| `otlpEndpoint` | `GEMINI_TELEMETRY_OTLP_ENDPOINT` | OTLP collector endpoint | URL string | `http://localhost:4317` |
| `otlpProtocol` | `GEMINI_TELEMETRY_OTLP_PROTOCOL` | OTLP transport protocol | `"grpc"`/`"http"` | `"grpc"` |
| `outfile` | `GEMINI_TELEMETRY_OUTFILE` | Save telemetry to file (overrides `otlpEndpoint`) | file path | - |
| `logPrompts` | `GEMINI_TELEMETRY_LOG_PROMPTS` | Include prompts in telemetry logs | `true`/`false` | `true` |
| `useCollector` | `GEMINI_TELEMETRY_USE_COLLECTOR` | Use external OTLP collector (advanced) | `true`/`false` | `false` |
**Note on boolean environment variables:** For the boolean settings (`enabled`,
`logPrompts`, `useCollector`), setting the corresponding environment variable to
`true` or `1` will enable the feature. Any other value will disable it.
For detailed information about all configuration options, see the
[Configuration guide](../reference/configuration.md).
[Configuration Guide](../get-started/configuration.md).
## Google Cloud telemetry
## Google Cloud Telemetry
### Prerequisites
@@ -134,35 +130,7 @@ Before using either method below, complete these steps:
--project="$OTLP_GOOGLE_CLOUD_PROJECT"
```
### Authenticating with CLI Credentials
By default, the telemetry collector for Google Cloud uses Application Default
Credentials (ADC). However, you can configure it to use the same OAuth
credentials that you use to log in to the Gemini CLI. This is useful in
environments where you don't have ADC set up.
To enable this, set the `useCliAuth` property in your `telemetry` settings to
`true`:
```json
{
"telemetry": {
"enabled": true,
"target": "gcp",
"useCliAuth": true
}
}
```
**Important:**
- This setting requires the use of **Direct Export** (in-process exporters).
- It **cannot** be used with `useCollector: true`. If you enable both, telemetry
will be disabled and an error will be logged.
- The CLI will automatically use your credentials to authenticate with Google
Cloud Trace, Metrics, and Logging APIs.
### Direct export (recommended)
### Direct Export (Recommended)
Sends telemetry directly to Google Cloud services. No collector needed.
@@ -182,7 +150,7 @@ Sends telemetry directly to Google Cloud services. No collector needed.
- Metrics: https://console.cloud.google.com/monitoring/metrics-explorer
- Traces: https://console.cloud.google.com/traces/list
### Collector-based export (advanced)
### Collector-Based Export (Advanced)
For custom processing, filtering, or routing, use an OpenTelemetry collector to
forward data to Google Cloud.
@@ -216,29 +184,11 @@ forward data to Google Cloud.
- Open `~/.gemini/tmp/<projectHash>/otel/collector-gcp.log` to view local
collector logs.
### Monitoring Dashboards
Gemini CLI provides a pre-configured
[Google Cloud Monitoring](https://cloud.google.com/monitoring) dashboard to
visualize your telemetry.
This dashboard can be found under **Google Cloud Monitoring Dashboard
Templates** as "**Gemini CLI Monitoring**".
![Gemini CLI Monitoring Dashboard Overview](/docs/assets/monitoring-dashboard-overview.png)
![Gemini CLI Monitoring Dashboard Metrics](/docs/assets/monitoring-dashboard-metrics.png)
![Gemini CLI Monitoring Dashboard Logs](/docs/assets/monitoring-dashboard-logs.png)
To learn more, check out this blog post:
[Instant insights: Gemini CLIs new pre-configured monitoring dashboards](https://cloud.google.com/blog/topics/developers-practitioners/instant-insights-gemini-clis-new-pre-configured-monitoring-dashboards/).
## Local telemetry
## Local Telemetry
For local development and debugging, you can capture telemetry data locally:
### File-based output (recommended)
### File-based Output (Recommended)
1. Enable telemetry in your `.gemini/settings.json`:
```json
@@ -254,7 +204,7 @@ For local development and debugging, you can capture telemetry data locally:
2. Run Gemini CLI and send prompts.
3. View logs and metrics in the specified file (e.g., `.gemini/telemetry.log`).
### Collector-based export (advanced)
### Collector-Based Export (Advanced)
1. Run the automation script:
```bash
@@ -270,14 +220,14 @@ For local development and debugging, you can capture telemetry data locally:
3. View traces at http://localhost:16686 and logs/metrics in the collector log
file.
## Logs and metrics
## Logs and Metrics
The following section describes the structure of logs and metrics generated for
Gemini CLI.
The `session.id`, `installation.id`, `active_approval_mode`, and `user.email`
(available only when authenticated with a Google account) are included as common
attributes on all logs and metrics.
The `session.id`, `installation.id`, and `user.email` (available only when
authenticated with a Google account) are included as common attributes on all
logs and metrics.
### Logs
@@ -316,34 +266,9 @@ Captures startup configuration and user prompt submissions.
- `prompt` (string; excluded if `telemetry.logPrompts` is `false`)
- `auth_type` (string)
#### Approval Mode
Tracks changes and duration of approval modes.
##### Lifecycle
- `approval_mode_switch`: Approval mode was changed.
- **Attributes**:
- `from_mode` (string)
- `to_mode` (string)
- `approval_mode_duration`: Duration spent in an approval mode.
- **Attributes**:
- `mode` (string)
- `duration_ms` (int)
##### Execution
These events track the execution of an approval mode, such as Plan Mode.
- `plan_execution`: A plan was executed and the session switched from plan mode
to active execution.
- **Attributes**:
- `approval_mode` (string)
#### Tools
Captures tool executions, output truncation, and Edit behavior.
Captures tool executions, output truncation, and Smart Edit behavior.
- `gemini_cli.tool_call`: Emitted for each tool (function) call.
- **Attributes**:
@@ -360,21 +285,7 @@ Captures tool executions, output truncation, and Edit behavior.
- `extension_name` (string, if applicable)
- `extension_id` (string, if applicable)
- `content_length` (int, if applicable)
- `metadata` (if applicable), which includes for the `AskUser` tool:
- `ask_user` (object):
- `question_types` (array of strings)
- `ask_user_dismissed` (boolean)
- `ask_user_empty_submission` (boolean)
- `ask_user_answer_count` (number)
- `diffStat` (if applicable), which includes:
- `model_added_lines` (number)
- `model_removed_lines` (number)
- `model_added_chars` (number)
- `model_removed_chars` (number)
- `user_added_lines` (number)
- `user_removed_lines` (number)
- `user_added_chars` (number)
- `user_removed_chars` (number)
- `metadata` (if applicable)
- `gemini_cli.tool_output_truncated`: Output of a tool call was truncated.
- **Attributes**:
@@ -385,11 +296,11 @@ Captures tool executions, output truncation, and Edit behavior.
- `lines` (int)
- `prompt_id` (string)
- `gemini_cli.edit_strategy`: Edit strategy chosen.
- `gemini_cli.smart_edit_strategy`: Smart Edit strategy chosen.
- **Attributes**:
- `strategy` (string)
- `gemini_cli.edit_correction`: Edit correction result.
- `gemini_cli.smart_edit_correction`: Smart Edit correction result.
- **Attributes**:
- `correction` ("success" | "failure")
@@ -450,7 +361,6 @@ Captures Gemini API requests, responses, and errors.
- `response_text` (string, optional)
- `prompt_id` (string)
- `auth_type` (string)
- `finish_reasons` (array of strings)
- `gemini_cli.api_error`: API request failed.
- **Attributes**:
@@ -467,7 +377,9 @@ Captures Gemini API requests, responses, and errors.
- **Attributes**:
- `model` (string)
#### Model routing
#### Model Routing
Tracks model selections via slash commands and router decisions.
- `gemini_cli.slash_command`: A slash command was executed.
- **Attributes**:
@@ -487,9 +399,10 @@ Captures Gemini API requests, responses, and errors.
- `reasoning` (string, optional)
- `failed` (boolean)
- `error_message` (string, optional)
- `approval_mode` (string)
#### Chat and streaming
#### Chat and Streaming
Observes streaming integrity, compression, and retry behavior.
- `gemini_cli.chat_compression`: Chat context was compressed.
- **Attributes**:
@@ -575,7 +488,9 @@ Tracks extension lifecycle and settings changes.
- `extension_source` (string)
- `status` (string)
#### Agent runs
#### Agent Runs
Tracks agent lifecycle and outcomes.
- `gemini_cli.agent.start`: Agent run started.
- **Attributes**:
@@ -651,7 +566,7 @@ Tracks API request volume and latency.
- `model`
- Note: Overlaps with `gen_ai.client.operation.duration` (GenAI conventions).
##### Token usage
##### Token Usage
Tracks tokens used by model and type.
@@ -679,7 +594,7 @@ Counts file operations with basic context.
- `function_name`
- `type` ("added" or "removed")
##### Chat and streaming
##### Chat and Streaming
Resilience counters for compression, invalid chunks, and retries.
@@ -698,7 +613,7 @@ Resilience counters for compression, invalid chunks, and retries.
- `gemini_cli.chat.content_retry_failure.count` (Counter, Int): Counts requests
where all content retries failed.
##### Model routing
##### Model Routing
Routing latency/failures and slash-command selections.
@@ -712,16 +627,14 @@ Routing latency/failures and slash-command selections.
- **Attributes**:
- `routing.decision_model` (string)
- `routing.decision_source` (string)
- `routing.approval_mode` (string)
- `gemini_cli.model_routing.failure.count` (Counter, Int): Counts model routing
failures.
- **Attributes**:
- `routing.decision_source` (string)
- `routing.error_message` (string)
- `routing.approval_mode` (string)
##### Agent runs
##### Agent Runs
Agent lifecycle metrics: runs, durations, and turns.
@@ -738,17 +651,6 @@ Agent lifecycle metrics: runs, durations, and turns.
- **Attributes**:
- `agent_name` (string)
##### Approval Mode
###### Execution
These metrics track the adoption and usage of specific approval workflows, such
as Plan Mode.
- `gemini_cli.plan.execution.count` (Counter, Int): Counts plan executions.
- **Attributes**:
- `approval_mode` (string)
##### UI
UI stability signals such as flicker count.
@@ -824,7 +726,7 @@ Optional performance monitoring for startup, CPU/memory, and phase timing.
- `current_value` (number)
- `baseline_value` (number)
#### GenAI semantic convention
#### GenAI Semantic Convention
The following metrics comply with [OpenTelemetry GenAI semantic conventions] for
standardized observability across GenAI applications:
+69 -101
View File
@@ -4,29 +4,27 @@ Gemini CLI supports a variety of themes to customize its color scheme and
appearance. You can change the theme to suit your preferences via the `/theme`
command or `"theme":` configuration setting.
## Available themes
## Available Themes
Gemini CLI comes with a selection of pre-defined themes, which you can list
using the `/theme` command within Gemini CLI:
- **Dark themes:**
- **Dark Themes:**
- `ANSI`
- `Atom One`
- `Ayu`
- `Default`
- `Dracula`
- `GitHub`
- `Solarized Dark`
- **Light themes:**
- **Light Themes:**
- `ANSI Light`
- `Ayu Light`
- `Default Light`
- `GitHub Light`
- `Google Code`
- `Solarized Light`
- `Xcode`
### Changing themes
### Changing Themes
1. Enter `/theme` into Gemini CLI.
2. A dialog or selection prompt appears, listing the available themes.
@@ -38,25 +36,25 @@ using the `/theme` command within Gemini CLI:
by a file path), you must remove the `"theme"` setting from the file before you
can change the theme using the `/theme` command.
### Theme persistence
### Theme Persistence
Selected themes are saved in Gemini CLI's
[configuration](../reference/configuration.md) so your preference is remembered
across sessions.
[configuration](../get-started/configuration.md) so your preference is
remembered across sessions.
---
## Custom color themes
## Custom Color Themes
Gemini CLI lets you create your own custom color themes by specifying them in
your `settings.json` file. This gives you full control over the color palette
Gemini CLI allows you to create your own custom color themes by specifying them
in your `settings.json` file. This gives you full control over the color palette
used in the CLI.
### How to define a custom theme
### How to Define a Custom Theme
Add a `customThemes` block to your user, project, or system `settings.json`
file. Each custom theme is defined as an object with a unique name and a set of
nested configuration objects. For example:
color keys. For example:
```json
{
@@ -65,52 +63,51 @@ nested configuration objects. For example:
"MyCustomTheme": {
"name": "MyCustomTheme",
"type": "custom",
"background": {
"primary": "#181818"
},
"text": {
"primary": "#f0f0f0",
"secondary": "#a0a0a0"
}
"Background": "#181818",
...
}
}
}
}
```
**Configuration objects:**
**Color keys:**
- **`text`**: Defines text colors.
- `primary`: The default text color.
- `secondary`: Used for less prominent text.
- `link`: Color for URLs and links.
- `accent`: Used for highlights and emphasis.
- `response`: Precedence over `primary` for rendering model responses.
- **`background`**: Defines background colors.
- `primary`: The main background color of the UI.
- `diff.added`: Background for added lines in diffs.
- `diff.removed`: Background for removed lines in diffs.
- **`border`**: Defines border colors.
- `default`: The standard border color.
- `focused`: Border color when an element is focused.
- **`status`**: Colors for status indicators.
- `success`: Used for successful operations.
- `warning`: Used for warnings.
- `error`: Used for errors.
- **`ui`**: Other UI elements.
- `comment`: Color for code comments.
- `symbol`: Color for code symbols and operators.
- `gradient`: An array of colors used for gradient effects.
- `Background`
- `Foreground`
- `LightBlue`
- `AccentBlue`
- `AccentPurple`
- `AccentCyan`
- `AccentGreen`
- `AccentYellow`
- `AccentRed`
- `Comment`
- `Gray`
- `DiffAdded` (optional, for added lines in diffs)
- `DiffRemoved` (optional, for removed lines in diffs)
- `DiffModified` (optional, for modified lines in diffs)
**Required properties:**
You can also override individual UI text roles by adding a nested `text` object.
This object supports the keys `primary`, `secondary`, `link`, `accent`, and
`response`. When `text.response` is provided it takes precedence over
`text.primary` for rendering model responses in chat.
**Required Properties:**
- `name` (must match the key in the `customThemes` object and be a string)
- `type` (must be the string `"custom"`)
While all sub-properties are technically optional, we recommend providing at
least `background.primary`, `text.primary`, `text.secondary`, and the various
accent colors via `text.link`, `text.accent`, and `status` to ensure a cohesive
UI.
- `Background`
- `Foreground`
- `LightBlue`
- `AccentBlue`
- `AccentPurple`
- `AccentCyan`
- `AccentGreen`
- `AccentYellow`
- `AccentRed`
- `Comment`
- `Gray`
You can use either hex codes (e.g., `#FF0000`) **or** standard CSS color names
(e.g., `coral`, `teal`, `blue`) for any color value. See
@@ -120,7 +117,7 @@ for a full list of supported names.
You can define multiple custom themes by adding more entries to the
`customThemes` object.
### Loading themes from a file
### Loading Themes from a File
In addition to defining custom themes in `settings.json`, you can also load a
theme directly from a JSON file by specifying the file path in your
@@ -145,70 +142,49 @@ custom theme defined in `settings.json`.
```json
{
"name": "Gruvbox Dark",
"name": "My File Theme",
"type": "custom",
"background": {
"primary": "#282828",
"diff": {
"added": "#2b3312",
"removed": "#341212"
}
},
"text": {
"primary": "#ebdbb2",
"secondary": "#a89984",
"link": "#83a598",
"accent": "#d3869b"
},
"border": {
"default": "#3c3836",
"focused": "#458588"
},
"status": {
"success": "#b8bb26",
"warning": "#fabd2f",
"error": "#fb4934"
},
"ui": {
"comment": "#928374",
"symbol": "#8ec07c",
"gradient": ["#cc241d", "#d65d0e", "#d79921"]
}
"Background": "#282A36",
"Foreground": "#F8F8F2",
"LightBlue": "#82AAFF",
"AccentBlue": "#61AFEF",
"AccentPurple": "#BD93F9",
"AccentCyan": "#8BE9FD",
"AccentGreen": "#50FA7B",
"AccentYellow": "#F1FA8C",
"AccentRed": "#FF5555",
"Comment": "#6272A4",
"Gray": "#ABB2BF",
"DiffAdded": "#A6E3A1",
"DiffRemoved": "#F38BA8",
"DiffModified": "#89B4FA",
"GradientColors": ["#4796E4", "#847ACE", "#C3677F"]
}
```
**Security note:** For your safety, Gemini CLI will only load theme files that
**Security Note:** For your safety, Gemini CLI will only load theme files that
are located within your home directory. If you attempt to load a theme from
outside your home directory, a warning will be displayed and the theme will not
be loaded. This is to prevent loading potentially malicious theme files from
untrusted sources.
### Example custom theme
### Example Custom Theme
<img src="../assets/theme-custom.png" alt="Custom theme example" width="600" />
### Using your custom theme
### Using Your Custom Theme
- Select your custom theme using the `/theme` command in Gemini CLI. Your custom
theme will appear in the theme selection dialog.
- Or, set it as the default by adding `"theme": "MyCustomTheme"` to the `ui`
object in your `settings.json`.
- Custom themes can be set at the user, project, or system level, and follow the
same [configuration precedence](../reference/configuration.md) as other
same [configuration precedence](../get-started/configuration.md) as other
settings.
### Themes from extensions
[Extensions](../extensions/reference.md#themes) can also provide custom themes.
Once an extension is installed and enabled, its themes are automatically added
to the selection list in the `/theme` command.
Themes from extensions appear with the extension name in parentheses to help you
identify their source, for example: `shades-of-green (green-extension)`.
---
## Dark themes
## Dark Themes
### ANSI
@@ -234,11 +210,7 @@ identify their source, for example: `shades-of-green (green-extension)`.
<img src="/assets/theme-github.png" alt="GitHub theme" width="600">
### Solarized Dark
<img src="/assets/theme-solarized-dark.png" alt="Solarized Dark theme" width="600">
## Light themes
## Light Themes
### ANSI Light
@@ -260,10 +232,6 @@ identify their source, for example: `shades-of-green (green-extension)`.
<img src="/assets/theme-google-light.png" alt="Google Code theme" width="600">
### Solarized Light
<img src="/assets/theme-solarized-light.png" alt="Solarized Light theme" width="600">
### Xcode
<img src="/assets/theme-xcode-light.png" alt="Xcode Light theme" width="600">
+1 -1
View File
@@ -1,4 +1,4 @@
# Token caching and cost optimization
# Token Caching and Cost Optimization
Gemini CLI automatically optimizes API costs through token caching when using
API key authentication (Gemini API key or Vertex AI). This feature reuses
+16 -47
View File
@@ -5,7 +5,7 @@ which projects can use the full capabilities of the Gemini CLI. It prevents
potentially malicious code from running by asking you to approve a folder before
the CLI loads any project-specific configurations from it.
## Enabling the feature
## Enabling the Feature
The Trusted Folders feature is **disabled by default**. To use it, you must
first enable it in your settings.
@@ -22,7 +22,7 @@ Add the following to your user `settings.json` file:
}
```
## How it works: The trust dialog
## How It Works: The Trust Dialog
Once the feature is enabled, the first time you run the Gemini CLI from a
folder, a dialog will automatically appear, prompting you to make a choice:
@@ -38,89 +38,58 @@ folder, a dialog will automatically appear, prompting you to make a choice:
Your choice is saved in a central file (`~/.gemini/trustedFolders.json`), so you
will only be asked once per folder.
## Understanding folder contents: The discovery phase
Before you make a choice, the Gemini CLI performs a **discovery phase** to scan
the folder for potential configurations. This information is displayed in the
trust dialog to help you make an informed decision.
The discovery UI lists the following categories of items found in the project:
- **Commands**: Custom `.toml` command definitions that add new functionality.
- **MCP Servers**: Configured Model Context Protocol servers that the CLI will
attempt to connect to.
- **Hooks**: System or custom hooks that can intercept and modify CLI behavior.
- **Skills**: Local agent skills that provide specialized capabilities.
- **Setting overrides**: Any project-specific configurations that override your
global user settings.
### Security warnings and errors
The trust dialog also highlights critical information that requires your
attention:
- **Security Warnings**: The CLI will explicitly flag potentially dangerous
settings, such as auto-approving certain tools or disabling the security
sandbox.
- **Discovery Errors**: If the CLI encounters issues while scanning the folder
(e.g., a malformed `settings.json` file), these errors will be displayed
prominently.
By reviewing these details, you can ensure that you only grant trust to projects
that you know are safe.
## Why trust matters: The impact of an untrusted workspace
## Why Trust Matters: The Impact of an Untrusted Workspace
When a folder is **untrusted**, the Gemini CLI runs in a restricted "safe mode"
to protect you. In this mode, the following features are disabled:
1. **Workspace settings are ignored**: The CLI will **not** load the
1. **Workspace Settings are Ignored**: The CLI will **not** load the
`.gemini/settings.json` file from the project. This prevents the loading of
custom tools and other potentially dangerous configurations.
2. **Environment variables are ignored**: The CLI will **not** load any `.env`
2. **Environment Variables are Ignored**: The CLI will **not** load any `.env`
files from the project.
3. **Extension management is restricted**: You **cannot install, update, or
3. **Extension Management is Restricted**: You **cannot install, update, or
uninstall** extensions.
4. **Tool auto-acceptance is disabled**: You will always be prompted before any
4. **Tool Auto-Acceptance is Disabled**: You will always be prompted before any
tool is run, even if you have auto-acceptance enabled globally.
5. **Automatic memory loading is disabled**: The CLI will not automatically
5. **Automatic Memory Loading is Disabled**: The CLI will not automatically
load files into context from directories specified in local settings.
6. **MCP servers do not connect**: The CLI will not attempt to connect to any
6. **MCP Servers Do Not Connect**: The CLI will not attempt to connect to any
[Model Context Protocol (MCP)](../tools/mcp-server.md) servers.
7. **Custom commands are not loaded**: The CLI will not load any custom
7. **Custom Commands are Not Loaded**: The CLI will not load any custom
commands from .toml files, including both project-specific and global user
commands.
Granting trust to a folder unlocks the full functionality of the Gemini CLI for
that workspace.
## Managing your trust settings
## Managing Your Trust Settings
If you need to change a decision or see all your settings, you have a couple of
options:
- **Change the current folder's trust**: Run the `/permissions` command from
- **Change the Current Folder's Trust**: Run the `/permissions` command from
within the CLI. This will bring up the same interactive dialog, allowing you
to change the trust level for the current folder.
- **View all trust rules**: To see a complete list of all your trusted and
- **View All Trust Rules**: To see a complete list of all your trusted and
untrusted folder rules, you can inspect the contents of the
`~/.gemini/trustedFolders.json` file in your home directory.
## The trust check process (advanced)
## The Trust Check Process (Advanced)
For advanced users, it's helpful to know the exact order of operations for how
trust is determined:
1. **IDE trust signal**: If you are using the
1. **IDE Trust Signal**: If you are using the
[IDE Integration](../ide-integration/index.md), the CLI first asks the IDE
if the workspace is trusted. The IDE's response takes highest priority.
2. **Local trust file**: If the IDE is not connected, the CLI checks the
2. **Local Trust File**: If the IDE is not connected, the CLI checks the
central `~/.gemini/trustedFolders.json` file.

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