Compare commits

..

282 Commits

Author SHA1 Message Date
Dev Randalpura af0b5ee817 Intentionally cause memory leaks on pressing x 2026-04-09 13:59:42 -04:00
Jacob Richman 6686c8ee4c Support ctrl+shift+g (#25035) 2026-04-09 16:23:04 +00:00
Emily Hedlund 5724d6be0f refactor(core): use centralized path resolution for Linux sandbox (#24985) 2026-04-09 15:28:58 +00:00
Sandy Tao 615e078341 fix(sdk): skip broken sendStream tests to unblock nightly (#25000) 2026-04-09 03:39:36 +00:00
Jarrod Whelan faa7a9da30 feat(cli): refine tool output formatting for compact mode (#24677) 2026-04-09 03:30:52 +00:00
Emily Hedlund 5d589946ad refactor(sandbox): use centralized sandbox paths in macOS Seatbelt implementation (#24984) 2026-04-09 01:29:38 +00:00
Sehoon Shon 464bac270c fix(cli): optimize startup with lightweight parent process (#24667) 2026-04-09 00:17:32 +00:00
Christian Gunderman f1bb2af6de Generalize evals infra to support more types of evals, organization and queuing of named suites (#24941) 2026-04-08 23:57:26 +00:00
Jarrod Whelan bc3ed61adb feat(core): refine shell tool description display logic (#24903) 2026-04-08 23:40:43 +00:00
Jacob Richman 9c4e17b7ce Update ink version to 6.6.9 (#24980) 2026-04-08 23:36:19 +00:00
Tommaso Sciortino d06dba3538 fix(core): dynamic session ID injection to resolve resume bugs (#24972) 2026-04-08 23:27:24 +00:00
dogukanozen 80764c8bb5 fix(cli-ui): enable Ctrl+Backspace for word deletion in Windows Terminal (#21447) 2026-04-08 22:25:29 +00:00
Jarrod Whelan 14b2f35677 fix(cli): restore file path display in edit and write tool confirmations (#24974) 2026-04-08 22:19:25 +00:00
Adamya Singh 1023c5b7a6 test(sdk): add unit tests for GeminiCliSession (#21897) 2026-04-08 22:05:57 +00:00
Emily Hedlund af3638640c fix(core): resolve windows symlink bypass and stabilize sandbox integration tests (#24834) 2026-04-08 22:00:50 +00:00
Sri Pasumarthi c7b920717f feat(test-utils): add CPU performance integration test harness (#24951) 2026-04-08 21:50:29 +00:00
ruomeng 15f7b24312 feat(plan): require user confirmation for activate_skill in Plan Mode (#24946) 2026-04-08 21:44:53 +00:00
gemini-cli-robot 18cb7fd46c Changelog for v0.37.0 (#24940)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-04-08 21:41:55 +00:00
JAYADITYA 8b01d78512 chore: ignore conductor directory (#22128)
Co-authored-by: Coco Sheng <cocosheng@google.com>
2026-04-08 20:56:02 +00:00
gemini-cli-robot 56c2397e78 Changelog for v0.38.0-preview.0 (#24938)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: g-samroberts <samroberts@google.com>
2026-04-08 20:45:59 +00:00
Jacob Richman d1a062bcc4 chore: update ink version to 6.6.8 (#24934) 2026-04-08 20:02:03 +00:00
Emily Hedlund a39461718c fix(core): ensure robust sandbox cleanup in all process execution paths (#24763)
Co-authored-by: Spencer <spencertang@google.com>
2026-04-08 19:03:36 +00:00
gemini-cli-robot 3df99d8bcb chore(release): bump version to 0.39.0-nightly.20260408.e77b22e63 (#24939) 2026-04-08 18:10:28 +00:00
Sandy Tao a837b39f8d feat(memory): add /memory inbox command for reviewing extracted skills (#24544) 2026-04-08 18:08:49 +00:00
Sri Pasumarthi 4ebc43bc66 feat(test-utils): add memory usage integration test harness (#24876) 2026-04-08 17:42:18 +00:00
ruomeng 34b4f1c6e4 refactor(plan): simplify policy priorities and consolidate read-only rules (#24849) 2026-04-08 15:58:29 +00:00
Gaurav e77b22e638 fix: isolate concurrent browser agent instances (#24794) 2026-04-08 14:31:10 +00:00
Adam Weidman 1b3e7d674f docs: update MCP server OAuth redirect port documentation (#24844) 2026-04-08 14:06:30 +00:00
Gaurav Ghosh e7f8d9cf1a Revert "feat: Introduce an AI-driven interactive shell mode with new"
This reverts commit 651ad63ed6.
2026-04-08 07:31:17 -07:00
Gaurav Ghosh 651ad63ed6 feat: Introduce an AI-driven interactive shell mode with new
`read-shell` and `write-to-shell` tools and a configurable mode setting.
2026-04-08 07:27:28 -07:00
Jacob Richman cbacdc67d0 feat(cli): switch to ctrl+g from ctrl-x (#24861) 2026-04-08 06:22:45 +00:00
Jacob Richman 7e1938c1bc fix(cli): switch default back to terminalBuffer=false and fix regressions introduced for that mode (#24873) 2026-04-08 05:47:54 +00:00
Anjaligarhwal b9f1d832c8 fix(core): dispose Scheduler to prevent McpProgress listener leak (#24870) 2026-04-08 03:05:53 +00:00
Dev Randalpura 47c5d25d93 Added flag for ept size and increased default size (#24859) 2026-04-08 03:03:36 +00:00
Jacob Richman 28efab483f fix(cli): always show shell command description or actual command (#24774) 2026-04-08 01:52:33 +00:00
gemini-cli-robot 9fd92c0eea Changelog for v0.37.0-preview.2 (#24848)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-04-08 00:13:06 +00:00
Michael Bleigh 16768c08f2 refactor(core): make LegacyAgentSession dependencies optional (#24287)
Co-authored-by: Adam Weidman <adamfweidman@gmail.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
2026-04-07 23:45:22 +00:00
JAYADITYA 1aa798dd18 refactor(cli): remove duplication in interactive shell awaiting input hint (#24801) 2026-04-07 23:36:44 +00:00
Christian Gunderman f96d5f98fe Revert "fix(ui): improve narration suppression and reduce flicker (#2… (#24857) 2026-04-07 22:45:40 +00:00
Yuna Seol 3c5b5db034 feat(core): use experiment flags for default fetch timeouts (#24261) 2026-04-07 22:35:04 +00:00
Michael Bleigh 986293bd38 feat(core): add agent protocol UI types and experimental flag (#24275)
Co-authored-by: Adam Weidman <adamfweidman@gmail.com>
Co-authored-by: Adam Weidman <adamfweidman@google.com>
2026-04-07 21:45:18 +00:00
David Pierce adf7b3b717 Improve sandbox error matching and caching (#24550) 2026-04-07 21:08:18 +00:00
Jack Wotherspoon 9637fb3990 fix(core): remove tmux alternate buffer warning (#24852) 2026-04-07 21:01:14 +00:00
Sri Pasumarthi 06fcdc231c feat(acp): add /help command (#24839) 2026-04-07 20:01:44 +00:00
Sehoon Shon d29da15427 fix(cli): prevent multiple banner increments on remount (#24843) 2026-04-07 19:44:09 +00:00
Enjoy Kumawat ab3075feb9 fix: use directory junctions on Windows for skill linking (#24823) 2026-04-07 19:28:43 +00:00
Abhi 5588000e93 chore: fix formatting for behavioral eval skill reference file (#24846) 2026-04-07 19:26:53 +00:00
krishdef7 68fef8745e fix(core): propagate BeforeModel hook model override end-to-end (#24784)
Signed-off-by: krishdef7 <gargkrish06@gmail.com>
Co-authored-by: Sandy Tao <sandytao520@icloud.com>
2026-04-07 17:49:26 +00:00
Michael Bleigh e432f7c009 feat(hooks): display hook system messages in UI (#24616) 2026-04-07 17:42:39 +00:00
Alisa 846051f716 Alisa/approve button (#24645) 2026-04-07 16:44:07 +00:00
Tommaso Sciortino 1c22c5b37b Remove flakey test (#24837) 2026-04-07 09:39:15 -07:00
Emily Hedlund 1762c9c509 temporarily disable sandbox integration test on windows (#24786) 2026-04-07 15:33:40 +00:00
Abhijit Balaji 0025978d76 feat(cli): support selective topic expansion and click-to-expand (#24793) 2026-04-07 15:00:40 +00:00
Gaurav 4c5e887732 feat(telemetry): add browser agent clearcut metrics (#24688) 2026-04-07 07:48:38 +00:00
Abhi 83096c68b0 fix(policy): allow complete_task in plan mode (#24771) 2026-04-07 03:43:42 +00:00
Christian Gunderman d2b775f9a7 Add an eval for and fix unsafe cloning behavior. (#24457) 2026-04-07 03:17:44 +00:00
Spencer 0a8da988ed fix(cli): ensure skills list outputs to stdout in non-interactive environments (#24566) 2026-04-07 02:40:23 +00:00
David Pierce 984f02c180 relax tool sandboxing overrides for plan mode to match defaults. (#24762) 2026-04-06 22:18:10 +00:00
Tommaso Sciortino df67f973ed fix(cli): respect global environment variable allowlist (#24767) 2026-04-06 22:17:55 +00:00
Christian Gunderman 7872d6d7fe fix(ui): improve narration suppression and reduce flicker (#24635) 2026-04-06 21:18:59 +00:00
Gaurav e116aa34f4 fix(browser): remove premature browser cleanup after subagent invocation (#24753) 2026-04-06 21:17:31 +00:00
Abhijit Balaji ad98294352 Revert "feat(core,cli): prioritize summary for topics (#24608)" (#24777) 2026-04-06 20:33:18 +00:00
Dev Randalpura 2353a6d253 fix(ui): fixed auth race condition causing logo to flicker (#24652) 2026-04-06 20:17:05 +00:00
krishdef7 8ac560d2c9 fix(core): handle partial llm_request in BeforeModel hook override (#22326) 2026-04-06 20:11:38 +00:00
Tommaso Sciortino c6a9d3de13 fix(cli): remove -S from shebang to fix Windows and BSD execution (#24756) 2026-04-06 19:06:56 +00:00
Christian Gunderman 8f131ffef7 Fix issue where topic headers can be posted back to back (#24759) 2026-04-06 18:36:22 +00:00
Jacob Richman 70f6d6a992 split context (#24623) 2026-04-06 17:20:38 +00:00
cynthialong0-0 c96cb09e09 feat(cli): add role specific metrics to /stats (#24659) 2026-04-06 16:20:48 +00:00
Sri Pasumarthi 15298b28c2 feat(acp): add support for /about command (#24649) 2026-04-04 07:42:27 +00:00
Gal Zahavi 7311e242ec feat(cli): enhance tool confirmation UI and selection layout (#24376) 2026-04-04 01:32:35 +00:00
Gal Zahavi 21a3925f99 docs: update sandboxing documentation and toolSandboxing settings (#24655) 2026-04-04 01:26:41 +00:00
Jacob Richman ec35ebbe57 fix(core): detect uninitialized lines (#24646) 2026-04-04 00:51:29 +00:00
Gal Zahavi 65024d4538 fix(core): ensure global temp directory is always in sandbox allowed paths (#24638)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-04 00:23:27 +00:00
Samee Zahid 4fb3790051 feat(core): discourage update topic tool for simple tasks (#24640)
Co-authored-by: Samee Zahid <sameez@google.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-03 23:52:24 +00:00
Christian Gunderman 4a040931ef Fix restoration of topic headers. (#24650) 2026-04-03 23:50:38 +00:00
Alisa e74efc5c0b Do not run pr-eval workflow when no steering changes detected (#24621) 2026-04-03 22:54:05 +00:00
Jacob Richman d5a5995281 feat(cli) Scrollbar for input prompt (#21992) 2026-04-03 22:10:04 +00:00
Gal Zahavi 893ae4d29a fix(core): ensure sandbox approvals are correctly persisted and matched for proactive expansions (#24577) 2026-04-03 21:48:18 +00:00
Emily Hedlund 370c45de67 fix(core): improve windows sandbox reliability and fix integration tests (#24480) 2026-04-03 20:54:48 +00:00
Abhi a93a1ebd65 fix(core): inject skill system instructions into subagent prompts if activated (#24620) 2026-04-03 18:45:11 +00:00
Jarrod Whelan 3f12c1d7c7 feat(cli): enable compact tool output by default (#24509) (#24510) 2026-04-03 17:59:12 +00:00
Jacob Richman 61719a3926 show color (#24613) 2026-04-03 16:53:34 +00:00
Abhijit Balaji beaa2a968b feat(core,cli): prioritize summary for topics (#24608) (#24609) 2026-04-03 16:26:38 +00:00
Emily Hedlund ca0e6f9bd9 test: fix Windows CI execution and resolve exposed platform failures (#24476) 2026-04-03 15:50:29 +00:00
Aditya Bijalwan 7a70ab9a5d Feat/browser agent metrics (#24210)
Co-authored-by: Gaurav Ghosh <gaghosh@google.com>
2026-04-03 08:21:09 +00:00
Gal Zahavi e54eecca51 feat(cli): minimalist sandbox status labels (#24582) 2026-04-03 05:22:21 +00:00
Jacob Richman 7de3e4dcf9 Add instructions for how to start react in prod and force react to prod mode (#24590) 2026-04-03 04:42:32 +00:00
Tommaso Sciortino 8c215c7a88 fix(core): remove broken PowerShell translation and fix native __write in Windows sandbox (#24571) 2026-04-03 02:50:44 +00:00
Tommaso Sciortino fe4fcf89d9 docs: clarify release coordination (#24575) 2026-04-03 01:37:35 +00:00
Jacob Richman 1f5d7014c6 feat(ui): enable "TerminalBuffer" mode to solve flicker (#24512) 2026-04-03 00:39:49 +00:00
Gal Zahavi 1ae0499e5d fix(core): pass includeDirectories to sandbox configuration (#24573) 2026-04-02 23:34:12 +00:00
Dev Randalpura 9d741abdba fix(ui): fixed table styling (#24565) 2026-04-02 22:52:25 +00:00
Ishaan Arora f54bccfe03 docs: add missing .md extensions to internal doc links (#24145) 2026-04-02 21:52:18 +00:00
gemini-cli-robot 1db169bc66 Changelog for v0.37.0-preview.1 (#24568)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-04-02 21:31:11 +00:00
gemini-cli-robot b9b7bba48d Changelog for v0.36.0 (#24558)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-04-02 21:10:48 +00:00
Dan Zaharia 29caa52bb7 fix(ui): hide model quota in /stats and refactor quota display (#24206) 2026-04-02 20:49:14 +00:00
Saurav Sharma e5adeaca80 fix(core): unsafe type assertions in Core File System #19712 (#19739)
Co-authored-by: Dev Randalpura <devrandalpura@google.com>
2026-04-02 20:44:22 +00:00
Adam Weidman 6fb58bd31f feat(cli): migrate nonInteractiveCli to LegacyAgentSession (#22987) 2026-04-02 20:21:40 +00:00
Jack Wotherspoon 7c3469713d docs: move agent disabling instructions and update remote agent status (#24559) 2026-04-02 20:16:01 +00:00
Jerop Kipruto 64c928fce7 feat(core): implement context-aware persistent policy approvals (#23257) 2026-04-02 20:01:33 +00:00
gemini-cli-robot 61b21e3d63 Changelog for v0.37.0-preview.0 (#24464)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-04-02 19:52:14 +00:00
Aashir Javed 77027dff82 fix(cli): clear stale retry/loading state after cancellation (#21096) (#21960)
Co-authored-by: Aashir Javed <Aaxhirrr@users.noreply.github.com>
Co-authored-by: Dev Randalpura <devrandalpura@google.com>
2026-04-02 19:44:39 +00:00
ruomeng c0dfa1aec3 Enable 'Other' option for yesno question type (#24545) 2026-04-02 19:42:53 +00:00
Sandy Tao 06173c0885 fix(core): move project memory dir under tmp directory (#24542) 2026-04-02 17:50:43 +00:00
Jyo 08b926796c Fix crash when vim editor is not found in PATH on Windows (#22423)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
2026-04-02 17:40:19 +00:00
Sri Pasumarthi b80234aa3e fix(acp): handle all InvalidStreamError types gracefully in prompt (#24540) 2026-04-02 17:16:36 +00:00
Jacob Richman efbddcbf98 Update ink version to 6.6.7 (#24514) 2026-04-02 16:42:52 +00:00
Sandy Tao 63cc363606 feat(core): scope subagent workspace directories via AsyncLocalStorage (#24445) 2026-04-02 16:33:08 +00:00
joshualitt e0044f2868 feat(core): Land ContextCompressionService (#24483) 2026-04-02 16:22:04 +00:00
Gaurav beff8c91aa fix(browser): handle computer-use model detection for analyze_screenshot (#24502) 2026-04-02 15:05:21 +00:00
Coco Sheng f510394721 Implement background process monitoring and inspection tools (#23799) 2026-04-02 15:01:00 +00:00
Gaurav 811a383d50 fix: enable browser_agent in integration tests and add localhost fixture tests (#24523) 2026-04-02 14:54:38 +00:00
Gaurav 8d171e0200 docs(browser-agent): update stale browser agent documentation (#24463)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-02 14:52:30 +00:00
ruomeng 7b6ab50138 feat(cli): support default values for environment variables (#24469) 2026-04-02 14:38:45 +00:00
Sehoon Shon 44c8b43328 fix(cli): prevent crash in AnsiOutputText when handling non-array data (#24498) 2026-04-02 11:48:17 +00:00
Sehoon Shon 242afd49a1 revert(cli): bring back input box and footer visibility in copy mode (#24504) 2026-04-02 06:54:51 +00:00
Jarrod Whelan 66c07d7296 fix(ui): resolve unwanted vertical spacing around various tool output treatments (#24449) 2026-04-02 06:29:56 +00:00
Jacob Richman 40b73c9447 Fix shell output display (#24490) 2026-04-02 05:53:46 +00:00
Alisa 973092df50 feat: implement high-signal PR regression check for evaluations (#23937) 2026-04-02 05:14:43 +00:00
Sandy Tao e446733b53 feat(core): add background memory service for skill extraction (#24274) 2026-04-02 05:05:31 +00:00
Alisa 3344f6849c Unused error variables in catch block are not allowed (#24487) 2026-04-02 04:33:07 +00:00
Jacob Richman 84936dc85d Auto configure memory. (#24474) 2026-04-02 03:15:27 +00:00
Jacob Richman 18cdbbf81a Terminal Serializer Optimization (#24485) 2026-04-02 02:56:52 +00:00
Gal Zahavi 13ccc16457 fix(core): enhance sandbox usability and fix build error (#24460)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-01 23:51:06 +00:00
N. Taylor Mullen ca78a0f177 fix(cli): ensure agent stops when all declinable tools are cancelled (#24479) 2026-04-01 23:16:34 +00:00
Keith Guerin cb7f7d6c72 feat(cli): change default loadingPhrases to 'off' to hide tips (#24342) 2026-04-01 23:04:43 +00:00
gemini-cli-robot 0d7e778e08 Changelog for v0.36.0-preview.8 (#24453)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-04-01 20:47:06 +00:00
Adam Weidman b5f568fefe feat(config): add experimental.adk.agentSessionNoninteractiveEnabled setting (#24439) 2026-04-01 20:41:38 +00:00
Emily Hedlund d00b43733c fix(core): refactor linux sandbox to fix ARG_MAX crashes (#24286) 2026-04-01 20:17:10 +00:00
Adib234 55f5d3923c feat(policy): explicitly allow web_fetch in plan mode with ask_user (#24456)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-04-01 19:57:56 +00:00
Abhi 2d432c1489 fix(core): ensure complete_task tool calls are recorded in chat history (#24437) 2026-04-01 19:53:46 +00:00
Sam Roberts 597778e55f Update README.md for links. (#22759) 2026-04-01 19:15:44 +00:00
N. Taylor Mullen 4e21e5b8a3 fix(cli): refresh slash command list after /skills reload (#24454) 2026-04-01 19:15:27 +00:00
AK d9d51ba15b docs(core): add subagent tool isolation draft doc (#23275)
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
2026-04-01 18:45:21 +00:00
Gaurav aed85725b6 feat(browser): supersede stale snapshots to reclaim context-window tokens (#24440) 2026-04-01 18:41:39 +00:00
anj-s 43cf63e189 fix: update task tracker storage location in system prompt (#24034) 2026-04-01 18:29:09 +00:00
gemini-cli-robot bda4491616 Changelog for v0.36.0-preview.7 (#24346)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-04-01 18:23:28 +00:00
Sri Pasumarthi 6b303a13eb fix(acp) refactor(core,cli): centralize model discovery logic in ModelConfigService (#24392) 2026-04-01 18:03:30 +00:00
cynthialong0-0 16468a855d feat(core): update browser agent prompt to check open pages first when bringing up (#24431) 2026-04-01 17:52:18 +00:00
joshualitt 377e834e03 refactor(core): Unified context management settings schema (#24391) 2026-04-01 17:24:45 +00:00
anj-s 3a32d9723e feat(core): enhance tracker task schemas for detailed titles and descriptions (#23902) 2026-04-01 17:19:47 +00:00
Gaurav bf3ac20da0 feat(browser): add sandbox-aware browser agent initialization (#24419) 2026-04-01 17:18:17 +00:00
Gaurav a3ef87e6e2 fix(build): wire bundle:browser-mcp into bundle pipeline (#24424) 2026-04-01 17:09:58 +00:00
Dev Randalpura 4c4d8bc411 fix(ui): removed additional vertical padding for tables (#24381) 2026-04-01 16:46:38 +00:00
Sehoon Shon f938a3f51d fix(build): upload full bundle directory archive to GitHub releases (#24403) 2026-04-01 16:39:44 +00:00
cynthialong0-0 c61506bbc1 fix(core): ensure blue border overlay and input blocker to act correctly depending on browser agent activities (#24385) 2026-04-01 16:35:44 +00:00
Emily Hedlund 6a8a0d4faa feat(core): populate sandbox forbidden paths with project ignore file contents (#24038) 2026-04-01 16:27:55 +00:00
Dev Randalpura 066da2a1d1 fix(ui): add accelerated scrolling on alternate buffer mode (#23940)
Co-authored-by: jacob314 <jacob314@gmail.com>
2026-04-01 16:23:40 +00:00
PROTHAM 7d1848d578 fix(cli): cap shell output at 10 MB to prevent RangeError crash (#24168) 2026-04-01 16:09:30 +00:00
ruomeng eb95e99b3d feat(plan): conditionally add enter/exit plan mode tools based on current mode (#24378) 2026-04-01 15:56:10 +00:00
Jerop Kipruto ca43f8c291 feat(core): prioritize discussion before formal plan approval (#24423) 2026-04-01 15:55:47 +00:00
Abhi dcf5afafda fix(core): resolve subagent chat recording gaps and directory inheritance (#24368) 2026-04-01 15:29:38 +00:00
Jacob Richman 9f76f34049 ink 6.6.3 (#24372)
Co-authored-by: matt korwel <matt.korwel@gmail.com>
2026-04-01 04:50:12 +00:00
matt korwel 7c5cd693ce Set memoryManager to false in settings.json (#24393) 2026-04-01 03:38:50 +00:00
matt korwel c9ed5e41b1 fix(cli): refactor test config loading and mock debugLogger in test-setup (#24389) 2026-03-31 20:11:02 -07:00
Daniel R. Neal 8ae5b56b5b feat(ui): add Tokyo Night theme (#24054)
Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com>
2026-04-01 01:08:28 +00:00
Sri Pasumarthi 1b265f343f fix(core): pin AuthType.GATEWAY to use Gemini 3.1 Pro/Flash Lite by default (#24375) 2026-04-01 00:25:59 +00:00
joshualitt fd5c103f99 refactor(core): Centralize context management logic into src/context (#24380) 2026-04-01 00:01:46 +00:00
Jarrod Whelan cdc602edd7 fix(ui): wrap topic and intent fields in TopicMessage (#24386) 2026-04-01 00:00:48 +00:00
Gaurav 782bb4e4bd fix(core): fix browser agent UX issues and improve E2E test reliability (#24312) 2026-03-31 23:00:16 +00:00
David Pierce 94f9480a3a fix(core): resolve Plan Mode deadlock during plan file creation due to sandbox restrictions (#24047) 2026-03-31 22:06:50 +00:00
Abhi 9364dd8a49 feat(core): infrastructure for event-driven subagent history (#23914) 2026-03-31 21:54:22 +00:00
Tirth Panchal 6d48a12efe docs: fix broken GEMINI.md link in CONTRIBUTING.md (#24182)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-03-31 21:44:00 +00:00
Abhi beab7cc053 docs(policy): remove unsupported mcpName wildcard edge case (#24133) 2026-03-31 21:11:29 +00:00
Gal Zahavi 6cade3eaec test(sandbox): add integration test for dynamic permission expansion (#24359) 2026-03-31 20:59:44 +00:00
Sandy Tao c8d18eb2ac fix(config): disable JIT context loading by default (#24364) 2026-03-31 20:31:22 +00:00
Tommaso Sciortino 91400c5b0b don't try to remove tags in dry run (#24356) 2026-03-31 12:54:53 -07:00
Gal Zahavi 554a5a36a3 fix(core): implement __read and __write commands in sandbox managers (#24283) 2026-03-31 19:39:51 +00:00
Abhi 7e117ac0ac docs: update subagents docs to not be experimental (#24343) 2026-03-31 18:58:41 +00:00
Jerop Kipruto 6f053dd8b9 Revert "Add security settings for tool sandboxing" (#24357) 2026-03-31 18:39:28 +00:00
Sehoon Shon 25af91e4df chore(release): allow bundling for all builds, including stable (#24305) 2026-03-31 18:37:14 +00:00
Emily Hedlund 1edc542b55 ci: install bubblewrap on Linux for release workflows (#24347) 2026-03-31 18:19:48 +00:00
Sehoon Shon 119dff3b73 perf(build): optimize build scripts for parallel execution and remove redundant checks (#24307) 2026-03-31 17:46:36 +00:00
cynthialong0-0 7c4b497a84 fix(core): fix race condition between browser agent and main closing process (#24340) 2026-03-31 17:43:37 +00:00
Emily Hedlund 65ee6171e7 fix(core): batch macOS seatbelt rules into a profile file to prevent ARG_MAX errors (#24255) 2026-03-31 17:35:13 +00:00
Yifan Ruan 9cb09ccf8e docs: Add 'plan' option to approval mode in CLI reference (#24134) 2026-03-31 17:34:59 +00:00
cynthialong0-0 a79f2f81ae Fix(browser): terminate immediately for "browser is already running" error (#24233)
Co-authored-by: Gaurav <39389231+gsquared94@users.noreply.github.com>
2026-03-31 17:07:58 +00:00
ruomeng 140c2b9914 feat(cli): add UI to update extensions (#23682) 2026-03-31 17:05:08 +00:00
Gaurav 6805e818f7 fix(browser): terminate subagent immediately on domain restriction violations (#24313) 2026-03-31 16:51:27 +00:00
ruomeng 07e2053e12 feat(plan): promote planning feature to stable (#24282) 2026-03-31 16:10:13 +00:00
Sehoon Shon f9a93a1337 feat(cli): add auth info to footer (#24042) 2026-03-31 16:10:13 +00:00
cynthialong0-0 3982a252bb fix(browser): reset action counter for each agent session and let it ignore internal actions (#24228) 2026-03-31 15:23:19 +00:00
gemini-cli-robot e293424bb4 Changelog for v0.35.3 (#24083)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-03-31 06:35:30 +00:00
gemini-cli-robot 21ad42f677 Changelog for v0.36.0-preview.6 (#24082)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-03-31 06:35:26 +00:00
Sehoon Shon 561418c554 fix(core): enable mid-stream retries for all models and re-enable compression test (#24302) 2026-03-31 06:25:21 +00:00
Adib234 d0d3639e16 feat(plan): support Plan mode in untrusted folders (#17586) 2026-03-31 03:33:55 +00:00
Sehoon Shon 2f7f967189 test(integration): fix plan mode write denial test false positive (#24299) 2026-03-31 03:17:36 +00:00
Sandy Tao 46d6b119b6 feat(core): add project-level memory scope to save_memory tool (#24161) 2026-03-31 01:32:15 +00:00
Abhijit Balaji 80929c48c5 feat(core): enable topic update narration for legacy models (#24241)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-31 00:57:46 +00:00
Sehoon Shon 35efdfc409 chore(test-utils): switch integration tests to use PREVIEW_GEMINI_MODEL (#24276)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
2026-03-31 00:31:04 +00:00
Gal Zahavi bea57a2f3d Add security settings for tool sandboxing (#23923) 2026-03-30 23:49:53 +00:00
Jarrod Whelan 1df5c98b33 feat(cli): implement compact tool output (#20974) 2026-03-30 23:43:29 +00:00
Sehoon Shon 3e95b8ec59 feat(cli): show Flash Lite Preview model regardless of user tier (#23904) 2026-03-30 23:30:33 +00:00
Abhi 5b5f87abc7 fix(core): ensure default agents provide tools and use model-specific schemas (#24268) 2026-03-30 23:10:57 +00:00
Christian Gunderman 991dca4c40 Default enable narration for the team. (#24224) 2026-03-30 22:30:55 +00:00
joshualitt dfba0e91e2 feat(core): Unified Context Management and Tool Distillation. (#24157) 2026-03-30 22:29:59 +00:00
Christian Gunderman 117a2d3844 fix(evals): add update_topic behavioral eval (#24223) 2026-03-30 22:02:53 +00:00
Tommaso Sciortino 4b20d93e1d fix broken tests (#24279) 2026-03-30 15:25:56 -07:00
Tommaso Sciortino 44cdb3e376 fix(cli): resolve missing F12 logs via global console store (#24235) 2026-03-30 13:15:10 -07:00
Alex Stephen 9cf410478c Text can be added after /plan command (#22833) 2026-03-30 14:31:20 +00:00
Spencer a255529c6b fix(a2a-server): prioritize ADC before evaluating headless constraints for auth initialization (#23614) 2026-03-30 12:26:15 +00:00
Abhi d9d2ce36f2 test(evals): add comprehensive subagent delegation evaluations (#24132) 2026-03-29 23:13:50 +00:00
Tommaso Sciortino da8c841ef4 fix: shellcheck warnings in scripts (#24035) 2026-03-29 02:47:05 +00:00
Christian Gunderman b7c86b5497 UX for topic narration tool (#24079) 2026-03-28 21:33:38 +00:00
Adam Weidman 3eebb75b7a feat(core): agnostic background task UI with CompletionBehavior (#22740)
Co-authored-by: mkorwel <matt.korwel@gmail.com>
2026-03-28 21:27:51 +00:00
Christian Gunderman 07ab16dbbe feat(cli): support 'tab to queue' for messages while generating (#24052) 2026-03-28 01:31:11 +00:00
Abhijit Balaji afc1d50c20 feat(core): implement tool-based topic grouping (Chapters) (#23150)
Co-authored-by: Christian Gunderman <gundermanc@google.com>
2026-03-28 01:28:25 +00:00
Gal Zahavi ae123c547c fix(sandbox): implement Windows Mandatory Integrity Control for GeminiSandbox (#24057) 2026-03-28 00:14:35 +00:00
Keith Guerin c2705e8332 fix(cli): resolve layout contention and flashing loop in StatusRow (#24065) 2026-03-28 00:06:07 +00:00
Sam Roberts 9574855435 Re-word intro to Gemini 3 page. (#24069) 2026-03-28 00:01:22 +00:00
krishdef7 bf6dae4690 fix(hooks): prevent SessionEnd from firing twice in non-interactive mode (#22139)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
2026-03-27 23:39:48 +00:00
Ivan Porty b5529c2475 fix(core): resolve ACP Operation Aborted Errors in grep_search (#23821)
Co-authored-by: Sri Pasumarthi <sripas@google.com>
2026-03-27 23:12:34 +00:00
Tommaso Sciortino 9e74a7ec18 feat(core): implement windows sandbox expansion and denial detection (#24027) 2026-03-27 22:35:01 +00:00
Sandy Tao 4034c030e7 feat(context): add configurable memoryBoundaryMarkers setting (#24020) 2026-03-27 21:51:32 +00:00
Gal Zahavi 765fb67011 Enable network access in sandbox configuration (#24055) 2026-03-27 21:28:01 +00:00
Jacob Richman 97c99f263a Fix test flakes by globally mocking ink-spinner (#24044) 2026-03-27 21:19:46 +00:00
gemini-cli-robot f1a3c35dee Changelog for v0.36.0-preview.5 (#24046)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-03-27 21:19:26 +00:00
Jacob Richman ebe98fdee9 Debug command. (#23851)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-27 21:05:22 +00:00
Abhi ba71ffa736 fix(core): switch to subshells for shell tool wrapping to fix heredocs and edge cases (#24024) 2026-03-27 20:34:39 +00:00
joshualitt 320c8aba4c feat(core): Land AgentHistoryProvider. (#23978) 2026-03-27 19:22:35 +00:00
Sri Pasumarthi e7dccabf14 fix(acp): prevent crash on empty response in ACP mode (#23952) 2026-03-27 18:49:13 +00:00
Jacob Richman a84d4d876e Increase memory limited for eslint. (#24022) 2026-03-27 18:40:26 +00:00
Emily Hedlund 29031ea7cf refactor(core): improve ignore resolution and fix directory-matching bug (#23816) 2026-03-27 17:12:26 +00:00
Spencer f3977392e6 revert(core): support custom base URL via env vars (#23976) 2026-03-27 17:10:14 +00:00
Emily Hedlund 535667baf6 feat(core): add forbiddenPaths to GlobalSandboxOptions and refactor createSandboxManager (#23936) 2026-03-27 16:57:26 +00:00
Tommaso Sciortino 33cf2da1df disable extension-reload test (#24018) 2026-03-27 16:19:15 +00:00
Abhi 104587bae8 feat(core): subagent isolation and cleanup hardening (#23903) 2026-03-27 03:43:39 +00:00
Yuna Seol aca8e1af05 fix(core): explicitly set error names to avoid bundling renaming issues (#23913) 2026-03-27 03:40:49 +00:00
Sam Roberts 6f92642524 ACP integration documents (#22254)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: nmcnamara-eng <118702206+nmcnamara-eng@users.noreply.github.com>
2026-03-27 02:10:29 +00:00
gemini-cli-robot 8413dd62ef Changelog for v0.35.2 (#23960)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-03-27 02:10:03 +00:00
Sri Pasumarthi 750dec5d8d fix(acp): Update allow approval policy flow for ACP clients to fix config persistence and compatible with TUI (#23818) 2026-03-27 01:42:17 +00:00
gemini-cli-robot 335b36893b Changelog for v0.36.0-preview.4 (#23935)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-03-27 01:08:39 +00:00
Jenna Inouye 25a20f8e4e Docs: Update 'docs-writer' skill for relative links (#21463) 2026-03-27 00:32:20 +00:00
Jacob Richman b5ba88b001 dep(update) Update Ink version to 6.5.0 (#23843) 2026-03-26 23:49:51 +00:00
Tommaso Sciortino 8868b34c75 refactor(core): delegate sandbox denial parsing to SandboxManager (#23928) 2026-03-26 22:10:15 +00:00
Aditya Bijalwan 73dd7328df feat(core): implement persistent browser session management (#21306)
Co-authored-by: Gaurav <39389231+gsquared94@users.noreply.github.com>
Co-authored-by: cynthialong0-0 <82900738+cynthialong0-0@users.noreply.github.com>
2026-03-26 21:33:37 +00:00
Spencer d25ce0e143 fix(core): remove shell outputChunks buffer caching to prevent memory bloat and sanitize prompt input (#23751) 2026-03-26 21:16:07 +00:00
David Pierce 30397816da feat(sandbox): implement secret visibility lockdown for env files (#23712)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
2026-03-26 20:35:21 +00:00
Gen Zhang 84f1c19265 feat(cli): enable notifications cross-platform via terminal bell fallback (#21618)
Co-authored-by: Sandy Tao <sandytao520@icloud.com>
2026-03-26 20:10:49 +00:00
Gal Zahavi d33170931c fix(core): allow disabling environment variable redaction (#23927) 2026-03-26 20:04:44 +00:00
Jenna Inouye 1d230dbfbf Docs: Update quotas and pricing (#23835) 2026-03-26 19:29:37 +00:00
Sehoon Shon c92ae8a359 feat(core): define TrajectoryProvider interface (#23050) 2026-03-26 19:24:06 +00:00
Keith Schaab bf03543bf6 fix(a2a-server): A2A server should execute ask policies in interactive mode (#23831) 2026-03-26 19:10:18 +00:00
matt korwel 1d2fbbf9c3 feat(gcp): add development worker infrastructure (#23814) 2026-03-26 19:01:37 +00:00
Adib234 9762bf2965 fix(plan): after exiting plan mode switches model to a flash model (#23885) 2026-03-26 18:45:03 +00:00
ruomeng c888da5f73 fix(core): replace hardcoded non-interactive ASK_USER denial with explicit policy rules (#23668) 2026-03-26 18:35:12 +00:00
Dev Randalpura aa4d9316a9 feat(core): new skill to look for duplicated code while reviewing PRs (#23704) 2026-03-26 18:32:30 +00:00
Aditya Bijalwan 5755ec2dcf fix(browser): keep input blocker active across navigations (#22562)
Co-authored-by: cynthialong0-0 <82900738+cynthialong0-0@users.noreply.github.com>
2026-03-26 16:54:49 +00:00
gemini-cli-robot a3c1c659fd Changelog for v0.35.1 (#23840)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-03-26 16:43:23 +00:00
Sehoon Shon 49534209f2 fix(cli): prioritize primary name matches in slash command search (#23850) 2026-03-26 12:18:57 +00:00
Chris Williams 9e7f52b8f5 Merge examples of use into quickstart documentation (#23319) 2026-03-26 02:57:23 +00:00
Gal Zahavi 30e0ab102a feat(sandbox): dynamic Linux sandbox expansion and worktree support (#23692)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-26 01:58:45 +00:00
Alisa 2e03e3aed5 feat(evals): add reliability harvester and 500/503 retry support (#23626) 2026-03-26 01:48:45 +00:00
gemini-cli-robot c1e4dbd157 Changelog for v0.35.0 (#23819)
Co-authored-by: g-samroberts <158088236+g-samroberts@users.noreply.github.com>
Co-authored-by: g-samroberts <samroberts@google.com>
2026-03-26 01:33:27 +00:00
Yuna Seol ae3dbab38a fix(core): strip leading underscores from error types in telemetry (#23824)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-25 23:34:18 +00:00
Jacob Richman a86935b6de fix(cli): allow ask question dialog to take full window height (#23693) 2026-03-25 23:26:34 +00:00
Tommaso Sciortino b91758bf6b Don't try removing a tag from a non-existent release. (#23830) 2026-03-25 22:27:17 +00:00
Steven Robertson 20fd405f9c fix: Chat logs and errors handle tail tool calls correctly (#22460)
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
2026-03-25 22:17:30 +00:00
nirali 8595b07f6d fix(cli): show helpful guidance when no skills are available (#23785) 2026-03-25 22:06:44 +00:00
Alisa 7b710a2790 new linting check: github-actions-pinning (#23808) 2026-03-25 21:43:12 +00:00
gemini-cli-robot 124d5cfb9e Changelog for v0.36.0-preview.3 (#23827)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
2026-03-25 21:32:39 +00:00
christine betts 3ada29fb51 feat(core,ui): Add experiment-gated support for gemini flash 3.1 lite (#23794) 2026-03-25 20:28:49 +00:00
gemini-cli-robot 012740b68f Changelog for v0.36.0-preview.0 (#23702)
Co-authored-by: gemini-cli-robot <224641728+gemini-cli-robot@users.noreply.github.com>
Co-authored-by: Sam Roberts <158088236+g-samroberts@users.noreply.github.com>
2026-03-25 20:25:50 +00:00
Prasanna Pal fd0893c346 fix(ui): prevent escape key from cancelling requests in shell mode (#21245) 2026-03-25 20:25:13 +00:00
Tommaso Sciortino a6a3689298 don't silence errors from wombat (#23822) 2026-03-25 13:38:30 -07:00
Tommaso Sciortino 20aa695ac4 Revert "perf(cli): optimize --version startup time (#23671)" (#23812) 2026-03-25 19:59:23 +00:00
Jerop Kipruto 6d3437badb docs: clarify policy requirement for general.plan.directory in settings schema (#23784) 2026-03-25 19:37:48 +00:00
cynthialong0-0 86111c4d54 feat(browser): dynamically discover read-only tools (#23805) 2026-03-25 19:16:48 +00:00
Keith Guerin fe92a43e31 fix(ui): cleanup estimated string length hacks in composer (#23694) 2026-03-25 19:15:08 +00:00
Coco Sheng 830f7dec61 fix(cli): resolve TTY hang on headless environments by unconditionally resuming process.stdin before React Ink launch (#23673) 2026-03-25 18:18:43 +00:00
Adam Weidman 0bb6c25dc7 docs(core): document agent_card_json string literal options for remote agents (#23797) 2026-03-25 18:04:28 +00:00
Chris Williams f618da15d6 Add note about root privileges in sandbox docs (#23314) 2026-03-25 18:03:50 +00:00
Tommaso Sciortino 1b052df52f feat(core): implement Windows sandbox dynamic expansion Phase 1 and 2.1 (#23691) 2026-03-25 17:54:45 +00:00
Shaswat Raj f11bd3d079 fix(core): thread AbortSignal to chat compression requests (#20405) (#20778)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
2026-03-25 16:57:59 +00:00
Sri Pasumarthi c06794b3c6 fix(acp): allow attachments by adding a permission prompt (#23680) 2026-03-25 16:52:21 +00:00
splint-disk-8i ec953426db docs: fix grammar in CONTRIBUTING and numbering in sandbox docs (#23448)
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
2026-03-25 09:49:58 -07:00
Adib234 028d0368d5 fix(policy): relax write_file argsPattern in plan mode to allow paths without session ID (#23695) 2026-03-25 16:06:45 +00:00
tony-shi 6deee11449 fix(browser): add proxy bypass constraint to domain restriction system prompt (#23229)
Co-authored-by: cynthialong0-0 <82900738+cynthialong0-0@users.noreply.github.com>
2026-03-25 15:59:21 +00:00
tony-shi bbf5c2fe95 fix(browser): detect embedded URLs in query params to prevent allowedDomains bypass (#23225)
Co-authored-by: cynthialong0-0 <82900738+cynthialong0-0@users.noreply.github.com>
2026-03-25 15:26:00 +00:00
Sheikh Limon e667739c04 docs(reference): split tools table into category sections (#21516) 2026-03-25 15:11:39 +00:00
Emily Hedlund 109a7dc531 test(core): install bubblewrap on Linux CI for sandbox integration tests (#23583) 2026-03-25 14:29:46 +00:00
cynthialong0-0 5e186bfb22 fix(cli): skip console log/info in headless mode (#22739) 2026-03-25 13:46:00 +00:00
862 changed files with 55727 additions and 15788 deletions
+89
View File
@@ -0,0 +1,89 @@
# --- STAGE 1: Base Runtime ---
FROM docker.io/library/node:20-slim AS base
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
python3-pip \
python3-venv \
curl \
dnsutils \
less \
jq \
ca-certificates \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# --- STAGE 2: Builder (Compile Main) ---
FROM base AS builder
WORKDIR /build
COPY . .
RUN npm ci --ignore-scripts
RUN npm run bundle
# Run the official release preparation script to move the bundle and assets into packages/cli
RUN node scripts/prepare-npm-release.js
# --- STAGE 3: Development Environment ---
FROM base AS development
WORKDIR /home/node/dev/main
# Set up npm global package folder
RUN mkdir -p /usr/local/share/npm-global \
&& chown -R node:node /usr/local/share/npm-global
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
ENV PATH=$PATH:/usr/local/share/npm-global/bin
# Copy package.json to extract versions for global tools
COPY package.json /tmp/package.json
# Install Build Tools, Global Dev Tools (pinned), and Linters
ARG ACTIONLINT_VER=1.7.7
ARG SHELLCHECK_VER=0.11.0
ARG YAMLLINT_VER=1.35.1
RUN apt-get update && apt-get install -y --no-install-recommends \
make \
g++ \
gh \
git \
unzip \
rsync \
ripgrep \
procps \
psmisc \
lsof \
socat \
tmux \
docker.io \
build-essential \
libsecret-1-dev \
libkrb5-dev \
file \
&& curl -sSLo /tmp/actionlint.tar.gz https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VER}/actionlint_${ACTIONLINT_VER}_linux_amd64.tar.gz \
&& tar -xzf /tmp/actionlint.tar.gz -C /usr/local/bin actionlint \
&& curl -sSLo /tmp/shellcheck.tar.xz https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VER}/shellcheck-v${SHELLCHECK_VER}.linux.x86_64.tar.xz \
&& tar -xf /tmp/shellcheck.tar.xz -C /usr/local/bin --strip-components=1 shellcheck-v${SHELLCHECK_VER}/shellcheck \
&& pip3 install --break-system-packages yamllint==${YAMLLINT_VER} \
&& export TSX_VER=$(node -p "require('/tmp/package.json').devDependencies.tsx") \
&& export VITEST_VER=$(node -p "require('/tmp/package.json').devDependencies.vitest") \
&& export PRETTIER_VER=$(node -p "require('/tmp/package.json').devDependencies.prettier") \
&& export ESLINT_VER=$(node -p "require('/tmp/package.json').devDependencies.eslint") \
&& export CROSS_ENV_VER=$(node -p "require('/tmp/package.json').devDependencies['cross-env']") \
&& npm install -g tsx@$TSX_VER vitest@$VITEST_VER prettier@$PRETTIER_VER eslint@$ESLINT_VER cross-env@$CROSS_ENV_VER typescript@5.3.3 \
&& npm install -g @google/gemini-cli@nightly && mv /usr/local/share/npm-global/bin/gemini /usr/local/share/npm-global/bin/g-nightly \
&& npm install -g @google/gemini-cli@preview && mv /usr/local/share/npm-global/bin/gemini /usr/local/share/npm-global/bin/g-preview \
&& npm install -g @google/gemini-cli@latest && mv /usr/local/share/npm-global/bin/gemini /usr/local/share/npm-global/bin/g-stable \
&& apt-get purge -y build-essential libsecret-1-dev libkrb5-dev \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /root/.npm
# Copy the bundled CLI package to a permanent location and install it
# We MUST not delete this source folder as 'npm install -g <folder>'
# often symlinks to it for local folder installs.
COPY --from=builder /build/packages/cli /usr/local/lib/gemini-cli
RUN npm install -g /usr/local/lib/gemini-cli
USER node
CMD ["/bin/bash"]
+10
View File
@@ -0,0 +1,10 @@
node_modules
.git
.gemini/workspaces
dist
!packages/*/dist/*.tgz
bundle
out
*.log
.env
.DS_Store
+58
View File
@@ -0,0 +1,58 @@
substitutions:
_IMAGE_NAME: 'development'
_ARTIFACT_REGISTRY_REPO: 'us-docker.pkg.dev/gemini-code-dev/gemini-cli'
steps:
# Step 1: Install root dependencies
- name: 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code-builder'
id: 'Install Dependencies'
entrypoint: 'npm'
args: ['install']
# Step 2: Authenticate for Docker
- name: 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code-builder'
id: 'Authenticate docker'
entrypoint: 'npm'
args: ['run', 'auth']
# Step 3: Build workspace packages
- name: 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code-builder'
id: 'Build packages'
entrypoint: 'npm'
args: ['run', 'build:packages']
# Step 4: Build Development Image
- name: 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code-builder'
id: 'Build Development Image'
entrypoint: 'bash'
env:
- 'RAW_BRANCH_VALUE=${BRANCH_NAME}'
args:
- '-c'
- |-
IMAGE_BASE="${_ARTIFACT_REGISTRY_REPO}/${_IMAGE_NAME}"
# Determine the primary tag (branch name or 'latest' for main)
# Use $$ for shell variables to avoid Cloud Build attempting premature substitution
RAW_BRANCH="$$RAW_BRANCH_VALUE"
if [ "$${RAW_BRANCH}" == "main" ]; then
TAG_PRIMARY="latest"
else
TAG_PRIMARY=$$(echo "$${RAW_BRANCH}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]')
fi
# Use SHORT_SHA if available (Cloud Build) or fallback to latest-dev
TAG_SHA="$${SHORT_SHA:-latest-dev}"
echo "📦 Building Development Image for: $${RAW_BRANCH} -> $${TAG_PRIMARY} ($${TAG_SHA})"
docker build -f .gcp/Dockerfile.development \
-t "$${IMAGE_BASE}:$${TAG_SHA}" \
-t "$${IMAGE_BASE}:$${TAG_PRIMARY}" .
docker push "$${IMAGE_BASE}:$${TAG_SHA}"
docker push "$${IMAGE_BASE}:$${TAG_PRIMARY}"
options:
defaultLogsBucketBehavior: 'REGIONAL_USER_OWNED_BUCKET'
dynamicSubstitutions: true
+1 -2
View File
@@ -1,9 +1,8 @@
{
"experimental": {
"plan": true,
"extensionReloading": true,
"modelSteering": true,
"memoryManager": true
"topicUpdateNarration": true
},
"general": {
"devtools": true
@@ -1,190 +1,194 @@
#!/bin/bash
notify() {
local title="$1"
local message="$2"
local pr="$3"
local title="${1}"
local message="${2}"
local pr="${3}"
# Terminal escape sequence
printf "\e]9;%s | PR #%s | %s\a" "$title" "$pr" "$message"
printf "\e]9;%s | PR #%s | %s\a" "${title}" "${pr}" "${message}"
# Native macOS notification
if [[ "$(uname)" == "Darwin" ]]; then
osascript -e "display notification \"$message\" with title \"$title\" subtitle \"PR #$pr\""
os_type="$(uname || true)"
if [[ "${os_type}" == "Darwin" ]]; then
osascript -e "display notification \"${message}\" with title \"${title}\" subtitle \"PR #${pr}\""
fi
}
pr_number=$1
if [[ -z "$pr_number" ]]; then
pr_number="${1}"
if [[ -z "${pr_number}" ]]; then
echo "Usage: async-review <pr_number>"
exit 1
fi
base_dir=$(git rev-parse --show-toplevel 2>/dev/null)
if [[ -z "$base_dir" ]]; then
base_dir="$(git rev-parse --show-toplevel 2>/dev/null || true)"
if [[ -z "${base_dir}" ]]; then
echo "❌ Must be run from within a git repository."
exit 1
fi
# Use the repository's local .gemini/tmp directory for ephemeral worktrees and logs
pr_dir="$base_dir/.gemini/tmp/async-reviews/pr-$pr_number"
target_dir="$pr_dir/worktree"
log_dir="$pr_dir/logs"
pr_dir="${base_dir}/.gemini/tmp/async-reviews/pr-${pr_number}"
target_dir="${pr_dir}/worktree"
log_dir="${pr_dir}/logs"
cd "$base_dir" || exit 1
cd "${base_dir}" || exit 1
mkdir -p "$log_dir"
rm -f "$log_dir/setup.exit" "$log_dir/final-assessment.exit" "$log_dir/final-assessment.md"
mkdir -p "${log_dir}"
rm -f "${log_dir}/setup.exit" "${log_dir}/final-assessment.exit" "${log_dir}/final-assessment.md"
echo "🧹 Cleaning up previous worktree if it exists..." | tee -a "$log_dir/setup.log"
git worktree remove -f "$target_dir" >> "$log_dir/setup.log" 2>&1 || true
git branch -D "gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1 || true
git worktree prune >> "$log_dir/setup.log" 2>&1 || true
echo "🧹 Cleaning up previous worktree if it exists..." | tee -a "${log_dir}/setup.log"
git worktree remove -f "${target_dir}" >> "${log_dir}/setup.log" 2>&1 || true
git branch -D "gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1 || true
git worktree prune >> "${log_dir}/setup.log" 2>&1 || true
echo "📡 Fetching PR #$pr_number..." | tee -a "$log_dir/setup.log"
if ! git fetch origin -f "pull/$pr_number/head:gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1; then
echo 1 > "$log_dir/setup.exit"
echo "❌ Fetch failed. Check $log_dir/setup.log"
notify "Async Review Failed" "Fetch failed." "$pr_number"
echo "📡 Fetching PR #${pr_number}..." | tee -a "${log_dir}/setup.log"
if ! git fetch origin -f "pull/${pr_number}/head:gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1; then
echo 1 > "${log_dir}/setup.exit"
echo "❌ Fetch failed. Check ${log_dir}/setup.log"
notify "Async Review Failed" "Fetch failed." "${pr_number}"
exit 1
fi
if [[ ! -d "$target_dir" ]]; then
echo "🧹 Pruning missing worktrees..." | tee -a "$log_dir/setup.log"
git worktree prune >> "$log_dir/setup.log" 2>&1
echo "🌿 Creating worktree in $target_dir..." | tee -a "$log_dir/setup.log"
if ! git worktree add "$target_dir" "gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1; then
echo 1 > "$log_dir/setup.exit"
echo "❌ Worktree creation failed. Check $log_dir/setup.log"
notify "Async Review Failed" "Worktree creation failed." "$pr_number"
if [[ ! -d "${target_dir}" ]]; then
echo "🧹 Pruning missing worktrees..." | tee -a "${log_dir}/setup.log"
git worktree prune >> "${log_dir}/setup.log" 2>&1
echo "🌿 Creating worktree in ${target_dir}..." | tee -a "${log_dir}/setup.log"
if ! git worktree add "${target_dir}" "gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1; then
echo 1 > "${log_dir}/setup.exit"
echo "❌ Worktree creation failed. Check ${log_dir}/setup.log"
notify "Async Review Failed" "Worktree creation failed." "${pr_number}"
exit 1
fi
else
echo "🌿 Worktree already exists." | tee -a "$log_dir/setup.log"
echo "🌿 Worktree already exists." | tee -a "${log_dir}/setup.log"
fi
echo 0 > "$log_dir/setup.exit"
echo 0 > "${log_dir}/setup.exit"
cd "$target_dir" || exit 1
cd "${target_dir}" || exit 1
echo "🚀 Launching background tasks. Logs saving to: $log_dir"
echo "🚀 Launching background tasks. Logs saving to: ${log_dir}"
echo " ↳ [1/5] Grabbing PR diff..."
rm -f "$log_dir/pr-diff.exit"
{ gh pr diff "$pr_number" > "$log_dir/pr-diff.diff" 2>&1; echo $? > "$log_dir/pr-diff.exit"; } &
rm -f "${log_dir}/pr-diff.exit"
{ gh pr diff "${pr_number}" > "${log_dir}/pr-diff.diff" 2>&1; echo $? > "${log_dir}/pr-diff.exit"; } &
echo " ↳ [2/5] Starting build and lint..."
rm -f "$log_dir/build-and-lint.exit"
{ { 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"; } &
rm -f "${log_dir}/build-and-lint.exit"
{ { 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)
GEMINI_CMD=$(which gemini || echo "$HOME/.gcli/nightly/node_modules/.bin/gemini")
GEMINI_CMD="$(command -v gemini || echo "${HOME}/.gcli/nightly/node_modules/.bin/gemini")"
# shellcheck disable=SC2312
POLICY_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/policy.toml"
echo " ↳ [3/5] Starting Gemini code review..."
rm -f "$log_dir/review.exit"
{ "$GEMINI_CMD" --policy "$POLICY_PATH" -p "/review-frontend $pr_number" > "$log_dir/review.md" 2>&1; echo $? > "$log_dir/review.exit"; } &
rm -f "${log_dir}/review.exit"
{ "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "/review-frontend ${pr_number}" > "${log_dir}/review.md" 2>&1; echo $? > "${log_dir}/review.exit"; } &
echo " ↳ [4/5] Starting automated tests (waiting for build and lint)..."
rm -f "$log_dir/npm-test.exit"
rm -f "${log_dir}/npm-test.exit"
{
while [ ! -f "$log_dir/build-and-lint.exit" ]; do sleep 1; done
if [ "$(cat "$log_dir/build-and-lint.exit")" == "0" ]; then
gh pr checks "$pr_number" > "$log_dir/ci-checks.log" 2>&1
while [[ ! -f "${log_dir}/build-and-lint.exit" ]]; do sleep 1; done
read -r build_exit < "${log_dir}/build-and-lint.exit" || build_exit=""
if [[ "${build_exit}" == "0" ]]; then
gh pr checks "${pr_number}" > "${log_dir}/ci-checks.log" 2>&1
ci_status=$?
if [ "$ci_status" -eq 0 ]; then
echo "CI checks passed. Skipping local npm tests." > "$log_dir/npm-test.log"
echo 0 > "$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 0 > "$log_dir/npm-test.exit"
if [[ "${ci_status}" -eq 0 ]]; then
echo "CI checks passed. Skipping local npm tests." > "${log_dir}/npm-test.log"
echo 0 > "${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 0 > "${log_dir}/npm-test.exit"
else
echo "CI checks failed. Failing checks:" > "$log_dir/npm-test.log"
gh pr checks "$pr_number" --json name,bucket -q '.[] | select(.bucket=="fail") | .name' >> "$log_dir/npm-test.log" 2>&1
echo "CI checks failed. Failing checks:" > "${log_dir}/npm-test.log"
gh pr checks "${pr_number}" --json name,bucket -q '.[] | select(.bucket=="fail") | .name' >> "${log_dir}/npm-test.log" 2>&1
echo "Attempting to extract failing test files from CI logs..." >> "$log_dir/npm-test.log"
pr_branch=$(gh pr view "$pr_number" --json headRefName -q '.headRefName' 2>/dev/null)
run_id=$(gh run list --branch "$pr_branch" --workflow ci.yml --json databaseId -q '.[0].databaseId' 2>/dev/null)
echo "Attempting to extract failing test files from CI logs..." >> "${log_dir}/npm-test.log"
pr_branch="$(gh pr view "${pr_number}" --json headRefName -q '.headRefName' 2>/dev/null || true)"
run_id="$(gh run list --branch "${pr_branch}" --workflow ci.yml --json databaseId -q '.[0].databaseId' 2>/dev/null || true)"
failed_files=""
if [[ -n "$run_id" ]]; then
failed_files=$(gh run view "$run_id" --log-failed 2>/dev/null | grep -o -E '(packages/[a-zA-Z0-9_-]+|integration-tests|evals)/[a-zA-Z0-9_/-]+\.test\.ts(x)?' | sort | uniq)
if [[ -n "${run_id}" ]]; then
failed_files="$(gh run view "${run_id}" --log-failed 2>/dev/null | grep -o -E '(packages/[a-zA-Z0-9_-]+|integration-tests|evals)/[a-zA-Z0-9_/-]+\.test\.ts(x)?' | sort | uniq || true)"
fi
if [[ -n "$failed_files" ]]; then
echo "Found failing test files from CI:" >> "$log_dir/npm-test.log"
for f in $failed_files; do echo " - $f" >> "$log_dir/npm-test.log"; done
echo "Running ONLY failing tests locally..." >> "$log_dir/npm-test.log"
if [[ -n "${failed_files}" ]]; then
echo "Found failing test files from CI:" >> "${log_dir}/npm-test.log"
for f in ${failed_files}; do echo " - ${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)
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)
ws_dir="$(echo "${file}" | cut -d'/' -f1)"
fi
rel_file=${file#$ws_dir/}
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
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"
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"
echo 1 > "$log_dir/npm-test.exit"
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"
echo 1 > "${log_dir}/npm-test.exit"
fi
fi
else
echo "Skipped due to build-and-lint failure" > "$log_dir/npm-test.log"
echo 1 > "$log_dir/npm-test.exit"
echo "Skipped due to build-and-lint failure" > "${log_dir}/npm-test.log"
echo 1 > "${log_dir}/npm-test.exit"
fi
} &
echo " ↳ [5/5] Starting Gemini test execution (waiting for build and lint)..."
rm -f "$log_dir/test-execution.exit"
rm -f "${log_dir}/test-execution.exit"
{
while [ ! -f "$log_dir/build-and-lint.exit" ]; do sleep 1; done
if [ "$(cat "$log_dir/build-and-lint.exit")" == "0" ]; then
"$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"
while [[ ! -f "${log_dir}/build-and-lint.exit" ]]; do sleep 1; done
read -r build_exit < "${log_dir}/build-and-lint.exit" || build_exit=""
if [[ "${build_exit}" == "0" ]]; then
"${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"
echo 1 > "$log_dir/test-execution.exit"
echo "Skipped due to build-and-lint failure" > "${log_dir}/test-execution.log"
echo 1 > "${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"
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
tasks=("pr-diff" "build-and-lint" "review" "npm-test" "test-execution")
log_files=("pr-diff.diff" "build-and-lint.log" "review.md" "npm-test.log" "test-execution.log")
declare -A task_done
for t in "${tasks[@]}"; do task_done[$t]=0; done
for t in "${tasks[@]}"; do task_done[${t}]=0; done
all_done=0
while [[ $all_done -eq 0 ]]; do
while [[ "${all_done}" -eq 0 ]]; do
clear
echo "=================================================="
echo "🚀 Async PR Review Status for PR #$pr_number"
echo "🚀 Async PR Review Status for PR #${pr_number}"
echo "=================================================="
echo ""
all_done=1
for i in "${!tasks[@]}"; do
t="${tasks[$i]}"
t="${tasks[${i}]}"
if [[ -f "$log_dir/$t.exit" ]]; then
exit_code=$(cat "$log_dir/$t.exit")
if [[ "$exit_code" == "0" ]]; then
echo "$t: SUCCESS"
if [[ -f "${log_dir}/${t}.exit" ]]; then
read -r task_exit < "${log_dir}/${t}.exit" || task_exit=""
if [[ "${task_exit}" == "0" ]]; then
echo "${t}: SUCCESS"
else
echo "$t: FAILED (exit code $exit_code)"
echo "${t}: FAILED (exit code ${task_exit})"
fi
task_done[$t]=1
task_done[${t}]=1
else
echo "$t: RUNNING"
echo "${t}: RUNNING"
all_done=0
fi
done
@@ -195,47 +199,47 @@ while [[ $all_done -eq 0 ]]; do
echo "=================================================="
for i in "${!tasks[@]}"; do
t="${tasks[$i]}"
log_file="${log_files[$i]}"
t="${tasks[${i}]}"
log_file="${log_files[${i}]}"
if [[ ${task_done[$t]} -eq 0 ]]; then
if [[ -f "$log_dir/$log_file" ]]; then
if [[ "${task_done[${t}]}" -eq 0 ]]; then
if [[ -f "${log_dir}/${log_file}" ]]; then
echo ""
echo "--- $t ---"
tail -n 5 "$log_dir/$log_file"
echo "--- ${t} ---"
tail -n 5 "${log_dir}/${log_file}"
fi
fi
done
if [[ $all_done -eq 0 ]]; then
if [[ "${all_done}" -eq 0 ]]; then
sleep 3
fi
done
clear
echo "=================================================="
echo "🚀 Async PR Review Status for PR #$pr_number"
echo "🚀 Async PR Review Status for PR #${pr_number}"
echo "=================================================="
echo ""
for t in "${tasks[@]}"; do
exit_code=$(cat "$log_dir/$t.exit")
if [[ "$exit_code" == "0" ]]; then
echo "$t: SUCCESS"
read -r task_exit < "${log_dir}/${t}.exit" || task_exit=""
if [[ "${task_exit}" == "0" ]]; then
echo "${t}: SUCCESS"
else
echo "$t: FAILED (exit code $exit_code)"
echo "${t}: FAILED (exit code ${task_exit})"
fi
done
echo ""
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"
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."
notify "Async Review Failed" "Final assessment synthesis failed." "$pr_number"
echo "Check ${log_dir}/final-assessment.md for details."
notify "Async Review Failed" "Final assessment synthesis failed." "${pr_number}"
exit 1
fi
echo 0 > "$log_dir/final-assessment.exit"
echo "✅ Final assessment complete! Check $log_dir/final-assessment.md"
notify "Async Review Complete" "Review and test execution finished successfully." "$pr_number"
echo 0 > "${log_dir}/final-assessment.exit"
echo "✅ Final assessment complete! Check ${log_dir}/final-assessment.md"
notify "Async Review Complete" "Review and test execution finished successfully." "${pr_number}"
@@ -1,22 +1,22 @@
#!/bin/bash
pr_number=$1
pr_number="${1}"
if [[ -z "$pr_number" ]]; then
if [[ -z "${pr_number}" ]]; then
echo "Usage: check-async-review <pr_number>"
exit 1
fi
base_dir=$(git rev-parse --show-toplevel 2>/dev/null)
if [[ -z "$base_dir" ]]; then
base_dir="$(git rev-parse --show-toplevel 2>/dev/null || true)"
if [[ -z "${base_dir}" ]]; then
echo "❌ Must be run from within a git repository."
exit 1
fi
log_dir="$base_dir/.gemini/tmp/async-reviews/pr-$pr_number/logs"
log_dir="${base_dir}/.gemini/tmp/async-reviews/pr-${pr_number}/logs"
if [[ ! -d "$log_dir" ]]; then
if [[ ! -d "${log_dir}" ]]; then
echo "STATUS: NOT_FOUND"
echo "❌ No logs found for PR #$pr_number in $log_dir"
echo "❌ No logs found for PR #${pr_number} in ${log_dir}"
exit 0
fi
@@ -34,32 +34,32 @@ all_done=true
echo "STATUS: CHECKING"
for task_info in "${tasks[@]}"; do
IFS="|" read -r task_name log_file <<< "$task_info"
IFS="|" read -r task_name log_file <<< "${task_info}"
file_path="$log_dir/$log_file"
exit_file="$log_dir/$task_name.exit"
file_path="${log_dir}/${log_file}"
exit_file="${log_dir}/${task_name}.exit"
if [[ -f "$exit_file" ]]; then
exit_code=$(cat "$exit_file")
if [[ "$exit_code" == "0" ]]; then
echo "$task_name: SUCCESS"
if [[ -f "${exit_file}" ]]; then
read -r exit_code < "${exit_file}" || exit_code=""
if [[ "${exit_code}" == "0" ]]; then
echo "${task_name}: SUCCESS"
else
echo "$task_name: FAILED (exit code $exit_code)"
echo " Last lines of $file_path:"
tail -n 3 "$file_path" | sed 's/^/ /'
echo "${task_name}: FAILED (exit code ${exit_code})"
echo " Last lines of ${file_path}:"
tail -n 3 "${file_path}" | sed 's/^/ /' || true
fi
elif [[ -f "$file_path" ]]; then
echo "$task_name: RUNNING"
elif [[ -f "${file_path}" ]]; then
echo "${task_name}: RUNNING"
all_done=false
else
echo " $task_name: NOT STARTED"
echo " ${task_name}: NOT STARTED"
all_done=false
fi
done
if $all_done; then
if [[ "${all_done}" == "true" ]]; then
echo "STATUS: COMPLETE"
echo "LOG_DIR: $log_dir"
echo "LOG_DIR: ${log_dir}"
else
echo "STATUS: IN_PROGRESS"
fi
fi
@@ -33,6 +33,35 @@ evaluation.
- **Warning**: Do not lose test fidelity by making prompts too direct/easy.
- **Primary Fix Trigger**: Adjust tool descriptions, system prompts
(`snippets.ts`), or **modules that contribute to the prompt template**.
- Fixes should generally try to improve the prompt
`@packages/core/src/prompts/snippets.ts` first.
- **Instructional Generality**: Changes to the system prompt should aim to
be as general as possible while still accomplishing the goal. Specificity
should be added only as needed.
- **Principle**: Instead of creating "forbidden lists" for specific syntax
(e.g., "Don't use `Object.create()`"), formulate a broader engineering
principle that covers the underlying issue (e.g., "Prioritize explicit
composition over hidden prototype manipulation"). This improves
steerability across a wider range of similar scenarios.
- _Low Specificity_: "Follow ecosystem best practices"
- _Medium Specificity_: "Utilize OOP and functional best practices, as
applicable"
- _High Specificity_: Provide ecosystem-specific hints as examples of a
broader principle rather than direct instructions. e.g., "NEVER use
hacks like bypassing the type system or employing 'hidden' logic (e.g.:
reflection, prototype manipulation). Instead, use explicit and idiomatic
language features (e.g.: type guards, explicit class instantiation, or
object spread) that maintain structural integrity."
- **Prompt Simplification**: Once the test is passing, use `ask_user` to
determine if prompt simplification is desired.
- **Criteria**: Simplification should be attempted only if there are
related clauses that can be de-duplicated or reparented under a single
heading.
- **Verification**: As part of simplification, you MUST identify and run
any behavioral eval tests that might be affected by the changes to
ensure no regressions are introduced.
- Test fixes should not "cheat" by changing a test's `GEMINI.md` file or by
updating the test's prompt to instruct it to not repro the bug.
- **Warning**: Prompts have multiple configurations; ensure your fix targets
the correct config for the model in question.
4. **Architecture Options**: If prompt or instruction tuning triggers no
+12 -3
View File
@@ -65,8 +65,6 @@ accessible.
- **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
@@ -100,6 +98,18 @@ accessible.
> This is an example of a multi-line note that will be preserved
> by Prettier.
### Links
- **Accessibility:** Use descriptive anchor text; avoid "click here." Ensure the
link makes sense out of context, such as when being read by a screen reader.
- **Use relative links in docs:** Use relative links in documentation (`/docs/`)
to ensure portability. Use paths relative to the current file's directory
(for example, `../tools/` from `docs/cli/`). Do not include the `/docs/`
section of a path, but do verify that the resulting relative link exists. This
does not apply to meta files such as README.MD and CONTRIBUTING.MD.
- **When changing headings, check for deep links:** If a user is changing a
heading, check for deep links to that heading in other pages and update
accordingly.
### Structure
- **BLUF:** Start with an introduction explaining what to expect.
- **Experimental features:** If a feature is clearly noted as experimental,
@@ -157,7 +167,6 @@ documentation.
- **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.
@@ -0,0 +1,69 @@
---
name: review-duplication
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.
### 2. Hypothesize Existing Locations & Trace Dependencies
Think about where this type of code *would* live if it already existed in the project. Provide absolute paths from the repo root to disambiguate.
- **Utilities:** `packages/core/src/utils/`, `packages/cli/src/utils/`
- **UI Components:** `packages/cli/src/ui/components/`, `packages/cli/src/ui/`
- **Services:** `packages/core/src/services/`, `packages/cli/src/services/`
- **Configuration:** `packages/core/src/config/`, `packages/cli/src/config/`
- **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';
>
> // Then use it here:
> const displayDate = formatDate(userDate, 'MMM Do, YYYY');
> ```
> Reusing this ensures that the date formatting remains consistent with the rest of the application and handles timezone conversions correctly."
+28 -5
View File
@@ -175,7 +175,9 @@ runs:
--dry-run="${INPUTS_DRY_RUN}" \
--workspace="${INPUTS_CORE_PACKAGE_NAME}" \
--no-tag
npm dist-tag rm ${INPUTS_CORE_PACKAGE_NAME} false --silent
if [[ "${INPUTS_DRY_RUN}" == "false" ]]; then
npm dist-tag rm ${INPUTS_CORE_PACKAGE_NAME} false
fi
- name: '🔗 Install latest core package'
working-directory: '${{ inputs.working-directory }}'
@@ -193,7 +195,7 @@ runs:
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
- name: '📦 Prepare bundled CLI for npm release'
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/' && inputs.npm-tag != 'latest'"
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/'"
working-directory: '${{ inputs.working-directory }}'
shell: 'bash'
run: |
@@ -221,7 +223,9 @@ runs:
--dry-run="${INPUTS_DRY_RUN}" \
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \
--no-tag
npm dist-tag rm ${INPUTS_CLI_PACKAGE_NAME} false --silent
if [[ "${INPUTS_DRY_RUN}" == "false" ]]; then
npm dist-tag rm ${INPUTS_CLI_PACKAGE_NAME} false
fi
- name: 'Get a2a-server Token'
uses: './.github/actions/npm-auth-token'
@@ -246,7 +250,9 @@ runs:
--dry-run="${INPUTS_DRY_RUN}" \
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \
--no-tag
npm dist-tag rm ${INPUTS_A2A_PACKAGE_NAME} false --silent
if [[ "${INPUTS_DRY_RUN}" == "false" ]]; then
npm dist-tag rm ${INPUTS_A2A_PACKAGE_NAME} false
fi
- name: '🔬 Verify NPM release by version'
uses: './.github/actions/verify-release'
@@ -285,8 +291,25 @@ runs:
INPUTS_PREVIOUS_TAG: '${{ inputs.previous-tag }}'
shell: 'bash'
run: |
rm -f gemini-cli-bundle.zip
(cd bundle && chmod +x gemini.js && zip -r ../gemini-cli-bundle.zip .)
echo "Testing the generated bundle archive..."
rm -rf test-bundle
mkdir -p test-bundle
unzip -q gemini-cli-bundle.zip -d test-bundle
# Verify it runs and outputs a version
BUNDLE_VERSION=$(node test-bundle/gemini.js --version | xargs)
echo "Bundle version output: ${BUNDLE_VERSION}"
if [[ -z "${BUNDLE_VERSION}" ]]; then
echo "Error: Bundle failed to execute or return version."
exit 1
fi
rm -rf test-bundle
gh release create "${INPUTS_RELEASE_TAG}" \
bundle/gemini.js \
gemini-cli-bundle.zip \
--target "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}" \
--title "Release ${INPUTS_RELEASE_TAG}" \
--notes-start-tag "${INPUTS_PREVIOUS_TAG}" \
+4 -4
View File
@@ -34,7 +34,7 @@ runs:
JSON_INPUTS: '${{ toJSON(inputs) }}'
run: 'echo "$JSON_INPUTS"'
- name: 'Checkout'
uses: 'actions/checkout@v4'
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet:actions/checkout@v4
with:
ref: '${{ inputs.github-sha }}'
fetch-depth: 0
@@ -45,11 +45,11 @@ runs:
shell: 'bash'
run: 'npm run build'
- name: 'Set up QEMU'
uses: 'docker/setup-qemu-action@v3'
uses: 'docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130' # ratchet:docker/setup-qemu-action@v3
- name: 'Set up Docker Buildx'
uses: 'docker/setup-buildx-action@v3'
uses: 'docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f' # ratchet:docker/setup-buildx-action@v3
- name: 'Log in to GitHub Container Registry'
uses: 'docker/login-action@v3'
uses: 'docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9' # ratchet:docker/login-action@v3
with:
registry: 'docker.io'
username: '${{ inputs.dockerhub-username }}'
+7
View File
@@ -18,6 +18,13 @@ runs:
env:
JSON_INPUTS: '${{ toJSON(inputs) }}'
run: 'echo "$JSON_INPUTS"'
- name: 'Install system dependencies'
if: "runner.os == 'Linux'"
run: |
sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq bubblewrap
# Ubuntu 24.04+ requires this to allow bwrap to function in CI
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
shell: 'bash'
- name: 'Run Tests'
env:
GEMINI_API_KEY: '${{ inputs.gemini_api_key }}'
+1 -1
View File
@@ -36,7 +36,7 @@ runs:
run: 'echo "$JSON_INPUTS"'
- name: 'setup node'
uses: 'actions/setup-node@v4'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
with:
node-version: '20'
+14
View File
@@ -334,8 +334,22 @@ jobs:
if: "${{ steps.check_evals.outputs.should_run == 'true' }}"
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
GEMINI_MODEL: 'gemini-3-pro-preview'
# Only run always passes behavioral tests.
EVAL_SUITE_TYPE: 'behavioral'
# Disable Vitest internal retries to avoid double-retrying;
# custom retry logic is handled in evals/test-helper.ts
VITEST_RETRY: 0
run: 'npm run test:always_passing_evals'
- name: 'Upload Reliability Logs'
if: "always() && steps.check_evals.outputs.should_run == 'true'"
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'eval-logs-${{ github.run_id }}-${{ github.run_attempt }}'
path: 'evals/logs/api-reliability.jsonl'
retention-days: 7
e2e:
name: 'E2E'
if: |
+20 -8
View File
@@ -67,7 +67,7 @@ jobs:
cache: 'npm'
- name: 'Cache Linters'
uses: 'actions/cache@v4'
uses: 'actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830' # ratchet:actions/cache@v4
with:
path: '${{ env.GEMINI_LINT_TEMP_DIR }}'
key: "${{ runner.os }}-${{ runner.arch }}-linters-${{ hashFiles('scripts/lint.js') }}"
@@ -76,7 +76,7 @@ jobs:
run: 'npm ci'
- name: 'Cache ESLint'
uses: 'actions/cache@v4'
uses: 'actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830' # ratchet:actions/cache@v4
with:
path: '.eslintcache'
key: "${{ runner.os }}-eslint-${{ hashFiles('package-lock.json', 'eslint.config.js') }}"
@@ -114,6 +114,9 @@ jobs:
- name: 'Run sensitive keyword linter'
run: 'node scripts/lint.js --sensitive-keywords'
- name: 'Run GitHub Actions pinning linter'
run: 'node scripts/lint.js --check-github-actions-pinning'
link_checker:
name: 'Link Checker'
runs-on: 'ubuntu-latest'
@@ -158,6 +161,12 @@ jobs:
- name: 'Build project'
run: 'npm run build'
- name: 'Install system dependencies'
run: |
sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq bubblewrap
# Ubuntu 24.04+ requires this to allow bwrap to function in CI
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
- name: 'Install dependencies for testing'
run: 'npm ci'
@@ -166,10 +175,10 @@ jobs:
NO_COLOR: true
run: |
if [[ "${{ matrix.shard }}" == "cli" ]]; then
npm run test:ci --workspace @google/gemini-cli
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 -- --coverage.enabled=false
npm run test:ci --workspace "@google/gemini-cli-core" --workspace "@google/gemini-cli-a2a-server" --workspace "gemini-cli-vscode-ide-companion" --workspace "@google/gemini-cli-test-utils" --if-present -- --coverage.enabled=false
npm run test:scripts
fi
@@ -254,10 +263,10 @@ jobs:
NO_COLOR: true
run: |
if [[ "${{ matrix.shard }}" == "cli" ]]; then
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
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: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
@@ -420,11 +429,14 @@ jobs:
NODE_ENV: 'test'
run: |
if ("${{ matrix.shard }}" -eq "cli") {
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
npm run test:ci --workspace "@google/gemini-cli" -- --coverage.enabled=false
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
} 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: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
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
npm run test:scripts
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
shell: 'pwsh'
-69
View File
@@ -1,69 +0,0 @@
name: 'Evals: PR Guidance'
on:
pull_request:
paths:
- 'packages/core/src/**/*.ts'
- '!**/*.test.ts'
- '!**/*.test.tsx'
permissions:
pull-requests: 'write'
contents: 'read'
jobs:
provide-guidance:
name: 'Model Steering Guidance'
runs-on: 'ubuntu-latest'
if: "github.repository == 'google-gemini/gemini-cli'"
steps:
- name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v4
with:
fetch-depth: 0
- name: 'Set up Node.js'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 'Detect Steering Changes'
id: 'detect'
run: |
STEERING_DETECTED=$(node scripts/changed_prompt.js --steering-only)
echo "STEERING_DETECTED=$STEERING_DETECTED" >> "$GITHUB_OUTPUT"
- name: 'Analyze PR Content'
if: "steps.detect.outputs.STEERING_DETECTED == 'true'"
id: 'analysis'
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: |
# Check for behavioral eval changes
EVAL_CHANGES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep "^evals/" || true)
if [ -z "$EVAL_CHANGES" ]; then
echo "MISSING_EVALS=true" >> "$GITHUB_OUTPUT"
fi
# Check if user is a maintainer (has write/admin access)
USER_PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission')
if [[ "$USER_PERMISSION" == "admin" || "$USER_PERMISSION" == "write" ]]; then
echo "IS_MAINTAINER=true" >> "$GITHUB_OUTPUT"
fi
- name: 'Post Guidance Comment'
if: "steps.detect.outputs.STEERING_DETECTED == 'true'"
uses: 'thollander/actions-comment-pull-request@65f9e5c9a1f2cd378bd74b2e057c9736982a8e74' # ratchet:thollander/actions-comment-pull-request@v3
with:
comment-tag: 'eval-guidance-bot'
message: |
### 🧠 Model Steering Guidance
This PR modifies files that affect the model's behavior (prompts, tools, or instructions).
${{ steps.analysis.outputs.MISSING_EVALS == 'true' && '- ⚠️ **Consider adding Evals:** No behavioral evaluations (`evals/*.eval.ts`) were added or updated in this PR. Consider adding a test case to verify the new behavior and prevent regressions.' || '' }}
${{ steps.analysis.outputs.IS_MAINTAINER == 'true' && '- 🚀 **Maintainer Reminder:** Please ensure that these changes do not regress results on benchmark evals before merging.' || '' }}
---
*This is an automated guidance message triggered by steering logic signatures.*
+209
View File
@@ -0,0 +1,209 @@
name: 'Evals: PR Evaluation & Regression'
on:
pull_request_target:
types: ['opened', 'synchronize', 'reopened', 'ready_for_review']
paths:
- 'packages/core/src/prompts/**'
- 'packages/core/src/tools/**'
- 'packages/core/src/agents/**'
- 'evals/**'
- '!**/*.test.ts'
- '!**/*.test.tsx'
workflow_dispatch:
# Prevents multiple runs for the same PR simultaneously (saves tokens)
concurrency:
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
cancel-in-progress: true
permissions:
pull-requests: 'write'
contents: 'read'
actions: 'read'
jobs:
detect-changes:
name: 'Detect Steering Changes'
runs-on: 'gemini-cli-ubuntu-16-core'
# Security: pull_request_target allows secrets, so we must gate carefully.
# Detection should not run code from the fork.
if: "github.repository == 'google-gemini/gemini-cli' && github.event.pull_request.draft == false"
outputs:
SHOULD_RUN: '${{ steps.detect.outputs.SHOULD_RUN }}'
STEERING_DETECTED: '${{ steps.detect.outputs.STEERING_DETECTED }}'
steps:
- name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
with:
# Check out the trusted code from main for detection
fetch-depth: 0
- name: 'Detect Steering Changes'
id: 'detect'
env:
# Use the PR's head SHA for comparison without checking it out
PR_HEAD_SHA: '${{ github.event.pull_request.head.sha }}'
run: |
# Fetch the fork's PR branch for analysis
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-head
# Run the trusted script from main
SHOULD_RUN=$(node scripts/changed_prompt.js)
STEERING_DETECTED=$(node scripts/changed_prompt.js --steering-only)
echo "SHOULD_RUN=$SHOULD_RUN" >> "$GITHUB_OUTPUT"
echo "STEERING_DETECTED=$STEERING_DETECTED" >> "$GITHUB_OUTPUT"
- name: 'Notify Approval Required'
if: "steps.detect.outputs.SHOULD_RUN == 'true'"
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: |
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
COMMENT_BODY="### 🛑 Action Required: Evaluation Approval
Steering changes have been detected in this PR. To prevent regressions, a maintainer must approve the evaluation run before this PR can be merged.
**Maintainers:**
1. Go to the [**Workflow Run Summary**]($RUN_URL).
2. Click the yellow **'Review deployments'** button.
3. Select the **'eval-gate'** environment and click **'Approve'**.
Once approved, the evaluation results will be posted here automatically.
<!-- eval-approval-notification -->"
# Check if comment already exists to avoid spamming
COMMENT_ID=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains("<!-- eval-approval-notification -->")) | .url' | grep -oE "[0-9]+$" | head -n 1)
if [ -z "$COMMENT_ID" ]; then
gh pr comment ${{ github.event.pull_request.number }} --body "$COMMENT_BODY"
else
echo "Updating existing notification comment $COMMENT_ID..."
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -F body="$COMMENT_BODY"
fi
pr-evaluation:
name: 'Evaluate Steering & Regressions'
needs: 'detect-changes'
if: "needs.detect-changes.outputs.SHOULD_RUN == 'true'"
# Manual approval gate via environment
environment: 'eval-gate'
runs-on: 'gemini-cli-ubuntu-16-core'
env:
# CENTRALIZED MODEL LIST
MODEL_LIST: 'gemini-3-flash-preview'
steps:
- name: 'Checkout'
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
with:
# Check out the fork's PR code for the actual evaluation
# This only runs AFTER manual approval
ref: '${{ github.event.pull_request.head.sha }}'
fetch-depth: 0
- name: 'Remove Approval Notification'
# Run even if other steps fail, to ensure we clean up the "Action Required" message
if: 'always()'
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
PR_NUMBER: '${{ github.event.pull_request.number }}'
run: |
echo "Debug: PR_NUMBER is '$PR_NUMBER'"
# Search for the notification comment by its hidden tag
COMMENT_ID=$(gh pr view "$PR_NUMBER" --json comments --jq '.comments[] | select(.body | contains("<!-- eval-approval-notification -->")) | .url' | grep -oE "[0-9]+$" | head -n 1)
if [ -n "$COMMENT_ID" ]; then
echo "Removing notification comment $COMMENT_ID now that run is approved..."
gh api -X DELETE "repos/${{ github.repository }}/issues/comments/$COMMENT_ID"
fi
- name: 'Set up Node.js'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'npm'
- name: 'Install dependencies'
run: 'npm ci'
- name: 'Build project'
run: 'npm run build'
- name: 'Analyze PR Content (Guidance)'
if: "needs.detect-changes.outputs.STEERING_DETECTED == 'true'"
id: 'analysis'
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: |
# Check for behavioral eval changes
EVAL_CHANGES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep "^evals/" || true)
if [ -z "$EVAL_CHANGES" ]; then
echo "MISSING_EVALS=true" >> "$GITHUB_OUTPUT"
fi
# Check if user is a maintainer
USER_PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission')
if [[ "$USER_PERMISSION" == "admin" || "$USER_PERMISSION" == "write" ]]; then
echo "IS_MAINTAINER=true" >> "$GITHUB_OUTPUT"
fi
- name: 'Execute Regression Check'
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
MODEL_LIST: '${{ env.MODEL_LIST }}'
run: |
# Run the regression check loop. The script saves the report to a file.
node scripts/run_eval_regression.js
# Use the generated report file if it exists
if [[ -f eval_regression_report.md ]]; then
echo "REPORT_FILE=eval_regression_report.md" >> "$GITHUB_ENV"
fi
- name: 'Post or Update PR Comment'
if: "always() && (needs.detect-changes.outputs.STEERING_DETECTED == 'true' || env.REPORT_FILE != '')"
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
run: |
# 1. Build the full comment body
{
if [[ -f eval_regression_report.md ]]; then
cat eval_regression_report.md
echo ""
fi
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
COMMENT_ID=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains("<!-- eval-pr-report -->")) | .url' | grep -oE "[0-9]+$" | head -n 1)
# 3. Update or Create the comment
if [ -n "$COMMENT_ID" ]; then
echo "Updating existing comment $COMMENT_ID via API..."
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -F body=@full_comment.md
else
echo "Creating new PR comment..."
gh pr comment ${{ github.event.pull_request.number }} --body-file full_comment.md
fi
+17 -5
View File
@@ -5,10 +5,18 @@ on:
- 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
suite_type:
description: 'Suite type to run'
type: 'choice'
options:
- 'behavioral'
- 'component-level'
- 'hero-scenario'
default: 'behavioral'
suite_name:
description: 'Specific suite name to run'
required: false
type: 'string'
test_name_pattern:
description: 'Test name pattern or file name'
required: false
@@ -59,8 +67,12 @@ jobs:
env:
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
GEMINI_MODEL: '${{ matrix.model }}'
RUN_EVALS: "${{ github.event.inputs.run_all != 'false' }}"
RUN_EVALS: 'true'
EVAL_SUITE_TYPE: "${{ github.event.inputs.suite_type || 'behavioral' }}"
EVAL_SUITE_NAME: '${{ github.event.inputs.suite_name }}'
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
# Disable Vitest internal retries to avoid double-retrying;
# custom retry logic is handled in evals/test-helper.ts
VITEST_RETRY: 0
run: |
CMD="npm run test:all_evals"
@@ -28,14 +28,14 @@ jobs:
steps:
- name: 'Generate GitHub App Token'
id: 'generate_token'
uses: 'actions/create-github-app-token@v2'
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet: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'
uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # ratchet:actions/github-script@v7
env:
DRY_RUN: '${{ inputs.dry_run }}'
with:
@@ -27,13 +27,13 @@ jobs:
APP_ID: '${{ secrets.APP_ID }}'
if: |-
${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@v2'
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet: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'
uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # ratchet:actions/github-script@v7
env:
DRY_RUN: '${{ inputs.dry_run }}'
with:
@@ -18,10 +18,10 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- name: 'Checkout'
uses: 'actions/checkout@v4'
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet:actions/checkout@v4
- name: 'Setup Node.js'
uses: 'actions/setup-node@v4'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
@@ -40,10 +40,10 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- name: 'Checkout'
uses: 'actions/checkout@v4'
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet:actions/checkout@v4
- name: 'Setup Node.js'
uses: 'actions/setup-node@v4'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
@@ -15,7 +15,7 @@ jobs:
issues: 'write'
steps:
- name: 'Check for Parent Workstream and Apply Label'
uses: 'actions/github-script@v7'
uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # ratchet:actions/github-script@v7
with:
script: |
const labelToAdd = 'workstream-rollup';
+33
View File
@@ -0,0 +1,33 @@
name: 'Memory Tests: Nightly'
on:
schedule:
- cron: '0 2 * * *' # Runs at 2 AM every day
workflow_dispatch: # Allow manual trigger
permissions:
contents: 'read'
jobs:
memory-test:
name: 'Run Memory Usage Tests'
runs-on: 'gemini-cli-ubuntu-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
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: 'Run Memory Tests'
run: 'npm run test:memory'
+33
View File
@@ -0,0 +1,33 @@
name: 'Performance Tests: Nightly'
on:
schedule:
- cron: '0 3 * * *' # Runs at 3 AM every day
workflow_dispatch: # Allow manual trigger
permissions:
contents: 'read'
jobs:
perf-test:
name: 'Run Performance Usage Tests'
runs-on: 'gemini-cli-ubuntu-16-core'
if: "github.repository == 'google-gemini/gemini-cli'"
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: 'Run Performance Tests'
run: 'npm run test:perf'
@@ -19,7 +19,7 @@ jobs:
APP_ID: '${{ secrets.APP_ID }}'
if: |-
${{ env.APP_ID != '' }}
uses: 'actions/create-github-app-token@v2'
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet:actions/create-github-app-token@v2
with:
app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}'
+1 -1
View File
@@ -40,7 +40,7 @@ jobs:
issues: 'write'
steps:
- name: 'Checkout repository'
uses: 'actions/checkout@v4'
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet:actions/checkout@v4
with:
ref: '${{ github.ref }}'
fetch-depth: 0
+3 -3
View File
@@ -29,14 +29,14 @@ jobs:
pull-requests: 'write'
steps:
- name: 'Checkout repository'
uses: 'actions/checkout@v4'
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet: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'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
with:
node-version: '20'
@@ -86,7 +86,7 @@ jobs:
- name: 'Create Pull Request'
if: "steps.validate_version.outputs.CONTINUE == 'true'"
uses: 'peter-evans/create-pull-request@v6'
uses: 'peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c' # ratchet: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 }}'
+4 -4
View File
@@ -33,7 +33,7 @@ jobs:
steps:
- name: 'Checkout'
uses: 'actions/checkout@v4'
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet:actions/checkout@v4
- name: 'Optimize Windows Performance'
if: "matrix.os == 'windows-latest'"
@@ -46,7 +46,7 @@ jobs:
shell: 'powershell'
- name: 'Set up Node.js'
uses: 'actions/setup-node@v4'
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
with:
node-version-file: '.nvmrc'
architecture: '${{ matrix.arch }}'
@@ -63,7 +63,7 @@ jobs:
- name: 'Setup Windows SDK (Windows)'
if: "matrix.os == 'windows-latest'"
uses: 'microsoft/setup-msbuild@v2'
uses: 'microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce' # ratchet:microsoft/setup-msbuild@v2
- name: 'Add Signtool to Path (Windows)'
if: "matrix.os == 'windows-latest'"
@@ -153,7 +153,7 @@ jobs:
npm run test:integration:sandbox:none -- --testTimeout=600000
- name: 'Upload Artifact'
uses: 'actions/upload-artifact@v4'
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
with:
name: 'gemini-cli-${{ matrix.platform_name }}'
path: 'dist/${{ matrix.platform_name }}/'
@@ -40,13 +40,13 @@ jobs:
steps:
- name: 'Generate GitHub App Token'
id: 'generate_token'
uses: 'actions/create-github-app-token@v2'
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet:actions/create-github-app-token@v2
with:
app-id: '${{ secrets.APP_ID }}'
private-key: '${{ secrets.PRIVATE_KEY }}'
- name: 'Unassign inactive assignees'
uses: 'actions/github-script@v7'
uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # ratchet:actions/github-script@v7
env:
DRY_RUN: '${{ inputs.dry_run }}'
with:
+4
View File
@@ -48,6 +48,7 @@ packages/cli/src/generated/
packages/core/src/generated/
packages/devtools/src/_client-assets.ts
.integration-tests/
.perf-tests/
packages/vscode-ide-companion/*.vsix
packages/cli/download-ripgrep*/
@@ -64,3 +65,6 @@ gemini-debug.log
evals/logs/
temp_agents/
# conductor extension and planning directories
conductor/
+10 -7
View File
@@ -323,8 +323,8 @@ fi
#### Formatting
To separately format the code in this project by running the following command
from the root directory:
To separately format the code in this project, run the following command from
the root directory:
```bash
npm run format
@@ -346,9 +346,11 @@ npm run lint
- Please adhere to the coding style, patterns, and conventions used throughout
the existing codebase.
- Consult [GEMINI.md](../GEMINI.md) (typically found in the project root) for
specific instructions related to AI-assisted development, including
conventions for React, comments, and Git usage.
- Consult
[GEMINI.md](https://github.com/google-gemini/gemini-cli/blob/main/GEMINI.md)
(typically found in the project root) for specific instructions related to
AI-assisted development, including conventions for React, comments, and Git
usage.
- **Imports:** Pay special attention to import paths. The project uses ESLint to
enforce restrictions on relative imports between packages.
@@ -505,8 +507,9 @@ code.
### Documentation structure
Our documentation is organized using [sidebar.json](/docs/sidebar.json) as the
table of contents. When adding new documentation:
Our documentation is organized using
[sidebar.json](https://github.com/google-gemini/gemini-cli/blob/main/docs/sidebar.json)
as the table of contents. When adding new documentation:
1. Create your markdown file **in the appropriate directory** under `/docs`.
2. Add an entry to `sidebar.json` in the relevant section.
+7
View File
@@ -44,6 +44,13 @@ powerful tool for developers.
- **Test Commands:**
- **Unit (All):** `npm run test`
- **Integration (E2E):** `npm run test:e2e`
- > **NOTE**: Please run the memory and perf tests locally **only if** you are
> implementing changes related to those test areas. Otherwise skip these
> tests locally and rely on CI to run them on nightly builds.
- **Memory (Nightly):** `npm run test:memory` (Runs memory regression tests
against baselines. Excluded from `preflight`, run nightly.)
- **Performance (Nightly):** `npm run test:perf` (Runs CPU performance
regression tests against baselines. Excluded from `preflight`, run nightly.)
- **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`)
+58 -50
View File
@@ -30,7 +30,7 @@ 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)
[Gemini CLI installation, execution, and releases](https://www.geminicli.com/docs/get-started/installation)
for recommended system specifications and a detailed installation guide.
### Quick Install
@@ -71,9 +71,9 @@ conda activate gemini_env
npm install -g @google/gemini-cli
```
## Release Cadence and Tags
## Release Channels
See [Releases](./docs/releases.md) for more details.
See [Releases](https://www.geminicli.com/docs/changelogs) for more details.
### Preview
@@ -209,7 +209,7 @@ gemini
```
For Google Workspace accounts and other authentication methods, see the
[authentication guide](./docs/get-started/authentication.md).
[authentication guide](https://www.geminicli.com/docs/get-started/authentication).
## 🚀 Getting Started
@@ -278,59 +278,64 @@ gemini
### Getting Started
- [**Quickstart Guide**](./docs/get-started/index.md) - Get up and running
quickly.
- [**Authentication Setup**](./docs/get-started/authentication.md) - Detailed
auth configuration.
- [**Configuration Guide**](./docs/reference/configuration.md) - Settings and
customization.
- [**Keyboard Shortcuts**](./docs/reference/keyboard-shortcuts.md) -
- [**Quickstart Guide**](https://www.geminicli.com/docs/get-started) - Get up
and running quickly.
- [**Authentication Setup**](https://www.geminicli.com/docs/get-started/authentication) -
Detailed auth configuration.
- [**Configuration Guide**](https://www.geminicli.com/docs/reference/configuration) -
Settings and customization.
- [**Keyboard Shortcuts**](https://www.geminicli.com/docs/reference/keyboard-shortcuts) -
Productivity tips.
### Core Features
- [**Commands Reference**](./docs/reference/commands.md) - All slash commands
(`/help`, `/chat`, etc).
- [**Custom Commands**](./docs/cli/custom-commands.md) - Create your own
reusable commands.
- [**Context Files (GEMINI.md)**](./docs/cli/gemini-md.md) - Provide persistent
context to Gemini CLI.
- [**Checkpointing**](./docs/cli/checkpointing.md) - Save and resume
conversations.
- [**Token Caching**](./docs/cli/token-caching.md) - Optimize token usage.
- [**Commands Reference**](https://www.geminicli.com/docs/reference/commands) -
All slash commands (`/help`, `/chat`, etc).
- [**Custom Commands**](https://www.geminicli.com/docs/cli/custom-commands) -
Create your own reusable commands.
- [**Context Files (GEMINI.md)**](https://www.geminicli.com/docs/cli/gemini-md) -
Provide persistent context to Gemini CLI.
- [**Checkpointing**](https://www.geminicli.com/docs/cli/checkpointing) - Save
and resume conversations.
- [**Token Caching**](https://www.geminicli.com/docs/cli/token-caching) -
Optimize token usage.
### Tools & Extensions
- [**Built-in Tools Overview**](./docs/reference/tools.md)
- [File System Operations](./docs/tools/file-system.md)
- [Shell Commands](./docs/tools/shell.md)
- [Web Fetch & Search](./docs/tools/web-fetch.md)
- [**MCP Server Integration**](./docs/tools/mcp-server.md) - Extend with custom
tools.
- [**Custom Extensions**](./docs/extensions/index.md) - Build and share your own
commands.
- [**Built-in Tools Overview**](https://www.geminicli.com/docs/reference/tools)
- [File System Operations](https://www.geminicli.com/docs/tools/file-system)
- [Shell Commands](https://www.geminicli.com/docs/tools/shell)
- [Web Fetch & Search](https://www.geminicli.com/docs/tools/web-fetch)
- [**MCP Server Integration**](https://www.geminicli.com/docs/tools/mcp-server) -
Extend with custom tools.
- [**Custom Extensions**](https://geminicli.com/docs/extensions/writing-extensions) -
Build and share your own commands.
### Advanced Topics
- [**Headless Mode (Scripting)**](./docs/cli/headless.md) - Use Gemini CLI in
automated workflows.
- [**IDE Integration**](./docs/ide-integration/index.md) - VS Code companion.
- [**Sandboxing & Security**](./docs/cli/sandbox.md) - Safe execution
environments.
- [**Trusted Folders**](./docs/cli/trusted-folders.md) - Control execution
policies by folder.
- [**Enterprise Guide**](./docs/cli/enterprise.md) - Deploy and manage in a
corporate environment.
- [**Telemetry & Monitoring**](./docs/cli/telemetry.md) - Usage tracking.
- [**Tools reference**](./docs/reference/tools.md) - Built-in tools overview.
- [**Local development**](./docs/local-development.md) - Local development
tooling.
- [**Headless Mode (Scripting)**](https://www.geminicli.com/docs/cli/headless) -
Use Gemini CLI in automated workflows.
- [**IDE Integration**](https://www.geminicli.com/docs/ide-integration) - VS
Code companion.
- [**Sandboxing & Security**](https://www.geminicli.com/docs/cli/sandbox) - Safe
execution environments.
- [**Trusted Folders**](https://www.geminicli.com/docs/cli/trusted-folders) -
Control execution policies by folder.
- [**Enterprise Guide**](https://www.geminicli.com/docs/cli/enterprise) - Deploy
and manage in a corporate environment.
- [**Telemetry & Monitoring**](https://www.geminicli.com/docs/cli/telemetry) -
Usage tracking.
- [**Tools reference**](https://www.geminicli.com/docs/reference/tools) -
Built-in tools overview.
- [**Local development**](https://www.geminicli.com/docs/local-development) -
Local development tooling.
### Troubleshooting & Support
- [**Troubleshooting Guide**](./docs/resources/troubleshooting.md) - Common
issues and solutions.
- [**FAQ**](./docs/resources/faq.md) - Frequently asked questions.
- [**Troubleshooting Guide**](https://www.geminicli.com/docs/resources/troubleshooting) -
Common issues and solutions.
- [**FAQ**](https://www.geminicli.com/docs/resources/faq) - Frequently asked
questions.
- Use `/bug` command to report issues directly from the CLI.
### Using MCP Servers
@@ -344,8 +349,9 @@ custom tools:
> @database Run a query to find inactive users
```
See the [MCP Server Integration guide](./docs/tools/mcp-server.md) for setup
instructions.
See the
[MCP Server Integration guide](https://www.geminicli.com/docs/tools/mcp-server)
for setup instructions.
## 🤝 Contributing
@@ -366,7 +372,8 @@ for planned features and priorities.
## 📖 Resources
- **[Official Roadmap](./ROADMAP.md)** - See what's coming next.
- **[Changelog](./docs/changelogs/index.md)** - See recent notable updates.
- **[Changelog](https://www.geminicli.com/docs/changelogs)** - See recent
notable updates.
- **[NPM Package](https://www.npmjs.com/package/@google/gemini-cli)** - Package
registry.
- **[GitHub Issues](https://github.com/google-gemini/gemini-cli/issues)** -
@@ -376,13 +383,14 @@ for planned features and priorities.
### Uninstall
See the [Uninstall Guide](./docs/resources/uninstall.md) for removal
instructions.
See the [Uninstall Guide](https://www.geminicli.com/docs/resources/uninstall)
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](https://www.geminicli.com/docs/resources/tos-privacy)
- **Security**: [Security Policy](SECURITY.md)
---
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+70
View File
@@ -18,6 +18,76 @@ on GitHub.
| [Preview](preview.md) | Experimental features ready for early feedback. |
| [Stable](latest.md) | Stable, recommended for general use. |
## Announcements: v0.37.0 - 2026-04-08
- **Dynamic Sandbox Expansion:** Implemented dynamic sandbox expansion and
worktree support for Linux and Windows, improving developer workflows in
isolated environments
([#23692](https://github.com/google-gemini/gemini-cli/pull/23692) by @galz10,
[#23691](https://github.com/google-gemini/gemini-cli/pull/23691) by
@scidomino).
- **Chapters Narrative Flow:** Introduced tool-based topic grouping ("Chapters")
to provide better session structure and narrative continuity
([#23150](https://github.com/google-gemini/gemini-cli/pull/23150) by
@Abhijit-2592,
[#24079](https://github.com/google-gemini/gemini-cli/pull/24079) by
@gundermanc).
- **Advanced Browser Capabilities:** Enhanced the browser agent with persistent
sessions and dynamic tool discovery
([#21306](https://github.com/google-gemini/gemini-cli/pull/21306) by
@kunal-10-cloud,
[#23805](https://github.com/google-gemini/gemini-cli/pull/23805) by
@cynthialong0-0).
## Announcements: v0.36.0 - 2026-04-01
- **Multi-Registry Architecture and Sandboxing:** Introduced a multi-registry
architecture and implemented native macOS Seatbelt and Windows sandboxing for
enhanced subagent security
([#22712](https://github.com/google-gemini/gemini-cli/pull/22712),
[#22718](https://github.com/google-gemini/gemini-cli/pull/22718) by @akh64bit,
[#22832](https://github.com/google-gemini/gemini-cli/pull/22832) by @ehedlund,
[#21807](https://github.com/google-gemini/gemini-cli/pull/21807) by
@mattKorwel).
- **Refreshed Composer UX:** Implemented a refreshed user experience for the
Composer layout and improved terminal interaction robustness
([#21212](https://github.com/google-gemini/gemini-cli/pull/21212),
[#23286](https://github.com/google-gemini/gemini-cli/pull/23286) by
@jwhelangoog).
- **Git Worktree Support:** Added native support for Git worktrees, allowing for
isolated parallel sessions
([#22973](https://github.com/google-gemini/gemini-cli/pull/22973),
[#23265](https://github.com/google-gemini/gemini-cli/pull/23265) by @jerop).
- **Subagent Context and Feedback:** Enhanced subagents with JIT context
injection and resilient tool rejection with contextual feedback
([#23032](https://github.com/google-gemini/gemini-cli/pull/23032),
[#22951](https://github.com/google-gemini/gemini-cli/pull/22951) by
@abhipatel12).
## Announcements: v0.35.0 - 2026-03-24
- **Customizable Keyboard Shortcuts:** Users can now customize their keyboard
shortcuts, including support for literal character keybindings and the
extended Kitty protocol
([#21945](https://github.com/google-gemini/gemini-cli/pull/21945),
[#21972](https://github.com/google-gemini/gemini-cli/pull/21972) by
@scidomino).
- **Vim Mode Improvements:** Added missing motions (X, ~, r, f/F/t/T) and
yank/paste support with the unnamed register
([#21932](https://github.com/google-gemini/gemini-cli/pull/21932),
[#22026](https://github.com/google-gemini/gemini-cli/pull/22026) by @aanari).
- **Tool Isolation and Sandboxing:** Introduced `SandboxManager` to isolate
process-spawning tools and added Linux bubblewrap/seccomp sandboxing support
([#21774](https://github.com/google-gemini/gemini-cli/pull/21774),
[#22231](https://github.com/google-gemini/gemini-cli/pull/22231) by @galz10,
[#22680](https://github.com/google-gemini/gemini-cli/pull/22680) by
@DavidAPierce).
- **JIT Context Discovery:** Implemented Just-In-Time context discovery for file
system tools to improve model performance and accuracy
([#22082](https://github.com/google-gemini/gemini-cli/pull/22082),
[#22736](https://github.com/google-gemini/gemini-cli/pull/22736) by
@SandyTao520).
## Announcements: v0.34.0 - 2026-03-17
- **Plan Mode Enabled by Default:** Plan Mode is now enabled by default to help
+400 -465
View File
@@ -1,6 +1,6 @@
# Latest stable release: v0.34.0
# Latest stable release: v0.37.0
Released: March 17, 2026
Released: April 08, 2026
For most users, our latest stable release is the recommended release. Install
the latest stable version with:
@@ -11,474 +11,409 @@ npm install -g @google/gemini-cli
## Highlights
- **Plan Mode Enabled by Default**: The comprehensive planning capability is now
enabled by default, allowing for better structured task management and
execution.
- **Enhanced Sandboxing Capabilities**: Added support for native gVisor (runsc)
sandboxing as well as experimental LXC container sandboxing to provide more
robust and isolated execution environments.
- **Improved Loop Detection & Recovery**: Implemented iterative loop detection
and model feedback mechanisms to prevent the CLI from getting stuck in
repetitive actions.
- **Customizable UI Elements**: You can now configure a custom footer using the
new `/footer` command, and enjoy standardized semantic focus colors for better
history visibility.
- **Extensive Subagent Updates**: Refinements across the tracker visualization
tools, background process logging, and broader fallback support for models in
tool execution scenarios.
- **Dynamic Sandbox Expansion:** Implemented dynamic sandbox expansion and
worktree support for both Linux and Windows, enhancing development flexibility
in restricted environments.
- **Tool-Based Topic Grouping (Chapters):** Introduced "Chapters" to logically
group agent interactions based on tool usage and intent, providing a clearer
narrative flow in long sessions.
- **Enhanced Browser Agent:** Added persistent session management, dynamic
read-only tool discovery, and sandbox-aware initialization for the browser
agent.
- **Security & Permission Hardening:** Implemented secret visibility lockdown
for environment files and integrated integrity controls for Windows
sandboxing.
## What's Changed
- feat(cli): add chat resume footer on session quit by @lordshashank in
[#20667](https://github.com/google-gemini/gemini-cli/pull/20667)
- Support bold and other styles in svg snapshots by @jacob314 in
[#20937](https://github.com/google-gemini/gemini-cli/pull/20937)
- fix(core): increase A2A agent timeout to 30 minutes by @adamfweidman in
[#21028](https://github.com/google-gemini/gemini-cli/pull/21028)
- Cleanup old branches. by @jacob314 in
[#19354](https://github.com/google-gemini/gemini-cli/pull/19354)
- chore(release): bump version to 0.34.0-nightly.20260303.34f0c1538 by
@gemini-cli-robot in
[#21034](https://github.com/google-gemini/gemini-cli/pull/21034)
- feat(ui): standardize semantic focus colors and enhance history visibility by
@keithguerin in
[#20745](https://github.com/google-gemini/gemini-cli/pull/20745)
- fix: merge duplicate imports in packages/core (3/4) by @Nixxx19 in
[#20928](https://github.com/google-gemini/gemini-cli/pull/20928)
- Add extra safety checks for proto pollution by @jacob314 in
[#20396](https://github.com/google-gemini/gemini-cli/pull/20396)
- feat(core): Add tracker CRUD tools & visualization by @anj-s in
[#19489](https://github.com/google-gemini/gemini-cli/pull/19489)
- Revert "fix(ui): persist expansion in AskUser dialog when navigating options"
by @jacob314 in
[#21042](https://github.com/google-gemini/gemini-cli/pull/21042)
- Changelog for v0.33.0-preview.0 by @gemini-cli-robot in
[#21030](https://github.com/google-gemini/gemini-cli/pull/21030)
- fix: model persistence for all scenarios by @sripasg in
[#21051](https://github.com/google-gemini/gemini-cli/pull/21051)
- chore/release: bump version to 0.34.0-nightly.20260304.28af4e127 by
@gemini-cli-robot in
[#21054](https://github.com/google-gemini/gemini-cli/pull/21054)
- Consistently guard restarts against concurrent auto updates by @scidomino in
[#21016](https://github.com/google-gemini/gemini-cli/pull/21016)
- Defensive coding to reduce the risk of Maximum update depth errors by
@jacob314 in [#20940](https://github.com/google-gemini/gemini-cli/pull/20940)
- fix(cli): Polish shell autocomplete rendering to be a little more shell native
feeling. by @jacob314 in
[#20931](https://github.com/google-gemini/gemini-cli/pull/20931)
- Docs: Update plan mode docs by @jkcinouye in
[#19682](https://github.com/google-gemini/gemini-cli/pull/19682)
- fix(mcp): Notifications/tools/list_changed support not working by @jacob314 in
[#21050](https://github.com/google-gemini/gemini-cli/pull/21050)
- fix(cli): register extension lifecycle events in DebugProfiler by
@fayerman-source in
[#20101](https://github.com/google-gemini/gemini-cli/pull/20101)
- chore(dev): update vscode settings for typescriptreact by @rohit-4321 in
[#19907](https://github.com/google-gemini/gemini-cli/pull/19907)
- fix(cli): enable multi-arch docker builds for sandbox by @ru-aish in
[#19821](https://github.com/google-gemini/gemini-cli/pull/19821)
- Changelog for v0.32.0 by @gemini-cli-robot in
[#21033](https://github.com/google-gemini/gemini-cli/pull/21033)
- Changelog for v0.33.0-preview.1 by @gemini-cli-robot in
[#21058](https://github.com/google-gemini/gemini-cli/pull/21058)
- feat(core): improve @scripts/copy_files.js autocomplete to prioritize
filenames by @sehoon38 in
[#21064](https://github.com/google-gemini/gemini-cli/pull/21064)
- feat(sandbox): add experimental LXC container sandbox support by @h30s in
[#20735](https://github.com/google-gemini/gemini-cli/pull/20735)
- feat(evals): add overall pass rate row to eval nightly summary table by
@gundermanc in
[#20905](https://github.com/google-gemini/gemini-cli/pull/20905)
- feat(telemetry): include language in telemetry and fix accepted lines
computation by @gundermanc in
[#21126](https://github.com/google-gemini/gemini-cli/pull/21126)
- Changelog for v0.32.1 by @gemini-cli-robot in
[#21055](https://github.com/google-gemini/gemini-cli/pull/21055)
- feat(core): add robustness tests, logging, and metrics for CodeAssistServer
SSE parsing by @yunaseoul in
[#21013](https://github.com/google-gemini/gemini-cli/pull/21013)
- feat: add issue assignee workflow by @kartikangiras in
[#21003](https://github.com/google-gemini/gemini-cli/pull/21003)
- fix: improve error message when OAuth succeeds but project ID is required by
@Nixxx19 in [#21070](https://github.com/google-gemini/gemini-cli/pull/21070)
- feat(loop-reduction): implement iterative loop detection and model feedback by
@aishaneeshah in
[#20763](https://github.com/google-gemini/gemini-cli/pull/20763)
- chore(github): require prompt approvers for agent prompt files by @gundermanc
in [#20896](https://github.com/google-gemini/gemini-cli/pull/20896)
- Docs: Create tools reference by @jkcinouye in
[#19470](https://github.com/google-gemini/gemini-cli/pull/19470)
- fix(core, a2a-server): prevent hang during OAuth in non-interactive sessions
by @spencer426 in
[#21045](https://github.com/google-gemini/gemini-cli/pull/21045)
- chore(cli): enable deprecated settings removal by default by @yashodipmore in
[#20682](https://github.com/google-gemini/gemini-cli/pull/20682)
- feat(core): Disable fast ack helper for hints. by @joshualitt in
[#21011](https://github.com/google-gemini/gemini-cli/pull/21011)
- fix(ui): suppress redundant failure note when tool error note is shown by
@NTaylorMullen in
[#21078](https://github.com/google-gemini/gemini-cli/pull/21078)
- docs: document planning workflows with Conductor example by @jerop in
[#21166](https://github.com/google-gemini/gemini-cli/pull/21166)
- feat(release): ship esbuild bundle in npm package by @genneth in
[#19171](https://github.com/google-gemini/gemini-cli/pull/19171)
- fix(extensions): preserve symlinks in extension source path while enforcing
folder trust by @galz10 in
[#20867](https://github.com/google-gemini/gemini-cli/pull/20867)
- fix(cli): defer tool exclusions to policy engine in non-interactive mode by
@EricRahm in [#20639](https://github.com/google-gemini/gemini-cli/pull/20639)
- fix(ui): removed double padding on rendered content by @devr0306 in
[#21029](https://github.com/google-gemini/gemini-cli/pull/21029)
- fix(core): truncate excessively long lines in grep search output by
@gundermanc in
[#21147](https://github.com/google-gemini/gemini-cli/pull/21147)
- feat: add custom footer configuration via `/footer` by @jackwotherspoon in
[#19001](https://github.com/google-gemini/gemini-cli/pull/19001)
- perf(core): fix OOM crash in long-running sessions by @WizardsForgeGames in
[#19608](https://github.com/google-gemini/gemini-cli/pull/19608)
- refactor(cli): categorize built-in themes into dark/ and light/ directories by
@JayadityaGit in
[#18634](https://github.com/google-gemini/gemini-cli/pull/18634)
- fix(core): explicitly allow codebase_investigator and cli_help in read-only
mode by @Adib234 in
[#21157](https://github.com/google-gemini/gemini-cli/pull/21157)
- test: add browser agent integration tests by @kunal-10-cloud in
[#21151](https://github.com/google-gemini/gemini-cli/pull/21151)
- fix(cli): fix enabling kitty codes on Windows Terminal by @scidomino in
[#21136](https://github.com/google-gemini/gemini-cli/pull/21136)
- refactor(core): extract shared OAuth flow primitives from MCPOAuthProvider by
@SandyTao520 in
[#20895](https://github.com/google-gemini/gemini-cli/pull/20895)
- fix(ui): add partial output to cancelled shell UI by @devr0306 in
[#21178](https://github.com/google-gemini/gemini-cli/pull/21178)
- fix(cli): replace hardcoded keybinding strings with dynamic formatters by
@scidomino in [#21159](https://github.com/google-gemini/gemini-cli/pull/21159)
- DOCS: Update quota and pricing page by @g-samroberts in
[#21194](https://github.com/google-gemini/gemini-cli/pull/21194)
- feat(telemetry): implement Clearcut logging for startup statistics by
@yunaseoul in [#21172](https://github.com/google-gemini/gemini-cli/pull/21172)
- feat(triage): add area/documentation to issue triage by @g-samroberts in
[#21222](https://github.com/google-gemini/gemini-cli/pull/21222)
- Fix so shell calls are formatted by @jacob314 in
[#21237](https://github.com/google-gemini/gemini-cli/pull/21237)
- feat(cli): add native gVisor (runsc) sandboxing support by @Zheyuan-Lin in
[#21062](https://github.com/google-gemini/gemini-cli/pull/21062)
- docs: use absolute paths for internal links in plan-mode.md by @jerop in
[#21299](https://github.com/google-gemini/gemini-cli/pull/21299)
- fix(core): prevent unhandled AbortError crash during stream loop detection by
@7hokerz in [#21123](https://github.com/google-gemini/gemini-cli/pull/21123)
- fix:reorder env var redaction checks to scan values first by @kartikangiras in
[#21059](https://github.com/google-gemini/gemini-cli/pull/21059)
- fix(acp): rename --experimental-acp to --acp & remove Zed-specific refrences
by @skeshive in
[#21171](https://github.com/google-gemini/gemini-cli/pull/21171)
- feat(core): fallback to 2.5 models with no access for toolcalls by @sehoon38
in [#21283](https://github.com/google-gemini/gemini-cli/pull/21283)
- test(core): improve testing for API request/response parsing by @sehoon38 in
[#21227](https://github.com/google-gemini/gemini-cli/pull/21227)
- docs(links): update docs-writer skill and fix broken link by @g-samroberts in
[#21314](https://github.com/google-gemini/gemini-cli/pull/21314)
- Fix code colorizer ansi escape bug. by @jacob314 in
[#21321](https://github.com/google-gemini/gemini-cli/pull/21321)
- remove wildcard behavior on keybindings by @scidomino in
[#21315](https://github.com/google-gemini/gemini-cli/pull/21315)
- feat(acp): Add support for AI Gateway auth by @skeshive in
[#21305](https://github.com/google-gemini/gemini-cli/pull/21305)
- fix(theme): improve theme color contrast for macOS Terminal.app by @clocky in
[#21175](https://github.com/google-gemini/gemini-cli/pull/21175)
- feat (core): Implement tracker related SI changes by @anj-s in
[#19964](https://github.com/google-gemini/gemini-cli/pull/19964)
- Changelog for v0.33.0-preview.2 by @gemini-cli-robot in
[#21333](https://github.com/google-gemini/gemini-cli/pull/21333)
- Changelog for v0.33.0-preview.3 by @gemini-cli-robot in
[#21347](https://github.com/google-gemini/gemini-cli/pull/21347)
- docs: format release times as HH:MM UTC by @pavan-sh in
[#20726](https://github.com/google-gemini/gemini-cli/pull/20726)
- fix(cli): implement --all flag for extensions uninstall by @sehoon38 in
[#21319](https://github.com/google-gemini/gemini-cli/pull/21319)
- docs: fix incorrect relative links to command reference by @kanywst in
[#20964](https://github.com/google-gemini/gemini-cli/pull/20964)
- documentiong ensures ripgrep by @Jatin24062005 in
[#21298](https://github.com/google-gemini/gemini-cli/pull/21298)
- fix(core): handle AbortError thrown during processTurn by @MumuTW in
[#21296](https://github.com/google-gemini/gemini-cli/pull/21296)
- docs(cli): clarify ! command output visibility in shell commands tutorial by
@MohammedADev in
[#21041](https://github.com/google-gemini/gemini-cli/pull/21041)
- fix: logic for task tracker strategy and remove tracker tools by @anj-s in
[#21355](https://github.com/google-gemini/gemini-cli/pull/21355)
- fix(partUtils): display media type and size for inline data parts by @Aboudjem
in [#21358](https://github.com/google-gemini/gemini-cli/pull/21358)
- Fix(accessibility): add screen reader support to RewindViewer by @Famous077 in
[#20750](https://github.com/google-gemini/gemini-cli/pull/20750)
- fix(hooks): propagate stopHookActive in AfterAgent retry path (#20426) by
@Aarchi-07 in [#20439](https://github.com/google-gemini/gemini-cli/pull/20439)
- fix(core): deduplicate GEMINI.md files by device/inode on case-insensitive
filesystems (#19904) by @Nixxx19 in
[#19915](https://github.com/google-gemini/gemini-cli/pull/19915)
- feat(core): add concurrency safety guidance for subagent delegation (#17753)
by @abhipatel12 in
[#21278](https://github.com/google-gemini/gemini-cli/pull/21278)
- feat(ui): dynamically generate all keybinding hints by @scidomino in
[#21346](https://github.com/google-gemini/gemini-cli/pull/21346)
- feat(core): implement unified KeychainService and migrate token storage by
@ehedlund in [#21344](https://github.com/google-gemini/gemini-cli/pull/21344)
- fix(cli): gracefully handle --resume when no sessions exist by @SandyTao520 in
[#21429](https://github.com/google-gemini/gemini-cli/pull/21429)
- fix(plan): keep approved plan during chat compression by @ruomengz in
[#21284](https://github.com/google-gemini/gemini-cli/pull/21284)
- feat(core): implement generic CacheService and optimize setupUser by @sehoon38
in [#21374](https://github.com/google-gemini/gemini-cli/pull/21374)
- Update quota and pricing documentation with subscription tiers by @srithreepo
in [#21351](https://github.com/google-gemini/gemini-cli/pull/21351)
- fix(core): append correct OTLP paths for HTTP exporters by
@sebastien-prudhomme in
[#16836](https://github.com/google-gemini/gemini-cli/pull/16836)
- Changelog for v0.33.0-preview.4 by @gemini-cli-robot in
[#21354](https://github.com/google-gemini/gemini-cli/pull/21354)
- feat(cli): implement dot-prefixing for slash command conflicts by @ehedlund in
[#20979](https://github.com/google-gemini/gemini-cli/pull/20979)
- refactor(core): standardize MCP tool naming to mcp\_ FQN format by
@abhipatel12 in
[#21425](https://github.com/google-gemini/gemini-cli/pull/21425)
- feat(cli): hide gemma settings from display and mark as experimental by
@abhipatel12 in
[#21471](https://github.com/google-gemini/gemini-cli/pull/21471)
- feat(skills): refine string-reviewer guidelines and description by @clocky in
[#20368](https://github.com/google-gemini/gemini-cli/pull/20368)
- fix(core): whitelist TERM and COLORTERM in environment sanitization by
@deadsmash07 in
[#20514](https://github.com/google-gemini/gemini-cli/pull/20514)
- fix(billing): fix overage strategy lifecycle and settings integration by
@gsquared94 in
[#21236](https://github.com/google-gemini/gemini-cli/pull/21236)
- fix: expand paste placeholders in TextInput on submit by @Jefftree in
[#19946](https://github.com/google-gemini/gemini-cli/pull/19946)
- fix(core): add in-memory cache to ChatRecordingService to prevent OOM by
@SandyTao520 in
[#21502](https://github.com/google-gemini/gemini-cli/pull/21502)
- feat(cli): overhaul thinking UI by @keithguerin in
[#18725](https://github.com/google-gemini/gemini-cli/pull/18725)
- fix(ui): unify Ctrl+O expansion hint experience across buffer modes by
@jwhelangoog in
[#21474](https://github.com/google-gemini/gemini-cli/pull/21474)
- fix(cli): correct shell height reporting by @jacob314 in
[#21492](https://github.com/google-gemini/gemini-cli/pull/21492)
- Make test suite pass when the GEMINI_SYSTEM_MD env variable or
GEMINI_WRITE_SYSTEM_MD variable happens to be set locally/ by @jacob314 in
[#21480](https://github.com/google-gemini/gemini-cli/pull/21480)
- Disallow underspecified types by @gundermanc in
[#21485](https://github.com/google-gemini/gemini-cli/pull/21485)
- refactor(cli): standardize on 'reload' verb for all components by @keithguerin
in [#20654](https://github.com/google-gemini/gemini-cli/pull/20654)
- feat(cli): Invert quota language to 'percent used' by @keithguerin in
[#20100](https://github.com/google-gemini/gemini-cli/pull/20100)
- Docs: Add documentation for notifications (experimental)(macOS) by @jkcinouye
in [#21163](https://github.com/google-gemini/gemini-cli/pull/21163)
- Code review comments as a pr by @jacob314 in
[#21209](https://github.com/google-gemini/gemini-cli/pull/21209)
- feat(cli): unify /chat and /resume command UX by @LyalinDotCom in
[#20256](https://github.com/google-gemini/gemini-cli/pull/20256)
- docs: fix typo 'allowslisted' -> 'allowlisted' in mcp-server.md by
@Gyanranjan-Priyam in
[#21665](https://github.com/google-gemini/gemini-cli/pull/21665)
- fix(core): display actual graph output in tracker_visualize tool by @anj-s in
[#21455](https://github.com/google-gemini/gemini-cli/pull/21455)
- fix(core): sanitize SSE-corrupted JSON and domain strings in error
classification by @gsquared94 in
[#21702](https://github.com/google-gemini/gemini-cli/pull/21702)
- Docs: Make documentation links relative by @diodesign in
[#21490](https://github.com/google-gemini/gemini-cli/pull/21490)
- feat(cli): expose /tools desc as explicit subcommand for discoverability by
@aworki in [#21241](https://github.com/google-gemini/gemini-cli/pull/21241)
- feat(cli): add /compact alias for /compress command by @jackwotherspoon in
[#21711](https://github.com/google-gemini/gemini-cli/pull/21711)
- feat(plan): enable Plan Mode by default by @jerop in
[#21713](https://github.com/google-gemini/gemini-cli/pull/21713)
- feat(core): Introduce `AgentLoopContext`. by @joshualitt in
[#21198](https://github.com/google-gemini/gemini-cli/pull/21198)
- fix(core): resolve symlinks for non-existent paths during validation by
@Adib234 in [#21487](https://github.com/google-gemini/gemini-cli/pull/21487)
- docs: document tool exclusion from memory via deny policy by @Abhijit-2592 in
[#21428](https://github.com/google-gemini/gemini-cli/pull/21428)
- perf(core): cache loadApiKey to reduce redundant keychain access by @sehoon38
in [#21520](https://github.com/google-gemini/gemini-cli/pull/21520)
- feat(cli): implement /upgrade command by @sehoon38 in
[#21511](https://github.com/google-gemini/gemini-cli/pull/21511)
- Feat/browser agent progress emission by @kunal-10-cloud in
[#21218](https://github.com/google-gemini/gemini-cli/pull/21218)
- fix(settings): display objects as JSON instead of [object Object] by
@Zheyuan-Lin in
[#21458](https://github.com/google-gemini/gemini-cli/pull/21458)
- Unmarshall update by @DavidAPierce in
[#21721](https://github.com/google-gemini/gemini-cli/pull/21721)
- Update mcp's list function to check for disablement. by @DavidAPierce in
[#21148](https://github.com/google-gemini/gemini-cli/pull/21148)
- robustness(core): static checks to validate history is immutable by @jacob314
in [#21228](https://github.com/google-gemini/gemini-cli/pull/21228)
- refactor(cli): better react patterns for BaseSettingsDialog by @psinha40898 in
[#21206](https://github.com/google-gemini/gemini-cli/pull/21206)
- feat(security): implement robust IP validation and safeFetch foundation by
@alisa-alisa in
[#21401](https://github.com/google-gemini/gemini-cli/pull/21401)
- feat(core): improve subagent result display by @joshualitt in
[#20378](https://github.com/google-gemini/gemini-cli/pull/20378)
- docs: fix broken markdown syntax and anchor links in /tools by @campox747 in
[#20902](https://github.com/google-gemini/gemini-cli/pull/20902)
- feat(policy): support subagent-specific policies in TOML by @akh64bit in
[#21431](https://github.com/google-gemini/gemini-cli/pull/21431)
- Add script to speed up reviewing PRs adding a worktree. by @jacob314 in
[#21748](https://github.com/google-gemini/gemini-cli/pull/21748)
- fix(core): prevent infinite recursion in symlink resolution by @Adib234 in
[#21750](https://github.com/google-gemini/gemini-cli/pull/21750)
- fix(docs): fix headless mode docs by @ame2en in
[#21287](https://github.com/google-gemini/gemini-cli/pull/21287)
- feat/redesign header compact by @jacob314 in
[#20922](https://github.com/google-gemini/gemini-cli/pull/20922)
- refactor: migrate to useKeyMatchers hook by @scidomino in
[#21753](https://github.com/google-gemini/gemini-cli/pull/21753)
- perf(cli): cache loadSettings to reduce redundant disk I/O at startup by
@sehoon38 in [#21521](https://github.com/google-gemini/gemini-cli/pull/21521)
- fix(core): resolve Windows line ending and path separation bugs across CLI by
@muhammadusman586 in
[#21068](https://github.com/google-gemini/gemini-cli/pull/21068)
- docs: fix heading formatting in commands.md and phrasing in tools-api.md by
@campox747 in [#20679](https://github.com/google-gemini/gemini-cli/pull/20679)
- refactor(ui): unify keybinding infrastructure and support string
initialization by @scidomino in
[#21776](https://github.com/google-gemini/gemini-cli/pull/21776)
- Add support for updating extension sources and names by @chrstnb in
[#21715](https://github.com/google-gemini/gemini-cli/pull/21715)
- fix(core): handle GUI editor non-zero exit codes gracefully by @reyyanxahmed
in [#20376](https://github.com/google-gemini/gemini-cli/pull/20376)
- fix(core): destroy PTY on kill() and exception to prevent fd leak by @nbardy
in [#21693](https://github.com/google-gemini/gemini-cli/pull/21693)
- fix(docs): update theme screenshots and add missing themes by @ashmod in
[#20689](https://github.com/google-gemini/gemini-cli/pull/20689)
- refactor(cli): rename 'return' key to 'enter' internally by @scidomino in
[#21796](https://github.com/google-gemini/gemini-cli/pull/21796)
- build(release): restrict npm bundling to non-stable tags by @sehoon38 in
[#21821](https://github.com/google-gemini/gemini-cli/pull/21821)
- fix(core): override toolRegistry property for sub-agent schedulers by
@gsquared94 in
[#21766](https://github.com/google-gemini/gemini-cli/pull/21766)
- fix(cli): make footer items equally spaced by @jacob314 in
[#21843](https://github.com/google-gemini/gemini-cli/pull/21843)
- docs: clarify global policy rules application in plan mode by @jerop in
[#21864](https://github.com/google-gemini/gemini-cli/pull/21864)
- fix(core): ensure correct flash model steering in plan mode implementation
phase by @jerop in
[#21871](https://github.com/google-gemini/gemini-cli/pull/21871)
- fix(core): update @a2a-js/sdk to 0.3.11 by @adamfweidman in
[#21875](https://github.com/google-gemini/gemini-cli/pull/21875)
- refactor(core): improve API response error logging when retry by @yunaseoul in
[#21784](https://github.com/google-gemini/gemini-cli/pull/21784)
- fix(ui): handle headless execution in credits and upgrade dialogs by
@gsquared94 in
[#21850](https://github.com/google-gemini/gemini-cli/pull/21850)
- fix(core): treat retryable errors with >5 min delay as terminal quota errors
by @gsquared94 in
[#21881](https://github.com/google-gemini/gemini-cli/pull/21881)
- feat(telemetry): add specific PR, issue, and custom tracking IDs for GitHub
Actions by @cocosheng-g in
[#21129](https://github.com/google-gemini/gemini-cli/pull/21129)
- feat(core): add OAuth2 Authorization Code auth provider for A2A agents by
@SandyTao520 in
[#21496](https://github.com/google-gemini/gemini-cli/pull/21496)
- feat(cli): give visibility to /tools list command in the TUI and follow the
subcommand pattern of other commands by @JayadityaGit in
[#21213](https://github.com/google-gemini/gemini-cli/pull/21213)
- Handle dirty worktrees better and warn about running scripts/review.sh on
untrusted code. by @jacob314 in
[#21791](https://github.com/google-gemini/gemini-cli/pull/21791)
- feat(policy): support auto-add to policy by default and scoped persistence by
@spencer426 in
[#20361](https://github.com/google-gemini/gemini-cli/pull/20361)
- fix(core): handle AbortError when ESC cancels tool execution by @PrasannaPal21
in [#20863](https://github.com/google-gemini/gemini-cli/pull/20863)
- fix(release): Improve Patch Release Workflow Comments: Clearer Approval
Guidance by @jerop in
[#21894](https://github.com/google-gemini/gemini-cli/pull/21894)
- docs: clarify telemetry setup and comprehensive data map by @jerop in
[#21879](https://github.com/google-gemini/gemini-cli/pull/21879)
- feat(core): add per-model token usage to stream-json output by @yongruilin in
[#21839](https://github.com/google-gemini/gemini-cli/pull/21839)
- docs: remove experimental badge from plan mode in sidebar by @jerop in
[#21906](https://github.com/google-gemini/gemini-cli/pull/21906)
- fix(cli): prevent race condition in loop detection retry by @skyvanguard in
[#17916](https://github.com/google-gemini/gemini-cli/pull/17916)
- Add behavioral evals for tracker by @anj-s in
[#20069](https://github.com/google-gemini/gemini-cli/pull/20069)
- fix(auth): update terminology to 'sign in' and 'sign out' by @clocky in
[#20892](https://github.com/google-gemini/gemini-cli/pull/20892)
- docs(mcp): standardize mcp tool fqn documentation by @abhipatel12 in
[#21664](https://github.com/google-gemini/gemini-cli/pull/21664)
- fix(ui): prevent empty tool-group border stubs after filtering by @Aaxhirrr in
[#21852](https://github.com/google-gemini/gemini-cli/pull/21852)
- make command names consistent by @scidomino in
[#21907](https://github.com/google-gemini/gemini-cli/pull/21907)
- refactor: remove agent_card_requires_auth config flag by @adamfweidman in
[#21914](https://github.com/google-gemini/gemini-cli/pull/21914)
- feat(a2a): implement standardized normalization and streaming reassembly by
@alisa-alisa in
[#21402](https://github.com/google-gemini/gemini-cli/pull/21402)
- feat(cli): enable skill activation via slash commands by @NTaylorMullen in
[#21758](https://github.com/google-gemini/gemini-cli/pull/21758)
- docs(cli): mention per-model token usage in stream-json result event by
@yongruilin in
[#21908](https://github.com/google-gemini/gemini-cli/pull/21908)
- fix(plan): prevent plan truncation in approval dialog by supporting
unconstrained heights by @Adib234 in
[#21037](https://github.com/google-gemini/gemini-cli/pull/21037)
- feat(a2a): switch from callback-based to event-driven tool scheduler by
@cocosheng-g in
[#21467](https://github.com/google-gemini/gemini-cli/pull/21467)
- feat(voice): implement speech-friendly response formatter by @ayush31010 in
[#20989](https://github.com/google-gemini/gemini-cli/pull/20989)
- feat: add pulsating blue border automation overlay to browser agent by
@kunal-10-cloud in
[#21173](https://github.com/google-gemini/gemini-cli/pull/21173)
- Add extensionRegistryURI setting to change where the registry is read from by
- feat(evals): centralize test agents into test-utils for reuse by @Samee24 in
[#23616](https://github.com/google-gemini/gemini-cli/pull/23616)
- revert: chore(config): disable agents by default by @abhipatel12 in
[#23672](https://github.com/google-gemini/gemini-cli/pull/23672)
- fix(plan): update telemetry attribute keys and add timestamp by @Adib234 in
[#23685](https://github.com/google-gemini/gemini-cli/pull/23685)
- fix(core): prevent premature MCP discovery completion by @jackwotherspoon in
[#23637](https://github.com/google-gemini/gemini-cli/pull/23637)
- feat(browser): add maxActionsPerTask for browser agent setting by
@cynthialong0-0 in
[#23216](https://github.com/google-gemini/gemini-cli/pull/23216)
- fix(core): improve agent loader error formatting for empty paths by
@adamfweidman in
[#23690](https://github.com/google-gemini/gemini-cli/pull/23690)
- fix(cli): only show updating spinner when auto-update is in progress by
@scidomino in [#23709](https://github.com/google-gemini/gemini-cli/pull/23709)
- Refine onboarding metrics to log the duration explicitly and use the tier
name. by @yunaseoul in
[#23678](https://github.com/google-gemini/gemini-cli/pull/23678)
- chore(tools): add toJSON to tools and invocations to reduce logging verbosity
by @alisa-alisa in
[#22899](https://github.com/google-gemini/gemini-cli/pull/22899)
- fix(cli): stabilize copy mode to prevent flickering and cursor resets by
@mattKorwel in
[#22584](https://github.com/google-gemini/gemini-cli/pull/22584)
- fix(test): move flaky ctrl-c-exit test to non-blocking suite by @mattKorwel in
[#23732](https://github.com/google-gemini/gemini-cli/pull/23732)
- feat(skills): add ci skill for automated failure replication by @mattKorwel in
[#23720](https://github.com/google-gemini/gemini-cli/pull/23720)
- feat(sandbox): implement forbiddenPaths for OS-specific sandbox managers by
@ehedlund in [#23282](https://github.com/google-gemini/gemini-cli/pull/23282)
- fix(core): conditionally expose additional_permissions in shell tool by
@galz10 in [#23729](https://github.com/google-gemini/gemini-cli/pull/23729)
- refactor(core): standardize OS-specific sandbox tests and extract linux helper
methods by @ehedlund in
[#23715](https://github.com/google-gemini/gemini-cli/pull/23715)
- format recently added script by @scidomino in
[#23739](https://github.com/google-gemini/gemini-cli/pull/23739)
- fix(ui): prevent over-eager slash subcommand completion by @keithguerin in
[#20136](https://github.com/google-gemini/gemini-cli/pull/20136)
- Fix dynamic model routing for gemini 3.1 pro to customtools model by
@kevinjwang1 in
[#20463](https://github.com/google-gemini/gemini-cli/pull/20463)
- fix: patch gaxios v7 Array.toString() stream corruption by @gsquared94 in
[#21884](https://github.com/google-gemini/gemini-cli/pull/21884)
- fix: prevent hangs in non-interactive mode and improve agent guidance by
@cocosheng-g in
[#20893](https://github.com/google-gemini/gemini-cli/pull/20893)
- Add ExtensionDetails dialog and support install by @chrstnb in
[#20845](https://github.com/google-gemini/gemini-cli/pull/20845)
- chore/release: bump version to 0.34.0-nightly.20260310.4653b126f by
[#23641](https://github.com/google-gemini/gemini-cli/pull/23641)
- feat(core): support inline agentCardJson for remote agents by @adamfweidman in
[#23743](https://github.com/google-gemini/gemini-cli/pull/23743)
- fix(cli): skip console log/info in headless mode by @cynthialong0-0 in
[#22739](https://github.com/google-gemini/gemini-cli/pull/22739)
- test(core): install bubblewrap on Linux CI for sandbox integration tests by
@ehedlund in [#23583](https://github.com/google-gemini/gemini-cli/pull/23583)
- docs(reference): split tools table into category sections by @sheikhlimon in
[#21516](https://github.com/google-gemini/gemini-cli/pull/21516)
- fix(browser): detect embedded URLs in query params to prevent allowedDomains
bypass by @tony-shi in
[#23225](https://github.com/google-gemini/gemini-cli/pull/23225)
- fix(browser): add proxy bypass constraint to domain restriction system prompt
by @tony-shi in
[#23229](https://github.com/google-gemini/gemini-cli/pull/23229)
- fix(policy): relax write_file argsPattern in plan mode to allow paths without
session ID by @Adib234 in
[#23695](https://github.com/google-gemini/gemini-cli/pull/23695)
- docs: fix grammar in CONTRIBUTING and numbering in sandbox docs by
@splint-disk-8i in
[#23448](https://github.com/google-gemini/gemini-cli/pull/23448)
- fix(acp): allow attachments by adding a permission prompt by @sripasg in
[#23680](https://github.com/google-gemini/gemini-cli/pull/23680)
- fix(core): thread AbortSignal to chat compression requests (#20405) by
@SH20RAJ in [#20778](https://github.com/google-gemini/gemini-cli/pull/20778)
- feat(core): implement Windows sandbox dynamic expansion Phase 1 and 2.1 by
@scidomino in [#23691](https://github.com/google-gemini/gemini-cli/pull/23691)
- Add note about root privileges in sandbox docs by @diodesign in
[#23314](https://github.com/google-gemini/gemini-cli/pull/23314)
- docs(core): document agent_card_json string literal options for remote agents
by @adamfweidman in
[#23797](https://github.com/google-gemini/gemini-cli/pull/23797)
- fix(cli): resolve TTY hang on headless environments by unconditionally
resuming process.stdin before React Ink launch by @cocosheng-g in
[#23673](https://github.com/google-gemini/gemini-cli/pull/23673)
- fix(ui): cleanup estimated string length hacks in composer by @keithguerin in
[#23694](https://github.com/google-gemini/gemini-cli/pull/23694)
- feat(browser): dynamically discover read-only tools by @cynthialong0-0 in
[#23805](https://github.com/google-gemini/gemini-cli/pull/23805)
- docs: clarify policy requirement for `general.plan.directory` in settings
schema by @jerop in
[#23784](https://github.com/google-gemini/gemini-cli/pull/23784)
- Revert "perf(cli): optimize --version startup time (#23671)" by @scidomino in
[#23812](https://github.com/google-gemini/gemini-cli/pull/23812)
- don't silence errors from wombat by @scidomino in
[#23822](https://github.com/google-gemini/gemini-cli/pull/23822)
- fix(ui): prevent escape key from cancelling requests in shell mode by
@PrasannaPal21 in
[#21245](https://github.com/google-gemini/gemini-cli/pull/21245)
- Changelog for v0.36.0-preview.0 by @gemini-cli-robot in
[#23702](https://github.com/google-gemini/gemini-cli/pull/23702)
- feat(core,ui): Add experiment-gated support for gemini flash 3.1 lite by
@chrstnb in [#23794](https://github.com/google-gemini/gemini-cli/pull/23794)
- Changelog for v0.36.0-preview.3 by @gemini-cli-robot in
[#23827](https://github.com/google-gemini/gemini-cli/pull/23827)
- new linting check: github-actions-pinning by @alisa-alisa in
[#23808](https://github.com/google-gemini/gemini-cli/pull/23808)
- fix(cli): show helpful guidance when no skills are available by @Niralisj in
[#23785](https://github.com/google-gemini/gemini-cli/pull/23785)
- fix: Chat logs and errors handle tail tool calls correctly by @googlestrobe in
[#22460](https://github.com/google-gemini/gemini-cli/pull/22460)
- Don't try removing a tag from a non-existent release. by @scidomino in
[#23830](https://github.com/google-gemini/gemini-cli/pull/23830)
- fix(cli): allow ask question dialog to take full window height by @jacob314 in
[#23693](https://github.com/google-gemini/gemini-cli/pull/23693)
- fix(core): strip leading underscores from error types in telemetry by
@yunaseoul in [#23824](https://github.com/google-gemini/gemini-cli/pull/23824)
- Changelog for v0.35.0 by @gemini-cli-robot in
[#23819](https://github.com/google-gemini/gemini-cli/pull/23819)
- feat(evals): add reliability harvester and 500/503 retry support by
@alisa-alisa in
[#23626](https://github.com/google-gemini/gemini-cli/pull/23626)
- feat(sandbox): dynamic Linux sandbox expansion and worktree support by @galz10
in [#23692](https://github.com/google-gemini/gemini-cli/pull/23692)
- Merge examples of use into quickstart documentation by @diodesign in
[#23319](https://github.com/google-gemini/gemini-cli/pull/23319)
- fix(cli): prioritize primary name matches in slash command search by @sehoon38
in [#23850](https://github.com/google-gemini/gemini-cli/pull/23850)
- Changelog for v0.35.1 by @gemini-cli-robot in
[#23840](https://github.com/google-gemini/gemini-cli/pull/23840)
- fix(browser): keep input blocker active across navigations by @kunal-10-cloud
in [#22562](https://github.com/google-gemini/gemini-cli/pull/22562)
- feat(core): new skill to look for duplicated code while reviewing PRs by
@devr0306 in [#23704](https://github.com/google-gemini/gemini-cli/pull/23704)
- fix(core): replace hardcoded non-interactive ASK_USER denial with explicit
policy rules by @ruomengz in
[#23668](https://github.com/google-gemini/gemini-cli/pull/23668)
- fix(plan): after exiting plan mode switches model to a flash model by @Adib234
in [#23885](https://github.com/google-gemini/gemini-cli/pull/23885)
- feat(gcp): add development worker infrastructure by @mattKorwel in
[#23814](https://github.com/google-gemini/gemini-cli/pull/23814)
- fix(a2a-server): A2A server should execute ask policies in interactive mode by
@kschaab in [#23831](https://github.com/google-gemini/gemini-cli/pull/23831)
- feat(core): define TrajectoryProvider interface by @sehoon38 in
[#23050](https://github.com/google-gemini/gemini-cli/pull/23050)
- Docs: Update quotas and pricing by @jkcinouye in
[#23835](https://github.com/google-gemini/gemini-cli/pull/23835)
- fix(core): allow disabling environment variable redaction by @galz10 in
[#23927](https://github.com/google-gemini/gemini-cli/pull/23927)
- feat(cli): enable notifications cross-platform via terminal bell fallback by
@genneth in [#21618](https://github.com/google-gemini/gemini-cli/pull/21618)
- feat(sandbox): implement secret visibility lockdown for env files by
@DavidAPierce in
[#23712](https://github.com/google-gemini/gemini-cli/pull/23712)
- fix(core): remove shell outputChunks buffer caching to prevent memory bloat
and sanitize prompt input by @spencer426 in
[#23751](https://github.com/google-gemini/gemini-cli/pull/23751)
- feat(core): implement persistent browser session management by @kunal-10-cloud
in [#21306](https://github.com/google-gemini/gemini-cli/pull/21306)
- refactor(core): delegate sandbox denial parsing to SandboxManager by
@scidomino in [#23928](https://github.com/google-gemini/gemini-cli/pull/23928)
- dep(update) Update Ink version to 6.5.0 by @jacob314 in
[#23843](https://github.com/google-gemini/gemini-cli/pull/23843)
- Docs: Update 'docs-writer' skill for relative links by @jkcinouye in
[#21463](https://github.com/google-gemini/gemini-cli/pull/21463)
- Changelog for v0.36.0-preview.4 by @gemini-cli-robot in
[#23935](https://github.com/google-gemini/gemini-cli/pull/23935)
- fix(acp): Update allow approval policy flow for ACP clients to fix config
persistence and compatible with TUI by @sripasg in
[#23818](https://github.com/google-gemini/gemini-cli/pull/23818)
- Changelog for v0.35.2 by @gemini-cli-robot in
[#23960](https://github.com/google-gemini/gemini-cli/pull/23960)
- ACP integration documents by @g-samroberts in
[#22254](https://github.com/google-gemini/gemini-cli/pull/22254)
- fix(core): explicitly set error names to avoid bundling renaming issues by
@yunaseoul in [#23913](https://github.com/google-gemini/gemini-cli/pull/23913)
- feat(core): subagent isolation and cleanup hardening by @abhipatel12 in
[#23903](https://github.com/google-gemini/gemini-cli/pull/23903)
- disable extension-reload test by @scidomino in
[#24018](https://github.com/google-gemini/gemini-cli/pull/24018)
- feat(core): add forbiddenPaths to GlobalSandboxOptions and refactor
createSandboxManager by @ehedlund in
[#23936](https://github.com/google-gemini/gemini-cli/pull/23936)
- refactor(core): improve ignore resolution and fix directory-matching bug by
@ehedlund in [#23816](https://github.com/google-gemini/gemini-cli/pull/23816)
- revert(core): support custom base URL via env vars by @spencer426 in
[#23976](https://github.com/google-gemini/gemini-cli/pull/23976)
- Increase memory limited for eslint. by @jacob314 in
[#24022](https://github.com/google-gemini/gemini-cli/pull/24022)
- fix(acp): prevent crash on empty response in ACP mode by @sripasg in
[#23952](https://github.com/google-gemini/gemini-cli/pull/23952)
- feat(core): Land `AgentHistoryProvider`. by @joshualitt in
[#23978](https://github.com/google-gemini/gemini-cli/pull/23978)
- fix(core): switch to subshells for shell tool wrapping to fix heredocs and
edge cases by @abhipatel12 in
[#24024](https://github.com/google-gemini/gemini-cli/pull/24024)
- Debug command. by @jacob314 in
[#23851](https://github.com/google-gemini/gemini-cli/pull/23851)
- Changelog for v0.36.0-preview.5 by @gemini-cli-robot in
[#24046](https://github.com/google-gemini/gemini-cli/pull/24046)
- Fix test flakes by globally mocking ink-spinner by @jacob314 in
[#24044](https://github.com/google-gemini/gemini-cli/pull/24044)
- Enable network access in sandbox configuration by @galz10 in
[#24055](https://github.com/google-gemini/gemini-cli/pull/24055)
- feat(context): add configurable memoryBoundaryMarkers setting by @SandyTao520
in [#24020](https://github.com/google-gemini/gemini-cli/pull/24020)
- feat(core): implement windows sandbox expansion and denial detection by
@scidomino in [#24027](https://github.com/google-gemini/gemini-cli/pull/24027)
- fix(core): resolve ACP Operation Aborted Errors in grep_search by @ivanporty
in [#23821](https://github.com/google-gemini/gemini-cli/pull/23821)
- fix(hooks): prevent SessionEnd from firing twice in non-interactive mode by
@krishdef7 in [#22139](https://github.com/google-gemini/gemini-cli/pull/22139)
- Re-word intro to Gemini 3 page. by @g-samroberts in
[#24069](https://github.com/google-gemini/gemini-cli/pull/24069)
- fix(cli): resolve layout contention and flashing loop in StatusRow by
@keithguerin in
[#24065](https://github.com/google-gemini/gemini-cli/pull/24065)
- fix(sandbox): implement Windows Mandatory Integrity Control for GeminiSandbox
by @galz10 in [#24057](https://github.com/google-gemini/gemini-cli/pull/24057)
- feat(core): implement tool-based topic grouping (Chapters) by @Abhijit-2592 in
[#23150](https://github.com/google-gemini/gemini-cli/pull/23150)
- feat(cli): support 'tab to queue' for messages while generating by @gundermanc
in [#24052](https://github.com/google-gemini/gemini-cli/pull/24052)
- feat(core): agnostic background task UI with CompletionBehavior by
@adamfweidman in
[#22740](https://github.com/google-gemini/gemini-cli/pull/22740)
- UX for topic narration tool by @gundermanc in
[#24079](https://github.com/google-gemini/gemini-cli/pull/24079)
- fix: shellcheck warnings in scripts by @scidomino in
[#24035](https://github.com/google-gemini/gemini-cli/pull/24035)
- test(evals): add comprehensive subagent delegation evaluations by @abhipatel12
in [#24132](https://github.com/google-gemini/gemini-cli/pull/24132)
- fix(a2a-server): prioritize ADC before evaluating headless constraints for
auth initialization by @spencer426 in
[#23614](https://github.com/google-gemini/gemini-cli/pull/23614)
- Text can be added after /plan command by @rambleraptor in
[#22833](https://github.com/google-gemini/gemini-cli/pull/22833)
- fix(cli): resolve missing F12 logs via global console store by @scidomino in
[#24235](https://github.com/google-gemini/gemini-cli/pull/24235)
- fix broken tests by @scidomino in
[#24279](https://github.com/google-gemini/gemini-cli/pull/24279)
- fix(evals): add update_topic behavioral eval by @gundermanc in
[#24223](https://github.com/google-gemini/gemini-cli/pull/24223)
- feat(core): Unified Context Management and Tool Distillation. by @joshualitt
in [#24157](https://github.com/google-gemini/gemini-cli/pull/24157)
- Default enable narration for the team. by @gundermanc in
[#24224](https://github.com/google-gemini/gemini-cli/pull/24224)
- fix(core): ensure default agents provide tools and use model-specific schemas
by @abhipatel12 in
[#24268](https://github.com/google-gemini/gemini-cli/pull/24268)
- feat(cli): show Flash Lite Preview model regardless of user tier by @sehoon38
in [#23904](https://github.com/google-gemini/gemini-cli/pull/23904)
- feat(cli): implement compact tool output by @jwhelangoog in
[#20974](https://github.com/google-gemini/gemini-cli/pull/20974)
- Add security settings for tool sandboxing by @galz10 in
[#23923](https://github.com/google-gemini/gemini-cli/pull/23923)
- chore(test-utils): switch integration tests to use PREVIEW_GEMINI_MODEL by
@sehoon38 in [#24276](https://github.com/google-gemini/gemini-cli/pull/24276)
- feat(core): enable topic update narration for legacy models by @Abhijit-2592
in [#24241](https://github.com/google-gemini/gemini-cli/pull/24241)
- feat(core): add project-level memory scope to save_memory tool by @SandyTao520
in [#24161](https://github.com/google-gemini/gemini-cli/pull/24161)
- test(integration): fix plan mode write denial test false positive by @sehoon38
in [#24299](https://github.com/google-gemini/gemini-cli/pull/24299)
- feat(plan): support `Plan` mode in untrusted folders by @Adib234 in
[#17586](https://github.com/google-gemini/gemini-cli/pull/17586)
- fix(core): enable mid-stream retries for all models and re-enable compression
test by @sehoon38 in
[#24302](https://github.com/google-gemini/gemini-cli/pull/24302)
- Changelog for v0.36.0-preview.6 by @gemini-cli-robot in
[#24082](https://github.com/google-gemini/gemini-cli/pull/24082)
- Changelog for v0.35.3 by @gemini-cli-robot in
[#24083](https://github.com/google-gemini/gemini-cli/pull/24083)
- feat(cli): add auth info to footer by @sehoon38 in
[#24042](https://github.com/google-gemini/gemini-cli/pull/24042)
- fix(browser): reset action counter for each agent session and let it ignore
internal actions by @cynthialong0-0 in
[#24228](https://github.com/google-gemini/gemini-cli/pull/24228)
- feat(plan): promote planning feature to stable by @ruomengz in
[#24282](https://github.com/google-gemini/gemini-cli/pull/24282)
- fix(browser): terminate subagent immediately on domain restriction violations
by @gsquared94 in
[#24313](https://github.com/google-gemini/gemini-cli/pull/24313)
- feat(cli): add UI to update extensions by @ruomengz in
[#23682](https://github.com/google-gemini/gemini-cli/pull/23682)
- Fix(browser): terminate immediately for "browser is already running" error by
@cynthialong0-0 in
[#24233](https://github.com/google-gemini/gemini-cli/pull/24233)
- docs: Add 'plan' option to approval mode in CLI reference by @YifanRuan in
[#24134](https://github.com/google-gemini/gemini-cli/pull/24134)
- fix(core): batch macOS seatbelt rules into a profile file to prevent ARG_MAX
errors by @ehedlund in
[#24255](https://github.com/google-gemini/gemini-cli/pull/24255)
- fix(core): fix race condition between browser agent and main closing process
by @cynthialong0-0 in
[#24340](https://github.com/google-gemini/gemini-cli/pull/24340)
- perf(build): optimize build scripts for parallel execution and remove
redundant checks by @sehoon38 in
[#24307](https://github.com/google-gemini/gemini-cli/pull/24307)
- ci: install bubblewrap on Linux for release workflows by @ehedlund in
[#24347](https://github.com/google-gemini/gemini-cli/pull/24347)
- chore(release): allow bundling for all builds, including stable by @sehoon38
in [#24305](https://github.com/google-gemini/gemini-cli/pull/24305)
- Revert "Add security settings for tool sandboxing" by @jerop in
[#24357](https://github.com/google-gemini/gemini-cli/pull/24357)
- docs: update subagents docs to not be experimental by @abhipatel12 in
[#24343](https://github.com/google-gemini/gemini-cli/pull/24343)
- fix(core): implement **read and **write commands in sandbox managers by
@galz10 in [#24283](https://github.com/google-gemini/gemini-cli/pull/24283)
- don't try to remove tags in dry run by @scidomino in
[#24356](https://github.com/google-gemini/gemini-cli/pull/24356)
- fix(config): disable JIT context loading by default by @SandyTao520 in
[#24364](https://github.com/google-gemini/gemini-cli/pull/24364)
- test(sandbox): add integration test for dynamic permission expansion by
@galz10 in [#24359](https://github.com/google-gemini/gemini-cli/pull/24359)
- docs(policy): remove unsupported mcpName wildcard edge case by @abhipatel12 in
[#24133](https://github.com/google-gemini/gemini-cli/pull/24133)
- docs: fix broken GEMINI.md link in CONTRIBUTING.md by @Panchal-Tirth in
[#24182](https://github.com/google-gemini/gemini-cli/pull/24182)
- feat(core): infrastructure for event-driven subagent history by @abhipatel12
in [#23914](https://github.com/google-gemini/gemini-cli/pull/23914)
- fix(core): resolve Plan Mode deadlock during plan file creation due to sandbox
restrictions by @DavidAPierce in
[#24047](https://github.com/google-gemini/gemini-cli/pull/24047)
- fix(core): fix browser agent UX issues and improve E2E test reliability by
@gsquared94 in
[#24312](https://github.com/google-gemini/gemini-cli/pull/24312)
- fix(ui): wrap topic and intent fields in TopicMessage by @jwhelangoog in
[#24386](https://github.com/google-gemini/gemini-cli/pull/24386)
- refactor(core): Centralize context management logic into src/context by
@joshualitt in
[#24380](https://github.com/google-gemini/gemini-cli/pull/24380)
- fix(core): pin AuthType.GATEWAY to use Gemini 3.1 Pro/Flash Lite by default by
@sripasg in [#24375](https://github.com/google-gemini/gemini-cli/pull/24375)
- feat(ui): add Tokyo Night theme by @danrneal in
[#24054](https://github.com/google-gemini/gemini-cli/pull/24054)
- fix(cli): refactor test config loading and mock debugLogger in test-setup by
@mattKorwel in
[#24389](https://github.com/google-gemini/gemini-cli/pull/24389)
- Set memoryManager to false in settings.json by @mattKorwel in
[#24393](https://github.com/google-gemini/gemini-cli/pull/24393)
- ink 6.6.3 by @jacob314 in
[#24372](https://github.com/google-gemini/gemini-cli/pull/24372)
- fix(core): resolve subagent chat recording gaps and directory inheritance by
@abhipatel12 in
[#24368](https://github.com/google-gemini/gemini-cli/pull/24368)
- fix(cli): cap shell output at 10 MB to prevent RangeError crash by @ProthamD
in [#24168](https://github.com/google-gemini/gemini-cli/pull/24168)
- feat(plan): conditionally add enter/exit plan mode tools based on current mode
by @ruomengz in
[#24378](https://github.com/google-gemini/gemini-cli/pull/24378)
- feat(core): prioritize discussion before formal plan approval by @jerop in
[#24423](https://github.com/google-gemini/gemini-cli/pull/24423)
- fix(ui): add accelerated scrolling on alternate buffer mode by @devr0306 in
[#23940](https://github.com/google-gemini/gemini-cli/pull/23940)
- feat(core): populate sandbox forbidden paths with project ignore file contents
by @ehedlund in
[#24038](https://github.com/google-gemini/gemini-cli/pull/24038)
- fix(core): ensure blue border overlay and input blocker to act correctly
depending on browser agent activities by @cynthialong0-0 in
[#24385](https://github.com/google-gemini/gemini-cli/pull/24385)
- fix(ui): removed additional vertical padding for tables by @devr0306 in
[#24381](https://github.com/google-gemini/gemini-cli/pull/24381)
- fix(build): upload full bundle directory archive to GitHub releases by
@sehoon38 in [#24403](https://github.com/google-gemini/gemini-cli/pull/24403)
- fix(build): wire bundle:browser-mcp into bundle pipeline by @gsquared94 in
[#24424](https://github.com/google-gemini/gemini-cli/pull/24424)
- feat(browser): add sandbox-aware browser agent initialization by @gsquared94
in [#24419](https://github.com/google-gemini/gemini-cli/pull/24419)
- feat(core): enhance tracker task schemas for detailed titles and descriptions
by @anj-s in [#23902](https://github.com/google-gemini/gemini-cli/pull/23902)
- refactor(core): Unified context management settings schema by @joshualitt in
[#24391](https://github.com/google-gemini/gemini-cli/pull/24391)
- feat(core): update browser agent prompt to check open pages first when
bringing up by @cynthialong0-0 in
[#24431](https://github.com/google-gemini/gemini-cli/pull/24431)
- fix(acp) refactor(core,cli): centralize model discovery logic in
ModelConfigService by @sripasg in
[#24392](https://github.com/google-gemini/gemini-cli/pull/24392)
- Changelog for v0.36.0-preview.7 by @gemini-cli-robot in
[#24346](https://github.com/google-gemini/gemini-cli/pull/24346)
- fix: update task tracker storage location in system prompt by @anj-s in
[#24034](https://github.com/google-gemini/gemini-cli/pull/24034)
- feat(browser): supersede stale snapshots to reclaim context-window tokens by
@gsquared94 in
[#24440](https://github.com/google-gemini/gemini-cli/pull/24440)
- docs(core): add subagent tool isolation draft doc by @akh64bit in
[#23275](https://github.com/google-gemini/gemini-cli/pull/23275)
- fix(patch): cherry-pick 64c928f to release/v0.37.0-preview.0-pr-23257 to patch
version v0.37.0-preview.0 and create version 0.37.0-preview.1 by
@gemini-cli-robot in
[#21816](https://github.com/google-gemini/gemini-cli/pull/21816)
- Changelog for v0.33.0-preview.13 by @gemini-cli-robot in
[#21927](https://github.com/google-gemini/gemini-cli/pull/21927)
- fix(cli): stabilize prompt layout to prevent jumping when typing by
@NTaylorMullen in
[#21081](https://github.com/google-gemini/gemini-cli/pull/21081)
- fix: preserve prompt text when cancelling streaming by @Nixxx19 in
[#21103](https://github.com/google-gemini/gemini-cli/pull/21103)
- fix: robust UX for remote agent errors by @Shyam-Raghuwanshi in
[#20307](https://github.com/google-gemini/gemini-cli/pull/20307)
- feat: implement background process logging and cleanup by @galz10 in
[#21189](https://github.com/google-gemini/gemini-cli/pull/21189)
- Changelog for v0.33.0-preview.14 by @gemini-cli-robot in
[#21938](https://github.com/google-gemini/gemini-cli/pull/21938)
- fix(patch): cherry-pick 45faf4d to release/v0.34.0-preview.0-pr-22148
[CONFLICTS] by @gemini-cli-robot in
[#22174](https://github.com/google-gemini/gemini-cli/pull/22174)
- fix(patch): cherry-pick 8432bce to release/v0.34.0-preview.1-pr-22069 to patch
version v0.34.0-preview.1 and create version 0.34.0-preview.2 by
[#24561](https://github.com/google-gemini/gemini-cli/pull/24561)
- fix(patch): cherry-pick cb7f7d6 to release/v0.37.0-preview.1-pr-24342 to patch
version v0.37.0-preview.1 and create version 0.37.0-preview.2 by
@gemini-cli-robot in
[#22205](https://github.com/google-gemini/gemini-cli/pull/22205)
- fix(patch): cherry-pick 24adacd to release/v0.34.0-preview.2-pr-22332 to patch
version v0.34.0-preview.2 and create version 0.34.0-preview.3 by
@gemini-cli-robot in
[#22391](https://github.com/google-gemini/gemini-cli/pull/22391)
- fix(patch): cherry-pick 48130eb to release/v0.34.0-preview.3-pr-22665 to patch
version v0.34.0-preview.3 and create version 0.34.0-preview.4 by
@gemini-cli-robot in
[#22719](https://github.com/google-gemini/gemini-cli/pull/22719)
[#24842](https://github.com/google-gemini/gemini-cli/pull/24842)
**Full Changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.33.2...v0.34.0
https://github.com/google-gemini/gemini-cli/compare/v0.36.0...v0.37.0
+246 -365
View File
@@ -1,6 +1,6 @@
# Preview release: v0.35.0-preview.5
# Preview release: v0.38.0-preview.0
Released: March 23, 2026
Released: April 08, 2026
Our preview release includes the latest, new, and experimental features. This
release may not be as stable as our [latest weekly release](latest.md).
@@ -13,375 +13,256 @@ npm install -g @google/gemini-cli@preview
## Highlights
- **Subagents & Architecture Enhancements**: Enabled subagents and laid the
foundation for subagent tool isolation. Added proxy routing support for remote
A2A subagents and integrated `SandboxManager` to sandbox all process-spawning
tools.
- **CLI & UI Improvements**: Introduced customizable keyboard shortcuts and
support for literal character keybindings. Added missing vim mode motions and
CJK input support. Enabled code splitting and deferred UI loading for improved
performance.
- **Context & Tools Optimization**: JIT context loading is now enabled by
default with deduplication for project memory. Introduced a model-driven
parallel tool scheduler and allowed safe tools to execute concurrently.
- **Security & Extensions**: Implemented cryptographic integrity verification
for extension updates and added a `disableAlwaysAllow` setting to prevent
auto-approvals for enhanced security.
- **Plan Mode & Web Fetch Updates**: Added an 'All the above' option for
multi-select AskUser questions in Plan Mode. Rolled out Stage 1 and Stage 2
security and consistency improvements for the `web_fetch` tool.
- **Context Management:** Introduced a Context Compression Service to optimize
context window usage and landed a background memory service for skill
extraction.
- **Enhanced Security:** Implemented context-aware persistent policy approvals
for smarter tool permissions and enabled `web_fetch` in plan mode with user
confirmation.
- **Workflow Monitoring:** Added background process monitoring and inspection
tools for better visibility into long-running tasks.
- **UI/UX Refinements:** Enhanced the tool confirmation UI, selection layout,
and added support for selective topic expansion and click-to-expand.
- **Core Stability:** Improved sandbox reliability on Linux and Windows,
resolved shebang compatibility issues, and fixed various crashes in the CLI
and core services.
## What's Changed
- fix(patch): cherry-pick b2d6dc4 to release/v0.35.0-preview.4-pr-23546
[CONFLICTS] by @gemini-cli-robot in
[#23585](https://github.com/google-gemini/gemini-cli/pull/23585)
- fix(patch): cherry-pick daf3691 to release/v0.35.0-preview.2-pr-23558 to patch
version v0.35.0-preview.2 and create version 0.35.0-preview.3 by
@gemini-cli-robot in
[#23565](https://github.com/google-gemini/gemini-cli/pull/23565)
- fix(patch): cherry-pick 4e5dfd0 to release/v0.35.0-preview.1-pr-23074 to patch
version v0.35.0-preview.1 and create version 0.35.0-preview.2 by
@gemini-cli-robot in
[#23134](https://github.com/google-gemini/gemini-cli/pull/23134)
- feat(cli): customizable keyboard shortcuts by @scidomino in
[#21945](https://github.com/google-gemini/gemini-cli/pull/21945)
- feat(core): Thread `AgentLoopContext` through core. by @joshualitt in
[#21944](https://github.com/google-gemini/gemini-cli/pull/21944)
- chore(release): bump version to 0.35.0-nightly.20260311.657f19c1f by
@gemini-cli-robot in
[#21966](https://github.com/google-gemini/gemini-cli/pull/21966)
- refactor(a2a): remove legacy CoreToolScheduler by @adamfweidman in
[#21955](https://github.com/google-gemini/gemini-cli/pull/21955)
- feat(ui): add missing vim mode motions (X, ~, r, f/F/t/T, df/dt and friends)
by @aanari in [#21932](https://github.com/google-gemini/gemini-cli/pull/21932)
- Feat/retry fetch notifications by @aishaneeshah in
[#21813](https://github.com/google-gemini/gemini-cli/pull/21813)
- fix(core): remove OAuth check from handleFallback and clean up stray file by
@sehoon38 in [#21962](https://github.com/google-gemini/gemini-cli/pull/21962)
- feat(cli): support literal character keybindings and extended Kitty protocol
keys by @scidomino in
[#21972](https://github.com/google-gemini/gemini-cli/pull/21972)
- fix(ui): clamp cursor to last char after all NORMAL mode deletes by @aanari in
[#21973](https://github.com/google-gemini/gemini-cli/pull/21973)
- test(core): add missing tests for prompts/utils.ts by @krrishverma1805-web in
[#19941](https://github.com/google-gemini/gemini-cli/pull/19941)
- fix(cli): allow scrolling keys in copy mode (Ctrl+S selection mode) by
@nsalerni in [#19933](https://github.com/google-gemini/gemini-cli/pull/19933)
- docs(cli): add custom keybinding documentation by @scidomino in
[#21980](https://github.com/google-gemini/gemini-cli/pull/21980)
- docs: fix misleading YOLO mode description in defaultApprovalMode by
@Gyanranjan-Priyam in
[#21878](https://github.com/google-gemini/gemini-cli/pull/21878)
- fix: clean up /clear and /resume by @jackwotherspoon in
[#22007](https://github.com/google-gemini/gemini-cli/pull/22007)
- fix(core)#20941: reap orphaned descendant processes on PTY abort by @manavmax
in [#21124](https://github.com/google-gemini/gemini-cli/pull/21124)
- fix(core): update language detection to use LSP 3.18 identifiers by @yunaseoul
in [#21931](https://github.com/google-gemini/gemini-cli/pull/21931)
- feat(cli): support removing keybindings via '-' prefix by @scidomino in
[#22042](https://github.com/google-gemini/gemini-cli/pull/22042)
- feat(policy): add --admin-policy flag for supplemental admin policies by
@galz10 in [#20360](https://github.com/google-gemini/gemini-cli/pull/20360)
- merge duplicate imports packages/cli/src subtask1 by @Nixxx19 in
[#22040](https://github.com/google-gemini/gemini-cli/pull/22040)
- perf(core): parallelize user quota and experiments fetching in refreshAuth by
@sehoon38 in [#21648](https://github.com/google-gemini/gemini-cli/pull/21648)
- Changelog for v0.34.0-preview.0 by @gemini-cli-robot in
[#21965](https://github.com/google-gemini/gemini-cli/pull/21965)
- Changelog for v0.33.0 by @gemini-cli-robot in
[#21967](https://github.com/google-gemini/gemini-cli/pull/21967)
- fix(core): handle EISDIR in robustRealpath on Windows by @sehoon38 in
[#21984](https://github.com/google-gemini/gemini-cli/pull/21984)
- feat(core): include initiationMethod in conversation interaction telemetry by
@yunaseoul in [#22054](https://github.com/google-gemini/gemini-cli/pull/22054)
- feat(ui): add vim yank/paste (y/p/P) with unnamed register by @aanari in
[#22026](https://github.com/google-gemini/gemini-cli/pull/22026)
- fix(core): enable numerical routing for api key users by @sehoon38 in
[#21977](https://github.com/google-gemini/gemini-cli/pull/21977)
- feat(telemetry): implement retry attempt telemetry for network related retries
by @aishaneeshah in
[#22027](https://github.com/google-gemini/gemini-cli/pull/22027)
- fix(policy): remove unnecessary escapeRegex from pattern builders by
@spencer426 in
[#21921](https://github.com/google-gemini/gemini-cli/pull/21921)
- fix(core): preserve dynamic tool descriptions on session resume by @sehoon38
in [#18835](https://github.com/google-gemini/gemini-cli/pull/18835)
- chore: allow 'gemini-3.1' in sensitive keyword linter by @scidomino in
[#22065](https://github.com/google-gemini/gemini-cli/pull/22065)
- feat(core): support custom base URL via env vars by @junaiddshaukat in
[#21561](https://github.com/google-gemini/gemini-cli/pull/21561)
- merge duplicate imports packages/cli/src subtask2 by @Nixxx19 in
[#22051](https://github.com/google-gemini/gemini-cli/pull/22051)
- fix(core): silently retry API errors up to 3 times before halting session by
@spencer426 in
[#21989](https://github.com/google-gemini/gemini-cli/pull/21989)
- feat(core): simplify subagent success UI and improve early termination display
by @abhipatel12 in
[#21917](https://github.com/google-gemini/gemini-cli/pull/21917)
- merge duplicate imports packages/cli/src subtask3 by @Nixxx19 in
[#22056](https://github.com/google-gemini/gemini-cli/pull/22056)
- fix(hooks): fix BeforeAgent/AfterAgent inconsistencies (#18514) by @krishdef7
in [#21383](https://github.com/google-gemini/gemini-cli/pull/21383)
- feat(core): implement SandboxManager interface and config schema by @galz10 in
[#21774](https://github.com/google-gemini/gemini-cli/pull/21774)
- docs: document npm deprecation warnings as safe to ignore by @h30s in
[#20692](https://github.com/google-gemini/gemini-cli/pull/20692)
- fix: remove status/need-triage from maintainer-only issues by @SandyTao520 in
[#22044](https://github.com/google-gemini/gemini-cli/pull/22044)
- fix(core): propagate subagent context to policy engine by @NTaylorMullen in
[#22086](https://github.com/google-gemini/gemini-cli/pull/22086)
- fix(cli): resolve skill uninstall failure when skill name is updated by
- fix(cli): refresh slash command list after /skills reload by @NTaylorMullen in
[#24454](https://github.com/google-gemini/gemini-cli/pull/24454)
- Update README.md for links. by @g-samroberts in
[#22759](https://github.com/google-gemini/gemini-cli/pull/22759)
- fix(core): ensure complete_task tool calls are recorded in chat history by
@abhipatel12 in
[#24437](https://github.com/google-gemini/gemini-cli/pull/24437)
- feat(policy): explicitly allow web_fetch in plan mode with ask_user by
@Adib234 in [#24456](https://github.com/google-gemini/gemini-cli/pull/24456)
- fix(core): refactor linux sandbox to fix ARG_MAX crashes by @ehedlund in
[#24286](https://github.com/google-gemini/gemini-cli/pull/24286)
- feat(config): add experimental.adk.agentSessionNoninteractiveEnabled setting
by @adamfweidman in
[#24439](https://github.com/google-gemini/gemini-cli/pull/24439)
- Changelog for v0.36.0-preview.8 by @gemini-cli-robot in
[#24453](https://github.com/google-gemini/gemini-cli/pull/24453)
- feat(cli): change default loadingPhrases to 'off' to hide tips by @keithguerin
in [#24342](https://github.com/google-gemini/gemini-cli/pull/24342)
- fix(cli): ensure agent stops when all declinable tools are cancelled by
@NTaylorMullen in
[#22085](https://github.com/google-gemini/gemini-cli/pull/22085)
- docs(plan): clarify interactive plan editing with Ctrl+X by @Adib234 in
[#22076](https://github.com/google-gemini/gemini-cli/pull/22076)
- fix(policy): ensure user policies are loaded when policyPaths is empty by
@NTaylorMullen in
[#22090](https://github.com/google-gemini/gemini-cli/pull/22090)
- Docs: Add documentation for model steering (experimental). by @jkcinouye in
[#21154](https://github.com/google-gemini/gemini-cli/pull/21154)
- Add issue for automated changelogs by @g-samroberts in
[#21912](https://github.com/google-gemini/gemini-cli/pull/21912)
- fix(core): secure argsPattern and revert WEB_FETCH_TOOL_NAME escalation by
@spencer426 in
[#22104](https://github.com/google-gemini/gemini-cli/pull/22104)
- feat(core): differentiate User-Agent for a2a-server and ACP clients by
@bdmorgan in [#22059](https://github.com/google-gemini/gemini-cli/pull/22059)
- refactor(core): extract ExecutionLifecycleService for tool backgrounding by
@adamfweidman in
[#21717](https://github.com/google-gemini/gemini-cli/pull/21717)
- feat: Display pending and confirming tool calls by @sripasg in
[#22106](https://github.com/google-gemini/gemini-cli/pull/22106)
- feat(browser): implement input blocker overlay during automation by
@kunal-10-cloud in
[#21132](https://github.com/google-gemini/gemini-cli/pull/21132)
- fix: register themes on extension load not start by @jackwotherspoon in
[#22148](https://github.com/google-gemini/gemini-cli/pull/22148)
- feat(ui): Do not show Ultra users /upgrade hint (#22154) by @sehoon38 in
[#22156](https://github.com/google-gemini/gemini-cli/pull/22156)
- chore: remove unnecessary log for themes by @jackwotherspoon in
[#22165](https://github.com/google-gemini/gemini-cli/pull/22165)
- fix(core): resolve MCP tool FQN validation, schema export, and wildcards in
subagents by @abhipatel12 in
[#22069](https://github.com/google-gemini/gemini-cli/pull/22069)
- fix(cli): validate --model argument at startup by @JaisalJain in
[#21393](https://github.com/google-gemini/gemini-cli/pull/21393)
- fix(core): handle policy ALLOW for exit_plan_mode by @backnotprop in
[#21802](https://github.com/google-gemini/gemini-cli/pull/21802)
- feat(telemetry): add Clearcut instrumentation for AI credits billing events by
[#24479](https://github.com/google-gemini/gemini-cli/pull/24479)
- fix(core): enhance sandbox usability and fix build error by @galz10 in
[#24460](https://github.com/google-gemini/gemini-cli/pull/24460)
- Terminal Serializer Optimization by @jacob314 in
[#24485](https://github.com/google-gemini/gemini-cli/pull/24485)
- Auto configure memory. by @jacob314 in
[#24474](https://github.com/google-gemini/gemini-cli/pull/24474)
- Unused error variables in catch block are not allowed by @alisa-alisa in
[#24487](https://github.com/google-gemini/gemini-cli/pull/24487)
- feat(core): add background memory service for skill extraction by @SandyTao520
in [#24274](https://github.com/google-gemini/gemini-cli/pull/24274)
- feat: implement high-signal PR regression check for evaluations by
@alisa-alisa in
[#23937](https://github.com/google-gemini/gemini-cli/pull/23937)
- Fix shell output display by @jacob314 in
[#24490](https://github.com/google-gemini/gemini-cli/pull/24490)
- fix(ui): resolve unwanted vertical spacing around various tool output
treatments by @jwhelangoog in
[#24449](https://github.com/google-gemini/gemini-cli/pull/24449)
- revert(cli): bring back input box and footer visibility in copy mode by
@sehoon38 in [#24504](https://github.com/google-gemini/gemini-cli/pull/24504)
- fix(cli): prevent crash in AnsiOutputText when handling non-array data by
@sehoon38 in [#24498](https://github.com/google-gemini/gemini-cli/pull/24498)
- feat(cli): support default values for environment variables by @ruomengz in
[#24469](https://github.com/google-gemini/gemini-cli/pull/24469)
- Implement background process monitoring and inspection tools by @cocosheng-g
in [#23799](https://github.com/google-gemini/gemini-cli/pull/23799)
- docs(browser-agent): update stale browser agent documentation by @gsquared94
in [#24463](https://github.com/google-gemini/gemini-cli/pull/24463)
- fix: enable browser_agent in integration tests and add localhost fixture tests
by @gsquared94 in
[#24523](https://github.com/google-gemini/gemini-cli/pull/24523)
- fix(browser): handle computer-use model detection for analyze_screenshot by
@gsquared94 in
[#22153](https://github.com/google-gemini/gemini-cli/pull/22153)
- feat(core): add google credentials provider for remote agents by @adamfweidman
in [#21024](https://github.com/google-gemini/gemini-cli/pull/21024)
- test(cli): add integration test for node deprecation warnings by @Nixxx19 in
[#20215](https://github.com/google-gemini/gemini-cli/pull/20215)
- feat(cli): allow safe tools to execute concurrently while agent is busy by
@spencer426 in
[#21988](https://github.com/google-gemini/gemini-cli/pull/21988)
- feat(core): implement model-driven parallel tool scheduler by @abhipatel12 in
[#21933](https://github.com/google-gemini/gemini-cli/pull/21933)
- update vulnerable deps by @scidomino in
[#22180](https://github.com/google-gemini/gemini-cli/pull/22180)
- fix(core): fix startup stats to use int values for timestamps and durations by
@yunaseoul in [#22201](https://github.com/google-gemini/gemini-cli/pull/22201)
- fix(core): prevent duplicate tool schemas for instantiated tools by
@abhipatel12 in
[#22204](https://github.com/google-gemini/gemini-cli/pull/22204)
- fix(core): add proxy routing support for remote A2A subagents by @adamfweidman
in [#22199](https://github.com/google-gemini/gemini-cli/pull/22199)
- fix(core/ide): add Antigravity CLI fallbacks by @apfine in
[#22030](https://github.com/google-gemini/gemini-cli/pull/22030)
- fix(browser): fix duplicate function declaration error in browser agent by
@gsquared94 in
[#22207](https://github.com/google-gemini/gemini-cli/pull/22207)
- feat(core): implement Stage 1 improvements for webfetch tool by @aishaneeshah
in [#21313](https://github.com/google-gemini/gemini-cli/pull/21313)
- Changelog for v0.34.0-preview.1 by @gemini-cli-robot in
[#22194](https://github.com/google-gemini/gemini-cli/pull/22194)
- perf(cli): enable code splitting and deferred UI loading by @sehoon38 in
[#22117](https://github.com/google-gemini/gemini-cli/pull/22117)
- fix: remove unused img.png from project root by @SandyTao520 in
[#22222](https://github.com/google-gemini/gemini-cli/pull/22222)
- docs(local model routing): add docs on how to use Gemma for local model
routing by @douglas-reid in
[#21365](https://github.com/google-gemini/gemini-cli/pull/21365)
- feat(a2a): enable native gRPC support and protocol routing by @alisa-alisa in
[#21403](https://github.com/google-gemini/gemini-cli/pull/21403)
- fix(cli): escape @ symbols on paste to prevent unintended file expansion by
@krishdef7 in [#21239](https://github.com/google-gemini/gemini-cli/pull/21239)
- feat(core): add trajectoryId to ConversationOffered telemetry by @yunaseoul in
[#22214](https://github.com/google-gemini/gemini-cli/pull/22214)
- docs: clarify that tools.core is an allowlist for ALL built-in tools by
@hobostay in [#18813](https://github.com/google-gemini/gemini-cli/pull/18813)
- docs(plan): document hooks with plan mode by @ruomengz in
[#22197](https://github.com/google-gemini/gemini-cli/pull/22197)
- Changelog for v0.33.1 by @gemini-cli-robot in
[#22235](https://github.com/google-gemini/gemini-cli/pull/22235)
- build(ci): fix false positive evals trigger on merge commits by @gundermanc in
[#22237](https://github.com/google-gemini/gemini-cli/pull/22237)
- fix(core): explicitly pass messageBus to policy engine for MCP tool saves by
@abhipatel12 in
[#22255](https://github.com/google-gemini/gemini-cli/pull/22255)
- feat(core): Fully migrate packages/core to AgentLoopContext. by @joshualitt in
[#22115](https://github.com/google-gemini/gemini-cli/pull/22115)
- feat(core): increase sub-agent turn and time limits by @bdmorgan in
[#22196](https://github.com/google-gemini/gemini-cli/pull/22196)
- feat(core): instrument file system tools for JIT context discovery by
[#24502](https://github.com/google-gemini/gemini-cli/pull/24502)
- feat(core): Land ContextCompressionService by @joshualitt in
[#24483](https://github.com/google-gemini/gemini-cli/pull/24483)
- feat(core): scope subagent workspace directories via AsyncLocalStorage by
@SandyTao520 in
[#22082](https://github.com/google-gemini/gemini-cli/pull/22082)
- refactor(ui): extract pure session browser utilities by @abhipatel12 in
[#22256](https://github.com/google-gemini/gemini-cli/pull/22256)
- fix(plan): Fix AskUser evals by @Adib234 in
[#22074](https://github.com/google-gemini/gemini-cli/pull/22074)
- fix(settings): prevent j/k navigation keys from intercepting edit buffer input
by @student-ankitpandit in
[#21865](https://github.com/google-gemini/gemini-cli/pull/21865)
- feat(skills): improve async-pr-review workflow and logging by @mattKorwel in
[#21790](https://github.com/google-gemini/gemini-cli/pull/21790)
- refactor(cli): consolidate getErrorMessage utility to core by @scidomino in
[#22190](https://github.com/google-gemini/gemini-cli/pull/22190)
- fix(core): show descriptive error messages when saving settings fails by
@afarber in [#18095](https://github.com/google-gemini/gemini-cli/pull/18095)
- docs(core): add authentication guide for remote subagents by @adamfweidman in
[#22178](https://github.com/google-gemini/gemini-cli/pull/22178)
- docs: overhaul subagents documentation and add /agents command by @abhipatel12
in [#22345](https://github.com/google-gemini/gemini-cli/pull/22345)
- refactor(ui): extract SessionBrowser static ui components by @abhipatel12 in
[#22348](https://github.com/google-gemini/gemini-cli/pull/22348)
- test: add Object.create context regression test and tool confirmation
integration test by @gsquared94 in
[#22356](https://github.com/google-gemini/gemini-cli/pull/22356)
- feat(tracker): return TodoList display for tracker tools by @anj-s in
[#22060](https://github.com/google-gemini/gemini-cli/pull/22060)
- feat(agent): add allowed domain restrictions for browser agent by
@cynthialong0-0 in
[#21775](https://github.com/google-gemini/gemini-cli/pull/21775)
- chore/release: bump version to 0.35.0-nightly.20260313.bb060d7a9 by
@gemini-cli-robot in
[#22251](https://github.com/google-gemini/gemini-cli/pull/22251)
- Move keychain fallback to keychain service by @chrstnb in
[#22332](https://github.com/google-gemini/gemini-cli/pull/22332)
- feat(core): integrate SandboxManager to sandbox all process-spawning tools by
@galz10 in [#22231](https://github.com/google-gemini/gemini-cli/pull/22231)
- fix(cli): support CJK input and full Unicode scalar values in terminal
protocols by @scidomino in
[#22353](https://github.com/google-gemini/gemini-cli/pull/22353)
- Promote stable tests. by @gundermanc in
[#22253](https://github.com/google-gemini/gemini-cli/pull/22253)
- feat(tracker): add tracker policy by @anj-s in
[#22379](https://github.com/google-gemini/gemini-cli/pull/22379)
- feat(security): add disableAlwaysAllow setting to disable auto-approvals by
@galz10 in [#21941](https://github.com/google-gemini/gemini-cli/pull/21941)
- Revert "fix(cli): validate --model argument at startup" by @sehoon38 in
[#22378](https://github.com/google-gemini/gemini-cli/pull/22378)
- fix(mcp): handle equivalent root resource URLs in OAuth validation by @galz10
in [#20231](https://github.com/google-gemini/gemini-cli/pull/20231)
- fix(core): use session-specific temp directory for task tracker by @anj-s in
[#22382](https://github.com/google-gemini/gemini-cli/pull/22382)
- Fix issue where config was undefined. by @gundermanc in
[#22397](https://github.com/google-gemini/gemini-cli/pull/22397)
- fix(core): deduplicate project memory when JIT context is enabled by
@SandyTao520 in
[#22234](https://github.com/google-gemini/gemini-cli/pull/22234)
- feat(prompts): implement Topic-Action-Summary model for verbosity reduction by
@Abhijit-2592 in
[#21503](https://github.com/google-gemini/gemini-cli/pull/21503)
- fix(core): fix manual deletion of subagent histories by @abhipatel12 in
[#22407](https://github.com/google-gemini/gemini-cli/pull/22407)
- Add registry var by @kevinjwang1 in
[#22224](https://github.com/google-gemini/gemini-cli/pull/22224)
- Add ModelDefinitions to ModelConfigService by @kevinjwang1 in
[#22302](https://github.com/google-gemini/gemini-cli/pull/22302)
- fix(cli): improve command conflict handling for skills by @NTaylorMullen in
[#21942](https://github.com/google-gemini/gemini-cli/pull/21942)
- fix(core): merge user settings with extension-provided MCP servers by
@abhipatel12 in
[#22484](https://github.com/google-gemini/gemini-cli/pull/22484)
- fix(core): skip discovery for incomplete MCP configs and resolve merge race
condition by @abhipatel12 in
[#22494](https://github.com/google-gemini/gemini-cli/pull/22494)
- fix(automation): harden stale PR closer permissions and maintainer detection
by @bdmorgan in
[#22558](https://github.com/google-gemini/gemini-cli/pull/22558)
- fix(automation): evaluate staleness before checking protected labels by
@bdmorgan in [#22561](https://github.com/google-gemini/gemini-cli/pull/22561)
- feat(agent): replace the runtime npx for browser agent chrome devtool mcp with
pre-built bundle by @cynthialong0-0 in
[#22213](https://github.com/google-gemini/gemini-cli/pull/22213)
- perf: optimize TrackerService dependency checks by @anj-s in
[#22384](https://github.com/google-gemini/gemini-cli/pull/22384)
- docs(policy): remove trailing space from commandPrefix examples by @kawasin73
in [#22264](https://github.com/google-gemini/gemini-cli/pull/22264)
- fix(a2a-server): resolve unsafe assignment lint errors by @ehedlund in
[#22661](https://github.com/google-gemini/gemini-cli/pull/22661)
- fix: Adjust ToolGroupMessage filtering to hide Confirming and show Canceled
tool calls. by @sripasg in
[#22230](https://github.com/google-gemini/gemini-cli/pull/22230)
- Disallow Object.create() and reflect. by @gundermanc in
[#22408](https://github.com/google-gemini/gemini-cli/pull/22408)
- Guard pro model usage by @sehoon38 in
[#22665](https://github.com/google-gemini/gemini-cli/pull/22665)
- refactor(core): Creates AgentSession abstraction for consolidated agent
interface. by @mbleigh in
[#22270](https://github.com/google-gemini/gemini-cli/pull/22270)
- docs(changelog): remove internal commands from release notes by
[#24445](https://github.com/google-gemini/gemini-cli/pull/24445)
- Update ink version to 6.6.7 by @jacob314 in
[#24514](https://github.com/google-gemini/gemini-cli/pull/24514)
- fix(acp): handle all InvalidStreamError types gracefully in prompt by @sripasg
in [#24540](https://github.com/google-gemini/gemini-cli/pull/24540)
- Fix crash when vim editor is not found in PATH on Windows by
@Nagajyothi-tammisetti in
[#22423](https://github.com/google-gemini/gemini-cli/pull/22423)
- fix(core): move project memory dir under tmp directory by @SandyTao520 in
[#24542](https://github.com/google-gemini/gemini-cli/pull/24542)
- Enable 'Other' option for yesno question type by @ruomengz in
[#24545](https://github.com/google-gemini/gemini-cli/pull/24545)
- fix(cli): clear stale retry/loading state after cancellation (#21096) by
@Aaxhirrr in [#21960](https://github.com/google-gemini/gemini-cli/pull/21960)
- Changelog for v0.37.0-preview.0 by @gemini-cli-robot in
[#24464](https://github.com/google-gemini/gemini-cli/pull/24464)
- feat(core): implement context-aware persistent policy approvals by @jerop in
[#23257](https://github.com/google-gemini/gemini-cli/pull/23257)
- docs: move agent disabling instructions and update remote agent status by
@jackwotherspoon in
[#22529](https://github.com/google-gemini/gemini-cli/pull/22529)
- feat: enable subagents by @abhipatel12 in
[#22386](https://github.com/google-gemini/gemini-cli/pull/22386)
- feat(extensions): implement cryptographic integrity verification for extension
updates by @ehedlund in
[#21772](https://github.com/google-gemini/gemini-cli/pull/21772)
- feat(tracker): polish UI sorting and formatting by @anj-s in
[#22437](https://github.com/google-gemini/gemini-cli/pull/22437)
- Changelog for v0.34.0-preview.2 by @gemini-cli-robot in
[#22220](https://github.com/google-gemini/gemini-cli/pull/22220)
- fix(core): fix three JIT context bugs in read_file, read_many_files, and
memoryDiscovery by @SandyTao520 in
[#22679](https://github.com/google-gemini/gemini-cli/pull/22679)
- refactor(core): introduce InjectionService with source-aware injection and
backend-native background completions by @adamfweidman in
[#22544](https://github.com/google-gemini/gemini-cli/pull/22544)
- Linux sandbox bubblewrap by @DavidAPierce in
[#22680](https://github.com/google-gemini/gemini-cli/pull/22680)
- feat(core): increase thought signature retry resilience by @bdmorgan in
[#22202](https://github.com/google-gemini/gemini-cli/pull/22202)
- feat(core): implement Stage 2 security and consistency improvements for
web_fetch by @aishaneeshah in
[#22217](https://github.com/google-gemini/gemini-cli/pull/22217)
- refactor(core): replace positional execute params with ExecuteOptions bag by
@adamfweidman in
[#22674](https://github.com/google-gemini/gemini-cli/pull/22674)
- feat(config): enable JIT context loading by default by @SandyTao520 in
[#22736](https://github.com/google-gemini/gemini-cli/pull/22736)
- fix(config): ensure discoveryMaxDirs is passed to global config during
initialization by @kevin-ramdass in
[#22744](https://github.com/google-gemini/gemini-cli/pull/22744)
- fix(plan): allowlist get_internal_docs in Plan Mode by @Adib234 in
[#22668](https://github.com/google-gemini/gemini-cli/pull/22668)
- Changelog for v0.34.0-preview.3 by @gemini-cli-robot in
[#22393](https://github.com/google-gemini/gemini-cli/pull/22393)
- feat(core): add foundation for subagent tool isolation by @akh64bit in
[#22708](https://github.com/google-gemini/gemini-cli/pull/22708)
- fix(core): handle surrogate pairs in truncateString by @sehoon38 in
[#22754](https://github.com/google-gemini/gemini-cli/pull/22754)
- fix(cli): override j/k navigation in settings dialog to fix search input
conflict by @sehoon38 in
[#22800](https://github.com/google-gemini/gemini-cli/pull/22800)
- feat(plan): add 'All the above' option to multi-select AskUser questions by
@Adib234 in [#22365](https://github.com/google-gemini/gemini-cli/pull/22365)
- docs: distribute package-specific GEMINI.md context to each package by
@SandyTao520 in
[#22734](https://github.com/google-gemini/gemini-cli/pull/22734)
- fix(cli): clean up stale pasted placeholder metadata after word/line deletions
by @Jomak-x in
[#20375](https://github.com/google-gemini/gemini-cli/pull/20375)
- refactor(core): align JIT memory placement with tiered context model by
@SandyTao520 in
[#22766](https://github.com/google-gemini/gemini-cli/pull/22766)
- Linux sandbox seccomp by @DavidAPierce in
[#22815](https://github.com/google-gemini/gemini-cli/pull/22815)
[#24559](https://github.com/google-gemini/gemini-cli/pull/24559)
- feat(cli): migrate nonInteractiveCli to LegacyAgentSession by @adamfweidman in
[#22987](https://github.com/google-gemini/gemini-cli/pull/22987)
- fix(core): unsafe type assertions in Core File System #19712 by
@aniketsaurav18 in
[#19739](https://github.com/google-gemini/gemini-cli/pull/19739)
- fix(ui): hide model quota in /stats and refactor quota display by @danzaharia1
in [#24206](https://github.com/google-gemini/gemini-cli/pull/24206)
- Changelog for v0.36.0 by @gemini-cli-robot in
[#24558](https://github.com/google-gemini/gemini-cli/pull/24558)
- Changelog for v0.37.0-preview.1 by @gemini-cli-robot in
[#24568](https://github.com/google-gemini/gemini-cli/pull/24568)
- docs: add missing .md extensions to internal doc links by @ishaan-arora-1 in
[#24145](https://github.com/google-gemini/gemini-cli/pull/24145)
- fix(ui): fixed table styling by @devr0306 in
[#24565](https://github.com/google-gemini/gemini-cli/pull/24565)
- fix(core): pass includeDirectories to sandbox configuration by @galz10 in
[#24573](https://github.com/google-gemini/gemini-cli/pull/24573)
- feat(ui): enable "TerminalBuffer" mode to solve flicker by @jacob314 in
[#24512](https://github.com/google-gemini/gemini-cli/pull/24512)
- docs: clarify release coordination by @scidomino in
[#24575](https://github.com/google-gemini/gemini-cli/pull/24575)
- fix(core): remove broken PowerShell translation and fix native \_\_write in
Windows sandbox by @scidomino in
[#24571](https://github.com/google-gemini/gemini-cli/pull/24571)
- Add instructions for how to start react in prod and force react to prod mode
by @jacob314 in
[#24590](https://github.com/google-gemini/gemini-cli/pull/24590)
- feat(cli): minimalist sandbox status labels by @galz10 in
[#24582](https://github.com/google-gemini/gemini-cli/pull/24582)
- Feat/browser agent metrics by @kunal-10-cloud in
[#24210](https://github.com/google-gemini/gemini-cli/pull/24210)
- test: fix Windows CI execution and resolve exposed platform failures by
@ehedlund in [#24476](https://github.com/google-gemini/gemini-cli/pull/24476)
- feat(core,cli): prioritize summary for topics (#24608) by @Abhijit-2592 in
[#24609](https://github.com/google-gemini/gemini-cli/pull/24609)
- show color by @jacob314 in
[#24613](https://github.com/google-gemini/gemini-cli/pull/24613)
- feat(cli): enable compact tool output by default (#24509) by @jwhelangoog in
[#24510](https://github.com/google-gemini/gemini-cli/pull/24510)
- fix(core): inject skill system instructions into subagent prompts if activated
by @abhipatel12 in
[#24620](https://github.com/google-gemini/gemini-cli/pull/24620)
- fix(core): improve windows sandbox reliability and fix integration tests by
@ehedlund in [#24480](https://github.com/google-gemini/gemini-cli/pull/24480)
- fix(core): ensure sandbox approvals are correctly persisted and matched for
proactive expansions by @galz10 in
[#24577](https://github.com/google-gemini/gemini-cli/pull/24577)
- feat(cli) Scrollbar for input prompt by @jacob314 in
[#21992](https://github.com/google-gemini/gemini-cli/pull/21992)
- Do not run pr-eval workflow when no steering changes detected by @alisa-alisa
in [#24621](https://github.com/google-gemini/gemini-cli/pull/24621)
- Fix restoration of topic headers. by @gundermanc in
[#24650](https://github.com/google-gemini/gemini-cli/pull/24650)
- feat(core): discourage update topic tool for simple tasks by @Samee24 in
[#24640](https://github.com/google-gemini/gemini-cli/pull/24640)
- fix(core): ensure global temp directory is always in sandbox allowed paths by
@galz10 in [#24638](https://github.com/google-gemini/gemini-cli/pull/24638)
- fix(core): detect uninitialized lines by @jacob314 in
[#24646](https://github.com/google-gemini/gemini-cli/pull/24646)
- docs: update sandboxing documentation and toolSandboxing settings by @galz10
in [#24655](https://github.com/google-gemini/gemini-cli/pull/24655)
- feat(cli): enhance tool confirmation UI and selection layout by @galz10 in
[#24376](https://github.com/google-gemini/gemini-cli/pull/24376)
- feat(acp): add support for `/about` command by @sripasg in
[#24649](https://github.com/google-gemini/gemini-cli/pull/24649)
- feat(cli): add role specific metrics to /stats by @cynthialong0-0 in
[#24659](https://github.com/google-gemini/gemini-cli/pull/24659)
- split context by @jacob314 in
[#24623](https://github.com/google-gemini/gemini-cli/pull/24623)
- fix(cli): remove -S from shebang to fix Windows and BSD execution by
@scidomino in [#24756](https://github.com/google-gemini/gemini-cli/pull/24756)
- Fix issue where topic headers can be posted back to back by @gundermanc in
[#24759](https://github.com/google-gemini/gemini-cli/pull/24759)
- fix(core): handle partial llm_request in BeforeModel hook override by
@krishdef7 in [#22326](https://github.com/google-gemini/gemini-cli/pull/22326)
- fix(ui): improve narration suppression and reduce flicker by @gundermanc in
[#24635](https://github.com/google-gemini/gemini-cli/pull/24635)
- fix(ui): fixed auth race condition causing logo to flicker by @devr0306 in
[#24652](https://github.com/google-gemini/gemini-cli/pull/24652)
- fix(browser): remove premature browser cleanup after subagent invocation by
@gsquared94 in
[#24753](https://github.com/google-gemini/gemini-cli/pull/24753)
- Revert "feat(core,cli): prioritize summary for topics (#24608)" by
@Abhijit-2592 in
[#24777](https://github.com/google-gemini/gemini-cli/pull/24777)
- relax tool sandboxing overrides for plan mode to match defaults. by
@DavidAPierce in
[#24762](https://github.com/google-gemini/gemini-cli/pull/24762)
- fix(cli): respect global environment variable allowlist by @scidomino in
[#24767](https://github.com/google-gemini/gemini-cli/pull/24767)
- fix(cli): ensure skills list outputs to stdout in non-interactive environments
by @spencer426 in
[#24566](https://github.com/google-gemini/gemini-cli/pull/24566)
- Add an eval for and fix unsafe cloning behavior. by @gundermanc in
[#24457](https://github.com/google-gemini/gemini-cli/pull/24457)
- fix(policy): allow complete_task in plan mode by @abhipatel12 in
[#24771](https://github.com/google-gemini/gemini-cli/pull/24771)
- feat(telemetry): add browser agent clearcut metrics by @gsquared94 in
[#24688](https://github.com/google-gemini/gemini-cli/pull/24688)
- feat(cli): support selective topic expansion and click-to-expand by
@Abhijit-2592 in
[#24793](https://github.com/google-gemini/gemini-cli/pull/24793)
- temporarily disable sandbox integration test on windows by @ehedlund in
[#24786](https://github.com/google-gemini/gemini-cli/pull/24786)
- Remove flakey test by @scidomino in
[#24837](https://github.com/google-gemini/gemini-cli/pull/24837)
- Alisa/approve button by @alisa-alisa in
[#24645](https://github.com/google-gemini/gemini-cli/pull/24645)
- feat(hooks): display hook system messages in UI by @mbleigh in
[#24616](https://github.com/google-gemini/gemini-cli/pull/24616)
- fix(core): propagate BeforeModel hook model override end-to-end by @krishdef7
in [#24784](https://github.com/google-gemini/gemini-cli/pull/24784)
- chore: fix formatting for behavioral eval skill reference file by @abhipatel12
in [#24846](https://github.com/google-gemini/gemini-cli/pull/24846)
- fix: use directory junctions on Windows for skill linking by @enjoykumawat in
[#24823](https://github.com/google-gemini/gemini-cli/pull/24823)
- fix(cli): prevent multiple banner increments on remount by @sehoon38 in
[#24843](https://github.com/google-gemini/gemini-cli/pull/24843)
- feat(acp): add /help command by @sripasg in
[#24839](https://github.com/google-gemini/gemini-cli/pull/24839)
- fix(core): remove tmux alternate buffer warning by @jackwotherspoon in
[#24852](https://github.com/google-gemini/gemini-cli/pull/24852)
- Improve sandbox error matching and caching by @DavidAPierce in
[#24550](https://github.com/google-gemini/gemini-cli/pull/24550)
- feat(core): add agent protocol UI types and experimental flag by @mbleigh in
[#24275](https://github.com/google-gemini/gemini-cli/pull/24275)
- feat(core): use experiment flags for default fetch timeouts by @yunaseoul in
[#24261](https://github.com/google-gemini/gemini-cli/pull/24261)
- Revert "fix(ui): improve narration suppression and reduce flicker (#2… by
@gundermanc in
[#24857](https://github.com/google-gemini/gemini-cli/pull/24857)
- refactor(cli): remove duplication in interactive shell awaiting input hint by
@JayadityaGit in
[#24801](https://github.com/google-gemini/gemini-cli/pull/24801)
- refactor(core): make LegacyAgentSession dependencies optional by @mbleigh in
[#24287](https://github.com/google-gemini/gemini-cli/pull/24287)
- Changelog for v0.37.0-preview.2 by @gemini-cli-robot in
[#24848](https://github.com/google-gemini/gemini-cli/pull/24848)
- fix(cli): always show shell command description or actual command by @jacob314
in [#24774](https://github.com/google-gemini/gemini-cli/pull/24774)
- Added flag for ept size and increased default size by @devr0306 in
[#24859](https://github.com/google-gemini/gemini-cli/pull/24859)
- fix(core): dispose Scheduler to prevent McpProgress listener leak by
@Anjaligarhwal in
[#24870](https://github.com/google-gemini/gemini-cli/pull/24870)
- fix(cli): switch default back to terminalBuffer=false and fix regressions
introduced for that mode by @jacob314 in
[#24873](https://github.com/google-gemini/gemini-cli/pull/24873)
- feat(cli): switch to ctrl+g from ctrl-x by @jacob314 in
[#24861](https://github.com/google-gemini/gemini-cli/pull/24861)
- fix: isolate concurrent browser agent instances by @gsquared94 in
[#24794](https://github.com/google-gemini/gemini-cli/pull/24794)
- docs: update MCP server OAuth redirect port documentation by @adamfweidman in
[#24844](https://github.com/google-gemini/gemini-cli/pull/24844)
**Full Changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.34.0-preview.4...v0.35.0-preview.5
https://github.com/google-gemini/gemini-cli/compare/v0.37.0-preview.2...v0.38.0-preview.0
+126
View File
@@ -0,0 +1,126 @@
# ACP Mode
ACP (Agent Client Protocol) mode is a special operational mode of Gemini CLI
designed for programmatic control, primarily for IDE and other developer tool
integrations. It uses a JSON-RPC protocol over stdio to communicate between
Gemini CLI agent and a client.
To start Gemini CLI in ACP mode, use the `--acp` flag:
```bash
gemini --acp
```
## Agent Client Protocol (ACP)
ACP is an open protocol that standardizes how AI coding agents communicate with
code editors and IDEs. It addresses the challenge of fragmented distribution,
where agents traditionally needed custom integrations for each client. With ACP,
developers can implement their agent once, and it becomes compatible with any
ACP-compliant editor.
For a comprehensive introduction to ACP, including its architecture and
benefits, refer to the official
[ACP Introduction](https://agentclientprotocol.com/get-started/introduction)
documentation.
### Existing integrations using ACP
The ACP Agent Registry simplifies the distribution and management of
ACP-compatible agents across various IDEs. Gemini CLI is an ACP-compatible agent
and can be found in this registry.
For more general information about the registry, and how to use it with specific
IDEs like JetBrains and Zed, refer to the
[IDE Integration](../ide-integration/index.md) documentation.
You can also find more information on the official
[ACP Agent Registry](https://agentclientprotocol.com/get-started/registry) page.
## Architecture and protocol basics
ACP mode establishes a client-server relationship between your tool (the client)
and Gemini CLI (the server).
- **Communication:** The entire communication happens over standard input/output
(stdio) using the JSON-RPC 2.0 protocol.
- **Client's role:** The client is responsible for sending requests (e.g.,
prompts) and handling responses and notifications from Gemini CLI.
- **Gemini CLI's role:** In ACP mode, Gemini CLI listens for incoming JSON-RPC
requests, processes them, and sends back responses.
The core of the ACP implementation can be found in
`packages/cli/src/acp/acpClient.ts`.
### Extending with MCP
ACP can be used with the Model Context Protocol (MCP). This lets an ACP client
(like an IDE) expose its own functionality as "tools" that the Gemini model can
use.
1. The client implements an **MCP server** that advertises its tools.
2. During the ACP `initialize` handshake, the client provides the connection
details for its MCP server.
3. Gemini CLI connects to the MCP server, discovers the available tools, and
makes them available to the AI model.
4. When the model decides to use one of these tools, Gemini CLI sends a tool
call request to the MCP server.
This mechanism lets for a powerful, two-way integration where the agent can
leverage the IDE's capabilities to perform tasks. The MCP client logic is in
`packages/core/src/tools/mcp-client.ts`.
## Capabilities and supported methods
The ACP protocol exposes a number of methods for ACP clients (e.g. IDEs) to
control Gemini CLI.
### Core methods
- `initialize`: Establishes the initial connection and lets the client to
register its MCP server.
- `authenticate`: Authenticates the user.
- `newSession`: Starts a new chat session.
- `loadSession`: Loads a previous session.
- `prompt`: Sends a prompt to the agent.
- `cancel`: Cancels an ongoing prompt.
### Session control
- `setSessionMode`: Allows changing the approval level for tool calls (e.g., to
`auto-approve`).
- `unstable_setSessionModel`: Changes the model for the current session.
### File system proxy
ACP includes a proxied file system service. This means that when the agent needs
to read or write files, it does so through the ACP client. This is a security
feature that ensures the agent only has access to the files that the client (and
by extension, the user) has explicitly allowed.
## Debugging and telemetry
You can get insights into the ACP communication and the agent's behavior through
debugging logs and telemetry.
### Debugging logs
To enable general debugging logs, start Gemini CLI with the `--debug` flag:
```bash
gemini --acp --debug
```
### Telemetry
For more detailed telemetry, you can use the following environment variables to
capture telemetry data to a file:
- `GEMINI_TELEMETRY_ENABLED=true`
- `GEMINI_TELEMETRY_TARGET=local`
- `GEMINI_TELEMETRY_OUTFILE=/path/to/your/log.json`
This will write a JSON log file containing detailed information about all the
events happening within the agent, including ACP requests and responses. The
integration test `integration-tests/acp-telemetry.test.ts` provides a working
example of how to set this up.
+1 -1
View File
@@ -52,7 +52,7 @@ These commands are available within the interactive REPL.
| `--prompt-interactive` | `-i` | string | - | Execute prompt and continue in interactive mode |
| `--worktree` | `-w` | string | - | Start Gemini in a new git worktree. If no name is provided, one is generated automatically. Requires `experimental.worktrees: true` in settings. |
| `--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` |
| `--approval-mode` | - | string | `default` | Approval mode for tool execution. Choices: `default`, `auto_edit`, `yolo`, `plan` |
| `--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.** |
+5 -5
View File
@@ -15,14 +15,14 @@ CLI works in the background.
## Requirements
Currently, system notifications are only supported on macOS.
### Terminal support
The CLI uses the OSC 9 terminal escape sequence to trigger system notifications.
This is supported by several modern terminal emulators. If your terminal does
not support OSC 9 notifications, Gemini CLI falls back to a system alert sound
to get your attention.
This is supported by several modern terminal emulators including iTerm2,
WezTerm, Ghostty, and Kitty. If your terminal does not support OSC 9
notifications, Gemini CLI falls back to a terminal bell (BEL) to get your
attention. Most terminals respond to BEL with a taskbar flash or system alert
sound.
## Enable notifications
+23 -11
View File
@@ -39,7 +39,9 @@ To start Plan Mode while using Gemini CLI:
the rotation when Gemini CLI is actively processing or showing confirmation
dialogs.
- **Command:** Type `/plan` in the input box.
- **Command:** Type `/plan [goal]` in the input box. The `[goal]` is optional;
for example, `/plan implement authentication` will switch to Plan Mode and
immediately submit the prompt to the model.
- **Natural Language:** Ask Gemini CLI to "start a plan for...". Gemini CLI
calls the
@@ -54,19 +56,21 @@ Gemini CLI takes action.
1. **Provide a goal:** Start by describing what you want to achieve. Gemini CLI
will then enter Plan Mode (if it's not already) to research the task.
2. **Review research and provide input:** As Gemini CLI analyzes your codebase,
it may ask you questions or present different implementation options using
[`ask_user`](../tools/ask-user.md). Provide your preferences to help guide
the design.
3. **Review the plan:** Once Gemini CLI has a proposed strategy, it creates a
detailed implementation plan as a Markdown file in your plans directory.
2. **Discuss and agree on strategy:** As Gemini CLI analyzes your codebase, it
will discuss its findings and proposed strategy with you to ensure
alignment. It may ask you questions or present different implementation
options using [`ask_user`](../tools/ask-user.md). **Gemini CLI will stop and
wait for your confirmation** before drafting the formal plan. You should
reach an informal agreement on the approach before proceeding.
3. **Review the plan:** Once you've agreed on the strategy, Gemini CLI creates
a detailed implementation plan as a Markdown file in your plans directory.
- **View:** You can open and read this file to understand the proposed
changes.
- **Edit:** Press `Ctrl+X` to open the plan directly in your configured
external editor.
4. **Approve or iterate:** Gemini CLI will present the finalized plan for your
approval.
formal approval.
- **Approve:** If you're satisfied with the plan, approve it to start the
implementation immediately: **Yes, automatically accept edits** or **Yes,
manually accept edits**.
@@ -119,6 +123,7 @@ These are the only allowed tools:
[`glob`](../tools/file-system.md#4-glob-findfiles)
- **Search:** [`grep_search`](../tools/file-system.md#5-grep_search-searchtext),
[`google_web_search`](../tools/web-search.md),
[`web_fetch`](../tools/web-fetch.md) (requires explicit confirmation),
[`get_internal_docs`](../tools/internal-docs.md)
- **Research Subagents:**
[`codebase_investigator`](../core/subagents.md#codebase-investigator),
@@ -176,9 +181,16 @@ As described in the
rule that does not explicitly specify `modes` is considered "always active" and
will apply to Plan Mode as well.
If you want a rule to apply to other modes but _not_ to Plan Mode, you must
explicitly specify the target modes. For example, to allow `npm test` in default
and Auto-Edit modes but not in Plan Mode:
To maintain the integrity of Plan Mode as a safe research environment,
persistent tool approvals are context-aware. Approvals granted in modes like
Default or Auto-Edit do not apply to Plan Mode, ensuring that tools trusted for
implementation don't automatically execute while you're researching. However,
approvals granted while in Plan Mode are treated as intentional choices for
global trust and apply to all modes.
If you want to manually restrict a rule to other modes but _not_ to Plan Mode,
you must explicitly specify the target modes. For example, to allow `npm test`
in default and Auto-Edit modes but not in Plan Mode:
```toml
[[rule]]
+53 -1
View File
@@ -92,7 +92,7 @@ To set up runsc:
2. Configure the Docker daemon to use the runsc runtime.
3. Verify the installation.
### 4. LXC/LXD (Linux only, experimental)
### 5. LXC/LXD (Linux only, experimental)
Full-system container sandboxing using LXC/LXD. Unlike Docker/Podman, LXC
containers run a complete Linux system with `systemd`, `snapd`, and other system
@@ -136,6 +136,58 @@ gemini -p "build the snap"
absolute path — the path must be writable inside the container.
- Used with tools like Snapcraft or Rockcraft that require a full system.
## Tool sandboxing
Tool-level sandboxing provides granular isolation for individual tool executions
(like `shell_exec` and `write_file`) instead of sandboxing the entire Gemini CLI
process.
This approach offers better integration with your local environment for non-tool
tasks (like UI rendering and configuration loading) while still providing
security for tool-driven operations.
### How to turn off tool sandboxing
If you experience issues with tool sandboxing or prefer full-process isolation,
you can disable it by setting `security.toolSandboxing` to `false` in your
`settings.json` file.
```json
{
"security": {
"toolSandboxing": false
}
}
```
<!-- prettier-ignore -->
> [!NOTE]
> Changing the `security.toolSandboxing` setting requires a restart of Gemini
> CLI to take effect.
## Sandbox expansion
Sandbox expansion is a dynamic permission system that lets Gemini CLI request
additional permissions for a command when needed.
When a sandboxed command fails due to permission restrictions (like restricted
file paths or network access), or when a command is proactively identified as
requiring extra permissions (like `npm install`), Gemini CLI will present you
with a "Sandbox Expansion Request."
### How sandbox expansion works
1. **Detection**: Gemini CLI detects a sandbox denial or proactively identifies
a command that requires extra permissions.
2. **Request**: A modal dialog is shown, explaining which additional
permissions (e.g., specific directories or network access) are required.
3. **Approval**: If you approve the expansion, the command is executed with the
extended permissions for that specific run.
This mechanism ensures you don't have to manually re-run commands with more
permissive sandbox settings, while still maintaining control over what the AI
can access.
## Quickstart
```bash
+54 -50
View File
@@ -29,8 +29,9 @@ they appear in the UI.
| 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 mode (auto-approve all actions) can only be enabled via command line (--yolo or --approval-mode=yolo). | `"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` |
| Enable Notifications | `general.enableNotifications` | Enable run-event notifications for action-required prompts and session completion. | `false` |
| Enable Plan Mode | `general.plan.enabled` | Enable Plan Mode for read-only safety during planning. | `true` |
| Plan Directory | `general.plan.directory` | The directory where planning artifacts are stored. If not specified, defaults to the system temporary directory. A custom directory requires a policy to allow write access in Plan Mode. | `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` |
| Retry Fetch Errors | `general.retryFetchErrors` | Retry on "exception TypeError: fetch failed sending request" errors. | `true` |
| Max Chat Model Attempts | `general.maxAttempts` | Maximum number of attempts for requests to the main chat model. Cannot exceed 10. | `10` |
@@ -46,38 +47,41 @@ they appear in the UI.
### UI
| UI Label | Setting | Description | Default |
| ------------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
| Show Compatibility Warnings | `ui.showCompatibilityWarnings` | Show warnings about terminal or OS compatibility issues. | `true` |
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
| Escape Pasted @ Symbols | `ui.escapePastedAtSymbols` | When enabled, @ symbols in pasted text are escaped to prevent unintended @path expansion. | `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 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 usage 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 signed-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"` |
| Error Verbosity | `ui.errorVerbosity` | Controls whether recoverable errors are hidden (low) or fully shown (full). | `"low"` |
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
| UI Label | Setting | Description | Default |
| ------------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
| 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` |
| Escape Pasted @ Symbols | `ui.escapePastedAtSymbols` | When enabled, @ symbols in pasted text are escaped to prevent unintended @path expansion. | `false` |
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
| Compact Tool Output | `ui.compactToolOutput` | Display tool outputs (like directory listings and file reads) in a compact, structured format. | `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 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 usage 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 signed-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` |
| Render Process | `ui.renderProcess` | Enable Ink render process for the UI. | `true` |
| Terminal Buffer | `ui.terminalBuffer` | Use the new terminal buffer architecture for rendering. | `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, all, or off. | `"off"` |
| Error Verbosity | `ui.errorVerbosity` | Controls whether recoverable errors are hidden (low) or fully shown (full). | `"low"` |
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
### IDE
@@ -127,7 +131,7 @@ they appear in the UI.
| Sandbox Allowed Paths | `tools.sandboxAllowedPaths` | List of additional paths that the sandbox is allowed to access. | `[]` |
| Sandbox Network Access | `tools.sandboxNetworkAccess` | Whether the sandbox is allowed to access the network. | `false` |
| 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` |
| Show Color | `tools.shell.showColor` | Show color in shell output. | `true` |
| 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` |
@@ -136,7 +140,7 @@ they appear in the UI.
| UI Label | Setting | Description | Default |
| ------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| Tool Sandboxing | `security.toolSandboxing` | Experimental tool-level sandboxing (implementation in progress). | `false` |
| Tool Sandboxing | `security.toolSandboxing` | Tool-level sandboxing. Isolates individual tools instead of the entire CLI process. | `false` |
| Disable YOLO Mode | `security.disableYoloMode` | Disable YOLO mode, even if enabled by a flag. | `false` |
| Disable Always Allow | `security.disableAlwaysAllow` | Disable "Always allow" options in tool confirmation dialogs. | `false` |
| Allow Permanent Tool Approval | `security.enablePermanentToolApproval` | Enable the "Allow for all future sessions" option in tool confirmation dialogs. | `false` |
@@ -149,23 +153,23 @@ they appear in the UI.
### Advanced
| UI Label | Setting | Description | Default |
| --------------------------------- | ------------------------------ | --------------------------------------------- | ------- |
| Auto Configure Max Old Space Size | `advanced.autoConfigureMemory` | Automatically configure Node.js memory limits | `false` |
| UI Label | Setting | Description | Default |
| --------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Auto Configure Max Old Space Size | `advanced.autoConfigureMemory` | Automatically configure Node.js memory limits. Note: Because memory is allocated during the initial process boot, this setting is only read from the global user settings file and ignores workspace-level overrides. | `true` |
### Experimental
| UI Label | Setting | Description | Default |
| -------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Enable Tool Output Masking | `experimental.toolOutputMasking.enabled` | Enables tool output masking to save tokens. | `true` |
| Enable Git Worktrees | `experimental.worktrees` | Enable automated Git worktree management for parallel work. | `false` |
| 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 Plan Mode. | `true` |
| 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` |
| Memory Manager Agent | `experimental.memoryManager` | Replace the built-in save_memory tool with a memory manager subagent that supports adding, removing, de-duplicating, and organizing memories. | `false` |
| Topic & Update Narration | `experimental.topicUpdateNarration` | Enable the experimental Topic & Update communication model for reduced chattiness and structured progress reporting. | `false` |
| UI Label | Setting | Description | Default |
| ---------------------------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| Enable Git Worktrees | `experimental.worktrees` | Enable automated Git worktree management for parallel work. | `false` |
| 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` |
| 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` |
| Memory Manager Agent | `experimental.memoryManager` | Replace the built-in save_memory tool with a memory manager subagent that supports adding, removing, de-duplicating, and organizing memories. | `false` |
| Use the generalist profile to manage agent contexts. | `experimental.generalistProfile` | Suitable for general coding and software development tasks. | `false` |
| Enable Context Management | `experimental.contextManagement` | Enable logic for context management. | `false` |
| Topic & Update Narration | `experimental.topicUpdateNarration` | Enable the experimental Topic & Update communication model for reduced chattiness and structured progress reporting. | `false` |
### Skills
+5
View File
@@ -19,6 +19,7 @@ using the `/theme` command within Gemini CLI:
- `Holiday`
- `Shades Of Purple`
- `Solarized Dark`
- `Tokyo Night`
- **Light themes:**
- `ANSI Light`
- `Ayu Light`
@@ -252,6 +253,10 @@ identify their source, for example: `shades-of-green (green-extension)`.
<img src="/docs/assets/theme-solarized-dark.png" alt="Solarized Dark theme" width="600">
### Tokyo Night
<img src="/docs/assets/theme-tokyonight-dark.png" alt="Tokyo Night theme" width="600">
## Light themes
### ANSI Light
+2 -2
View File
@@ -7,8 +7,8 @@ requests sent from `packages/cli`. For a general overview of Gemini CLI, see the
## Navigating this section
- **[Sub-agents (experimental)](./subagents.md):** Learn how to create and use
specialized sub-agents for complex tasks.
- **[Sub-agents](./subagents.md):** Learn how to create and use specialized
sub-agents for complex tasks.
- **[Core tools reference](../reference/tools.md):** Information on how tools
are defined, registered, and used by the core.
- **[Memory Import Processor](../reference/memport.md):** Documentation for the
+110 -24
View File
@@ -1,4 +1,4 @@
# Remote Subagents (experimental)
# Remote Subagents
Gemini CLI supports connecting to remote subagents using the Agent-to-Agent
(A2A) protocol. This allows Gemini CLI to interact with other agents, expanding
@@ -10,23 +10,6 @@ agents in the following repositories:
- [ADK Samples (Python)](https://github.com/google/adk-samples/tree/main/python)
- [ADK Python Contributing Samples](https://github.com/google/adk-python/tree/main/contributing/samples)
<!-- prettier-ignore -->
> [!NOTE]
> Remote subagents are currently an experimental feature.
## Configuration
To use remote subagents, you must explicitly enable them in your
`settings.json`:
```json
{
"experimental": {
"enableAgents": true
}
}
```
## Proxy support
Gemini CLI routes traffic to remote agents through an HTTP/HTTPS proxy if one is
@@ -51,12 +34,13 @@ You can place them in:
### Configuration schema
| Field | Type | Required | Description |
| :--------------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------- |
| `kind` | string | Yes | Must be `remote`. |
| `name` | string | Yes | A unique name for the agent. Must be a valid slug (lowercase letters, numbers, hyphens, and underscores only). |
| `agent_card_url` | string | Yes | The URL to the agent's A2A card endpoint. |
| `auth` | object | No | Authentication configuration. See [Authentication](#authentication). |
| Field | Type | Required | Description |
| :---------------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------- |
| `kind` | string | Yes | Must be `remote`. |
| `name` | string | Yes | A unique name for the agent. Must be a valid slug (lowercase letters, numbers, hyphens, and underscores only). |
| `agent_card_url` | string | Yes\* | The URL to the agent's A2A card endpoint. Required if `agent_card_json` is not provided. |
| `agent_card_json` | string | Yes\* | The inline JSON string of the agent's A2A card. Required if `agent_card_url` is not provided. |
| `auth` | object | No | Authentication configuration. See [Authentication](#authentication). |
### Single-subagent example
@@ -88,6 +72,95 @@ Markdown file.
> [!NOTE] Mixed local and remote agents, or multiple local agents, are not
> supported in a single file; the list format is currently remote-only.
### Inline Agent Card JSON
<details>
<summary>View formatting options for JSON strings</summary>
If you don't have an endpoint serving the agent card, you can provide the A2A
card directly as a JSON string using `agent_card_json`.
When providing a JSON string in YAML, you must properly format it as a string
scalar. You can use single quotes, a block scalar, or double quotes (which
require escaping internal double quotes).
#### Using single quotes
Single quotes allow you to embed unescaped double quotes inside the JSON string.
This format is useful for shorter, single-line JSON strings.
```markdown
---
kind: remote
name: single-quotes-agent
agent_card_json:
'{ "protocolVersion": "0.3.0", "name": "Example Agent", "version": "1.0.0",
"url": "dummy-url" }'
---
```
#### Using a block scalar
The literal block scalar (`|`) preserves line breaks and is highly recommended
for multiline JSON strings as it avoids quote escaping entirely. The following
is a complete, valid Agent Card configuration using dummy values.
```markdown
---
kind: remote
name: block-scalar-agent
agent_card_json: |
{
"protocolVersion": "0.3.0",
"name": "Example Agent Name",
"description": "An example agent description for documentation purposes.",
"version": "1.0.0",
"url": "dummy-url",
"preferredTransport": "HTTP+JSON",
"capabilities": {
"streaming": true,
"extendedAgentCard": false
},
"defaultInputModes": [
"text/plain"
],
"defaultOutputModes": [
"application/json"
],
"skills": [
{
"id": "ExampleSkill",
"name": "Example Skill Assistant",
"description": "A description of what this example skill does.",
"tags": [
"example-tag"
],
"examples": [
"Show me an example."
]
}
]
}
---
```
#### Using double quotes
Double quotes are also supported, but any internal double quotes in your JSON
must be escaped with a backslash.
```markdown
---
kind: remote
name: double-quotes-agent
agent_card_json:
'{ "protocolVersion": "0.3.0", "name": "Example Agent", "version": "1.0.0",
"url": "dummy-url" }'
---
```
</details>
## Authentication
Many remote agents require authentication. Gemini CLI supports several
@@ -369,3 +442,16 @@ Users can manage subagents using the following commands within the Gemini CLI:
> [!TIP]
> You can use the `@cli_help` agent within Gemini CLI for assistance
> with configuring subagents.
## Disabling remote agents
Remote subagents are enabled by default. To disable them, set `enableAgents` to
`false` in your `settings.json`:
```json
{
"experimental": {
"enableAgents": false
}
}
```
+192 -45
View File
@@ -1,23 +1,10 @@
# Subagents (experimental)
# Subagents
Subagents are specialized agents that operate within your main Gemini CLI
session. They are designed to handle specific, complex tasks—like deep codebase
analysis, documentation lookup, or domain-specific reasoning—without cluttering
the main agent's context or toolset.
<!-- prettier-ignore -->
> [!NOTE]
> Subagents are currently an experimental feature.
>
To use custom subagents, you must ensure they are enabled in your
`settings.json` (enabled by default):
```json
{
"experimental": { "enableAgents": true }
}
```
## What are subagents?
Subagents are "specialists" that the main Gemini agent can hire for a specific
@@ -124,10 +111,12 @@ Gemini CLI comes with the following built-in subagents:
The browser agent requires:
- **Chrome** version 144 or later (any recent stable release will work).
- **Node.js** with `npx` available (used to launch the
[`chrome-devtools-mcp`](https://www.npmjs.com/package/chrome-devtools-mcp)
server).
- **Chrome** version 144 or later (any recent stable release works).
The underlying
[`chrome-devtools-mcp`](https://www.npmjs.com/package/chrome-devtools-mcp)
server is bundled with Gemini CLI and launched automatically — no separate
installation is needed.
#### Enabling the browser agent
@@ -173,26 +162,58 @@ The available modes are:
| `isolated` | Launches Chrome with a temporary profile that is deleted after each session. Use this for clean-state automation. |
| `existing` | Attaches to an already-running Chrome instance. You must enable remote debugging first by navigating to `chrome://inspect/#remote-debugging` in Chrome. No new browser process is launched. |
#### First-run consent
The first time the browser agent is invoked, Gemini CLI displays a consent
dialog. You must accept before the browser session starts. This dialog only
appears once.
#### Configuration reference
All browser-specific settings go under `agents.browser` in your `settings.json`.
For full details, see the
[`agents.browser` configuration reference](../reference/configuration.md#agents).
| Setting | Type | Default | Description |
| :------------ | :-------- | :------------- | :---------------------------------------------------------------------------------------------- |
| `sessionMode` | `string` | `"persistent"` | How Chrome is managed: `"persistent"`, `"isolated"`, or `"existing"`. |
| `headless` | `boolean` | `false` | Run Chrome in headless mode (no visible window). |
| `profilePath` | `string` | — | Custom path to a browser profile directory. |
| `visualModel` | `string` | — | Model override for the visual agent (for example, `"gemini-2.5-computer-use-preview-10-2025"`). |
| Setting | Type | Default | Description |
| :------------------------ | :--------- | :------------- | :------------------------------------------------------------------------------ |
| `sessionMode` | `string` | `"persistent"` | How Chrome is managed: `"persistent"`, `"isolated"`, or `"existing"`. |
| `headless` | `boolean` | `false` | Run Chrome in headless mode (no visible window). |
| `profilePath` | `string` | — | Custom path to a browser profile directory. |
| `visualModel` | `string` | — | Model override for the visual agent. |
| `allowedDomains` | `string[]` | — | Restrict navigation to specific domains (for example, `["github.com"]`). |
| `disableUserInput` | `boolean` | `true` | Disable user input on the browser window during automation (non-headless only). |
| `maxActionsPerTask` | `number` | `100` | Maximum tool calls per task. The agent is terminated when the limit is reached. |
| `confirmSensitiveActions` | `boolean` | `false` | Require manual confirmation for `upload_file` and `evaluate_script`. |
| `blockFileUploads` | `boolean` | `false` | Hard-block all file upload requests from the agent. |
#### Automation overlay and input blocking
In non-headless mode, the browser agent injects a visual overlay into the
browser window to indicate that automation is in progress. By default, user
input (keyboard and mouse) is also blocked to prevent accidental interference.
You can disable this by setting `disableUserInput` to `false`.
#### Security
The browser agent enforces the following security restrictions:
The browser agent enforces several layers of security:
- **Blocked URL patterns:** `file://`, `javascript:`, `data:text/html`,
`chrome://extensions`, and `chrome://settings/passwords` are always blocked.
- **Sensitive action confirmation:** Actions like form filling, file uploads,
and form submissions require user confirmation through the standard policy
engine.
- **Domain restrictions:** When `allowedDomains` is set, the agent can only
navigate to the listed domains (and their subdomains when using `*.` prefix).
Attempting to visit a disallowed domain throws a fatal error that immediately
terminates the agent. The agent also attempts to detect and block the use of
allowed domains as proxies (e.g., via query parameters or fragments) to access
restricted content.
- **Blocked URL patterns:** The underlying MCP server blocks dangerous URL
schemes including `file://`, `javascript:`, `data:text/html`,
`chrome://extensions`, and `chrome://settings/passwords`.
- **Sensitive action confirmation:** Form filling (`fill`, `fill_form`) always
requires user confirmation through the policy engine, regardless of approval
mode. When `confirmSensitiveActions` is `true`, `upload_file` and
`evaluate_script` also require confirmation.
- **File upload blocking:** Set `blockFileUploads` to `true` to hard-block all
file upload requests, preventing the agent from uploading any files.
- **Action rate limiting:** The `maxActionsPerTask` setting (default: 100)
limits the total number of tool calls per task to prevent runaway execution.
#### Visual agent
@@ -226,19 +247,65 @@ the `click_at` tool for precise, coordinate-based interactions.
> The visual agent requires API key or Vertex AI authentication. It is
> not available when using "Sign in with Google".
#### Sandbox support
The browser agent adjusts its behavior automatically when running inside a
sandbox.
##### macOS seatbelt (`sandbox-exec`)
When the CLI runs under the macOS seatbelt sandbox, `persistent` and `isolated`
session modes are forced to `isolated` with `headless` enabled. This avoids
permission errors caused by seatbelt file-system restrictions on persistent
browser profiles. If `sessionMode` is set to `existing`, no override is applied.
##### Container sandboxes (Docker / Podman)
Chrome is not available inside the container, so the browser agent is
**disabled** unless `sessionMode` is set to `"existing"`. When enabled with
`existing` mode, the agent automatically connects to Chrome on the host via the
resolved IP of `host.docker.internal:9222` instead of using local pipe
discovery. Port `9222` is currently hardcoded and cannot be customized.
To use the browser agent in a Docker sandbox:
1. Start Chrome on the host with remote debugging enabled:
```bash
# Option A: Launch Chrome from the command line
google-chrome --remote-debugging-port=9222
# Option B: Enable in Chrome settings
# Navigate to chrome://inspect/#remote-debugging and enable
```
2. Configure `sessionMode` and allowed domains in your project's
`.gemini/settings.json`:
```json
{
"agents": {
"overrides": {
"browser_agent": { "enabled": true }
},
"browser": {
"sessionMode": "existing",
"allowedDomains": ["example.com"]
}
}
}
```
3. Launch the CLI with port forwarding:
```bash
GEMINI_SANDBOX=docker SANDBOX_PORTS=9222 gemini
```
## Creating custom subagents
You can create your own subagents to automate specific workflows or enforce
specific personas. To use custom subagents, you must enable them in your
`settings.json`:
```json
{
"experimental": {
"enableAgents": true
}
}
```
specific personas.
### Agent definition files
@@ -290,6 +357,7 @@ it yourself; just report it.
| `description` | string | Yes | Short description of what the agent does. This is visible to the main agent to help it decide when to call this subagent. |
| `kind` | string | No | `local` (default) or `remote`. |
| `tools` | array | No | List of tool names this agent can use. Supports wildcards: `*` (all tools), `mcp_*` (all MCP tools), `mcp_server_*` (all tools from a server). **If omitted, it inherits all tools from the parent session.** |
| `mcpServers` | object | No | Configuration for inline Model Context Protocol (MCP) servers isolated to this specific agent. |
| `model` | string | No | Specific model to use (e.g., `gemini-3-preview`). Defaults to `inherit` (uses the main session model). |
| `temperature` | number | No | Model temperature (0.0 - 2.0). Defaults to `1`. |
| `max_turns` | number | No | Maximum number of conversation turns allowed for this agent before it must return. Defaults to `30`. |
@@ -317,6 +385,78 @@ Each subagent runs in its own isolated context loop. This means:
subagents **cannot** call other subagents. If a subagent is granted the `*`
tool wildcard, it will still be unable to see or invoke other agents.
## Subagent tool isolation
Subagent tool isolation moves Gemini CLI away from a single global tool
registry. By providing isolated execution environments, you can ensure that
subagents only interact with the parts of the system they are designed for. This
prevents unintended side effects, improves reliability by avoiding state
contamination, and enables fine-grained permission control.
With this feature, you can:
- **Specify tool access:** Define exactly which tools an agent can access using
a `tools` list in the agent definition.
- **Define inline MCP servers:** Configure Model Context Protocol (MCP) servers
(which provide a standardized way to connect AI models to external tools and
data sources) directly in the subagent's markdown frontmatter, isolating them
to that specific agent.
- **Maintain state isolation:** Ensure that subagents only interact with their
own set of tools and servers, preventing side effects and state contamination.
- **Apply subagent-specific policies:** Enforce granular rules in your
[Policy Engine](../reference/policy-engine.md) TOML configuration based on the
executing subagent's name.
### Configuring isolated tools and servers
You can configure tool isolation for a subagent by updating its markdown
frontmatter. This allows you to explicitly state which tools the subagent can
use, rather than relying on the global registry.
Add an `mcpServers` object to define inline MCP servers that are unique to the
agent.
**Example:**
```yaml
---
name: my-isolated-agent
tools:
- grep_search
- read_file
mcpServers:
my-custom-server:
command: 'node'
args: ['path/to/server.js']
---
```
### Subagent-specific policies
You can enforce fine-grained control over subagents using the
[Policy Engine's](../reference/policy-engine.md) TOML configuration. This allows
you to grant or restrict permissions specifically for an agent, without
affecting the rest of your CLI session.
To restrict a policy rule to a specific subagent, add the `subagent` property to
the `[[rules]]` block in your `policy.toml` file.
**Example:**
```toml
[[rules]]
name = "Allow pr-creator to push code"
subagent = "pr-creator"
description = "Permit pr-creator to push branches automatically."
action = "allow"
toolName = "run_shell_command"
commandPrefix = "git push"
```
In this configuration, the policy rule only triggers if the executing subagent's
name matches `pr-creator`. Rules without the `subagent` property apply
universally to all agents.
## Managing subagents
You can manage subagents interactively using the `/agents` command or
@@ -406,15 +546,11 @@ If you need to further tune your subagent, you can do so by selecting the model
to optimize for with `/model` and then asking the model why it does not think
that your subagent was called with a specific prompt and the given description.
## Remote subagents (Agent2Agent) (experimental)
## Remote subagents (Agent2Agent)
Gemini CLI can also delegate tasks to remote subagents using the Agent-to-Agent
(A2A) protocol.
<!-- prettier-ignore -->
> [!NOTE]
> Remote subagents are currently an experimental feature.
See the [Remote Subagents documentation](remote-agents) for detailed
configuration, authentication, and usage instructions.
@@ -423,3 +559,14 @@ configuration, authentication, and usage instructions.
Extensions can bundle and distribute subagents. See the
[Extensions documentation](../extensions/index.md#subagents) for details on how
to package agents within an extension.
## Disabling subagents
Subagents are enabled by default. To disable them, set `enableAgents` to `false`
in your `settings.json`:
```json
{
"experimental": { "enableAgents": false }
}
```
+2 -2
View File
@@ -398,8 +398,8 @@ on this page.
## Running in headless mode <a id="headless"></a>
[Headless mode](../cli/headless) will use your existing authentication method,
if an existing authentication credential is cached.
[Headless mode](../cli/headless.md) will use your existing authentication
method, if an existing authentication credential is cached.
If you have not already signed in with an authentication credential, you must
configure authentication using environment variables:
-141
View File
@@ -1,141 +0,0 @@
# Gemini CLI examples
Gemini CLI helps you automate common engineering tasks by combining AI reasoning
with local system tools. This document provides examples of how to use the CLI
for file management, code analysis, and data transformation.
<!-- prettier-ignore -->
> [!NOTE]
> These examples demonstrate potential capabilities. Your actual
> results can vary based on the model used and your project environment.
## Rename your photographs based on content
You can use Gemini CLI to automate file management tasks that require visual
analysis. In this example, Gemini CLI renames images based on their actual
subject matter.
Scenario: You have a folder containing the following files:
```bash
photos/photo1.png
photos/photo2.png
photos/photo3.png
```
Give Gemini the following prompt:
```cli
Rename the photos in my "photos" directory based on their contents.
```
Result: Gemini asks for permission to rename your files.
Select **Allow once** and your files are renamed:
```bash
photos/yellow_flowers.png
photos/antique_dresser.png
photos/green_android_robot.png
```
## Explain a repository by reading its code
Gemini CLI is effective for rapid codebase exploration. The following example
shows how to ask Gemini CLI to fetch, analyze, and summarize a remote project.
Scenario: You want to understand how a popular open-source utility works by
inspecting its code, not just its README.
Give Gemini CLI the following prompt:
```cli
Clone the 'chalk' repository from https://github.com/chalk/chalk, read its key source files, and explain how it works.
```
Result: Gemini performs a sequence of actions to answer your request.
1. First, it asks for permission to run `git clone` to download the repository.
2. Next, it finds the important source files and asks for permission to read
them.
3. Finally, after analyzing the code, it provides a summary.
Gemini CLI returns an explanation based on the actual source code:
```markdown
The `chalk` library is a popular npm package for styling terminal output with
colors. After analyzing the source code, here's how it works:
- **Core functionality:** The main file sets up a chainable API. Each color or
modifier (like `bold` or `italic`) is a getter that appends the corresponding
ANSI escape code to an internal stack.
- **Chainable API:** When you call `chalk.red.bold('Hello')`, you are accessing
getters. The `red` getter adds the red color code, and the `bold` getter adds
the bold code.
- **Output generation:** When the chain is treated as a string (e.g., in
`console.log`), a final `toString()` method is called. This method joins all
the stored ANSI codes, wraps them around the input string ('Hello'), and adds
a reset code at the end. This produces the final, styled string that the
terminal can render.
```
## Combine two spreadsheets into one spreadsheet
Gemini CLI can process and transform data across multiple files. Use this
capability to merge reports or reformat data sets without manual copying.
Scenario: You have two .csv files: `Revenue - 2023.csv` and
`Revenue - 2024.csv`. Each file contains monthly revenue figures.
Give Gemini CLI the following prompt:
```cli
Combine the two .csv files into a single .csv file, with each year a different column.
```
Result: Gemini CLI reads each file and then asks for permission to write a new
file. Provide your permission and Gemini CLI provides the combined data:
```csv
Month,2023,2024
January,0,1000
February,0,1200
March,0,2400
April,900,500
May,1000,800
June,1000,900
July,1200,1000
August,1800,400
September,2000,2000
October,2400,3400
November,3400,1800
December,2100,9000
```
## Run unit tests
Gemini CLI can generate boilerplate code and tests based on your existing
implementation. This example demonstrates how to request code coverage for a
JavaScript component.
Scenario: You've written a simple login page. You wish to write unit tests to
ensure that your login page has code coverage.
Give Gemini CLI the following prompt:
```cli
Write unit tests for Login.js.
```
Result: Gemini CLI asks for permission to write a new file and creates a test
for your login page.
## Next steps
- Follow the [File management](../cli/tutorials/file-management.md) guide to
start working with your codebase.
- Follow the [Quickstart](./index.md) to start your first session.
- See the [Cheatsheet](../cli/cli-reference.md) for a quick reference of
available commands.
+1 -1
View File
@@ -1,6 +1,6 @@
# Gemini 3 Pro and Gemini 3 Flash on Gemini CLI
Gemini 3 Pro and Gemini 3 Flash are available on Gemini CLI for all users!
Learn about how you can use Gemini 3 Pro and Gemini 3 Flash on Gemini CLI.
<!-- prettier-ignore -->
> [!NOTE]
+127 -1
View File
@@ -62,7 +62,133 @@ Once installed and authenticated, you can start using Gemini CLI by issuing
commands and prompts in your terminal. Ask it to generate code, explain files,
and more.
To explore the power of Gemini CLI, see [Gemini CLI examples](./examples.md).
<!-- prettier-ignore -->
> [!NOTE]
> These examples demonstrate potential capabilities. Your actual
> results can vary based on the model used and your project environment.
### Rename your photographs based on content
You can use Gemini CLI to automate file management tasks that require visual
analysis. In this example, Gemini CLI renames images based on their actual
subject matter.
Scenario: You have a folder containing the following files:
```bash
photos/photo1.png
photos/photo2.png
photos/photo3.png
```
Give Gemini the following prompt:
```cli
Rename the photos in my "photos" directory based on their contents.
```
Result: Gemini asks for permission to rename your files.
Select **Allow once** and your files are renamed:
```bash
photos/yellow_flowers.png
photos/antique_dresser.png
photos/green_android_robot.png
```
### Explain a repository by reading its code
Gemini CLI is effective for rapid codebase exploration. The following example
shows how to ask Gemini CLI to fetch, analyze, and summarize a remote project.
Scenario: You want to understand how a popular open-source utility works by
inspecting its code, not just its README.
Give Gemini CLI the following prompt:
```cli
Clone the 'chalk' repository from https://github.com/chalk/chalk, read its key source files, and explain how it works.
```
Result: Gemini performs a sequence of actions to answer your request.
1. First, it asks for permission to run `git clone` to download the repository.
2. Next, it finds the important source files and asks for permission to read
them.
3. Finally, after analyzing the code, it provides a summary.
Gemini CLI returns an explanation based on the actual source code:
```markdown
The `chalk` library is a popular npm package for styling terminal output with
colors. After analyzing the source code, here's how it works:
- **Core functionality:** The main file sets up a chainable API. Each color or
modifier (like `bold` or `italic`) is a getter that appends the corresponding
ANSI escape code to an internal stack.
- **Chainable API:** When you call `chalk.red.bold('Hello')`, you are accessing
getters. The `red` getter adds the red color code, and the `bold` getter adds
the bold code.
- **Output generation:** When the chain is treated as a string (e.g., in
`console.log`), a final `toString()` method is called. This method joins all
the stored ANSI codes, wraps them around the input string ('Hello'), and adds
a reset code at the end. This produces the final, styled string that the
terminal can render.
```
### Combine two spreadsheets into one spreadsheet
Gemini CLI can process and transform data across multiple files. Use this
capability to merge reports or reformat data sets without manual copying.
Scenario: You have two .csv files: `Revenue - 2023.csv` and
`Revenue - 2024.csv`. Each file contains monthly revenue figures.
Give Gemini CLI the following prompt:
```cli
Combine the two .csv files into a single .csv file, with each year a different column.
```
Result: Gemini CLI reads each file and then asks for permission to write a new
file. Provide your permission and Gemini CLI provides the combined data:
```csv
Month,2023,2024
January,0,1000
February,0,1200
March,0,2400
April,900,500
May,1000,800
June,1000,900
July,1200,1000
August,1800,400
September,2000,2000
October,2400,3400
November,3400,1800
December,2100,9000
```
### Run unit tests
Gemini CLI can generate boilerplate code and tests based on your existing
implementation. This example demonstrates how to request code coverage for a
JavaScript component.
Scenario: You've written a simple login page. You wish to write unit tests to
ensure that your login page has code coverage.
Give Gemini CLI the following prompt:
```cli
Write unit tests for Login.js.
```
Result: Gemini CLI asks for permission to write a new file and creates a test
for your login page.
## Check usage and quota
+7
View File
@@ -122,6 +122,13 @@ code.
# From the root of the repository
npm run start
```
- **Production mode (React optimizations):** This method runs the CLI with React
production mode enabled, which is useful for testing performance without
development overhead.
```bash
# From the root of the repository
npm run start:prod
```
- **Production-like mode (linked package):** This method simulates a global
installation by linking your local package. It's useful for testing a local
build in a production workflow.
+6 -6
View File
@@ -22,11 +22,11 @@ With hooks, you can:
### Getting started
- **[Writing hooks guide](../hooks/writing-hooks)**: A tutorial on creating your
first hook with comprehensive examples.
- **[Best practices](../hooks/best-practices)**: Guidelines on security,
- **[Writing hooks guide](../hooks/writing-hooks.md)**: A tutorial on creating
your first hook with comprehensive examples.
- **[Best practices](../hooks/best-practices.md)**: Guidelines on security,
performance, and debugging.
- **[Hooks reference](../hooks/reference)**: The definitive technical
- **[Hooks reference](../hooks/reference.md)**: The definitive technical
specification of I/O schemas and exit codes.
## Core concepts
@@ -154,8 +154,8 @@ Gemini CLI **fingerprints** project hooks. If a hook's name or command changes
(e.g., via `git pull`), it is treated as a **new, untrusted hook** and you will
be warned before it executes.
See [Security Considerations](../hooks/best-practices#using-hooks-securely) for
a detailed threat model.
See [Security Considerations](../hooks/best-practices.md#using-hooks-securely)
for a detailed threat model.
## Managing hooks
+99 -24
View File
@@ -1,15 +1,29 @@
# IDE integration
# IDE Integration
Gemini CLI can integrate with your IDE to provide a more seamless and
context-aware experience. This integration allows the CLI to understand your
workspace better and enables powerful features like native in-editor diffing.
Currently, the supported IDEs are [Antigravity](https://antigravity.google),
[Visual Studio Code](https://code.visualstudio.com/), and other editors that
support VS Code extensions. To build support for other editors, see the
[IDE Companion Extension Spec](./ide-companion-spec.md).
There are two primary ways to integrate Gemini CLI with an IDE:
## Features
1. **VS Code companion extension**: Install the "Gemini CLI Companion"
extension on [Antigravity](https://antigravity.google),
[Visual Studio Code](https://code.visualstudio.com/), or other VS Code
compatible editors.
2. **Agent Client Protocol (ACP)**: An open protocol for interoperability
between AI coding agents and IDEs. This method is used for integrations with
tools like JetBrains and Zed, which leverage the ACP Agent Registry for easy
discovery and installation of compatible agents like Gemini CLI.
## VS Code companion extension
The **Gemini CLI Companion extension** grants Gemini CLI direct access to your
VS Code compatible IDEs and improves your experience by providing real-time
context such as open files, cursor positions, and text selection. The extension
also enables a native diffing interface so you can seamlessly review and apply
AI-generated code changes directly within your editor.
### Features
- **Workspace context:** The CLI automatically gains awareness of your workspace
to provide more relevant and accurate responses. This context includes:
@@ -19,8 +33,8 @@ support VS Code extensions. To build support for other editors, see the
truncated).
- **Native diffing:** When Gemini suggests code modifications, you can view the
changes directly within your IDE's native diff viewer. This allows you to
review, edit, and accept or reject the suggested changes seamlessly.
changes directly within your IDE's native diff viewer. This lets you review,
edit, and accept or reject the suggested changes seamlessly.
- **VS Code commands:** You can access Gemini CLI features directly from the VS
Code Command Palette (`Cmd+Shift+P` or `Ctrl+Shift+P`):
@@ -32,18 +46,18 @@ support VS Code extensions. To build support for other editors, see the
- `Gemini CLI: View Third-Party Notices`: Displays the third-party notices for
the extension.
## Installation and setup
### Installation and setup
There are three ways to set up the IDE integration:
### 1. Automatic nudge (recommended)
#### 1. Automatic nudge (recommended)
When you run Gemini CLI inside a supported editor, it will automatically detect
your environment and prompt you to connect. Answering "Yes" will automatically
run the necessary setup, which includes installing the companion extension and
enabling the connection.
### 2. Manual installation from CLI
#### 2. Manual installation from CLI
If you previously dismissed the prompt or want to install the extension
manually, you can run the following command inside Gemini CLI:
@@ -54,7 +68,7 @@ manually, you can run the following command inside Gemini CLI:
This will find the correct extension for your IDE and install it.
### 3. Manual installation from a marketplace
#### 3. Manual installation from a marketplace
You can also install the extension directly from a marketplace.
@@ -75,9 +89,9 @@ You can also install the extension directly from a marketplace.
> After manually installing the extension, you must run `/ide enable` in the CLI
> to activate the integration.
## Usage
### Usage
### Enabling and disabling
#### Enabling and disabling
You can control the IDE integration from within the CLI:
@@ -93,7 +107,7 @@ You can control the IDE integration from within the CLI:
When enabled, Gemini CLI will automatically attempt to connect to the IDE
companion extension.
### Checking the status
#### Checking the status
To check the connection status and see the context the CLI has received from the
IDE, run:
@@ -108,9 +122,9 @@ recently opened files it is aware of.
<!-- prettier-ignore -->
> [!NOTE]
> The file list is limited to 10 recently accessed files within your
> workspace and only includes local files on disk.)
> workspace and only includes local files on disk.
### Working with diffs
#### Working with diffs
When you ask Gemini to modify a file, it can open a diff view directly in your
editor.
@@ -135,6 +149,63 @@ accepting them.
If you select Allow for this session in the CLI, changes will no longer show
up in the IDE as they will be auto-accepted.
## Agent Client Protocol (ACP)
ACP is an open protocol that standardizes how AI coding agents communicate with
code editors and IDEs. It addresses the challenge of fragmented distribution,
where agents traditionally needed custom integrations for each client. With ACP,
developers can implement their agent once, and it becomes compatible with any
ACP-compliant editor.
For a comprehensive introduction to ACP, including its architecture and
benefits, refer to the official
[ACP Introduction](https://agentclientprotocol.com/get-started/introduction)
documentation.
### The ACP Agent Registry
Gemini CLI is officially available in the **ACP Agent Registry**. This allows
you to install and update Gemini CLI directly within supporting IDEs and
eliminates the need for manual downloads or IDE-specific extensions.
Using the registry ensures:
- **Ease of use**: Discover and install agents directly within your IDE
settings.
- **Latest versions**: Ensures users always have access to the most up-to-date
agent implementations.
For more details on how the registry works, visit the official
[ACP Agent Registry](https://agentclientprotocol.com/get-started/registry) page.
You can learn about how specific IDEs leverage this integration in the following
section.
### IDE-specific integration
Gemini CLI is an ACP-compatible agent available in the ACP Agent Registry.
Heres how different IDEs leverage the ACP and the registry:
#### JetBrains IDEs
JetBrains IDEs (like IntelliJ IDEA, PyCharm, or GoLand) offer built-in registry
support, allowing users to find and install ACP-compatible agents directly.
For more details, refer to the official
[JetBrains AI Blog announcement](https://blog.jetbrains.com/ai/2026/01/acp-agent-registry/).
#### Zed
Zed, a modern code editor, also integrates with the ACP Agent Registry. This
allows Zed users to easily browse, install, and manage ACP agents.
Learn more about Zed's integration with the ACP Registry in their
[blog post](https://zed.dev/blog/acp-registry).
#### Other ACP-compatible IDEs
Any other IDE that supports the ACP Agent Registry can install Gemini CLI
directly through their in-built registry features.
## Using with sandboxing
If you are using Gemini CLI within a sandbox, please be aware of the following:
@@ -151,10 +222,9 @@ If you are using Gemini CLI within a sandbox, please be aware of the following:
## Troubleshooting
If you encounter issues with IDE integration, here are some common error
messages and how to resolve them.
### VS Code companion extension errors
### Connection errors
#### Connection errors
- **Message:**
`🔴 Disconnected: Failed to connect to IDE companion extension in [IDE Name]. Please ensure the extension is running. To install the extension, run /ide install.`
@@ -174,7 +244,7 @@ messages and how to resolve them.
- **Solution:** Run `/ide enable` to try and reconnect. If the issue
continues, open a new terminal window or restart your IDE.
### Manual PID override
#### Manual PID override
If automatic IDE detection fails, or if you are running Gemini CLI in a
standalone terminal and want to manually associate it with a specific IDE
@@ -196,7 +266,7 @@ $env:GEMINI_CLI_IDE_PID=12345
When this variable is set, Gemini CLI will skip automatic detection and attempt
to connect using the provided PID.
### Configuration errors
#### Configuration errors
- **Message:**
`🔴 Disconnected: Directory mismatch. Gemini CLI is running in a different location than the open workspace in [IDE Name]. Please run the CLI from one of the following directories: [List of directories]`
@@ -210,7 +280,7 @@ to connect using the provided PID.
- **Cause:** You have no workspace open in your IDE.
- **Solution:** Open a workspace in your IDE and restart the CLI.
### General errors
#### General errors
- **Message:**
`IDE integration is not supported in your current environment. To use this feature, run Gemini CLI in one of these supported IDEs: [List of IDEs]`
@@ -220,9 +290,14 @@ to connect using the provided PID.
IDE, like Antigravity or VS Code.
- **Message:**
`No installer is available for IDE. Please install the Gemini CLI Companion extension manually from the marketplace.`
`No installer is available for IDE. Please install Gemini CLI Companion extension manually from the marketplace.`
- **Cause:** You ran `/ide install`, but the CLI does not have an automated
installer for your specific IDE.
- **Solution:** Open your IDE's extension marketplace, search for "Gemini CLI
Companion", and
[install it manually](#3-manual-installation-from-a-marketplace).
### ACP integration errors
For issues related to ACP integration, please refer to the debugging and
telemetry section in the [ACP Mode](../cli/acp-mode.md) documentation.
-2
View File
@@ -19,8 +19,6 @@ Jump in to Gemini CLI.
on your system.
- **[Authentication](./get-started/authentication.md):** Setup instructions for
personal and enterprise accounts.
- **[Examples](./get-started/examples.md):** Practical examples of Gemini CLI in
action.
- **[CLI cheatsheet](./cli/cli-reference.md):** A quick reference for common
commands and options.
- **[Gemini 3 on Gemini CLI](./get-started/gemini-3.md):** Learn about Gemini 3
+82
View File
@@ -117,6 +117,88 @@ npm run test:integration:sandbox:docker
npm run test:integration:sandbox:podman
```
## Memory regression tests
Memory regression tests are designed to detect heap growth and leaks across key
CLI scenarios. They are located in the `memory-tests` directory.
These tests are distinct from standard integration tests because they measure
memory usage and compare it against committed baselines.
### Running memory tests
Memory tests are not run as part of the default `npm run test` or
`npm run test:e2e` commands. They are run nightly in CI but can be run manually:
```bash
npm run test:memory
```
### Updating baselines
If you intentionally change behavior that affects memory usage, you may need to
update the baselines. Set the `UPDATE_MEMORY_BASELINES` environment variable to
`true`:
```bash
UPDATE_MEMORY_BASELINES=true npm run test:memory
```
This will run the tests, take median snapshots, and overwrite
`memory-tests/baselines.json`. You should review the changes and commit the
updated baseline file.
### How it works
The harness (`MemoryTestHarness` in `packages/test-utils`):
- Forces garbage collection multiple times to reduce noise.
- Takes median snapshots to filter spikes.
- Compares against baselines with a 10% tolerance.
- Can analyze sustained leaks across 3 snapshots using `analyzeSnapshots()`.
## Performance regression tests
Performance regression tests are designed to detect wall-clock time, CPU usage,
and event loop delay regressions across key CLI scenarios. They are located in
the `perf-tests` directory.
These tests are distinct from standard integration tests because they measure
performance metrics and compare it against committed baselines.
### Running performance tests
Performance tests are not run as part of the default `npm run test` or
`npm run test:e2e` commands. They are run nightly in CI but can be run manually:
```bash
npm run test:perf
```
### Updating baselines
If you intentionally change behavior that affects performance, you may need to
update the baselines. Set the `UPDATE_PERF_BASELINES` environment variable to
`true`:
```bash
UPDATE_PERF_BASELINES=true npm run test:perf
```
This will run the tests multiple times (with warmup), apply IQR outlier
filtering, and overwrite `perf-tests/baselines.json`. You should review the
changes and commit the updated baseline file.
### How it works
The harness (`PerfTestHarness` in `packages/test-utils`):
- Measures wall-clock time using `performance.now()`.
- Measures CPU usage using `process.cpuUsage()`.
- Monitors event loop delay using `perf_hooks.monitorEventLoopDelay()`.
- Applies IQR (Interquartile Range) filtering to remove outlier samples.
- Compares against baselines with a 15% tolerance.
## Diagnostics
The integration test runner provides several options for diagnostics to help
+1
View File
@@ -13,6 +13,7 @@
"/docs/faq": "/docs/resources/faq",
"/docs/get-started/configuration": "/docs/reference/configuration",
"/docs/get-started/configuration-v1": "/docs/reference/configuration",
"/docs/get-started/examples": "/docs/get-started/index",
"/docs/index": "/docs",
"/docs/quota-and-pricing": "/docs/resources/quota-and-pricing",
"/docs/tos-privacy": "/docs/resources/tos-privacy",
+1 -3
View File
@@ -17,8 +17,6 @@ Slash commands provide meta-level control over the CLI itself.
### `/agents`
- **Description:** Manage local and remote subagents.
- **Note:** This command is experimental and requires
`experimental.enableAgents: true` in your `settings.json`.
- **Sub-commands:**
- **`list`**:
- **Description:** Lists all discovered agents, including built-in, local,
@@ -305,7 +303,7 @@ Slash commands provide meta-level control over the CLI itself.
- **Description:** Switch to Plan Mode (read-only) and view the current plan if
one has been generated.
- **Note:** This feature is enabled by default. It can be disabled via the
`experimental.plan` setting in your configuration.
`general.plan.enabled` setting in your configuration.
- **Sub-commands:**
- **`copy`**:
- **Description:** Copy the currently approved plan to your clipboard.
+240 -103
View File
@@ -62,11 +62,13 @@ locations for these files:
**Note on environment variables in settings:** String values within your
`settings.json` and `gemini-extension.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"`. Additionally, each extension can have its own
`.env` file in its directory, which will be loaded automatically.
variables using `$VAR_NAME`, `${VAR_NAME}`, or `${VAR_NAME:-DEFAULT_VALUE}`
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"`. If you
want to provide a fallback value, use `${MY_API_TOKEN:-default-token}`.
Additionally, each extension can have its own `.env` file in its directory,
which will be loaded automatically.
**Note for Enterprise Users:** For guidance on deploying and managing Gemini CLI
in a corporate environment, please see the
@@ -133,7 +135,7 @@ their corresponding top-level category object in your `settings.json` file.
- **`general.enableNotifications`** (boolean):
- **Description:** Enable run-event notifications for action-required prompts
and session completion. Currently macOS only.
and session completion.
- **Default:** `false`
- **`general.checkpointing.enabled`** (boolean):
@@ -141,9 +143,15 @@ their corresponding top-level category object in your `settings.json` file.
- **Default:** `false`
- **Requires restart:** Yes
- **`general.plan.enabled`** (boolean):
- **Description:** Enable Plan Mode for read-only safety during planning.
- **Default:** `true`
- **Requires restart:** Yes
- **`general.plan.directory`** (string):
- **Description:** The directory where planning artifacts are stored. If not
specified, defaults to the system temporary directory.
specified, defaults to the system temporary directory. A custom directory
requires a policy to allow write access in Plan Mode.
- **Default:** `undefined`
- **Requires restart:** Yes
@@ -256,6 +264,11 @@ their corresponding top-level category object in your `settings.json` file.
- **Description:** Show the "? for shortcuts" hint above the input.
- **Default:** `true`
- **`ui.compactToolOutput`** (boolean):
- **Description:** Display tool outputs (like directory listings and file
reads) in a compact, structured format.
- **Default:** `true`
- **`ui.hideBanner`** (boolean):
- **Description:** Hide the application banner
- **Default:** `false`
@@ -326,6 +339,16 @@ their corresponding top-level category object in your `settings.json` file.
- **Default:** `false`
- **Requires restart:** Yes
- **`ui.renderProcess`** (boolean):
- **Description:** Enable Ink render process for the UI.
- **Default:** `true`
- **Requires restart:** Yes
- **`ui.terminalBuffer`** (boolean):
- **Description:** Use the new terminal buffer architecture for rendering.
- **Default:** `false`
- **Requires restart:** Yes
- **`ui.useBackgroundColor`** (boolean):
- **Description:** Whether to use background colors in the UI.
- **Default:** `true`
@@ -343,8 +366,8 @@ their corresponding top-level category object in your `settings.json` file.
- **`ui.loadingPhrases`** (enum):
- **Description:** What to show while the model is working: tips, witty
comments, both, or nothing.
- **Default:** `"tips"`
comments, all, or off.
- **Default:** `"off"`
- **Values:** `"tips"`, `"witty"`, `"all"`, `"off"`
- **`ui.errorVerbosity`** (enum):
@@ -645,6 +668,11 @@ their corresponding top-level category object in your `settings.json` file.
"model": "gemini-3-flash-preview"
}
},
"chat-compression-3.1-flash-lite": {
"modelConfig": {
"model": "gemini-3.1-flash-lite-preview"
}
},
"chat-compression-2.5-pro": {
"modelConfig": {
"model": "gemini-2.5-pro"
@@ -664,6 +692,11 @@ their corresponding top-level category object in your `settings.json` file.
"modelConfig": {
"model": "gemini-3-pro-preview"
}
},
"agent-history-provider-summarizer": {
"modelConfig": {
"model": "gemini-3-flash-preview"
}
}
}
```
@@ -979,6 +1012,17 @@ their corresponding top-level category object in your `settings.json` file.
"auto-gemini-2.5": {
"default": "gemini-2.5-pro"
},
"gemini-3.1-flash-lite-preview": {
"default": "gemini-3.1-flash-lite-preview",
"contexts": [
{
"condition": {
"useGemini3_1FlashLite": false
},
"target": "gemini-2.5-flash-lite"
}
]
},
"flash": {
"default": "gemini-3-flash-preview",
"contexts": [
@@ -991,7 +1035,15 @@ their corresponding top-level category object in your `settings.json` file.
]
},
"flash-lite": {
"default": "gemini-2.5-flash-lite"
"default": "gemini-2.5-flash-lite",
"contexts": [
{
"condition": {
"useGemini3_1FlashLite": true
},
"target": "gemini-3.1-flash-lite-preview"
}
]
}
}
```
@@ -1202,7 +1254,8 @@ their corresponding top-level category object in your `settings.json` file.
- **Requires restart:** Yes
- **`agents.browser.visualModel`** (string):
- **Description:** Model override for the visual agent.
- **Description:** Model for the visual agent's analyze_screenshot tool. When
set, enables the tool.
- **Default:** `undefined`
- **Requires restart:** Yes
@@ -1257,6 +1310,18 @@ their corresponding top-level category object in your `settings.json` file.
- **Description:** Maximum number of directories to search for memory.
- **Default:** `200`
- **`context.memoryBoundaryMarkers`** (array):
- **Description:** File or directory names that mark the boundary for
GEMINI.md discovery. The upward traversal stops at the first directory
containing any of these markers. An empty array disables parent traversal.
- **Default:**
```json
[".git"]
```
- **Requires restart:** Yes
- **`context.includeDirectories`** (array):
- **Description:** Additional directories to include in the workspace context.
Missing directories will be skipped with a warning.
@@ -1324,6 +1389,14 @@ their corresponding top-level category object in your `settings.json` file.
- **Default:** `true`
- **Requires restart:** Yes
- **`tools.shell.backgroundCompletionBehavior`** (enum):
- **Description:** Controls what happens when a background shell command
finishes. 'silent' (default): quietly exits in background. 'inject':
automatically returns output to agent. 'notify': shows brief message in
chat.
- **Default:** `"silent"`
- **Values:** `"silent"`, `"inject"`, `"notify"`
- **`tools.shell.pager`** (string):
- **Description:** The pager command to use for shell output. Defaults to
`cat`.
@@ -1331,7 +1404,7 @@ their corresponding top-level category object in your `settings.json` file.
- **`tools.shell.showColor`** (boolean):
- **Description:** Show color in shell output.
- **Default:** `false`
- **Default:** `true`
- **`tools.shell.inactivityTimeout`** (number):
- **Description:** The maximum time in seconds allowed without output from the
@@ -1419,9 +1492,10 @@ their corresponding top-level category object in your `settings.json` file.
#### `security`
- **`security.toolSandboxing`** (boolean):
- **Description:** Experimental tool-level sandboxing (implementation in
progress).
- **Description:** Tool-level sandboxing. Isolates individual tools instead of
the entire CLI process.
- **Default:** `false`
- **Requires restart:** Yes
- **`security.disableYoloMode`** (boolean):
- **Description:** Disable YOLO mode, even if enabled by a flag.
@@ -1504,8 +1578,11 @@ their corresponding top-level category object in your `settings.json` file.
#### `advanced`
- **`advanced.autoConfigureMemory`** (boolean):
- **Description:** Automatically configure Node.js memory limits
- **Default:** `false`
- **Description:** Automatically configure Node.js memory limits. Note:
Because memory is allocated during the initial process boot, this setting is
only read from the global user settings file and ignores workspace-level
overrides.
- **Default:** `true`
- **Requires restart:** Yes
- **`advanced.dnsResolutionOrder`** (string):
@@ -1527,26 +1604,15 @@ their corresponding top-level category object in your `settings.json` file.
#### `experimental`
- **`experimental.toolOutputMasking.enabled`** (boolean):
- **Description:** Enables tool output masking to save tokens.
- **Default:** `true`
- **`experimental.adk.agentSessionNoninteractiveEnabled`** (boolean):
- **Description:** Enable non-interactive agent sessions.
- **Default:** `false`
- **Requires restart:** Yes
- **`experimental.toolOutputMasking.toolProtectionThreshold`** (number):
- **Description:** Minimum number of tokens to protect from masking (most
recent tool outputs).
- **Default:** `50000`
- **Requires restart:** Yes
- **`experimental.toolOutputMasking.minPrunableTokensThreshold`** (number):
- **Description:** Minimum prunable tokens required to trigger a masking pass.
- **Default:** `30000`
- **Requires restart:** Yes
- **`experimental.toolOutputMasking.protectLatestTurn`** (boolean):
- **Description:** Ensures the absolute latest turn is never masked,
regardless of token count.
- **Default:** `true`
- **`experimental.adk.agentSessionInteractiveEnabled`** (boolean):
- **Description:** Enable the agent session implementation for the interactive
CLI.
- **Default:** `false`
- **Requires restart:** Yes
- **`experimental.enableAgents`** (boolean):
@@ -1587,7 +1653,7 @@ their corresponding top-level category object in your `settings.json` file.
- **`experimental.jitContext`** (boolean):
- **Description:** Enable Just-In-Time (JIT) context loading.
- **Default:** `true`
- **Default:** `false`
- **Requires restart:** Yes
- **`experimental.useOSC52Paste`** (boolean):
@@ -1602,11 +1668,6 @@ their corresponding top-level category object in your `settings.json` file.
configured to allow it).
- **Default:** `false`
- **`experimental.plan`** (boolean):
- **Description:** Enable Plan Mode.
- **Default:** `true`
- **Requires restart:** Yes
- **`experimental.taskTracker`** (boolean):
- **Description:** Enable task tracker tools.
- **Default:** `false`
@@ -1652,6 +1713,16 @@ their corresponding top-level category object in your `settings.json` file.
- **Default:** `false`
- **Requires restart:** Yes
- **`experimental.generalistProfile`** (boolean):
- **Description:** Suitable for general coding and software development tasks.
- **Default:** `false`
- **Requires restart:** Yes
- **`experimental.contextManagement`** (boolean):
- **Description:** Enable logic for context management.
- **Default:** `false`
- **Requires restart:** Yes
- **`experimental.topicUpdateNarration`** (boolean):
- **Description:** Enable the experimental Topic & Update communication model
for reduced chattiness and structured progress reporting.
@@ -1743,6 +1814,69 @@ their corresponding top-level category object in your `settings.json` file.
prioritize available tools dynamically.
- **Default:** `[]`
#### `contextManagement`
- **`contextManagement.historyWindow.maxTokens`** (number):
- **Description:** The number of tokens to allow before triggering
compression.
- **Default:** `150000`
- **Requires restart:** Yes
- **`contextManagement.historyWindow.retainedTokens`** (number):
- **Description:** The number of tokens to always retain.
- **Default:** `40000`
- **Requires restart:** Yes
- **`contextManagement.messageLimits.normalMaxTokens`** (number):
- **Description:** The target number of tokens to budget for a normal
conversation turn.
- **Default:** `2500`
- **Requires restart:** Yes
- **`contextManagement.messageLimits.retainedMaxTokens`** (number):
- **Description:** The maximum number of tokens a single conversation turn can
consume before truncation.
- **Default:** `12000`
- **Requires restart:** Yes
- **`contextManagement.messageLimits.normalizationHeadRatio`** (number):
- **Description:** The ratio of tokens to retain from the beginning of a
truncated message (0.0 to 1.0).
- **Default:** `0.25`
- **Requires restart:** Yes
- **`contextManagement.tools.distillation.maxOutputTokens`** (number):
- **Description:** Maximum tokens to show to the model when truncating large
tool outputs.
- **Default:** `10000`
- **Requires restart:** Yes
- **`contextManagement.tools.distillation.summarizationThresholdTokens`**
(number):
- **Description:** Threshold above which truncated tool outputs will be
summarized by an LLM.
- **Default:** `20000`
- **Requires restart:** Yes
- **`contextManagement.tools.outputMasking.protectionThresholdTokens`**
(number):
- **Description:** Minimum number of tokens to protect from masking (most
recent tool outputs).
- **Default:** `50000`
- **Requires restart:** Yes
- **`contextManagement.tools.outputMasking.minPrunableThresholdTokens`**
(number):
- **Description:** Minimum prunable tokens required to trigger a masking pass.
- **Default:** `30000`
- **Requires restart:** Yes
- **`contextManagement.tools.outputMasking.protectLatestTurn`** (boolean):
- **Description:** Ensures the absolute latest turn is never masked,
regardless of token count.
- **Default:** `true`
- **Requires restart:** Yes
#### `admin`
- **`admin.secureModeEnabled`** (boolean):
@@ -2135,37 +2269,14 @@ You can customize this behavior in your `settings.json` file:
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-3-pro-preview`
- **`--prompt <your_prompt>`** (**`-p <your_prompt>`**):
- **Deprecated:** Use positional arguments instead.
- 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"`
- **`--output-format <format>`**:
- **Description:** Specifies the format of the CLI output for non-interactive
mode.
- **Values:**
- `text`: (Default) The standard human-readable output.
- `json`: A machine-readable JSON output.
- `stream-json`: A streaming JSON output that emits real-time events.
- **Note:** For structured output and scripting, use the
`--output-format json` or `--output-format stream-json` flag.
- **`--sandbox`** (**`-s`**):
- Enables sandbox mode for this session.
- **`--debug`** (**`-d`**):
- Enables debug mode for this session, providing more verbose output. Open the
debug console with F12 to see the additional logging.
- **`--help`** (or **`-h`**):
- Displays help information about command-line arguments.
- **`--yolo`**:
- Enables YOLO mode, which automatically approves all tool calls.
- **`--acp`**:
- Starts the agent in Agent Communication Protocol (ACP) mode.
- **`--allowed-mcp-server-names`**:
- A comma-separated list of MCP server names to allow for the session.
- **`--allowed-tools <tool1,tool2,...>`**:
- A comma-separated list of tool names that will bypass the confirmation
dialog.
- Example: `gemini --allowed-tools "ShellTool(git status)"`
- **`--approval-mode <mode>`**:
- Sets the approval mode for tool calls. Available modes:
- `default`: Prompt for approval on each tool call (default behavior)
@@ -2179,35 +2290,24 @@ for that specific session.
- Cannot be used together with `--yolo`. Use `--approval-mode=yolo` instead of
`--yolo` for the new unified approach.
- Example: `gemini --approval-mode auto_edit`
- **`--allowed-tools <tool1,tool2,...>`**:
- A comma-separated list of tool names that will bypass the confirmation
dialog.
- Example: `gemini --allowed-tools "ShellTool(git status)"`
- **`--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.
- **`--resume [session_id]`** (**`-r [session_id]`**):
- Resume a previous chat session. Use "latest" for the most recent session,
provide a session index number, or provide a full session UUID.
- If no session_id is provided, defaults to "latest".
- Example: `gemini --resume 5` or `gemini --resume latest` or
`gemini --resume a1b2c3d4-e5f6-7890-abcd-ef1234567890` or `gemini --resume`
- See [Session Management](../cli/session-management.md) for more details.
- **`--list-sessions`**:
- List all available chat sessions for the current project and exit.
- Shows session indices, dates, message counts, and preview of first user
message.
- Example: `gemini --list-sessions`
- **`--debug`** (**`-d`**):
- Enables debug mode for this session, providing more verbose output. Open the
debug console with F12 to see the additional logging.
- **`--delete-session <identifier>`**:
- Delete a specific chat session by its index number or full session UUID.
- Use `--list-sessions` first to see available sessions, their indices, and
UUIDs.
- Example: `gemini --delete-session 3` or
`gemini --delete-session a1b2c3d4-e5f6-7890-abcd-ef1234567890`
- **`--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`
- **`--fake-responses`**:
- Path to a file with fake model responses for testing.
- **`--help`** (or **`-h`**):
- Displays help information about command-line arguments.
- **`--include-directories <dir1,dir2,...>`**:
- Includes additional directories in the workspace for multi-directory
support.
@@ -2215,19 +2315,52 @@ for that specific session.
- 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`
- **`--list-extensions`** (**`-l`**):
- Lists all available extensions and exits.
- **`--list-sessions`**:
- List all available chat sessions for the current project and exit.
- Shows session indices, dates, message counts, and preview of first user
message.
- Example: `gemini --list-sessions`
- **`--model <model_name>`** (**`-m <model_name>`**):
- Specifies the Gemini model to use for this session.
- Example: `npm start -- --model gemini-3-pro-preview`
- **`--output-format <format>`**:
- **Description:** Specifies the format of the CLI output for non-interactive
mode.
- **Values:**
- `text`: (Default) The standard human-readable output.
- `json`: A machine-readable JSON output.
- `stream-json`: A streaming JSON output that emits real-time events.
- **Note:** For structured output and scripting, use the
`--output-format json` or `--output-format stream-json` flag.
- **`--prompt <your_prompt>`** (**`-p <your_prompt>`**):
- **Deprecated:** Use positional arguments instead.
- 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"`
- **`--record-responses`**:
- Path to a file to record model responses for testing.
- **`--resume [session_id]`** (**`-r [session_id]`**):
- Resume a previous chat session. Use "latest" for the most recent session,
provide a session index number, or provide a full session UUID.
- If no session_id is provided, defaults to "latest".
- Example: `gemini --resume 5` or `gemini --resume latest` or
`gemini --resume a1b2c3d4-e5f6-7890-abcd-ef1234567890` or `gemini --resume`
- See [Session Management](../cli/session-management.md) for more details.
- **`--sandbox`** (**`-s`**):
- Enables sandbox mode for this session.
- **`--screen-reader`**:
- Enables screen reader mode, which adjusts the TUI for better compatibility
with screen readers.
- **`--version`**:
- Displays the version of the CLI.
- **`--experimental-acp`**:
- Starts the agent in ACP mode.
- **`--allowed-mcp-server-names`**:
- Allowed MCP server names.
- **`--fake-responses`**:
- Path to a file with fake model responses for testing.
- **`--record-responses`**:
- Path to a file to record model responses for testing.
- **`--yolo`**:
- Enables YOLO mode, which automatically approves all tool calls.
## Context files (hierarchical instructional context)
@@ -2352,9 +2485,13 @@ can be based on the base sandbox image:
```dockerfile
FROM gemini-cli-sandbox
# Add your custom dependencies or configurations here
# Add your custom dependencies or configurations here.
# Note: The base image runs as the non-root 'node' user.
# You must switch to 'root' to install system packages.
# For example:
# USER root
# RUN apt-get update && apt-get install -y some-package
# USER node
# COPY ./my-config /app/my-config
```
+21 -8
View File
@@ -86,12 +86,14 @@ available combinations.
#### Text Input
| Command | Action | Keys |
| -------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `input.submit` | Submit the current prompt. | `Enter` |
| `input.newline` | Insert a newline without submitting. | `Ctrl+Enter`<br />`Cmd/Win+Enter`<br />`Alt+Enter`<br />`Shift+Enter`<br />`Ctrl+J` |
| `input.openExternalEditor` | Open the current prompt or the plan in an external editor. | `Ctrl+X` |
| `input.paste` | Paste from the clipboard. | `Ctrl+V`<br />`Cmd/Win+V`<br />`Alt+V` |
| Command | Action | Keys |
| ------------------------------------ | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `input.submit` | Submit the current prompt. | `Enter` |
| `input.queueMessage` | Queue the current prompt to be processed after the current task finishes. | `Tab` |
| `input.newline` | Insert a newline without submitting. | `Ctrl+Enter`<br />`Cmd/Win+Enter`<br />`Alt+Enter`<br />`Shift+Enter`<br />`Ctrl+J` |
| `input.openExternalEditor` | Open the current prompt or the plan in an external editor. | `Ctrl+G`<br />`Ctrl+Shift+G` |
| `input.deprecatedOpenExternalEditor` | Deprecated command to open external editor. | `Ctrl+X` |
| `input.paste` | Paste from the clipboard. | `Ctrl+V`<br />`Cmd/Win+V`<br />`Alt+V` |
#### App Controls
@@ -99,9 +101,10 @@ available combinations.
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `app.showErrorDetails` | Toggle detailed error information. | `F12` |
| `app.showFullTodos` | Toggle the full TODO list. | `Ctrl+T` |
| `app.showIdeContextDetail` | Show IDE context details. | `Ctrl+G` |
| `app.showIdeContextDetail` | Show IDE context details. | `F4` |
| `app.toggleMarkdown` | Toggle Markdown rendering. | `Alt+M` |
| `app.toggleCopyMode` | Toggle copy mode when in alternate buffer mode. | `Ctrl+S` |
| `app.toggleCopyMode` | Toggle copy mode when in alternate buffer mode. | `F9` |
| `app.toggleMouseMode` | Toggle mouse mode (scrolling and clicking). | `Ctrl+S` |
| `app.toggleYolo` | Toggle YOLO (auto-approval) mode for tool calls. | `Ctrl+Y` |
| `app.cycleApprovalMode` | Cycle through approval modes: default (prompt), auto_edit (auto-approve edits), and plan (read-only). Plan mode is skipped when the agent is busy. | `Shift+Tab` |
| `app.showMoreLines` | Expand and collapse blocks of content when not in alternate buffer mode. | `Ctrl+O` |
@@ -125,6 +128,16 @@ available combinations.
| `background.unfocus` | Move focus from background shell to Gemini. | `Shift+Tab` |
| `background.unfocusList` | Move focus from background shell list to Gemini. | `Tab` |
| `background.unfocusWarning` | Show warning when trying to move focus away from background shell. | `Tab` |
| `app.dumpFrame` | Dump the current frame as a snapshot. | `F8` |
| `app.startRecording` | Start recording the session. | `F6` |
| `app.stopRecording` | Stop recording the session. | `F7` |
#### Extension Controls
| Command | Action | Keys |
| ------------------ | ------------------------------------------- | ---- |
| `extension.update` | Update the current extension if available. | `I` |
| `extension.link` | Link the current extension to a local path. | `L` |
<!-- KEYBINDINGS-AUTOGEN:END -->
+36 -31
View File
@@ -29,13 +29,12 @@ To create your first policy:
```toml
[[rule]]
toolName = "run_shell_command"
commandPrefix = "git status"
decision = "allow"
commandPrefix = "rm -rf"
decision = "deny"
priority = 100
```
3. **Run a command** that triggers the policy (e.g., ask Gemini CLI to
`git status`). The tool will now execute automatically without prompting for
confirmation.
`rm -rf /`). The tool will now be blocked automatically.
## Core concepts
@@ -143,25 +142,26 @@ engine transforms this into a final priority using the following formula:
This system guarantees that:
- Admin policies always override User, Workspace, and Default policies.
- Admin policies always override User, Workspace, and Default policies (defined
in policy TOML files).
- User policies override Workspace and Default policies.
- Workspace policies override Default policies.
- You can still order rules within a single tier with fine-grained control.
For example:
- A `priority: 50` rule in a Default policy file becomes `1.050`.
- A `priority: 10` rule in a Workspace policy policy file becomes `2.010`.
- A `priority: 100` rule in a User policy file becomes `3.100`.
- A `priority: 20` rule in an Admin policy file becomes `4.020`.
- A `priority: 50` rule in a Default policy TOML becomes `1.050`.
- A `priority: 10` rule in a Workspace policy TOML becomes `2.010`.
- A `priority: 100` rule in a User policy TOML becomes `3.100`.
- A `priority: 20` rule in an Admin policy TOML becomes `4.020`.
### Approval modes
Approval modes allow the policy engine to apply different sets of rules based on
the CLI's operational mode. A rule can be associated with one or more modes
(e.g., `yolo`, `autoEdit`, `plan`). The rule will only be active if the CLI is
running in one of its specified modes. If a rule has no modes specified, it is
always active.
the CLI's operational mode. A rule in a TOML policy file can be associated with
one or more modes (e.g., `yolo`, `autoEdit`, `plan`). The rule will only be
active if the CLI is running in one of its specified modes. If a rule has no
modes specified, it is always active.
- `default`: The standard interactive mode where most write tools require
confirmation.
@@ -171,6 +171,24 @@ always active.
[Customizing Plan Mode Policies](../cli/plan-mode.md#customizing-policies).
- `yolo`: A mode where all tools are auto-approved (use with extreme caution).
To maintain the integrity of Plan Mode as a safe research environment,
persistent tool approvals are context-aware. When you select **"Allow for all
future sessions"**, the policy engine explicitly includes the current mode and
all more permissive modes in the hierarchy (`plan` < `default` < `autoEdit` <
`yolo`).
- **Approvals in `plan` mode**: These represent an intentional choice to trust a
tool globally. The resulting rule explicitly includes all modes (`plan`,
`default`, `autoEdit`, and `yolo`).
- **Approvals in other modes**: These only apply to the current mode and those
more permissive. For example:
- An approval granted in **`default`** mode applies to `default`, `autoEdit`,
and `yolo`.
- An approval granted in **`autoEdit`** mode applies to `autoEdit` and `yolo`.
- An approval granted in **`yolo`** mode applies only to `yolo`. This ensures
that trust flows correctly to more permissive environments while maintaining
the safety of more restricted modes like `plan`.
## Rule matching
When a tool call is made, the engine checks it against all active rules,
@@ -179,8 +197,8 @@ outcome.
A rule matches a tool call if all of its conditions are met:
1. **Tool name**: The `toolName` in the rule must match the name of the tool
being called.
1. **Tool name**: The `toolName` in the TOML rule must match the name of the
tool being called.
- **Wildcards**: You can use wildcards like `*`, `mcp_server_*`, or
`mcp_*_toolName` to match multiple tools. See [Tool Name](#tool-name) for
details.
@@ -264,7 +282,7 @@ toolName = "run_shell_command"
# (Optional) The name of a subagent. If provided, the rule only applies to tool
# calls made by this specific subagent.
subagent = "generalist"
subagent = "codebase_investigator"
# (Optional) The name of an MCP server. Can be combined with toolName
# to form a composite FQN internally like "mcp_mcpName_toolName".
@@ -304,7 +322,8 @@ priority = 10
denyMessage = "Deletion is permanent"
# (Optional) An array of approval modes where this rule is active.
modes = ["autoEdit"]
# If omitted or empty, the rule applies to all modes.
modes = ["default", "autoEdit", "yolo"]
# (Optional) A boolean to restrict the rule to interactive (true) or
# non-interactive (false) environments.
@@ -419,20 +438,6 @@ decision = "ask_user"
priority = 10
```
**4. Targeting a tool name across all servers**
Use `mcpName = "*"` with a specific `toolName` to target that operation
regardless of which server provides it.
```toml
# Allow the `search` tool across all connected MCP servers
[[rule]]
mcpName = "*"
toolName = "search"
decision = "allow"
priority = 50
```
## Default policies
The Gemini CLI ships with a set of default policies to provide a safe
+55 -22
View File
@@ -63,29 +63,62 @@ details.
## Available tools
The following table lists all available tools, categorized by their primary
function.
The following sections list all available tools, categorized by their primary
function. For detailed parameter information, see the linked documentation for
each tool.
| Category | Tool | Kind | Description |
| :---------- | :----------------------------------------------- | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Execution | [`run_shell_command`](../tools/shell.md) | `Execute` | Executes arbitrary shell commands. Supports interactive sessions and background processes. Requires manual confirmation.<br><br>**Parameters:** `command`, `description`, `dir_path`, `is_background` |
| File System | [`glob`](../tools/file-system.md) | `Search` | Finds files matching specific glob patterns across the workspace.<br><br>**Parameters:** `pattern`, `dir_path`, `case_sensitive`, `respect_git_ignore`, `respect_gemini_ignore` |
| File System | [`grep_search`](../tools/file-system.md) | `Search` | Searches for a regular expression pattern within file contents. Legacy alias: `search_file_content`.<br><br>**Parameters:** `pattern`, `dir_path`, `include`, `exclude_pattern`, `names_only`, `max_matches_per_file`, `total_max_matches` |
| File System | [`list_directory`](../tools/file-system.md) | `Read` | Lists the names of files and subdirectories within a specified path.<br><br>**Parameters:** `dir_path`, `ignore`, `file_filtering_options` |
| File System | [`read_file`](../tools/file-system.md) | `Read` | Reads the content of a specific file. Supports text, images, audio, and PDF.<br><br>**Parameters:** `file_path`, `start_line`, `end_line` |
| File System | [`read_many_files`](../tools/file-system.md) | `Read` | Reads and concatenates content from multiple files. Often triggered by the `@` symbol in your prompt.<br><br>**Parameters:** `include`, `exclude`, `recursive`, `useDefaultExcludes`, `file_filtering_options` |
| File System | [`replace`](../tools/file-system.md) | `Edit` | Performs precise text replacement within a file. Requires manual confirmation.<br><br>**Parameters:** `file_path`, `instruction`, `old_string`, `new_string`, `allow_multiple` |
| File System | [`write_file`](../tools/file-system.md) | `Edit` | Creates or overwrites a file with new content. Requires manual confirmation.<br><br>**Parameters:** `file_path`, `content` |
| Interaction | [`ask_user`](../tools/ask-user.md) | `Communicate` | Requests clarification or missing information via an interactive dialog.<br><br>**Parameters:** `questions` |
| Interaction | [`write_todos`](../tools/todos.md) | `Other` | Maintains an internal list of subtasks. The model uses this to track its own progress and display it to you.<br><br>**Parameters:** `todos` |
| Memory | [`activate_skill`](../tools/activate-skill.md) | `Other` | Loads specialized procedural expertise for specific tasks from the `.gemini/skills` directory.<br><br>**Parameters:** `name` |
| Memory | [`get_internal_docs`](../tools/internal-docs.md) | `Think` | Accesses Gemini CLI's own documentation to provide more accurate answers about its capabilities.<br><br>**Parameters:** `path` |
| Memory | [`save_memory`](../tools/memory.md) | `Think` | Persists specific facts and project details to your `GEMINI.md` file to retain context.<br><br>**Parameters:** `fact` |
| Planning | [`enter_plan_mode`](../tools/planning.md) | `Plan` | Switches the CLI to a safe, read-only "Plan Mode" for researching complex changes.<br><br>**Parameters:** `reason` |
| Planning | [`exit_plan_mode`](../tools/planning.md) | `Plan` | Finalizes a plan, presents it for review, and requests approval to start implementation.<br><br>**Parameters:** `plan` |
| System | `complete_task` | `Other` | Finalizes a subagent's mission and returns the result to the parent agent. This tool is not available to the user.<br><br>**Parameters:** `result` |
| Web | [`google_web_search`](../tools/web-search.md) | `Search` | Performs a Google Search to find up-to-date information.<br><br>**Parameters:** `query` |
| Web | [`web_fetch`](../tools/web-fetch.md) | `Fetch` | Retrieves and processes content from specific URLs. **Warning:** This tool can access local and private network addresses (e.g., localhost), which may pose a security risk if used with untrusted prompts.<br><br>**Parameters:** `prompt` |
### Execution
| Tool | Kind | Description |
| :--------------------------------------- | :-------- | :----------------------------------------------------------------------------------------------------------------------- |
| [`run_shell_command`](../tools/shell.md) | `Execute` | Executes arbitrary shell commands. Supports interactive sessions and background processes. Requires manual confirmation. |
### File System
| Tool | Kind | Description |
| :------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------------- |
| [`glob`](../tools/file-system.md) | `Search` | Finds files matching specific glob patterns across the workspace. |
| [`grep_search`](../tools/file-system.md) | `Search` | Searches for a regular expression pattern within file contents. Legacy alias: `search_file_content`. |
| [`list_directory`](../tools/file-system.md) | `Read` | Lists the names of files and subdirectories within a specified path. |
| [`read_file`](../tools/file-system.md) | `Read` | Reads the content of a specific file. Supports text, images, audio, and PDF. |
| [`read_many_files`](../tools/file-system.md) | `Read` | Reads and concatenates content from multiple files. Often triggered by the `@` symbol in your prompt. |
| [`replace`](../tools/file-system.md) | `Edit` | Performs precise text replacement within a file. Requires manual confirmation. |
| [`write_file`](../tools/file-system.md) | `Edit` | Creates or overwrites a file with new content. Requires manual confirmation. |
### Interaction
| Tool | Kind | Description |
| :--------------------------------- | :------------ | :------------------------------------------------------------------------------------- |
| [`ask_user`](../tools/ask-user.md) | `Communicate` | Requests clarification or missing information via an interactive dialog. |
| [`write_todos`](../tools/todos.md) | `Other` | Maintains an internal list of subtasks. The model uses this to track its own progress. |
### Memory
| Tool | Kind | Description |
| :----------------------------------------------- | :------ | :----------------------------------------------------------------------------------- |
| [`activate_skill`](../tools/activate-skill.md) | `Other` | Loads specialized procedural expertise from the `.gemini/skills` directory. |
| [`get_internal_docs`](../tools/internal-docs.md) | `Think` | Accesses Gemini CLI's own documentation for accurate answers about its capabilities. |
| [`save_memory`](../tools/memory.md) | `Think` | Persists specific facts and project details to your `GEMINI.md` file. |
### Planning
| Tool | Kind | Description |
| :---------------------------------------- | :----- | :--------------------------------------------------------------------------------------- |
| [`enter_plan_mode`](../tools/planning.md) | `Plan` | Switches the CLI to a safe, read-only "Plan Mode" for researching complex changes. |
| [`exit_plan_mode`](../tools/planning.md) | `Plan` | Finalizes a plan, presents it for review, and requests approval to start implementation. |
### System
| Tool | Kind | Description |
| :-------------- | :------ | :----------------------------------------------------------------------------------------------------------------- |
| `complete_task` | `Other` | Finalizes a subagent's mission and returns the result to the parent agent. This tool is not available to the user. |
### Web
| Tool | Kind | Description |
| :-------------------------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`google_web_search`](../tools/web-search.md) | `Search` | Performs a Google Search to find up-to-date information. |
| [`web_fetch`](../tools/web-fetch.md) | `Fetch` | Retrieves and processes content from specific URLs. **Warning:** This tool can access local and private network addresses (e.g., localhost), which may pose a security risk if used with untrusted prompts. In Plan Mode, this tool requires explicit user confirmation. |
## Under the hood
-6
View File
@@ -22,12 +22,6 @@ nightly) or the release branch (for preview/stable).
- **Platforms:** Tests must pass on **Linux and macOS**.
<!-- prettier-ignore -->
> [!NOTE]
> Windows tests currently run with `continue-on-error: true`. While a
> failure here doesn't block the release technically, it should be
> investigated.
- **Checks:**
- **Linting:** No linting errors (ESLint, Prettier, etc.).
- **Typechecking:** No TypeScript errors.
+4
View File
@@ -1,5 +1,9 @@
# Gemini CLI releases
<!-- prettier-ignore -->
> [!IMPORTANT]
> **Coordinate with the Release Manager:** The release manager is responsible for coordinating patches and releases. Please update them before performing any of the release actions described in this document.
## `dev` vs `prod` environment
Our release flows support both `dev` and `prod` environments.
+23 -9
View File
@@ -12,6 +12,21 @@ quota for your needs, see the [Plans page](https://geminicli.com/plans/).
This article outlines the specific quotas and pricing applicable to Gemini CLI
when using different authentication methods.
The following table summarizes the available quotas and their respective limits:
| Authentication method | Tier / Subscription | Maximum requests per user per day |
| :-------------------- | :------------------------------ | :-------------------------------- |
| **Google account** | Gemini Code Assist (Individual) | 1,000 requests |
| | Google AI Pro | 1,500 requests |
| | Google AI Ultra | 2,000 requests |
| **Gemini API key** | Free tier (Unpaid) | 250 requests |
| | Pay-as-you-go (Paid) | Varies |
| **Vertex AI** | Express mode (Free) | Varies |
| | Pay-as-you-go (Paid) | Varies |
| **Google Workspace** | Code Assist Standard | 1,500 requests |
| | Code Assist Enterprise | 2,000 requests |
| | Workspace AI Ultra | 2,000 requests |
Generally, there are three categories to choose from:
- Free Usage: Ideal for experimentation and light use.
@@ -20,6 +35,9 @@ Generally, there are three categories to choose from:
- Pay-As-You-Go: The most flexible option for professional use, long-running
tasks, or when you need full control over your usage.
Requests are limited per user per minute and are subject to the availability of
the service in times of high demand.
## Free usage
Access to Gemini CLI begins with a generous free tier, perfect for
@@ -33,8 +51,7 @@ authorization type.
For users who authenticate by using their Google account to access Gemini Code
Assist for individuals. This includes:
- 1000 model requests / user / day
- 60 model requests / user / minute
- 1000 maximum model requests / user / day
- Model requests will be made across the Gemini model family as determined by
Gemini CLI.
@@ -46,8 +63,7 @@ Learn more at
If you are using a Gemini API key, you can also benefit from a free tier. This
includes:
- 250 model requests / user / day
- 10 model requests / user / minute
- 250 maximum model requests / user / day
- Model requests to Flash model only.
Learn more at
@@ -59,7 +75,7 @@ Vertex AI offers an Express Mode without the need to enable billing. This
includes:
- 90 days before you need to enable billing.
- Quotas and models are variable and specific to your account.
- Quotas and models are specific to your account and their limits vary.
Learn more at
[Vertex AI Express Mode Limits](https://cloud.google.com/vertex-ai/generative-ai/docs/start/express-mode/overview#quotas).
@@ -112,11 +128,9 @@ Standard/Plus and AI Expanded, are not supported._
This includes the following request limits:
- Gemini Code Assist Standard edition:
- 1500 model requests / user / day
- 120 model requests / user / minute
- 1500 maximum model requests / user / day
- Gemini Code Assist Enterprise edition:
- 2000 model requests / user / day
- 120 model requests / user / minute
- 2000 maximum model requests / user / day
- Model requests will be made across the Gemini model family as determined by
Gemini CLI.
+11 -4
View File
@@ -12,7 +12,6 @@
"label": "Authentication",
"slug": "docs/get-started/authentication"
},
{ "label": "Examples", "slug": "docs/get-started/examples" },
{ "label": "CLI cheatsheet", "slug": "docs/cli/cli-reference" },
{
"label": "Gemini 3 on Gemini CLI",
@@ -112,7 +111,17 @@
{ "label": "Reference", "slug": "docs/hooks/reference" }
]
},
{ "label": "IDE integration", "slug": "docs/ide-integration" },
{
"label": "IDE integration",
"collapsed": true,
"items": [
{ "label": "Overview", "slug": "docs/ide-integration" },
{
"label": "Developer guide: ACP mode",
"slug": "docs/cli/acp-mode"
}
]
},
{ "label": "MCP servers", "slug": "docs/tools/mcp-server" },
{ "label": "Model routing", "slug": "docs/cli/model-routing" },
{ "label": "Model selection", "slug": "docs/cli/model" },
@@ -129,12 +138,10 @@
{ "label": "Plan mode", "slug": "docs/cli/plan-mode" },
{
"label": "Subagents",
"badge": "🔬",
"slug": "docs/core/subagents"
},
{
"label": "Remote subagents",
"badge": "🔬",
"slug": "docs/core/remote-agents"
},
{ "label": "Rewind", "slug": "docs/cli/rewind" },
+3 -3
View File
@@ -290,7 +290,7 @@ When connecting to an OAuth-enabled server:
> OAuth authentication requires that your local machine can:
>
> - Open a web browser for authentication
> - Receive redirects on `http://localhost:7777/oauth/callback`
> - Receive redirects on `http://localhost:<random-port>/oauth/callback` (or a specific port if configured via `redirectUri`)
This feature will not work in:
@@ -323,8 +323,8 @@ Use the `/mcp auth` command to manage OAuth authentication:
if omitted)
- **`tokenUrl`** (string): OAuth token endpoint (auto-discovered if omitted)
- **`scopes`** (string[]): Required OAuth scopes
- **`redirectUri`** (string): Custom redirect URI (defaults to
`http://localhost:7777/oauth/callback`)
- **`redirectUri`** (string): Custom redirect URI (defaults to an OS-assigned
random port, e.g., `http://localhost:<random-port>/oauth/callback`)
- **`tokenParamName`** (string): Query parameter name for tokens in SSE URLs
- **`audiences`** (string[]): Audiences the token is valid for
+6 -4
View File
@@ -32,7 +32,9 @@ and planning.
## 2. `exit_plan_mode` (ExitPlanMode)
`exit_plan_mode` signals that the planning phase is complete. It presents the
finalized plan to the user and requests approval to start the implementation.
finalized plan to the user and requests formal approval to start the
implementation. The agent MUST reach an informal agreement with the user in the
chat regarding the proposed strategy BEFORE calling this tool.
- **Tool name:** `exit_plan_mode`
- **Display name:** Exit Plan Mode
@@ -44,7 +46,7 @@ finalized plan to the user and requests approval to start the implementation.
- **Behavior:**
- Validates that the `plan_path` is within the allowed directory and that the
file exists and has content.
- Presents the plan to the user for review.
- Presents the plan to the user for formal review.
- If the user approves the plan:
- Switches the CLI's approval mode to the user's chosen approval mode (
`DEFAULT` or `AUTO_EDIT`).
@@ -56,5 +58,5 @@ finalized plan to the user and requests approval to start the implementation.
- On approval: A message indicating the plan was approved and the new approval
mode.
- On rejection: A message containing the user's feedback.
- **Confirmation:** Yes. Shows the finalized plan and asks for user approval to
proceed with implementation.
- **Confirmation:** Yes. Shows the finalized plan and asks for user formal
approval to proceed with implementation.
+3
View File
@@ -17,6 +17,9 @@ specific operations like summarization or extraction.
## Technical behavior
- **Confirmation:** Triggers a confirmation dialog showing the converted URLs.
- **Plan Mode:** In [Plan Mode](../cli/plan-mode.md), `web_fetch` is available
but always requires explicit user confirmation (`ask_user`) due to security
implications of accessing external or private network addresses.
- **Processing:** Uses the Gemini API's `urlContext` for retrieval.
- **Fallback:** If API access fails, the tool attempts to fetch raw content
directly from your local machine.
+9 -1
View File
@@ -13,7 +13,7 @@ import { wasmLoader } from 'esbuild-plugin-wasm';
let esbuild;
try {
esbuild = (await import('esbuild')).default;
} catch (_error) {
} catch {
console.error('esbuild not available - cannot build bundle');
process.exit(1);
}
@@ -94,6 +94,10 @@ const cliConfig = {
'process.env.GEMINI_SANDBOX_IMAGE_DEFAULT': JSON.stringify(
pkg.config?.sandboxImageUri,
),
'process.env.NODE_ENV': JSON.stringify(
process.env.NODE_ENV || 'production',
),
'process.env.DEV': JSON.stringify(process.env.DEV || 'false'),
},
plugins: createWasmPlugins(),
alias: {
@@ -114,6 +118,10 @@ const a2aServerConfig = {
__filename: '__chunk_filename',
__dirname: '__chunk_dirname',
'process.env.CLI_VERSION': JSON.stringify(pkg.version),
'process.env.NODE_ENV': JSON.stringify(
process.env.NODE_ENV || 'production',
),
'process.env.DEV': JSON.stringify(process.env.DEV || 'false'),
},
plugins: createWasmPlugins(),
alias: commonAliases,
+9 -4
View File
@@ -41,6 +41,11 @@ const commonRestrictedSyntaxRules = [
message:
'Do not use typeof to check object properties. Define a TypeScript interface and a type guard function instead.',
},
{
selector: 'CatchClause > Identifier[name=/^_/]',
message:
'Do not use underscored identifiers in catch blocks. If the error is unused, use "catch {}". If it is used, remove the underscore.',
},
];
export default tseslint.config(
@@ -129,7 +134,7 @@ export default tseslint.config(
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
caughtErrors: 'all',
},
],
// Prevent async errors from bypassing catch handlers
@@ -336,7 +341,7 @@ export default tseslint.config(
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
caughtErrors: 'all',
},
],
},
@@ -360,7 +365,7 @@ export default tseslint.config(
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
caughtErrors: 'all',
},
],
},
@@ -422,7 +427,7 @@ export default tseslint.config(
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
caughtErrors: 'all',
},
],
},
+50
View File
@@ -212,6 +212,56 @@ The nightly workflow executes the full evaluation suite multiple times
(currently 3 attempts) to account for non-determinism. These results are
aggregated into a **Nightly Summary** attached to the workflow run.
## Regression Check Scripts
The project includes several scripts to automate high-signal regression checking
in Pull Requests. These can also be run locally for debugging.
- **`scripts/get_trustworthy_evals.js`**: Analyzes nightly history to identify
stable tests (80%+ aggregate pass rate).
- **`scripts/run_regression_check.js`**: Runs a specific set of tests using the
"Best-of-4" logic and "Dynamic Baseline Verification".
- **`scripts/run_eval_regression.js`**: The main orchestrator that loops through
models and generates the final PR report.
### Running Regression Checks Locally
You can simulate the PR regression check locally to verify your changes before
pushing:
```bash
# Run the full regression loop for a specific model
MODEL_LIST=gemini-3-flash-preview node scripts/run_eval_regression.js
```
To debug a specific failing test with the same logic used in CI:
```bash
# 1. Get the Vitest pattern for trustworthy tests
OUTPUT=$(node scripts/get_trustworthy_evals.js "gemini-3-flash-preview")
# 2. Run the regression logic for those tests
node scripts/run_regression_check.js "gemini-3-flash-preview" "$OUTPUT"
```
### The Regression Quality Bar
Because LLMs are non-deterministic, the PR regression check uses a high-signal
probabilistic approach rather than a 100% pass requirement:
1. **Trustworthiness (60/80 Filter):** Only tests with a proven track record
are run. A test must score at least **60% (2/3)** every single night and
maintain an **80% aggregate** pass rate over the last 6 days.
2. **The 50% Pass Rule:** In a PR, a test is considered a **Pass** if the model
correctly performs the behavior at least half the time (**2 successes** out
of up to 4 attempts).
3. **Dynamic Baseline Verification:** If a test fails in a PR (e.g., 0/3), the
system automatically checks the `main` branch. If it fails there too, it is
marked as **Pre-existing** and cleared for the PR, ensuring you are only
blocked by regressions caused by your specific changes.
## Fixing Evaluations
#### How to interpret the report:
- **Pass Rate (%)**: Each cell represents the percentage of successful runs for
+12
View File
@@ -19,6 +19,8 @@ describe('Answer vs. ask eval', () => {
* automatically modify the file, but instead asks for permission.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not edit files when asked to inspect for bugs',
prompt: 'Inspect app.ts for bugs',
files: FILES,
@@ -42,6 +44,8 @@ describe('Answer vs. ask eval', () => {
* does modify the file.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should edit files when asked to fix bug',
prompt: 'Fix the bug in app.ts - it should add numbers not subtract',
files: FILES,
@@ -66,6 +70,8 @@ describe('Answer vs. ask eval', () => {
* automatically modify the file, but instead asks for permission.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not edit when asking "any bugs"',
prompt: 'Any bugs in app.ts?',
files: FILES,
@@ -89,6 +95,8 @@ describe('Answer vs. ask eval', () => {
* automatically modify the file.
*/
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not edit files when asked a general question',
prompt: 'How does app.ts work?',
files: FILES,
@@ -112,6 +120,8 @@ describe('Answer vs. ask eval', () => {
* automatically modify the file.
*/
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not edit files when asked about style',
prompt: 'Is app.ts following good style?',
files: FILES,
@@ -135,6 +145,8 @@ describe('Answer vs. ask eval', () => {
* the agent does NOT automatically modify the file.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not edit files when user notes an issue',
prompt: 'The add function subtracts numbers.',
files: FILES,
+49 -49
View File
@@ -10,10 +10,13 @@ import {
runEval,
prepareLogDir,
symlinkNodeModules,
withEvalRetries,
prepareWorkspace,
type BaseEvalCase,
EVAL_MODEL,
} from './test-helper.js';
import fs from 'node:fs';
import path from 'node:path';
import { DEFAULT_GEMINI_MODEL } from '@google/gemini-cli-core';
/**
* Config overrides for evals, with tool-restriction fields explicitly
@@ -29,15 +32,13 @@ interface EvalConfigOverrides {
allowedTools?: never;
/** Restricting tools via mainAgentTools in evals is forbidden. */
mainAgentTools?: never;
[key: string]: unknown;
}
export interface AppEvalCase {
name: string;
export interface AppEvalCase extends BaseEvalCase {
configOverrides?: EvalConfigOverrides;
prompt: string;
timeout?: number;
files?: Record<string, string>;
setup?: (rig: AppRig) => Promise<void>;
assert: (rig: AppRig, output: string) => Promise<void>;
}
@@ -48,56 +49,55 @@ export interface AppEvalCase {
*/
export function appEvalTest(policy: EvalPolicy, evalCase: AppEvalCase) {
const fn = async () => {
const rig = new AppRig({
configOverrides: {
model: DEFAULT_GEMINI_MODEL,
...evalCase.configOverrides,
},
});
await withEvalRetries(evalCase.name, async () => {
const rig = new AppRig({
configOverrides: {
model: EVAL_MODEL,
...evalCase.configOverrides,
},
});
const { logDir, sanitizedName } = await prepareLogDir(evalCase.name);
const logFile = path.join(logDir, `${sanitizedName}.log`);
const { logDir, sanitizedName } = await prepareLogDir(evalCase.name);
const logFile = path.join(logDir, `${sanitizedName}.log`);
try {
await rig.initialize();
try {
await rig.initialize();
const testDir = rig.getTestDir();
symlinkNodeModules(testDir);
const testDir = rig.getTestDir();
symlinkNodeModules(testDir);
// Setup initial files
if (evalCase.files) {
for (const [filePath, content] of Object.entries(evalCase.files)) {
const fullPath = path.join(testDir, filePath);
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, content);
// Setup initial files
if (evalCase.files) {
// Note: AppRig does not use a separate homeDir, so we use testDir twice
await prepareWorkspace(testDir, testDir, evalCase.files);
}
// Run custom setup if provided (e.g. for breakpoints)
if (evalCase.setup) {
await evalCase.setup(rig);
}
// Render the app!
await rig.render();
// Wait for initial ready state
await rig.waitForIdle();
// Send the initial prompt
await rig.sendMessage(evalCase.prompt);
// Run assertion. Interaction-heavy tests can do their own waiting/steering here.
const output = rig.getStaticOutput();
await evalCase.assert(rig, output);
} finally {
const output = rig.getStaticOutput();
if (output) {
await fs.promises.writeFile(logFile, output);
}
await rig.unmount();
}
// Run custom setup if provided (e.g. for breakpoints)
if (evalCase.setup) {
await evalCase.setup(rig);
}
// Render the app!
await rig.render();
// Wait for initial ready state
await rig.waitForIdle();
// Send the initial prompt
await rig.sendMessage(evalCase.prompt);
// Run assertion. Interaction-heavy tests can do their own waiting/steering here.
const output = rig.getStaticOutput();
await evalCase.assert(rig, output);
} finally {
const output = rig.getStaticOutput();
if (output) {
await fs.promises.writeFile(logFile, output);
}
await rig.unmount();
}
});
};
runEval(policy, evalCase.name, fn, (evalCase.timeout ?? 60000) + 10000);
runEval(policy, evalCase, fn, (evalCase.timeout ?? 60000) + 10000);
}
+18 -6
View File
@@ -5,17 +5,21 @@
*/
import { describe, expect } from 'vitest';
import { appEvalTest, AppEvalCase } from './app-test-helper.js';
import { EvalPolicy } from './test-helper.js';
import { ApprovalMode, isRecord } from '@google/gemini-cli-core';
import { appEvalTest, type AppEvalCase } from './app-test-helper.js';
import { type EvalPolicy } from './test-helper.js';
function askUserEvalTest(policy: EvalPolicy, evalCase: AppEvalCase) {
const existingGeneral = evalCase.configOverrides?.['general'];
const generalBase = isRecord(existingGeneral) ? existingGeneral : {};
return appEvalTest(policy, {
...evalCase,
configOverrides: {
...evalCase.configOverrides,
approvalMode: ApprovalMode.DEFAULT,
general: {
...evalCase.configOverrides?.general,
approvalMode: 'default',
...generalBase,
enableAutoUpdate: false,
enableAutoUpdateNotification: false,
},
@@ -28,6 +32,8 @@ function askUserEvalTest(policy: EvalPolicy, evalCase: AppEvalCase) {
describe('ask_user', () => {
askUserEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'Agent uses AskUser tool to present multiple choice options',
prompt: `Use the ask_user tool to ask me what my favorite color is. Provide 3 options: red, green, or blue.`,
setup: async (rig) => {
@@ -43,6 +49,8 @@ describe('ask_user', () => {
});
askUserEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'Agent uses AskUser tool to clarify ambiguous requirements',
files: {
'package.json': JSON.stringify({ name: 'my-app', version: '1.0.0' }),
@@ -61,6 +69,8 @@ describe('ask_user', () => {
});
askUserEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'Agent uses AskUser tool before performing significant ambiguous rework',
files: {
'packages/core/src/index.ts': '// index\nexport const version = "1.0.0";',
@@ -82,8 +92,8 @@ describe('ask_user', () => {
]);
expect(confirmation, 'Expected a tool call confirmation').toBeDefined();
if (confirmation?.name === 'enter_plan_mode') {
rig.acceptConfirmation('enter_plan_mode');
if (confirmation?.toolName === 'enter_plan_mode') {
await rig.resolveTool('enter_plan_mode');
confirmation = await rig.waitForPendingConfirmation('ask_user');
}
@@ -101,6 +111,8 @@ describe('ask_user', () => {
// updates to clarify that shell command confirmation is handled by the UI.
// See fix: https://github.com/google-gemini/gemini-cli/pull/20504
askUserEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'Agent does NOT use AskUser to confirm shell commands',
files: {
'package.json': JSON.stringify({
+4
View File
@@ -14,6 +14,8 @@ describe('Automated tool use', () => {
* a repro by guiding the agent into using the existing deficient script.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use automated tools (eslint --fix) to fix code style issues',
files: {
'package.json': JSON.stringify(
@@ -102,6 +104,8 @@ describe('Automated tool use', () => {
* instead of trying to edit the files itself.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use automated tools (prettier --write) to fix formatting issues',
files: {
'package.json': JSON.stringify(
+77
View File
@@ -0,0 +1,77 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, expect } from 'vitest';
import { evalTest } from './test-helper.js';
import fs from 'node:fs';
import path from 'node:path';
describe('Background Process Monitoring', () => {
evalTest('USUALLY_PASSES', {
name: 'should naturally use read output tool to find token',
prompt:
"Run the script using 'bash generate_token.sh'. It will emit a token after a short delay and continue running. Find the token and tell me what it is.",
files: {
'generate_token.sh': `#!/bin/bash
sleep 2
echo "TOKEN=xyz123"
sleep 100
`,
},
setup: async (rig) => {
// Create .gemini directory to avoid file system error in test rig
if (rig.homeDir) {
const geminiDir = path.join(rig.homeDir, '.gemini');
fs.mkdirSync(geminiDir, { recursive: true });
}
},
assert: async (rig, result) => {
const toolCalls = rig.readToolLogs();
// Check if read_background_output was called
const hasReadCall = toolCalls.some(
(call) => call.toolRequest.name === 'read_background_output',
);
expect(
hasReadCall,
'Expected agent to call read_background_output to find the token',
).toBe(true);
// Verify that the agent found the correct token
expect(
result.includes('xyz123'),
`Expected agent to find the token xyz123. Agent output: ${result}`,
).toBe(true);
},
});
evalTest('USUALLY_PASSES', {
name: 'should naturally use list tool to verify multiple processes',
prompt:
"Start three background processes that run 'sleep 100', 'sleep 200', and 'sleep 300' respectively. Verify that all three are currently running.",
setup: async (rig) => {
// Create .gemini directory to avoid file system error in test rig
if (rig.homeDir) {
const geminiDir = path.join(rig.homeDir, '.gemini');
fs.mkdirSync(geminiDir, { recursive: true });
}
},
assert: async (rig, result) => {
const toolCalls = rig.readToolLogs();
// Check if list_background_processes was called
const hasListCall = toolCalls.some(
(call) => call.toolRequest.name === 'list_background_processes',
);
expect(
hasListCall,
'Expected agent to call list_background_processes',
).toBe(true);
},
});
});
+2
View File
@@ -3,6 +3,8 @@ import { evalTest } from './test-helper.js';
describe('CliHelpAgent Delegation', () => {
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should delegate to cli_help agent for subagent creation questions',
params: {
settings: {
+136
View File
@@ -0,0 +1,136 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {
type EvalPolicy,
runEval,
prepareLogDir,
withEvalRetries,
prepareWorkspace,
type BaseEvalCase,
} from './test-helper.js';
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { randomUUID } from 'node:crypto';
import {
Config,
type ConfigParameters,
AuthType,
ApprovalMode,
createPolicyEngineConfig,
ExtensionLoader,
IntegrityDataStatus,
makeFakeConfig,
type GeminiCLIExtension,
} from '@google/gemini-cli-core';
import { createMockSettings } from '../packages/cli/src/test-utils/settings.js';
// A minimal mock ExtensionManager to bypass integrity checks
class MockExtensionManager extends ExtensionLoader {
override getExtensions(): GeminiCLIExtension[] {
return [];
}
setRequestConsent = (): void => {};
setRequestSetting = (): void => {};
integrityManager = {
verifyExtensionIntegrity: async (): Promise<IntegrityDataStatus> =>
IntegrityDataStatus.VERIFIED,
storeExtensionIntegrity: async (): Promise<void> => undefined,
};
}
export interface ComponentEvalCase extends BaseEvalCase {
configOverrides?: Partial<ConfigParameters>;
setup?: (config: Config) => Promise<void>;
assert: (config: Config) => Promise<void>;
}
export class ComponentRig {
public config: Config | undefined;
public testDir: string;
public sessionId: string;
constructor(
private options: { configOverrides?: Partial<ConfigParameters> } = {},
) {
const uniqueId = randomUUID();
this.testDir = fs.mkdtempSync(
path.join(os.tmpdir(), `gemini-component-rig-${uniqueId.slice(0, 8)}-`),
);
this.sessionId = `test-session-${uniqueId}`;
}
async initialize() {
const settings = createMockSettings();
const policyEngineConfig = await createPolicyEngineConfig(
settings.merged,
ApprovalMode.DEFAULT,
);
const configParams: ConfigParameters = {
sessionId: this.sessionId,
targetDir: this.testDir,
cwd: this.testDir,
debugMode: false,
model: 'test-model',
interactive: false,
approvalMode: ApprovalMode.DEFAULT,
policyEngineConfig,
enableEventDrivenScheduler: false, // Don't need scheduler for direct component tests
extensionLoader: new MockExtensionManager(),
useAlternateBuffer: false,
...this.options.configOverrides,
};
this.config = makeFakeConfig(configParams);
await this.config.initialize();
// Refresh auth using USE_GEMINI to initialize the real BaseLlmClient
await this.config.refreshAuth(AuthType.USE_GEMINI);
}
async cleanup() {
fs.rmSync(this.testDir, { recursive: true, force: true });
}
}
/**
* A helper for running behavioral evaluations directly against backend components.
* It provides a fully initialized Config with real API access, bypassing the UI.
*/
export function componentEvalTest(
policy: EvalPolicy,
evalCase: ComponentEvalCase,
) {
const fn = async () => {
await withEvalRetries(evalCase.name, async () => {
const rig = new ComponentRig({
configOverrides: evalCase.configOverrides,
});
await prepareLogDir(evalCase.name);
try {
await rig.initialize();
if (evalCase.files) {
await prepareWorkspace(rig.testDir, rig.testDir, evalCase.files);
}
if (evalCase.setup) {
await evalCase.setup(rig.config!);
}
await evalCase.assert(rig.config!);
} finally {
await rig.cleanup();
}
});
};
runEval(policy, evalCase, fn, (evalCase.timeout ?? 60000) + 10000);
}
+2
View File
@@ -20,6 +20,8 @@ You are the mutation agent. Do the mutation requested.
describe('concurrency safety eval test cases', () => {
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'mutation agents are run in parallel when explicitly requested',
params: {
settings: {
+2
View File
@@ -13,6 +13,8 @@ describe('Edits location eval', () => {
* instead of creating a new one.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should update existing test file instead of creating a new one',
files: {
'package.json': JSON.stringify(
+6
View File
@@ -15,6 +15,8 @@ describe('Frugal reads eval', () => {
* nearby ranges into a single contiguous read to save tool calls.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use ranged read when nearby lines are targeted',
files: {
'package.json': JSON.stringify({
@@ -135,6 +137,8 @@ describe('Frugal reads eval', () => {
* apart to avoid the need to read the whole file.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use ranged read when targets are far apart',
files: {
'package.json': JSON.stringify({
@@ -204,6 +208,8 @@ describe('Frugal reads eval', () => {
* (e.g.: 10), as it's more efficient than many small ranged reads.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should read the entire file when there are many matches',
files: {
'package.json': JSON.stringify({
+2 -12
View File
@@ -13,18 +13,6 @@ import { evalTest } from './test-helper.js';
* This ensures the agent doesn't flood the context window with unnecessary search results.
*/
describe('Frugal Search', () => {
const getGrepParams = (call: any): any => {
let args = call.toolRequest.args;
if (typeof args === 'string') {
try {
args = JSON.parse(args);
} catch (e) {
// Ignore parse errors
}
}
return args;
};
/**
* Ensure that the agent makes use of either grep or ranged reads in fulfilling this task.
* The task is specifically phrased to not evoke "view" or "search" specifically because
@@ -33,6 +21,8 @@ describe('Frugal Search', () => {
* ranged reads.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use grep or ranged read for large files',
prompt: 'What year was legacy_processor.ts written?',
files: {
+2
View File
@@ -11,6 +11,8 @@ import fs from 'node:fs/promises';
describe('generalist_agent', () => {
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should be able to use generalist agent by explicitly asking the main agent to invoke it',
params: {
settings: {
+8
View File
@@ -11,6 +11,8 @@ describe('generalist_delegation', () => {
// --- Positive Evals (Should Delegate) ---
appEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should delegate batch error fixing to generalist agent',
configOverrides: {
agents: {
@@ -54,6 +56,8 @@ describe('generalist_delegation', () => {
});
appEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should autonomously delegate complex batch task to generalist agent',
configOverrides: {
agents: {
@@ -94,6 +98,8 @@ describe('generalist_delegation', () => {
// --- Negative Evals (Should NOT Delegate - Assertive Handling) ---
appEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should NOT delegate simple read and fix to generalist agent',
configOverrides: {
agents: {
@@ -128,6 +134,8 @@ describe('generalist_delegation', () => {
});
appEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should NOT delegate simple direct question to generalist agent',
configOverrides: {
agents: {
+4
View File
@@ -26,6 +26,8 @@ describe('git repo eval', () => {
* be more consistent.
*/
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not git add commit changes unprompted',
prompt:
'Finish this up for me by just making a targeted fix for the bug in index.ts. Do not build, install anything, or add tests',
@@ -55,6 +57,8 @@ describe('git repo eval', () => {
* instructed to not do so by default.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should git commit changes when prompted',
prompt:
'Make a targeted fix for the bug in index.ts without building, installing anything, or adding tests. Then, commit your changes.',
+12
View File
@@ -15,6 +15,8 @@ describe('grep_search_functionality', () => {
const TEST_PREFIX = 'Grep Search Functionality: ';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should find a simple string in a file',
files: {
'test.txt': `hello
@@ -33,6 +35,8 @@ describe('grep_search_functionality', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should perform a case-sensitive search',
files: {
'test.txt': `Hello
@@ -63,6 +67,8 @@ describe('grep_search_functionality', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should return only file names when names_only is used',
files: {
'file1.txt': 'match me',
@@ -93,6 +99,8 @@ describe('grep_search_functionality', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should search only within the specified include_pattern glob',
files: {
'file.js': 'my_function();',
@@ -123,6 +131,8 @@ describe('grep_search_functionality', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should search within a specific subdirectory',
files: {
'src/main.js': 'unique_string_1',
@@ -153,6 +163,8 @@ describe('grep_search_functionality', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should report no matches correctly',
files: {
'file.txt': 'nothing to see here',
+7 -2
View File
@@ -5,13 +5,14 @@
*/
import { describe, expect } from 'vitest';
import { evalTest } from './test-helper.js';
import { assertModelHasOutput } from '../integration-tests/test-helper.js';
import { evalTest, assertModelHasOutput } from './test-helper.js';
describe('Hierarchical Memory', () => {
const conflictResolutionTest =
'Agent follows hierarchy for contradictory instructions';
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: conflictResolutionTest,
params: {
settings: {
@@ -48,6 +49,8 @@ What is my favorite fruit? Tell me just the name of the fruit.`,
const provenanceAwarenessTest = 'Agent is aware of memory provenance';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: provenanceAwarenessTest,
params: {
settings: {
@@ -87,6 +90,8 @@ Provide the answer as an XML block like this:
const extensionVsGlobalTest = 'Extension memory wins over Global memory';
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: extensionVsGlobalTest,
params: {
settings: {
+4
View File
@@ -8,6 +8,8 @@ describe('interactive_commands', () => {
* intervention.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not use interactive commands',
prompt: 'Execute tests.',
files: {
@@ -49,6 +51,8 @@ describe('interactive_commands', () => {
* Validates that the agent uses non-interactive flags when scaffolding a new project.
*/
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use non-interactive flags when scaffolding a new app',
prompt: 'Create a new react application named my-app using vite.',
assert: async (rig, result) => {
+4 -2
View File
@@ -5,14 +5,14 @@
*/
import { describe, expect } from 'vitest';
import { act } from 'react';
import path from 'node:path';
import fs from 'node:fs';
import { appEvalTest } from './app-test-helper.js';
import { PolicyDecision } from '@google/gemini-cli-core';
describe('Model Steering Behavioral Evals', () => {
appEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'Corrective Hint: Model switches task based on hint during tool turn',
configOverrides: {
modelSteering: true,
@@ -52,6 +52,8 @@ describe('Model Steering Behavioral Evals', () => {
});
appEvalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'Suggestive Hint: Model incorporates user guidance mid-stream',
configOverrides: {
modelSteering: true,
+94 -3
View File
@@ -15,7 +15,9 @@ import {
describe('plan_mode', () => {
const TEST_PREFIX = 'Plan Mode: ';
const settings = {
experimental: { plan: true },
general: {
plan: { enabled: true },
},
};
const getWriteTargets = (logs: any[]) =>
@@ -31,6 +33,8 @@ describe('plan_mode', () => {
.filter(Boolean);
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should refuse file modification when in plan mode',
approvalMode: ApprovalMode.PLAN,
params: {
@@ -66,6 +70,8 @@ describe('plan_mode', () => {
});
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should refuse saving new documentation to the repo when in plan mode',
approvalMode: ApprovalMode.PLAN,
params: {
@@ -103,6 +109,8 @@ describe('plan_mode', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should enter plan mode when asked to create a plan',
approvalMode: ApprovalMode.DEFAULT,
params: {
@@ -120,6 +128,8 @@ describe('plan_mode', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should exit plan mode when plan is complete and implementation is requested',
approvalMode: ApprovalMode.PLAN,
params: {
@@ -167,12 +177,15 @@ describe('plan_mode', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should allow file modification in plans directory when in plan mode',
approvalMode: ApprovalMode.PLAN,
params: {
settings,
},
prompt: 'Create a plan for a new login feature.',
prompt:
'I agree with the strategy to use a JWT-based login. Create a plan for a new login feature.',
assert: async (rig, result) => {
await rig.waitForTelemetryReady();
const toolLogs = rig.readToolLogs();
@@ -198,6 +211,8 @@ describe('plan_mode', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should create a plan in plan mode and implement it for a refactoring task',
params: {
settings,
@@ -209,7 +224,7 @@ describe('plan_mode', () => {
'import { sum } from "./mathUtils";\nconsole.log(sum(1, 2));',
},
prompt:
'I want to refactor our math utilities. Move the `sum` function from `src/mathUtils.ts` to a new file `src/basicMath.ts` and update `src/main.ts` to use the new file. Please create a detailed implementation plan first, then execute it.',
'I want to refactor our math utilities. I agree with the strategy to move the `sum` function from `src/mathUtils.ts` to a new file `src/basicMath.ts` and update `src/main.ts`. Please create a detailed implementation plan first, then execute it.',
assert: async (rig, result) => {
const enterPlanCalled = await rig.waitForToolCall('enter_plan_mode');
expect(
@@ -281,4 +296,80 @@ describe('plan_mode', () => {
assertModelHasOutput(result);
},
});
evalTest('ALWAYS_PASSES', {
name: 'should transition from plan mode to normal execution and create a plan file from scratch',
params: {
settings,
},
prompt:
'Enter plan mode and plan to create a new module called foo. The plan should be saved as foo-plan.md. Then, exit plan mode.',
assert: async (rig, result) => {
const enterPlanCalled = await rig.waitForToolCall('enter_plan_mode');
expect(
enterPlanCalled,
'Expected enter_plan_mode tool to be called',
).toBe(true);
const exitPlanCalled = await rig.waitForToolCall('exit_plan_mode');
expect(exitPlanCalled, 'Expected exit_plan_mode tool to be called').toBe(
true,
);
await rig.waitForTelemetryReady();
const toolLogs = rig.readToolLogs();
// Check if the plan file was written successfully
const planWrite = toolLogs.find(
(log) =>
log.toolRequest.name === 'write_file' &&
log.toolRequest.args.includes('foo-plan.md'),
);
expect(
planWrite,
'Expected write_file to be called for foo-plan.md',
).toBeDefined();
expect(
planWrite?.toolRequest.success,
`Expected write_file to succeed, but got error: ${planWrite?.toolRequest.error}`,
).toBe(true);
assertModelHasOutput(result);
},
});
evalTest('USUALLY_PASSES', {
name: 'should not exit plan mode or draft before informal agreement',
approvalMode: ApprovalMode.PLAN,
params: {
settings,
},
prompt: 'I need to build a new login feature. Please plan it.',
assert: async (rig, result) => {
await rig.waitForTelemetryReady();
const toolLogs = rig.readToolLogs();
const exitPlanCall = toolLogs.find(
(log) => log.toolRequest.name === 'exit_plan_mode',
);
expect(
exitPlanCall,
'Should NOT call exit_plan_mode before informal agreement',
).toBeUndefined();
const planWrite = toolLogs.find(
(log) =>
log.toolRequest.name === 'write_file' &&
log.toolRequest.args.includes('/plans/'),
);
expect(
planWrite,
'Should NOT draft the plan file before informal agreement',
).toBeUndefined();
assertModelHasOutput(result);
},
});
});
+2
View File
@@ -11,6 +11,8 @@ import fs from 'node:fs/promises';
describe('redundant_casts', () => {
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should not add redundant or unsafe casts when modifying typescript code',
files: {
'src/cast_example.ts': `
+2
View File
@@ -3,6 +3,8 @@ import { evalTest } from './test-helper.js';
describe('Sandbox recovery', () => {
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'attempts to use additional_permissions when operation not permitted',
prompt:
'Run ./script.sh. It will fail with "Operation not permitted". When it does, you must retry running it by passing the appropriate additional_permissions.',
+28 -2
View File
@@ -5,16 +5,18 @@
*/
import { describe, expect } from 'vitest';
import { evalTest } from './test-helper.js';
import {
evalTest,
assertModelHasOutput,
checkModelOutputContent,
} from '../integration-tests/test-helper.js';
} from './test-helper.js';
describe('save_memory', () => {
const TEST_PREFIX = 'Save memory test: ';
const rememberingFavoriteColor = "Agent remembers user's favorite color";
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingFavoriteColor,
prompt: `remember that my favorite color is blue.
@@ -35,6 +37,8 @@ describe('save_memory', () => {
});
const rememberingCommandRestrictions = 'Agent remembers command restrictions';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingCommandRestrictions,
prompt: `I don't want you to ever run npm commands.`,
@@ -54,6 +58,8 @@ describe('save_memory', () => {
const rememberingWorkflow = 'Agent remembers workflow preferences';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingWorkflow,
prompt: `I want you to always lint after building.`,
@@ -74,6 +80,8 @@ describe('save_memory', () => {
const ignoringTemporaryInformation =
'Agent ignores temporary conversation details';
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: ignoringTemporaryInformation,
prompt: `I'm going to get a coffee.`,
@@ -97,6 +105,8 @@ describe('save_memory', () => {
const rememberingPetName = "Agent remembers user's pet's name";
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingPetName,
prompt: `Please remember that my dog's name is Buddy.`,
@@ -116,6 +126,8 @@ describe('save_memory', () => {
const rememberingCommandAlias = 'Agent remembers custom command aliases';
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingCommandAlias,
prompt: `When I say 'start server', you should run 'npm run dev'.`,
@@ -136,6 +148,8 @@ describe('save_memory', () => {
const ignoringDbSchemaLocation =
"Agent ignores workspace's database schema location";
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: ignoringDbSchemaLocation,
prompt: `The database schema for this workspace is located in \`db/schema.sql\`.`,
assert: async (rig, result) => {
@@ -155,6 +169,8 @@ describe('save_memory', () => {
const rememberingCodingStyle =
"Agent remembers user's coding style preference";
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingCodingStyle,
prompt: `I prefer to use tabs instead of spaces for indentation.`,
@@ -175,6 +191,8 @@ describe('save_memory', () => {
const ignoringBuildArtifactLocation =
'Agent ignores workspace build artifact location';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: ignoringBuildArtifactLocation,
prompt: `In this workspace, build artifacts are stored in the \`dist/artifacts\` directory.`,
assert: async (rig, result) => {
@@ -193,6 +211,8 @@ describe('save_memory', () => {
const ignoringMainEntryPoint = "Agent ignores workspace's main entry point";
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: ignoringMainEntryPoint,
prompt: `The main entry point for this workspace is \`src/index.js\`.`,
assert: async (rig, result) => {
@@ -211,6 +231,8 @@ describe('save_memory', () => {
const rememberingBirthday = "Agent remembers user's birthday";
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: rememberingBirthday,
prompt: `My birthday is on June 15th.`,
@@ -231,6 +253,8 @@ describe('save_memory', () => {
const proactiveMemoryFromLongSession =
'Agent saves preference from earlier in conversation history';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: proactiveMemoryFromLongSession,
params: {
settings: {
@@ -309,6 +333,8 @@ describe('save_memory', () => {
const memoryManagerRoutingPreferences =
'Agent routes global and project preferences to memory';
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: memoryManagerRoutingPreferences,
params: {
settings: {
+6
View File
@@ -21,6 +21,8 @@ describe('Shell Efficiency', () => {
};
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use --silent/--quiet flags when installing packages',
prompt: 'Install the "lodash" package using npm.',
assert: async (rig) => {
@@ -50,6 +52,8 @@ describe('Shell Efficiency', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use --no-pager with git commands',
prompt: 'Show the git log.',
assert: async (rig) => {
@@ -73,6 +77,8 @@ describe('Shell Efficiency', () => {
});
evalTest('ALWAYS_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should NOT use efficiency flags when enableShellOutputEfficiency is disabled',
params: {
settings: {
+129 -19
View File
@@ -13,8 +13,21 @@ import { evalTest, TEST_AGENTS } from './test-helper.js';
const INDEX_TS = 'export const add = (a: number, b: number) => a + b;\n';
// A minimal package.json is used to provide a realistic workspace anchor.
// This prevents the agent from making incorrect assumptions about the environment
// and helps it properly navigate or act as if it is in a standard Node.js project.
const MOCK_PACKAGE_JSON = JSON.stringify(
{
name: 'subagent-eval-project',
version: '1.0.0',
type: 'module',
},
null,
2,
);
function readProjectFile(
rig: { testDir?: string },
rig: { testDir: string | null },
relativePath: string,
): string {
return fs.readFileSync(path.join(rig.testDir!, relativePath), 'utf8');
@@ -32,6 +45,8 @@ describe('subagent eval test cases', () => {
* This tests the system prompt's subagent specific clauses.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should delegate to user provided agent with relevant expertise',
params: {
settings: {
@@ -56,6 +71,8 @@ describe('subagent eval test cases', () => {
* subagents are available. This helps catch orchestration overuse.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should avoid delegating trivial direct edit work',
params: {
settings: {
@@ -100,6 +117,8 @@ describe('subagent eval test cases', () => {
* This is meant to codify the "overusing Generalist" failure mode.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should prefer relevant specialist over generalist',
params: {
settings: {
@@ -117,15 +136,7 @@ describe('subagent eval test cases', () => {
files: {
...TEST_AGENTS.TESTING_AGENT.asFile(),
'index.ts': INDEX_TS,
'package.json': JSON.stringify(
{
name: 'subagent-eval-project',
version: '1.0.0',
type: 'module',
},
null,
2,
),
'package.json': MOCK_PACKAGE_JSON,
},
assert: async (rig, _result) => {
const toolLogs = rig.readToolLogs() as Array<{
@@ -144,6 +155,8 @@ describe('subagent eval test cases', () => {
* naturally spans docs and tests, so multiple specialists should be used.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should use multiple relevant specialists for multi-surface task',
params: {
settings: {
@@ -164,15 +177,7 @@ describe('subagent eval test cases', () => {
...TEST_AGENTS.TESTING_AGENT.asFile(),
'index.ts': INDEX_TS,
'README.md': 'TODO: update the README.\n',
'package.json': JSON.stringify(
{
name: 'subagent-eval-project',
version: '1.0.0',
type: 'module',
},
null,
2,
),
'package.json': MOCK_PACKAGE_JSON,
},
assert: async (rig, _result) => {
const toolLogs = rig.readToolLogs() as Array<{
@@ -190,4 +195,109 @@ describe('subagent eval test cases', () => {
);
},
});
/**
* Checks that the main agent can correctly select the appropriate subagent
* from a large pool of available subagents (10 total).
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should select the correct subagent from a pool of 10 different agents',
prompt: 'Please add a new SQL table migration for a user profile.',
files: {
...TEST_AGENTS.DOCS_AGENT.asFile(),
...TEST_AGENTS.TESTING_AGENT.asFile(),
...TEST_AGENTS.DATABASE_AGENT.asFile(),
...TEST_AGENTS.CSS_AGENT.asFile(),
...TEST_AGENTS.I18N_AGENT.asFile(),
...TEST_AGENTS.SECURITY_AGENT.asFile(),
...TEST_AGENTS.DEVOPS_AGENT.asFile(),
...TEST_AGENTS.ANALYTICS_AGENT.asFile(),
...TEST_AGENTS.ACCESSIBILITY_AGENT.asFile(),
...TEST_AGENTS.MOBILE_AGENT.asFile(),
'package.json': MOCK_PACKAGE_JSON,
},
assert: async (rig, _result) => {
const toolLogs = rig.readToolLogs() as Array<{
toolRequest: { name: string };
}>;
await rig.expectToolCallSuccess(['database-agent']);
// Ensure the generalist and other irrelevant specialists were not invoked
const uncalledAgents = [
'generalist',
TEST_AGENTS.DOCS_AGENT.name,
TEST_AGENTS.TESTING_AGENT.name,
TEST_AGENTS.CSS_AGENT.name,
TEST_AGENTS.I18N_AGENT.name,
TEST_AGENTS.SECURITY_AGENT.name,
TEST_AGENTS.DEVOPS_AGENT.name,
TEST_AGENTS.ANALYTICS_AGENT.name,
TEST_AGENTS.ACCESSIBILITY_AGENT.name,
TEST_AGENTS.MOBILE_AGENT.name,
];
for (const agentName of uncalledAgents) {
expect(toolLogs.some((l) => l.toolRequest.name === agentName)).toBe(
false,
);
}
},
});
/**
* Checks that the main agent can correctly select the appropriate subagent
* from a large pool of available subagents, even when many irrelevant MCP tools are present.
*
* This test includes stress tests the subagent delegation with ~80 tools.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should select the correct subagent from a pool of 10 different agents with MCP tools present',
prompt: 'Please add a new SQL table migration for a user profile.',
setup: async (rig) => {
rig.addTestMcpServer('workspace-server', 'google-workspace');
},
files: {
...TEST_AGENTS.DOCS_AGENT.asFile(),
...TEST_AGENTS.TESTING_AGENT.asFile(),
...TEST_AGENTS.DATABASE_AGENT.asFile(),
...TEST_AGENTS.CSS_AGENT.asFile(),
...TEST_AGENTS.I18N_AGENT.asFile(),
...TEST_AGENTS.SECURITY_AGENT.asFile(),
...TEST_AGENTS.DEVOPS_AGENT.asFile(),
...TEST_AGENTS.ANALYTICS_AGENT.asFile(),
...TEST_AGENTS.ACCESSIBILITY_AGENT.asFile(),
...TEST_AGENTS.MOBILE_AGENT.asFile(),
'package.json': MOCK_PACKAGE_JSON,
},
assert: async (rig, _result) => {
const toolLogs = rig.readToolLogs() as Array<{
toolRequest: { name: string };
}>;
await rig.expectToolCallSuccess(['database-agent']);
// Ensure the generalist and other irrelevant specialists were not invoked
const uncalledAgents = [
'generalist',
TEST_AGENTS.DOCS_AGENT.name,
TEST_AGENTS.TESTING_AGENT.name,
TEST_AGENTS.CSS_AGENT.name,
TEST_AGENTS.I18N_AGENT.name,
TEST_AGENTS.SECURITY_AGENT.name,
TEST_AGENTS.DEVOPS_AGENT.name,
TEST_AGENTS.ANALYTICS_AGENT.name,
TEST_AGENTS.ACCESSIBILITY_AGENT.name,
TEST_AGENTS.MOBILE_AGENT.name,
];
for (const agentName of uncalledAgents) {
expect(toolLogs.some((l) => l.toolRequest.name === agentName)).toBe(
false,
);
}
},
});
});
+219
View File
@@ -0,0 +1,219 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';
import { internalEvalTest } from './test-helper.js';
import { TestRig } from '@google/gemini-cli-test-utils';
// Mock TestRig to control API success/failure
vi.mock('@google/gemini-cli-test-utils', () => {
return {
TestRig: vi.fn().mockImplementation(() => ({
setup: vi.fn(),
run: vi.fn(),
cleanup: vi.fn(),
readToolLogs: vi.fn().mockReturnValue([]),
_lastRunStderr: '',
})),
};
});
describe('evalTest reliability logic', () => {
const LOG_DIR = path.resolve(process.cwd(), 'evals/logs');
const RELIABILITY_LOG = path.join(LOG_DIR, 'api-reliability.jsonl');
beforeEach(() => {
vi.clearAllMocks();
if (fs.existsSync(RELIABILITY_LOG)) {
fs.unlinkSync(RELIABILITY_LOG);
}
});
afterEach(() => {
if (fs.existsSync(RELIABILITY_LOG)) {
fs.unlinkSync(RELIABILITY_LOG);
}
});
it('should retry 3 times on 500 INTERNAL error and then SKIP', async () => {
const mockRig = new TestRig() as any;
(TestRig as any).mockReturnValue(mockRig);
// Simulate permanent 500 error
mockRig.run.mockRejectedValue(new Error('status: INTERNAL - API Down'));
// Execute the test function directly
await internalEvalTest({
suiteName: 'test',
suiteType: 'behavioral',
name: 'test-api-failure',
prompt: 'do something',
assert: async () => {},
});
// Verify retries: 1 initial + 3 retries = 4 setups/runs
expect(mockRig.run).toHaveBeenCalledTimes(4);
// Verify log content
const logContent = fs
.readFileSync(RELIABILITY_LOG, 'utf-8')
.trim()
.split('\n');
expect(logContent.length).toBe(4);
const entries = logContent.map((line) => JSON.parse(line));
expect(entries[0].status).toBe('RETRY');
expect(entries[0].attempt).toBe(0);
expect(entries[3].status).toBe('SKIP');
expect(entries[3].attempt).toBe(3);
expect(entries[3].testName).toBe('test-api-failure');
});
it('should fail immediately on non-500 errors (like assertion failures)', async () => {
const mockRig = new TestRig() as any;
(TestRig as any).mockReturnValue(mockRig);
// Simulate a real logic error/bug
mockRig.run.mockResolvedValue('Success');
const assertError = new Error('Assertion failed: expected foo to be bar');
// Expect the test function to throw immediately
await expect(
internalEvalTest({
suiteName: 'test',
suiteType: 'behavioral',
name: 'test-logic-failure',
prompt: 'do something',
assert: async () => {
throw assertError;
},
}),
).rejects.toThrow('Assertion failed');
// Verify NO retries: only 1 attempt
expect(mockRig.run).toHaveBeenCalledTimes(1);
// Verify NO reliability log was created (it's not an API error)
expect(fs.existsSync(RELIABILITY_LOG)).toBe(false);
});
it('should recover if a retry succeeds', async () => {
const mockRig = new TestRig() as any;
(TestRig as any).mockReturnValue(mockRig);
// Fail once, then succeed
mockRig.run
.mockRejectedValueOnce(new Error('status: INTERNAL'))
.mockResolvedValueOnce('Success');
await internalEvalTest({
suiteName: 'test',
suiteType: 'behavioral',
name: 'test-recovery',
prompt: 'do something',
assert: async () => {},
});
// Ran twice: initial (fail) + retry 1 (success)
expect(mockRig.run).toHaveBeenCalledTimes(2);
// Log should only have the one RETRY entry
const logContent = fs
.readFileSync(RELIABILITY_LOG, 'utf-8')
.trim()
.split('\n');
expect(logContent.length).toBe(1);
expect(JSON.parse(logContent[0]).status).toBe('RETRY');
});
it('should retry 3 times on 503 UNAVAILABLE error and then SKIP', async () => {
const mockRig = new TestRig() as any;
(TestRig as any).mockReturnValue(mockRig);
// Simulate permanent 503 error
mockRig.run.mockRejectedValue(
new Error('status: UNAVAILABLE - Service Busy'),
);
await internalEvalTest({
suiteName: 'test',
suiteType: 'behavioral',
name: 'test-api-503',
prompt: 'do something',
assert: async () => {},
});
expect(mockRig.run).toHaveBeenCalledTimes(4);
const logContent = fs
.readFileSync(RELIABILITY_LOG, 'utf-8')
.trim()
.split('\n');
const entries = logContent.map((line) => JSON.parse(line));
expect(entries[0].errorCode).toBe('503');
expect(entries[3].status).toBe('SKIP');
});
it('should throw if an absolute path is used in files', async () => {
const mockRig = new TestRig() as any;
(TestRig as any).mockReturnValue(mockRig);
mockRig.testDir = path.resolve(process.cwd(), 'test-dir-tmp');
if (!fs.existsSync(mockRig.testDir)) {
fs.mkdirSync(mockRig.testDir, { recursive: true });
}
try {
await expect(
internalEvalTest({
suiteName: 'test',
suiteType: 'behavioral',
name: 'test-absolute-path',
prompt: 'do something',
files: {
'/etc/passwd': 'hacked',
},
assert: async () => {},
}),
).rejects.toThrow('Invalid file path in test case: /etc/passwd');
} finally {
if (fs.existsSync(mockRig.testDir)) {
fs.rmSync(mockRig.testDir, { recursive: true, force: true });
}
}
});
it('should throw if directory traversal is detected in files', async () => {
const mockRig = new TestRig() as any;
(TestRig as any).mockReturnValue(mockRig);
mockRig.testDir = path.resolve(process.cwd(), 'test-dir-tmp');
// Create a mock test-dir
if (!fs.existsSync(mockRig.testDir)) {
fs.mkdirSync(mockRig.testDir, { recursive: true });
}
try {
await expect(
internalEvalTest({
suiteName: 'test',
suiteType: 'behavioral',
name: 'test-traversal',
prompt: 'do something',
files: {
'../sensitive.txt': 'hacked',
},
assert: async () => {},
}),
).rejects.toThrow('Invalid file path in test case: ../sensitive.txt');
} finally {
if (fs.existsSync(mockRig.testDir)) {
fs.rmSync(mockRig.testDir, { recursive: true, force: true });
}
}
});
});
+225 -80
View File
@@ -16,10 +16,19 @@ import {
Storage,
getProjectHash,
SESSION_FILE_PREFIX,
PREVIEW_GEMINI_FLASH_MODEL,
getErrorMessage,
} from '@google/gemini-cli-core';
export * from '@google/gemini-cli-test-utils';
/**
* The default model used for all evaluations.
* Can be overridden by setting the GEMINI_MODEL environment variable.
*/
export const EVAL_MODEL =
process.env['GEMINI_MODEL'] || PREVIEW_GEMINI_FLASH_MODEL;
// Indicates the consistency expectation for this test.
// - ALWAYS_PASSES - Means that the test is expected to pass 100% of the time. These
// These tests are typically trivial and test basic functionality with unambiguous
@@ -39,87 +48,75 @@ export * from '@google/gemini-cli-test-utils';
export type EvalPolicy = 'ALWAYS_PASSES' | 'USUALLY_PASSES';
export function evalTest(policy: EvalPolicy, evalCase: EvalCase) {
const fn = async () => {
runEval(policy, evalCase, () => internalEvalTest(evalCase));
}
export async function withEvalRetries(
name: string,
attemptFn: (attempt: number) => Promise<void>,
) {
const maxRetries = 3;
let attempt = 0;
while (attempt <= maxRetries) {
try {
await attemptFn(attempt);
return; // Success! Exit the retry loop.
} catch (error: unknown) {
const errorMessage = getErrorMessage(error);
const errorCode = getApiErrorCode(errorMessage);
if (errorCode) {
const status = attempt < maxRetries ? 'RETRY' : 'SKIP';
logReliabilityEvent(name, attempt, status, errorCode, errorMessage);
if (attempt < maxRetries) {
attempt++;
console.warn(
`[Eval] Attempt ${attempt} failed with ${errorCode} Error. Retrying...`,
);
continue; // Retry
}
console.warn(
`[Eval] '${name}' failed after ${maxRetries} retries due to persistent API errors. Skipping failure to avoid blocking PR.`,
);
return; // Gracefully exit without failing the test
}
throw error; // Real failure
}
}
}
export async function internalEvalTest(evalCase: EvalCase) {
await withEvalRetries(evalCase.name, async () => {
const rig = new TestRig();
const { logDir, sanitizedName } = await prepareLogDir(evalCase.name);
const activityLogFile = path.join(logDir, `${sanitizedName}.jsonl`);
const logFile = path.join(logDir, `${sanitizedName}.log`);
let isSuccess = false;
try {
rig.setup(evalCase.name, evalCase.params);
// Symlink node modules to reduce the amount of time needed to
// bootstrap test projects.
symlinkNodeModules(rig.testDir || '');
try {
const setupOptions = {
...evalCase.params,
settings: {
model: { name: EVAL_MODEL },
...evalCase.params?.settings,
},
};
rig.setup(evalCase.name, setupOptions);
if (evalCase.setup) {
await evalCase.setup(rig);
}
if (evalCase.files) {
const acknowledgedAgents: Record<string, Record<string, string>> = {};
const projectRoot = fs.realpathSync(rig.testDir!);
for (const [filePath, content] of Object.entries(evalCase.files)) {
const fullPath = path.join(rig.testDir!, filePath);
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, content);
// If it's an agent file, calculate hash for acknowledgement
if (
filePath.startsWith('.gemini/agents/') &&
filePath.endsWith('.md')
) {
const hash = crypto
.createHash('sha256')
.update(content)
.digest('hex');
try {
const agentDefs = await parseAgentMarkdown(fullPath, content);
if (agentDefs.length > 0) {
const agentName = agentDefs[0].name;
if (!acknowledgedAgents[projectRoot]) {
acknowledgedAgents[projectRoot] = {};
}
acknowledgedAgents[projectRoot][agentName] = hash;
}
} catch (error) {
console.warn(
`Failed to parse agent for test acknowledgement: ${filePath}`,
error,
);
}
}
}
// Write acknowledged_agents.json to the home directory
if (Object.keys(acknowledgedAgents).length > 0) {
const ackPath = path.join(
rig.homeDir!,
'.gemini',
'acknowledgments',
'agents.json',
);
fs.mkdirSync(path.dirname(ackPath), { recursive: true });
fs.writeFileSync(
ackPath,
JSON.stringify(acknowledgedAgents, null, 2),
);
}
const execOptions = { cwd: rig.testDir!, stdio: 'inherit' as const };
execSync('git init', execOptions);
execSync('git config user.email "test@example.com"', execOptions);
execSync('git config user.name "Test User"', execOptions);
// Temporarily disable the interactive editor and git pager
// to avoid hanging the tests. It seems the the agent isn't
// consistently honoring the instructions to avoid interactive
// commands.
execSync('git config core.editor "true"', execOptions);
execSync('git config core.pager "cat"', execOptions);
execSync('git config commit.gpgsign false', execOptions);
execSync('git add .', execOptions);
execSync('git commit --allow-empty -m "Initial commit"', execOptions);
await prepareWorkspace(rig.testDir!, rig.homeDir!, evalCase.files);
}
symlinkNodeModules(rig.testDir || '');
// If messages are provided, write a session file so --resume can load it.
let sessionId: string | undefined;
if (evalCase.messages) {
@@ -206,9 +203,135 @@ export function evalTest(policy: EvalPolicy, evalCase: EvalCase) {
);
await rig.cleanup();
}
});
}
function getApiErrorCode(message: string): '500' | '503' | undefined {
if (
message.includes('status: UNAVAILABLE') ||
message.includes('code: 503') ||
message.includes('Service Unavailable')
) {
return '503';
}
if (
message.includes('status: INTERNAL') ||
message.includes('code: 500') ||
message.includes('Internal error encountered')
) {
return '500';
}
return undefined;
}
/**
* Log reliability event for later harvesting.
*
* Note: Uses synchronous file I/O to ensure the log is persisted even if the
* test process is abruptly terminated by a timeout or CI crash. Performance
* impact is negligible compared to long-running evaluation tests.
*/
function logReliabilityEvent(
testName: string,
attempt: number,
status: 'RETRY' | 'SKIP',
errorCode: '500' | '503',
errorMessage: string,
) {
const reliabilityLog = {
timestamp: new Date().toISOString(),
testName,
model: process.env['GEMINI_MODEL'] || 'unknown',
attempt,
status,
errorCode,
error: errorMessage,
};
runEval(policy, evalCase.name, fn, evalCase.timeout);
try {
const relDir = path.resolve(process.cwd(), 'evals/logs');
fs.mkdirSync(relDir, { recursive: true });
fs.appendFileSync(
path.join(relDir, 'api-reliability.jsonl'),
JSON.stringify(reliabilityLog) + '\n',
);
} catch (logError) {
console.error('Failed to write reliability log:', logError);
}
}
/**
* Helper to setup test files and git repository.
*
* Note: While this is an async function (due to parseAgentMarkdown), it
* intentionally uses synchronous filesystem and child_process operations
* for simplicity and to ensure sequential environment preparation.
*/
export async function prepareWorkspace(
testDir: string,
homeDir: string,
files: Record<string, string>,
) {
const acknowledgedAgents: Record<string, Record<string, string>> = {};
const projectRoot = fs.realpathSync(testDir);
for (const [filePath, content] of Object.entries(files)) {
if (filePath.includes('..') || path.isAbsolute(filePath)) {
throw new Error(`Invalid file path in test case: ${filePath}`);
}
const fullPath = path.join(projectRoot, filePath);
if (!fullPath.startsWith(projectRoot)) {
throw new Error(`Path traversal detected: ${filePath}`);
}
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, content);
if (filePath.startsWith('.gemini/agents/') && filePath.endsWith('.md')) {
const hash = crypto.createHash('sha256').update(content).digest('hex');
try {
const agentDefs = await parseAgentMarkdown(fullPath, content);
if (agentDefs.length > 0) {
const agentName = agentDefs[0].name;
if (!acknowledgedAgents[projectRoot]) {
acknowledgedAgents[projectRoot] = {};
}
acknowledgedAgents[projectRoot][agentName] = hash;
}
} catch (error) {
console.warn(
`Failed to parse agent for test acknowledgement: ${filePath}`,
error,
);
}
}
}
if (Object.keys(acknowledgedAgents).length > 0) {
const ackPath = path.join(
homeDir,
'.gemini',
'acknowledgments',
'agents.json',
);
fs.mkdirSync(path.dirname(ackPath), { recursive: true });
fs.writeFileSync(ackPath, JSON.stringify(acknowledgedAgents, null, 2));
}
const execOptions = { cwd: testDir, stdio: 'ignore' as const };
execSync('git init --initial-branch=main', execOptions);
execSync('git config user.email "test@example.com"', execOptions);
execSync('git config user.name "Test User"', execOptions);
// Temporarily disable the interactive editor and git pager
// to avoid hanging the tests. It seems the the agent isn't
// consistently honoring the instructions to avoid interactive
// commands.
execSync('git config core.editor "true"', execOptions);
execSync('git config core.pager "cat"', execOptions);
execSync('git config commit.gpgsign false', execOptions);
execSync('git add .', execOptions);
execSync('git commit --allow-empty -m "Initial commit"', execOptions);
}
/**
@@ -216,14 +339,30 @@ export function evalTest(policy: EvalPolicy, evalCase: EvalCase) {
*/
export function runEval(
policy: EvalPolicy,
name: string,
evalCase: BaseEvalCase,
fn: () => Promise<void>,
timeout?: number,
timeoutOverride?: number,
) {
if (policy === 'USUALLY_PASSES' && !process.env['RUN_EVALS']) {
it.skip(name, fn);
const { name, timeout, suiteName, suiteType } = evalCase;
const targetSuiteType = process.env['EVAL_SUITE_TYPE'];
const targetSuiteName = process.env['EVAL_SUITE_NAME'];
const meta = { suiteType, suiteName };
const skipBySuiteType =
targetSuiteType && suiteType && suiteType !== targetSuiteType;
const skipBySuiteName =
targetSuiteName && suiteName && suiteName !== targetSuiteName;
const options = { timeout: timeoutOverride ?? timeout, meta };
if (
(policy === 'USUALLY_PASSES' && !process.env['RUN_EVALS']) ||
skipBySuiteType ||
skipBySuiteName
) {
it.skip(name, options, fn);
} else {
it(name, fn, timeout);
it(name, options, fn);
}
}
@@ -262,15 +401,21 @@ interface ForbiddenToolSettings {
};
}
export interface EvalCase {
export interface BaseEvalCase {
suiteName: string;
suiteType: 'behavioral' | 'component-level' | 'hero-scenario';
name: string;
timeout?: number;
files?: Record<string, string>;
}
export interface EvalCase extends BaseEvalCase {
params?: {
settings?: ForbiddenToolSettings & Record<string, unknown>;
[key: string]: unknown;
};
prompt: string;
timeout?: number;
files?: Record<string, string>;
setup?: (rig: TestRig) => Promise<void> | void;
/** Conversation history to pre-load via --resume. Each entry is a message object with type, content, etc. */
messages?: Record<string, unknown>[];
/** Session ID for the resumed session. Auto-generated if not provided. */
+4
View File
@@ -31,6 +31,8 @@ describe('Tool Output Masking Behavioral Evals', () => {
* It should recognize the <tool_output_masked> tag and use a tool to read the file.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should attempt to read the redirected full output file when information is masked',
params: {
security: {
@@ -167,6 +169,8 @@ Output too large. Full output available at: ${outputFilePath}
* Scenario: Information is in the preview.
*/
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should NOT read the full output file when the information is already in the preview',
params: {
security: {
+21
View File
@@ -25,6 +25,8 @@ const FILES = {
describe('tracker_mode', () => {
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should manage tasks in the tracker when explicitly requested during a bug fix',
params: {
settings: { experimental: { taskTracker: true } },
@@ -78,6 +80,8 @@ describe('tracker_mode', () => {
});
evalTest('USUALLY_PASSES', {
suiteName: 'default',
suiteType: 'behavioral',
name: 'should implicitly create tasks when asked to build a feature plan',
params: {
settings: { experimental: { taskTracker: true } },
@@ -113,4 +117,21 @@ describe('tracker_mode', () => {
assertModelHasOutput(result);
},
});
evalTest('USUALLY_PASSES', {
name: 'should correctly identify the task tracker storage location from the system prompt',
params: {
settings: { experimental: { taskTracker: true } },
},
prompt:
'Where is my task tracker storage located? Please provide the absolute path in your response.',
assert: async (rig, result) => {
// The rig sets GEMINI_CLI_HOME to rig.homeDir
const homeDir = rig.homeDir!;
// The response should contain the dynamic path which includes the home directory
// and follows the .gemini/tmp/.../tracker structure.
expect(result).toContain(homeDir);
expect(result).toMatch(/\.gemini\/tmp\/.*\/tracker/);
},
});
});

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