In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines while adding code to packages/cli.
## Testing Standards
* **Async Testing**: ALWAYS use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` to prevent flakiness and `act` warnings. NEVER use fixed waits (e.g., `await delay(100)`).
* **State Changes**: Wrap all blocks that change component state in `act`.
* **Snapshots**: Use `toMatchSnapshot` to verify rendering.
* **Rendering**: Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `ink-testing-library` directly.
* **Mocking**:
* Reuse existing mocks/fakes where possible.
* **Parameterized Tests**: Use parameterized tests with explicit types to reduce duplication and ensure type safety.
* Avoid mocking the file system, os, or child_process if at all possible; if you have to mock the Mock critical dependencies (`fs`, `os`, `child_process`) do so ONLY at the top of the file.
## React & Ink Architecture
* **Keyboard Handling**: You MUST use `useKeyPress.ts` from Gemini CLI for keyboard handling, NOT the standard ink library. This is critical for supporting slow terminals and multiple events per frame.
* Handle multiple events gracefully (often requires a reducer pattern, see `text-buffer.ts`).
* **State Management**:
* NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary.
* Initialize state explicitly (e.g., use `undefined` rather than `true` if unknown).
* **Performance**:
* Avoid synchronous file I/O in components.
* Do not introduce excessive property drilling; leverage or extend existing providers.
## Configuration & Settings
* **Settings vs Args**: Use settings for user-configurable options; do not add new CLI arguments.
* **Schema**: Add new settings to `packages/cli/src/config/settingsSchema.ts`.
* **Documentation**:
* If `showInDialog: true`, document in `docs/get-started/configuration.md`.
* Ensure `requiresRestart` is correctly set.
## Keyboard Shortcuts
* **Registration**: Define new shortcuts in `packages/cli/src/config/keyBindings.ts`.
* **Documentation**: Document all new shortcuts in `docs/cli/keyboard-shortcuts.md`.
* **Compatibility**: Avoid function keys and common VSCode shortcuts. Be cautious with `Meta` key (Mac-limited support).
## General
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
* **TypeScript**: Avoid the non-null assertion operator (`!`).
In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines when writing code in packages/cli.
## Testing Standards
* **Async Testing**: ALWAYS use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` to prevent flakiness and `act` warnings. NEVER use fixed waits (e.g., `await delay(100)`).
* **State Changes**: Wrap all blocks that change component state in `act`.
* **Snapshots**: Use `toMatchSnapshot` to verify rendering.
* **Rendering**: Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `ink-testing-library` directly.
* **Mocking**:
* Reuse existing mocks/fakes where possible.
* **Parameterized Tests**: Use parameterized tests with explicit types to reduce duplication and ensure type safety.
* Avoid mocking the file system, os, or child_process if at all possible; if you have to mock the Mock critical dependencies (`fs`, `os`, `child_process`) do so ONLY at the top of the file.
## React & Ink Architecture
* **Keyboard Handling**: You MUST use `useKeyPress.ts` from Gemini CLI for keyboard handling, NOT the standard ink library. This is critical for supporting slow terminals and multiple events per frame.
* Handle multiple events gracefully (often requires a reducer pattern, see `text-buffer.ts`).
* **State Management**:
* NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary.
* Initialize state explicitly (e.g., use `undefined` rather than `true` if unknown).
* **Performance**:
* Avoid synchronous file I/O in components.
* Do not introduce excessive property drilling; leverage or extend existing providers.
## Configuration & Settings
* **Settings vs Args**: Use settings for user-configurable options; do not add new CLI arguments.
* **Schema**: Add new settings to `packages/cli/src/config/settingsSchema.ts`.
* **Documentation**:
* If `showInDialog: true`, document in `docs/get-started/configuration.md`.
* Ensure `requiresRestart` is correctly set.
## Keyboard Shortcuts
* **Registration**: Define new shortcuts in `packages/cli/src/config/keyBindings.ts`.
* **Documentation**: Document all new shortcuts in `docs/cli/keyboard-shortcuts.md`.
* **Compatibility**: Avoid function keys and common VSCode shortcuts. Be cautious with `Meta` key (Mac-limited support).
## General
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
* **TypeScript**: Avoid the non-null assertion operator (`!`).
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.
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.
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.
description: Trigger this skill when the user wants to start an asynchronous PR review, run background checks on a PR, or check the status of a previously started async PR review.
---
# Async PR Review
This skill provides a set of tools to asynchronously review a Pull Request. It will create a background job to run the project's preflight checks, execute Gemini-powered test plans, and perform a comprehensive code review using custom prompts.
This skill is designed to showcase an advanced "Agentic Asynchronous Pattern":
1.**Native Background Shells vs Headless Inference**: While Gemini CLI can natively spawn and detach background shell commands (using the `run_shell_command` tool with `is_background: true`), a standard bash background job cannot perform LLM inference. To conduct AI-driven code reviews and test generation in the background, the shell script *must* invoke the `gemini` executable headlessly using `-p`. This offloads the AI tasks to independent worker agents.
2.**Dynamic Git Scoping**: The review scripts avoid hardcoded paths. They use `git rev-parse --show-toplevel` to automatically resolve the root of the user's current project.
3.**Ephemeral Worktrees**: Instead of checking out branches in the user's main workspace, the skill provisions temporary git worktrees in `.gemini/tmp/async-reviews/pr-<number>`. This prevents git lock conflicts and namespace pollution.
4.**Agentic Evaluation (`check-async-review.sh`)**: The check script outputs clean JSON/text statuses for the main agent to parse. The interactive agent itself synthesizes the final assessment dynamically from the generated log files.
## Workflow
1.**Determine Action**: Establish whether the user wants to start a new async review or check the status of an existing one.
* If the user says "start an async review for PR #123" or similar, proceed to **Start Review**.
* If the user says "check the status of my async review for PR #123" or similar, proceed to **Check Status**.
### Start Review
If the user wants to start a new async PR review:
1. Ask the user for the PR number if they haven't provided it.
2. Execute the `async-review.sh` script, passing the PR number as the first argument. Be sure to run it with the `is_background` flag set to true to ensure it immediately detaches.
3. **Evaluate Output**: Read the output from the script.
* If the output contains `STATUS: IN_PROGRESS`, tell the user which tasks are still running.
* If the output contains `STATUS: COMPLETE`, use your file reading tools (`read_file`) to retrieve the contents of `final-assessment.md`, `review.md`, `pr-diff.diff`, `npm-test.log`, and `test-execution.log` files from the `LOG_DIR` specified in the output.
***Final Assessment**: Read those files, synthesize their results, and give the user a concise recommendation on whether the PR builds successfully, passes tests, and if you recommend they approve it based on the review.
{{ npm run clean && npm ci && npm run format && npm run build && npm run lint:ci && npm run typecheck;} > "${log_dir}/build-and-lint.log" 2>&1;echo$? > "${log_dir}/build-and-lint.exit";}&
# Dynamically resolve gemini binary (fallback to your nightly path)
echo"CI checks passed. Skipping local npm tests." > "${log_dir}/npm-test.log"
echo0 > "${log_dir}/npm-test.exit"
elif[["${ci_status}" -eq 8]];then
echo"CI checks are still pending. Skipping local npm tests to avoid duplicate work. Please check GitHub for final results." > "${log_dir}/npm-test.log"
echo"Found failing test files from CI:" >> "${log_dir}/npm-test.log"
for f in ${failed_files};doecho" - ${f}" >> "${log_dir}/npm-test.log";done
echo"Running ONLY failing tests locally..." >> "${log_dir}/npm-test.log"
exit_code=0
for file in ${failed_files};do
if[["${file}"== packages/* ]];then
ws_dir="$(echo"${file}"| cut -d'/' -f1,2)"
else
ws_dir="$(echo"${file}"| cut -d'/' -f1)"
fi
rel_file="${file#"${ws_dir}"/}"
echo"--- Running ${rel_file} in workspace ${ws_dir} ---" >> "${log_dir}/npm-test.log"
if ! npm run test:ci -w "${ws_dir}" -- "${rel_file}" >> "${log_dir}/npm-test.log" 2>&1;then
exit_code=1
fi
done
echo"${exit_code}" > "${log_dir}/npm-test.exit"
else
echo"Could not extract specific failing files. Skipping full local test suite as it takes too long. Please check CI logs manually." >> "${log_dir}/npm-test.log"
echo1 > "${log_dir}/npm-test.exit"
fi
fi
else
echo"Skipped due to build-and-lint failure" > "${log_dir}/npm-test.log"
echo1 > "${log_dir}/npm-test.exit"
fi
}&
echo" ↳ [5/5] Starting Gemini test execution (waiting for build and lint)..."
"${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "Analyze the diff for PR ${pr_number} using 'gh pr diff ${pr_number}'. Instead of running the project's automated test suite (like 'npm test'), physically exercise the newly changed code in the terminal (e.g., by writing a temporary script to call the new functions, or testing the CLI command directly). Verify the feature's behavior works as expected. IMPORTANT: Do NOT modify any source code to fix errors. Just exercise the code and log the results, reporting any failures clearly. Do not ask for user confirmation." > "${log_dir}/test-execution.log" 2>&1;echo$? > "${log_dir}/test-execution.exit"
else
echo"Skipped due to build-and-lint failure" > "${log_dir}/test-execution.log"
echo1 > "${log_dir}/test-execution.exit"
fi
}&
echo"✅ All tasks dispatched!"
echo"You can monitor progress with: tail -f ${log_dir}/*.log"
echo"Read your review later at: ${log_dir}/review.md"
# Polling loop to wait for all background tasks to finish
echo"⏳ Tasks complete! Synthesizing final assessment..."
if ! "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "Read the review at ${log_dir}/review.md, the automated test logs at ${log_dir}/npm-test.log, and the manual test execution logs at ${log_dir}/test-execution.log. Summarize the results, state whether the build and tests passed based on ${log_dir}/build-and-lint.exit and ${log_dir}/npm-test.exit, and give a final recommendation for PR ${pr_number}." > "${log_dir}/final-assessment.md" 2>&1;then
echo$? > "${log_dir}/final-assessment.exit"
echo"❌ Final assessment synthesis failed!"
echo"Check ${log_dir}/final-assessment.md for details."
description: Guidance for creating, running, fixing, and promoting behavioral evaluations. Use when verifying agent decision logic, debugging failures, debugging prompt steering, or adding workspace regression tests.
---
# Behavioral Evals
## Overview
Behavioral evaluations (evals) are tests that validate the **agent's decision-making** (e.g., tool choice) rather than pure functionality. They are critical for verifying prompt changes, debugging steerability, and preventing regressions.
> [!NOTE]
> **Single Source of Truth**: For core concepts, policies, running tests, and general best practices, always refer to **[evals/README.md](file:///Users/abhipatel/code/gemini-cli/docs/evals/README.md)**.
---
## 🔄 Workflow Decision Tree
1.**Does a prompt/tool change need validation?**
**No* -> Normal integration tests.
**Yes* -> Continue below.
2.**Is it UI/Interaction heavy?**
**Yes* -> Use `appEvalTest` (`AppRig`). See **[creating.md](references/creating.md)**.
**No* -> Use `evalTest` (`TestRig`). See **[creating.md](references/creating.md)**.
3.**Is it a new test?**
**Yes* -> Set policy to `USUALLY_PASSES`.
**No* -> `ALWAYS_PASSES` (locks in regression).
4.**Are you fixing a failure or promoting a test?**
**Fixing* -> See **[fixing.md](references/fixing.md)**.
**Promoting* -> See **[promoting.md](references/promoting.md)**.
---
## 📋 Quick Checklist
### 1. Setup Workspace
Seed the workspace with necessary files using the `files` object to simulate a realistic scenario (e.g., NodeJS project with `package.json`).
**Details in **[creating.md](references/creating.md)***
### 2. Write Assertions
Audit agent decisions using `rig.setBreakpoint()` (AppRig only) or index verification on `rig.readToolLogs()`.
**Details in **[creating.md](references/creating.md)***
### 3. Verify
Run single tests locally with Vitest. Confirm stability locally before relying on CI workflows.
**See **[evals/README.md](file:///Users/abhipatel/code/gemini-cli/docs/evals/README.md)** for running commands.*
| **`evalTest`** | `./test-helper.js` | **Subprocess**. Runs the CLI in a separate process + waits for exit. | Standard workspace tests. **Do not use `setBreakpoint`**; auditing history (`readToolLogs`) is safer. |
| **`appEvalTest`** | `./app-test-helper.js` | **In-Process**. Runs directly inside the runner loop. | UI/Ink rendering. Safe for `setBreakpoint` triggers. |
---
## 🏗️ Scenario Design
Evals must simulate realistic agent environments to effectively test
decision-making.
- **Workspace State**: Seed with standard project anchors if testing general
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.
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).
description: Analyzes and cleans up GitHub issues. DO NOT trigger this skill automatically. ONLY use when the user explicitly mentions "github-issue-triage", or explicitly asks to "triage issues", "clean up old issues", or "triage this issue".
---
# GitHub Issue Triage
This skill provides workflows for finding, analyzing, and triaging GitHub issues to maintain a clean and actionable backlog.
## Phase 1: Discovery (Optional)
If the user asks you to "triage issues" or "clean up old issues" without providing a specific issue URL, you must first find candidate issues.
- If `is_stale` is `true`, the issue has already been marked as stale and should be closed according to the rules in Phase 3.
- Take note of `inactive_over_30_days`, `inactive_over_60_days`, `is_epic`, and other boolean flags.
## Phase 3: Triage Execution
After analyzing the issue and receiving the JSON output, you MUST consult the detailed triage rules to determine the next steps.
Read the rules in [references/triage_rules.md](references/triage_rules.md) and execute the appropriate steps. You must follow the steps sequentially.
If a step instructs you to **STOP EXECUTION**, you must conclude your work on this issue and not proceed to subsequent steps. If you are triaging a batch of issues, you may move on to the next issue in the list.
**Important Note on CLI Commands**: When posting comments via the `gh` CLI that contain newlines (e.g. `\n`), you MUST use bash command substitution with `echo -e` so the newlines are rendered correctly. For example: `gh issue comment <issue_url> --body "$(echo -e "### Triage Summary\n\n<your summary>")"`.
When executing triage on an issue, you must evaluate the following steps sequentially using the data provided from `scripts/analyze_issue.cjs` and the issue comments (`gh issue view <issue_url> --json comments`).
## Categorization Guide: Help-wanted
When categorizing an issue, determine if it is a good candidate for community contributions. Only use the **Help-wanted** label for these types of issues. Everything else remains unassigned to a specific whitelist label. Examples of **Help-wanted** issues include:
* Small, well-defined features.
* Easy-to-fix bugs (where the root cause might be identified but the fix isn't trivially "simple" enough to just patch immediately).
* Tasks that are clearly scoped and ready for external help.
* Issues that DO NOT require deep architectural knowledge, significant maintainer review time, modifications to core sensitive business logic (telemetry, security, billing), or sweeping UI/UX changes.
Conversely, do **NOT** use the `help wanted` label for issues such as:
* Easily reproducible bugs with a simple identified fix.
* Epics or roadmap initiatives.
* Changes to core architecture, sensitive security fixes, or internal tasks.
* Issues requiring deep investigation.
* Changes to key UI/UX that affect all users.
* Modifications to core internal data structures and IPC mechanisms.
* Changes to token/billing logic.
* Changes to key model and diff/edit functionalities.
* Features or changes that touch multiple parts of the codebase and would require significant reviewer time from maintainers.
* Changes touching key workflows (like the core stream or execution workflows) that affect all users and require careful architectural consideration.
* Changes touching sensitive business logic, telemetry, or API usage statistics/tracking.
* Proposals affecting community guidelines, contributor frameworks, or project governance that require significant maintainer discretion and alignment.
* Complex new subsystems, such as background LLM integration tasks, AI-driven automation, or new agentic behaviors that require significant design validation.
## Step 1: Resolution Check
**CRITICAL MISTAKE PREVENTION**: You MUST thoroughly read every single comment. Look explicitly for phrases like "appears to fix", "fixes this", "might be fixed", "resolved by", "no longer an issue", or links to other PRs/issues that suggest a resolution. Do not skim. If a user (even a non-maintainer) suggests a fix or PR exists, and the original reporter has not contradicted them, you MUST treat the issue as resolved.
Read ALL the comments from the issue carefully, and review the JSON output for `cross_references`.
Check if ANY of the following conditions are met:
1. Is there a cross-referenced PR in `cross_references` where `is_pr` is `true` and `is_merged` is `true`? If so, use `gh pr view <pr_url> --json title,body` to verify that the PR actually addresses and resolves the issue's request. If it does not, treat condition 1 as NOT met.
2. Is it fixed, resolved, no longer reproducible, or functioning properly in the comments? (e.g., someone mentions it `might be fixed`, `should be fixed`, or `no longer an issue`) AND the reporter has not replied afterward to contradict this?
3. Is there a workaround provided in the comments?
4. Does someone state the issue is actually unrelated to this repository/project, or is an external problem (like a terminal emulator bug)?
- If condition 1 is met: Execute `gh issue close <issue_url> --comment "Closing because this issue was referenced by a merged pull request. Feel free to reopen if the problem persists or if the PR did not fully resolve this." --reason "completed"` and **STOP EXECUTION**.
- If condition 2 or 3 is met: Execute `gh issue close <issue_url> --comment "Closing because the comments indicate this issue might be fixed, has a workaround, is no longer an issue, or is resolved. Feel free to reopen if the problem persists." --reason "completed"` and **STOP EXECUTION**.
- If condition 4 is met: Execute `gh issue close <issue_url> --comment "Closing because the comments indicate this issue is unrelated to this project or is an external problem." --reason "not planned"` and **STOP EXECUTION**.
- If NONE of these conditions are met: Proceed to Step 1.1.
## Step 1.1: Existing Feature Check
**CRITICAL MISTAKE PREVENTION**: If the issue describes a feature request or enhancement (regardless of whether the JSON `is_feature_request` flag is true or false), you **MUST explicitly search the codebase** to verify if it is already implemented. You cannot skip this step for feature requests.
1. Use the `grep_search` tool to look for relevant keywords related to the feature in files like `schemas/settings.schema.json`, `packages/cli/src/config/config.ts`, command definitions, or UI components.
- **Hotkeys & UI Actions**: If the user asks for a way to expand text, pause output, copy text, or perform a UI action, explicitly check `packages/cli/src/ui/key/keyBindings.ts` and the `Command` enum. Many interactive features (e.g., `Ctrl+O` for expanding truncated tool confirmations or output) already exist natively.
2. If you verify that the requested functionality (e.g., a setting, flag, hotkey, or command) already exists natively:
- Execute `gh issue close <issue_url> --comment "This feature is actually already implemented! <Provide a brief explanation of how to use the feature, such as the command to run, the setting to change, or the hotkey to press>.\n\nI'm going to close this issue since the functionality already exists natively. Let us know if you run into any other issues!" --reason "completed"`
- **STOP EXECUTION**.
3. If the feature does NOT exist, proceed to Step 1.2.
## Step 1.2: Closed PR Re-evaluation
If there is a cross-referenced PR in `cross_references` where `is_pr` is `true` and `is_merged` is `false` (and its state is `closed` or it has an automated closure comment):
1. Use `gh pr view <pr_url> --json author,comments,state,title,body` to analyze the PR.
2. Check the comments to see if it was closed by an automated bot (e.g., `gemini-cli` bot closing it automatically due to missing labels like 'help wanted' after 14 days).
3. Analyze the PR's title, body, and comments to determine if it implements a valid and useful feature/fix and is worth resuming.
4.**Existing Feature Check**: Check if the requested feature is actually already implemented natively in the codebase (e.g., an existing hotkey, setting, or command). Search the codebase using `grep_search` if unsure.
- If the feature is ALREADY IMPLEMENTED:
a. Do NOT reopen the PR.
b. Execute `gh issue close <issue_url> --comment "This feature is actually already implemented! <Provide a brief explanation of how to use the feature>.\n\nI'm going to close this issue since the functionality already exists natively. Let us know if you run into any other issues!" --reason "completed"`
c. Comment on the PR: `gh pr comment <pr_url> --body "@<author_username>, thank you for your contribution! We've reviewed this again and decided to keep it closed. The core feature requested in the parent issue is actually already implemented natively in the CLI. We appreciate the effort, but this specific PR is no longer needed!"`
d. **STOP EXECUTION**.
5. Critically evaluate the PR's approach for correctness and safety. Ensure it does not introduce breaking changes, make false assumptions (e.g., making an optional configuration mandatory for all users), or negatively impact other workflows.
- If the PR's approach is flawed or introduces breaking changes:
a. Do NOT reopen the PR.
b. Determine if the issue itself should be **Help-wanted** (using the Categorization Guide).
c. If **Help-wanted**, run `gh issue edit <issue_url> --remove-label "status/need-triage" --add-label "help wanted"`. If not, just remove `status/need-triage`.
d. Execute `gh issue comment <issue_url> --body "### Triage Summary\n\nWhile this issue is valid, the proposed fix in PR <pr_url> introduces potential breaking changes or relies on incorrect assumptions (e.g., <brief explanation of the flaw>). Therefore, we will not reopen that PR, but we still welcome a different approach to fix this issue!"`
e. Comment on the PR: `gh pr comment <pr_url> --body "@<author_username>, thank you for your contribution! We've reviewed the approach in this PR and decided to keep it closed because <brief explanation of the flaw>. We still welcome improvements here using a different approach! Feel free to open a new PR if you're interested."`
f. **STOP EXECUTION**.
- If it is worth resuming AND was closed by a bot:
a. Determine if the issue should be **Help-wanted** (using the Categorization Guide).
- Execute `gh issue comment <issue_url> --body "$(echo -e "### Triage Summary\n\n<brief explanation of why this issue requires maintainer attention and is not suitable for community contribution>")"`
- **STOP EXECUTION**. (Do not reopen the PR).
c. If it should be **Help-wanted**:
- Reopen the PR: `gh pr reopen <pr_url>`
- Assign the PR to the author: `gh pr edit <pr_url> --add-assignee <author_username>`
- Assign the issue to the author: `gh issue edit <issue_url> --add-assignee <author_username>`
- Add the help wanted label to the issue to prevent the bot from closing the PR again: `gh issue edit <issue_url> --add-label "help wanted"`
- Comment on the issue: `gh issue comment <issue_url> --body "### Triage Summary\n\n<brief explanation of why this is a help-wanted task>\n\n@<author_username>, apologies! It looks like your PR <pr_url> was incorrectly closed by our bot. I have reopened it and assigned this issue to you. Would you like to continue working on it?"`
- Comment on the PR: `gh pr comment <pr_url> --body "@<author_username>, apologies for the bot closing this PR! We have reopened it. Please sync your branch to the latest \`main\` and we will have someone review it shortly."`
1. Check if the most recent comments include a request for more information, clarification, or reproduction steps directed at the reporter from any other user (maintainer or community member).
2. Check if the reporter has NOT replied to that request.
3. Check if that request was made over 14 days ago. (You can check the date of the comment vs today's date).
4.**CRITICAL**: Before closing, verify if OTHER users have chimed in after the request to provide the necessary context, answer the question on behalf of the reporter, or confirm the bug's existence. If they have, the issue is NO LONGER pending response and you must proceed to Step 2.
- If conditions 1, 2, and 3 are met AND condition 4 is false: Execute `gh issue close <issue_url> --comment "Closing because more information was requested over 2 weeks ago and we haven't received a response. Feel free to reopen if you can provide the requested details." --reason "not planned"` and **STOP EXECUTION**.
- If NOT met: Proceed to Step 2.
## Step 2: Assignee and Inactivity Handling
Use the JSON output from `analyze_issue.cjs` to determine necessary actions.
**CRITICAL VERIFICATION**: Before proceeding, explicitly verify the exact boolean values of `inactive_over_60_days`, `inactive_over_30_days`, and `is_feature_request` in the JSON output. Do not guess these values based on the date. Note that `is_feature_request` might be `false` even for feature requests if the title/labels lack specific keywords; if the body clearly asks for a new feature/enhancement, treat it as a feature request regardless of the JSON flag.
1.**Assignee Check:** If an assignee is a contributor and hasn't made any updates on the issue for over 2 weeks, execute `gh issue edit <issue_url> --remove-assignee <username>` to remove them. (Do this before proceeding further).
2.**Inactivity Check:**
- If `inactive_over_60_days` is `true`:
a. Formulate a comment to the reporter (@<reporter_username>). Evaluate the issue description and whether it is an Epic (`is_epic`):
- Always mention that the issue is being closed or pinged because it has been inactive for over 60 days.
- IF IT IS AN EPIC: Ask the reporter if it is still in progress or complete, and if it is complete, ask them to close it.
- IF IT IS NOT AN EPIC:
- If it's a feature/enhancement request and the description is relatively vague, ask: 1) if it is still needed and 2) if they can provide more details on the feature request.
- If the issue was mentioned by another issue that is closed as completed or by a pull request that is merged/closed (check `cross_references`), mention this cross-reference (e.g., "I see this issue was mentioned by #123 which is closed as completed...") and ask if this means it is resolved. Do NOT mention cross-references that are still open or closed as "not planned".
- If it's a feature/enhancement request but well-described, just ask if it's still needed.
- If it's a bug, ask if they can reproduce it with the latest build and provide detailed reproduction steps.
- If the issue has assignees, append a ping to the assignees to check in.
- If it is NOT an Epic AND `is_tracked_by_epic` is `false`, append "Feel free to reopen this issue." to the comment.
b. Execute `gh issue edit <issue_url> --remove-label "status/need-triage"`. If it is NOT an Epic, also append `--add-label "status/needs-info"`.
c. Execute `gh issue comment <issue_url> --body "<your formulated comment>"`
d. If it is NOT an Epic AND `is_tracked_by_epic` is `false`, execute `gh issue close <issue_url> --reason "not planned"`.
- After executing these actions, **STOP EXECUTION**.
- If `inactive_over_30_days` is `true` AND it is a bug report (`is_feature_request` is `false`) AND it is NOT an Epic (`is_epic` is `false`):
a. Execute `gh issue edit <issue_url> --remove-label "status/need-triage" --add-label "status/needs-info"`.
b. Execute `gh issue comment <issue_url> --body "@<reporter_username>, this issue has been inactive for over a month. Could you please try reproducing it with the latest nightly build and let us know if it still occurs? If we don't hear back, we will close this issue on <deadline_date>."`
- After executing these actions, **STOP EXECUTION**.
- If neither condition is met, proceed to Step 3.
## Step 3: Vagueness Check
**CRITICAL MISTAKE PREVENTION**: You MUST NOT skip this step just because you recognize the problem domain as complex or requiring maintainer attention. No matter how obvious the problem domain might seem, a bug report without explicit, step-by-step reproduction instructions must be halted and marked as vague first.
Is the issue fundamentally missing context AND no one has asked for more information yet?
- **For bugs**: Explicit reproduction steps are **REQUIRED**. Even if the user provides logs, error traces, or screenshots, if they do not provide clear, step-by-step instructions on how to reproduce the bug, it MUST be considered vague.
- **For feature requests**: If it is just a vague statement without clear use cases or details, it is considered vague.
- If YES (it is vague): Execute `gh issue edit <issue_url> --remove-label "status/need-triage" --add-label "status/needs-info"`. Ask the reporter: `gh issue comment <issue_url> --body "@<reporter_username>, thank you for the report! Could you please provide more specific details (e.g., detailed reproduction steps, expected behavior, logs, and environment details)? Closing this as vague if no response is received in a week."` and **STOP EXECUTION**.
- If NO: Proceed to Step 4.
## Step 4: Reproduction & Code Validity
1. Review the issue comments. If a community member has already clearly identified the root cause of the bug or answered the feature request, DO NOT investigate the code. Proceed to Step 5.
2. Clone the target repository to a temporary directory (`git clone <repo_url> target-repo`).
3. Search the `target-repo/` codebase using `grep_search` and `read_file` ONLY. You are explicitly FORBIDDEN from writing new files, running tests, attempting to fix the code, OR attempting to reproduce the bug by executing code or shell commands. Your ONLY goal is to perform STATIC code analysis to determine if the logic for the bug still exists or if the reported behavior is actually intentional by design.
- If definitively NO LONGER VALID: Close it: `gh issue close <issue_url> --comment "Closing because I have verified this works correctly in the latest codebase. <brief explanation>"` and **STOP EXECUTION**.
- If INTENTIONAL BY DESIGN: Close it: `gh issue close <issue_url> --reason "not planned" --comment "Closing this issue as the reported behavior is intentional by design. <brief explanation of the design logic>"` and **STOP EXECUTION**.
- If still valid: Proceed to Step 5.
## Step 5: Duplicates
Search for duplicates using `gh issue list --search "<keywords>" --repo <owner/repo> --state all`.
- **CRITICAL**: Pay special attention to newer issues that might already have active pull requests or more detailed context. If a duplicate exists that already has an active PR or more maintainer engagement, close the *current* issue you are triaging in favor of the active one.
- If found: `gh issue close <issue_url> --reason "not planned" --comment "Closing as duplicate of #<duplicate_number>."` and **STOP EXECUTION**.
- If no duplicates: Proceed to Step 6.
## Step 6: Triage Summary
Review the issue comments to see if a community member has already identified the root cause.
- Determine if it should be **Help-wanted** (using the Categorization Guide) and explain why in your summary.
- If you categorized the issue as **Help-wanted**, run `gh issue edit <issue_url> --remove-label "status/need-triage" --add-label "help wanted"`.
- If it does not fit **Help-wanted**, you must still explain *why* it requires maintainer attention or why it's not a good fit for community contribution (e.g., "This issue touches core architecture and requires significant maintainer review time"). Simply run `gh issue edit <issue_url> --remove-label "status/need-triage"` to mark it triaged without a specific whitelist label.
Every issue that is triaged and remains OPEN MUST be assigned at least one of the following labels before you finish your triage process for that issue:
-`status/needs-info` (for inactive, vague, or issues requiring more details)
- NONE of the above (If the issue is triaged, valid, but too complex for a community contribution, it should simply remain open without `status/need-triage`). If an issue reaches the end of triage and remains open, you must remove `status/need-triage`.
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.
description: Use this skill during code reviews to proactively investigate the codebase for duplicated functionality, reinvented wheels, or failure to reuse existing project best practices and shared utilities.
---
# Review Duplication
## Overview
This skill provides a structured workflow for investigating a codebase during a code review to identify duplicated logic, reinvented utilities, and missed opportunities to reuse established patterns. By executing this workflow, you ensure that new code integrates seamlessly with the existing project architecture.
## Workflow: Investigating for Duplication
When reviewing code, perform the following steps before finalizing your review:
### 1. Extract Core Logic
Analyze the new code to identify the core algorithms, utility functions, generic data structures, or UI components being introduced. Look beyond the specific business logic to see the underlying mechanics.
- **Core Logic:** Call out `packages/core/` if functionality does not appear React UI specific.
**Trace Third-Party Dependencies:** If the PR introduces a new import for a utility library (e.g., `lodash.merge`, `date-fns`), trace how and where the project currently uses that library. There is likely an existing wrapper or shared utility.
**Check Package Files:** Before flagging a custom implementation of a complex algorithm, check `package.json` to see if a standard library (like `lodash` or `uuid`) is already installed that provides this functionality.
### 3. Investigate the Codebase (Sub-Agent Delegation)
Delegate the heavy lifting of codebase investigation to specialized sub-agents. They are optimized to perform deep searches and semantic mapping without bloating your session history.
To ensure a comprehensive review, you MUST formulate highly specific objectives for the sub-agents, providing them with the "scents" you discovered in Step 1.
- **Codebase Investigator:** Use the `codebase_investigator` as your primary researcher. When delegating, formulate an objective that asks specific, investigative questions about the codebase, explicitly including these search vectors:
- **Structural Similarity:** Ask if existing code uses the same underlying APIs (e.g., "Does any existing code use `Intl.DateTimeFormat` or `setTimeout` for similar purposes?").
- **Naming Conventions:** Ask if there are existing symbols with similar naming patterns (e.g., "Are there existing symbols with naming patterns like `*Format*` or `*Debounce*`?").
- **Comments & Documentation:** Ask if keywords from the PR's comments or JSDoc exist in describing similar behavior elsewhere.
- **Architectural Fit:** Ask where this type of logic is currently centralized (e.g., "Where is centralized date formatting logic located?").
- **Refactoring Guidance:** Crucially, ask the sub-agent to explain *how* the new code could be refactored to use any existing logic it finds.
- **Generalist Agent:** Use the `generalist` for detailed, turn-intensive comparisons. For example: "Review the implementation of `MyNewComponent` in the PR and compare it semantically against all components in `packages/ui/src`. Are there any existing components that could be extended or used instead?"
- **Retain Fast Path for Simple Searches:** For extremely simple, unambiguous checks (e.g., "Does `package.json` include `lodash`?"), perform a direct search to save time. Default to delegation for any open-ended "investigations."
### 4. Evaluate Best Practices
Check if the new code aligns with the project's established conventions.
- **Error Handling:** Does it use the project's standard error classes or logging mechanisms?
- **State Management:** Does it bypass established stores or contexts?
- **Styling:** Does it hardcode colors or spacing instead of using theme variables?
If the PR introduces a new pattern, compare it against the documented standards and explicitly confirm if an existing project pattern should have been used instead.
### 5. Formulate Constructive Feedback
If you discover that the PR duplicates existing functionality or ignores a best practice:
- Provide a clear review comment.
- **Identify the Source:** Explicitly mention the absolute or project-relative file path and the specific symbol (function, component, class) that should be reused.
- **Implementation Guidance:** Provide a brief code snippet or a clear explanation showing **how** to integrate the existing code to fulfill the task's requirements.
- **Explain the Value:** Briefly explain why reusing the existing code is beneficial (e.g., maintainability, consistency, built-in edge case handling).
Example comment:
> "It looks like this PR introduces a new `formatDate` utility. We already have a robust, tested `formatDate` function in `src/utils/dateHelpers.ts`.
>
> You can replace your implementation by importing it like this:
> ```typescript
> import { formatDate } from '../utils/dateHelpers';
description:'Please paste the full text from the `/about` command run from Gemini CLI. Also include which platform (macOS, Windows, Linux).'
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.'
echo "Dry run: Would have added tag '${{ inputs.channel }}' to version '${{ inputs.version }}' for ${{ inputs.cli-package-name }}, ${{ inputs.core-package-name }}, and ${{ inputs.a2a-package-name }}."
echo "Dry run: Would have added tag '${INPUTS_CHANNEL}' to version '${INPUTS_VERSION}' for ${INPUTS_CLI_PACKAGE_NAME}, ${INPUTS_CORE_PACKAGE_NAME}, and ${INPUTS_A2A_PACKAGE_NAME}."
if [[ "${{ needs.detect-changes.outputs.STEERING_DETECTED }}" == "true" ]]; then
echo "### 🧠 Model Steering Guidance"
echo ""
echo "This PR modifies files that affect the model's behavior (prompts, tools, or instructions)."
echo ""
if [[ "${{ steps.analysis.outputs.MISSING_EVALS }}" == "true" ]]; then
echo "- ⚠️ **Consider adding Evals:** No behavioral evaluations (\`evals/*.eval.ts\`) were added or updated in this PR. Consider [adding a test case](https://github.com/google-gemini/gemini-cli/blob/main/evals/README.md#creating-an-evaluation) to verify the new behavior and prevent regressions."
fi
if [[ "${{ steps.analysis.outputs.IS_MAINTAINER }}" == "true" ]]; then
echo "- 🚀 **Maintainer Reminder:** Please ensure that these changes do not regress results on benchmark evals before merging."
fi
fi
echo ""
echo "---"
echo "*This is an automated guidance message triggered by steering logic signatures.*"
echo "<!-- eval-pr-report -->"
} > full_comment.md
# 2. Find if a comment with our unique tag already exists
# We extract the numeric ID from the URL to ensure compatibility with the REST API
- Description: Issues related to user-facing documentation and other content on the documentation website.
- Example Issues:
"A typo in a README file."
"DOCS: A command is not working as described in the documentation."
"A request for a new documentation page."
"Instructions missing for skills feature"
area/unknown
- 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.
@@ -284,8 +296,21 @@ jobs:
return;
}
} else {
core.setFailed(`Output is not valid JSON and does not contain a JSON markdown block.\nRaw output: ${rawOutput}`);
return;
// 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)
// Closure Policy: No help-wanted label = Close after 14 days
if (pr.state === 'open' && !hasHelpWanted && !hasMaintainerOnly) {
const prCreatedAt = new Date(pr.created_at);
// We give a 14-day grace period for non-help-wanted PRs to be manually reviewed/labeled by an EM
if (prCreatedAt > fourteenDaysAgo) {
core.info(`PR #${pr.number} is new and lacks 'help wanted'. Giving 14-day grace period for EM review.`);
continue;
}
core.info(`PR #${pr.number} is older than 14 days and lacks 'help wanted' association. 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 interest in contributing to Gemini CLI. \n\nTo ensure we maintain high code quality and focus on our prioritized roadmap, we have updated our contribution policy (see [Discussion #17383](https://github.com/google-gemini/gemini-cli/discussions/17383)). \n\n**We only *guarantee* review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'.** All other community pull requests are subject to closure after 14 days if they do not align with our current focus areas. For this reason, we strongly recommend that contributors only submit pull requests against issues explicitly labeled as **'help-wanted'**. \n\nThis pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding and for being part of our community!"
});
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
state: 'closed'
});
}
continue;
}
// Also check for linked issue even if it has help wanted (redundant but safe)
if (pr.state === 'open' && !hasLinkedIssue) {
// Already covered by hasHelpWanted check above, but good for future-proofing
continue;
}
// 4. Staleness Check (Scheduled only)
if (pr.state === 'open' && context.eventName !== 'pull_request') {
// Skip PRs that were created less than 30 days ago - they cannot be stale yet
core.info(`PR #${pr.number} is stale but has a protected label. Skipping closure.`);
continue;
}
core.info(`PR #${pr.number} is stale (no maintainer activity for 30+ days). 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 keep our backlog manageable, we are closing pull requests that haven't seen maintainer activity for 30 days. If you're still working on this, please let us know!"
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
body: `👋 @${commenter}, you've been assigned to this issue! Thank you for taking the time to contribute. Make sure to check out our [contributing guidelines](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md).`
if (permission === 'admin' || permission === 'write') {
core.info(`${username} has '${permission}' permission. Allowed.`);
return;
}
core.info(`${username} has '${permission}' permission (needs 'write' or 'admin'). Reverting '${action}' action for '${labelName}' label.`);
} catch (error) {
core.error(`Failed to check permissions for ${username}: ${error.message}`);
// Fall through to revert logic if we can't verify permissions (fail safe)
}
// If we are here, the user is NOT authorized.
if (true) { // wrapping block to preserve variable scope if needed
if (action === 'labeled') {
// 1. Remove the label if added by a non-maintainer
await github.rest.issues.removeLabel ({
owner: org,
repo: context.repo.repo,
issue_number: context.issue.number,
name: labelName
});
// 2. Post a polite comment
const comment = `
Hi @${username}, thank you for your interest in helping triage issues!
The \`${labelName}\` label is reserved for project maintainers to apply. This helps us ensure that an issue is ready and properly vetted for community contribution.
A maintainer will review this issue soon. Please see our [CONTRIBUTING.md](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md) for more details on our labeling process.
`.trim().replace(/^[ ]+/gm, '');
await github.rest.issues.createComment ({
owner: org,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
} else if (action === 'unlabeled') {
// 1. Add the label back if removed by a non-maintainer
await github.rest.issues.addLabels ({
owner: org,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: [labelName]
});
// 2. Post a polite comment
const comment = `
Hi @${username}, it looks like the \`${labelName}\` label was removed.
This label is managed by project maintainers. We've added it back to ensure the issue remains visible to potential contributors until a maintainer decides otherwise.
**⏳ Status:** The patch creation workflow has been triggered and is waiting for deployment approval. Please visit the specific workflow links below and approve the runs.
**⏳ Status:** The patch creation workflow has been triggered and is waiting for deployment approval. Please visit the workflow history link below and approve the runs.
- **Internal Project Modules**: Dependencies from other project packages are
often mocked.
### 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
## Documentation guidelines
When working in the `/docs` directory, follow the guidelines in this section:
- **Role:** You are an expert technical writer and AI assistant for contributors
to Gemini CLI. Produce professional, accurate, and consistent documentation to
guide users of Gemini CLI.
- **Technical Accuracy:** Do not invent facts, commands, code, API names, or
output. All technical information specific to Gemini CLI must be based on code
found within this directory and its subdirectories.
- **Style Authority:** Your source for writing guidance and style is the
"Documentation contribution process" section in the root directory's
`CONTRIBUTING.md` file, as well as any guidelines provided this section.
- **Information Architecture Consideration:** Before proposing documentation
changes, consider the information architecture. If a change adds significant
new content to existing documents, evaluate if creating a new, more focused
page or changes to `sidebar.json` would provide a better user experience.
- **Proactive User Consideration:** The user experience should be a primary
concern when making changes to documentation. Aim to fill gaps in existing
knowledge whenever possible while keeping documentation concise and easy for
users to understand. If changes might hinder user understanding or
accessibility, proactively raise these concerns and propose alternatives.
## Comments policy
Only write high-value comments if at all. Avoid talking to the user through
comments.
## Logging and Error Handling
- **Avoid Console Statements:** Do not use `console.log`, `console.error`, or
similar methods directly.
- **Non-User-Facing Logs:** For developer-facing debug messages, use
`debugLogger` (from `@google/gemini-cli-core`).
- **User-Facing Feedback:** To surface errors or warnings to the user, use
- `timeout`: (Optional) Timeout in milliseconds for MCP requests.
**Client Enforcement Logic:**
- Required servers are injected **after** allowlist filtering, so they are
always available even if the allowlist is active.
- If a required server has the **same name** as a locally configured server, the
admin configuration **completely overrides** the local one.
- Required servers only support remote transports (`sse`, `http`). Local
execution fields (`command`, `args`, `env`, `cwd`) are not supported.
- Required servers can coexist with allowlisted servers — both features work
independently.
### 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.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.