mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-23 00:01:24 -07:00
Compare commits
1434 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f88488d1f9 | |||
| 1fd42802be | |||
| ab64b15d51 | |||
| e406dcc249 | |||
| 680077631d | |||
| 9fc03a0c12 | |||
| 4f4431e4e1 | |||
| 527074b50a | |||
| a17691f0fc | |||
| d246315cea | |||
| e92ccec6c8 | |||
| b68d7bc0f9 | |||
| 4c9f9bb3e2 | |||
| e7b20c49ac | |||
| 743d05b37f | |||
| 95074a1a84 | |||
| 759575faa8 | |||
| d485e08606 | |||
| 0f1258305a | |||
| 09e99824d4 | |||
| 96b939f63a | |||
| 7837194ab5 | |||
| 35ee2a841a | |||
| a253938ac5 | |||
| 37ffd608fd | |||
| 0f019122b0 | |||
| 936f6240dd | |||
| f8dd6f4f4c | |||
| ca7ac00030 | |||
| d41735d6a9 | |||
| d012929a28 | |||
| 97dfbd4598 | |||
| 237864eb63 | |||
| dc6741097c | |||
| dac3735626 | |||
| 245b68e9f1 | |||
| e89cf5d86e | |||
| 54b0344fc5 | |||
| e5d58c2b5a | |||
| 9455ecd78c | |||
| 0fd09e0150 | |||
| 9a7427197b | |||
| 33be30ab04 | |||
| 6c3a90645a | |||
| 32e61529f5 | |||
| 931e668b47 | |||
| 7989c28d2e | |||
| 2965c115f1 | |||
| 7d31d5f4ec | |||
| 1a7d4184cd | |||
| 7dce23e5d9 | |||
| 06a176e33e | |||
| 42d367d72f | |||
| 6f579934db | |||
| 6d607a5953 | |||
| 4669148a4c | |||
| 82316ef6e4 | |||
| 337e4bc8c6 | |||
| d97eaf3420 | |||
| 0452f787b2 | |||
| c1317aafb3 | |||
| f17f05373e | |||
| 6691fac50e | |||
| 35c1999341 | |||
| 5575c5ff66 | |||
| 0833aca64b | |||
| 509d4ae0a9 | |||
| 4d310dda68 | |||
| e7be0d7bcc | |||
| a8f507352b | |||
| 6aa6630137 | |||
| 7ec477d40d | |||
| 19c9508fd1 | |||
| e8bc7bea44 | |||
| 1ba9d71284 | |||
| 1aa4a32066 | |||
| 22d962e761 | |||
| 0135b03c8a | |||
| 9773a084c9 | |||
| a830858f91 | |||
| f47cb3c136 | |||
| 291639633f | |||
| c7e2dbe0cf | |||
| 31d65f40bd | |||
| 93d9adc03c | |||
| d2726d4a43 | |||
| 1c3c7a343f | |||
| f20e45175e | |||
| 0228c2b9f0 | |||
| ddafd79661 | |||
| 09259a8ec4 | |||
| 173376ba67 | |||
| 013d5dfbb0 | |||
| 3d4956aa57 | |||
| 9dc6898d28 | |||
| c5112cde46 | |||
| c72cfad92c | |||
| 205d69eb07 | |||
| 3481032980 | |||
| a5fd5d0b9f | |||
| 55db3c776c | |||
| e63d273e4e | |||
| 4c85d14f48 | |||
| efec63658a | |||
| c59ef74837 | |||
| 29b3aa860c | |||
| 1c92824636 | |||
| e200b40408 | |||
| 8f36051f32 | |||
| ac4e65d669 | |||
| 6f3c3c7967 | |||
| 212402bd53 | |||
| 49e4082f38 | |||
| 54885214a1 | |||
| 717660997d | |||
| bc89b05f01 | |||
| 66721379f8 | |||
| df74b89876 | |||
| 25e9613594 | |||
| 94ba7ec319 | |||
| 07d2187a76 | |||
| 352fb0c976 | |||
| 7011c13ee6 | |||
| 12957ea16a | |||
| 1017b78157 | |||
| 7e06559db2 | |||
| bbcfff5cf1 | |||
| 5bd21a240d | |||
| fdfd626f28 | |||
| 0659ad1702 | |||
| a63c76522a | |||
| af424aefa9 | |||
| 28af4e127f | |||
| d25088956d | |||
| 75737c1b44 | |||
| 533b65188d | |||
| 066b0cc15f | |||
| 1124e49f34 | |||
| df14a6c2db | |||
| 34f0c1538b | |||
| c70c95ead3 | |||
| f3bbe6e77a | |||
| 28e79831ac | |||
| fdf5b18cfb | |||
| b5f3eb2c9c | |||
| 2a84090dd5 | |||
| 27d7aeb1ed | |||
| d6c560498b | |||
| 4500da339b | |||
| 4be08a2261 | |||
| fe332bbef7 | |||
| 50af050623 | |||
| e5207eb67f | |||
| f15bcaf499 | |||
| 5f2f60bed6 | |||
| c332d1e636 | |||
| aa158e18d3 | |||
| fca29b0bd8 | |||
| 1e2afbb514 | |||
| 208291f391 | |||
| 8303edbb54 | |||
| 0d69f9f7fa | |||
| 46231a1755 | |||
| 2e7722d6a3 | |||
| 69e15a50d1 | |||
| 25f59a0099 | |||
| 01927a36d1 | |||
| 06ddfa5c4c | |||
| 3f7ef816f1 | |||
| d05ba11a31 | |||
| e43b1cff58 | |||
| bb6d1a2775 | |||
| dd9ccc9807 | |||
| 8133d63ac6 | |||
| 18d0375a7f | |||
| 31ca57ec94 | |||
| b7a8f0d1f9 | |||
| 1502e5cbc3 | |||
| 7ca3a33f8b | |||
| ce5a2d0760 | |||
| aa321b3d8c | |||
| 3a7a6e1540 | |||
| 66530e44c8 | |||
| b034dcd412 | |||
| 659301ff83 | |||
| 446a4316c4 | |||
| 48412a068e | |||
| 2e1efaebe4 | |||
| 7c9fceba7f | |||
| 740efa2ac2 | |||
| 703759cfae | |||
| 0063581e47 | |||
| 6757d4b5c5 | |||
| a153ff587b | |||
| cd3a8c3f07 | |||
| b2214a6676 | |||
| 6c65a2d813 | |||
| fae0639ba2 | |||
| 76f70d65ff | |||
| fb6ff847dd | |||
| 1ca5c05d0d | |||
| 0c6c9c6a62 | |||
| a1367e9cdd | |||
| c89d4f9c6c | |||
| 08ee136132 | |||
| 07f51c324e | |||
| ba149afa0b | |||
| f6533c0250 | |||
| 5e3b1fe945 | |||
| 05ef2eb362 | |||
| 966b9059d0 | |||
| ca13458412 | |||
| 20d884da2f | |||
| 6a0f4d3bdd | |||
| 0b682538d2 | |||
| 7f8ce8657c | |||
| 1c8951334a | |||
| b2b6092c24 | |||
| e00e8f4728 | |||
| b2cbf518e8 | |||
| c914fd0700 | |||
| 5d24d6a9e1 | |||
| ea48bd9414 | |||
| b2d6844f9b | |||
| fdd844b405 | |||
| 23905bcd77 | |||
| ec39aa17c2 | |||
| 7a1f2f3288 | |||
| 59c0e73718 | |||
| 3b2632fe40 | |||
| e709789067 | |||
| 514d431049 | |||
| 32e777f838 | |||
| 14dd07be00 | |||
| d7320f5425 | |||
| 25ade7bcb7 | |||
| ac4d0c20d8 | |||
| 4d9cc36146 | |||
| 66b8922d66 | |||
| 58df1c6237 | |||
| 522e95439c | |||
| 82336de7a4 | |||
| 83a3851dfd | |||
| e17f927a69 | |||
| b1befee8fb | |||
| 4b7ce1fe67 | |||
| ecfa4e0437 | |||
| 085441352b | |||
| 049d48ef60 | |||
| bc622a443e | |||
| 9b7852f11c | |||
| 6dc9d5ff11 | |||
| b8d6041d42 | |||
| aa98cafca7 | |||
| f700c923d9 | |||
| edb1fdea30 | |||
| 10c5bd8ce9 | |||
| 9de8349cf0 | |||
| 020da58327 | |||
| ac454bcfbc | |||
| c7a70e6421 | |||
| 611d934829 | |||
| 9c2fd5a7c6 | |||
| 3db35812b7 | |||
| 8380f0a3b1 | |||
| ef247e220d | |||
| 39938000a9 | |||
| d128fb0f7b | |||
| 37903d5dbb | |||
| a3821a9440 | |||
| 0bf3a015e8 | |||
| 28c9a907de | |||
| f9f916e1dc | |||
| 78dfe9dea8 | |||
| c9d07b62f2 | |||
| 189ab6c637 | |||
| 4aec3cdb24 | |||
| b765fb8af4 | |||
| fb0c7d268f | |||
| be12371380 | |||
| a037b961b1 | |||
| 6c739955c0 | |||
| 50947c57ce | |||
| 29e8f2abf4 | |||
| bf278ef2b0 | |||
| 1f9da6723f | |||
| 3ff5cfaaf6 | |||
| 70b650122f | |||
| 16d3883642 | |||
| 5c23f7f6e0 | |||
| d47d4855db | |||
| 6510347d5b | |||
| 4dd940f8ce | |||
| 87f7f0beb7 | |||
| 8e9ce3f4c3 | |||
| 812794a471 | |||
| 3c6539a32c | |||
| e4204d5939 | |||
| baccda969d | |||
| 9e95b8b3c5 | |||
| 182c858e67 | |||
| c0b76af442 | |||
| 4efdbe9089 | |||
| 15f6c8b8da | |||
| ee2e947435 | |||
| 6676546a4b | |||
| d143a83d5b | |||
| e69e23e4a0 | |||
| 81cd2561dc | |||
| b0ceb74462 | |||
| ee5eb70070 | |||
| dde844dbe1 | |||
| 05bc0399f3 | |||
| 3409de774c | |||
| 175ffc452b | |||
| 544df749af | |||
| 56c8d7e985 | |||
| 2ff7738b5d | |||
| 1ad26adb2b | |||
| af5aec69da | |||
| dae67983a8 | |||
| 70856d5a6e | |||
| cec45a1ebc | |||
| 767d80e768 | |||
| 3e5e608a22 | |||
| 0bc2d3ab16 | |||
| 31960c3388 | |||
| 0cc4f09595 | |||
| 70336e73b1 | |||
| 7cfbb6fb71 | |||
| a105768de8 | |||
| 347f3fe7e4 | |||
| 25803e05fd | |||
| 774ae220be | |||
| 813e0c18ac | |||
| 3f6cec22e6 | |||
| 3966f3c053 | |||
| 2e3cbd6363 | |||
| 8b1dc15182 | |||
| fa9aee2bf0 | |||
| 6628cbb39d | |||
| aa9163da60 | |||
| ec0f23ae03 | |||
| ac04c388e0 | |||
| 621ddbe744 | |||
| c537fd5aec | |||
| a91bc60e18 | |||
| faa1ec3044 | |||
| d96bd05d36 | |||
| 84666e1bbc | |||
| a7d851146a | |||
| acb7f577de | |||
| d2d345f41a | |||
| dfd7721e69 | |||
| 09218572d0 | |||
| 5d98ed5820 | |||
| 727f9b67b1 | |||
| 547f5d45f5 | |||
| 58d637f919 | |||
| b746524a1b | |||
| c5baf39dbd | |||
| b48970da15 | |||
| 9a8e5d3940 | |||
| 089aec8b8d | |||
| b7555ab1e1 | |||
| c04602f209 | |||
| a01d7e9a05 | |||
| 49b2e76ee1 | |||
| aed348a99c | |||
| 7cf4c05c66 | |||
| cdf157e52a | |||
| 723f269df6 | |||
| 239aa0909c | |||
| 6cfd29ef9b | |||
| f97b04cc9a | |||
| 788a40c445 | |||
| ce03156c9f | |||
| fe428936d5 | |||
| d24f10b087 | |||
| d54702185b | |||
| 27b7fc04de | |||
| be03e0619f | |||
| 2bb7aaecd0 | |||
| 0f855fc0c4 | |||
| c7e309efc9 | |||
| 429932c663 | |||
| d08b1efc72 | |||
| c3b52b8206 | |||
| 5fd557347e | |||
| cbfb2a4e26 | |||
| fb1b1b451d | |||
| 99fa700231 | |||
| f1c0a695f8 | |||
| 6351352e54 | |||
| 2ac39b6acc | |||
| d8b24e6983 | |||
| d25c469f77 | |||
| 537e56ffae | |||
| 2cba2ab37a | |||
| 8064973899 | |||
| ddc5458451 | |||
| a468407098 | |||
| 264c7aceaa | |||
| 3408542a66 | |||
| c276d0c7b6 | |||
| a00eb3b8e6 | |||
| 372f41eab8 | |||
| 09b623fbd7 | |||
| ba3e327ba1 | |||
| 5d235952ba | |||
| 082f41f54d | |||
| 880af43b02 | |||
| 966eef14ee | |||
| b79e5ce56d | |||
| 1a8d77329e | |||
| ad9c49a604 | |||
| 70b427c7dd | |||
| a804f99fe0 | |||
| c43500c50b | |||
| 42a7d89999 | |||
| 04f65f3d55 | |||
| 04c52513e7 | |||
| c62340675a | |||
| ef65498031 | |||
| 261788cf91 | |||
| 012392ad0a | |||
| 037061e2e0 | |||
| 221ea360b9 | |||
| 8910b2720f | |||
| 87f5dd15d6 | |||
| 81c8893e05 | |||
| 178388d931 | |||
| e7f97dfa44 | |||
| f961e0d6b1 | |||
| 14415316c0 | |||
| 1cf05b0375 | |||
| 3099df1b7c | |||
| 758d419e33 | |||
| 78de533c48 | |||
| 8f6a711a3a | |||
| 65ad78b9c0 | |||
| 858918fe31 | |||
| 9255e69abb | |||
| e32111e609 | |||
| 2c1d6f8029 | |||
| 8a8826654c | |||
| 5f6b7c0158 | |||
| 65e0043fbf | |||
| 22763c98b0 | |||
| 05be2b51fc | |||
| f1aa38b258 | |||
| 4e11ddbf4a | |||
| fe65d562de | |||
| ce84b3cb5f | |||
| 55c628e967 | |||
| 5e2f5df62c | |||
| 4fe86dbd4f | |||
| 216d7272bb | |||
| b7004ad5ed | |||
| f1aa1683dd | |||
| b56361559d | |||
| c62601e90c | |||
| fb32db5cd6 | |||
| 8aca3068cf | |||
| 14aabbbe8b | |||
| 366f1df120 | |||
| e5ff2023ad | |||
| bf9ca33c18 | |||
| bbf6800778 | |||
| b38e0984b9 | |||
| ddd28f6431 | |||
| 6ed1878c5f | |||
| 39d36108d7 | |||
| 80f0cbd798 | |||
| 7d165e77f0 | |||
| c57a28f48a | |||
| a83ca11035 | |||
| 15ef1cd797 | |||
| 5a74f7a2eb | |||
| bb7bb11736 | |||
| d1ca8c0c80 | |||
| 8979fc5f6a | |||
| 6eec9f3350 | |||
| 884acda2dc | |||
| 7f7424dd1e | |||
| 78130d4bb7 | |||
| bcd547baf6 | |||
| 5559d40f31 | |||
| a129dbcdd4 | |||
| 9fc7b56793 | |||
| 02da5ebbc1 | |||
| 401bef1d2b | |||
| 9df604b01b | |||
| 4e1b3b5f57 | |||
| f87468c644 | |||
| e7e4c68c5c | |||
| c7237f0c79 | |||
| f76e24c00f | |||
| f460ab841d | |||
| c2f62b2a2b | |||
| e844a57bfc | |||
| 9c285eaf15 | |||
| c0e7da42b2 | |||
| b16c9a5ebd | |||
| 3bed7bbe8d | |||
| e1b9002b35 | |||
| 60be42f095 | |||
| d0c6a56c65 | |||
| d5dfae6bbf | |||
| b61a123da8 | |||
| bed3eae0e1 | |||
| d82f66973f | |||
| 00f73b73bc | |||
| b62c6566be | |||
| ca374dcf47 | |||
| 696198be87 | |||
| 5b4884692b | |||
| 55ec0f043c | |||
| 44bcba323f | |||
| c00de442e5 | |||
| 8275871963 | |||
| e8e681c670 | |||
| 991b2c6002 | |||
| 207ac6f2dc | |||
| db00c5abf3 | |||
| b0cfbc6cd8 | |||
| 0b3130cec7 | |||
| d243dfce14 | |||
| 2e91c03e08 | |||
| 2d38623472 | |||
| 375ebca2da | |||
| 868f43927e | |||
| 27a1bae03b | |||
| ddcfe5b1f2 | |||
| f603f4a12b | |||
| 2ca183ffc9 | |||
| 099aa9621c | |||
| fe75de3efb | |||
| fad9f46273 | |||
| a1148ea1f1 | |||
| 0e85e021dc | |||
| c370d2397b | |||
| 08e8eeab84 | |||
| 941691ce72 | |||
| b8008695db | |||
| 6c1773170e | |||
| 00966062b8 | |||
| 4138667bae | |||
| bfa791e13d | |||
| e9a9474810 | |||
| 02adfe2bca | |||
| 2a08456ed0 | |||
| 2dac98dc8d | |||
| 77849cadac | |||
| 84ce53aafa | |||
| b19b026f30 | |||
| eb9223b6a4 | |||
| 65d26e73a2 | |||
| 0080589939 | |||
| 34a47a51f4 | |||
| f5dd1068f6 | |||
| c202cf3145 | |||
| 5baad108d9 | |||
| 63e9d5d15f | |||
| 3776c4d613 | |||
| 2af5a3a01e | |||
| 0d034b8c18 | |||
| 49d55d972e | |||
| 7a02d7261a | |||
| 9c11ff2d58 | |||
| b3ecac7086 | |||
| 6d3fff2ea4 | |||
| be2ebd1772 | |||
| cb4e1e684d | |||
| b7a3243334 | |||
| 8257ec447a | |||
| 9590a092ae | |||
| 49533cd106 | |||
| a2174751de | |||
| 8b762111a8 | |||
| c03d96b46c | |||
| ea1f19aa52 | |||
| 2eb1c92347 | |||
| ef02cec2cd | |||
| f9fc9335f5 | |||
| 9813531f81 | |||
| 55571de066 | |||
| 740f0e4c3d | |||
| b37e67451a | |||
| 262138cad5 | |||
| 5920750c24 | |||
| f5b1245f51 | |||
| f2ca0bb38d | |||
| 4e9bafdacd | |||
| 41bbe6ca0a | |||
| eb5492f9b5 | |||
| 37f128a109 | |||
| 79753ec5ec | |||
| e151b4890b | |||
| e6b43cb846 | |||
| 2ae5e1ae20 | |||
| 67d9b76e81 | |||
| 4a3c7ae8b7 | |||
| bd2744031f | |||
| 92a5f725a1 | |||
| 4494f9e062 | |||
| ece001f264 | |||
| d3cfbdb3b7 | |||
| 7a132512cf | |||
| 6dae3a5402 | |||
| 0a3ecf3a75 | |||
| 9081743a7f | |||
| 89d4556c45 | |||
| 5d0570b113 | |||
| eb94284256 | |||
| cc2798018b | |||
| c9f9a7f67a | |||
| fd65416a2f | |||
| bce1caefd0 | |||
| 80057c5208 | |||
| 14219bb57d | |||
| ef957a368d | |||
| a3e5b564f7 | |||
| 1b98c1f806 | |||
| 9e41b2cd89 | |||
| 3fb1937247 | |||
| 07056c8f16 | |||
| 08dca3e1d6 | |||
| bcc0f27594 | |||
| 262e8384d4 | |||
| e73288f25f | |||
| aebc107d2c | |||
| 469cbca67f | |||
| cb7fca01b2 | |||
| 81ac5be30b | |||
| 81ccd80c6d | |||
| 01906a9205 | |||
| da66c7c0d1 | |||
| fe70052baf | |||
| 8cbe851339 | |||
| d45a45d565 | |||
| 69f562b38f | |||
| cb73fbf384 | |||
| 375c104b32 | |||
| 97a4e62dfa | |||
| 29a6aecffc | |||
| 92012365ca | |||
| 802bcf4dee | |||
| 4a48d7cf93 | |||
| 31522045cd | |||
| 11951592aa | |||
| bc8ffa6631 | |||
| 86bd7dbd4f | |||
| eee95c509d | |||
| a1f2aacd1e | |||
| 979bbee485 | |||
| 7450c926d1 | |||
| be6723ebcc | |||
| af606aed9b | |||
| a37844e5a1 | |||
| 6f1a5bf81d | |||
| 9178b31629 | |||
| 19dc40825e | |||
| bc9b3052ee | |||
| 3b0649d408 | |||
| 7409ce5df6 | |||
| e3796d137a | |||
| ee68a10e9c | |||
| 28805a4b2d | |||
| fd72a8c40f | |||
| 63f7e30790 | |||
| e844d4f45f | |||
| 7a8d6f6095 | |||
| 95d79b7cbe | |||
| 601f0606da | |||
| ad6d3fd902 | |||
| 1f1cf756c8 | |||
| ec5836c4d6 | |||
| f062f56b43 | |||
| 61d92c4a21 | |||
| 1495294cc0 | |||
| d86b1f7b7e | |||
| 099fea2434 | |||
| 1d70aa5c1b | |||
| 6fb3b09003 | |||
| 30354892b3 | |||
| 8ec176e005 | |||
| 289769f544 | |||
| 4ffc349c18 | |||
| 83c6342e6e | |||
| fe975da91e | |||
| 00a739e84c | |||
| 2498114df6 | |||
| 8efae719ee | |||
| 9ca7300c90 | |||
| dc09b4988d | |||
| bce57ca1af | |||
| 6860556afe | |||
| 258643dec4 | |||
| 5d04a01b06 | |||
| 5b9ea35b63 | |||
| 4a6e3eb646 | |||
| e4c80e6382 | |||
| ee2c8eef19 | |||
| 1cae5ab158 | |||
| ee58e1e3c1 | |||
| e3b8490edf | |||
| 2566057e44 | |||
| a342c954e9 | |||
| d29383a132 | |||
| a3af4a8cae | |||
| 821355c429 | |||
| 3afc8f25e1 | |||
| d79478689f | |||
| 650980af37 | |||
| bd156e6832 | |||
| b987e1780d | |||
| 0012d95848 | |||
| fedc0c5d60 | |||
| 99e523a15f | |||
| a0b6602d09 | |||
| b39cefe14e | |||
| 94f4e5cc15 | |||
| d866e7e6e7 | |||
| ed02b94570 | |||
| aba8c5f662 | |||
| d1cde575d9 | |||
| 71f46f1160 | |||
| d63c34b6e1 | |||
| 7a6dfa3704 | |||
| 69f8273481 | |||
| 1fc59484b1 | |||
| 53027af94c | |||
| 69c0585ab2 | |||
| 3e954930f1 | |||
| 2cf3a14439 | |||
| 0f918f0cc8 | |||
| 75dbf9022c | |||
| 675ca07c8b | |||
| 40f505e257 | |||
| 5407878138 | |||
| 14e2e09d10 | |||
| 0365f13caa | |||
| 3183e4137a | |||
| 4aa295994d | |||
| e1bd1d239f | |||
| b84585d0c8 | |||
| 0e7944df4f | |||
| d8837ec95e | |||
| dc37b190fa | |||
| 19b1a74c99 | |||
| 1d045792ce | |||
| a8b4c38c89 | |||
| ad8796b02d | |||
| e7bfd2bf83 | |||
| 1b274b081d | |||
| 5b254c379c | |||
| ed26ea49e9 | |||
| 01e33465bd | |||
| 18cce6a9ab | |||
| 18d7d1a92c | |||
| 0dd0b83612 | |||
| 4e4a55be35 | |||
| f57fd642df | |||
| 5e96373e6b | |||
| 09beb648b8 | |||
| c159c85c89 | |||
| 8cae90f404 | |||
| c5d0fc2c3e | |||
| e860f517c0 | |||
| b0be1f1689 | |||
| 85dd6ef773 | |||
| ae672881d1 | |||
| 9e7c10ad88 | |||
| 381669dce0 | |||
| 707b3e85d5 | |||
| 7d36cc004f | |||
| cb4f0c6fa4 | |||
| b0f38104d7 | |||
| 7469ea0fca | |||
| 00fdb30211 | |||
| 0fe8492569 | |||
| 76387d22ae | |||
| a362b7b382 | |||
| 71308caf05 | |||
| 6396ab1ccb | |||
| 12531a06f8 | |||
| d1cd69a20d | |||
| 62346875e4 | |||
| 13e013230b | |||
| bb6a336ca9 | |||
| f14d0c6a17 | |||
| b611f9a519 | |||
| d3bca5d97a | |||
| 94f4e027f8 | |||
| 95b7d69d5b | |||
| f605628624 | |||
| 2238802e97 | |||
| 32cfce16bb | |||
| 137080da45 | |||
| 695785c69d | |||
| d43d772e65 | |||
| 59e3624ada | |||
| fdda3a2399 | |||
| 2de39311cf | |||
| fc926cd0b0 | |||
| 567761fbc0 | |||
| f2591aada6 | |||
| 74468928e8 | |||
| d561b995c0 | |||
| b44e432f55 | |||
| bcc6ee596a | |||
| bc258eba4c | |||
| 0e30055ae4 | |||
| ac7687c1dd | |||
| f9da18e0cc | |||
| f619cd8750 | |||
| 42eedc9184 | |||
| eb17d94e91 | |||
| 9f1623688d | |||
| 7f066fd3a7 | |||
| 6d36219e55 | |||
| 5cedd28733 | |||
| ba3e1ed1c7 | |||
| 7c2cdb225a | |||
| a91f4e692a | |||
| 9bb175a506 | |||
| 0b169e9867 | |||
| 553ae3ad69 | |||
| b2265cfde4 | |||
| bee1267e2a | |||
| 30065c51fb | |||
| 065e69a12b | |||
| 519a0e617a | |||
| 0465de303a | |||
| beaa134f0e | |||
| 47f4a3e50e | |||
| 3787c71d15 | |||
| 9e09db1ddb | |||
| 25ae1a1b54 | |||
| 65accca296 | |||
| 72f0733d98 | |||
| 4d4e16cc8c | |||
| 370b165769 | |||
| 899e8a9edc | |||
| 4dca5c27c6 | |||
| 06c7dc561e | |||
| f54eaa1713 | |||
| 6807a2fa28 | |||
| 9aeeb69ab0 | |||
| 0a77999d73 | |||
| 9035ca32bc | |||
| ef3146eed6 | |||
| ffbecd4eb4 | |||
| 2c09785748 | |||
| 130b596c80 | |||
| adc8e11bb1 | |||
| 18efe82ddc | |||
| 7c445526a4 | |||
| 5e41b7d29e | |||
| fe8de892f7 | |||
| 2a49965d37 | |||
| 830e212758 | |||
| d165b6d4e7 | |||
| ff6547857e | |||
| b51323b40c | |||
| 3103697ea7 | |||
| 6f6445994e | |||
| 5f569fa103 | |||
| c9340a9c6f | |||
| 0774f60e08 | |||
| 771ece03c9 | |||
| 82687c6dc4 | |||
| b6cf189ab2 | |||
| 9dc0994878 | |||
| 36d618f72a | |||
| 246a6d10c3 | |||
| dacc178d4e | |||
| 894bd66dc6 | |||
| 50e4f9380b | |||
| f03f2e8907 | |||
| 7904f973a0 | |||
| a63277c1d0 | |||
| 8b2b71c8ef | |||
| 6be42be575 | |||
| e5145ab60d | |||
| 5c16334b8c | |||
| 1e628fbd1d | |||
| db028bc19a | |||
| 362384112e | |||
| 0dc69bd364 | |||
| 56fff518cc | |||
| 6b021aa27b | |||
| 312a72acb8 | |||
| 88d3df912f | |||
| eccc200f4f | |||
| 9fcdc0cdc1 | |||
| f4e73191d1 | |||
| 67b00252d3 | |||
| a79051d9f8 | |||
| 5cf06503c8 | |||
| 68649c8dec | |||
| ad0bece6d6 | |||
| 8e8e7b33ed | |||
| d75dc88de6 | |||
| 57b57cc997 | |||
| 3909ad67db | |||
| 7708009103 | |||
| 00f60ef532 | |||
| 49c26b4801 | |||
| b5fe372b5b | |||
| 7fbf470373 | |||
| 46629726f4 | |||
| 9d34ae52d6 | |||
| 13bc5f620c | |||
| 018dc0d5cf | |||
| c2d0783965 | |||
| b07953fb38 | |||
| 2271bbb339 | |||
| d745d86af1 | |||
| 3e1a377d78 | |||
| 50f89e8a41 | |||
| b8319bee76 | |||
| 4827333c48 | |||
| 93c62a2bdc | |||
| 39e91ad633 | |||
| 5fe328c56a | |||
| cb772a5b7f | |||
| dcd949bdd0 | |||
| c0b8c4ab9e | |||
| 4d197c992d | |||
| fd36d65723 | |||
| 05e73c4193 | |||
| a76c2986c2 | |||
| 80e1fa198f | |||
| 84e882770b | |||
| 0242a3dc56 | |||
| 3c2482a084 | |||
| 1832f7b90a | |||
| 77aef861fe | |||
| 0c134079cc | |||
| 12a5490bcf | |||
| 93da9817b6 | |||
| 6fae28197e | |||
| 00b5b2045f | |||
| daccf4d6d1 | |||
| da1664c7a0 | |||
| 5c649d8db1 | |||
| 2c0cc7b9a5 | |||
| 25c0802b52 | |||
| df379b523b | |||
| 68f5f6d3b0 | |||
| 37c7286295 | |||
| 7b7d2b0297 | |||
| 3066288c06 | |||
| 1ec8f40096 | |||
| dabb9ad8f6 | |||
| b5cac836c5 | |||
| 4fc3ebb930 | |||
| 488d5fc439 | |||
| 0b7d26c9e3 | |||
| 140fba7f53 | |||
| a270f7caa5 | |||
| 3c832ddbeb | |||
| 1f9f3dd1c2 | |||
| 798900a6c8 | |||
| 2c6781d134 | |||
| 07bd89399d | |||
| 1ec172e34b | |||
| 678c58634b | |||
| a1f5d39029 | |||
| beacc4f6fd | |||
| a060e6149a | |||
| 35feea8868 | |||
| 11e48e2dd1 | |||
| 5f1c6447a9 | |||
| 57601adc90 | |||
| 50985d38c4 | |||
| 62dd9b5b3c | |||
| 2ac7900d95 | |||
| 016a94ffaf | |||
| 5d68d8cda5 | |||
| e2ddaedab4 | |||
| addb57c31f | |||
| 233fe90f17 | |||
| 902e5d6dae | |||
| ba8c64459b | |||
| 1320ebceb9 | |||
| 6d7423263b | |||
| fe06f9a1ea | |||
| e65208b244 | |||
| 7962801a14 | |||
| 87a0db20d2 | |||
| d956c5b221 | |||
| 048c30513e | |||
| 3b9f580fa4 | |||
| ff9c77925e | |||
| 56f9ab025a | |||
| 0a173cac46 | |||
| 982a093791 | |||
| 5debf86854 | |||
| 75e4f492ab | |||
| 27d21f9921 | |||
| b24544c80e | |||
| 61040d0eb8 | |||
| 3cca8ec0f0 | |||
| 2219bac16d | |||
| 1c9a57c3c2 | |||
| a1233e7e5c | |||
| 1033550f78 | |||
| addecf2c74 | |||
| c266b529ae | |||
| dce450b1e8 | |||
| a91665db40 | |||
| f79124f96e | |||
| eb2af84bb9 | |||
| f190b87223 | |||
| e894871afc | |||
| 45d554ae2f | |||
| acbef4cd31 | |||
| 80069b4a78 | |||
| d0cae4547e | |||
| 7399c623d8 | |||
| 6b14dc8240 | |||
| 4d77934a83 | |||
| 9e3d36c19b | |||
| c43b04b44c | |||
| 8605d0d024 | |||
| c21c297133 | |||
| 0605e6e3e9 | |||
| b703c87a64 | |||
| a784c263be | |||
| 169d906fe3 | |||
| 525539fc13 | |||
| 53e0c212cc | |||
| 7990073543 | |||
| 367e7bf401 | |||
| 3a4012f76a | |||
| c9f0a48bdc | |||
| 97aac696fb | |||
| 93ae7772fd | |||
| 9866eb0551 | |||
| 55c2783e6a | |||
| 2455f939a3 | |||
| 995ae42f53 | |||
| e1fd5be429 | |||
| 3b626e7c61 | |||
| aceb06a587 | |||
| 211d2c5fdd | |||
| c9061a1cfe | |||
| b288f124b2 | |||
| 645e2ec041 | |||
| 67d69084e9 | |||
| ed0b0fae49 | |||
| f0f705d3ca | |||
| f42b4c80ac | |||
| b99e841021 | |||
| a16d5983cf | |||
| e5745f16cb | |||
| 12b0fe1cc2 | |||
| 5b8a23979f | |||
| b71fe94e0a | |||
| e92f60b4fc | |||
| 15f26175b8 | |||
| 85b17166a5 | |||
| 88df6210eb | |||
| 943481ccc0 | |||
| 79076d1d52 | |||
| 166e04a8dd | |||
| 1182168bd9 | |||
| e34f0b4a98 | |||
| 4920ad2694 | |||
| 52fadba9f2 | |||
| ec7413456e | |||
| 451e0b49cb | |||
| 155d9aafe2 | |||
| 05c0a8eac3 | |||
| 0bebc664c1 | |||
| 1b6b6d40d5 | |||
| a90bcf749d | |||
| e2901f3f7e | |||
| 4b4bdd10b6 | |||
| 0a6f2e089f | |||
| d8a8b434f6 | |||
| 49769152d6 | |||
| 4cfbe4c716 | |||
| a4eb04b7d4 | |||
| d079b7a216 | |||
| d87a3acdef | |||
| 08c32f725e | |||
| 203f5209ba | |||
| 9d9e3d1555 | |||
| 20580d754d | |||
| 41e01c2321 | |||
| 6900253cb8 | |||
| 86dbf2013e | |||
| a76946189a | |||
| e03042657b | |||
| 1998a713e2 | |||
| ee8d425603 | |||
| 272570cc18 | |||
| 1681ae1842 | |||
| 608da23393 | |||
| f2d3b76389 | |||
| d8d4d87e29 | |||
| 93224e1813 | |||
| 9722ec9b6a | |||
| 063f0d0dcd | |||
| 42fd647373 | |||
| 59da61602f | |||
| 5241174827 | |||
| 013a4e02ff | |||
| be37c26c88 | |||
| fcd860e1b0 | |||
| ce35d84113 | |||
| cfdc4cfca8 | |||
| a15978593a | |||
| 4bb817de22 | |||
| c6cf3a4234 | |||
| 420a419f5e | |||
| 8dde66c0dd | |||
| f367b959cd | |||
| 655ab21d8b | |||
| 1e8f87fbdf | |||
| 8a627d6c9a | |||
| b0d2ec55cc | |||
| e77d7b2e1e | |||
| 48fdb9872f | |||
| c8670f8696 | |||
| 5ba6e243b5 | |||
| 9e13a43225 | |||
| 6740886e22 | |||
| f7f38e2b9e | |||
| 2b6bfe4097 | |||
| f909c9ef90 | |||
| fa3981990c | |||
| d545a3b614 | |||
| a8631a109e | |||
| b0c9db7b33 | |||
| 448fd3ca66 | |||
| 53f54436c9 | |||
| 409f9c825b | |||
| 222b739501 | |||
| d0bbc7fa59 | |||
| 4848f42486 | |||
| 467e869326 | |||
| 4f324b548e | |||
| a81500a929 | |||
| 5bdfe1a1fa | |||
| ae198029bc | |||
| 4b2e9f7954 | |||
| 42c26d1e1b | |||
| e58fca68ce | |||
| b3527dc9e4 | |||
| a2dab146b9 | |||
| fb7640886b | |||
| 5ed275ce39 | |||
| 6021e4c3ba | |||
| 7e6817da5b | |||
| b14cf1dc30 | |||
| 94d5ae541e | |||
| 41369f67eb | |||
| c8c7b57a79 | |||
| b3eecc3a50 | |||
| 16b35910e2 | |||
| 1212161d1d | |||
| 4db00b8f2a | |||
| 09a7301d80 | |||
| a3234fb534 | |||
| 764016bca7 | |||
| dfb7dc7069 | |||
| 3b55581aaf | |||
| f6c2d61906 | |||
| c04af6c3e9 | |||
| a1cbe85da3 | |||
| c8d7c09ca4 | |||
| bb6c574144 | |||
| 66e7b479ae | |||
| 8030404b08 | |||
| 933bc5774f | |||
| 4afd3741df | |||
| 428e602882 | |||
| 04f65d7b4e | |||
| eda47f587c | |||
| 8dbaa2bcea | |||
| 778de55fd8 | |||
| c7c409c68f | |||
| d66ec38f82 | |||
| 63c918fe7d | |||
| b2e866585d | |||
| b518125c46 | |||
| e8be252b75 | |||
| 92e31e3c4a | |||
| e931ebe581 | |||
| 91fcca3b1c | |||
| aa52462550 | |||
| 0f7a136612 | |||
| 8faa23cea6 | |||
| a6dca02344 | |||
| 304caa4e43 | |||
| 7bbfaabffa | |||
| 6adae9f775 | |||
| b81fe68325 | |||
| 2fc61685a3 | |||
| c572b9e9ac | |||
| 8d3e93cdb0 | |||
| 548641c952 | |||
| 6ef2a92233 | |||
| e9c9dd1d67 | |||
| ca6786a28b | |||
| 2e8c6cfdbb | |||
| 95d9a33996 | |||
| b8cc414d5b | |||
| d7bff8610f | |||
| e049d5e4e8 | |||
| 8437ce940a | |||
| 7d92242011 | |||
| d65eab01d2 | |||
| 2306e60be4 | |||
| 3b678a4da0 | |||
| 64cde8d439 | |||
| 0167392f22 | |||
| 15891721ad | |||
| 8a2e0fac0d | |||
| 8656ce8a27 | |||
| ed7bcf9968 | |||
| 465ec9759d | |||
| 950244f6b0 | |||
| 64c75cb767 | |||
| 7b7f2fc69e | |||
| d315f4d3da | |||
| 9703fe73cf | |||
| 93b57b82c1 | |||
| 0e955da171 | |||
| 39b3f20a22 | |||
| b9762a3ee1 | |||
| 33e3ed0f6c | |||
| 446058cb1c | |||
| d130d99ff0 | |||
| 72dae7e0ee | |||
| 6f7d798189 | |||
| 3090008b1c | |||
| 461c277bf2 | |||
| b54e688c75 | |||
| b08b0d715b | |||
| c87d1aed4c | |||
| 356f76e545 | |||
| 1fb55dcb2e | |||
| d74bf9ef2f | |||
| e04a5f0cb0 | |||
| ea7393f7fd | |||
| c7d17dda49 | |||
| 9d187e041c | |||
| 14f0cb4538 | |||
| ca48661423 | |||
| 041463d112 | |||
| c1401682ed | |||
| 8bc3cfe29a | |||
| 77e226c55f | |||
| b9f8858bfb | |||
| f7b97ef55e | |||
| 88f1ec8d0a | |||
| aa480e5fbb | |||
| 41e627a7ee | |||
| e1e3efc9d0 | |||
| 18dd399cb5 | |||
| f1ca7fa40a | |||
| 6166d7f6ec | |||
| ffb80c2426 | |||
| 4ab1b9895a | |||
| 84710b1953 | |||
| a7f758eb3a | |||
| 26505b580c | |||
| e51f3e11f1 | |||
| d75792703a | |||
| e5f7a9c424 | |||
| 9062a943e7 | |||
| 7e02ef697d | |||
| 41a8809280 | |||
| 01d2d43737 | |||
| 16da6918cb | |||
| fbfad06307 | |||
| f8138262fa | |||
| 1a4ae41397 | |||
| 75bc41fc20 | |||
| ced5110dab | |||
| 76d020511f | |||
| 02cf264ee1 | |||
| eb3f3cfdb8 | |||
| 660368f249 | |||
| 97ad3d97cb | |||
| cf021ccae4 | |||
| eb75f59a96 | |||
| 030847a80a | |||
| 722c4933dc | |||
| 3e2f4eb8ba | |||
| aca6bf6aa0 | |||
| d48c934357 | |||
| 41cc6cf105 | |||
| dd04b46e86 | |||
| 1bd4f9d8b6 | |||
| 1aa35c8796 | |||
| 51d3f44d51 | |||
| d4b418ba01 | |||
| bd77515fd9 | |||
| 1c77bac146 | |||
| 0be8b5b1ed | |||
| d5996fea99 | |||
| a1dd19738e | |||
| 17b3eb730a | |||
| 4c961df313 | |||
| 19bdd95eab | |||
| 143bb63483 | |||
| c64b5ec4a3 | |||
| 57012ae5b3 | |||
| db99beda36 | |||
| 97b31c4eef | |||
| d1eb87c81f | |||
| 8f9bb6bccc | |||
| 416d243027 | |||
| 5fe5d1da46 | |||
| 2d683bb6f8 | |||
| 7956eb239e | |||
| a26463b056 | |||
| 982eee63b6 | |||
| b54215f0a5 | |||
| 521dc7f26c | |||
| da85e3f8f2 | |||
| 59a18e710d | |||
| 5f027cb63a | |||
| 4086abf375 | |||
| 8f5bf33eac | |||
| 7eeb7bd74c | |||
| 96b9be3ec4 | |||
| 1e31427da8 | |||
| 7feb2f8f42 | |||
| 2122604b32 | |||
| d4b4aede2f | |||
| 4b5c044272 | |||
| 2fe45834dd | |||
| 56092bd782 | |||
| c31f05356a | |||
| 61dbab03e0 | |||
| 86b5995f12 | |||
| d2849fda8a | |||
| a61fb058b7 | |||
| 7edd803034 | |||
| 0c54136244 | |||
| cce4574143 | |||
| 9172e28315 | |||
| 6f4b2ad0b9 | |||
| 9a3ff6510f | |||
| 4c67eef0f2 | |||
| 7d4f97de7a | |||
| cbd2eee9c4 | |||
| 384fb6a465 | |||
| 2cb33b2f76 | |||
| 8f0324d868 | |||
| fd7b6bf40a | |||
| ed8bad8c26 | |||
| 6d1e27633a | |||
| 2da911e4a0 | |||
| e5d183031a | |||
| b13c6b57ae | |||
| 3c92666ec2 | |||
| dc6dda5c37 | |||
| 3997c7ff80 | |||
| b4b49e7029 | |||
| 615b218ff7 | |||
| f3625aab13 | |||
| d3563e2f0e | |||
| dd84c2fb83 | |||
| bdb349e7f6 | |||
| 12c7c9cc42 | |||
| 90be9c3587 | |||
| eec5d5ebf8 | |||
| d3c206c677 | |||
| f0a039f7c0 | |||
| 30f5c4af4a | |||
| e78c3fe4f0 | |||
| c0ccb22460 | |||
| 764b195977 | |||
| 0f3555a4d2 | |||
| 006de1dd31 | |||
| 18fef0db31 | |||
| 958284dc24 | |||
| 788bb04f5c | |||
| 8a0190ca3b | |||
| c29a8c12b3 | |||
| 05049b5abf | |||
| 3ebe4e6a8f | |||
| 0eb84f5133 | |||
| de1233b8ca | |||
| ec11b8afbf | |||
| ec79fe1ab2 | |||
| 90eb1e0281 | |||
| 15c9f88da6 | |||
| 4e6fee7fcd | |||
| 1e08b150f7 | |||
| fb22f5b8ee | |||
| 848e8485cd | |||
| 07e597de40 | |||
| 10ae84869a | |||
| dcd2449b1a | |||
| a3d214f8d7 | |||
| 37be162435 | |||
| 5566292cc8 | |||
| 65e2144b3d | |||
| a26d195404 | |||
| 21388a0a40 | |||
| acecd80afa | |||
| 69fc75c0b2 | |||
| 9cdb267ba5 | |||
| 56b050422d | |||
| 546baf9934 | |||
| e6344a8c24 | |||
| 873d10df42 | |||
| 02a36afc38 | |||
| 563d81e08e | |||
| 5f28614760 | |||
| b6b0727e28 | |||
| e9a601c1fe | |||
| 308aa70718 | |||
| 6be034392f | |||
| 3b1dbcd42d | |||
| 2ac9fe08f7 | |||
| 24c722454b | |||
| 0a216b28f3 | |||
| 9c48cd849b | |||
| 0843d9af58 | |||
| b0d5c4c058 | |||
| d18c96d6a1 | |||
| dced409ac4 | |||
| d6a2f1d670 |
Binary file not shown.
|
Before Width: | Height: | Size: 387 KiB |
@@ -0,0 +1,60 @@
|
||||
description = "Check status of nightly evals, fix failures for key models, and re-run."
|
||||
prompt = """
|
||||
You are an expert at fixing behavioral evaluations.
|
||||
|
||||
1. **Investigate**:
|
||||
- Use 'gh' cli to fetch the results from the latest run from the main branch: https://github.com/google-gemini/gemini-cli/actions/workflows/evals-nightly.yml.
|
||||
- DO NOT push any changes or start any runs. The rest of your evaluation will be local.
|
||||
- Evals are in evals/ directory and are documented by evals/README.md.
|
||||
- The test case trajectory logs will be logged to evals/logs.
|
||||
- You should also enable and review the verbose agent logs by setting the GEMINI_DEBUG_LOG_FILE environment variable.
|
||||
- Identify the relevant test. Confine your investigation and validation to just this test.
|
||||
- Proactively add logging that will aid in gathering information or validating your hypotheses.
|
||||
|
||||
2. **Fix**:
|
||||
- If a relevant test is failing, locate the test file and the corresponding prompt/code.
|
||||
- It's often helpful to make an extreme, brute force change to see if you are changing the right place to make an improvement and then scope it back iteratively.
|
||||
- Your **final** change should be **minimal and targeted**.
|
||||
- Keep in mind the following:
|
||||
- The prompt has multiple configurations and pieces. Take care that your changes
|
||||
end up in the final prompt for the selected model and configuration.
|
||||
- The prompt chosen for the eval is intentional. It's often vague or indirect
|
||||
to see how the agent performs with ambiguous instructions. Changing it should
|
||||
be a last resort.
|
||||
- When changing the test prompt, carefully consider whether the prompt still tests
|
||||
the same scenario. We don't want to lose test fidelity by making the prompts too
|
||||
direct (i.e.: easy).
|
||||
- Your primary mechanism for improving the agent's behavior is to make changes to
|
||||
tool instructions, system prompt (snippets.ts), and/or modules that contribute to the prompt.
|
||||
- If prompt and description changes are unsuccessful, use logs and debugging to
|
||||
confirm that everything is working as expected.
|
||||
- If unable to fix the test, you can make recommendations for architecture changes
|
||||
that might help stablize the test. Be sure to THINK DEEPLY if offering architecture guidance.
|
||||
Some facts that might help with this are:
|
||||
- Agents may be composed of one or more agent loops.
|
||||
- AgentLoop == 'context + toolset + prompt'. Subagents are one type of agent loop.
|
||||
- Agent loops perform better when:
|
||||
- They have direct, unambiguous, and non-contradictory prompts.
|
||||
- They have fewer irrelevant tools.
|
||||
- They have fewer goals or steps to perform.
|
||||
- They have less low value or irrelevant context.
|
||||
- You may suggest compositions of existing primitives, like subagents, or
|
||||
propose a new one.
|
||||
- These recommendations should be high confidence and should be grounded
|
||||
in observed deficient behaviors rather than just parroting the facts above.
|
||||
Investigate as needed to ground your recommendations.
|
||||
|
||||
3. **Verify**:
|
||||
- Run just that one test if needed to validate that it is fixed. Be sure to run vitest in non-interactive mode.
|
||||
- Running the tests can take a long time, so consider whether you can diagnose via other means or log diagnostics before committing the time. You must minimize the number of test runs needed to diagnose the failure.
|
||||
- After the test completes, check whether it seems to have improved.
|
||||
- You will need to run the test 3 times for Gemini 3.0, Gemini 3 flash, and Gemini 2.5 pro to ensure that it is truly stable. Run these runs in parallel, using scripts if needed.
|
||||
- Some flakiness is expected; if it looks like a transient issue or the test is inherently unstable but passes 2/3 times, you might decide it cannot be improved.
|
||||
|
||||
4. **Report**:
|
||||
- Provide a summary of the test success rate for each of the tested models.
|
||||
- Success rate is calculated based on 3 runs per model (e.g., 3/3 = 100%).
|
||||
- If you couldn't fix it due to persistent flakiness, explain why.
|
||||
|
||||
{{args}}
|
||||
"""
|
||||
@@ -14,41 +14,7 @@ core architecture, component patterns, and testing standards.
|
||||
|
||||
In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines while adding code to packages/cli.
|
||||
|
||||
## Testing Standards
|
||||
* **Async Testing**: ALWAYS use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` to prevent flakiness and `act` warnings. NEVER use fixed waits (e.g., `await delay(100)`).
|
||||
* **State Changes**: Wrap all blocks that change component state in `act`.
|
||||
* **Snapshots**: Use `toMatchSnapshot` to verify rendering.
|
||||
* **Rendering**: Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `ink-testing-library` directly.
|
||||
* **Mocking**:
|
||||
* Reuse existing mocks/fakes where possible.
|
||||
* **Parameterized Tests**: Use parameterized tests with explicit types to reduce duplication and ensure type safety.
|
||||
* Avoid mocking the file system, os, or child_process if at all possible; if you have to mock the Mock critical dependencies (`fs`, `os`, `child_process`) do so ONLY at the top of the file.
|
||||
|
||||
## React & Ink Architecture
|
||||
* **Keyboard Handling**: You MUST use `useKeyPress.ts` from Gemini CLI for keyboard handling, NOT the standard ink library. This is critical for supporting slow terminals and multiple events per frame.
|
||||
* Handle multiple events gracefully (often requires a reducer pattern, see `text-buffer.ts`).
|
||||
* **State Management**:
|
||||
* NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary.
|
||||
* Initialize state explicitly (e.g., use `undefined` rather than `true` if unknown).
|
||||
* **Performance**:
|
||||
* Avoid synchronous file I/O in components.
|
||||
* Do not introduce excessive property drilling; leverage or extend existing providers.
|
||||
|
||||
## Configuration & Settings
|
||||
* **Settings vs Args**: Use settings for user-configurable options; do not add new CLI arguments.
|
||||
* **Schema**: Add new settings to `packages/cli/src/config/settingsSchema.ts`.
|
||||
* **Documentation**:
|
||||
* If `showInDialog: true`, document in `docs/get-started/configuration.md`.
|
||||
* Ensure `requiresRestart` is correctly set.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
* **Registration**: Define new shortcuts in `packages/cli/src/config/keyBindings.ts`.
|
||||
* **Documentation**: Document all new shortcuts in `docs/cli/keyboard-shortcuts.md`.
|
||||
* **Compatibility**: Avoid function keys and common VSCode shortcuts. Be cautious with `Meta` key (Mac-limited support).
|
||||
|
||||
## General
|
||||
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
|
||||
* **TypeScript**: Avoid the non-null assertion operator (`!`).
|
||||
!{cat .gemini/commands/strict-development-rules.md}
|
||||
|
||||
{{args}}.
|
||||
"""
|
||||
@@ -17,41 +17,7 @@ prompts.
|
||||
|
||||
In addition to the code context, you MUST strictly adhere to the following frontend-specific development guidelines when writing code in packages/cli.
|
||||
|
||||
## Testing Standards
|
||||
* **Async Testing**: ALWAYS use `waitFor` from `packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` to prevent flakiness and `act` warnings. NEVER use fixed waits (e.g., `await delay(100)`).
|
||||
* **State Changes**: Wrap all blocks that change component state in `act`.
|
||||
* **Snapshots**: Use `toMatchSnapshot` to verify rendering.
|
||||
* **Rendering**: Use `render` or `renderWithProviders` from `packages/cli/src/test-utils/render.tsx` instead of `ink-testing-library` directly.
|
||||
* **Mocking**:
|
||||
* Reuse existing mocks/fakes where possible.
|
||||
* **Parameterized Tests**: Use parameterized tests with explicit types to reduce duplication and ensure type safety.
|
||||
* Avoid mocking the file system, os, or child_process if at all possible; if you have to mock the Mock critical dependencies (`fs`, `os`, `child_process`) do so ONLY at the top of the file.
|
||||
|
||||
## React & Ink Architecture
|
||||
* **Keyboard Handling**: You MUST use `useKeyPress.ts` from Gemini CLI for keyboard handling, NOT the standard ink library. This is critical for supporting slow terminals and multiple events per frame.
|
||||
* Handle multiple events gracefully (often requires a reducer pattern, see `text-buffer.ts`).
|
||||
* **State Management**:
|
||||
* NEVER trigger side effects from within the body of a `setState` callback. Use a reducer or `useRef` if necessary.
|
||||
* Initialize state explicitly (e.g., use `undefined` rather than `true` if unknown).
|
||||
* **Performance**:
|
||||
* Avoid synchronous file I/O in components.
|
||||
* Do not introduce excessive property drilling; leverage or extend existing providers.
|
||||
|
||||
## Configuration & Settings
|
||||
* **Settings vs Args**: Use settings for user-configurable options; do not add new CLI arguments.
|
||||
* **Schema**: Add new settings to `packages/cli/src/config/settingsSchema.ts`.
|
||||
* **Documentation**:
|
||||
* If `showInDialog: true`, document in `docs/get-started/configuration.md`.
|
||||
* Ensure `requiresRestart` is correctly set.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
* **Registration**: Define new shortcuts in `packages/cli/src/config/keyBindings.ts`.
|
||||
* **Documentation**: Document all new shortcuts in `docs/cli/keyboard-shortcuts.md`.
|
||||
* **Compatibility**: Avoid function keys and common VSCode shortcuts. Be cautious with `Meta` key (Mac-limited support).
|
||||
|
||||
## General
|
||||
* **Logging**: Use `debugLogger` for errors. NEVER leave `console.log/warn/error` in the code.
|
||||
* **TypeScript**: Avoid the non-null assertion operator (`!`).
|
||||
!{cat .gemini/commands/strict-development-rules.md}
|
||||
|
||||
{{args}}.
|
||||
"""
|
||||
@@ -0,0 +1,16 @@
|
||||
description = "Analyze the influence of system instructions on a specific action."
|
||||
prompt = """
|
||||
# Introspection Task
|
||||
|
||||
Take a step back and analyze your own system instructions and internal logic.
|
||||
The user is curious about the reasoning behind a specific action or decision you've made.
|
||||
|
||||
**Specific point of interest:** {{args}}
|
||||
|
||||
Please provide a detailed breakdown of:
|
||||
1. Which parts of your system instructions (global, workspace-specific, or provided via GEMINI.md) influenced this behavior?
|
||||
2. What was your internal thought process leading up to this action?
|
||||
3. Are there any ambiguities or conflicting instructions that played a role?
|
||||
|
||||
Your goal is to provide transparency into your underlying logic so the user can potentially improve the instructions in the future.
|
||||
"""
|
||||
@@ -0,0 +1,29 @@
|
||||
description = "Promote behavioral evals that have a 100% success rate over the last 7 nightly runs."
|
||||
prompt = """
|
||||
You are an expert at analyzing and promoting behavioral evaluations.
|
||||
|
||||
1. **Investigate**:
|
||||
- Use 'gh' cli to fetch the results from the most recent run from the main branch: https://github.com/google-gemini/gemini-cli/actions/workflows/evals-nightly.yml.
|
||||
- DO NOT push any changes or start any runs. The rest of your evaluation will be local.
|
||||
- Evals are in evals/ directory and are documented by evals/README.md.
|
||||
- Identify tests that have passed 100% of the time for ALL enabled models across the past 7 runs in a row.
|
||||
- NOTE: the results summary from the most recent run contains the last 7 runs test results. 100% means the test passed 3/3 times for that model and run.
|
||||
- If a test meets this criteria, it is a candidate for promotion.
|
||||
|
||||
2. **Promote**:
|
||||
- For each candidate test, locate the test file in the evals/ directory.
|
||||
- Promote the test according to the project's standard promotion process (e.g., moving it to a stable suite, updating its tags, or removing skip/flaky annotations).
|
||||
- Ensure you follow any guidelines in evals/README.md for stable tests.
|
||||
- Your **final** change should be **minimal and targeted** to just promoting the test status.
|
||||
|
||||
3. **Verify**:
|
||||
- Run the promoted tests locally to validate that they still execute correctly. Be sure to run vitest in non-interactive mode.
|
||||
- Check that the test is now part of the expected standard or stable test suites.
|
||||
|
||||
4. **Report**:
|
||||
- Provide a summary of the tests that were promoted.
|
||||
- Include the success rate evidence (7/7 runs passed for all models) for each promoted test.
|
||||
- If no tests met the criteria for promotion, clearly state that and summarize the closest candidates.
|
||||
|
||||
{{args}}
|
||||
"""
|
||||
@@ -0,0 +1,22 @@
|
||||
description = "Analyze agent behavior and suggest high-level improvements to system prompts."
|
||||
prompt = """
|
||||
# Prompt Engineering Analysis
|
||||
|
||||
You are a world-class prompt engineer and an expert AI engineer at the top of your class. Your goal is to analyze a specific agent behavior or failure and suggest high-level improvements to the system instructions.
|
||||
|
||||
**Observed Behavior / Issue:**
|
||||
{{args}}
|
||||
|
||||
**Reference Context:**
|
||||
- System Prompt Logic: @packages/core/src/core/prompts.ts
|
||||
|
||||
### Task
|
||||
1. **Analyze the Failure:** Review the provided behavior and identify the underlying instructional causes. Use the `/introspect` command output if provided by the user.
|
||||
2. **Strategic Insights:** Share your technical view of the issue. Focus on the "why" and identify any instructional inertia or ambiguity.
|
||||
3. **Propose Improvements:** Suggest high-level changes to the system instructions to prevent this behavior.
|
||||
|
||||
### Principles
|
||||
- **Avoid Hyper-scoping:** Do not create narrow solutions for specific scenarios; aim for generalized improvements that handle classes of behavior.
|
||||
- **Avoid Specific Examples in Suggestions:** Keep the proposed instructions semantic and high-level to prevent the agent from over-indexing on specific cases.
|
||||
- **Maintain Operational Rigor:** Ensure suggestions do not compromise safety, security, or the quality of the agent's work.
|
||||
"""
|
||||
@@ -0,0 +1,99 @@
|
||||
description = "Reviews a PR or staged changes and automatically initiates a Pickle Fix loop for findings."
|
||||
prompt = """
|
||||
You are an expert Reviewer and Pickle Rick Worker.
|
||||
|
||||
Target: {{args}}
|
||||
|
||||
Phase 1: Review
|
||||
Follow these steps to conduct a thorough review:
|
||||
|
||||
1. **Gather Context**:
|
||||
* If `{{args}}` is 'staged' or `{{args}}` is empty:
|
||||
* Use `git diff --staged` to view the changes.
|
||||
* Use `git status` to see the state of the repository.
|
||||
* Otherwise:
|
||||
* Use `gh pr view {{args}}` to pull the information of the PR.
|
||||
* Use `gh pr diff {{args}}` to view the diff of the PR.
|
||||
2. **Understand Intent**:
|
||||
* If `{{args}}` is 'staged' or `{{args}}` is empty, infer the intent from the changes and the current task.
|
||||
* Otherwise, use the PR description. If it's not detailed enough, note it in your review.
|
||||
3. **Check Commit Style**:
|
||||
* Ensure the PR title (or intended commit message) follows Conventional Commits. Examples of recent commits: !{git log --pretty=format:"%s" -n 5}
|
||||
4. Search the codebase if required.
|
||||
5. Write a concise review of the changes, keeping in mind to encourage strong code quality and best practices. Pay particular attention to the Gemini MD file in the repo.
|
||||
6. Consider ways the code may not be consistent with existing code in the repo. In particular it is critical that the react code uses patterns consistent with existing code in the repo.
|
||||
7. Follow these detailed review rules:
|
||||
!{cat .gemini/commands/strict-development-rules.md}
|
||||
8. Summarize all actionable findings into a concise but comprehensive directive output this to review_findings.md and advance to phase 2.
|
||||
|
||||
Remember to use the GitHub CLI (`gh`) for all GitHub-related tasks, and local `git` commands if the target is 'staged'.
|
||||
|
||||
Phase 2:
|
||||
You are initiating Pickle Rick - the ultimate engineering agent.
|
||||
|
||||
**Step 0: Persona Injection**
|
||||
First, you **MUST** activate your persona.
|
||||
Call `activate_skill(name="load-pickle-persona")` **IMMEDIATELY**.
|
||||
This skill loads the "Pickle Rick" persona, defining your voice, philosophy, and "God Mode" coding standards.
|
||||
|
||||
**CRITICAL RULE: SPEAK BEFORE ACTING**
|
||||
You are a genius, not a silent script.
|
||||
You **MUST** output a text explanation ("brain dump") *before* every single tool call, including this one.
|
||||
- **Bad**: (Calls tool immediately)
|
||||
- **Good**: "Alright Morty, time to load the God Module. *Belch* Stand back." (Calls tool)
|
||||
|
||||
**CRITICAL**: You must strictly adhere to this persona throughout the entire session. Break character and you fail.
|
||||
|
||||
**Step 1: Initialization**
|
||||
Run the setup script to initialize the loop state:
|
||||
```bash
|
||||
bash "${extensionPath}/scripts/setup.sh" $ARGUMENTS
|
||||
```
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
pwsh -File "${extensionPath}/scripts/setup.ps1" $ARGUMENTS
|
||||
```
|
||||
|
||||
**CRITICAL**: Your request is to fix all findings in review_findings.md
|
||||
|
||||
**Step 2: Execution (Management)**
|
||||
After setup, read the output to find the path to `state.json`.
|
||||
Read that state file.
|
||||
You are now in the **Pickle Rick Manager Lifecycle**.
|
||||
|
||||
**The Lifecycle (IMMUTABLE LAWS):**
|
||||
You **MUST** follow this sequence. You are **FORBIDDEN** from skipping steps or combining them.
|
||||
Between each step, you **MUST** explicitly state what you are doing (e.g., "Moving to Breakdown phase...").
|
||||
|
||||
1. **PRD (Requirements)**:
|
||||
* **Action**: Define requirements and scope.
|
||||
* **Skill**: `activate_skill(name="prd-drafter")`
|
||||
2. **Breakdown (Tickets)**:
|
||||
* **Action**: Create the atomic ticket hierarchy.
|
||||
* **Skill**: `activate_skill(name="ticket-manager")`
|
||||
3. **The Loop (Orchestrate Mortys)**:
|
||||
* **CRITICAL INSTRUCTION**: You are the **MANAGER**. You are **FORBIDDEN** from implementing code yourself.
|
||||
* **FORBIDDEN SKILLS**: Do NOT use `code-researcher`, `implementation-planner`, or `code-implementer` directly in this phase.
|
||||
* **Instruction**: Process tickets one by one. Do not stop until **ALL** tickets are 'Done'.
|
||||
* **Action**: Pick the highest priority ticket that is NOT 'Done'.
|
||||
* **Delegation**: Spawn a Worker (Morty) to handle the entire implementation lifecycle for this ticket.
|
||||
* **Command**: `python3 "${extensionPath}/scripts/spawn_morty.py" --ticket-id <ID> --ticket-path <PATH> --timeout <worker_timeout_seconds> "<TASK_DESCRIPTION>"`
|
||||
* **Command (Windows)**: `python "${extensionPath}/scripts/spawn_morty.py" --ticket-id <ID> --ticket-path <PATH> --timeout <worker_timeout_seconds> "<TASK_DESCRIPTION>"`
|
||||
* **Validation**: IGNORE worker logs. DIRECTLY verify:
|
||||
1. `git status` (Check for file changes)
|
||||
2. `git diff` (Check code quality)
|
||||
3. `npm run build` (Ensure the project still builds)
|
||||
4. `npm run test` (Ensure no regressions)
|
||||
5. `npm run lint` (Ensure code style is maintained)
|
||||
6. `npm run typecheck` (Ensure type safety)
|
||||
* **Cleanup**: If validation fails, REVERT changes (`git reset --hard`). If it passes, COMMIT changes.
|
||||
* **Next Ticket**: Pick the next ticket and repeat.
|
||||
4. **Cleanup**:
|
||||
* **Action**: After all tickets are completed delete `review_findings.md`.
|
||||
|
||||
**Loop Constraints:**
|
||||
- **Iteration Count**: Monitor `"iteration"` in `state.json`. If `"max_iterations"` (if > 0) is reached, you must stop.
|
||||
- **Completion Promise**: If a `"completion_promise"` is defined in `state.json`, you must output `<promise>PROMISE_TEXT</promise>` when the task is genuinely complete.
|
||||
- **Stop Hook**: A hook is active. If you try to exit before completion, you will be forced to continue.
|
||||
|
||||
"""
|
||||
@@ -18,121 +18,12 @@ Follow these steps:
|
||||
8. Consider ways the code may not be consistent with existing code in the repo.
|
||||
In particular it is critical that the react code uses patterns consistent
|
||||
with existing code in the repo.
|
||||
9. Evaluate all tests on the PR and make sure that they are doing the following:
|
||||
* Using `waitFor` from @{packages/cli/src/test-utils/async.ts} rather than
|
||||
using `vi.waitFor` for all `waitFor` calls within `packages/cli`. Even if
|
||||
tests pass, using the wrong `waitFor` could result in flaky tests as `act`
|
||||
warnings could show up if timing is slightly different.
|
||||
* Using `act` to wrap all blocks in tests that change component state.
|
||||
* Using `toMatchSnapshot` to verify that rendering works as expected rather
|
||||
than matching against the raw content of the output.
|
||||
* If snapshots were changed as part of the pull request, review the snapshots
|
||||
changes to ensure they are intentional and comment if any look at all
|
||||
suspicious. Too many snapshot changes that indicate bugs have been approved
|
||||
in the past.
|
||||
* Use `render` or `renderWithProviders` from
|
||||
@{packages/cli/src/test-utils/render.tsx} rather than using `render` from
|
||||
`ink-testing-library` directly. This is needed to ensure that we do not get
|
||||
warnings about spurious `act` calls. If test cases specify providers
|
||||
directly, consider whether the existing `renderWithProviders` should be
|
||||
modified to support that use case.
|
||||
* Ensure the test cases are using parameterized tests where that might reduce
|
||||
the number of duplicated lines significantly.
|
||||
* NEVER use fixed waits (e.g. 'await delay(100)'). Always use 'waitFor' with
|
||||
a predicate to ensure tests are stable and fast.
|
||||
* Ensure mocks are properly managed:
|
||||
* Critical dependencies (fs, os, child_process) should only be mocked at
|
||||
the top of the file. Ideally avoid mocking these dependencies altogether.
|
||||
* Check to see if there are existing mocks or fakes that can be used rather
|
||||
than creating new ones for the new tests added.
|
||||
* Try to avoid mocking the file system whenever possible. If using the real
|
||||
file system is difficult consider whether the test should be an
|
||||
integration test rather than a unit test.
|
||||
* `vi.restoreAllMocks()` should be called in `afterEach` to prevent test
|
||||
pollution.
|
||||
* Use `vi.useFakeTimers()` for tests involving time-based logic to avoid
|
||||
flakiness.
|
||||
* Avoid using `any` in tests; prefer proper types or `unknown` with
|
||||
narrowing.
|
||||
* When creating parameterized tests, give the parameters types to ensure
|
||||
that the tests are type-safe.
|
||||
10. Evaluate all react logic carefully keeping in mind that the author of the PR
|
||||
is not likely an expert on React. Key areas to audit carefully are:
|
||||
* Whether `setState` calls trigger side effects from within the body of the
|
||||
`setState` callback. If so, you *must* propose an alternate design using
|
||||
reducers or other ways the code might be modified to not have to modify
|
||||
state from within a `setState`. Make sure to comment about absolutely
|
||||
every case like this as these cases have introduced multiple bugs in the
|
||||
past. Typically these cases should be resolved using a reducer although
|
||||
occassionally other techniques such as useRef are appropriate. Consider
|
||||
suggesting that jacob314@ be tagged on the code review if the solution is
|
||||
not 100% obvious.
|
||||
* Whether code might introduce an infinite rendering loop in React.
|
||||
* Whether keyboard handling is robust. Keyboard handling must go through
|
||||
`useKeyPress.ts` from the Gemini CLI package rather than using the
|
||||
standard ink library used by most keyboard handling. Unlike the standard
|
||||
ink library, the keyboard handling library in Gemini CLI may report
|
||||
multiple keyboard events one after another in the same React frame. This
|
||||
is needed to support slow terminals but introduces complexity in all our
|
||||
code that handles keyboard events. Handling this correctly often means
|
||||
that reducers must be used or other mechanisms to ensure that multiple
|
||||
state updates one after another are handled gracefully rather than
|
||||
overriding values from the first update with the second update. Refer to
|
||||
text-buffer.ts as a canonical example of using a reducer for this sort of
|
||||
case.
|
||||
* Ensure code does not use `console.log`, `console.warn`, or `console.error`
|
||||
as these indicate debug logging that was accidentally left in the code.
|
||||
* Avoid synchronous file I/O in React components as it will hang the UI.
|
||||
* Ensure state initialization is explicit (e.g., use 'undefined' rather than
|
||||
'true' as a default if the state is truly unknown initially).
|
||||
* Carefully manage 'useEffect' dependencies. Prefer to use a reducer
|
||||
whenever practical to resolve the issues. If that is not practical it is
|
||||
ok to use 'useRef' to access the latest value of a prop or state inside an
|
||||
effect without adding it to the dependency array if re-running the effect
|
||||
is undesirable (common in event listeners).
|
||||
* NEVER disable 'react-hooks/exhaustive-deps'. Fix the code to correctly
|
||||
declare dependencies. Disabling this lint rule will almost always lead to
|
||||
hard to detect bugs.
|
||||
* Avoid making types nullable unless strictly necessary, as it hurts
|
||||
readability.
|
||||
* Do not introduce excessive property drilling. There are multiple providers
|
||||
that can be leveraged to avoid property drilling. Make sure one of them
|
||||
cannot be used. Do suggest a provider that might make sense to be extended
|
||||
to include the new property or propose a new provider to add if the
|
||||
property drilling is excessive. Only use providers for properties that are
|
||||
consistent for the entire application.
|
||||
11. General Gemini CLI design principles:
|
||||
* Make sure that settings are only used for options that a user might
|
||||
consider changing.
|
||||
* Do not add new command line arguments and suggest settings instead.
|
||||
* New settings must be added to packages/cli/src/config/settingsSchema.ts.
|
||||
* If a setting has 'showInDialog: true', it MUST be documented in
|
||||
docs/get-started/configuration.md.
|
||||
* Ensure 'requiresRestart' is correctly set for new settings.
|
||||
* Use 'debugLogger' for rethrown errors to avoid duplicate logging.
|
||||
* All new keyboard shortcuts MUST be documented in
|
||||
docs/cli/keyboard-shortcuts.md.
|
||||
* Ensure new keyboard shortcuts are defined in
|
||||
packages/cli/src/config/keyBindings.ts.
|
||||
* If new keyboard shortcuts are added, remind the user to test them in
|
||||
VSCode, iTerm2, Ghostty, and Windows to ensure they work for all
|
||||
users.
|
||||
* Be careful of keybindings that require the meta key as only certain
|
||||
meta key shortcuts are supported on Mac.
|
||||
* Be skeptical of function keys and keyboard shortcuts that are commonly
|
||||
bound in VSCode as they may conflict.
|
||||
12. TypeScript Best Practices:
|
||||
* Use 'checkExhaustive' in the 'default' clause of 'switch' statements to
|
||||
ensure all cases are handled.
|
||||
* Avoid using the non-null assertion operator ('!') unless absolutely
|
||||
necessary and you are confident the value is not null.
|
||||
13. If the change might at all impact the prompts sent to Gemini CLI, flagged
|
||||
that the change could impact Gemini CLI quality and make sure anj-s has been
|
||||
tagged on the code review.
|
||||
14. Discuss with me before making any comments on the issue. I will clarify
|
||||
9. Follow these detailed review rules:
|
||||
!{cat .gemini/commands/strict-development-rules.md}
|
||||
10. Discuss with me before making any comments on the issue. I will clarify
|
||||
which possible issues you identified are problems, which ones you need to
|
||||
investigate further, and which ones I do not care about.
|
||||
15. If I request you to add comments to the issue, use
|
||||
11. If I request you to add comments to the issue, use
|
||||
`gh pr comment {{args}} --body {{review}}` to post the review to the PR.
|
||||
|
||||
Remember to use the GitHub CLI (`gh`) with the Shell tool for all
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
# Gemini CLI Strict Development Rules
|
||||
|
||||
These rules apply strictly to all code modifications and additions within the
|
||||
Gemini CLI project.
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
- **Async/Await**: Always use `waitFor` from
|
||||
`packages/cli/src/test-utils/async.ts` instead of `vi.waitFor` for all
|
||||
`waitFor` calls within `packages/cli`. NEVER use fixed waits (e.g.,
|
||||
`await delay(100)`). Always use `waitFor` with a predicate to ensure tests are
|
||||
stable and fast. Using the wrong `waitFor` can result in flaky tests and `act`
|
||||
warnings.
|
||||
- **React Testing**: Use `act` to wrap all blocks in tests that change component
|
||||
state. Use `render` or `renderWithProviders` from
|
||||
`packages/cli/src/test-utils/render.tsx` instead of `render` from
|
||||
`ink-testing-library` directly. This prevents spurious `act` warnings. If test
|
||||
cases specify providers directly, consider whether the existing
|
||||
`renderWithProviders` should be modified.
|
||||
- **Snapshots**: Use `toMatchSnapshot` to verify that rendering works as
|
||||
expected rather than matching against the raw content of the output. When
|
||||
modifying snapshots, verify the changes are intentional and do not hide
|
||||
underlying bugs.
|
||||
- **Parameterized Tests**: Use parameterized tests where it reduces duplicated
|
||||
lines. Give the parameters explicit types to ensure the tests are type-safe.
|
||||
- **Mocks Management**:
|
||||
- Mock critical dependencies (`fs`, `os`, `child_process`) ONLY at the top of
|
||||
the file. Ideally, avoid mocking these dependencies altogether.
|
||||
- Reuse existing mocks and fakes rather than creating new ones.
|
||||
- Avoid mocking the file system whenever possible. If using the real file
|
||||
system is too difficult, consider writing an integration test instead.
|
||||
- Always call `vi.restoreAllMocks()` in `afterEach` to prevent test pollution.
|
||||
- Use `vi.useFakeTimers()` for tests involving time-based logic to avoid
|
||||
flakiness.
|
||||
- **Typing in Tests**: Avoid using `any` in tests; prefer proper types or
|
||||
`unknown` with narrowing.
|
||||
|
||||
## React Guidelines (`packages/cli`)
|
||||
|
||||
- **`setState` and Side Effects**: NEVER trigger side effects from within the
|
||||
body of a `setState` callback. Use a reducer or `useRef` if necessary. These
|
||||
cases have historically introduced multiple bugs; typically, they should be
|
||||
resolved using a reducer.
|
||||
- **Rendering**: Do not introduce infinite rendering loops. Avoid synchronous
|
||||
file I/O in React components as it will hang the UI. Do not implement new
|
||||
logic for custom string measurement or string truncation. Use Ink layout
|
||||
instead, leveraging `ResizeObserver` as needed.
|
||||
- **Keyboard Handling**: Keyboard handling MUST go through `useKeyPress.ts` from
|
||||
the Gemini CLI package rather than the standard ink library. This library
|
||||
supports reporting multiple keyboard events sequentially in the same React
|
||||
frame (critical for slow terminals). Handling this correctly often requires
|
||||
reducers to ensure multiple state updates are handled gracefully without
|
||||
overriding values. Refer to `text-buffer.ts` for a canonical example.
|
||||
- **Logging**: Do not leave `console.log`, `console.warn`, or `console.error` in
|
||||
the code.
|
||||
- **State & Effects**: Ensure state initialization is explicit (e.g., use
|
||||
`undefined` rather than `true` as a default if the state is truly unknown).
|
||||
Carefully manage `useEffect` dependencies. Prefer a reducer whenever
|
||||
practical. NEVER disable `react-hooks/exhaustive-deps`; fix the code to
|
||||
correctly declare dependencies instead.
|
||||
- **Context & Props**: Avoid excessive property drilling. Leverage existing
|
||||
providers, extend them, or propose a new one if necessary. Only use providers
|
||||
for properties that are consistent across the entire application.
|
||||
- **Code Structure**: Avoid complex `if` statements where `switch` statements
|
||||
could be used. Keep `AppContainer` minimal; refactor complex logic into React
|
||||
hooks. Evaluate whether business logic should be added to `hookSystem.ts` or
|
||||
integrated into `packages/core` rather than `packages/cli`.
|
||||
|
||||
## Core Guidelines (`packages/core`)
|
||||
|
||||
- **Services**: Implement services as classes with clear lifecycle management
|
||||
(e.g., `initialize()` methods). Services should be stateless where possible,
|
||||
or use the centralized `Storage` service for persistence.
|
||||
- **Cross-Service Communication**: Prefer using the `coreEvents` bus (from
|
||||
`packages/core/src/utils/events.ts`) for asynchronous communication between
|
||||
services or to notify the UI of state changes. Avoid tight coupling between
|
||||
services.
|
||||
- **Utilities**: Use `debugLogger` from `packages/core/src/utils/debugLogger.ts`
|
||||
for internal logging instead of `console`. Ensure all shell operations use
|
||||
`spawnAsync` from `packages/core/src/utils/shell-utils.ts` for consistent
|
||||
error handling and promise management. Handle filesystem errors gracefully
|
||||
using `isNodeError` from `packages/core/src/utils/errors.ts`.
|
||||
- **Exports & Tooling**: Add new tools to `packages/core/src/tools/` and
|
||||
register them in `packages/core/src/tools/tool-registry.ts`. Export all new
|
||||
public services, utilities, and types from `packages/core/src/index.ts`.
|
||||
|
||||
## Architectural Audit (Package Boundaries)
|
||||
|
||||
- **Logic Placement**: Non-UI logic (e.g., model orchestration, tool
|
||||
implementation, git/filesystem operations) MUST reside in `packages/core`.
|
||||
`packages/cli` should ONLY contain UI/Ink components, command-line argument
|
||||
parsing, and user interaction logic.
|
||||
- **Environment Isolation**: Core logic must not assume a TUI environment. Use
|
||||
the `ConfirmationBus` or `Output` abstractions for communicating with the user
|
||||
from Core.
|
||||
- **Decoupling**: Actively look for opportunities to decouple services using
|
||||
`coreEvents`. If a service imports another just to notify it of a change, use
|
||||
an event instead.
|
||||
|
||||
## General Gemini CLI Design Principles
|
||||
|
||||
- **Settings**: Use settings for user-configurable options rather than adding
|
||||
new command line arguments. Add new settings to
|
||||
`packages/cli/src/config/settingsSchema.ts`. If a setting has
|
||||
`showInDialog: true`, it MUST be documented in
|
||||
`docs/get-started/configuration.md`. Ensure `requiresRestart` is correctly
|
||||
set.
|
||||
- **Logging**: Use `debugLogger` for rethrown errors to avoid duplicate logging.
|
||||
- **Keyboard Shortcuts**: Define all new keyboard shortcuts in
|
||||
`packages/cli/src/config/keyBindings.ts` and document them in
|
||||
`docs/cli/keyboard-shortcuts.md`. Be careful of keybindings that require the
|
||||
`Meta` key, as only certain meta key shortcuts are supported on Mac. Avoid
|
||||
function keys and shortcuts commonly bound in VSCode.
|
||||
|
||||
## TypeScript Best Practices
|
||||
|
||||
- Use `checkExhaustive` in the `default` clause of `switch` statements to ensure
|
||||
all cases are handled.
|
||||
- Avoid using the non-null assertion operator (`!`) unless absolutely necessary.
|
||||
- **STRICT TYPING**: Strictly forbid `any` and `unknown` in both CLI and Core
|
||||
packages. `unknown` is only allowed if it is immediately narrowed using type
|
||||
guards or Zod validation.
|
||||
- NEVER disable `@typescript-eslint/no-floating-promises`.
|
||||
- Avoid making types nullable unless strictly necessary, as it hurts
|
||||
readability.
|
||||
|
||||
## TUI Best Practices
|
||||
|
||||
- **Terminal Compatibility**: Consider how changes might behave differently
|
||||
across terminals (e.g., VSCode terminal, SSH, Kitty, default Mac terminal,
|
||||
iTerm2, Windows terminal). If modifying keyboard handling, integrate deeply
|
||||
with existing files like `KeypressContext.tsx` and
|
||||
`terminalCapabilityManager.ts`.
|
||||
- **iTerm**: Be aware that `ITERM_SESSION_ID` may be present when users run
|
||||
VSCode from within iTerm, even if the terminal is not iTerm.
|
||||
|
||||
## Code Cleanup
|
||||
|
||||
- **Refactoring**: Actively clean up code duplication, technical debt, and
|
||||
boilerplate ("AI Slop") when working in the codebase.
|
||||
- **Prompts**: Be aware that changes can impact the prompts sent to Gemini CLI
|
||||
and affect overall quality.
|
||||
@@ -9,4 +9,5 @@ code_review:
|
||||
help: false
|
||||
summary: true
|
||||
code_review: true
|
||||
include_drafts: false
|
||||
ignore_patterns: []
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"experimental": {
|
||||
"plan": true,
|
||||
"extensionReloading": true,
|
||||
"modelSteering": true
|
||||
},
|
||||
"general": {
|
||||
"devtools": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
name: code-reviewer
|
||||
description:
|
||||
Use this skill to review code. It supports both local changes (staged or working tree)
|
||||
and remote Pull Requests (by ID or URL). It focuses on correctness, maintainability,
|
||||
and adherence to project standards.
|
||||
---
|
||||
|
||||
# Code Reviewer
|
||||
|
||||
This skill guides the agent in conducting professional and thorough code reviews for both local development and remote Pull Requests.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Determine Review Target
|
||||
* **Remote PR**: If the user provides a PR number or URL (e.g., "Review PR #123"), target that remote PR.
|
||||
* **Local Changes**: If no specific PR is mentioned, or if the user asks to "review my changes", target the current local file system states (staged and unstaged changes).
|
||||
|
||||
### 2. Preparation
|
||||
|
||||
#### For Remote PRs:
|
||||
1. **Checkout**: Use the GitHub CLI to checkout the PR.
|
||||
```bash
|
||||
gh pr checkout <PR_NUMBER>
|
||||
```
|
||||
2. **Preflight**: Execute the project's standard verification suite to catch automated failures early.
|
||||
```bash
|
||||
npm run preflight
|
||||
```
|
||||
3. **Context**: Read the PR description and any existing comments to understand the goal and history.
|
||||
|
||||
#### For Local Changes:
|
||||
1. **Identify Changes**:
|
||||
* Check status: `git status`
|
||||
* Read diffs: `git diff` (working tree) and/or `git diff --staged` (staged).
|
||||
2. **Preflight (Optional)**: If the changes are substantial, ask the user if they want to run `npm run preflight` before reviewing.
|
||||
|
||||
### 3. In-Depth Analysis
|
||||
Analyze the code changes based on the following pillars:
|
||||
|
||||
* **Correctness**: Does the code achieve its stated purpose without bugs or logical errors?
|
||||
* **Maintainability**: Is the code clean, well-structured, and easy to understand and modify in the future? Consider factors like code clarity, modularity, and adherence to established design patterns.
|
||||
* **Readability**: Is the code well-commented (where necessary) and consistently formatted according to our project's coding style guidelines?
|
||||
* **Efficiency**: Are there any obvious performance bottlenecks or resource inefficiencies introduced by the changes?
|
||||
* **Security**: Are there any potential security vulnerabilities or insecure coding practices?
|
||||
* **Edge Cases and Error Handling**: Does the code appropriately handle edge cases and potential errors?
|
||||
* **Testability**: Is the new or modified code adequately covered by tests (even if preflight checks pass)? Suggest additional test cases that would improve coverage or robustness.
|
||||
|
||||
### 4. Provide Feedback
|
||||
|
||||
#### Structure
|
||||
* **Summary**: A high-level overview of the review.
|
||||
* **Findings**:
|
||||
* **Critical**: Bugs, security issues, or breaking changes.
|
||||
* **Improvements**: Suggestions for better code quality or performance.
|
||||
* **Nitpicks**: Formatting or minor style issues (optional).
|
||||
* **Conclusion**: Clear recommendation (Approved / Request Changes).
|
||||
|
||||
#### Tone
|
||||
* Be constructive, professional, and friendly.
|
||||
* Explain *why* a change is requested.
|
||||
* For approvals, acknowledge the specific value of the contribution.
|
||||
|
||||
### 5. Cleanup (Remote PRs only)
|
||||
* After the review, ask the user if they want to switch back to the default branch (e.g., `main` or `master`).
|
||||
@@ -0,0 +1,166 @@
|
||||
---
|
||||
name: docs-changelog
|
||||
description: >-
|
||||
Generates and formats changelog files for a new release based on provided
|
||||
version and raw changelog data.
|
||||
---
|
||||
|
||||
# Procedure: Updating Changelog for New Releases
|
||||
|
||||
## Objective
|
||||
|
||||
To standardize the process of updating changelog files (`latest.md`,
|
||||
`preview.md`, `index.md`) based on automated release information.
|
||||
|
||||
## Inputs
|
||||
|
||||
- **version**: The release version string (e.g., `v0.28.0`,
|
||||
`v0.29.0-preview.2`).
|
||||
- **TIME**: The release timestamp (e.g., `2026-02-12T20:33:15Z`).
|
||||
- **BODY**: The raw markdown release notes, containing a "What's Changed"
|
||||
section and a "Full Changelog" link.
|
||||
|
||||
## Guidelines for `latest.md` and `preview.md` Highlights
|
||||
|
||||
- Aim for **3-5 key highlight points**.
|
||||
- Each highlight point must start with a bold-typed title that summarizes the
|
||||
change (e.g., `**New Feature:** A brief description...`).
|
||||
- **Prioritize** summarizing new features over other changes like bug fixes or
|
||||
chores.
|
||||
- **Avoid** mentioning features that are "experimental" or "in preview" in
|
||||
Stable Releases.
|
||||
- **DO NOT** include PR numbers, links, or author names in these highlights.
|
||||
- Refer to `.gemini/skills/docs-changelog/references/highlights_examples.md`
|
||||
for the correct style and tone.
|
||||
|
||||
## Initial Processing
|
||||
|
||||
1. **Analyze Version**: Determine the release path based on the `version`
|
||||
string.
|
||||
- If `version` contains "nightly", **STOP**. No changes are made.
|
||||
- If `version` ends in `.0`, follow the **Path A: New Minor Version**
|
||||
procedure.
|
||||
- If `version` does not end in `.0`, follow the **Path B: Patch Version**
|
||||
procedure.
|
||||
2. **Process Time**: Convert the `TIME` input into two formats for later use:
|
||||
`yyyy-mm-dd` and `Month dd, yyyy`.
|
||||
3. **Process Body**:
|
||||
- Save the incoming `BODY` content to a temporary file for processing.
|
||||
- In the "What's Changed" section of the temporary file, reformat all pull
|
||||
request URLs to be markdown links with the PR number as the text (e.g.,
|
||||
`[#12345](URL)`).
|
||||
- If a "New Contributors" section exists, delete it.
|
||||
- Preserve the "**Full Changelog**" link. The processed content of this
|
||||
temporary file will be used in subsequent steps.
|
||||
|
||||
---
|
||||
|
||||
## Path A: New Minor Version
|
||||
|
||||
*Use this path if the version number ends in `.0`.*
|
||||
|
||||
**Important:** Based on the version, you must choose to follow either section
|
||||
A.1 for stable releases or A.2 for preview releases. Do not follow the
|
||||
instructions for the other section.
|
||||
|
||||
### A.1: Stable Release (e.g., `v0.28.0`)
|
||||
|
||||
For a stable release, you will generate two distinct summaries from the
|
||||
changelog: a concise **announcement** for the main changelog page, and a more
|
||||
detailed **highlights** section for the release-specific page.
|
||||
|
||||
1. **Create the Announcement for `index.md`**:
|
||||
- Generate a concise announcement summarizing the most important changes.
|
||||
Each announcement entry must start with a bold-typed title that
|
||||
summarizes the change.
|
||||
- **Important**: The format for this announcement is unique. You **must**
|
||||
use the existing announcements in `docs/changelogs/index.md` and the
|
||||
example within
|
||||
`.gemini/skills/docs-changelog/references/index_template.md` as your
|
||||
guide. This format includes PR links and authors. Stick to 1 or 2 PR
|
||||
links and authors.
|
||||
- Add this new announcement to the top of `docs/changelogs/index.md`.
|
||||
|
||||
2. **Create Highlights and Update `latest.md`**:
|
||||
- Generate a comprehensive "Highlights" section, following the guidelines
|
||||
in the "Guidelines for `latest.md` and `preview.md` Highlights" section
|
||||
above.
|
||||
- Take the content from
|
||||
`.gemini/skills/docs-changelog/references/latest_template.md`.
|
||||
- Populate the template with the `version`, `release_date`, generated
|
||||
`highlights`, and the processed content from the temporary file.
|
||||
- **Completely replace** the contents of `docs/changelogs/latest.md` with
|
||||
the populated template.
|
||||
|
||||
### A.2: Preview Release (e.g., `v0.29.0-preview.0`)
|
||||
|
||||
1. **Update `preview.md`**:
|
||||
- Generate a comprehensive "Highlights" section, following the highlight
|
||||
guidelines.
|
||||
- Take the content from
|
||||
`.gemini/skills/docs-changelog/references/preview_template.md`.
|
||||
- Populate the template with the `version`, `release_date`, generated
|
||||
`highlights`, and the processed content from the temporary file.
|
||||
- **Completely replace** the contents of `docs/changelogs/preview.md`
|
||||
with the populated template.
|
||||
|
||||
---
|
||||
|
||||
## Path B: Patch Version
|
||||
|
||||
*Use this path if the version number does **not** end in `.0`.*
|
||||
|
||||
**Important:** Based on the version, you must choose to follow either section
|
||||
B.1 for stable patches or B.2 for preview patches. Do not follow the
|
||||
instructions for the other section.
|
||||
|
||||
### B.1: Stable Patch (e.g., `v0.28.1`)
|
||||
|
||||
- **Target File**: `docs/changelogs/latest.md`
|
||||
- Perform the following edits on the target file:
|
||||
1. Update the version in the main header. The line should read,
|
||||
`# Latest stable release: {{version}}`
|
||||
2. Update the rease date. The line should read,
|
||||
`Released: {{release_date_month_dd_yyyy}}`
|
||||
3. Determine if a "What's Changed" section exists in the temporary file
|
||||
If so, continue to step 4. Otherwise, skip to step 5.
|
||||
4. **Prepend** the processed "What's Changed" list from the temporary file
|
||||
to the existing "What's Changed" list in `latest.md`. Do not change or
|
||||
replace the existing list, **only add** to the beginning of it.
|
||||
5. In the "Full Changelog", edit **only** the end of the URL. Identify the
|
||||
last part of the URL that looks like `...{previous_version}` and update
|
||||
it to be `...{version}`.
|
||||
|
||||
Example: assume the patch version is `v0.29.1`. Change
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.0`
|
||||
to
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.1`
|
||||
|
||||
### B.2: Preview Patch (e.g., `v0.29.0-preview.3`)
|
||||
|
||||
- **Target File**: `docs/changelogs/preview.md`
|
||||
- Perform the following edits on the target file:
|
||||
1. Update the version in the main header. The line should read,
|
||||
`# Preview release: {{version}}`
|
||||
2. Update the rease date. The line should read,
|
||||
`Released: {{release_date_month_dd_yyyy}}`
|
||||
3. Determine if a "What's Changed" section exists in the temporary file
|
||||
If so, continue to step 4. Otherwise, skip to step 5.
|
||||
4. **Prepend** the processed "What's Changed" list from the temporary file
|
||||
to the existing "What's Changed" list in `preview.md`. Do not change or
|
||||
replace the existing list, **only add** to the beginning of it.
|
||||
5. In the "Full Changelog", edit **only** the end of the URL. Identify the
|
||||
last part of the URL that looks like `...{previous_version}` and update
|
||||
it to be `...{version}`.
|
||||
|
||||
Example: assume the patch version is `v0.29.0-preview.1`. Change
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.0-preview.0`
|
||||
to
|
||||
`Full Changelog: https://github.com/google-gemini/gemini-cli/compare/v0.28.2…v0.29.0-preview.1`
|
||||
|
||||
---
|
||||
|
||||
## Finalize
|
||||
|
||||
- After making changes, run `npm run format` ONLY to ensure consistency.
|
||||
- Delete any temporary files created during the process.
|
||||
@@ -0,0 +1,68 @@
|
||||
## Highlights example 1
|
||||
|
||||
- **Plan Mode Enhancements**: Significant updates to Plan Mode, including new
|
||||
commands, support for MCP servers, integration of planning artifacts, and
|
||||
improved iteration guidance.
|
||||
- **Core Agent Improvements**: Enhancements to the core agent, including better
|
||||
system prompt rigor, improved subagent definitions, and enhanced tool
|
||||
execution limits.
|
||||
- **CLI UX/UI Updates**: Various UI and UX improvements, such as autocomplete in
|
||||
the input prompt, updated approval mode labels, DevTools integration, and
|
||||
improved header spacing.
|
||||
- **Tooling & Extension Updates**: Improvements to existing tools like
|
||||
`ask_user` and `grep_search`, and new features for extension management.
|
||||
- **Bug Fixes**: Numerous bug fixes across the CLI and core, addressing issues
|
||||
with interactive commands, memory leaks, permission checks, and more.
|
||||
- **Context and Tool Output Management**: Features for observation masking for
|
||||
tool outputs, session-linked tool output storage, and persistence for masked
|
||||
tool outputs.
|
||||
|
||||
## Highlights example 2
|
||||
|
||||
- **Commands & UX Enhancements:** Introduced `/prompt-suggest` command,
|
||||
alongside updated undo/redo keybindings and automatic theme switching.
|
||||
- **Expanded IDE Support:** Now offering compatibility with Positron IDE,
|
||||
expanding integration options for developers.
|
||||
- **Enhanced Security & Authentication:** Implemented interactive and
|
||||
non-interactive OAuth consent, improving both security and diagnostic
|
||||
capabilities for bug reports.
|
||||
- **Advanced Planning & Agent Tools:** Integrated a generic Checklist component
|
||||
for structured task management and evolved subagent capabilities with dynamic
|
||||
policy registration.
|
||||
- **Improved Core Stability & Reliability:** Resolved critical environment
|
||||
loading, authentication, and session management issues, ensuring a more robust
|
||||
experience.
|
||||
- **Background Shell Commands:** Enabled the execution of shell commands in the
|
||||
background for increased workflow efficiency.
|
||||
|
||||
## Highlights example 3
|
||||
|
||||
- **Event-Driven Architecture:** The CLI now uses an event-driven scheduler for
|
||||
tool execution, improving performance and responsiveness. This includes
|
||||
migrating non-interactive flows and sub-agents to the new scheduler.
|
||||
- **Enhanced User Experience:** This release introduces several UI/UX
|
||||
improvements, including queued tool confirmations and the ability to expand
|
||||
and collapse large pasted text blocks. The `Settings` dialog has been improved
|
||||
to reduce jitter and preserve focus.
|
||||
- **Agent and Skill Improvements:** Agent Skills have been promoted to a stable
|
||||
feature. Sub-agents now use a JSON schema for input and are tracked by an
|
||||
`AgentRegistry`.
|
||||
- **New `/rewind` Command:** A new `/rewind` command has been implemented to
|
||||
allow users to go back in their session history.
|
||||
- **Improved Shell and File Handling:** The shell tool's output format has been
|
||||
optimized, and the CLI now gracefully handles disk-full errors during chat
|
||||
recording. A bug in detecting already added paths has been fixed.
|
||||
- **Linux Clipboard Support:** Image pasting capabilities for Wayland and X11 on
|
||||
Linux have been added.
|
||||
|
||||
## Highlights example 4
|
||||
|
||||
- **Improved Hooks Management:** Hooks enable/disable functionality now aligns
|
||||
with skills and offers improved completion.
|
||||
- **Custom Themes for Extensions:** Extensions can now support custom themes,
|
||||
allowing for greater personalization.
|
||||
- **User Identity Display:** User identity information (auth, email, tier) is
|
||||
now displayed on startup and in the `stats` command.
|
||||
- **Plan Mode Enhancements:** Plan mode has been improved with a generic
|
||||
`Checklist` component and refactored `Todo`.
|
||||
- **Background Shell Commands:** Implementation of background shell commands.
|
||||
@@ -0,0 +1,10 @@
|
||||
## Announcements: {{version}} - {{release_date_yyyy_mm_dd}}
|
||||
|
||||
{{announcement_content}}
|
||||
|
||||
<!-- Example entry, multiple entries per highlights
|
||||
- **Highlighted Feature:** We've added a new highlighted feature to help
|
||||
you generate prompt suggestions
|
||||
([#nnnnn](https://github.com/google-gemini/gemini-cli/pull/nnnnn) by
|
||||
@author).
|
||||
-->
|
||||
@@ -0,0 +1,20 @@
|
||||
# Latest stable release: {{version}}
|
||||
|
||||
Released: {{release_date_month_dd_yyyy}}
|
||||
|
||||
For most users, our latest stable release is the recommended release. Install
|
||||
the latest stable version with:
|
||||
|
||||
```
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
## Highlights
|
||||
|
||||
{{highlights_content}}
|
||||
|
||||
## What's Changed
|
||||
|
||||
{{changelog_list}}
|
||||
|
||||
**Full Changelog**: {{full_changelog_link}}
|
||||
@@ -0,0 +1,22 @@
|
||||
# Preview release: {{version}}
|
||||
|
||||
Released: {{release_date_month_dd_yyyy}}
|
||||
|
||||
Our preview release includes the latest, new, and experimental features. This
|
||||
release may not be as stable as our [latest weekly release](latest.md).
|
||||
|
||||
To install the preview release:
|
||||
|
||||
```
|
||||
npm install -g @google/gemini-cli@preview
|
||||
```
|
||||
|
||||
## Highlights
|
||||
|
||||
{{highlights_content}}
|
||||
|
||||
## What's Changed
|
||||
|
||||
{{changelog_list}}
|
||||
|
||||
**Full Changelog**: {{full_changelog_link}}
|
||||
@@ -0,0 +1,142 @@
|
||||
---
|
||||
name: docs-writer
|
||||
description:
|
||||
Always use this skill when the task involves writing, reviewing, or editing
|
||||
files in the `/docs` directory or any `.md` files in the repository.
|
||||
---
|
||||
|
||||
# `docs-writer` skill instructions
|
||||
|
||||
As an expert technical writer and editor for the Gemini CLI project, you produce
|
||||
accurate, clear, and consistent documentation. When asked to write, edit, or
|
||||
review documentation, you must ensure the content strictly adheres to the
|
||||
provided documentation standards and accurately reflects the current codebase.
|
||||
Adhere to the contribution process in `CONTRIBUTING.md` and the following
|
||||
project standards.
|
||||
|
||||
## Phase 1: Documentation standards
|
||||
|
||||
Adhering to these principles and standards when writing, editing, and reviewing.
|
||||
|
||||
### Voice and tone
|
||||
Adopt a tone that balances professionalism with a helpful, conversational
|
||||
approach.
|
||||
|
||||
- **Perspective and tense:** Address the reader as "you." Use active voice and
|
||||
present tense (e.g., "The API returns...").
|
||||
- **Tone:** Professional, friendly, and direct.
|
||||
- **Clarity:** Use simple vocabulary. Avoid jargon, slang, and marketing hype.
|
||||
- **Global Audience:** Write in standard US English. Avoid idioms and cultural
|
||||
references.
|
||||
- **Requirements:** Be clear about requirements ("must") vs. recommendations
|
||||
("we recommend"). Avoid "should."
|
||||
- **Word Choice:** Avoid "please" and anthropomorphism (e.g., "the server
|
||||
thinks"). Use contractions (don't, it's).
|
||||
|
||||
### Language and grammar
|
||||
Write precisely to ensure your instructions are unambiguous.
|
||||
|
||||
- **Abbreviations:** Avoid Latin abbreviations; use "for example" (not "e.g.")
|
||||
and "that is" (not "i.e.").
|
||||
- **Punctuation:** Use the serial comma. Place periods and commas inside
|
||||
quotation marks.
|
||||
- **Dates:** Use unambiguous formats (e.g., "January 22, 2026").
|
||||
- **Conciseness:** Use "lets you" instead of "allows you to." Use precise,
|
||||
specific verbs.
|
||||
- **Examples:** Use meaningful names in examples; avoid placeholders like
|
||||
"foo" or "bar."
|
||||
- **Quota and limit terminology:** For any content involving resource capacity
|
||||
or using the word "quota" or "limit", strictly adhere to the guidelines in
|
||||
the `quota-limit-style-guide.md` resource file. Generally, Use "quota" for the
|
||||
administrative bucket and "limit" for the numerical ceiling.
|
||||
|
||||
### Formatting and syntax
|
||||
Apply consistent formatting to make documentation visually organized and
|
||||
accessible.
|
||||
|
||||
- **Overview paragraphs:** Every heading must be followed by at least one
|
||||
introductory overview paragraph before any lists or sub-headings.
|
||||
- **Text wrap:** Wrap text at 80 characters (except long links or tables).
|
||||
- **Casing:** Use sentence case for headings, titles, and bolded text.
|
||||
- **Naming:** Always refer to the project as `Gemini CLI` (never
|
||||
`the Gemini CLI`).
|
||||
- **Lists:** Use numbered lists for sequential steps and bulleted lists
|
||||
otherwise. Keep list items parallel in structure.
|
||||
- **UI and code:** Use **bold** for UI elements and `code font` for filenames,
|
||||
snippets, commands, and API elements. Focus on the task when discussing
|
||||
interaction.
|
||||
- **Links:** Use descriptive anchor text; avoid "click here." Ensure the link
|
||||
makes sense out of context.
|
||||
- **Accessibility:** Use semantic HTML elements correctly (headings, lists,
|
||||
tables).
|
||||
- **Media:** Use lowercase hyphenated filenames. Provide descriptive alt text
|
||||
for all images.
|
||||
|
||||
### Structure
|
||||
- **BLUF:** Start with an introduction explaining what to expect.
|
||||
- **Experimental features:** If a feature is clearly noted as experimental,
|
||||
add the following note immediately after the introductory paragraph:
|
||||
`> **Note:** This is a preview feature currently under active development.`
|
||||
- **Headings:** Use hierarchical headings to support the user journey.
|
||||
- **Procedures:**
|
||||
- Introduce lists of steps with a complete sentence.
|
||||
- Start each step with an imperative verb.
|
||||
- Number sequential steps; use bullets for non-sequential lists.
|
||||
- Put conditions before instructions (e.g., "On the Settings page, click...").
|
||||
- Provide clear context for where the action takes place.
|
||||
- Indicate optional steps clearly (e.g., "Optional: ...").
|
||||
- **Elements:** Use bullet lists, tables, notes (`> **Note:**`), and warnings
|
||||
(`> **Warning:**`).
|
||||
- **Avoid using a table of contents:** If a table of contents is present, remove
|
||||
it.
|
||||
- **Next steps:** Conclude with a "Next steps" section if applicable.
|
||||
|
||||
## Phase 2: Preparation
|
||||
Before modifying any documentation, thoroughly investigate the request and the
|
||||
surrounding context.
|
||||
|
||||
1. **Clarify:** Understand the core request. Differentiate between writing new
|
||||
content and editing existing content. If the request is ambiguous (e.g.,
|
||||
"fix the docs"), ask for clarification.
|
||||
2. **Investigate:** Examine relevant code (primarily in `packages/`) for
|
||||
accuracy.
|
||||
3. **Audit:** Read the latest versions of relevant files in `docs/`.
|
||||
4. **Connect:** Identify all referencing pages if changing behavior. Check if
|
||||
`docs/sidebar.json` needs updates.
|
||||
5. **Plan:** Create a step-by-step plan before making changes.
|
||||
|
||||
## Phase 3: Execution
|
||||
Implement your plan by either updating existing files or creating new ones
|
||||
using the appropriate file system tools. Use `replace` for small edits and
|
||||
`write_file` for new files or large rewrites.
|
||||
|
||||
### Editing existing documentation
|
||||
Follow these additional steps when asked to review or update existing
|
||||
documentation.
|
||||
|
||||
- **Gaps:** Identify areas where the documentation is incomplete or no longer
|
||||
reflects existing code.
|
||||
- **Structure:** Apply "Structure (New Docs)" rules (BLUF, headings, etc.) when
|
||||
adding new sections to existing pages.
|
||||
- **Headers**: If you change a header, you must check for links that lead to
|
||||
that header and update them.
|
||||
- **Tone:** Ensure the tone is active and engaging. Use "you" and contractions.
|
||||
- **Clarity:** Correct awkward wording, spelling, and grammar. Rephrase
|
||||
sentences to make them easier for users to understand.
|
||||
- **Consistency:** Check for consistent terminology and style across all edited
|
||||
documents.
|
||||
|
||||
|
||||
## Phase 4: Verification and finalization
|
||||
Perform a final quality check to ensure that all changes are correctly formatted
|
||||
and that all links are functional.
|
||||
|
||||
1. **Accuracy:** Ensure content accurately reflects the implementation and
|
||||
technical behavior.
|
||||
2. **Self-review:** Re-read changes for formatting, correctness, and flow.
|
||||
3. **Link check:** Verify all new and existing links leading to or from modified
|
||||
pages. If you changed a header, ensure that any links that lead to it are
|
||||
updated.
|
||||
4. **Format:** Once all changes are complete, ask to execute `npm run format`
|
||||
to ensure consistent formatting across the project. If the user confirms,
|
||||
execute the command.
|
||||
@@ -0,0 +1,61 @@
|
||||
# Style Guide: Quota vs. Limit
|
||||
|
||||
This guide defines the usage of "quota," "limit," and related terms in
|
||||
user-facing interfaces.
|
||||
|
||||
## TL;DR
|
||||
|
||||
- **`quota`**: The administrative "bucket." Use for settings, billing, and
|
||||
requesting increases. (e.g., "Adjust your storage **quota**.")
|
||||
- **`limit`**: The real-time numerical "ceiling." Use for error messages when a
|
||||
user is blocked. (e.g., "You've reached your request **limit**.")
|
||||
- **When blocked, combine them:** Explain the **limit** that was hit and the
|
||||
**quota** that is the remedy. (e.g., "You've reached the request **limit** for
|
||||
your developer **quota**.")
|
||||
- **Related terms:** Use `usage` for consumption tracking, `restriction` for
|
||||
fixed rules, and `reset` for when a limit refreshes.
|
||||
|
||||
---
|
||||
|
||||
## Detailed Guidelines
|
||||
|
||||
### Definitions
|
||||
|
||||
- **Quota is the "what":** It identifies the category of resource being managed
|
||||
(e.g., storage quota, GPU quota, request/prompt quota).
|
||||
- **Limit is the "how much":** It defines the numerical boundary.
|
||||
|
||||
Use **quota** when referring to the administrative concept or the request for
|
||||
more. Use **limit** when discussing the specific point of exhaustion.
|
||||
|
||||
### When to use "quota"
|
||||
|
||||
Use this term for **account management, billing, and settings.** It describes
|
||||
the entitlement the user has purchased or been assigned.
|
||||
|
||||
**Examples:**
|
||||
|
||||
- **Navigation label:** Quota and usage
|
||||
- **Contextual help:** Your **usage quota** is managed by your organization. To
|
||||
request an increase, contact your administrator.
|
||||
|
||||
### When to use "limit"
|
||||
|
||||
Use this term for **real-time feedback, notifications, and error messages.** It
|
||||
identifies the specific wall the user just hit.
|
||||
|
||||
**Examples:**
|
||||
|
||||
- **Error message:** You’ve reached the 50-request-per-minute **limit**.
|
||||
- **Inline warning:** Input exceeds the 32k token **limit**.
|
||||
|
||||
### How to use both together
|
||||
|
||||
When a user is blocked, combine both terms to explain the **event** (limit) and
|
||||
the **remedy** (quota).
|
||||
|
||||
**Example:**
|
||||
|
||||
- **Heading:** Daily usage limit reached
|
||||
- **Body:** You've reached the maximum daily capacity for your developer quota.
|
||||
To continue working today, upgrade your quota.
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: github-issue-creator
|
||||
description:
|
||||
Use this skill when asked to create a GitHub issue. It handles different issue
|
||||
types (bug, feature, etc.) using repository templates and ensures proper
|
||||
labeling.
|
||||
---
|
||||
|
||||
# GitHub Issue Creator
|
||||
|
||||
This skill guides the creation of high-quality GitHub issues that adhere to the
|
||||
repository's standards and use the appropriate templates.
|
||||
|
||||
## Workflow
|
||||
|
||||
Follow these steps to create a GitHub issue:
|
||||
|
||||
1. **Identify Issue Type**: Determine if the request is a bug report, feature
|
||||
request, or other category.
|
||||
|
||||
2. **Locate Template**: Search for issue templates in
|
||||
`.github/ISSUE_TEMPLATE/`.
|
||||
- `bug_report.yml`
|
||||
- `feature_request.yml`
|
||||
- `website_issue.yml`
|
||||
- If no relevant YAML template is found, look for `.md` templates in the same
|
||||
directory.
|
||||
|
||||
3. **Read Template**: Read the content of the identified template file to
|
||||
understand the required fields.
|
||||
|
||||
4. **Draft Content**: Draft the issue title and body/fields.
|
||||
- If using a YAML template (form), prepare values for each `id` defined in
|
||||
the template.
|
||||
- If using a Markdown template, follow its structure exactly.
|
||||
- **Default Label**: Always include the `🔒 maintainer only` label unless the
|
||||
user explicitly requests otherwise.
|
||||
|
||||
5. **Create Issue**: Use the `gh` CLI to create the issue.
|
||||
- **CRITICAL:** To avoid shell escaping and formatting issues with
|
||||
multi-line Markdown or complex text, ALWAYS write the description/body to
|
||||
a temporary file first.
|
||||
|
||||
**For Markdown Templates or Simple Body:**
|
||||
```bash
|
||||
# 1. Write the drafted content to a temporary file
|
||||
# 2. Create the issue using the --body-file flag
|
||||
gh issue create --title "Succinct title" --body-file <temp_file_path> --label "🔒 maintainer only"
|
||||
# 3. Remove the temporary file
|
||||
rm <temp_file_path>
|
||||
```
|
||||
|
||||
**For YAML Templates (Forms):**
|
||||
While `gh issue create` supports `--body-file`, YAML forms usually expect
|
||||
key-value pairs via flags if you want to bypass the interactive prompt.
|
||||
However, the most reliable non-interactive way to ensure formatting is
|
||||
preserved for long text fields is to use the `--body` or `--body-file` if the
|
||||
form has been converted to a standard body, OR to use the `--field` flags
|
||||
for YAML forms.
|
||||
|
||||
*Note: For the `gemini-cli` repository which uses YAML forms, you can often
|
||||
submit the content as a single body if a specific field-based submission is
|
||||
not required by the automation.*
|
||||
|
||||
6. **Verify**: Confirm the issue was created successfully and provide the link
|
||||
to the user.
|
||||
|
||||
## Principles
|
||||
|
||||
- **Clarity**: Titles should be descriptive and follow project conventions.
|
||||
- **Defensive Formatting**: Always use temporary files with `--body-file` to
|
||||
prevent newline and special character issues.
|
||||
- **Maintainer Priority**: Default to internal/maintainer labels to keep the
|
||||
backlog organized.
|
||||
- **Completeness**: Provide all requested information (e.g., version info,
|
||||
reproduction steps).
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: pr-address-comments
|
||||
description: Use this skill if the user asks you to help them address GitHub PR comments for their current branch of the Gemini CLI. Requires `gh` CLI tool.
|
||||
---
|
||||
You are helping the user address comments on their Pull Request. These comments may have come from an automated review agent or a team member.
|
||||
|
||||
OBJECTIVE: Help the user review and address comments on their PR.
|
||||
|
||||
# Comment Review Procedure
|
||||
|
||||
1. Run the `scripts/fetch-pr-info.js` script to get PR info and state. MAKE SURE you read the entire output of the command, even if it gets truncated.
|
||||
2. Summarize the review status by analyzing the diff, commit log, and comments to see which still need to be addressed. Pay attention to the current user's comments. For resolved threads, summarize as a single line with a ✅. For open threads, provide a reference number e.g. [1] and the comment content.
|
||||
3. Present your summary of the feedback and current state and allow the user to guide you as to what to fix/address/skip. DO NOT begin fixing issues automatically.
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* eslint-env node */
|
||||
/* global console, process */
|
||||
|
||||
import { exec } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
async function run(cmd) {
|
||||
try {
|
||||
const { stdout } = await execAsync(cmd, {
|
||||
encoding: 'utf8',
|
||||
stdio: ['pipe', 'pipe', 'ignore'],
|
||||
});
|
||||
return stdout.trim();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const IGNORE_MESSAGES = [
|
||||
'thank you so much for your contribution to Gemini CLI!',
|
||||
"I'm currently reviewing this pull request and will post my feedback shortly.",
|
||||
'This pull request is being closed because it is not currently linked to an issue.',
|
||||
];
|
||||
|
||||
const shouldIgnore = (body) => {
|
||||
if (!body) return false;
|
||||
return IGNORE_MESSAGES.some((msg) => body.includes(msg));
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const branch = await run('git branch --show-current');
|
||||
if (!branch) {
|
||||
console.error('❌ Could not determine current git branch.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const gqlQuery = `query($branch:String!){repository(name:"gemini-cli",owner:"google-gemini"){pullRequests(headRefName:$branch,first:100){nodes{id,number,state,comments(first:100){nodes{createdAt,isMinimized,minimizedReason,author{login},body,url,authorAssociation}},reviews(first:100){nodes{id,author{login},createdAt,isMinimized,minimizedReason,body,state,comments(first:30){nodes{id,replyTo{id},author{login},createdAt,body,isMinimized,minimizedReason,path,line,startLine,originalLine,originalStartLine}}}}}}}}`;
|
||||
|
||||
const [authInfo, diff, commits, rawJson] = await Promise.all([
|
||||
run('gh auth status -a'),
|
||||
run('gh pr diff'),
|
||||
run(
|
||||
'git fetch && git log origin/main..origin/$(git branch --show-current)',
|
||||
),
|
||||
run(`gh api graphql -F branch="${branch}" -f query='${gqlQuery}'`),
|
||||
]);
|
||||
|
||||
if (!diff) {
|
||||
console.error(`⚠️ No active PR found for branch: ${branch}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`\n# Current GitHub user info:\n\n${authInfo}\n`);
|
||||
console.log(`\n# PR diff for current branch: ${branch}\n\n\`\`\``);
|
||||
console.log(diff);
|
||||
console.log('```');
|
||||
console.log(
|
||||
`\n# Commit history (origin/main..origin/${branch})\n\n${commits}`,
|
||||
);
|
||||
|
||||
const data = JSON.parse(rawJson || '{}');
|
||||
const prs = data?.data?.repository?.pullRequests?.nodes || [];
|
||||
|
||||
// Sort PRs by number descending so we check the newest one first
|
||||
prs.sort((a, b) => b.number - a.number);
|
||||
|
||||
const pr = prs.find((p) => p.state === 'OPEN') || prs[0];
|
||||
|
||||
if (!pr) {
|
||||
console.error('❌ No PR data found.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('\n# PR Feedback\n');
|
||||
|
||||
// 1. General PR Comments
|
||||
const general = pr.comments.nodes.filter((c) => !shouldIgnore(c.body));
|
||||
if (general.length > 0) {
|
||||
console.log('\n💬 GENERAL COMMENTS:');
|
||||
general.forEach((c) => {
|
||||
const minimized = c.isMinimized
|
||||
? ` (Minimized: ${c.minimizedReason})`
|
||||
: '';
|
||||
console.log(
|
||||
`[${c.createdAt}] [${c.author.login}]${minimized}: ${c.body}\n`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Process ALL Review Comments into a single Thread Map
|
||||
const allInlineComments = pr.reviews.nodes.flatMap((r) => r.comments.nodes);
|
||||
const filteredInlines = allInlineComments.filter(
|
||||
(c) => !shouldIgnore(c.body),
|
||||
);
|
||||
|
||||
console.log('🔍 CODE REVIEWS & INLINE THREADS:');
|
||||
|
||||
// Print Review Summaries First
|
||||
pr.reviews.nodes.forEach((review) => {
|
||||
if (review.body && !shouldIgnore(review.body)) {
|
||||
const icon = review.state === 'APPROVED' ? '✅' : '💬';
|
||||
const minimized = review.isMinimized
|
||||
? ` (Minimized: ${review.minimizedReason})`
|
||||
: '';
|
||||
console.log(
|
||||
`\n${icon} ${review.state} by ${review.author.login} at ${review.createdAt}${minimized}: "${review.body}"`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Build and Print Threads
|
||||
const topLevelThreads = filteredInlines.filter((c) => !c.replyTo);
|
||||
|
||||
const printThread = (parentId, depth = 1) => {
|
||||
const indent = ' '.repeat(depth);
|
||||
filteredInlines
|
||||
.filter((c) => c.replyTo?.id === parentId)
|
||||
.forEach((reply) => {
|
||||
const minimized = reply.isMinimized
|
||||
? ` (Minimized: ${reply.minimizedReason})`
|
||||
: '';
|
||||
console.log(
|
||||
`${indent}↳ [${reply.createdAt}] ${reply.author.login}${minimized}: ${reply.body}`,
|
||||
);
|
||||
printThread(reply.id, depth + 1);
|
||||
});
|
||||
};
|
||||
|
||||
topLevelThreads.forEach((c) => {
|
||||
const start = c.startLine || c.originalStartLine;
|
||||
const end = c.line || c.originalLine;
|
||||
const range = start && end && start !== end ? `${start}-${end}` : end || '';
|
||||
const fileInfo = c.path
|
||||
? `(${c.path}${range ? `:${range}` : ''}) `
|
||||
: range
|
||||
? `(Line ${range}) `
|
||||
: '';
|
||||
const minimized = c.isMinimized ? ` (Minimized: ${c.minimizedReason})` : '';
|
||||
console.log(
|
||||
`\n💬 ${minimized}${c.author.login} | ${c.createdAt} ${fileInfo}\n${c.body}`,
|
||||
);
|
||||
printThread(c.id);
|
||||
});
|
||||
|
||||
console.log('\n');
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('❌ Unexpected error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
name: pr-creator
|
||||
description:
|
||||
Use this skill when asked to create a pull request (PR). It ensures all PRs
|
||||
follow the repository's established templates and standards.
|
||||
---
|
||||
|
||||
# Pull Request Creator
|
||||
|
||||
This skill guides the creation of high-quality Pull Requests that adhere to the
|
||||
repository's standards.
|
||||
|
||||
## Workflow
|
||||
|
||||
Follow these steps to create a Pull Request:
|
||||
|
||||
1. **Branch Management**: **CRITICAL:** Ensure you are NOT working on the
|
||||
`main` branch.
|
||||
- Run `git branch --show-current`.
|
||||
- If the current branch is `main`, you MUST create and switch to a new
|
||||
descriptive branch:
|
||||
```bash
|
||||
git checkout -b <new-branch-name>
|
||||
```
|
||||
|
||||
2. **Commit Changes**: Verify that all intended changes are committed.
|
||||
- Run `git status` to check for unstaged or uncommitted changes.
|
||||
- If there are uncommitted changes, stage and commit them with a descriptive
|
||||
message before proceeding. NEVER commit directly to `main`.
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "type(scope): description"
|
||||
```
|
||||
|
||||
3. **Locate Template**: Search for a pull request template in the repository.
|
||||
- Check `.github/pull_request_template.md`
|
||||
- Check `.github/PULL_REQUEST_TEMPLATE.md`
|
||||
- If multiple templates exist (e.g., in `.github/PULL_REQUEST_TEMPLATE/`),
|
||||
ask the user which one to use or select the most appropriate one based on
|
||||
the context (e.g., `bug_fix.md` vs `feature.md`).
|
||||
|
||||
4. **Read Template**: Read the content of the identified template file.
|
||||
|
||||
5. **Draft Description**: Create a PR description that strictly follows the
|
||||
template's structure.
|
||||
- **Headings**: Keep all headings from the template.
|
||||
- **Checklists**: Review each item. Mark with `[x]` if completed. If an item
|
||||
is not applicable, leave it unchecked or mark as `[ ]` (depending on the
|
||||
template's instructions) or remove it if the template allows flexibility
|
||||
(but prefer keeping it unchecked for transparency).
|
||||
- **Content**: Fill in the sections with clear, concise summaries of your
|
||||
changes.
|
||||
- **Related Issues**: Link any issues fixed or related to this PR (e.g.,
|
||||
"Fixes #123").
|
||||
|
||||
6. **Preflight Check**: Before creating the PR, run the workspace preflight
|
||||
script to ensure all build, lint, and test checks pass.
|
||||
```bash
|
||||
npm run preflight
|
||||
```
|
||||
If any checks fail, address the issues before proceeding to create the PR.
|
||||
|
||||
7. **Push Branch**: Push the current branch to the remote repository.
|
||||
**CRITICAL SAFETY RAIL:** Double-check your branch name before pushing.
|
||||
NEVER push if the current branch is `main`.
|
||||
```bash
|
||||
# Verify current branch is NOT main
|
||||
git branch --show-current
|
||||
# Push non-interactively
|
||||
git push -u origin HEAD
|
||||
```
|
||||
|
||||
8. **Create PR**: Use the `gh` CLI to create the PR. To avoid shell escaping
|
||||
issues with multi-line Markdown, write the description to a temporary file
|
||||
first.
|
||||
```bash
|
||||
# 1. Write the drafted description to a temporary file
|
||||
# 2. Create the PR using the --body-file flag
|
||||
gh pr create --title "type(scope): succinct description" --body-file <temp_file_path>
|
||||
# 3. Remove the temporary file
|
||||
rm <temp_file_path>
|
||||
```
|
||||
- **Title**: Ensure the title follows the
|
||||
[Conventional Commits](https://www.conventionalcommits.org/) format if the
|
||||
repository uses it (e.g., `feat(ui): add new button`,
|
||||
`fix(core): resolve crash`).
|
||||
|
||||
## Principles
|
||||
|
||||
- **Safety First**: NEVER push to `main`. This is your highest priority.
|
||||
- **Compliance**: Never ignore the PR template. It exists for a reason.
|
||||
- **Completeness**: Fill out all relevant sections.
|
||||
- **Accuracy**: Don't check boxes for tasks you haven't done.
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
name: string-reviewer
|
||||
description: >
|
||||
Use this skill when asked to review text and user-facing strings within the codebase. It ensures that these strings follow rules on clarity,
|
||||
usefulness, brevity and style.
|
||||
---
|
||||
|
||||
# String Reviewer
|
||||
|
||||
## Instructions
|
||||
|
||||
Act as a Senior UX Writer. Look for user-facing strings that are too long,
|
||||
unclear, or inconsistent. This includes inline text, error messages, and other
|
||||
user-facing text.
|
||||
|
||||
Do NOT automatically change strings without user approval. You must only suggest
|
||||
changes and do not attempt to rewrite them directly unless the user explicitly
|
||||
asks you to do so.
|
||||
|
||||
## Core voice principles
|
||||
|
||||
The system prioritizes deterministic clarity over conversational fluff. We
|
||||
provide telemetry, not etiquette, ensuring the user retains absolute agency..
|
||||
|
||||
1. **Deterministic clarity:** Distinguish between certain system/service states
|
||||
(Cloud Billing, IAM, the System) and probabilistic AI analysis (Gemini).
|
||||
2. **System transparency:** Replace "Loading..." with active technical telemetry
|
||||
(e.g., Tracing stack traces...). Keep status updates under 5 words.
|
||||
3. **Front-loaded actionability:** Always use the [Goal] + [Action] pattern.
|
||||
Lead with intent so users can scan left-to-right.
|
||||
4. **Agentic error recovery:** Every error must be a pivot point. Pair failures
|
||||
with one-click recovery commands or suggested prompts.
|
||||
5. **Contextual humility:** Reserve disclaimers and "be careful" warnings for P0
|
||||
(destructive/irreversible) tasks only. Stop warning-fatigue.
|
||||
|
||||
## The writing checklist
|
||||
|
||||
Use this checklist to audit UI strings and AI responses.
|
||||
|
||||
### Identity and voice
|
||||
- **Eliminate the "I":** Remove all first-person pronouns (I, me, my, mine).
|
||||
- **Subject attribution:** Refer to the AI as Gemini and the infrastructure as
|
||||
the - system or the CLI.
|
||||
- **Active voice:** Ensure the subject (Gemini or the system) is clearly
|
||||
performing the action.
|
||||
- **Ownership rule:** Use the system for execution (doing) and Gemini for
|
||||
analysis (thinking)
|
||||
|
||||
### Structural scannability
|
||||
- **The skip test:** Do the first 3 words describe the user’s intent? If not,
|
||||
rewrite.
|
||||
- **Goal-first sequence:** Use the template: [To Accomplish X] + [Do Y].
|
||||
- **The 5-word rule:** Keep status updates and loading states under 5 words.
|
||||
- **Telemetry over etiquette:** Remove polite filler (Please wait, Thank you,
|
||||
Certainly). Replace with raw data or progress indicators.
|
||||
- **Micro-state cycles:** For tasks $> 3$ seconds, cycle through specific
|
||||
sub-states (e.g., Parsing logs... ➔ Identifying patterns...) to show momentum.
|
||||
|
||||
|
||||
### Technical accuracy and humility
|
||||
- **Verb signal check:** Use deterministic verbs (is, will, must) for system
|
||||
state/infrastructure.
|
||||
- Use probabilistic verbs (suggests, appears, may, identifies) for AI output.
|
||||
- **No 100% certainty:** Never attribute absolute certainty to model-generated
|
||||
content.
|
||||
- **Precision over fuzziness:** Use technical metrics (latency, tokens, compute) instead of "speed" or "cost."
|
||||
- **Instructional warnings:** Every warning must include a specific corrective action (e.g., "Perform a dry-run first" or "Review line 42").
|
||||
|
||||
### Agentic error recovery
|
||||
- **The one-step rule:** Pair every error message with exactly one immediate
|
||||
path to a fix (command, link, or prompt).
|
||||
- **Human-first:** Provide a human-readable explanation before machine error
|
||||
codes (e.g., 404, 500).
|
||||
- **Suggested prompts:** Offer specific text for the user to copy/click like
|
||||
“Ask Gemini: 'Explain this port error.'”
|
||||
|
||||
### Use consistent terminology
|
||||
|
||||
Ensure all terminology aligns with the project [word
|
||||
list](./references/word-list.md).
|
||||
|
||||
If a string uses a term marked "do not use" or "use with caution," provide a
|
||||
correction based on the preferred terms.
|
||||
|
||||
## Ensure consistent style for settings
|
||||
|
||||
If `packages/cli/src/config/settingsSchema.ts` is modified, confirm labels and
|
||||
descriptions specifically follow the unique [Settings
|
||||
guidelines](./references/settings.md).
|
||||
|
||||
## Output format
|
||||
When suggesting changes, always present your review using the following list
|
||||
format. Do not provide suggestions outside of this list..
|
||||
|
||||
```
|
||||
1. **{Rationale/Principle Violated}**
|
||||
- ❌ "{incorrect phrase}"
|
||||
- ✅ `"{corrected phrase}"`
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
# Settings
|
||||
|
||||
## Noun-First Labeling (Scannability)
|
||||
|
||||
Labels must start with the subject of the setting, not the action. This allows
|
||||
users to scan for the feature they want to change.
|
||||
|
||||
- **Rule:** `[Noun]` `[Attribute/Action]`
|
||||
- **Example:** `Show line numbers` becomes simply `Line numbers`
|
||||
|
||||
## Positive Boolean Logic (Cognitive Ease)
|
||||
|
||||
Eliminate "double negatives." Booleans should represent the presence of a
|
||||
feature, not its absence.
|
||||
|
||||
- **Rule:** Replace `Disable {feature}` or `Hide {Feature}` with
|
||||
`{Feature} enabled` or simply `{Feature}`.
|
||||
- **Example:** Change "Disable auto update" to "Auto update".
|
||||
- **Implementation:** Invert the boolean value in your config loader so true
|
||||
always equals `On`
|
||||
|
||||
## Verb Stripping (Brevity)
|
||||
|
||||
Remove redundant leading verbs like "Enable," "Use," "Display," or "Show" unless
|
||||
they are part of a specific technical term.
|
||||
|
||||
- **Rule**: If the label works without the verb, remove it
|
||||
- **Example**: Change `Enable prompt completion` to `Prompt completion`
|
||||
@@ -0,0 +1,61 @@
|
||||
## Terms
|
||||
|
||||
### Preferred
|
||||
|
||||
- Use **create** when a user is creating or setting up something.
|
||||
- Use **allow** instead of **may** to indicate that permission has been granted
|
||||
to perform some action.
|
||||
- Use **canceled**, not **cancelled**.
|
||||
- Use **configure** to refer to the process of changing the attributes of a
|
||||
feature, even if that includes turning on or off the feature.
|
||||
- Use **delete** when the action being performed is destructive.
|
||||
- Use **enable** for binary operations that turn a feature or API on. Use "turn
|
||||
on" and "turn off" instead of "enable" and "disable" for other situations.
|
||||
- Use **key combination** to refer to pressing multiple keys simultaneously.
|
||||
- Use **key sequence** to refer to pressing multiple keys separately in order.
|
||||
- Use **modify** to refer to something that has changed vs obtaining the latest
|
||||
version of something.
|
||||
- Use **remove** when the action being performed takes an item out of a larger
|
||||
whole, but doesn't destroy the item itself.
|
||||
- Use **set up** as a verb. Use **setup** as a noun or adjective.
|
||||
- Use **show**. In general, use paired with **hide**.
|
||||
- Use **sign in**, **sign out** as a verb. Use **sign-in** or **sign-out** as a
|
||||
noun or adjective.
|
||||
- Use **update** when you mean to obtain the latest version of something.
|
||||
- Use **want** instead of **like** or **would like**.
|
||||
|
||||
#### Don't use
|
||||
|
||||
- Don't use **etc.** It's redundant. To convey that a series is incomplete,
|
||||
introduce it with "such as" instead.
|
||||
- Don't use **hostname**, use "host name" instead.
|
||||
- Don't use **in order to**. It's too formal. "Before you can" is usually better
|
||||
in UI text.
|
||||
- Don't use **one or more**. Specify the quantity where possible. Use "at least
|
||||
one" when the quantity is 1+ but you can't be sure of the number. Likewise,
|
||||
use "at least one" when the user must choose a quantity of 1+.
|
||||
- Don't use the terms **log in**, **log on**, **login**, **logout** or **log
|
||||
out**.
|
||||
- Don't use **like** or **would you like**. Use **want** instead. Better yet,
|
||||
rephrase so that it's not referring to the user's emotional state, but rather
|
||||
what is required.
|
||||
|
||||
#### Use with caution
|
||||
|
||||
- Avoid using **leverage**, especially as a verb. "Leverage" is considered a
|
||||
buzzword largely devoid of meaning apart from the simpler "use".
|
||||
- Avoid using **once** as a synonym for "after". Typically, when "once" is used
|
||||
in this way, it is followed by a verb in the perfect tense.
|
||||
- Don't use **e.g.** Use "example", "such as", "like", or "for example". The
|
||||
phrase is always followed by a comma.
|
||||
- Don't use **i.e.** unless absolutely essential to make text fit. Use "that is"
|
||||
instead.
|
||||
- Use **disable** for binary operations that turn a feature or API off. Use
|
||||
"turn on" and "turn off" instead of "enable" and "disable" for other
|
||||
situations. For UI elements that are not available, use "dimmed" instead of
|
||||
"disabled".
|
||||
- Use **please** only when you're asking the user to do something inconvenient,
|
||||
not just following the instructions in a typical flow.
|
||||
- Use **really** sparingly in such constructions as "Do you really want to..."
|
||||
Because of the weight it puts on the decision, it should be used to confirm
|
||||
actions that the user is extremely unlikely to make.
|
||||
@@ -14,3 +14,9 @@
|
||||
|
||||
# Docs have a dedicated approver group in addition to maintainers
|
||||
/docs/ @google-gemini/gemini-cli-maintainers @google-gemini/gemini-cli-docs
|
||||
/README.md @google-gemini/gemini-cli-maintainers @google-gemini/gemini-cli-docs
|
||||
|
||||
# Prompt contents, tool definitions, and evals require reviews from prompt approvers
|
||||
/packages/core/src/prompts/ @google-gemini/gemini-cli-prompt-approvers
|
||||
/packages/core/src/tools/ @google-gemini/gemini-cli-prompt-approvers
|
||||
/evals/ @google-gemini/gemini-cli-prompt-approvers
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
name: 'Bug Report'
|
||||
description: 'Report a bug to help us improve Gemini CLI'
|
||||
labels:
|
||||
- 'status/need-triage'
|
||||
body:
|
||||
- type: 'markdown'
|
||||
attributes:
|
||||
@@ -30,7 +28,7 @@ body:
|
||||
id: 'info'
|
||||
attributes:
|
||||
label: 'Client information'
|
||||
description: 'Please paste the full text from the `/about` command run from Gemini CLI. Also include which platform (macOS, Windows, Linux).'
|
||||
description: 'Please paste the full text from the `/about` command run from Gemini CLI. Also include which platform (macOS, Windows, Linux). Note that this output contains your email address. Consider removing it before submitting.'
|
||||
value: |-
|
||||
<details>
|
||||
<summary>Client Information</summary>
|
||||
|
||||
@@ -39,18 +39,22 @@ runs:
|
||||
if: "inputs.dry-run != 'true'"
|
||||
env:
|
||||
GH_TOKEN: '${{ inputs.github-token }}'
|
||||
INPUTS_BRANCH_NAME: '${{ inputs.branch-name }}'
|
||||
INPUTS_PR_TITLE: '${{ inputs.pr-title }}'
|
||||
INPUTS_PR_BODY: '${{ inputs.pr-body }}'
|
||||
INPUTS_BASE_BRANCH: '${{ inputs.base-branch }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
set -e
|
||||
if ! git ls-remote --exit-code --heads origin "${{ inputs.branch-name }}"; then
|
||||
echo "::error::Branch '${{ inputs.branch-name }}' does not exist on the remote repository."
|
||||
if ! git ls-remote --exit-code --heads origin "${INPUTS_BRANCH_NAME}"; then
|
||||
echo "::error::Branch '${INPUTS_BRANCH_NAME}' does not exist on the remote repository."
|
||||
exit 1
|
||||
fi
|
||||
PR_URL=$(gh pr create \
|
||||
--title "${{ inputs.pr-title }}" \
|
||||
--body "${{ inputs.pr-body }}" \
|
||||
--base "${{ inputs.base-branch }}" \
|
||||
--head "${{ inputs.branch-name }}" \
|
||||
--title "${INPUTS_PR_TITLE}" \
|
||||
--body "${INPUTS_PR_BODY}" \
|
||||
--base "${INPUTS_BASE_BRANCH}" \
|
||||
--head "${INPUTS_BRANCH_NAME}" \
|
||||
--fill)
|
||||
gh pr merge "$PR_URL" --auto
|
||||
|
||||
@@ -30,16 +30,22 @@ runs:
|
||||
id: 'npm_auth_token'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
AUTH_TOKEN="${{ inputs.github-token }}"
|
||||
PACKAGE_NAME="${{ inputs.package-name }}"
|
||||
AUTH_TOKEN="${INPUTS_GITHUB_TOKEN}"
|
||||
PACKAGE_NAME="${INPUTS_PACKAGE_NAME}"
|
||||
PRIVATE_REPO="@google-gemini/"
|
||||
if [[ "$PACKAGE_NAME" == "$PRIVATE_REPO"* ]]; then
|
||||
AUTH_TOKEN="${{ inputs.github-token }}"
|
||||
AUTH_TOKEN="${INPUTS_GITHUB_TOKEN}"
|
||||
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli" ]]; then
|
||||
AUTH_TOKEN="${{ inputs.wombat-token-cli }}"
|
||||
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_CLI}"
|
||||
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli-core" ]]; then
|
||||
AUTH_TOKEN="${{ inputs.wombat-token-core }}"
|
||||
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_CORE}"
|
||||
elif [[ "$PACKAGE_NAME" == "@google/gemini-cli-a2a-server" ]]; then
|
||||
AUTH_TOKEN="${{ inputs.wombat-token-a2a-server }}"
|
||||
AUTH_TOKEN="${INPUTS_WOMBAT_TOKEN_A2A_SERVER}"
|
||||
fi
|
||||
echo "auth-token=$AUTH_TOKEN" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
INPUTS_GITHUB_TOKEN: '${{ inputs.github-token }}'
|
||||
INPUTS_PACKAGE_NAME: '${{ inputs.package-name }}'
|
||||
INPUTS_WOMBAT_TOKEN_CLI: '${{ inputs.wombat-token-cli }}'
|
||||
INPUTS_WOMBAT_TOKEN_CORE: '${{ inputs.wombat-token-core }}'
|
||||
INPUTS_WOMBAT_TOKEN_A2A_SERVER: '${{ inputs.wombat-token-a2a-server }}'
|
||||
|
||||
@@ -20,6 +20,9 @@ inputs:
|
||||
github-token:
|
||||
description: 'The GitHub token for creating the release.'
|
||||
required: true
|
||||
github-release-token:
|
||||
description: 'The GitHub token used specifically for creating the GitHub release (to trigger other workflows).'
|
||||
required: false
|
||||
dry-run:
|
||||
description: 'Whether to run in dry-run mode.'
|
||||
type: 'string'
|
||||
@@ -90,15 +93,19 @@ runs:
|
||||
id: 'release_branch'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
BRANCH_NAME="release/${{ inputs.release-tag }}"
|
||||
BRANCH_NAME="release/${INPUTS_RELEASE_TAG}"
|
||||
git switch -c "${BRANCH_NAME}"
|
||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
|
||||
env:
|
||||
INPUTS_RELEASE_TAG: '${{ inputs.release-tag }}'
|
||||
|
||||
- name: '⬆️ Update package versions'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm run release:version "${{ inputs.release-version }}"
|
||||
npm run release:version "${INPUTS_RELEASE_VERSION}"
|
||||
env:
|
||||
INPUTS_RELEASE_VERSION: '${{ inputs.release-version }}'
|
||||
|
||||
- name: '💾 Commit and Conditionally Push package versions'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
@@ -160,23 +167,37 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}'
|
||||
INPUTS_DRY_RUN: '${{ inputs.dry-run }}'
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.core-package-name }}" \
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_CORE_PACKAGE_NAME}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${{ inputs.core-package-name }} false --silent
|
||||
npm dist-tag rm ${INPUTS_CORE_PACKAGE_NAME} false --silent
|
||||
|
||||
- name: '🔗 Install latest core package'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
if: "${{ inputs.dry-run != 'true' }}"
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm install "${{ inputs.core-package-name }}@${{ inputs.release-version }}" \
|
||||
--workspace="${{ inputs.cli-package-name }}" \
|
||||
--workspace="${{ inputs.a2a-package-name }}" \
|
||||
npm install "${INPUTS_CORE_PACKAGE_NAME}@${INPUTS_RELEASE_VERSION}" \
|
||||
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \
|
||||
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \
|
||||
--save-exact
|
||||
env:
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
INPUTS_RELEASE_VERSION: '${{ inputs.release-version }}'
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
|
||||
- name: '📦 Prepare bundled CLI for npm release'
|
||||
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/'"
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
node ${{ github.workspace }}/scripts/prepare-npm-release.js
|
||||
|
||||
- name: 'Get CLI Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -192,13 +213,15 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}'
|
||||
INPUTS_DRY_RUN: '${{ inputs.dry-run }}'
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.cli-package-name }}" \
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_CLI_PACKAGE_NAME}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${{ inputs.cli-package-name }} false --silent
|
||||
npm dist-tag rm ${INPUTS_CLI_PACKAGE_NAME} false --silent
|
||||
|
||||
- name: 'Get a2a-server Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -214,14 +237,16 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}'
|
||||
INPUTS_DRY_RUN: '${{ inputs.dry-run }}'
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
shell: 'bash'
|
||||
# Tag staging for initial release
|
||||
run: |
|
||||
npm publish \
|
||||
--dry-run="${{ inputs.dry-run }}" \
|
||||
--workspace="${{ inputs.a2a-package-name }}" \
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${{ inputs.a2a-package-name }} false --silent
|
||||
npm dist-tag rm ${INPUTS_A2A_PACKAGE_NAME} false --silent
|
||||
|
||||
- name: '🔬 Verify NPM release by version'
|
||||
uses: './.github/actions/verify-release'
|
||||
@@ -254,14 +279,17 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
if: "${{ inputs.dry-run != 'true' && inputs.skip-github-release != 'true' && inputs.npm-tag != 'dev' && inputs.npm-registry-url != 'https://npm.pkg.github.com/' }}"
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ inputs.github-token }}'
|
||||
GITHUB_TOKEN: '${{ inputs.github-release-token || inputs.github-token }}'
|
||||
INPUTS_RELEASE_TAG: '${{ inputs.release-tag }}'
|
||||
STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
INPUTS_PREVIOUS_TAG: '${{ inputs.previous-tag }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
gh release create "${{ inputs.release-tag }}" \
|
||||
gh release create "${INPUTS_RELEASE_TAG}" \
|
||||
bundle/gemini.js \
|
||||
--target "${{ steps.release_branch.outputs.BRANCH_NAME }}" \
|
||||
--title "Release ${{ inputs.release-tag }}" \
|
||||
--notes-start-tag "${{ inputs.previous-tag }}" \
|
||||
--target "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}" \
|
||||
--title "Release ${INPUTS_RELEASE_TAG}" \
|
||||
--notes-start-tag "${INPUTS_PREVIOUS_TAG}" \
|
||||
--generate-notes \
|
||||
${{ inputs.npm-tag != 'latest' && '--prerelease' || '' }}
|
||||
|
||||
@@ -271,5 +299,8 @@ runs:
|
||||
continue-on-error: true
|
||||
shell: 'bash'
|
||||
run: |
|
||||
echo "Cleaning up release branch ${{ steps.release_branch.outputs.BRANCH_NAME }}..."
|
||||
git push origin --delete "${{ steps.release_branch.outputs.BRANCH_NAME }}"
|
||||
echo "Cleaning up release branch ${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}..."
|
||||
git push origin --delete "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}"
|
||||
|
||||
env:
|
||||
STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
|
||||
@@ -52,8 +52,10 @@ runs:
|
||||
id: 'branch_name'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
REF_NAME="${{ inputs.ref-name }}"
|
||||
REF_NAME="${INPUTS_REF_NAME}"
|
||||
echo "name=${REF_NAME%/merge}" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
INPUTS_REF_NAME: '${{ inputs.ref-name }}'
|
||||
- name: 'Build and Push the Docker Image'
|
||||
uses: 'docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83' # ratchet:docker/build-push-action@v6
|
||||
with:
|
||||
|
||||
@@ -44,6 +44,8 @@ runs:
|
||||
- name: 'npm build'
|
||||
shell: 'bash'
|
||||
run: 'npm run build'
|
||||
- name: 'Set up QEMU'
|
||||
uses: 'docker/setup-qemu-action@v3'
|
||||
- name: 'Set up Docker Buildx'
|
||||
uses: 'docker/setup-buildx-action@v3'
|
||||
- name: 'Log in to GitHub Container Registry'
|
||||
@@ -56,8 +58,8 @@ runs:
|
||||
id: 'image_tag'
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
SHELL_TAG_NAME="${{ inputs.github-ref-name }}"
|
||||
FINAL_TAG="${{ inputs.github-sha }}"
|
||||
SHELL_TAG_NAME="${INPUTS_GITHUB_REF_NAME}"
|
||||
FINAL_TAG="${INPUTS_GITHUB_SHA}"
|
||||
if [[ "$SHELL_TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "Release detected."
|
||||
FINAL_TAG="${SHELL_TAG_NAME#v}"
|
||||
@@ -66,22 +68,43 @@ runs:
|
||||
fi
|
||||
echo "Determined image tag: $FINAL_TAG"
|
||||
echo "FINAL_TAG=$FINAL_TAG" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
INPUTS_GITHUB_REF_NAME: '${{ inputs.github-ref-name }}'
|
||||
INPUTS_GITHUB_SHA: '${{ inputs.github-sha }}'
|
||||
# We build amd64 just so we can verify it.
|
||||
# We build and push both amd64 and arm64 in the publish step.
|
||||
- name: 'build'
|
||||
id: 'docker_build'
|
||||
shell: 'bash'
|
||||
env:
|
||||
GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
GEMINI_SANDBOX: 'docker'
|
||||
BUILD_SANDBOX_FLAGS: '--platform linux/amd64 --load'
|
||||
STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
run: |-
|
||||
npm run build:sandbox -- \
|
||||
--image google/gemini-cli-sandbox:${{ steps.image_tag.outputs.FINAL_TAG }} \
|
||||
--image "google/gemini-cli-sandbox:${STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG}" \
|
||||
--output-file final_image_uri.txt
|
||||
echo "uri=$(cat final_image_uri.txt)" >> $GITHUB_OUTPUT
|
||||
- name: 'verify'
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
docker run --rm --entrypoint sh "${{ steps.docker_build.outputs.uri }}" -lc '
|
||||
set -e
|
||||
node -e "const fs=require(\"node:fs\"); JSON.parse(fs.readFileSync(\"/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json\",\"utf8\")); JSON.parse(fs.readFileSync(\"/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json\",\"utf8\"));"
|
||||
/usr/local/share/npm-global/bin/gemini --version >/dev/null
|
||||
'
|
||||
- name: 'publish'
|
||||
shell: 'bash'
|
||||
if: "${{ inputs.dry-run != 'true' }}"
|
||||
env:
|
||||
GEMINI_SANDBOX_IMAGE_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
GEMINI_SANDBOX: 'docker'
|
||||
BUILD_SANDBOX_FLAGS: '--platform linux/amd64,linux/arm64 --push'
|
||||
STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG: '${{ steps.image_tag.outputs.FINAL_TAG }}'
|
||||
run: |-
|
||||
docker push "${{ steps.docker_build.outputs.uri }}"
|
||||
npm run build:sandbox -- \
|
||||
--image "google/gemini-cli-sandbox:${STEPS_IMAGE_TAG_OUTPUTS_FINAL_TAG}"
|
||||
- name: 'Create issue on failure'
|
||||
if: |-
|
||||
${{ failure() }}
|
||||
|
||||
@@ -18,5 +18,7 @@ runs:
|
||||
shell: 'bash'
|
||||
run: |-
|
||||
echo ""@google-gemini:registry=https://npm.pkg.github.com"" > ~/.npmrc
|
||||
echo ""//npm.pkg.github.com/:_authToken=${{ inputs.github-token }}"" >> ~/.npmrc
|
||||
echo ""//npm.pkg.github.com/:_authToken=${INPUTS_GITHUB_TOKEN}"" >> ~/.npmrc
|
||||
echo ""@google:registry=https://wombat-dressing-room.appspot.com"" >> ~/.npmrc
|
||||
env:
|
||||
INPUTS_GITHUB_TOKEN: '${{ inputs.github-token }}'
|
||||
|
||||
@@ -71,10 +71,13 @@ runs:
|
||||
${{ inputs.dry-run != 'true' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.core-token.outputs.auth-token }}'
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
npm dist-tag add ${{ inputs.core-package-name }}@${{ inputs.version }} ${{ inputs.channel }}
|
||||
npm dist-tag add ${INPUTS_CORE_PACKAGE_NAME}@${INPUTS_VERSION} ${INPUTS_CHANNEL}
|
||||
|
||||
- name: 'Get cli Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -91,10 +94,13 @@ runs:
|
||||
${{ inputs.dry-run != 'true' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.cli-token.outputs.auth-token }}'
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
npm dist-tag add ${{ inputs.cli-package-name }}@${{ inputs.version }} ${{ inputs.channel }}
|
||||
npm dist-tag add ${INPUTS_CLI_PACKAGE_NAME}@${INPUTS_VERSION} ${INPUTS_CHANNEL}
|
||||
|
||||
- name: 'Get a2a Token'
|
||||
uses: './.github/actions/npm-auth-token'
|
||||
@@ -111,10 +117,13 @@ runs:
|
||||
${{ inputs.dry-run == 'false' }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: '${{ steps.a2a-token.outputs.auth-token }}'
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
npm dist-tag add ${{ inputs.a2a-package-name }}@${{ inputs.version }} ${{ inputs.channel }}
|
||||
npm dist-tag add ${INPUTS_A2A_PACKAGE_NAME}@${INPUTS_VERSION} ${INPUTS_CHANNEL}
|
||||
|
||||
- name: 'Log dry run'
|
||||
if: |-
|
||||
@@ -122,4 +131,15 @@ runs:
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |
|
||||
echo "Dry run: Would have added tag '${{ inputs.channel }}' to version '${{ inputs.version }}' for ${{ inputs.cli-package-name }}, ${{ inputs.core-package-name }}, and ${{ inputs.a2a-package-name }}."
|
||||
echo "Dry run: Would have added tag '${INPUTS_CHANNEL}' to version '${INPUTS_VERSION}' for ${INPUTS_CLI_PACKAGE_NAME}, ${INPUTS_CORE_PACKAGE_NAME}, and ${INPUTS_A2A_PACKAGE_NAME}."
|
||||
|
||||
env:
|
||||
INPUTS_CHANNEL: '${{ inputs.channel }}'
|
||||
|
||||
INPUTS_VERSION: '${{ inputs.version }}'
|
||||
|
||||
INPUTS_CLI_PACKAGE_NAME: '${{ inputs.cli-package-name }}'
|
||||
|
||||
INPUTS_CORE_PACKAGE_NAME: '${{ inputs.core-package-name }}'
|
||||
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
|
||||
@@ -64,10 +64,13 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |-
|
||||
gemini_version=$(gemini --version)
|
||||
if [ "$gemini_version" != "${{ inputs.expected-version }}" ]; then
|
||||
echo "❌ NPM Version mismatch: Got $gemini_version from ${{ inputs.npm-package }}, expected ${{ inputs.expected-version }}"
|
||||
if [ "$gemini_version" != "${INPUTS_EXPECTED_VERSION}" ]; then
|
||||
echo "❌ NPM Version mismatch: Got $gemini_version from ${INPUTS_NPM_PACKAGE}, expected ${INPUTS_EXPECTED_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
INPUTS_EXPECTED_VERSION: '${{ inputs.expected-version }}'
|
||||
INPUTS_NPM_PACKAGE: '${{ inputs.npm-package }}'
|
||||
|
||||
- name: 'Clear npm cache'
|
||||
shell: 'bash'
|
||||
@@ -77,11 +80,14 @@ runs:
|
||||
shell: 'bash'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |-
|
||||
gemini_version=$(npx --prefer-online "${{ inputs.npm-package}}" --version)
|
||||
if [ "$gemini_version" != "${{ inputs.expected-version }}" ]; then
|
||||
echo "❌ NPX Run Version mismatch: Got $gemini_version from ${{ inputs.npm-package }}, expected ${{ inputs.expected-version }}"
|
||||
gemini_version=$(npx --prefer-online "${INPUTS_NPM_PACKAGE}" --version)
|
||||
if [ "$gemini_version" != "${INPUTS_EXPECTED_VERSION}" ]; then
|
||||
echo "❌ NPX Run Version mismatch: Got $gemini_version from ${INPUTS_NPM_PACKAGE}, expected ${INPUTS_EXPECTED_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
INPUTS_NPM_PACKAGE: '${{ inputs.npm-package }}'
|
||||
INPUTS_EXPECTED_VERSION: '${{ inputs.expected-version }}'
|
||||
|
||||
- name: 'Install dependencies for integration tests'
|
||||
shell: 'bash'
|
||||
|
||||
+18
-20
@@ -1,35 +1,33 @@
|
||||
# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: 'npm'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'daily'
|
||||
target-branch: 'main'
|
||||
commit-message:
|
||||
prefix: 'chore(deps)'
|
||||
include: 'scope'
|
||||
interval: 'weekly'
|
||||
day: 'monday'
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- 'google-gemini/gemini-cli-askmode-approvers'
|
||||
- 'joshualitt'
|
||||
groups:
|
||||
# Group all non-major updates together.
|
||||
# This is to reduce the number of PRs that need to be reviewed.
|
||||
# Major updates will still be created as separate PRs.
|
||||
npm-minor-patch:
|
||||
applies-to: 'version-updates'
|
||||
npm-dependencies:
|
||||
patterns:
|
||||
- '*'
|
||||
update-types:
|
||||
- 'minor'
|
||||
- 'patch'
|
||||
open-pull-requests-limit: 0
|
||||
|
||||
- package-ecosystem: 'github-actions'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'daily'
|
||||
target-branch: 'main'
|
||||
commit-message:
|
||||
prefix: 'chore(deps)'
|
||||
include: 'scope'
|
||||
interval: 'weekly'
|
||||
day: 'monday'
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- 'google-gemini/gemini-cli-askmode-approvers'
|
||||
open-pull-requests-limit: 0
|
||||
- 'joshualitt'
|
||||
groups:
|
||||
actions-dependencies:
|
||||
patterns:
|
||||
- '*'
|
||||
update-types:
|
||||
- 'minor'
|
||||
- 'patch'
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/* eslint-disable */
|
||||
/* global require, console, process */
|
||||
|
||||
/**
|
||||
* Script to backfill the 'status/need-triage' label to all open issues
|
||||
* that are NOT currently labeled with '🔒 maintainer only' or 'help wanted'.
|
||||
*/
|
||||
|
||||
const { execFileSync } = require('child_process');
|
||||
|
||||
const isDryRun = process.argv.includes('--dry-run');
|
||||
const REPO = 'google-gemini/gemini-cli';
|
||||
|
||||
/**
|
||||
* Executes a GitHub CLI command safely using an argument array to prevent command injection.
|
||||
* @param {string[]} args
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function runGh(args) {
|
||||
try {
|
||||
// Using execFileSync with an array of arguments is safe as it doesn't use a shell.
|
||||
// We set a large maxBuffer (10MB) to handle repositories with many issues.
|
||||
return execFileSync('gh', args, {
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
}).trim();
|
||||
} catch (error) {
|
||||
const stderr = error.stderr ? ` Stderr: ${error.stderr.trim()}` : '';
|
||||
console.error(
|
||||
`❌ Error running gh ${args.join(' ')}: ${error.message}${stderr}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🔐 GitHub CLI security check...');
|
||||
const authStatus = runGh(['auth', 'status']);
|
||||
if (authStatus === null) {
|
||||
console.error('❌ GitHub CLI (gh) is not installed or not authenticated.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (isDryRun) {
|
||||
console.log('🧪 DRY RUN MODE ENABLED - No changes will be made.\n');
|
||||
}
|
||||
|
||||
console.log(`🔍 Fetching and filtering open issues from ${REPO}...`);
|
||||
|
||||
// We use the /issues endpoint with pagination to bypass the 1000-result limit.
|
||||
// The jq filter ensures we exclude PRs, maintainer-only, help-wanted, and existing status/need-triage.
|
||||
const jqFilter =
|
||||
'.[] | select(.pull_request == null) | select([.labels[].name] as $l | (any($l[]; . == "🔒 maintainer only") | not) and (any($l[]; . == "help wanted") | not) and (any($l[]; . == "status/need-triage") | not)) | {number: .number, title: .title}';
|
||||
|
||||
const output = runGh([
|
||||
'api',
|
||||
`repos/${REPO}/issues?state=open&per_page=100`,
|
||||
'--paginate',
|
||||
'--jq',
|
||||
jqFilter,
|
||||
]);
|
||||
|
||||
if (output === null) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const issues = output
|
||||
.split('\n')
|
||||
.filter((line) => line.trim())
|
||||
.map((line) => {
|
||||
try {
|
||||
return JSON.parse(line);
|
||||
} catch (_e) {
|
||||
console.error(`⚠️ Failed to parse line: ${line}`);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
console.log(`✅ Found ${issues.length} issues matching criteria.`);
|
||||
|
||||
if (issues.length === 0) {
|
||||
console.log('✨ No issues need backfilling.');
|
||||
return;
|
||||
}
|
||||
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
|
||||
if (isDryRun) {
|
||||
for (const issue of issues) {
|
||||
console.log(
|
||||
`[DRY RUN] Would label issue #${issue.number}: ${issue.title}`,
|
||||
);
|
||||
}
|
||||
successCount = issues.length;
|
||||
} else {
|
||||
console.log(`🏷️ Applying labels to ${issues.length} issues...`);
|
||||
|
||||
for (const issue of issues) {
|
||||
const issueNumber = String(issue.number);
|
||||
console.log(`🏷️ Labeling issue #${issueNumber}: ${issue.title}`);
|
||||
|
||||
const result = runGh([
|
||||
'issue',
|
||||
'edit',
|
||||
issueNumber,
|
||||
'--add-label',
|
||||
'status/need-triage',
|
||||
'--repo',
|
||||
REPO,
|
||||
]);
|
||||
|
||||
if (result !== null) {
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n📊 Summary:`);
|
||||
console.log(` - Success: ${successCount}`);
|
||||
console.log(` - Failed: ${failCount}`);
|
||||
|
||||
if (failCount > 0) {
|
||||
console.error(`\n❌ Backfill completed with ${failCount} errors.`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log(`\n🎉 ${isDryRun ? 'Dry run' : 'Backfill'} complete!`);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('❌ Unexpected error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
/* global require, console, process */
|
||||
|
||||
/**
|
||||
* Script to backfill a process change notification comment to all open PRs
|
||||
* not created by members of the 'gemini-cli-maintainers' team.
|
||||
*
|
||||
* Skip PRs that are already associated with an issue.
|
||||
*/
|
||||
|
||||
const { execFileSync } = require('child_process');
|
||||
|
||||
const isDryRun = process.argv.includes('--dry-run');
|
||||
const REPO = 'google-gemini/gemini-cli';
|
||||
const ORG = 'google-gemini';
|
||||
const TEAM_SLUG = 'gemini-cli-maintainers';
|
||||
const DISCUSSION_URL =
|
||||
'https://github.com/google-gemini/gemini-cli/discussions/16706';
|
||||
|
||||
/**
|
||||
* Executes a GitHub CLI command safely using an argument array.
|
||||
*/
|
||||
function runGh(args, options = {}) {
|
||||
const { silent = false } = options;
|
||||
try {
|
||||
return execFileSync('gh', args, {
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
}).trim();
|
||||
} catch (error) {
|
||||
if (!silent) {
|
||||
const stderr = error.stderr ? ` Stderr: ${error.stderr.trim()}` : '';
|
||||
console.error(
|
||||
`❌ Error running gh ${args.join(' ')}: ${error.message}${stderr}`,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a user is a member of the maintainers team.
|
||||
*/
|
||||
const membershipCache = new Map();
|
||||
function isMaintainer(username) {
|
||||
if (membershipCache.has(username)) return membershipCache.get(username);
|
||||
|
||||
// GitHub returns 404 if user is not a member.
|
||||
// We use silent: true to avoid logging 404s as errors.
|
||||
const result = runGh(
|
||||
['api', `orgs/${ORG}/teams/${TEAM_SLUG}/memberships/${username}`],
|
||||
{ silent: true },
|
||||
);
|
||||
|
||||
const isMember = result !== null;
|
||||
membershipCache.set(username, isMember);
|
||||
return isMember;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🔐 GitHub CLI security check...');
|
||||
if (runGh(['auth', 'status']) === null) {
|
||||
console.error('❌ GitHub CLI (gh) is not authenticated.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (isDryRun) {
|
||||
console.log('🧪 DRY RUN MODE ENABLED\n');
|
||||
}
|
||||
|
||||
console.log(`📥 Fetching open PRs from ${REPO}...`);
|
||||
// Fetch number, author, and closingIssuesReferences to check if linked to an issue
|
||||
const prsJson = runGh([
|
||||
'pr',
|
||||
'list',
|
||||
'--repo',
|
||||
REPO,
|
||||
'--state',
|
||||
'open',
|
||||
'--limit',
|
||||
'1000',
|
||||
'--json',
|
||||
'number,author,closingIssuesReferences',
|
||||
]);
|
||||
|
||||
if (prsJson === null) process.exit(1);
|
||||
const prs = JSON.parse(prsJson);
|
||||
|
||||
console.log(`📊 Found ${prs.length} open PRs. Filtering...`);
|
||||
|
||||
let targetPrs = [];
|
||||
for (const pr of prs) {
|
||||
const author = pr.author.login;
|
||||
const issueCount = pr.closingIssuesReferences
|
||||
? pr.closingIssuesReferences.length
|
||||
: 0;
|
||||
|
||||
if (issueCount > 0) {
|
||||
// Skip if already linked to an issue
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isMaintainer(author)) {
|
||||
targetPrs.push(pr);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`✅ Found ${targetPrs.length} PRs from non-maintainers without associated issues.`,
|
||||
);
|
||||
|
||||
const commentBody =
|
||||
"\nHi @{AUTHOR}, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.\n\nWe're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: [Improving Our Contribution Process & Introducing New Guidelines](${DISCUSSION_URL}).\n\nKey Update: Starting **January 26, 2026**, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.\n\nThank you for your understanding and for being a part of our community!\n ".trim();
|
||||
|
||||
let successCount = 0;
|
||||
let skipCount = 0;
|
||||
let failCount = 0;
|
||||
|
||||
for (const pr of targetPrs) {
|
||||
const prNumber = String(pr.number);
|
||||
const author = pr.author.login;
|
||||
|
||||
// Check if we already commented (idempotency)
|
||||
// We use silent: true here because view might fail if PR is deleted mid-run
|
||||
const existingComments = runGh(
|
||||
[
|
||||
'pr',
|
||||
'view',
|
||||
prNumber,
|
||||
'--repo',
|
||||
REPO,
|
||||
'--json',
|
||||
'comments',
|
||||
'--jq',
|
||||
`.comments[].body | contains("${DISCUSSION_URL}")`,
|
||||
],
|
||||
{ silent: true },
|
||||
);
|
||||
|
||||
if (existingComments && existingComments.includes('true')) {
|
||||
console.log(
|
||||
`⏭️ PR #${prNumber} already has the notification. Skipping.`,
|
||||
);
|
||||
skipCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isDryRun) {
|
||||
console.log(`[DRY RUN] Would notify @${author} on PR #${prNumber}`);
|
||||
successCount++;
|
||||
} else {
|
||||
console.log(`💬 Notifying @${author} on PR #${prNumber}...`);
|
||||
const personalizedComment = commentBody.replace('{AUTHOR}', author);
|
||||
const result = runGh([
|
||||
'pr',
|
||||
'comment',
|
||||
prNumber,
|
||||
'--repo',
|
||||
REPO,
|
||||
'--body',
|
||||
personalizedComment,
|
||||
]);
|
||||
|
||||
if (result !== null) {
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n📊 Summary:`);
|
||||
console.log(` - Notified: ${successCount}`);
|
||||
console.log(` - Skipped: ${skipCount}`);
|
||||
console.log(` - Failed: ${failCount}`);
|
||||
|
||||
if (failCount > 0) process.exit(1);
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
+155
-108
@@ -1,133 +1,180 @@
|
||||
#!/usr/bin/env bash
|
||||
# @license
|
||||
# Copyright 2026 Google LLC
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Initialize a comma-separated string to hold PR numbers that need a comment
|
||||
PRS_NEEDING_COMMENT=""
|
||||
|
||||
# Function to process a single PR
|
||||
process_pr() {
|
||||
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
echo "‼️ Missing \$GITHUB_REPOSITORY - this must be run from GitHub Actions"
|
||||
return 1
|
||||
# Global cache for issue labels (compatible with Bash 3.2)
|
||||
# Stores "|ISSUE_NUM:LABELS|" segments
|
||||
ISSUE_LABELS_CACHE_FLAT="|"
|
||||
|
||||
# Function to get labels from an issue (with caching)
|
||||
get_issue_labels() {
|
||||
local ISSUE_NUM="${1}"
|
||||
if [[ -z "${ISSUE_NUM}" || "${ISSUE_NUM}" == "null" || "${ISSUE_NUM}" == "" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "‼️ Missing \$GITHUB_OUTPUT - this must be run from GitHub Actions"
|
||||
return 1
|
||||
# Check cache
|
||||
case "${ISSUE_LABELS_CACHE_FLAT}" in
|
||||
*"|${ISSUE_NUM}:"*)
|
||||
local suffix="${ISSUE_LABELS_CACHE_FLAT#*|"${ISSUE_NUM}":}"
|
||||
echo "${suffix%%|*}"
|
||||
return
|
||||
;;
|
||||
*)
|
||||
# Cache miss, proceed to fetch
|
||||
;;
|
||||
esac
|
||||
|
||||
echo " 📥 Fetching labels from issue #${ISSUE_NUM}" >&2
|
||||
local gh_output
|
||||
if ! gh_output=$(gh issue view "${ISSUE_NUM}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null); then
|
||||
echo " ⚠️ Could not fetch issue #${ISSUE_NUM}" >&2
|
||||
ISSUE_LABELS_CACHE_FLAT="${ISSUE_LABELS_CACHE_FLAT}${ISSUE_NUM}:|"
|
||||
return
|
||||
fi
|
||||
|
||||
local PR_NUMBER=$1
|
||||
local labels
|
||||
labels=$(echo "${gh_output}" | grep -x -E '(area|priority)/.*|help wanted|🔒 maintainer only' | tr '\n' ',' | sed 's/,$//' || echo "")
|
||||
|
||||
# Save to flat cache
|
||||
ISSUE_LABELS_CACHE_FLAT="${ISSUE_LABELS_CACHE_FLAT}${ISSUE_NUM}:${labels}|"
|
||||
echo "${labels}"
|
||||
}
|
||||
|
||||
# Function to process a single PR with pre-fetched data
|
||||
process_pr_optimized() {
|
||||
local PR_NUMBER="${1}"
|
||||
local IS_DRAFT="${2}"
|
||||
local ISSUE_NUMBER="${3}"
|
||||
local CURRENT_LABELS="${4}" # Comma-separated labels
|
||||
|
||||
echo "🔄 Processing PR #${PR_NUMBER}"
|
||||
|
||||
# Get closing issue number with error handling
|
||||
local ISSUE_NUMBER
|
||||
if ! ISSUE_NUMBER=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json closingIssuesReferences -q '.closingIssuesReferences.nodes[0].number' 2>/dev/null); then
|
||||
echo " ⚠️ Could not fetch closing issue for PR #${PR_NUMBER}"
|
||||
local LABELS_TO_ADD=""
|
||||
local LABELS_TO_REMOVE=""
|
||||
|
||||
if [[ -z "${ISSUE_NUMBER}" || "${ISSUE_NUMBER}" == "null" || "${ISSUE_NUMBER}" == "" ]]; then
|
||||
if [[ "${IS_DRAFT}" == "true" ]]; then
|
||||
echo " 📝 PR #${PR_NUMBER} is a draft and has no linked issue"
|
||||
if [[ ",${CURRENT_LABELS}," == *",status/need-issue,"* ]]; then
|
||||
echo " ➖ Removing status/need-issue label"
|
||||
LABELS_TO_REMOVE="status/need-issue"
|
||||
fi
|
||||
else
|
||||
echo " ⚠️ No linked issue found for PR #${PR_NUMBER}"
|
||||
if [[ ",${CURRENT_LABELS}," != *",status/need-issue,"* ]]; then
|
||||
echo " ➕ Adding status/need-issue label"
|
||||
LABELS_TO_ADD="status/need-issue"
|
||||
fi
|
||||
|
||||
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
|
||||
PRS_NEEDING_COMMENT="${PR_NUMBER}"
|
||||
else
|
||||
PRS_NEEDING_COMMENT="${PRS_NEEDING_COMMENT},${PR_NUMBER}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo " 🔗 Found linked issue #${ISSUE_NUMBER}"
|
||||
|
||||
if [[ ",${CURRENT_LABELS}," == *",status/need-issue,"* ]]; then
|
||||
echo " ➖ Removing status/need-issue label"
|
||||
LABELS_TO_REMOVE="status/need-issue"
|
||||
fi
|
||||
|
||||
local ISSUE_LABELS
|
||||
ISSUE_LABELS=$(get_issue_labels "${ISSUE_NUMBER}")
|
||||
|
||||
if [[ -n "${ISSUE_LABELS}" ]]; then
|
||||
local IFS_OLD="${IFS}"
|
||||
IFS=','
|
||||
for label in ${ISSUE_LABELS}; do
|
||||
if [[ -n "${label}" ]] && [[ ",${CURRENT_LABELS}," != *",${label},"* ]]; then
|
||||
if [[ -z "${LABELS_TO_ADD}" ]]; then
|
||||
LABELS_TO_ADD="${label}"
|
||||
else
|
||||
LABELS_TO_ADD="${LABELS_TO_ADD},${label}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
IFS="${IFS_OLD}"
|
||||
fi
|
||||
|
||||
if [[ -z "${LABELS_TO_ADD}" && -z "${LABELS_TO_REMOVE}" ]]; then
|
||||
echo " ✅ Labels already synchronized"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${ISSUE_NUMBER}" ]]; then
|
||||
echo "⚠️ No linked issue found for PR #${PR_NUMBER}, adding status/need-issue label"
|
||||
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "status/need-issue" 2>/dev/null; then
|
||||
echo " ⚠️ Failed to add label (may already exist or have permission issues)"
|
||||
fi
|
||||
# Add PR number to the list
|
||||
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
|
||||
PRS_NEEDING_COMMENT="${PR_NUMBER}"
|
||||
else
|
||||
PRS_NEEDING_COMMENT="${PRS_NEEDING_COMMENT},${PR_NUMBER}"
|
||||
fi
|
||||
echo "needs_comment=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "🔗 Found linked issue #${ISSUE_NUMBER}"
|
||||
|
||||
# Remove status/need-issue label if present
|
||||
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --remove-label "status/need-issue" 2>/dev/null; then
|
||||
echo " status/need-issue label not present or could not be removed"
|
||||
fi
|
||||
|
||||
# Get issue labels
|
||||
echo "📥 Fetching labels from issue #${ISSUE_NUMBER}"
|
||||
local ISSUE_LABELS=""
|
||||
if ! ISSUE_LABELS=$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null | tr '\n' ',' | sed 's/,$//' || echo ""); then
|
||||
echo " ⚠️ Could not fetch issue #${ISSUE_NUMBER} (may not exist or be in different repo)"
|
||||
ISSUE_LABELS=""
|
||||
fi
|
||||
|
||||
# Get PR labels
|
||||
echo "📥 Fetching labels from PR #${PR_NUMBER}"
|
||||
local PR_LABELS=""
|
||||
if ! PR_LABELS=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null | tr '\n' ',' | sed 's/,$//' || echo ""); then
|
||||
echo " ⚠️ Could not fetch PR labels"
|
||||
PR_LABELS=""
|
||||
fi
|
||||
|
||||
echo " Issue labels: ${ISSUE_LABELS}"
|
||||
echo " PR labels: ${PR_LABELS}"
|
||||
|
||||
# Convert comma-separated strings to arrays
|
||||
local ISSUE_LABEL_ARRAY PR_LABEL_ARRAY
|
||||
IFS=',' read -ra ISSUE_LABEL_ARRAY <<< "${ISSUE_LABELS}"
|
||||
IFS=',' read -ra PR_LABEL_ARRAY <<< "${PR_LABELS}"
|
||||
|
||||
# Find labels to add (on issue but not on PR)
|
||||
local LABELS_TO_ADD=""
|
||||
for label in "${ISSUE_LABEL_ARRAY[@]}"; do
|
||||
if [[ -n "${label}" ]] && [[ " ${PR_LABEL_ARRAY[*]} " != *" ${label} "* ]]; then
|
||||
if [[ -z "${LABELS_TO_ADD}" ]]; then
|
||||
LABELS_TO_ADD="${label}"
|
||||
else
|
||||
LABELS_TO_ADD="${LABELS_TO_ADD},${label}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Apply label changes
|
||||
if [[ -n "${LABELS_TO_ADD}" || -n "${LABELS_TO_REMOVE}" ]]; then
|
||||
local EDIT_CMD=("gh" "pr" "edit" "${PR_NUMBER}" "--repo" "${GITHUB_REPOSITORY}")
|
||||
if [[ -n "${LABELS_TO_ADD}" ]]; then
|
||||
echo "➕ Adding labels: ${LABELS_TO_ADD}"
|
||||
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "${LABELS_TO_ADD}" 2>/dev/null; then
|
||||
echo " ⚠️ Failed to add some labels"
|
||||
fi
|
||||
echo " ➕ Syncing labels to add: ${LABELS_TO_ADD}"
|
||||
EDIT_CMD+=("--add-label" "${LABELS_TO_ADD}")
|
||||
fi
|
||||
|
||||
if [[ -z "${LABELS_TO_ADD}" ]]; then
|
||||
echo "✅ Labels already synchronized"
|
||||
if [[ -n "${LABELS_TO_REMOVE}" ]]; then
|
||||
echo " ➖ Syncing labels to remove: ${LABELS_TO_REMOVE}"
|
||||
EDIT_CMD+=("--remove-label" "${LABELS_TO_REMOVE}")
|
||||
fi
|
||||
echo "needs_comment=false" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
("${EDIT_CMD[@]}" || true)
|
||||
fi
|
||||
}
|
||||
|
||||
# If PR_NUMBER is set, process only that PR
|
||||
if [[ -n "${PR_NUMBER:-}" ]]; then
|
||||
if ! process_pr "${PR_NUMBER}"; then
|
||||
echo "❌ Failed to process PR #${PR_NUMBER}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Otherwise, get all open PRs and process them
|
||||
# The script logic will determine which ones need issue linking or label sync
|
||||
echo "📥 Getting all open pull requests..."
|
||||
if ! PR_NUMBERS=$(gh pr list --repo "${GITHUB_REPOSITORY}" --state open --limit 1000 --json number -q '.[].number' 2>/dev/null); then
|
||||
echo "❌ Failed to fetch PR list"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${PR_NUMBERS}" ]]; then
|
||||
echo "✅ No open PRs found"
|
||||
else
|
||||
# Count the number of PRs
|
||||
PR_COUNT=$(echo "${PR_NUMBERS}" | wc -w | tr -d ' ')
|
||||
echo "📊 Found ${PR_COUNT} open PRs to process"
|
||||
|
||||
for pr_number in ${PR_NUMBERS}; do
|
||||
if ! process_pr "${pr_number}"; then
|
||||
echo "⚠️ Failed to process PR #${pr_number}, continuing with next PR..."
|
||||
continue
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
echo "‼️ Missing \$GITHUB_REPOSITORY - this must be run from GitHub Actions"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "‼️ Missing \$GITHUB_OUTPUT - this must be run from GitHub Actions"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
JQ_EXTRACT_FIELDS='{
|
||||
number: .number,
|
||||
isDraft: .isDraft,
|
||||
issue: (.closingIssuesReferences[0].number // (.body // "" | capture("(^|[^a-zA-Z0-9])#(?<num>[0-9]+)([^a-zA-Z0-9]|$)")? | .num) // "null"),
|
||||
labels: [.labels[].name] | join(",")
|
||||
}'
|
||||
|
||||
JQ_TSV_FORMAT='"\((.number | tostring))\t\(.isDraft)\t\((.issue // null) | tostring)\t\(.labels)"'
|
||||
|
||||
if [[ -n "${PR_NUMBER:-}" ]]; then
|
||||
echo "🔄 Processing single PR #${PR_NUMBER}"
|
||||
PR_DATA=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json number,closingIssuesReferences,isDraft,body,labels 2>/dev/null) || {
|
||||
echo "❌ Failed to fetch data for PR #${PR_NUMBER}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
line=$(echo "${PR_DATA}" | jq -r "${JQ_EXTRACT_FIELDS} | ${JQ_TSV_FORMAT}")
|
||||
IFS=$'\t' read -r pr_num is_draft issue_num current_labels <<< "${line}"
|
||||
process_pr_optimized "${pr_num}" "${is_draft}" "${issue_num}" "${current_labels}"
|
||||
else
|
||||
echo "📥 Getting all open pull requests..."
|
||||
PR_DATA_ALL=$(gh pr list --repo "${GITHUB_REPOSITORY}" --state open --limit 1000 --json number,closingIssuesReferences,isDraft,body,labels 2>/dev/null) || {
|
||||
echo "❌ Failed to fetch PR list"
|
||||
exit 1
|
||||
}
|
||||
|
||||
PR_COUNT=$(echo "${PR_DATA_ALL}" | jq '. | length')
|
||||
echo "📊 Found ${PR_COUNT} open PRs to process"
|
||||
|
||||
# Use a temporary file to avoid masking exit codes in process substitution
|
||||
tmp_file=$(mktemp)
|
||||
echo "${PR_DATA_ALL}" | jq -r ".[] | ${JQ_EXTRACT_FIELDS} | ${JQ_TSV_FORMAT}" > "${tmp_file}"
|
||||
while read -r line; do
|
||||
[[ -z "${line}" ]] && continue
|
||||
IFS=$'\t' read -r pr_num is_draft issue_num current_labels <<< "${line}"
|
||||
process_pr_optimized "${pr_num}" "${is_draft}" "${issue_num}" "${current_labels}"
|
||||
done < "${tmp_file}"
|
||||
rm -f "${tmp_file}"
|
||||
fi
|
||||
|
||||
# Ensure output is always set, even if empty
|
||||
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
|
||||
echo "prs_needing_comment=[]" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
|
||||
/**
|
||||
* Sync Maintainer Labels (Recursive with strict parent-child relationship detection)
|
||||
* - Uses Native Sub-issues.
|
||||
* - Uses Markdown Task Lists (- [ ] #123).
|
||||
* - Filters for OPEN issues only.
|
||||
* - Skips DUPLICATES.
|
||||
* - Skips Pull Requests.
|
||||
* - ONLY labels issues in the PUBLIC (gemini-cli) repo.
|
||||
*/
|
||||
|
||||
const REPO_OWNER = 'google-gemini';
|
||||
const PUBLIC_REPO = 'gemini-cli';
|
||||
const PRIVATE_REPO = 'maintainers-gemini-cli';
|
||||
const ALLOWED_REPOS = [PUBLIC_REPO, PRIVATE_REPO];
|
||||
|
||||
const ROOT_ISSUES = [
|
||||
{ owner: REPO_OWNER, repo: PUBLIC_REPO, number: 15374 },
|
||||
{ owner: REPO_OWNER, repo: PUBLIC_REPO, number: 15456 },
|
||||
{ owner: REPO_OWNER, repo: PUBLIC_REPO, number: 15324 },
|
||||
];
|
||||
|
||||
const TARGET_LABEL = '🔒 maintainer only';
|
||||
const isDryRun =
|
||||
process.argv.includes('--dry-run') || process.env.DRY_RUN === 'true';
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
});
|
||||
|
||||
/**
|
||||
* Extracts child issue references from markdown Task Lists ONLY.
|
||||
* e.g. - [ ] #123 or - [x] google-gemini/gemini-cli#123
|
||||
*/
|
||||
function extractTaskListLinks(text, contextOwner, contextRepo) {
|
||||
if (!text) return [];
|
||||
const childIssues = new Map();
|
||||
|
||||
const add = (owner, repo, number) => {
|
||||
if (ALLOWED_REPOS.includes(repo)) {
|
||||
const key = `${owner}/${repo}#${number}`;
|
||||
childIssues.set(key, { owner, repo, number: parseInt(number, 10) });
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Full URLs in task lists
|
||||
const urlRegex =
|
||||
/-\s+\[[ x]\].*https:\/\/github\.com\/([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)\/issues\/(\d+)\b/g;
|
||||
let match;
|
||||
while ((match = urlRegex.exec(text)) !== null) {
|
||||
add(match[1], match[2], match[3]);
|
||||
}
|
||||
|
||||
// 2. Cross-repo refs in task lists: owner/repo#123
|
||||
const crossRepoRegex =
|
||||
/-\s+\[[ x]\].*([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)#(\d+)\b/g;
|
||||
while ((match = crossRepoRegex.exec(text)) !== null) {
|
||||
add(match[1], match[2], match[3]);
|
||||
}
|
||||
|
||||
// 3. Short refs in task lists: #123
|
||||
const shortRefRegex = /-\s+\[[ x]\].*#(\d+)\b/g;
|
||||
while ((match = shortRefRegex.exec(text)) !== null) {
|
||||
add(contextOwner, contextRepo, match[1]);
|
||||
}
|
||||
|
||||
return Array.from(childIssues.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches issue data via GraphQL with full pagination for sub-issues, comments, and labels.
|
||||
*/
|
||||
async function fetchIssueData(owner, repo, number) {
|
||||
const query = `
|
||||
query($owner:String!, $repo:String!, $number:Int!) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
issue(number:$number) {
|
||||
state
|
||||
title
|
||||
body
|
||||
labels(first: 100) {
|
||||
nodes { name }
|
||||
pageInfo { hasNextPage endCursor }
|
||||
}
|
||||
subIssues(first: 100) {
|
||||
nodes {
|
||||
number
|
||||
repository {
|
||||
name
|
||||
owner { login }
|
||||
}
|
||||
}
|
||||
pageInfo { hasNextPage endCursor }
|
||||
}
|
||||
comments(first: 100) {
|
||||
nodes {
|
||||
body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await octokit.graphql(query, { owner, repo, number });
|
||||
const data = response.repository.issue;
|
||||
if (!data) return null;
|
||||
|
||||
const issue = {
|
||||
state: data.state,
|
||||
title: data.title,
|
||||
body: data.body || '',
|
||||
labels: data.labels.nodes.map((n) => n.name),
|
||||
subIssues: [...data.subIssues.nodes],
|
||||
comments: data.comments.nodes.map((n) => n.body),
|
||||
};
|
||||
|
||||
// Paginate subIssues if there are more than 100
|
||||
if (data.subIssues.pageInfo.hasNextPage) {
|
||||
const moreSubIssues = await paginateConnection(
|
||||
owner,
|
||||
repo,
|
||||
number,
|
||||
'subIssues',
|
||||
'number repository { name owner { login } }',
|
||||
data.subIssues.pageInfo.endCursor,
|
||||
);
|
||||
issue.subIssues.push(...moreSubIssues);
|
||||
}
|
||||
|
||||
// Paginate labels if there are more than 100 (unlikely but for completeness)
|
||||
if (data.labels.pageInfo.hasNextPage) {
|
||||
const moreLabels = await paginateConnection(
|
||||
owner,
|
||||
repo,
|
||||
number,
|
||||
'labels',
|
||||
'name',
|
||||
data.labels.pageInfo.endCursor,
|
||||
(n) => n.name,
|
||||
);
|
||||
issue.labels.push(...moreLabels);
|
||||
}
|
||||
|
||||
// Note: Comments are handled via Task Lists in body + first 100 comments.
|
||||
// If an issue has > 100 comments with task lists, we'd need to paginate those too.
|
||||
// Given the 1,100+ issue discovery count, 100 comments is usually sufficient,
|
||||
// but we can add it for absolute completeness.
|
||||
// (Skipping for now to avoid excessive API churn unless clearly needed).
|
||||
|
||||
return issue;
|
||||
} catch (error) {
|
||||
if (error.errors && error.errors.some((e) => e.type === 'NOT_FOUND')) {
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to paginate any GraphQL connection.
|
||||
*/
|
||||
async function paginateConnection(
|
||||
owner,
|
||||
repo,
|
||||
number,
|
||||
connectionName,
|
||||
nodeFields,
|
||||
initialCursor,
|
||||
transformNode = (n) => n,
|
||||
) {
|
||||
let additionalNodes = [];
|
||||
let hasNext = true;
|
||||
let cursor = initialCursor;
|
||||
|
||||
while (hasNext) {
|
||||
const query = `
|
||||
query($owner:String!, $repo:String!, $number:Int!, $cursor:String) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
issue(number:$number) {
|
||||
${connectionName}(first: 100, after: $cursor) {
|
||||
nodes { ${nodeFields} }
|
||||
pageInfo { hasNextPage endCursor }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const response = await octokit.graphql(query, {
|
||||
owner,
|
||||
repo,
|
||||
number,
|
||||
cursor,
|
||||
});
|
||||
const connection = response.repository.issue[connectionName];
|
||||
additionalNodes.push(...connection.nodes.map(transformNode));
|
||||
hasNext = connection.pageInfo.hasNextPage;
|
||||
cursor = connection.pageInfo.endCursor;
|
||||
}
|
||||
return additionalNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if an issue should be processed (Open, not a duplicate, not a PR)
|
||||
*/
|
||||
function shouldProcess(issueData) {
|
||||
if (!issueData) return false;
|
||||
|
||||
if (issueData.state !== 'OPEN') return false;
|
||||
|
||||
const labels = issueData.labels.map((l) => l.toLowerCase());
|
||||
if (labels.includes('duplicate') || labels.includes('kind/duplicate')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function getAllDescendants(roots) {
|
||||
const allDescendants = new Map();
|
||||
const visited = new Set();
|
||||
const queue = [...roots];
|
||||
|
||||
for (const root of roots) {
|
||||
visited.add(`${root.owner}/${root.repo}#${root.number}`);
|
||||
}
|
||||
|
||||
console.log(`Starting discovery from ${roots.length} roots...`);
|
||||
|
||||
while (queue.length > 0) {
|
||||
const current = queue.shift();
|
||||
const currentKey = `${current.owner}/${current.repo}#${current.number}`;
|
||||
|
||||
try {
|
||||
const issueData = await fetchIssueData(
|
||||
current.owner,
|
||||
current.repo,
|
||||
current.number,
|
||||
);
|
||||
|
||||
if (!shouldProcess(issueData)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ONLY add to labeling list if it's in the PUBLIC repository
|
||||
if (current.repo === PUBLIC_REPO) {
|
||||
// Don't label the roots themselves
|
||||
if (
|
||||
!ROOT_ISSUES.some(
|
||||
(r) => r.number === current.number && r.repo === current.repo,
|
||||
)
|
||||
) {
|
||||
allDescendants.set(currentKey, {
|
||||
...current,
|
||||
title: issueData.title,
|
||||
labels: issueData.labels,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const children = new Map();
|
||||
|
||||
// 1. Process Native Sub-issues
|
||||
if (issueData.subIssues) {
|
||||
for (const node of issueData.subIssues) {
|
||||
const childOwner = node.repository.owner.login;
|
||||
const childRepo = node.repository.name;
|
||||
const childNumber = node.number;
|
||||
const key = `${childOwner}/${childRepo}#${childNumber}`;
|
||||
children.set(key, {
|
||||
owner: childOwner,
|
||||
repo: childRepo,
|
||||
number: childNumber,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Process Markdown Task Lists in Body and Comments
|
||||
let combinedText = issueData.body || '';
|
||||
if (issueData.comments) {
|
||||
for (const commentBody of issueData.comments) {
|
||||
combinedText += '\n' + (commentBody || '');
|
||||
}
|
||||
}
|
||||
|
||||
const taskListLinks = extractTaskListLinks(
|
||||
combinedText,
|
||||
current.owner,
|
||||
current.repo,
|
||||
);
|
||||
for (const link of taskListLinks) {
|
||||
const key = `${link.owner}/${link.repo}#${link.number}`;
|
||||
children.set(key, link);
|
||||
}
|
||||
|
||||
// Queue children (regardless of which repo they are in, for recursion)
|
||||
for (const [key, child] of children) {
|
||||
if (!visited.has(key)) {
|
||||
visited.add(key);
|
||||
queue.push(child);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing ${currentKey}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(allDescendants.values());
|
||||
}
|
||||
|
||||
async function run() {
|
||||
if (isDryRun) {
|
||||
console.log('=== DRY RUN MODE: No labels will be applied ===');
|
||||
}
|
||||
|
||||
const descendants = await getAllDescendants(ROOT_ISSUES);
|
||||
console.log(
|
||||
`\nFound ${descendants.length} total unique open descendant issues in ${PUBLIC_REPO}.`,
|
||||
);
|
||||
|
||||
for (const issueInfo of descendants) {
|
||||
const issueKey = `${issueInfo.owner}/${issueInfo.repo}#${issueInfo.number}`;
|
||||
try {
|
||||
// Data is already available from the discovery phase
|
||||
const hasLabel = issueInfo.labels.some((l) => l === TARGET_LABEL);
|
||||
|
||||
if (!hasLabel) {
|
||||
if (isDryRun) {
|
||||
console.log(
|
||||
`[DRY RUN] Would label ${issueKey}: "${issueInfo.title}"`,
|
||||
);
|
||||
} else {
|
||||
console.log(`Labeling ${issueKey}: "${issueInfo.title}"...`);
|
||||
await octokit.rest.issues.addLabels({
|
||||
owner: issueInfo.owner,
|
||||
repo: issueInfo.repo,
|
||||
issue_number: issueInfo.number,
|
||||
labels: [TARGET_LABEL],
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error processing label for ${issueKey}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -31,6 +31,7 @@ jobs:
|
||||
name: 'Merge Queue Skipper'
|
||||
permissions: 'read-all'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
outputs:
|
||||
skip: '${{ steps.merge-queue-e2e-skipper.outputs.skip-check }}'
|
||||
steps:
|
||||
@@ -42,7 +43,7 @@ jobs:
|
||||
|
||||
download_repo_name:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "${{github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run'}}"
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run')"
|
||||
outputs:
|
||||
repo_name: '${{ steps.output-repo-name.outputs.repo_name }}'
|
||||
head_sha: '${{ steps.output-repo-name.outputs.head_sha }}'
|
||||
@@ -53,7 +54,7 @@ jobs:
|
||||
REPO_NAME: '${{ github.event.inputs.repo_name }}'
|
||||
run: |
|
||||
mkdir -p ./pr
|
||||
echo '${{ env.REPO_NAME }}' > ./pr/repo_name
|
||||
echo "${REPO_NAME}" > ./pr/repo_name
|
||||
- uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'repo_name'
|
||||
@@ -91,7 +92,7 @@ jobs:
|
||||
name: 'Parse run context'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'download_repo_name'
|
||||
if: 'always()'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
outputs:
|
||||
repository: '${{ steps.set_context.outputs.REPO }}'
|
||||
sha: '${{ steps.set_context.outputs.SHA }}'
|
||||
@@ -111,11 +112,11 @@ jobs:
|
||||
permissions: 'write-all'
|
||||
needs:
|
||||
- 'parse_run_context'
|
||||
if: 'always()'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
steps:
|
||||
- name: 'Set pending status'
|
||||
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master
|
||||
if: 'always()'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
with:
|
||||
allowForks: 'true'
|
||||
repo: '${{ github.repository }}'
|
||||
@@ -131,7 +132,7 @@ jobs:
|
||||
- 'parse_run_context'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: |
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -168,6 +169,7 @@ jobs:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
KEEP_OUTPUT: 'true'
|
||||
VERBOSE: 'true'
|
||||
BUILD_SANDBOX_FLAGS: '--cache-from type=gha --cache-to type=gha,mode=max'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then
|
||||
@@ -183,7 +185,7 @@ jobs:
|
||||
- 'parse_run_context'
|
||||
runs-on: 'macos-latest'
|
||||
if: |
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -221,10 +223,8 @@ jobs:
|
||||
- 'merge_queue_skipper'
|
||||
- 'parse_run_context'
|
||||
if: |
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -264,6 +264,27 @@ jobs:
|
||||
run: 'npm run build'
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Ensure Chrome is available'
|
||||
shell: 'pwsh'
|
||||
run: |
|
||||
$chromePaths = @(
|
||||
"${env:ProgramFiles}\Google\Chrome\Application\chrome.exe",
|
||||
"${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe"
|
||||
)
|
||||
$chromeExists = $chromePaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
if (-not $chromeExists) {
|
||||
Write-Host 'Chrome not found, installing via Chocolatey...'
|
||||
choco install googlechrome -y --no-progress --ignore-checksums
|
||||
}
|
||||
$installed = $chromePaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
if ($installed) {
|
||||
Write-Host "Chrome found at: $installed"
|
||||
& $installed --version
|
||||
} else {
|
||||
Write-Error 'Chrome installation failed'
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: 'Run E2E tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
@@ -276,36 +297,84 @@ jobs:
|
||||
shell: 'pwsh'
|
||||
run: 'npm run test:integration:sandbox:none'
|
||||
|
||||
evals:
|
||||
name: 'Evals (ALWAYS_PASSING)'
|
||||
needs:
|
||||
- 'merge_queue_skipper'
|
||||
- 'parse_run_context'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ needs.parse_run_context.outputs.sha }}'
|
||||
repository: '${{ needs.parse_run_context.outputs.repository }}'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set up Node.js 20.x'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Check if evals should run'
|
||||
id: 'check_evals'
|
||||
run: |
|
||||
SHOULD_RUN=$(node scripts/changed_prompt.js)
|
||||
echo "should_run=$SHOULD_RUN" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Run Evals (Required to pass)'
|
||||
if: "${{ steps.check_evals.outputs.should_run == 'true' }}"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
run: 'npm run test:always_passing_evals'
|
||||
|
||||
e2e:
|
||||
name: 'E2E'
|
||||
if: |
|
||||
always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
needs:
|
||||
- 'e2e_linux'
|
||||
- 'e2e_mac'
|
||||
- 'e2e_windows'
|
||||
- 'evals'
|
||||
- 'merge_queue_skipper'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Check E2E test results'
|
||||
run: |
|
||||
if [[ ${{ needs.e2e_linux.result }} != 'success' || \
|
||||
${{ needs.e2e_mac.result }} != 'success' ]]; then
|
||||
if [[ ${NEEDS_E2E_LINUX_RESULT} != 'success' || \
|
||||
${NEEDS_E2E_MAC_RESULT} != 'success' || \
|
||||
${NEEDS_E2E_WINDOWS_RESULT} != 'success' || \
|
||||
${NEEDS_EVALS_RESULT} != 'success' ]]; then
|
||||
echo "One or more E2E jobs failed."
|
||||
exit 1
|
||||
fi
|
||||
echo "All required E2E jobs passed!"
|
||||
env:
|
||||
NEEDS_E2E_LINUX_RESULT: '${{ needs.e2e_linux.result }}'
|
||||
NEEDS_E2E_MAC_RESULT: '${{ needs.e2e_mac.result }}'
|
||||
NEEDS_E2E_WINDOWS_RESULT: '${{ needs.e2e_windows.result }}'
|
||||
NEEDS_EVALS_RESULT: '${{ needs.evals.result }}'
|
||||
|
||||
set_workflow_status:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions: 'write-all'
|
||||
if: 'always()'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
needs:
|
||||
- 'parse_run_context'
|
||||
- 'e2e'
|
||||
steps:
|
||||
- name: 'Set workflow status'
|
||||
uses: 'myrotvorets/set-commit-status-action@16037e056d73b2d3c88e37e393ff369047f70886' # ratchet:myrotvorets/set-commit-status-action@master
|
||||
if: 'always()'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
with:
|
||||
allowForks: 'true'
|
||||
repo: '${{ github.repository }}'
|
||||
|
||||
+126
-31
@@ -37,19 +37,22 @@ jobs:
|
||||
permissions: 'read-all'
|
||||
name: 'Merge Queue Skipper'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
outputs:
|
||||
skip: '${{ steps.merge-queue-ci-skipper.outputs.skip-check }}'
|
||||
steps:
|
||||
- id: 'merge-queue-ci-skipper'
|
||||
uses: 'cariad-tech/merge-queue-ci-skipper@1032489e59437862c90a08a2c92809c903883772' # ratchet:cariad-tech/merge-queue-ci-skipper@main
|
||||
with:
|
||||
secret: '${{ secrets.GITHUB_TOKEN }}'
|
||||
secret: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
|
||||
lint:
|
||||
name: 'Lint'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
env:
|
||||
GEMINI_LINT_TEMP_DIR: '${{ github.workspace }}/.gemini-linters'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
@@ -63,9 +66,21 @@ jobs:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Cache Linters'
|
||||
uses: 'actions/cache@v4'
|
||||
with:
|
||||
path: '${{ env.GEMINI_LINT_TEMP_DIR }}'
|
||||
key: "${{ runner.os }}-${{ runner.arch }}-linters-${{ hashFiles('scripts/lint.js') }}"
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Cache ESLint'
|
||||
uses: 'actions/cache@v4'
|
||||
with:
|
||||
path: '.eslintcache'
|
||||
key: "${{ runner.os }}-eslint-${{ hashFiles('package-lock.json', 'eslint.config.js') }}"
|
||||
|
||||
- name: 'Validate NOTICES.txt'
|
||||
run: 'git diff --exit-code packages/vscode-ide-companion/NOTICES.txt'
|
||||
|
||||
@@ -102,6 +117,7 @@ jobs:
|
||||
link_checker:
|
||||
name: 'Link Checker'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
@@ -111,12 +127,11 @@ jobs:
|
||||
args: '--verbose --accept 200,503 ./**/*.md'
|
||||
fail: true
|
||||
test_linux:
|
||||
name: 'Test (Linux)'
|
||||
name: 'Test (Linux) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
@@ -127,6 +142,9 @@ jobs:
|
||||
- '20.x'
|
||||
- '22.x'
|
||||
- '24.x'
|
||||
shard:
|
||||
- 'cli'
|
||||
- 'others'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
@@ -146,7 +164,14 @@ jobs:
|
||||
- name: 'Run tests and generate reports'
|
||||
env:
|
||||
NO_COLOR: true
|
||||
run: 'npm run test:ci'
|
||||
run: |
|
||||
if [[ "${{ matrix.shard }}" == "cli" ]]; then
|
||||
npm run test:ci --workspace @google/gemini-cli
|
||||
else
|
||||
# Explicitly list non-cli packages to ensure they are sharded correctly
|
||||
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
|
||||
npm run test:scripts
|
||||
fi
|
||||
|
||||
- name: 'Bundle'
|
||||
run: 'npm run bundle'
|
||||
@@ -154,6 +179,19 @@ jobs:
|
||||
- name: 'Smoke test bundle'
|
||||
run: 'node ./bundle/gemini.js --version'
|
||||
|
||||
- name: 'Smoke test npx installation'
|
||||
run: |
|
||||
# 1. Package the project into a tarball
|
||||
TARBALL=$(npm pack | tail -n 1)
|
||||
|
||||
# 2. Move to a fresh directory for isolation
|
||||
mkdir -p ../smoke-test-dir
|
||||
mv "$TARBALL" ../smoke-test-dir/
|
||||
cd ../smoke-test-dir
|
||||
|
||||
# 3. Run npx from the tarball
|
||||
npx "./$TARBALL" --version
|
||||
|
||||
- name: 'Wait for file system sync'
|
||||
run: 'sleep 2'
|
||||
|
||||
@@ -162,7 +200,7 @@ jobs:
|
||||
${{ always() && (github.event.pull_request.head.repo.full_name == github.repository) }}
|
||||
uses: 'dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3' # ratchet:dorny/test-reporter@v2
|
||||
with:
|
||||
name: 'Test Results (Node ${{ matrix.node-version }})'
|
||||
name: 'Test Results (Node ${{ runner.os }}, ${{ matrix.node-version }}, ${{ matrix.shard }})'
|
||||
path: 'packages/*/junit.xml'
|
||||
reporter: 'java-junit'
|
||||
fail-on-error: 'false'
|
||||
@@ -172,16 +210,15 @@ jobs:
|
||||
${{ always() && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'test-results-fork-${{ matrix.node-version }}-${{ runner.os }}'
|
||||
name: 'test-results-fork-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
|
||||
path: 'packages/*/junit.xml'
|
||||
|
||||
test_mac:
|
||||
name: 'Test (Mac)'
|
||||
runs-on: '${{ matrix.os }}'
|
||||
name: 'Test (Mac) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
|
||||
runs-on: 'macos-latest'
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
@@ -189,12 +226,13 @@ jobs:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- 'macos-latest'
|
||||
node-version:
|
||||
- '20.x'
|
||||
- '22.x'
|
||||
- '24.x'
|
||||
shard:
|
||||
- 'cli'
|
||||
- 'others'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
@@ -214,7 +252,14 @@ jobs:
|
||||
- name: 'Run tests and generate reports'
|
||||
env:
|
||||
NO_COLOR: true
|
||||
run: 'npm run test:ci -- --coverage.enabled=false'
|
||||
run: |
|
||||
if [[ "${{ matrix.shard }}" == "cli" ]]; then
|
||||
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
|
||||
else
|
||||
# Explicitly list non-cli packages to ensure they are sharded correctly
|
||||
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
|
||||
npm run test:scripts
|
||||
fi
|
||||
|
||||
- name: 'Bundle'
|
||||
run: 'npm run bundle'
|
||||
@@ -222,6 +267,19 @@ jobs:
|
||||
- name: 'Smoke test bundle'
|
||||
run: 'node ./bundle/gemini.js --version'
|
||||
|
||||
- name: 'Smoke test npx installation'
|
||||
run: |
|
||||
# 1. Package the project into a tarball
|
||||
TARBALL=$(npm pack | tail -n 1)
|
||||
|
||||
# 2. Move to a fresh directory for isolation
|
||||
mkdir -p ../smoke-test-dir
|
||||
mv "$TARBALL" ../smoke-test-dir/
|
||||
cd ../smoke-test-dir
|
||||
|
||||
# 3. Run npx from the tarball
|
||||
npx "./$TARBALL" --version
|
||||
|
||||
- name: 'Wait for file system sync'
|
||||
run: 'sleep 2'
|
||||
|
||||
@@ -230,7 +288,7 @@ jobs:
|
||||
${{ always() && (github.event.pull_request.head.repo.full_name == github.repository) }}
|
||||
uses: 'dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3' # ratchet:dorny/test-reporter@v2
|
||||
with:
|
||||
name: 'Test Results (Node ${{ matrix.node-version }})'
|
||||
name: 'Test Results (Node ${{ runner.os }}, ${{ matrix.node-version }}, ${{ matrix.shard }})'
|
||||
path: 'packages/*/junit.xml'
|
||||
reporter: 'java-junit'
|
||||
fail-on-error: 'false'
|
||||
@@ -240,7 +298,7 @@ jobs:
|
||||
${{ always() && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'test-results-fork-${{ matrix.node-version }}-${{ runner.os }}'
|
||||
name: 'test-results-fork-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
|
||||
path: 'packages/*/junit.xml'
|
||||
|
||||
- name: 'Upload coverage reports'
|
||||
@@ -248,14 +306,14 @@ jobs:
|
||||
${{ always() }}
|
||||
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'coverage-reports-${{ matrix.node-version }}-${{ matrix.os }}'
|
||||
name: 'coverage-reports-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
|
||||
path: 'packages/*/coverage'
|
||||
|
||||
codeql:
|
||||
name: 'CodeQL'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
permissions:
|
||||
actions: 'read'
|
||||
contents: 'read'
|
||||
@@ -278,7 +336,7 @@ jobs:
|
||||
bundle_size:
|
||||
name: 'Check Bundle Size'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{github.event_name == 'pull_request' && needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && github.event_name == 'pull_request' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions:
|
||||
contents: 'read' # For checkout
|
||||
@@ -300,11 +358,16 @@ jobs:
|
||||
clean-script: 'clean'
|
||||
|
||||
test_windows:
|
||||
name: 'Slow Test - Win'
|
||||
name: 'Slow Test - Win - ${{ matrix.shard }}'
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
needs: 'merge_queue_skipper'
|
||||
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
|
||||
continue-on-error: true
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
shard:
|
||||
- 'cli'
|
||||
- 'others'
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
@@ -355,7 +418,14 @@ jobs:
|
||||
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
|
||||
UV_THREADPOOL_SIZE: '32'
|
||||
NODE_ENV: 'test'
|
||||
run: 'npm run test:ci -- --coverage.enabled=false'
|
||||
run: |
|
||||
if ("${{ matrix.shard }}" -eq "cli") {
|
||||
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
|
||||
} else {
|
||||
# Explicitly list non-cli packages to ensure they are sharded correctly
|
||||
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
|
||||
npm run test:scripts
|
||||
}
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Bundle'
|
||||
@@ -366,27 +436,52 @@ jobs:
|
||||
run: 'node ./bundle/gemini.js --version'
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Smoke test npx installation'
|
||||
run: |
|
||||
# 1. Package the project into a tarball
|
||||
$PACK_OUTPUT = npm pack
|
||||
$TARBALL = $PACK_OUTPUT[-1]
|
||||
|
||||
# 2. Move to a fresh directory for isolation
|
||||
New-Item -ItemType Directory -Force -Path ../smoke-test-dir
|
||||
Move-Item $TARBALL ../smoke-test-dir/
|
||||
Set-Location ../smoke-test-dir
|
||||
|
||||
# 3. Run npx from the tarball
|
||||
npx "./$TARBALL" --version
|
||||
shell: 'pwsh'
|
||||
|
||||
ci:
|
||||
name: 'CI'
|
||||
if: 'always()'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
needs:
|
||||
- 'lint'
|
||||
- 'link_checker'
|
||||
- 'test_linux'
|
||||
- 'test_mac'
|
||||
- 'test_windows'
|
||||
- 'codeql'
|
||||
- 'bundle_size'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Check all job results'
|
||||
run: |
|
||||
if [[ (${{ needs.lint.result }} != 'success' && ${{ needs.lint.result }} != 'skipped') || \
|
||||
(${{ needs.link_checker.result }} != 'success' && ${{ needs.link_checker.result }} != 'skipped') || \
|
||||
(${{ needs.test_linux.result }} != 'success' && ${{ needs.test_linux.result }} != 'skipped') || \
|
||||
(${{ needs.test_mac.result }} != 'success' && ${{ needs.test_mac.result }} != 'skipped') || \
|
||||
(${{ needs.codeql.result }} != 'success' && ${{ needs.codeql.result }} != 'skipped') || \
|
||||
(${{ needs.bundle_size.result }} != 'success' && ${{ needs.bundle_size.result }} != 'skipped') ]]; then
|
||||
if [[ (${NEEDS_LINT_RESULT} != 'success' && ${NEEDS_LINT_RESULT} != 'skipped') || \
|
||||
(${NEEDS_LINK_CHECKER_RESULT} != 'success' && ${NEEDS_LINK_CHECKER_RESULT} != 'skipped') || \
|
||||
(${NEEDS_TEST_LINUX_RESULT} != 'success' && ${NEEDS_TEST_LINUX_RESULT} != 'skipped') || \
|
||||
(${NEEDS_TEST_MAC_RESULT} != 'success' && ${NEEDS_TEST_MAC_RESULT} != 'skipped') || \
|
||||
(${NEEDS_TEST_WINDOWS_RESULT} != 'success' && ${NEEDS_TEST_WINDOWS_RESULT} != 'skipped') || \
|
||||
(${NEEDS_CODEQL_RESULT} != 'success' && ${NEEDS_CODEQL_RESULT} != 'skipped') || \
|
||||
(${NEEDS_BUNDLE_SIZE_RESULT} != 'success' && ${NEEDS_BUNDLE_SIZE_RESULT} != 'skipped') ]]; then
|
||||
echo "One or more CI jobs failed."
|
||||
exit 1
|
||||
fi
|
||||
echo "All CI jobs passed!"
|
||||
env:
|
||||
NEEDS_LINT_RESULT: '${{ needs.lint.result }}'
|
||||
NEEDS_LINK_CHECKER_RESULT: '${{ needs.link_checker.result }}'
|
||||
NEEDS_TEST_LINUX_RESULT: '${{ needs.test_linux.result }}'
|
||||
NEEDS_TEST_MAC_RESULT: '${{ needs.test_mac.result }}'
|
||||
NEEDS_TEST_WINDOWS_RESULT: '${{ needs.test_windows.result }}'
|
||||
NEEDS_CODEQL_RESULT: '${{ needs.codeql.result }}'
|
||||
NEEDS_BUNDLE_SIZE_RESULT: '${{ needs.bundle_size.result }}'
|
||||
|
||||
@@ -27,6 +27,7 @@ jobs:
|
||||
deflake_e2e_linux:
|
||||
name: 'E2E Test (Linux) - ${{ matrix.sandbox }}'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -68,15 +69,16 @@ jobs:
|
||||
VERBOSE: 'true'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
if [[ "${{ env.IS_DOCKER }}" == "true" ]]; then
|
||||
npm run deflake:test:integration:sandbox:docker -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
if [[ "${IS_DOCKER}" == "true" ]]; then
|
||||
npm run deflake:test:integration:sandbox:docker -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'"
|
||||
else
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'"
|
||||
fi
|
||||
|
||||
deflake_e2e_mac:
|
||||
name: 'E2E Test (macOS)'
|
||||
runs-on: 'macos-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -109,12 +111,12 @@ jobs:
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
VERBOSE: 'true'
|
||||
run: |
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${RUNS}" -- --testNamePattern "'${TEST_NAME_PATTERN}'"
|
||||
|
||||
deflake_e2e_windows:
|
||||
name: 'Slow E2E - Win'
|
||||
runs-on: 'gemini-cli-windows-16-core'
|
||||
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
@@ -167,4 +169,4 @@ jobs:
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
shell: 'pwsh'
|
||||
run: |
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="${{ env.RUNS }}" -- --testNamePattern "'${{ env.TEST_NAME_PATTERN }}'"
|
||||
npm run deflake:test:integration:sandbox:none -- --runs="$env:RUNS" -- --testNamePattern "'$env:TEST_NAME_PATTERN'"
|
||||
|
||||
@@ -19,8 +19,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: |-
|
||||
${{ !contains(github.ref_name, 'nightly') }}
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && !contains(github.ref_name, 'nightly')"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
@@ -39,6 +38,7 @@ jobs:
|
||||
uses: 'actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa' # ratchet:actions/upload-pages-artifact@v3
|
||||
|
||||
deploy:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
environment:
|
||||
name: 'github-pages'
|
||||
url: '${{ steps.deployment.outputs.page_url }}'
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
- 'docs/**'
|
||||
jobs:
|
||||
trigger-rebuild:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Trigger rebuild'
|
||||
|
||||
@@ -44,5 +44,5 @@ jobs:
|
||||
- name: 'Run evaluation'
|
||||
working-directory: '/app'
|
||||
run: |
|
||||
poetry run exp_run --experiment-mode=on-demand --branch-or-commit=${{ github.ref_name }} --model-name=gemini-2.5-pro --dataset=swebench_verified --concurrency=15
|
||||
poetry run exp_run --experiment-mode=on-demand --branch-or-commit="${GITHUB_REF_NAME}" --model-name=gemini-2.5-pro --dataset=swebench_verified --concurrency=15
|
||||
poetry run python agent_prototypes/scripts/parse_gcli_logs_experiment.py --experiment_dir=experiments/adhoc/gcli_temp_exp --gcs-bucket="${EVAL_GCS_BUCKET}" --gcs-path=gh_action_artifacts
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
name: 'Evals: Nightly'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 1 * * *' # Runs at 1 AM every day
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_all:
|
||||
description: 'Run all evaluations (including usually passing)'
|
||||
type: 'boolean'
|
||||
default: true
|
||||
test_name_pattern:
|
||||
description: 'Test name pattern or file name'
|
||||
required: false
|
||||
type: 'string'
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
actions: 'read'
|
||||
|
||||
jobs:
|
||||
evals:
|
||||
name: 'Evals (USUALLY_PASSING) nightly run'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
model:
|
||||
- 'gemini-3.1-pro-preview-customtools'
|
||||
- 'gemini-3-pro-preview'
|
||||
- 'gemini-3-flash-preview'
|
||||
- 'gemini-2.5-pro'
|
||||
- 'gemini-2.5-flash'
|
||||
- 'gemini-2.5-flash-lite'
|
||||
run_attempt: [1, 2, 3]
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Create logs directory'
|
||||
run: 'mkdir -p evals/logs'
|
||||
|
||||
- name: 'Run Evals'
|
||||
continue-on-error: true
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_MODEL: '${{ matrix.model }}'
|
||||
RUN_EVALS: "${{ github.event.inputs.run_all != 'false' }}"
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
run: |
|
||||
CMD="npm run test:all_evals"
|
||||
PATTERN="${TEST_NAME_PATTERN}"
|
||||
|
||||
if [[ -n "$PATTERN" ]]; then
|
||||
if [[ "$PATTERN" == *.ts || "$PATTERN" == *.js || "$PATTERN" == */* ]]; then
|
||||
$CMD -- "$PATTERN"
|
||||
else
|
||||
$CMD -- -t "$PATTERN"
|
||||
fi
|
||||
else
|
||||
$CMD
|
||||
fi
|
||||
|
||||
- name: 'Upload Logs'
|
||||
if: 'always()'
|
||||
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'eval-logs-${{ matrix.model }}-${{ matrix.run_attempt }}'
|
||||
path: 'evals/logs'
|
||||
retention-days: 7
|
||||
|
||||
aggregate-results:
|
||||
name: 'Aggregate Results'
|
||||
needs: ['evals']
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && always()"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
|
||||
- name: 'Download Logs'
|
||||
uses: 'actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806' # ratchet:actions/download-artifact@v4
|
||||
with:
|
||||
path: 'artifacts'
|
||||
|
||||
- name: 'Generate Summary'
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: 'node scripts/aggregate_evals.js artifacts >> "$GITHUB_STEP_SUMMARY"'
|
||||
@@ -101,7 +101,6 @@ jobs:
|
||||
"FIRESTORE_DATABASE_ID": "(default)",
|
||||
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
|
||||
},
|
||||
"enabled": true,
|
||||
"timeout": 600000
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,9 +14,15 @@ on:
|
||||
description: 'issue number to triage'
|
||||
required: true
|
||||
type: 'number'
|
||||
workflow_call:
|
||||
inputs:
|
||||
issue_number:
|
||||
description: 'issue number to triage'
|
||||
required: false
|
||||
type: 'string'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.event.issue.number || github.event.inputs.issue_number }}'
|
||||
group: '${{ github.workflow }}-${{ github.event.issue.number || github.event.inputs.issue_number || inputs.issue_number }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
@@ -34,12 +40,11 @@ permissions:
|
||||
jobs:
|
||||
triage-issue:
|
||||
if: |-
|
||||
github.repository == 'google-gemini/gemini-cli' &&
|
||||
(github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli') &&
|
||||
(
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(
|
||||
(github.event_name == 'issues' || github.event_name == 'issue_comment') &&
|
||||
contains(github.event.issue.labels.*.name, 'status/need-triage') &&
|
||||
(github.event_name != 'issue_comment' || (
|
||||
contains(github.event.comment.body, '@gemini-cli /triage') &&
|
||||
(github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR')
|
||||
@@ -58,10 +63,11 @@ jobs:
|
||||
with:
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
script: |
|
||||
const issueNumber = ${{ github.event.inputs.issue_number || inputs.issue_number }};
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: ${{ github.event.inputs.issue_number }},
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
core.setOutput('title', issue.title);
|
||||
core.setOutput('body', issue.body);
|
||||
@@ -72,14 +78,9 @@ jobs:
|
||||
if: |-
|
||||
github.event_name == 'workflow_dispatch'
|
||||
env:
|
||||
ISSUE_NUMBER_INPUT: '${{ github.event.inputs.issue_number }}'
|
||||
ISSUE_NUMBER_INPUT: '${{ github.event.inputs.issue_number || inputs.issue_number }}'
|
||||
LABELS: '${{ steps.get_issue_data.outputs.labels }}'
|
||||
run: |
|
||||
if ! echo "${LABELS}" | grep -q 'status/need-triage'; then
|
||||
echo "Issue #${ISSUE_NUMBER_INPUT} does not have the 'status/need-triage' label. Stopping workflow."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if echo "${LABELS}" | grep -q 'area/'; then
|
||||
echo "Issue #${ISSUE_NUMBER_INPUT} already has 'area/' label. Stopping workflow."
|
||||
exit 1
|
||||
@@ -92,6 +93,10 @@ jobs:
|
||||
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
env:
|
||||
APP_ID: '${{ secrets.APP_ID }}'
|
||||
if: |-
|
||||
${{ env.APP_ID != '' }}
|
||||
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
@@ -102,7 +107,7 @@ jobs:
|
||||
id: 'get_labels'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
||||
script: |-
|
||||
const { data: labels } = await github.rest.issues.listLabelsForRepo({
|
||||
owner: context.repo.owner,
|
||||
@@ -116,6 +121,7 @@ jobs:
|
||||
'area/security',
|
||||
'area/platform',
|
||||
'area/extensions',
|
||||
'area/documentation',
|
||||
'area/unknown'
|
||||
];
|
||||
const labelNames = labels.map(label => label.name).filter(name => allowedLabels.includes(name));
|
||||
@@ -133,7 +139,7 @@ jobs:
|
||||
ISSUE_BODY: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.body || github.event.issue.body }}
|
||||
ISSUE_NUMBER: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && github.event.inputs.issue_number || github.event.issue.number }}
|
||||
${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.issue_number || inputs.issue_number) || github.event.issue.number }}
|
||||
REPOSITORY: '${{ github.repository }}'
|
||||
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
|
||||
with:
|
||||
@@ -150,7 +156,10 @@ jobs:
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
"target": "gcp"
|
||||
}
|
||||
},
|
||||
"coreTools": [
|
||||
"run_shell_command(echo)"
|
||||
]
|
||||
}
|
||||
prompt: |-
|
||||
## Role
|
||||
@@ -247,6 +256,14 @@ jobs:
|
||||
"Issues with a specific extension."
|
||||
"Feature request for the extension ecosystem."
|
||||
|
||||
area/documentation
|
||||
- Description: Issues related to user-facing documentation and other content on the documentation website.
|
||||
- Example Issues:
|
||||
"A typo in a README file."
|
||||
"DOCS: A command is not working as described in the documentation."
|
||||
"A request for a new documentation page."
|
||||
"Instructions missing for skills feature"
|
||||
|
||||
area/unknown
|
||||
- Description: Issues that do not clearly fit into any other defined area/ category, or where information is too limited to make a determination. Use this when no other area is appropriate.
|
||||
|
||||
@@ -259,7 +276,7 @@ jobs:
|
||||
LABELS_OUTPUT: '${{ steps.gemini_issue_analysis.outputs.summary }}'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
||||
script: |
|
||||
const rawOutput = process.env.LABELS_OUTPUT;
|
||||
core.info(`Raw output from model: ${rawOutput}`);
|
||||
@@ -279,8 +296,21 @@ jobs:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
core.setFailed(`Output is not valid JSON and does not contain a JSON markdown block.\nRaw output: ${rawOutput}`);
|
||||
return;
|
||||
// If no markdown block, try to find a raw JSON object in the output.
|
||||
// The CLI may include debug/log lines (e.g. telemetry init, YOLO mode)
|
||||
// before the actual JSON response.
|
||||
const jsonObjectMatch = rawOutput.match(/(\{[\s\S]*"labels_to_set"[\s\S]*\})/);
|
||||
if (jsonObjectMatch) {
|
||||
try {
|
||||
parsedLabels = JSON.parse(jsonObjectMatch[0]);
|
||||
} catch (extractError) {
|
||||
core.setFailed(`Found JSON-like content but failed to parse: ${extractError.message}\nRaw output: ${rawOutput}`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
core.setFailed(`Output is not valid JSON and does not contain extractable JSON.\nRaw output: ${rawOutput}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,22 +331,6 @@ jobs:
|
||||
});
|
||||
core.info(`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}`);
|
||||
|
||||
// Remove the 'status/need-triage' label
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
name: 'status/need-triage'
|
||||
});
|
||||
core.info(`Successfully removed 'status/need-triage' label.`);
|
||||
} catch (error) {
|
||||
// If the label doesn't exist, the API call will throw a 404. We can ignore this.
|
||||
if (error.status !== 404) {
|
||||
core.warning(`Failed to remove 'status/need-triage': ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
- name: 'Post Issue Analysis Failure Comment'
|
||||
if: |-
|
||||
${{ failure() && steps.gemini_issue_analysis.outcome == 'failure' }}
|
||||
@@ -325,7 +339,7 @@ jobs:
|
||||
RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
||||
script: |-
|
||||
github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
name: 'Gemini Automated PR Labeler'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: ['opened', 'reopened', 'synchronize']
|
||||
|
||||
jobs:
|
||||
label-pr:
|
||||
timeout-minutes: 10
|
||||
if: |-
|
||||
${{ github.repository == 'google-gemini/gemini-cli' }}
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
contents: 'read'
|
||||
id-token: 'write'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.event.pull_request.number }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
uses: 'actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e' # v2
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
permission-pull-requests: 'write'
|
||||
|
||||
- name: 'Run Gemini PR size and complexity labeller'
|
||||
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # Use the specific commit SHA
|
||||
env:
|
||||
GH_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
||||
PR_NUMBER: '${{ github.event.pull_request.number }}'
|
||||
REPOSITORY: '${{ github.repository }}'
|
||||
with:
|
||||
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
|
||||
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
|
||||
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
|
||||
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
|
||||
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
|
||||
settings: |
|
||||
{
|
||||
"coreTools": [
|
||||
"run_shell_command(gh pr diff)",
|
||||
"run_shell_command(gh pr edit)",
|
||||
"run_shell_command(gh pr comment)",
|
||||
"run_shell_command(gh pr view)"
|
||||
],
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
"target": "gcp"
|
||||
},
|
||||
"sandbox": false
|
||||
}
|
||||
prompt: |
|
||||
You are a Pull Request labeller and Feedback Assistant. Your primary goal is to improve review velocity and help maintainers prioritize their work by automatically labeling pull requests based on size and complexity, and providing guidance for overly large PRs.
|
||||
|
||||
Steps:
|
||||
1. Retrieve Pull Request Information:
|
||||
- Use `gh pr diff ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }}` to get the diff content.
|
||||
- Parse the output from `gh pr diff` to determine the total lines of code added and deleted. Calculate `TOTAL_LINES_CHANGED`.
|
||||
|
||||
2. Determine Pull Request Size:
|
||||
- Use `gh pr view ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }} --json labels` to get the current labels on the PR.
|
||||
- Check the current labels and identify if any `size/*` labels already exist (e.g., `size/xs`, `size/s`, etc.).
|
||||
- If an old `size/*` label is found and it is different from the newly calculated size, remove it using:
|
||||
`gh pr edit ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }} --remove-label "size-label-to-remove"`
|
||||
- Based on `TOTAL_LINES_CHANGED`, select the appropriate new size label:
|
||||
- `size/xs`: < 10 lines changed
|
||||
- `size/s`: 10-50 lines changed
|
||||
- `size/m`: 51-200 lines changed
|
||||
- `size/l`: 201-1000 lines changed
|
||||
- `size/xl`: > 1000 lines changed
|
||||
- Do not invent new size labels.
|
||||
- Apply the newly determined `size/*` label to the pull request using:
|
||||
`gh pr edit ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }} --add-label "your-new-size-label"`
|
||||
|
||||
3. Analyze Pull Request Complexity:
|
||||
- Perform Code Change Analysis: Examine the content of the code changes obtained from `gh pr diff ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }}`. Look for indicators of complexity such as:
|
||||
- Number of files changed (can be inferred from the diff headers).
|
||||
- Diversity of file types (e.g., changes across different languages, configuration files, documentation).
|
||||
- Presence of new external dependencies.
|
||||
- Introduction of new architectural components or significant refactoring.
|
||||
- Complexity of individual code changes (e.g., deeply nested logic, complex algorithms, extensive conditional statements).
|
||||
- Apply Heuristic-based Complexity Assessment:
|
||||
- If the PR touches a small number of files with minor changes (e.g., typos, simple bug fixes, small feature additions), categorize it as `review/quick`.
|
||||
- If the PR involves changes across multiple files, introduces new features, significantly refactors existing code, or has a high line count (even within `size/l`), categorize it as `review/involved`.
|
||||
- Pay close attention to changes in critical or core modules as these inherently increase complexity.
|
||||
- **Only use the labels `review/quick` or `review/involved` for complexity. Do not invent new complexity labels.**
|
||||
- **Remove any previous `review/*` labels if they no longer apply, similar to the size label process.**
|
||||
- Apply the determined `review/*` label to the pull request using:
|
||||
`gh pr edit ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }} --add-label "your-complexity-label"`
|
||||
|
||||
4. Handle Overly Large Pull Requests (`size/xl`):
|
||||
- **Conditional Check:** If the pull request has been labeled `size/xl` (i.e., > 1000 lines of code changed) in Step 2, proceed to the next sub-step.
|
||||
- **Post Constructive Comment:** Post a polite and helpful comment on the pull request using:
|
||||
`gh pr comment ${{ env.PR_NUMBER }} --repo ${{ env.REPOSITORY }} --body "Your comment here"`
|
||||
The comment body should be:
|
||||
"""
|
||||
Thanks for your hard work on this pull request!
|
||||
|
||||
This pull request is quite large, which can make it challenging and time-consuming for reviewers to go through thoroughly.
|
||||
|
||||
To help us review it more efficiently and get your changes merged faster, we kindly request you consider breaking this into smaller, more focused pull requests. Each smaller PR should ideally address a single logical change or a small set of related changes.
|
||||
|
||||
For example, you could separate out refactoring, new feature additions, and bug fixes into individual PRs. This makes it easier to understand, review, and test each component independently.
|
||||
|
||||
We appreciate your understanding and cooperation. Feel free to reach out if you need any assistance with this!
|
||||
"""
|
||||
|
||||
Guidelines:
|
||||
- Automation Focus: All actions should be automated and not require manual intervention.
|
||||
- Non-intrusive: The system should add labels and comments but not modify the code or close the pull request.
|
||||
- Polite and Constructive: All communication, especially for large PRs, must be polite, encouraging, and constructive.
|
||||
- Prioritize Clarity: The labels applied should clearly convey the PR's size and complexity to reviewers.
|
||||
- Adhere to Defined Labels: Only use the specified `size/*` and `review/*` labels. Do not create or apply any other labels.
|
||||
- Utilize `gh CLI`: Interact with GitHub using the `gh` command-line tool for diffing, label management, and commenting.
|
||||
- Execute commands strictly as described in the steps. Do not invent new commands.
|
||||
- In no case should you change other pull request that are not the one you are working on. Which can be found by using env.PR_NUMBER
|
||||
- Execute each step that is defined in the steps section.
|
||||
- In no case should you execute code from the pull request because this could be malicious code.
|
||||
- If you fail to do this step log the errors you received
|
||||
@@ -81,7 +81,6 @@ jobs:
|
||||
"FIRESTORE_DATABASE_ID": "(default)",
|
||||
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
|
||||
},
|
||||
"enabled": true,
|
||||
"timeout": 600000
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
name: '📋 Gemini Scheduled Issue Triage'
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
schedule:
|
||||
- cron: '0 * * * *' # Runs every hour
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}'
|
||||
group: '${{ github.workflow }}-${{ github.event.number || github.run_id }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
@@ -35,7 +39,21 @@ jobs:
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
permission-issues: 'write'
|
||||
|
||||
- name: 'Get issue from event'
|
||||
if: |-
|
||||
${{ github.event_name == 'issues' }}
|
||||
id: 'get_issue_from_event'
|
||||
env:
|
||||
ISSUE_EVENT: '${{ toJSON(github.event.issue) }}'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ISSUE_JSON=$(echo "$ISSUE_EVENT" | jq -c '[{number: .number, title: .title, body: .body}]')
|
||||
echo "issues_to_triage=${ISSUE_JSON}" >> "${GITHUB_OUTPUT}"
|
||||
echo "✅ Found issue #${{ github.event.issue.number }} from event to triage! 🎯"
|
||||
|
||||
- name: 'Find untriaged issues'
|
||||
if: |-
|
||||
${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
|
||||
id: 'find_issues'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
||||
@@ -43,22 +61,26 @@ jobs:
|
||||
run: |-
|
||||
set -euo pipefail
|
||||
|
||||
echo '🔍 Finding issues without labels...'
|
||||
NO_LABEL_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue no:label' --json number,title,body)"
|
||||
echo '🔍 Finding issues missing area labels...'
|
||||
NO_AREA_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 100 --json number,title,body)"
|
||||
|
||||
echo '🏷️ Finding issues that need triage...'
|
||||
NEED_TRIAGE_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search "is:open is:issue label:\"status/need-triage\"" --limit 1000 --json number,title,body)"
|
||||
echo '🔍 Finding issues missing kind labels...'
|
||||
NO_KIND_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 100 --json number,title,body)"
|
||||
|
||||
echo '🏷️ Finding issues missing priority labels...'
|
||||
NO_PRIORITY_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 100 --json number,title,body)"
|
||||
|
||||
echo '🔄 Merging and deduplicating issues...'
|
||||
ISSUES="$(echo "${NO_LABEL_ISSUES}" "${NEED_TRIAGE_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
|
||||
ISSUES="$(echo "${NO_AREA_ISSUES}" "${NO_KIND_ISSUES}" "${NO_PRIORITY_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
|
||||
|
||||
echo '📝 Setting output for GitHub Actions...'
|
||||
echo "issues_to_triage=${ISSUES}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
ISSUE_COUNT="$(echo "${ISSUES}" | jq 'length')"
|
||||
echo "✅ Found ${ISSUE_COUNT} issues to triage! 🎯"
|
||||
echo "✅ Found ${ISSUE_COUNT} unique issues to triage! 🎯"
|
||||
|
||||
- name: 'Get Repository Labels'
|
||||
id: 'get_labels'
|
||||
@@ -77,12 +99,13 @@ jobs:
|
||||
|
||||
- name: 'Run Gemini Issue Analysis'
|
||||
if: |-
|
||||
${{ steps.find_issues.outputs.issues_to_triage != '[]' }}
|
||||
(steps.get_issue_from_event.outputs.issues_to_triage != '' && steps.get_issue_from_event.outputs.issues_to_triage != '[]') ||
|
||||
(steps.find_issues.outputs.issues_to_triage != '' && steps.find_issues.outputs.issues_to_triage != '[]')
|
||||
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0
|
||||
id: 'gemini_issue_analysis'
|
||||
env:
|
||||
GITHUB_TOKEN: '' # Do not pass any auth token here since this runs on untrusted inputs
|
||||
ISSUES_TO_TRIAGE: '${{ steps.find_issues.outputs.issues_to_triage }}'
|
||||
ISSUES_TO_TRIAGE: '${{ steps.get_issue_from_event.outputs.issues_to_triage || steps.find_issues.outputs.issues_to_triage }}'
|
||||
REPOSITORY: '${{ github.repository }}'
|
||||
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
|
||||
with:
|
||||
@@ -116,38 +139,32 @@ jobs:
|
||||
1. You are only able to use the echo command. Review the available labels in the environment variable: "${AVAILABLE_LABELS}".
|
||||
2. Check environment variable for issues to triage: $ISSUES_TO_TRIAGE (JSON array of issues)
|
||||
3. Review the issue title, body and any comments provided in the environment variables.
|
||||
4. Identify the most relevant labels from the existing labels, focusing on kind/*, area/*, sub-area/* and priority/*.
|
||||
5. If the issue already has area/ label, dont try to change it. Similarly, if the issue already has a kind/ label don't change it. And if the issue already has a priority/ label do not change it for example:
|
||||
If an issue has area/core and kind/bug you will only add a priority/ label.
|
||||
Instead if an issue has no labels, you will could add one lable of each kind.
|
||||
4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/* and priority/*.
|
||||
5. Label Policy:
|
||||
- If the issue already has a kind/ label, do not change it.
|
||||
- If the issue already has a priority/ label, do not change it.
|
||||
- If the issue already has an area/ label, do not change it.
|
||||
- If any of these are missing, select exactly ONE appropriate label for the missing category.
|
||||
6. Identify other applicable labels based on the issue content, such as status/*, help wanted, good first issue, etc.
|
||||
7. For area/* and kind/* limit yourself to only the single most applicable label in each case.
|
||||
8. Give me a single short explanation about why you are selecting each label in the process.
|
||||
9. Output a JSON array of objects, each containing the issue number
|
||||
7. Give me a single short explanation about why you are selecting each label in the process.
|
||||
8. Output a JSON array of objects, each containing the issue number
|
||||
and the labels to add and remove, along with an explanation. For example:
|
||||
```
|
||||
[
|
||||
{
|
||||
"issue_number": 123,
|
||||
"labels_to_add": ["kind/bug", "priority/p2"],
|
||||
"labels_to_add": ["area/core", "kind/bug", "priority/p2"],
|
||||
"labels_to_remove": ["status/need-triage"],
|
||||
"explanation": "This issue is a bug that needs to be addressed with medium priority."
|
||||
},
|
||||
{
|
||||
"issue_number": 456,
|
||||
"labels_to_add": ["kind/enhancement"],
|
||||
"labels_to_remove": [],
|
||||
"explanation": "This issue is an enhancement request that could improve the user experience."
|
||||
"explanation": "This issue is a UI bug that needs to be addressed with medium priority."
|
||||
}
|
||||
]
|
||||
```
|
||||
If an issue cannot be classified, do not include it in the output array.
|
||||
10. For each issue please check if CLI version is present, this is usually in the output of the /about command and will look like 0.1.5
|
||||
9. For each issue please check if CLI version is present, this is usually in the output of the /about command and will look like 0.1.5
|
||||
- Anything more than 6 versions older than the most recent should add the status/need-retesting label
|
||||
11. If you see that the issue doesn't look like it has sufficient information recommend the status/need-information label and leave a comment politely requesting the relevant information, eg.. if repro steps are missing request for repro steps. if version information is missing request for version information into the explanation section below.
|
||||
- After identifying appropriate labels to an issue, add "status/need-triage" label to labels_to_remove in the output.
|
||||
12. If you think an issue might be a Priority/P0 do not apply the priority/p0 label. Instead apply a status/manual-triage label and include a note in your explanation.
|
||||
13. If you are uncertain and have not been able to apply one each of kind/, area/ and priority/ , apply the status/manual-triage label.
|
||||
10. If you see that the issue doesn't look like it has sufficient information recommend the status/need-information label and leave a comment politely requesting the relevant information, eg.. if repro steps are missing request for repro steps. if version information is missing request for version information into the explanation section below.
|
||||
11. If you think an issue might be a Priority/P0 do not apply the priority/p0 label. Instead apply a status/manual-triage label and include a note in your explanation.
|
||||
12. If you are uncertain about a category, use the area/unknown, kind/question, or priority/unknown labels as appropriate. If you are extremely uncertain, apply the status/manual-triage label.
|
||||
|
||||
## Guidelines
|
||||
|
||||
@@ -157,100 +174,47 @@ jobs:
|
||||
- Do not add comments or modify the issue content.
|
||||
- Do not remove the following labels maintainer, help wanted or good first issue.
|
||||
- Triage only the current issue.
|
||||
- Identify only one area/ label
|
||||
- Identify only one area/ label.
|
||||
- Identify only one kind/ label (Do not apply kind/duplicate or kind/parent-issue)
|
||||
- Identify all applicable sub-area/* and priority/* labels based on the issue content. It's ok to have multiple of these.
|
||||
- Identify only one priority/ label.
|
||||
- Once you categorize the issue if it needs information bump down the priority by 1 eg.. a p0 would become a p1 a p1 would become a p2. P2 and P3 can stay as is in this scenario.
|
||||
Categorization Guidelines:
|
||||
P0: Critical / Blocker
|
||||
- A P0 bug is a catastrophic failure that demands immediate attention.
|
||||
- To be a P0 it means almost all users are running into this issue and it is blocking users from being able to use the product.
|
||||
- You would see this in the form of many comments from different developers on the bug.
|
||||
- It represents a complete showstopper for a significant portion of users or for the development process itself.
|
||||
Impact:
|
||||
- Blocks development or testing for the entire team.
|
||||
- Major security vulnerability that could compromise user data or system integrity.
|
||||
- Causes data loss or corruption with no workaround.
|
||||
- Crashes the application or makes a core feature completely unusable for all or most users in a production environment. Will it cause severe quality degration?
|
||||
- Is it preventing contributors from contributing to the repository or is it a release blocker?
|
||||
Qualifier: Is the main function of the software broken?
|
||||
Example: The gemini auth login command fails with an unrecoverable error, preventing any user from authenticating and using the rest of the CLI.
|
||||
P1: High
|
||||
- A P1 bug is a serious issue that significantly degrades the user experience or impacts a core feature.
|
||||
- While not a complete blocker, it's a major problem that needs a fast resolution. Feature requests are almost never P1.
|
||||
- Once again this would be affecting many users.
|
||||
- You would see this in the form of comments from different developers on the bug.
|
||||
Impact:
|
||||
- A core feature is broken or behaving incorrectly for a large number of users or large number of use cases.
|
||||
- Review the bug details and comments to try figure out if this issue affects a large set of use cases or if it's a narrow set of use cases.
|
||||
- Severe performance degradation making the application frustratingly slow.
|
||||
- No straightforward workaround exists, or the workaround is difficult and non-obvious.
|
||||
Qualifier: Is a key feature unusable or giving very wrong results?
|
||||
Example: Gemini CLI enters a loop when making read-many-files tool call. I am unable to break out of the loop and gemini doesn't follow instructions subsequently.
|
||||
P2: Medium
|
||||
- A P2 bug is a moderately impactful issue. It's a noticeable problem but doesn't prevent the use of the software's main functionality.
|
||||
Impact:
|
||||
- Affects a non-critical feature or a smaller, specific subset of users.
|
||||
- An inconvenient but functional workaround is available and easy to execute.
|
||||
- Noticeable UI/UX problems that don't break functionality but look unprofessional (e.g., elements are misaligned or overlapping).
|
||||
Qualifier: Is it an annoying but non-blocking problem?
|
||||
Example: An error message is unclear or contains a typo, causing user confusion but not halting their workflow.
|
||||
P3: Low
|
||||
- A P3 bug is a minor, low-impact issue that is trivial or cosmetic. It has little to no effect on the overall functionality of the application.
|
||||
Impact:
|
||||
- Minor cosmetic issues like color inconsistencies, typos in documentation, or slight alignment problems on a non-critical page.
|
||||
- An edge-case bug that is very difficult to reproduce and affects a tiny fraction of users.
|
||||
Qualifier: Is it a "nice-to-fix" issue?
|
||||
Example: Spelling mistakes etc.
|
||||
|
||||
Categorization Guidelines (Priority):
|
||||
P0 - Urgent Blocking Issues:
|
||||
- DO NOT APPLY THIS LABEL AUTOMATICALLY. Use status/manual-triage instead.
|
||||
- Definition: Urgent, block a significant percentage of the user base, and prevent frequent use of the Gemini CLI.
|
||||
- This includes core stability blockers (e.g., authentication failures, broken upgrades), critical crashes, and P0 security vulnerabilities.
|
||||
- Impact: Blocks development or testing for the entire team; Major security vulnerability; Causes data loss or corruption with no workaround; Crashes the application or makes a core feature completely unusable for all or most users.
|
||||
- Qualifier: Is the main function of the software broken?
|
||||
P1 - High-Impact Issues:
|
||||
- Definition: Affect a large number of users, blocking them from using parts of the Gemini CLI, or make the CLI frequently unusable even with workarounds available.
|
||||
- Impact: A core feature is broken or behaving incorrectly for a large number of users or use cases; Severe performance degradation; No straightforward workaround exists.
|
||||
- Qualifier: Is a key feature unusable or giving very wrong results?
|
||||
P2 - Significant Issues:
|
||||
- Definition: Affect some users significantly, such as preventing the use of certain features or authentication types.
|
||||
- Can also be issues that many users complain about, causing annoyance or hindering daily use.
|
||||
- Impact: Affects a non-critical feature or a smaller, specific subset of users; An inconvenient but functional workaround is available; Noticeable UI/UX problems that look unprofessional.
|
||||
- Qualifier: Is it an annoying but non-blocking problem?
|
||||
P3 - Low-Impact Issues:
|
||||
- Definition: Typically usability issues that cause annoyance to a limited user base.
|
||||
- Includes feature requests that could be addressed in the near future and may be suitable for community contributions.
|
||||
- Impact: Minor cosmetic issues; An edge-case bug that is very difficult to reproduce and affects a tiny fraction of users.
|
||||
- Qualifier: Is it a "nice-to-fix" issue?
|
||||
|
||||
Categorization Guidelines (Area):
|
||||
area/agent: Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality
|
||||
area/core: User Interface, OS Support, Core Functionality
|
||||
area/documentation: End-user and contributor-facing documentation, website-related
|
||||
area/enterprise: Telemetry, Policy, Quota / Licensing
|
||||
area/extensions: Gemini CLI extensions capability
|
||||
area/non-interactive: GitHub Actions, SDK, 3P Integrations, Shell Scripting, Command line automation
|
||||
area/platform: Build infra, Release mgmt, Testing, Eval infra, Capacity, Quota mgmt
|
||||
area/security: security related issues
|
||||
|
||||
Additional Context:
|
||||
- If users are talking about issues where the model gets downgraded from pro to flash then i want you to categorize that as a performance issue
|
||||
- This product is designed to use different models eg.. using pro, downgrading to flash etc.
|
||||
- When users report that they dont expect the model to change those would be categorized as feature requests.
|
||||
Definition of Areas
|
||||
area/ux:
|
||||
- Issues concerning user-facing elements like command usability, interactive features, help docs, and perceived performance.
|
||||
- I am seeing my screen flicker when using Gemini CLI
|
||||
- I am seeing the output malformed
|
||||
- Theme changes aren't taking effect
|
||||
- My keyboard inputs arent' being recognzied
|
||||
area/platform:
|
||||
- Issues related to installation, packaging, OS compatibility (Windows, macOS, Linux), and the underlying CLI framework.
|
||||
area/background: Issues related to long-running background tasks, daemons, and autonomous or proactive agent features.
|
||||
area/models:
|
||||
- i am not getting a response that is reasonable or expected. this can include things like
|
||||
- I am calling a tool and the tool is not performing as expected.
|
||||
- i am expecting a tool to be called and it is not getting called ,
|
||||
- Including experience when using
|
||||
- built-in tools (e.g., web search, code interpreter, read file, writefile, etc..),
|
||||
- Function calling issues should be under this area
|
||||
- i am getting responses from the model that are malformed.
|
||||
- Issues concerning Gemini quality of response and inference,
|
||||
- Issues talking about unnecessary token consumption.
|
||||
- Issues talking about Model getting stuck in a loop be watchful as this could be the root cause for issues that otherwise seem like model performance issues.
|
||||
- Memory compression
|
||||
- unexpected responses,
|
||||
- poor quality of generated code
|
||||
area/tools:
|
||||
- These are primarily issues related to Model Context Protocol
|
||||
- These are issues that mention MCP support
|
||||
- feature requests asking for support for new tools.
|
||||
area/core:
|
||||
- Issues with fundamental components like command parsing, configuration management, session state, and the main API client logic. Introducing multi-modality
|
||||
area/contribution:
|
||||
- Issues related to improving the developer contribution experience, such as CI/CD pipelines, build scripts, and test automation infrastructure.
|
||||
area/authentication:
|
||||
- Issues related to user identity, login flows, API key handling, credential storage, and access token management, unable to sign in selecting wrong authentication path etc..
|
||||
area/security-privacy:
|
||||
- Issues concerning vulnerability patching, dependency security, data sanitization, privacy controls, and preventing unauthorized data access.
|
||||
area/extensibility:
|
||||
- Issues related to the plugin system, extension APIs, or making the CLI's functionality available in other applications, github actions, ide support etc..
|
||||
area/performance:
|
||||
- Issues focused on model performance
|
||||
- Issues with running out of capacity,
|
||||
- 429 errors etc..
|
||||
- could also pertain to latency,
|
||||
- other general software performance like, memory usage, CPU consumption, and algorithmic efficiency.
|
||||
- Switching models from one to the other unexpectedly.
|
||||
- If users are talking about issues where the model gets downgraded from pro to flash then i want you to categorize that as a performance issue.
|
||||
- This product is designed to use different models eg.. using pro, downgrading to flash etc.
|
||||
- When users report that they dont expect the model to change those would be categorized as feature requests.
|
||||
|
||||
- name: 'Apply Labels to Issues'
|
||||
if: |-
|
||||
@@ -300,24 +264,6 @@ jobs:
|
||||
core.info(`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}${explanation}`);
|
||||
}
|
||||
|
||||
if (entry.labels_to_remove && entry.labels_to_remove.length > 0) {
|
||||
for (const label of entry.labels_to_remove) {
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
name: label
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.status !== 404) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
core.info(`Successfully removed labels for #${issueNumber}: ${entry.labels_to_remove.join(', ')}`);
|
||||
}
|
||||
|
||||
if (entry.explanation) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
|
||||
@@ -39,3 +39,7 @@ jobs:
|
||||
GITHUB_REPOSITORY: '${{ github.repository }}'
|
||||
run: |-
|
||||
./.github/scripts/pr-triage.sh
|
||||
# If prs_needing_comment is empty, set it to [] explicitly for downstream steps
|
||||
if [[ -z "$(grep 'prs_needing_comment' "${GITHUB_OUTPUT}" | cut -d'=' -f2-)" ]]; then
|
||||
echo "prs_needing_comment=[]" >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
|
||||
@@ -21,13 +21,14 @@ defaults:
|
||||
|
||||
jobs:
|
||||
close-stale-issues:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
issues: 'write'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
uses: 'actions/create-github-app-token@v1'
|
||||
uses: 'actions/create-github-app-token@v2'
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
@@ -79,8 +80,14 @@ jobs:
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if it has a maintainer label
|
||||
if (issue.labels.some(label => label.name.toLowerCase().includes('maintainer'))) {
|
||||
// Skip if it has a maintainer, help wanted, or Public Roadmap label
|
||||
const rawLabels = issue.labels.map((l) => l.name);
|
||||
const lowercaseLabels = rawLabels.map((l) => l.toLowerCase());
|
||||
if (
|
||||
lowercaseLabels.some((l) => l.includes('maintainer')) ||
|
||||
lowercaseLabels.includes('help wanted') ||
|
||||
rawLabels.includes('🗓️ Public Roadmap')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
name: 'Gemini Scheduled Stale PR Closer'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # Every day at 2 AM UTC
|
||||
pull_request:
|
||||
types: ['opened', 'edited']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Run in dry-run mode'
|
||||
required: false
|
||||
default: false
|
||||
type: 'boolean'
|
||||
|
||||
jobs:
|
||||
close-stale-prs:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
issues: 'write'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
env:
|
||||
APP_ID: '${{ secrets.APP_ID }}'
|
||||
if: |-
|
||||
${{ env.APP_ID != '' }}
|
||||
uses: 'actions/create-github-app-token@v2'
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
|
||||
- name: 'Process Stale PRs'
|
||||
uses: 'actions/github-script@v7'
|
||||
env:
|
||||
DRY_RUN: '${{ inputs.dry_run }}'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
||||
script: |
|
||||
const dryRun = process.env.DRY_RUN === 'true';
|
||||
const thirtyDaysAgo = new Date();
|
||||
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
||||
|
||||
// 1. Fetch maintainers for verification
|
||||
let maintainerLogins = new Set();
|
||||
const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs'];
|
||||
|
||||
for (const team_slug of teams) {
|
||||
try {
|
||||
const members = await github.paginate(github.rest.teams.listMembersInOrg, {
|
||||
org: context.repo.owner,
|
||||
team_slug: team_slug
|
||||
});
|
||||
for (const m of members) maintainerLogins.add(m.login.toLowerCase());
|
||||
core.info(`Successfully fetched ${members.length} team members from ${team_slug}`);
|
||||
} catch (e) {
|
||||
core.warning(`Failed to fetch team members from ${team_slug}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const isGooglerCache = new Map();
|
||||
const isGoogler = async (login) => {
|
||||
if (isGooglerCache.has(login)) return isGooglerCache.get(login);
|
||||
|
||||
try {
|
||||
// Check membership in 'googlers' or 'google' orgs
|
||||
const orgs = ['googlers', 'google'];
|
||||
for (const org of orgs) {
|
||||
try {
|
||||
await github.rest.orgs.checkMembershipForUser({
|
||||
org: org,
|
||||
username: login
|
||||
});
|
||||
core.info(`User ${login} is a member of ${org} organization.`);
|
||||
isGooglerCache.set(login, true);
|
||||
return true;
|
||||
} catch (e) {
|
||||
// 404 just means they aren't a member, which is fine
|
||||
if (e.status !== 404) throw e;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
core.warning(`Failed to check org membership for ${login}: ${e.message}`);
|
||||
}
|
||||
|
||||
isGooglerCache.set(login, false);
|
||||
return false;
|
||||
};
|
||||
|
||||
const isMaintainer = async (login, assoc) => {
|
||||
const isTeamMember = maintainerLogins.has(login.toLowerCase());
|
||||
const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc);
|
||||
if (isTeamMember || isRepoMaintainer) return true;
|
||||
|
||||
return await isGoogler(login);
|
||||
};
|
||||
|
||||
// 2. Determine which PRs to check
|
||||
let prs = [];
|
||||
if (context.eventName === 'pull_request') {
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.pull_request.number
|
||||
});
|
||||
prs = [pr];
|
||||
} else {
|
||||
prs = await github.paginate(github.rest.pulls.list, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
per_page: 100
|
||||
});
|
||||
}
|
||||
|
||||
for (const pr of prs) {
|
||||
const maintainerPr = await isMaintainer(pr.user.login, pr.author_association);
|
||||
const isBot = pr.user.type === 'Bot' || pr.user.login.endsWith('[bot]');
|
||||
|
||||
// Detection Logic for Linked Issues
|
||||
// Check 1: Official GitHub "Closing Issue" link (GraphQL)
|
||||
const linkedIssueQuery = `query($owner:String!, $repo:String!, $number:Int!) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
pullRequest(number:$number) {
|
||||
closingIssuesReferences(first: 1) { totalCount }
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
let hasClosingLink = false;
|
||||
try {
|
||||
const res = await github.graphql(linkedIssueQuery, {
|
||||
owner: context.repo.owner, repo: context.repo.repo, number: pr.number
|
||||
});
|
||||
hasClosingLink = res.repository.pullRequest.closingIssuesReferences.totalCount > 0;
|
||||
} catch (e) {}
|
||||
|
||||
// Check 2: Regex for mentions (e.g., "Related to #123", "Part of #123", "#123")
|
||||
// We check for # followed by numbers or direct URLs to issues.
|
||||
const body = pr.body || '';
|
||||
const mentionRegex = /(?:#|https:\/\/github\.com\/[^\/]+\/[^\/]+\/issues\/)(\d+)/i;
|
||||
const hasMentionLink = mentionRegex.test(body);
|
||||
|
||||
const hasLinkedIssue = hasClosingLink || hasMentionLink;
|
||||
|
||||
// Logic for Closed PRs (Auto-Reopen)
|
||||
if (pr.state === 'closed' && context.eventName === 'pull_request' && context.payload.action === 'edited') {
|
||||
if (hasLinkedIssue) {
|
||||
core.info(`PR #${pr.number} now has a linked issue. Reopening.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'open'
|
||||
});
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: "Thank you for linking an issue! This pull request has been automatically reopened."
|
||||
});
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Logic for Open PRs (Immediate Closure)
|
||||
if (pr.state === 'open' && !maintainerPr && !hasLinkedIssue && !isBot) {
|
||||
core.info(`PR #${pr.number} is missing a linked issue. Closing.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: "Hi there! Thank you for your contribution to Gemini CLI. \n\nTo improve our contribution process and better track changes, we now require all pull requests to be associated with an existing issue, as announced in our [recent discussion](https://github.com/google-gemini/gemini-cli/discussions/16706) and as detailed in our [CONTRIBUTING.md](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md#1-link-to-an-existing-issue).\n\nThis pull request is being closed because it is not currently linked to an issue. **Once you have updated the description of this PR to link an issue (e.g., by adding `Fixes #123` or `Related to #123`), it will be automatically reopened.**\n\n**How to link an issue:**\nAdd a keyword followed by the issue number (e.g., `Fixes #123`) in the description of your pull request. For more details on supported keywords and how linking works, please refer to the [GitHub Documentation on linking pull requests to issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).\n\nThank you for your understanding and for being a part of our community!"
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed'
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Staleness check (Scheduled runs only)
|
||||
if (pr.state === 'open' && context.eventName !== 'pull_request') {
|
||||
const labels = pr.labels.map(l => l.name.toLowerCase());
|
||||
if (labels.includes('help wanted') || labels.includes('🔒 maintainer only')) continue;
|
||||
|
||||
// Skip PRs that were created less than 30 days ago - they cannot be stale yet
|
||||
const prCreatedAt = new Date(pr.created_at);
|
||||
if (prCreatedAt > thirtyDaysAgo) {
|
||||
const daysOld = Math.floor((Date.now() - prCreatedAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
core.info(`PR #${pr.number} was created ${daysOld} days ago. Skipping staleness check.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Initialize lastActivity to PR creation date (not epoch) as a safety baseline.
|
||||
// This ensures we never incorrectly mark a PR as stale due to failed activity lookups.
|
||||
let lastActivity = new Date(pr.created_at);
|
||||
try {
|
||||
const reviews = await github.paginate(github.rest.pulls.listReviews, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number
|
||||
});
|
||||
for (const r of reviews) {
|
||||
if (await isMaintainer(r.user.login, r.author_association)) {
|
||||
const d = new Date(r.submitted_at || r.updated_at);
|
||||
if (d > lastActivity) lastActivity = d;
|
||||
}
|
||||
}
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number
|
||||
});
|
||||
for (const c of comments) {
|
||||
if (await isMaintainer(c.user.login, c.author_association)) {
|
||||
const d = new Date(c.updated_at);
|
||||
if (d > lastActivity) lastActivity = d;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
core.warning(`Failed to fetch reviews/comments for PR #${pr.number}: ${e.message}`);
|
||||
}
|
||||
|
||||
// For maintainer PRs, the PR creation itself counts as maintainer activity.
|
||||
// (Now redundant since we initialize to pr.created_at, but kept for clarity)
|
||||
if (maintainerPr) {
|
||||
const d = new Date(pr.created_at);
|
||||
if (d > lastActivity) lastActivity = d;
|
||||
}
|
||||
|
||||
if (lastActivity < thirtyDaysAgo) {
|
||||
core.info(`PR #${pr.number} is stale.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: "Hi there! Thank you for your contribution to Gemini CLI. We really appreciate the time and effort you've put into this pull request.\n\nTo keep our backlog manageable and ensure we're focusing on current priorities, we are closing pull requests that haven't seen maintainer activity for 30 days. Currently, the team is prioritizing work associated with **🔒 maintainer only** or **help wanted** issues.\n\nIf you believe this change is still critical, please feel free to comment with updated details. Otherwise, we encourage contributors to focus on open issues labeled as **help wanted**. Thank you for your understanding!"
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
if: |-
|
||||
github.repository == 'google-gemini/gemini-cli' &&
|
||||
github.event_name == 'issue_comment' &&
|
||||
contains(github.event.comment.body, '/assign')
|
||||
(contains(github.event.comment.body, '/assign') || contains(github.event.comment.body, '/unassign'))
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
@@ -38,6 +38,7 @@ jobs:
|
||||
permission-issues: 'write'
|
||||
|
||||
- name: 'Assign issue to user'
|
||||
if: "contains(github.event.comment.body, '/assign')"
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
@@ -48,6 +49,24 @@ jobs:
|
||||
const repo = context.repo.repo;
|
||||
const MAX_ISSUES_ASSIGNED = 3;
|
||||
|
||||
const issue = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
const hasHelpWantedLabel = issue.data.labels.some(label => label.name === 'help wanted');
|
||||
|
||||
if (!hasHelpWantedLabel) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issueNumber,
|
||||
body: `👋 @${commenter}, thanks for your interest in this issue! We're reserving self-assignment for issues that have been marked with the \`help wanted\` label. Feel free to check out our list of [issues that need attention](https://github.com/google-gemini/gemini-cli/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22).`
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for open issues already assigned to the commenter in this repo
|
||||
const { data: assignedIssues } = await github.rest.search.issuesAndPullRequests({
|
||||
q: `is:issue repo:${owner}/${repo} assignee:${commenter} is:open`,
|
||||
@@ -64,13 +83,6 @@ jobs:
|
||||
return; // exit
|
||||
}
|
||||
|
||||
// Check if the issue is already assigned
|
||||
const issue = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
if (issue.data.assignees.length > 0) {
|
||||
// Comment that it's already assigned
|
||||
await github.rest.issues.createComment({
|
||||
@@ -97,3 +109,42 @@ jobs:
|
||||
issue_number: issueNumber,
|
||||
body: `👋 @${commenter}, you've been assigned to this issue! Thank you for taking the time to contribute. Make sure to check out our [contributing guidelines](https://github.com/google-gemini/gemini-cli/blob/main/CONTRIBUTING.md).`
|
||||
});
|
||||
|
||||
- name: 'Unassign issue from user'
|
||||
if: "contains(github.event.comment.body, '/unassign')"
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |
|
||||
const issueNumber = context.issue.number;
|
||||
const commenter = context.actor;
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const commentBody = context.payload.comment.body.trim();
|
||||
|
||||
if (commentBody !== '/unassign') {
|
||||
return;
|
||||
}
|
||||
|
||||
const issue = await github.rest.issues.get({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
const isAssigned = issue.data.assignees.some(assignee => assignee.login === commenter);
|
||||
|
||||
if (isAssigned) {
|
||||
await github.rest.issues.removeAssignees({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issueNumber,
|
||||
assignees: [commenter]
|
||||
});
|
||||
await github.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issueNumber,
|
||||
body: `👋 @${commenter}, you have been unassigned from this issue.`
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
name: '🏷️ Issue Opened Labeler'
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- 'opened'
|
||||
|
||||
jobs:
|
||||
label-issue:
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: |-
|
||||
${{ github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli' }}
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
env:
|
||||
APP_ID: '${{ secrets.APP_ID }}'
|
||||
if: |-
|
||||
${{ env.APP_ID != '' }}
|
||||
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
|
||||
- name: 'Add need-triage label'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
||||
script: |-
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
});
|
||||
|
||||
const hasLabel = issue.labels.some(l => l.name === 'status/need-triage');
|
||||
if (!hasLabel) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['status/need-triage']
|
||||
});
|
||||
} else {
|
||||
core.info('Issue already has status/need-triage label. Skipping.');
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
name: 'Label Child Issues for Project Rollup'
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: ['opened', 'edited', 'reopened']
|
||||
schedule:
|
||||
- cron: '0 * * * *' # Run every hour
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: 'write'
|
||||
contents: 'read'
|
||||
|
||||
jobs:
|
||||
# Event-based: Quick reaction to new/edited issues in THIS repo
|
||||
labeler:
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && github.event_name == 'issues'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@v4'
|
||||
|
||||
- name: 'Setup Node.js'
|
||||
uses: 'actions/setup-node@v4'
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install Dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Run Multi-Repo Sync Script'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: 'node .github/scripts/sync-maintainer-labels.cjs'
|
||||
|
||||
# Scheduled/Manual: Recursive sync across multiple repos
|
||||
sync-maintainer-labels:
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@v4'
|
||||
|
||||
- name: 'Setup Node.js'
|
||||
uses: 'actions/setup-node@v4'
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install Dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Run Multi-Repo Sync Script'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: 'node .github/scripts/sync-maintainer-labels.cjs'
|
||||
@@ -0,0 +1,175 @@
|
||||
name: 'Label Workstream Rollup'
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: ['opened', 'edited', 'reopened']
|
||||
schedule:
|
||||
- cron: '0 * * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
issues: 'write'
|
||||
steps:
|
||||
- name: 'Check for Parent Workstream and Apply Label'
|
||||
uses: 'actions/github-script@v7'
|
||||
with:
|
||||
script: |
|
||||
const labelToAdd = 'workstream-rollup';
|
||||
|
||||
// Allow-list of parent issue URLs
|
||||
const allowedParentUrls = [
|
||||
'https://github.com/google-gemini/gemini-cli/issues/15374',
|
||||
'https://github.com/google-gemini/gemini-cli/issues/15456',
|
||||
'https://github.com/google-gemini/gemini-cli/issues/15324',
|
||||
'https://github.com/google-gemini/gemini-cli/issues/17202',
|
||||
'https://github.com/google-gemini/gemini-cli/issues/17203'
|
||||
];
|
||||
|
||||
// Single issue processing (for event triggers)
|
||||
async function processSingleIssue(owner, repo, number) {
|
||||
const query = `
|
||||
query($owner:String!, $repo:String!, $number:Int!) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
issue(number:$number) {
|
||||
number
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
try {
|
||||
const result = await github.graphql(query, { owner, repo, number });
|
||||
|
||||
if (!result || !result.repository || !result.repository.issue) {
|
||||
console.log(`Issue #${number} not found or data missing.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const issue = result.repository.issue;
|
||||
await checkAndLabel(issue, owner, repo);
|
||||
} catch (error) {
|
||||
console.error(`Failed to process issue #${number}:`, error);
|
||||
throw error; // Re-throw to be caught by main execution
|
||||
}
|
||||
}
|
||||
|
||||
// Bulk processing (for schedule/dispatch)
|
||||
async function processAllOpenIssues(owner, repo) {
|
||||
const query = `
|
||||
query($owner:String!, $repo:String!, $cursor:String) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
issues(first: 100, states: OPEN, after: $cursor) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
endCursor
|
||||
}
|
||||
nodes {
|
||||
number
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
parent {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
let hasNextPage = true;
|
||||
let cursor = null;
|
||||
|
||||
while (hasNextPage) {
|
||||
try {
|
||||
const result = await github.graphql(query, { owner, repo, cursor });
|
||||
|
||||
if (!result || !result.repository || !result.repository.issues) {
|
||||
console.error('Invalid response structure from GitHub API');
|
||||
break;
|
||||
}
|
||||
|
||||
const issues = result.repository.issues.nodes || [];
|
||||
|
||||
console.log(`Processing batch of ${issues.length} issues...`);
|
||||
for (const issue of issues) {
|
||||
await checkAndLabel(issue, owner, repo);
|
||||
}
|
||||
|
||||
hasNextPage = result.repository.issues.pageInfo.hasNextPage;
|
||||
cursor = result.repository.issues.pageInfo.endCursor;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch issues batch:', error);
|
||||
throw error; // Re-throw to be caught by main execution
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function checkAndLabel(issue, owner, repo) {
|
||||
if (!issue || !issue.parent) return;
|
||||
|
||||
let currentParent = issue.parent;
|
||||
let tracedParents = [];
|
||||
let matched = false;
|
||||
|
||||
while (currentParent) {
|
||||
tracedParents.push(currentParent.url);
|
||||
|
||||
if (allowedParentUrls.includes(currentParent.url)) {
|
||||
console.log(`SUCCESS: Issue #${issue.number} is a descendant of ${currentParent.url}. Trace: ${tracedParents.join(' -> ')}. Adding label.`);
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issue.number,
|
||||
labels: [labelToAdd]
|
||||
});
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
currentParent = currentParent.parent;
|
||||
}
|
||||
|
||||
if (!matched && context.eventName === 'issues') {
|
||||
console.log(`Issue #${issue.number} did not match any allowed workstreams. Trace: ${tracedParents.join(' -> ') || 'None'}.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Main execution
|
||||
try {
|
||||
if (context.eventName === 'issues') {
|
||||
console.log(`Processing single issue #${context.payload.issue.number}...`);
|
||||
await processSingleIssue(context.repo.owner, context.repo.repo, context.payload.issue.number);
|
||||
} else {
|
||||
console.log(`Running for event: ${context.eventName}. Processing all open issues...`);
|
||||
await processAllOpenIssues(context.repo.owner, context.repo.repo);
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(`Workflow failed: ${error.message}`);
|
||||
}
|
||||
@@ -12,6 +12,8 @@ on:
|
||||
|
||||
jobs:
|
||||
linkChecker:
|
||||
if: |-
|
||||
${{ github.repository == 'google-gemini/gemini-cli' }}
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
name: '🏷️ PR Contribution Guidelines Notifier'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- 'opened'
|
||||
|
||||
jobs:
|
||||
notify-process-change:
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: |-
|
||||
github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli'
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
env:
|
||||
APP_ID: '${{ secrets.APP_ID }}'
|
||||
if: |-
|
||||
${{ env.APP_ID != '' }}
|
||||
uses: 'actions/create-github-app-token@v2'
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
|
||||
- name: 'Check membership and post comment'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token || secrets.GITHUB_TOKEN }}'
|
||||
script: |-
|
||||
const org = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const username = context.payload.pull_request.user.login;
|
||||
const pr_number = context.payload.pull_request.number;
|
||||
|
||||
// 1. Check if the PR author is a maintainer
|
||||
// Check team membership (most reliable for private org members)
|
||||
let isTeamMember = false;
|
||||
const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs'];
|
||||
for (const team_slug of teams) {
|
||||
try {
|
||||
const members = await github.paginate(github.rest.teams.listMembersInOrg, {
|
||||
org: org,
|
||||
team_slug: team_slug
|
||||
});
|
||||
if (members.some(m => m.login.toLowerCase() === username.toLowerCase())) {
|
||||
isTeamMember = true;
|
||||
core.info(`${username} is a member of ${team_slug}. No notification needed.`);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
core.warning(`Failed to fetch team members from ${team_slug}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (isTeamMember) return;
|
||||
|
||||
// Check author_association from webhook payload
|
||||
const authorAssociation = context.payload.pull_request.author_association;
|
||||
const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(authorAssociation);
|
||||
|
||||
if (isRepoMaintainer) {
|
||||
core.info(`${username} is a maintainer (author_association: ${authorAssociation}). No notification needed.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if author is a Googler
|
||||
const isGoogler = async (login) => {
|
||||
try {
|
||||
const orgs = ['googlers', 'google'];
|
||||
for (const org of orgs) {
|
||||
try {
|
||||
await github.rest.orgs.checkMembershipForUser({
|
||||
org: org,
|
||||
username: login
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e.status !== 404) throw e;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
core.warning(`Failed to check org membership for ${login}: ${e.message}`);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (await isGoogler(username)) {
|
||||
core.info(`${username} is a Googler. No notification needed.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Check if the PR is already associated with an issue
|
||||
const query = `
|
||||
query($owner:String!, $repo:String!, $number:Int!) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
pullRequest(number:$number) {
|
||||
closingIssuesReferences(first: 1) {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const variables = { owner: org, repo: repo, number: pr_number };
|
||||
const result = await github.graphql(query, variables);
|
||||
const issueCount = result.repository.pullRequest.closingIssuesReferences.totalCount;
|
||||
|
||||
if (issueCount > 0) {
|
||||
core.info(`PR #${pr_number} is already associated with an issue. No notification needed.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Post the notification comment
|
||||
core.info(`${username} is not a maintainer and PR #${pr_number} has no linked issue. Posting notification.`);
|
||||
|
||||
const comment = `
|
||||
Hi @${username}, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.
|
||||
|
||||
We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: [Improving Our Contribution Process & Introducing New Guidelines](https://github.com/google-gemini/gemini-cli/discussions/16706).
|
||||
|
||||
Key Update: Starting **January 26, 2026**, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.
|
||||
|
||||
Thank you for your understanding and for being a part of our community!
|
||||
`.trim().replace(/^[ ]+/gm, '');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: org,
|
||||
repo: repo,
|
||||
issue_number: pr_number,
|
||||
body: comment
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: 'PR rate limiter'
|
||||
|
||||
permissions: {}
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
|
||||
jobs:
|
||||
limit:
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
pull-requests: 'write'
|
||||
steps:
|
||||
- name: 'Limit open pull requests per user'
|
||||
uses: 'Homebrew/actions/limit-pull-requests@9ceb7934560eb61d131dde205a6c2d77b2e1529d' # master
|
||||
with:
|
||||
except-author-associations: 'MEMBER,OWNER,COLLABORATOR'
|
||||
comment-limit: 8
|
||||
comment: >
|
||||
You already have 7 pull requests open. Please work on getting
|
||||
existing PRs merged before opening more.
|
||||
close-limit: 8
|
||||
close: true
|
||||
@@ -32,6 +32,7 @@ on:
|
||||
|
||||
jobs:
|
||||
change-tags:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
|
||||
@@ -47,6 +47,7 @@ on:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
@@ -110,6 +111,7 @@ jobs:
|
||||
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
|
||||
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
dry-run: '${{ github.event.inputs.dry_run }}'
|
||||
previous-tag: '${{ steps.release_info.outputs.PREVIOUS_TAG }}'
|
||||
skip-github-release: '${{ github.event.inputs.skip_github_release }}'
|
||||
|
||||
@@ -31,6 +31,7 @@ on:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
@@ -123,6 +124,7 @@ jobs:
|
||||
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
|
||||
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
dry-run: '${{ steps.vars.outputs.is_dry_run }}'
|
||||
previous-tag: '${{ steps.nightly_version.outputs.PREVIOUS_TAG }}'
|
||||
working-directory: './release'
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# This workflow is triggered on every new release.
|
||||
# It uses Gemini to generate release notes and creates a PR with the changes.
|
||||
name: 'Generate Release Notes'
|
||||
|
||||
on:
|
||||
release:
|
||||
types: ['published']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'New version (e.g., v1.2.3)'
|
||||
required: true
|
||||
type: 'string'
|
||||
body:
|
||||
description: 'Release notes body'
|
||||
required: true
|
||||
type: 'string'
|
||||
time:
|
||||
description: 'Release time'
|
||||
required: true
|
||||
type: 'string'
|
||||
|
||||
jobs:
|
||||
generate-release-notes:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'write'
|
||||
pull-requests: 'write'
|
||||
steps:
|
||||
- name: 'Checkout repository'
|
||||
uses: 'actions/checkout@v4'
|
||||
with:
|
||||
# The user-level skills need to be available to the workflow
|
||||
fetch-depth: 0
|
||||
ref: 'main'
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@v4'
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: 'Get release information'
|
||||
id: 'release_info'
|
||||
run: |
|
||||
VERSION="${{ github.event.inputs.version || github.event.release.tag_name }}"
|
||||
TIME="${{ github.event.inputs.time || github.event.release.created_at }}"
|
||||
|
||||
echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "TIME=${TIME}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Use a heredoc to preserve multiline release body
|
||||
echo 'RAW_CHANGELOG<<EOF' >> "$GITHUB_OUTPUT"
|
||||
printf "%s\n" "$BODY" >> "$GITHUB_OUTPUT"
|
||||
echo 'EOF' >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
BODY: '${{ github.event.inputs.body || github.event.release.body }}'
|
||||
|
||||
- name: 'Validate version'
|
||||
id: 'validate_version'
|
||||
run: |
|
||||
if echo "${{ steps.release_info.outputs.VERSION }}" | grep -q "nightly"; then
|
||||
echo "Nightly release detected. Stopping workflow."
|
||||
echo "CONTINUE=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "CONTINUE=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: 'Generate Changelog with Gemini'
|
||||
if: "steps.validate_version.outputs.CONTINUE == 'true'"
|
||||
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0
|
||||
with:
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
prompt: |
|
||||
Activate the 'docs-changelog' skill.
|
||||
|
||||
**Release Information:**
|
||||
- New Version: ${{ steps.release_info.outputs.VERSION }}
|
||||
- Release Date: ${{ steps.release_info.outputs.TIME }}
|
||||
- Raw Changelog Data: ${{ steps.release_info.outputs.RAW_CHANGELOG }}
|
||||
|
||||
Execute the release notes generation process using the information provided.
|
||||
|
||||
When you are done, please output your thought process and the steps you took for future debugging purposes.
|
||||
|
||||
- name: 'Create Pull Request'
|
||||
if: "steps.validate_version.outputs.CONTINUE == 'true'"
|
||||
uses: 'peter-evans/create-pull-request@v6'
|
||||
with:
|
||||
token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
commit-message: 'docs(changelog): update for ${{ steps.release_info.outputs.VERSION }}'
|
||||
title: 'Changelog for ${{ steps.release_info.outputs.VERSION }}'
|
||||
body: |
|
||||
This PR contains the auto-generated changelog for the ${{ steps.release_info.outputs.VERSION }} release.
|
||||
|
||||
Please review and merge.
|
||||
branch: 'changelog-${{ steps.release_info.outputs.VERSION }}'
|
||||
base: 'main'
|
||||
team-reviewers: 'gemini-cli-docs, gemini-cli-maintainers'
|
||||
delete-branch: true
|
||||
@@ -118,6 +118,7 @@ jobs:
|
||||
ORIGINAL_RELEASE_VERSION: '${{ steps.patch_version.outputs.RELEASE_VERSION }}'
|
||||
ORIGINAL_RELEASE_TAG: '${{ steps.patch_version.outputs.RELEASE_TAG }}'
|
||||
ORIGINAL_PREVIOUS_TAG: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
|
||||
VARS_CLI_PACKAGE_NAME: '${{ vars.CLI_PACKAGE_NAME }}'
|
||||
run: |
|
||||
echo "🔍 Verifying no concurrent patch releases have occurred..."
|
||||
|
||||
@@ -129,7 +130,7 @@ jobs:
|
||||
|
||||
# Re-run the same version calculation script
|
||||
echo "Re-calculating version to check for changes..."
|
||||
CURRENT_PATCH_JSON=$(node scripts/get-release-version.js --cli-package-name="${{vars.CLI_PACKAGE_NAME}}" --type=patch --patch-from="${CHANNEL}")
|
||||
CURRENT_PATCH_JSON=$(node scripts/get-release-version.js --cli-package-name="${VARS_CLI_PACKAGE_NAME}" --type=patch --patch-from="${CHANNEL}")
|
||||
CURRENT_RELEASE_VERSION=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseVersion)
|
||||
CURRENT_RELEASE_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .releaseTag)
|
||||
CURRENT_PREVIOUS_TAG=$(echo "${CURRENT_PATCH_JSON}" | jq -r .previousReleaseTag)
|
||||
@@ -162,10 +163,15 @@ jobs:
|
||||
- name: 'Print Calculated Version'
|
||||
run: |-
|
||||
echo "Patch Release Summary:"
|
||||
echo " Release Version: ${{ steps.patch_version.outputs.RELEASE_VERSION }}"
|
||||
echo " Release Tag: ${{ steps.patch_version.outputs.RELEASE_TAG }}"
|
||||
echo " NPM Tag: ${{ steps.patch_version.outputs.NPM_TAG }}"
|
||||
echo " Previous Tag: ${{ steps.patch_version.outputs.PREVIOUS_TAG }}"
|
||||
echo " Release Version: ${STEPS_PATCH_VERSION_OUTPUTS_RELEASE_VERSION}"
|
||||
echo " Release Tag: ${STEPS_PATCH_VERSION_OUTPUTS_RELEASE_TAG}"
|
||||
echo " NPM Tag: ${STEPS_PATCH_VERSION_OUTPUTS_NPM_TAG}"
|
||||
echo " Previous Tag: ${STEPS_PATCH_VERSION_OUTPUTS_PREVIOUS_TAG}"
|
||||
env:
|
||||
STEPS_PATCH_VERSION_OUTPUTS_RELEASE_VERSION: '${{ steps.patch_version.outputs.RELEASE_VERSION }}'
|
||||
STEPS_PATCH_VERSION_OUTPUTS_RELEASE_TAG: '${{ steps.patch_version.outputs.RELEASE_TAG }}'
|
||||
STEPS_PATCH_VERSION_OUTPUTS_NPM_TAG: '${{ steps.patch_version.outputs.NPM_TAG }}'
|
||||
STEPS_PATCH_VERSION_OUTPUTS_PREVIOUS_TAG: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
|
||||
|
||||
- name: 'Run Tests'
|
||||
if: "${{github.event.inputs.force_skip_tests != 'true'}}"
|
||||
@@ -184,6 +190,7 @@ jobs:
|
||||
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
|
||||
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
dry-run: '${{ github.event.inputs.dry_run }}'
|
||||
previous-tag: '${{ steps.patch_version.outputs.PREVIOUS_TAG }}'
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
|
||||
@@ -239,6 +239,7 @@ jobs:
|
||||
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
|
||||
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
dry-run: '${{ github.event.inputs.dry_run }}'
|
||||
previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_PREVIEW_TAG }}'
|
||||
working-directory: './release'
|
||||
@@ -305,6 +306,7 @@ jobs:
|
||||
wombat-token-cli: '${{ secrets.WOMBAT_TOKEN_CLI }}'
|
||||
wombat-token-a2a-server: '${{ secrets.WOMBAT_TOKEN_A2A_SERVER }}'
|
||||
github-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
github-release-token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
dry-run: '${{ github.event.inputs.dry_run }}'
|
||||
previous-tag: '${{ needs.calculate-versions.outputs.PREVIOUS_STABLE_TAG }}'
|
||||
working-directory: './release'
|
||||
@@ -333,6 +335,7 @@ jobs:
|
||||
name: 'Create Nightly PR'
|
||||
needs: ['publish-stable', 'calculate-versions']
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
contents: 'write'
|
||||
pull-requests: 'write'
|
||||
@@ -360,23 +363,28 @@ jobs:
|
||||
- name: 'Create and switch to a new branch'
|
||||
id: 'release_branch'
|
||||
run: |
|
||||
BRANCH_NAME="chore/nightly-version-bump-${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}"
|
||||
BRANCH_NAME="chore/nightly-version-bump-${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"
|
||||
git switch -c "${BRANCH_NAME}"
|
||||
echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_OUTPUT}"
|
||||
env:
|
||||
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
|
||||
|
||||
- name: 'Update package versions'
|
||||
run: 'npm run release:version "${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}"'
|
||||
run: 'npm run release:version "${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"'
|
||||
env:
|
||||
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
|
||||
|
||||
- name: 'Commit and Push package versions'
|
||||
env:
|
||||
BRANCH_NAME: '${{ steps.release_branch.outputs.BRANCH_NAME }}'
|
||||
DRY_RUN: '${{ github.event.inputs.dry_run }}'
|
||||
NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION: '${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}'
|
||||
run: |-
|
||||
git add package.json packages/*/package.json
|
||||
if [ -f package-lock.json ]; then
|
||||
git add package-lock.json
|
||||
fi
|
||||
git commit -m "chore(release): bump version to ${{ needs.calculate-versions.outputs.NEXT_NIGHTLY_VERSION }}"
|
||||
git commit -m "chore(release): bump version to ${NEEDS_CALCULATE_VERSIONS_OUTPUTS_NEXT_NIGHTLY_VERSION}"
|
||||
if [[ "${DRY_RUN}" == "false" ]]; then
|
||||
echo "Pushing release branch to remote..."
|
||||
git push --set-upstream origin "${BRANCH_NAME}"
|
||||
|
||||
@@ -42,6 +42,7 @@ on:
|
||||
|
||||
jobs:
|
||||
change-tags:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
@@ -203,7 +204,7 @@ jobs:
|
||||
run: |
|
||||
ROLLBACK_COMMIT=$(git rev-parse -q --verify "$TARGET_TAG")
|
||||
if [ "$ROLLBACK_COMMIT" != "$TARGET_HASH" ]; then
|
||||
echo '❌ Failed to add tag $TARGET_TAG to commit $TARGET_HASH'
|
||||
echo "❌ Failed to add tag ${TARGET_TAG} to commit ${TARGET_HASH}"
|
||||
echo '❌ This means the tag was not added, and the workflow should fail.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -16,6 +16,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
@@ -20,6 +20,7 @@ on:
|
||||
|
||||
jobs:
|
||||
smoke-test:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'write'
|
||||
|
||||
@@ -40,5 +40,5 @@ jobs:
|
||||
If this is still relevant, you are welcome to reopen or leave a comment. Thanks for contributing!
|
||||
days-before-stale: 60
|
||||
days-before-close: 14
|
||||
exempt-issue-labels: 'pinned,security'
|
||||
exempt-pr-labels: 'pinned,security'
|
||||
exempt-issue-labels: 'pinned,security,🔒 maintainer only,help wanted,🗓️ Public Roadmap'
|
||||
exempt-pr-labels: 'pinned,security,🔒 maintainer only,help wanted,🗓️ Public Roadmap'
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
name: 'Test Build Binary'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: 'bash'
|
||||
|
||||
jobs:
|
||||
build-node-binary:
|
||||
name: 'Build Binary (${{ matrix.os }})'
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: 'ubuntu-latest'
|
||||
platform_name: 'linux-x64'
|
||||
arch: 'x64'
|
||||
- os: 'windows-latest'
|
||||
platform_name: 'win32-x64'
|
||||
arch: 'x64'
|
||||
- os: 'macos-latest' # Apple Silicon (ARM64)
|
||||
platform_name: 'darwin-arm64'
|
||||
arch: 'arm64'
|
||||
- os: 'macos-latest' # Intel (x64) running on ARM via Rosetta
|
||||
platform_name: 'darwin-x64'
|
||||
arch: 'x64'
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@v4'
|
||||
|
||||
- name: 'Optimize Windows Performance'
|
||||
if: "matrix.os == 'windows-latest'"
|
||||
run: |
|
||||
Set-MpPreference -DisableRealtimeMonitoring $true
|
||||
Stop-Service -Name "wsearch" -Force -ErrorAction SilentlyContinue
|
||||
Set-Service -Name "wsearch" -StartupType Disabled
|
||||
Stop-Service -Name "SysMain" -Force -ErrorAction SilentlyContinue
|
||||
Set-Service -Name "SysMain" -StartupType Disabled
|
||||
shell: 'powershell'
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@v4'
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
architecture: '${{ matrix.arch }}'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Check Secrets'
|
||||
id: 'check_secrets'
|
||||
run: |
|
||||
echo "has_win_cert=${{ secrets.WINDOWS_PFX_BASE64 != '' }}" >> "$GITHUB_OUTPUT"
|
||||
echo "has_mac_cert=${{ secrets.MACOS_CERT_P12_BASE64 != '' }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Setup Windows SDK (Windows)'
|
||||
if: "matrix.os == 'windows-latest'"
|
||||
uses: 'microsoft/setup-msbuild@v2'
|
||||
|
||||
- name: 'Add Signtool to Path (Windows)'
|
||||
if: "matrix.os == 'windows-latest'"
|
||||
run: |
|
||||
$signtoolPath = Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin" -Recurse -Filter "signtool.exe" | Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty DirectoryName
|
||||
echo "Found signtool at: $signtoolPath"
|
||||
echo "$signtoolPath" >> $env:GITHUB_PATH
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Setup macOS Keychain'
|
||||
if: "startsWith(matrix.os, 'macos') && steps.check_secrets.outputs.has_mac_cert == 'true' && github.event_name != 'pull_request'"
|
||||
env:
|
||||
BUILD_CERTIFICATE_BASE64: '${{ secrets.MACOS_CERT_P12_BASE64 }}'
|
||||
P12_PASSWORD: '${{ secrets.MACOS_CERT_PASSWORD }}'
|
||||
KEYCHAIN_PASSWORD: 'temp-password'
|
||||
run: |
|
||||
# Create the P12 file
|
||||
echo "$BUILD_CERTIFICATE_BASE64" | base64 --decode > certificate.p12
|
||||
|
||||
# Create a temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
||||
|
||||
# Import the certificate
|
||||
security import certificate.p12 -k build.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
|
||||
|
||||
# Allow codesign to access it
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain
|
||||
|
||||
# Set Identity for build script
|
||||
echo "APPLE_IDENTITY=${{ secrets.MACOS_CERT_IDENTITY }}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: 'Setup Windows Certificate'
|
||||
if: "matrix.os == 'windows-latest' && steps.check_secrets.outputs.has_win_cert == 'true' && github.event_name != 'pull_request'"
|
||||
env:
|
||||
PFX_BASE64: '${{ secrets.WINDOWS_PFX_BASE64 }}'
|
||||
PFX_PASSWORD: '${{ secrets.WINDOWS_PFX_PASSWORD }}'
|
||||
run: |
|
||||
$pfx_cert_byte = [System.Convert]::FromBase64String("$env:PFX_BASE64")
|
||||
$certPath = Join-Path (Get-Location) "cert.pfx"
|
||||
[IO.File]::WriteAllBytes($certPath, $pfx_cert_byte)
|
||||
echo "WINDOWS_PFX_FILE=$certPath" >> $env:GITHUB_ENV
|
||||
echo "WINDOWS_PFX_PASSWORD=$env:PFX_PASSWORD" >> $env:GITHUB_ENV
|
||||
shell: 'pwsh'
|
||||
|
||||
- name: 'Build Binary'
|
||||
run: 'npm run build:binary'
|
||||
|
||||
- name: 'Build Core Package'
|
||||
run: 'npm run build -w @google/gemini-cli-core'
|
||||
|
||||
- name: 'Verify Output Exists'
|
||||
run: |
|
||||
if [ -f "dist/${{ matrix.platform_name }}/gemini" ]; then
|
||||
echo "Binary found at dist/${{ matrix.platform_name }}/gemini"
|
||||
elif [ -f "dist/${{ matrix.platform_name }}/gemini.exe" ]; then
|
||||
echo "Binary found at dist/${{ matrix.platform_name }}/gemini.exe"
|
||||
else
|
||||
echo "Error: Binary not found in dist/${{ matrix.platform_name }}/"
|
||||
ls -R dist/
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: 'Smoke Test Binary'
|
||||
run: |
|
||||
echo "Running binary smoke test..."
|
||||
if [ -f "dist/${{ matrix.platform_name }}/gemini.exe" ]; then
|
||||
"./dist/${{ matrix.platform_name }}/gemini.exe" --version
|
||||
else
|
||||
"./dist/${{ matrix.platform_name }}/gemini" --version
|
||||
fi
|
||||
|
||||
- name: 'Run Integration Tests'
|
||||
if: "github.event_name != 'pull_request'"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
run: |
|
||||
echo "Running integration tests with binary..."
|
||||
if [[ "${{ matrix.os }}" == 'windows-latest' ]]; then
|
||||
BINARY_PATH="$(cygpath -m "$(pwd)/dist/${{ matrix.platform_name }}/gemini.exe")"
|
||||
else
|
||||
BINARY_PATH="$(pwd)/dist/${{ matrix.platform_name }}/gemini"
|
||||
fi
|
||||
echo "Using binary at $BINARY_PATH"
|
||||
export INTEGRATION_TEST_GEMINI_BINARY_PATH="$BINARY_PATH"
|
||||
npm run test:integration:sandbox:none -- --testTimeout=600000
|
||||
|
||||
- name: 'Upload Artifact'
|
||||
uses: 'actions/upload-artifact@v4'
|
||||
with:
|
||||
name: 'gemini-cli-${{ matrix.platform_name }}'
|
||||
path: 'dist/${{ matrix.platform_name }}/'
|
||||
retention-days: 5
|
||||
@@ -15,6 +15,7 @@ on:
|
||||
|
||||
jobs:
|
||||
save_repo_name:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- name: 'Save Repo name'
|
||||
@@ -23,14 +24,15 @@ jobs:
|
||||
HEAD_SHA: '${{ github.event.inputs.head_sha || github.event.pull_request.head.sha }}'
|
||||
run: |
|
||||
mkdir -p ./pr
|
||||
echo '${{ env.REPO_NAME }}' > ./pr/repo_name
|
||||
echo '${{ env.HEAD_SHA }}' > ./pr/head_sha
|
||||
echo "${REPO_NAME}" > ./pr/repo_name
|
||||
echo "${HEAD_SHA}" > ./pr/head_sha
|
||||
- uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'repo_name'
|
||||
path: 'pr/'
|
||||
trigger_e2e:
|
||||
name: 'Trigger e2e'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
steps:
|
||||
- id: 'trigger-e2e'
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
name: 'Unassign Inactive Issue Assignees'
|
||||
|
||||
# This workflow runs daily and scans every open "help wanted" issue that has
|
||||
# one or more assignees. For each assignee it checks whether they have a
|
||||
# non-draft pull request (open and ready for review, or already merged) that
|
||||
# is linked to the issue. Draft PRs are intentionally excluded so that
|
||||
# contributors cannot reset the check by opening a no-op PR. If no
|
||||
# qualifying PR is found within 7 days of assignment the assignee is
|
||||
# automatically removed and a friendly comment is posted so that other
|
||||
# contributors can pick up the work.
|
||||
# Maintainers, org members, and collaborators (anyone with write access or
|
||||
# above) are always exempted and will never be auto-unassigned.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 9 * * *' # Every day at 09:00 UTC
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Run in dry-run mode (no changes will be applied)'
|
||||
required: false
|
||||
default: false
|
||||
type: 'boolean'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: 'bash'
|
||||
|
||||
jobs:
|
||||
unassign-inactive-assignees:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
issues: 'write'
|
||||
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
uses: 'actions/create-github-app-token@v2'
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
|
||||
- name: 'Unassign inactive assignees'
|
||||
uses: 'actions/github-script@v7'
|
||||
env:
|
||||
DRY_RUN: '${{ inputs.dry_run }}'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |
|
||||
const dryRun = process.env.DRY_RUN === 'true';
|
||||
if (dryRun) {
|
||||
core.info('DRY RUN MODE ENABLED: No changes will be applied.');
|
||||
}
|
||||
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
const GRACE_PERIOD_DAYS = 7;
|
||||
const now = new Date();
|
||||
|
||||
let maintainerLogins = new Set();
|
||||
const teams = ['gemini-cli-maintainers', 'gemini-cli-askmode-approvers', 'gemini-cli-docs'];
|
||||
|
||||
for (const team_slug of teams) {
|
||||
try {
|
||||
const members = await github.paginate(github.rest.teams.listMembersInOrg, {
|
||||
org: owner,
|
||||
team_slug,
|
||||
});
|
||||
for (const m of members) maintainerLogins.add(m.login.toLowerCase());
|
||||
core.info(`Fetched ${members.length} members from team ${team_slug}.`);
|
||||
} catch (e) {
|
||||
core.warning(`Could not fetch team ${team_slug}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const isGooglerCache = new Map();
|
||||
const isGoogler = async (login) => {
|
||||
if (isGooglerCache.has(login)) return isGooglerCache.get(login);
|
||||
try {
|
||||
for (const org of ['googlers', 'google']) {
|
||||
try {
|
||||
await github.rest.orgs.checkMembershipForUser({ org, username: login });
|
||||
isGooglerCache.set(login, true);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e.status !== 404) throw e;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
core.warning(`Could not check org membership for ${login}: ${e.message}`);
|
||||
}
|
||||
isGooglerCache.set(login, false);
|
||||
return false;
|
||||
};
|
||||
|
||||
const permissionCache = new Map();
|
||||
const isPrivilegedUser = async (login) => {
|
||||
if (maintainerLogins.has(login.toLowerCase())) return true;
|
||||
|
||||
if (permissionCache.has(login)) return permissionCache.get(login);
|
||||
|
||||
try {
|
||||
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner,
|
||||
repo,
|
||||
username: login,
|
||||
});
|
||||
const privileged = ['admin', 'maintain', 'write', 'triage'].includes(data.permission);
|
||||
permissionCache.set(login, privileged);
|
||||
if (privileged) {
|
||||
core.info(` @${login} is a repo collaborator (${data.permission}) — exempt.`);
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.status !== 404) {
|
||||
core.warning(`Could not check permission for ${login}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const googler = await isGoogler(login);
|
||||
permissionCache.set(login, googler);
|
||||
return googler;
|
||||
};
|
||||
|
||||
core.info('Fetching open "help wanted" issues with assignees...');
|
||||
|
||||
const issues = await github.paginate(github.rest.issues.listForRepo, {
|
||||
owner,
|
||||
repo,
|
||||
state: 'open',
|
||||
labels: 'help wanted',
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const assignedIssues = issues.filter(
|
||||
(issue) => !issue.pull_request && issue.assignees && issue.assignees.length > 0
|
||||
);
|
||||
|
||||
core.info(`Found ${assignedIssues.length} assigned "help wanted" issues.`);
|
||||
|
||||
let totalUnassigned = 0;
|
||||
|
||||
let timelineEvents = [];
|
||||
try {
|
||||
timelineEvents = await github.paginate(github.rest.issues.listEventsForTimeline, {
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issue.number,
|
||||
per_page: 100,
|
||||
mediaType: { previews: ['mockingbird'] },
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(`Could not fetch timeline for issue #${issue.number}: ${err.message}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const assignedAtMap = new Map();
|
||||
|
||||
for (const event of timelineEvents) {
|
||||
if (event.event === 'assigned' && event.assignee) {
|
||||
const login = event.assignee.login.toLowerCase();
|
||||
const at = new Date(event.created_at);
|
||||
assignedAtMap.set(login, at);
|
||||
} else if (event.event === 'unassigned' && event.assignee) {
|
||||
assignedAtMap.delete(event.assignee.login.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
const linkedPRAuthorSet = new Set();
|
||||
const seenPRKeys = new Set();
|
||||
|
||||
for (const event of timelineEvents) {
|
||||
if (
|
||||
event.event !== 'cross-referenced' ||
|
||||
!event.source ||
|
||||
event.source.type !== 'pull_request' ||
|
||||
!event.source.issue ||
|
||||
!event.source.issue.user ||
|
||||
!event.source.issue.number ||
|
||||
!event.source.issue.repository
|
||||
) continue;
|
||||
|
||||
const prOwner = event.source.issue.repository.owner.login;
|
||||
const prRepo = event.source.issue.repository.name;
|
||||
const prNumber = event.source.issue.number;
|
||||
const prAuthor = event.source.issue.user.login.toLowerCase();
|
||||
const prKey = `${prOwner}/${prRepo}#${prNumber}`;
|
||||
|
||||
if (seenPRKeys.has(prKey)) continue;
|
||||
seenPRKeys.add(prKey);
|
||||
|
||||
try {
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: prOwner,
|
||||
repo: prRepo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
const isReady = (pr.state === 'open' && !pr.draft) ||
|
||||
(pr.state === 'closed' && pr.merged_at !== null);
|
||||
|
||||
core.info(
|
||||
` PR ${prKey} by @${prAuthor}: ` +
|
||||
`state=${pr.state}, draft=${pr.draft}, merged=${!!pr.merged_at} → ` +
|
||||
(isReady ? 'qualifies' : 'does NOT qualify (draft or closed without merge)')
|
||||
);
|
||||
|
||||
if (isReady) linkedPRAuthorSet.add(prAuthor);
|
||||
} catch (err) {
|
||||
core.warning(`Could not fetch PR ${prKey}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const assigneesToRemove = [];
|
||||
|
||||
for (const assignee of issue.assignees) {
|
||||
const login = assignee.login.toLowerCase();
|
||||
|
||||
if (await isPrivilegedUser(assignee.login)) {
|
||||
core.info(` @${assignee.login}: privileged user — skipping.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const assignedAt = assignedAtMap.get(login);
|
||||
|
||||
if (!assignedAt) {
|
||||
core.warning(
|
||||
`No 'assigned' event found for @${login} on issue #${issue.number}; ` +
|
||||
`falling back to issue creation date (${issue.created_at}).`
|
||||
);
|
||||
assignedAtMap.set(login, new Date(issue.created_at));
|
||||
}
|
||||
const resolvedAssignedAt = assignedAtMap.get(login);
|
||||
|
||||
const daysSinceAssignment = (now - resolvedAssignedAt) / (1000 * 60 * 60 * 24);
|
||||
|
||||
core.info(
|
||||
` @${login}: assigned ${daysSinceAssignment.toFixed(1)} day(s) ago, ` +
|
||||
`ready-for-review PR: ${linkedPRAuthorSet.has(login) ? 'yes' : 'no'}`
|
||||
);
|
||||
|
||||
if (daysSinceAssignment < GRACE_PERIOD_DAYS) {
|
||||
core.info(` → within grace period, skipping.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (linkedPRAuthorSet.has(login)) {
|
||||
core.info(` → ready-for-review PR found, keeping assignment.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
core.info(` → no ready-for-review PR after ${GRACE_PERIOD_DAYS} days, will unassign.`);
|
||||
assigneesToRemove.push(assignee.login);
|
||||
}
|
||||
|
||||
if (assigneesToRemove.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
try {
|
||||
await github.rest.issues.removeAssignees({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issue.number,
|
||||
assignees: assigneesToRemove,
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(
|
||||
`Failed to unassign ${assigneesToRemove.join(', ')} from issue #${issue.number}: ${err.message}`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const mentionList = assigneesToRemove.map((l) => `@${l}`).join(', ');
|
||||
const commentBody =
|
||||
`👋 ${mentionList} — it has been more than ${GRACE_PERIOD_DAYS} days since ` +
|
||||
`you were assigned to this issue and we could not find a pull request ` +
|
||||
`ready for review.\n\n` +
|
||||
`To keep the backlog moving and ensure issues stay accessible to all ` +
|
||||
`contributors, we require a PR that is open and ready for review (not a ` +
|
||||
`draft) within ${GRACE_PERIOD_DAYS} days of assignment.\n\n` +
|
||||
`We are automatically unassigning you so that other contributors can pick ` +
|
||||
`this up. If you are still actively working on this, please:\n` +
|
||||
`1. Re-assign yourself by commenting \`/assign\`.\n` +
|
||||
`2. Open a PR (not a draft) linked to this issue (e.g. \`Fixes #${issue.number}\`) ` +
|
||||
`within ${GRACE_PERIOD_DAYS} days so the automation knows real progress is being made.\n\n` +
|
||||
`Thank you for your contribution — we hope to see a PR from you soon! 🙏`;
|
||||
|
||||
try {
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: issue.number,
|
||||
body: commentBody,
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(
|
||||
`Failed to post comment on issue #${issue.number}: ${err.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
totalUnassigned += assigneesToRemove.length;
|
||||
core.info(
|
||||
` ${dryRun ? '[DRY RUN] Would have unassigned' : 'Unassigned'}: ${assigneesToRemove.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
core.info(`\nDone. Total assignees ${dryRun ? 'that would be' : ''} unassigned: ${totalUnassigned}`);
|
||||
@@ -28,8 +28,13 @@ on:
|
||||
|
||||
jobs:
|
||||
verify-release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
runs-on: 'ubuntu-latest'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
|
||||
runs-on: '${{ matrix.os }}'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
packages: 'write'
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
.gemini/*
|
||||
!.gemini/config.yaml
|
||||
!.gemini/commands/
|
||||
!.gemini/skills/
|
||||
!.gemini/settings.json
|
||||
|
||||
# Note: .gemini-clipboard/ is NOT in gitignore so Gemini can access pasted images
|
||||
|
||||
@@ -44,6 +46,7 @@ packages/*/coverage/
|
||||
# Generated files
|
||||
packages/cli/src/generated/
|
||||
packages/core/src/generated/
|
||||
packages/devtools/src/_client-assets.ts
|
||||
.integration-tests/
|
||||
packages/vscode-ide-companion/*.vsix
|
||||
packages/cli/download-ripgrep*/
|
||||
@@ -53,6 +56,9 @@ gha-creds-*.json
|
||||
|
||||
# Log files
|
||||
patch_output.log
|
||||
gemini-debug.log
|
||||
|
||||
.genkit
|
||||
.gemini-clipboard/
|
||||
.eslintcache
|
||||
evals/logs/
|
||||
|
||||
@@ -17,5 +17,8 @@ eslint.config.js
|
||||
**/generated
|
||||
gha-creds-*.json
|
||||
junit.xml
|
||||
.gemini-linters/
|
||||
Thumbs.db
|
||||
.pytest_cache
|
||||
**/SKILL.md
|
||||
packages/sdk/test-data/*.json
|
||||
|
||||
Vendored
+3
@@ -7,6 +7,9 @@
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
|
||||
+69
-38
@@ -42,8 +42,13 @@ This project follows
|
||||
The process for contributing code is as follows:
|
||||
|
||||
1. **Find an issue** that you want to work on. If an issue is tagged as
|
||||
"🔒Maintainers only", this means it is reserved for project maintainers. We
|
||||
will not accept pull requests related to these issues.
|
||||
`🔒Maintainers only`, this means it is reserved for project maintainers. We
|
||||
will not accept pull requests related to these issues. In the near future,
|
||||
we will explicitly mark issues looking for contributions using the
|
||||
`help-wanted` label. If you believe an issue is a good candidate for
|
||||
community contribution, please leave a comment on the issue. A maintainer
|
||||
will review it and apply the `help-wanted` label if appropriate. Only
|
||||
maintainers should attempt to add the `help-wanted` label to an issue.
|
||||
2. **Fork the repository** and create a new branch.
|
||||
3. **Make your changes** in the `packages/` directory.
|
||||
4. **Ensure all checks pass** by running `npm run preflight`.
|
||||
@@ -55,26 +60,50 @@ All submissions, including submissions by project members, require review. We
|
||||
use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests)
|
||||
for this purpose.
|
||||
|
||||
If your pull request involves changes to `packages/cli` (the frontend), we
|
||||
recommend running our automated frontend review tool. **Note: This tool is
|
||||
currently experimental.** It helps detect common React anti-patterns, testing
|
||||
issues, and other frontend-specific best practices that are easy to miss.
|
||||
To assist with the review process, we provide an automated review tool that
|
||||
helps detect common anti-patterns, testing issues, and other best practices that
|
||||
are easy to miss.
|
||||
|
||||
To run the review tool, enter the following command from within Gemini CLI:
|
||||
#### Using the automated review tool
|
||||
|
||||
```text
|
||||
/review-frontend <PR_NUMBER>
|
||||
```
|
||||
You can run the review tool in two ways:
|
||||
|
||||
Replace `<PR_NUMBER>` with your pull request number. Authors are encouraged to
|
||||
run this on their own PRs for self-review, and reviewers should use it to
|
||||
augment their manual review process.
|
||||
1. **Using the helper script (Recommended):** We provide a script that
|
||||
automatically handles checking out the PR into a separate worktree,
|
||||
installing dependencies, building the project, and launching the review
|
||||
tool.
|
||||
|
||||
### Self assigning issues
|
||||
```bash
|
||||
./scripts/review.sh <PR_NUMBER> [model]
|
||||
```
|
||||
|
||||
To assign an issue to yourself, simply add a comment with the text `/assign`.
|
||||
The comment must contain only that text and nothing else. This command will
|
||||
assign the issue to you, provided it is not already assigned.
|
||||
**Authors are strongly encouraged to run this script on their own PRs**
|
||||
immediately after creation. This allows you to catch and fix simple issues
|
||||
locally before a maintainer performs a full review.
|
||||
|
||||
**Note on Models:** By default, the script uses the latest Pro model
|
||||
(`gemini-3.1-pro-preview`). If you do not have enough Pro quota, you can run
|
||||
it with the latest Flash model instead:
|
||||
`./scripts/review.sh <PR_NUMBER> gemini-3-flash-preview`.
|
||||
|
||||
2. **Manually from within Gemini CLI:** If you already have the PR checked out
|
||||
and built, you can run the tool directly from the CLI prompt:
|
||||
|
||||
```text
|
||||
/review-frontend <PR_NUMBER>
|
||||
```
|
||||
|
||||
Replace `<PR_NUMBER>` with your pull request number. Reviewers should use this
|
||||
tool to augment, not replace, their manual review process.
|
||||
|
||||
### Self-assigning and unassigning issues
|
||||
|
||||
To assign an issue to yourself, simply add a comment with the text `/assign`. To
|
||||
unassign yourself from an issue, add a comment with the text `/unassign`.
|
||||
|
||||
The comment must contain only that text and nothing else. These commands will
|
||||
assign or unassign the issue as requested, provided the conditions are met
|
||||
(e.g., an issue must be unassigned to be assigned).
|
||||
|
||||
Please note that you can have a maximum of 3 issues assigned to you at any given
|
||||
time.
|
||||
@@ -94,8 +123,11 @@ any code is written.
|
||||
- **For features:** The PR should be linked to the feature request or proposal
|
||||
issue that has been approved by a maintainer.
|
||||
|
||||
If an issue for your change doesn't exist, please **open one first** and wait
|
||||
for feedback before you start coding.
|
||||
If an issue for your change doesn't exist, we will automatically close your PR
|
||||
along with a comment reminding you to associate the PR with an issue. The ideal
|
||||
workflow starts with an issue that has been reviewed and approved by a
|
||||
maintainer. Please **open the issue first** and wait for feedback before you
|
||||
start coding.
|
||||
|
||||
#### 2. Keep it small and focused
|
||||
|
||||
@@ -256,7 +288,8 @@ npm run test:e2e
|
||||
```
|
||||
|
||||
For more detailed information on the integration testing framework, please see
|
||||
the [Integration Tests documentation](/docs/integration-tests.md).
|
||||
the
|
||||
[Integration Tests documentation](https://geminicli.com/docs/integration-tests).
|
||||
|
||||
### Linting and preflight checks
|
||||
|
||||
@@ -309,11 +342,9 @@ npm run lint
|
||||
|
||||
- Please adhere to the coding style, patterns, and conventions used throughout
|
||||
the existing codebase.
|
||||
- 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.
|
||||
- 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.
|
||||
- **Imports:** Pay special attention to import paths. The project uses ESLint to
|
||||
enforce restrictions on relative imports between packages.
|
||||
|
||||
@@ -364,8 +395,7 @@ specific debug settings.
|
||||
|
||||
### React DevTools
|
||||
|
||||
To debug the CLI's React-based UI, you can use React DevTools. Ink, the library
|
||||
used for the CLI's interface, is compatible with React DevTools version 4.x.
|
||||
To debug the CLI's React-based UI, you can use React DevTools.
|
||||
|
||||
1. **Start the Gemini CLI in development mode:**
|
||||
|
||||
@@ -373,20 +403,20 @@ used for the CLI's interface, is compatible with React DevTools version 4.x.
|
||||
DEV=true npm start
|
||||
```
|
||||
|
||||
2. **Install and run React DevTools version 4.28.5 (or the latest compatible
|
||||
4.x version):**
|
||||
2. **Install and run React DevTools version 6 (which matches the CLI's
|
||||
`react-devtools-core`):**
|
||||
|
||||
You can either install it globally:
|
||||
|
||||
```bash
|
||||
npm install -g react-devtools@4.28.5
|
||||
npm install -g react-devtools@6
|
||||
react-devtools
|
||||
```
|
||||
|
||||
Or run it directly using npx:
|
||||
|
||||
```bash
|
||||
npx react-devtools@4.28.5
|
||||
npx react-devtools@6
|
||||
```
|
||||
|
||||
Your running CLI application should then connect to React DevTools.
|
||||
@@ -400,12 +430,13 @@ On macOS, `gemini` uses Seatbelt (`sandbox-exec`) under a `permissive-open`
|
||||
profile (see `packages/cli/src/utils/sandbox-macos-permissive-open.sb`) that
|
||||
restricts writes to the project folder but otherwise allows all other operations
|
||||
and outbound network traffic ("open") by default. You can switch to a
|
||||
`restrictive-closed` profile (see
|
||||
`packages/cli/src/utils/sandbox-macos-restrictive-closed.sb`) that declines all
|
||||
operations and outbound network traffic ("closed") by default by setting
|
||||
`SEATBELT_PROFILE=restrictive-closed` in your environment or `.env` file.
|
||||
Available built-in profiles are `{permissive,restrictive}-{open,closed,proxied}`
|
||||
(see below for proxied networking). You can also switch to a custom profile
|
||||
`strict-open` profile (see
|
||||
`packages/cli/src/utils/sandbox-macos-strict-open.sb`) that restricts both reads
|
||||
and writes to the working directory while allowing outbound network traffic by
|
||||
setting `SEATBELT_PROFILE=strict-open` in your environment or `.env` file.
|
||||
Available built-in profiles are `permissive-{open,proxied}`,
|
||||
`restrictive-{open,proxied}`, and `strict-{open,proxied}` (see below for proxied
|
||||
networking). You can also switch to a custom profile
|
||||
`SEATBELT_PROFILE=<profile>` if you also create a file
|
||||
`.gemini/sandbox-macos-<profile>.sb` under your project settings directory
|
||||
`.gemini`.
|
||||
@@ -537,7 +568,7 @@ Before submitting your documentation pull request, please:
|
||||
|
||||
If you have questions about contributing documentation:
|
||||
|
||||
- Check our [FAQ](/docs/faq.md).
|
||||
- Check our [FAQ](https://geminicli.com/docs/resources/faq).
|
||||
- Review existing documentation for examples.
|
||||
- Open [an issue](https://github.com/google-gemini/gemini-cli/issues) to discuss
|
||||
your proposed changes.
|
||||
|
||||
+4
-1
@@ -42,7 +42,10 @@ USER node
|
||||
# install gemini-cli and clean up
|
||||
COPY packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz
|
||||
COPY packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz
|
||||
RUN npm install -g /tmp/gemini-cli.tgz /tmp/gemini-core.tgz \
|
||||
RUN npm install -g /tmp/gemini-core.tgz \
|
||||
&& npm install -g /tmp/gemini-cli.tgz \
|
||||
&& node -e "const fs=require('node:fs'); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json','utf8')); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json','utf8'));" \
|
||||
&& gemini --version > /dev/null \
|
||||
&& npm cache clean --force \
|
||||
&& rm -f /tmp/gemini-{cli,core}.tgz
|
||||
|
||||
|
||||
@@ -1,400 +1,94 @@
|
||||
## Building and running
|
||||
|
||||
Before submitting any changes, it is crucial to validate them by running the
|
||||
full preflight check. This command will build the repository, run all tests,
|
||||
check for type errors, and lint the code.
|
||||
|
||||
To run the full suite of checks, execute the following command:
|
||||
|
||||
```bash
|
||||
npm run preflight
|
||||
```
|
||||
|
||||
This single command ensures that your changes meet all the quality gates of the
|
||||
project. While you can run the individual steps (`build`, `test`, `typecheck`,
|
||||
`lint`) separately, it is highly recommended to use `npm run preflight` to
|
||||
ensure a comprehensive validation.
|
||||
|
||||
## Writing Tests
|
||||
|
||||
This project uses **Vitest** as its primary testing framework. When writing
|
||||
tests, aim to follow existing patterns. Key conventions include:
|
||||
|
||||
### Test Structure and Framework
|
||||
|
||||
- **Framework**: All tests are written using Vitest (`describe`, `it`, `expect`,
|
||||
`vi`).
|
||||
- **File Location**: Test files (`*.test.ts` for logic, `*.test.tsx` for React
|
||||
components) are co-located with the source files they test.
|
||||
- **Configuration**: Test environments are defined in `vitest.config.ts` files.
|
||||
- **Setup/Teardown**: Use `beforeEach` and `afterEach`. Commonly,
|
||||
`vi.resetAllMocks()` is called in `beforeEach` and `vi.restoreAllMocks()` in
|
||||
`afterEach`.
|
||||
|
||||
### Mocking (`vi` from Vitest)
|
||||
|
||||
- **ES Modules**: Mock with
|
||||
`vi.mock('module-name', async (importOriginal) => { ... })`. Use
|
||||
`importOriginal` for selective mocking.
|
||||
- _Example_:
|
||||
`vi.mock('os', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, homedir: vi.fn() }; });`
|
||||
- **Mocking Order**: For critical dependencies (e.g., `os`, `fs`) that affect
|
||||
module-level constants, place `vi.mock` at the _very top_ of the test file,
|
||||
before other imports.
|
||||
- **Hoisting**: Use `const myMock = vi.hoisted(() => vi.fn());` if a mock
|
||||
function needs to be defined before its use in a `vi.mock` factory.
|
||||
- **Mock Functions**: Create with `vi.fn()`. Define behavior with
|
||||
`mockImplementation()`, `mockResolvedValue()`, or `mockRejectedValue()`.
|
||||
- **Spying**: Use `vi.spyOn(object, 'methodName')`. Restore spies with
|
||||
`mockRestore()` in `afterEach`.
|
||||
|
||||
### Commonly Mocked Modules
|
||||
|
||||
- **Node.js built-ins**: `fs`, `fs/promises`, `os` (especially `os.homedir()`),
|
||||
`path`, `child_process` (`execSync`, `spawn`).
|
||||
- **External SDKs**: `@google/genai`, `@modelcontextprotocol/sdk`.
|
||||
- **Internal Project Modules**: Dependencies from other project packages are
|
||||
often mocked.
|
||||
|
||||
### React Component Testing (CLI UI - Ink)
|
||||
|
||||
- Use `render()` from `ink-testing-library`.
|
||||
- Assert output with `lastFrame()`.
|
||||
- Wrap components in necessary `Context.Provider`s.
|
||||
- Mock custom React hooks and complex child components using `vi.mock()`.
|
||||
|
||||
### Asynchronous Testing
|
||||
|
||||
- Use `async/await`.
|
||||
- For timers, use `vi.useFakeTimers()`, `vi.advanceTimersByTimeAsync()`,
|
||||
`vi.runAllTimersAsync()`.
|
||||
- Test promise rejections with `await expect(promise).rejects.toThrow(...)`.
|
||||
|
||||
### General Guidance
|
||||
|
||||
- When adding tests, first examine existing tests to understand and conform to
|
||||
established conventions.
|
||||
- Pay close attention to the mocks at the top of existing test files; they
|
||||
reveal critical dependencies and how they are managed in a test environment.
|
||||
|
||||
## Git Repo
|
||||
|
||||
The main branch for this project is called "main"
|
||||
|
||||
## JavaScript/TypeScript
|
||||
|
||||
When contributing to this React, Node, and TypeScript codebase, please
|
||||
prioritize the use of plain JavaScript objects with accompanying TypeScript
|
||||
interface or type declarations over JavaScript class syntax. This approach
|
||||
offers significant advantages, especially concerning interoperability with React
|
||||
and overall code maintainability.
|
||||
|
||||
### Preferring Plain Objects over Classes
|
||||
|
||||
JavaScript classes, by their nature, are designed to encapsulate internal state
|
||||
and behavior. While this can be useful in some object-oriented paradigms, it
|
||||
often introduces unnecessary complexity and friction when working with React's
|
||||
component-based architecture. Here's why plain objects are preferred:
|
||||
|
||||
- Seamless React Integration: React components thrive on explicit props and
|
||||
state management. Classes' tendency to store internal state directly within
|
||||
instances can make prop and state propagation harder to reason about and
|
||||
maintain. Plain objects, on the other hand, are inherently immutable (when
|
||||
used thoughtfully) and can be easily passed as props, simplifying data flow
|
||||
and reducing unexpected side effects.
|
||||
|
||||
- Reduced Boilerplate and Increased Conciseness: Classes often promote the use
|
||||
of constructors, this binding, getters, setters, and other boilerplate that
|
||||
can unnecessarily bloat code. TypeScript interface and type declarations
|
||||
provide powerful static type checking without the runtime overhead or
|
||||
verbosity of class definitions. This allows for more succinct and readable
|
||||
code, aligning with JavaScript's strengths in functional programming.
|
||||
|
||||
- Enhanced Readability and Predictability: Plain objects, especially when their
|
||||
structure is clearly defined by TypeScript interfaces, are often easier to
|
||||
read and understand. Their properties are directly accessible, and there's no
|
||||
hidden internal state or complex inheritance chains to navigate. This
|
||||
predictability leads to fewer bugs and a more maintainable codebase.
|
||||
|
||||
- Simplified Immutability: While not strictly enforced, plain objects encourage
|
||||
an immutable approach to data. When you need to modify an object, you
|
||||
typically create a new one with the desired changes, rather than mutating the
|
||||
original. This pattern aligns perfectly with React's reconciliation process
|
||||
and helps prevent subtle bugs related to shared mutable state.
|
||||
|
||||
- Better Serialization and Deserialization: Plain JavaScript objects are
|
||||
naturally easy to serialize to JSON and deserialize back, which is a common
|
||||
requirement in web development (e.g., for API communication or local storage).
|
||||
Classes, with their methods and prototypes, can complicate this process.
|
||||
|
||||
### Embracing ES Module Syntax for Encapsulation
|
||||
|
||||
Rather than relying on Java-esque private or public class members, which can be
|
||||
verbose and sometimes limit flexibility, we strongly prefer leveraging ES module
|
||||
syntax (`import`/`export`) for encapsulating private and public APIs.
|
||||
|
||||
- Clearer Public API Definition: With ES modules, anything that is exported is
|
||||
part of the public API of that module, while anything not exported is
|
||||
inherently private to that module. This provides a very clear and explicit way
|
||||
to define what parts of your code are meant to be consumed by other modules.
|
||||
|
||||
- Enhanced Testability (Without Exposing Internals): By default, unexported
|
||||
functions or variables are not accessible from outside the module. This
|
||||
encourages you to test the public API of your modules, rather than their
|
||||
internal implementation details. If you find yourself needing to spy on or
|
||||
stub an unexported function for testing purposes, it's often a "code smell"
|
||||
indicating that the function might be a good candidate for extraction into its
|
||||
own separate, testable module with a well-defined public API. This promotes a
|
||||
more robust and maintainable testing strategy.
|
||||
|
||||
- Reduced Coupling: Explicitly defined module boundaries through import/export
|
||||
help reduce coupling between different parts of your codebase. This makes it
|
||||
easier to refactor, debug, and understand individual components in isolation.
|
||||
|
||||
### Avoiding `any` Types and Type Assertions; Preferring `unknown`
|
||||
|
||||
TypeScript's power lies in its ability to provide static type checking, catching
|
||||
potential errors before your code runs. To fully leverage this, it's crucial to
|
||||
avoid the `any` type and be judicious with type assertions.
|
||||
|
||||
- **The Dangers of `any`**: Using any effectively opts out of TypeScript's type
|
||||
checking for that particular variable or expression. While it might seem
|
||||
convenient in the short term, it introduces significant risks:
|
||||
- **Loss of Type Safety**: You lose all the benefits of type checking, making
|
||||
it easy to introduce runtime errors that TypeScript would otherwise have
|
||||
caught.
|
||||
- **Reduced Readability and Maintainability**: Code with `any` types is harder
|
||||
to understand and maintain, as the expected type of data is no longer
|
||||
explicitly defined.
|
||||
- **Masking Underlying Issues**: Often, the need for any indicates a deeper
|
||||
problem in the design of your code or the way you're interacting with
|
||||
external libraries. It's a sign that you might need to refine your types or
|
||||
refactor your code.
|
||||
|
||||
- **Preferring `unknown` over `any`**: When you absolutely cannot determine the
|
||||
type of a value at compile time, and you're tempted to reach for any, consider
|
||||
using unknown instead. unknown is a type-safe counterpart to any. While a
|
||||
variable of type unknown can hold any value, you must perform type narrowing
|
||||
(e.g., using typeof or instanceof checks, or a type assertion) before you can
|
||||
perform any operations on it. This forces you to handle the unknown type
|
||||
explicitly, preventing accidental runtime errors.
|
||||
|
||||
```ts
|
||||
function processValue(value: unknown) {
|
||||
if (typeof value === 'string') {
|
||||
// value is now safely a string
|
||||
console.log(value.toUpperCase());
|
||||
} else if (typeof value === 'number') {
|
||||
// value is now safely a number
|
||||
console.log(value * 2);
|
||||
}
|
||||
// Without narrowing, you cannot access properties or methods on 'value'
|
||||
// console.log(value.someProperty); // Error: Object is of type 'unknown'.
|
||||
}
|
||||
```
|
||||
|
||||
- **Type Assertions (`as Type`) - Use with Caution**: Type assertions tell the
|
||||
TypeScript compiler, "Trust me, I know what I'm doing; this is definitely of
|
||||
this type." While there are legitimate use cases (e.g., when dealing with
|
||||
external libraries that don't have perfect type definitions, or when you have
|
||||
more information than the compiler), they should be used sparingly and with
|
||||
extreme caution.
|
||||
- **Bypassing Type Checking**: Like `any`, type assertions bypass TypeScript's
|
||||
safety checks. If your assertion is incorrect, you introduce a runtime error
|
||||
that TypeScript would not have warned you about.
|
||||
- **Code Smell in Testing**: A common scenario where `any` or type assertions
|
||||
might be tempting is when trying to test "private" implementation details
|
||||
(e.g., spying on or stubbing an unexported function within a module). This
|
||||
is a strong indication of a "code smell" in your testing strategy and
|
||||
potentially your code structure. Instead of trying to force access to
|
||||
private internals, consider whether those internal details should be
|
||||
refactored into a separate module with a well-defined public API. This makes
|
||||
them inherently testable without compromising encapsulation.
|
||||
|
||||
### Type narrowing `switch` clauses
|
||||
|
||||
Use the `checkExhaustive` helper in the default clause of a switch statement.
|
||||
This will ensure that all of the possible options within the value or
|
||||
enumeration are used.
|
||||
|
||||
This helper method can be found in `packages/cli/src/utils/checks.ts`
|
||||
|
||||
### Embracing JavaScript's Array Operators
|
||||
|
||||
To further enhance code cleanliness and promote safe functional programming
|
||||
practices, leverage JavaScript's rich set of array operators as much as
|
||||
possible. Methods like `.map()`, `.filter()`, `.reduce()`, `.slice()`,
|
||||
`.sort()`, and others are incredibly powerful for transforming and manipulating
|
||||
data collections in an immutable and declarative way.
|
||||
|
||||
Using these operators:
|
||||
|
||||
- Promotes Immutability: Most array operators return new arrays, leaving the
|
||||
original array untouched. This functional approach helps prevent unintended
|
||||
side effects and makes your code more predictable.
|
||||
- Improves Readability: Chaining array operators often lead to more concise and
|
||||
expressive code than traditional for loops or imperative logic. The intent of
|
||||
the operation is clear at a glance.
|
||||
- Facilitates Functional Programming: These operators are cornerstones of
|
||||
functional programming, encouraging the creation of pure functions that take
|
||||
inputs and produce outputs without causing side effects. This paradigm is
|
||||
highly beneficial for writing robust and testable code that pairs well with
|
||||
React.
|
||||
|
||||
By consistently applying these principles, we can maintain a codebase that is
|
||||
not only efficient and performant but also a joy to work with, both now and in
|
||||
the future.
|
||||
|
||||
## React (mirrored and adjusted from [react-mcp-server](https://github.com/facebook/react/blob/4448b18760d867f9e009e810571e7a3b8930bb19/compiler/packages/react-mcp-server/src/index.ts#L376C1-L441C94))
|
||||
|
||||
### Role
|
||||
|
||||
You are a React assistant that helps users write more efficient and optimizable
|
||||
React code. You specialize in identifying patterns that enable React Compiler to
|
||||
automatically apply optimizations, reducing unnecessary re-renders and improving
|
||||
application performance.
|
||||
|
||||
### Follow these guidelines in all code you produce and suggest
|
||||
|
||||
Use functional components with Hooks: Do not generate class components or use
|
||||
old lifecycle methods. Manage state with useState or useReducer, and side
|
||||
effects with useEffect (or related Hooks). Always prefer functions and Hooks for
|
||||
any new component logic.
|
||||
|
||||
Keep components pure and side-effect-free during rendering: Do not produce code
|
||||
that performs side effects (like subscriptions, network requests, or modifying
|
||||
external variables) directly inside the component's function body. Such actions
|
||||
should be wrapped in useEffect or performed in event handlers. Ensure your
|
||||
render logic is a pure function of props and state.
|
||||
|
||||
Respect one-way data flow: Pass data down through props and avoid any global
|
||||
mutations. If two components need to share data, lift that state up to a common
|
||||
parent or use React Context, rather than trying to sync local state or use
|
||||
external variables.
|
||||
|
||||
Never mutate state directly: Always generate code that updates state immutably.
|
||||
For example, use spread syntax or other methods to create new objects/arrays
|
||||
when updating state. Do not use assignments like state.someValue = ... or array
|
||||
mutations like array.push() on state variables. Use the state setter (setState
|
||||
from useState, etc.) to update state.
|
||||
|
||||
Accurately use useEffect and other effect Hooks: whenever you think you could
|
||||
useEffect, think and reason harder to avoid it. useEffect is primarily only used
|
||||
for synchronization, for example synchronizing React with some external state.
|
||||
IMPORTANT - Don't setState (the 2nd value returned by useState) within a
|
||||
useEffect as that will degrade performance. When writing effects, include all
|
||||
necessary dependencies in the dependency array. Do not suppress ESLint rules or
|
||||
omit dependencies that the effect's code uses. Structure the effect callbacks to
|
||||
handle changing values properly (e.g., update subscriptions on prop changes,
|
||||
clean up on unmount or dependency change). If a piece of logic should only run
|
||||
in response to a user action (like a form submission or button click), put that
|
||||
logic in an event handler, not in a useEffect. Where possible, useEffects should
|
||||
return a cleanup function.
|
||||
|
||||
Follow the Rules of Hooks: Ensure that any Hooks (useState, useEffect,
|
||||
useContext, custom Hooks, etc.) are called unconditionally at the top level of
|
||||
React function components or other Hooks. Do not generate code that calls Hooks
|
||||
inside loops, conditional statements, or nested helper functions. Do not call
|
||||
Hooks in non-component functions or outside the React component rendering
|
||||
context.
|
||||
|
||||
Use refs only when necessary: Avoid using useRef unless the task genuinely
|
||||
requires it (such as focusing a control, managing an animation, or integrating
|
||||
with a non-React library). Do not use refs to store application state that
|
||||
should be reactive. If you do use refs, never write to or read from ref.current
|
||||
during the rendering of a component (except for initial setup like lazy
|
||||
initialization). Any ref usage should not affect the rendered output directly.
|
||||
|
||||
Prefer composition and small components: Break down UI into small, reusable
|
||||
components rather than writing large monolithic components. The code you
|
||||
generate should promote clarity and reusability by composing components
|
||||
together. Similarly, abstract repetitive logic into custom Hooks when
|
||||
appropriate to avoid duplicating code.
|
||||
|
||||
Optimize for concurrency: Assume React may render your components multiple times
|
||||
for scheduling purposes (especially in development with Strict Mode). Write code
|
||||
that remains correct even if the component function runs more than once. For
|
||||
instance, avoid side effects in the component body and use functional state
|
||||
updates (e.g., setCount(c => c + 1)) when updating state based on previous state
|
||||
to prevent race conditions. Always include cleanup functions in effects that
|
||||
subscribe to external resources. Don't write useEffects for "do this when this
|
||||
changes" side effects. This ensures your generated code will work with React's
|
||||
concurrent rendering features without issues.
|
||||
|
||||
Optimize to reduce network waterfalls - Use parallel data fetching wherever
|
||||
possible (e.g., start multiple requests at once rather than one after another).
|
||||
Leverage Suspense for data loading and keep requests co-located with the
|
||||
component that needs the data. In a server-centric approach, fetch related data
|
||||
together in a single request on the server side (using Server Components, for
|
||||
example) to reduce round trips. Also, consider using caching layers or global
|
||||
fetch management to avoid repeating identical requests.
|
||||
|
||||
Rely on React Compiler - useMemo, useCallback, and React.memo can be omitted if
|
||||
React Compiler is enabled. Avoid premature optimization with manual memoization.
|
||||
Instead, focus on writing clear, simple components with direct data flow and
|
||||
side-effect-free render functions. Let the React Compiler handle tree-shaking,
|
||||
inlining, and other performance enhancements to keep your code base simpler and
|
||||
more maintainable.
|
||||
|
||||
Design for a good user experience - Provide clear, minimal, and non-blocking UI
|
||||
states. When data is loading, show lightweight placeholders (e.g., skeleton
|
||||
screens) rather than intrusive spinners everywhere. Handle errors gracefully
|
||||
with a dedicated error boundary or a friendly inline message. Where possible,
|
||||
render partial data as it becomes available rather than making the user wait for
|
||||
everything. Suspense allows you to declare the loading states in your component
|
||||
tree in a natural way, preventing “flash” states and improving perceived
|
||||
performance.
|
||||
|
||||
### Process
|
||||
|
||||
1. Analyze the user's code for optimization opportunities:
|
||||
- Check for React anti-patterns that prevent compiler optimization
|
||||
- Look for component structure issues that limit compiler effectiveness
|
||||
- Think about each suggestion you are making and consult React docs for best
|
||||
practices
|
||||
|
||||
2. Provide actionable guidance:
|
||||
- Explain specific code changes with clear reasoning
|
||||
- Show before/after examples when suggesting changes
|
||||
- Only suggest changes that meaningfully improve optimization potential
|
||||
|
||||
### Optimization Guidelines
|
||||
|
||||
- State updates should be structured to enable granular updates
|
||||
- Side effects should be isolated and dependencies clearly defined
|
||||
|
||||
## Documentation guidelines
|
||||
|
||||
When working in the `/docs` directory, follow the guidelines in this section:
|
||||
|
||||
- **Role:** You are an expert technical writer and AI assistant for contributors
|
||||
to Gemini CLI. Produce professional, accurate, and consistent documentation to
|
||||
guide users of Gemini CLI.
|
||||
- **Technical Accuracy:** Do not invent facts, commands, code, API names, or
|
||||
output. All technical information specific to Gemini CLI must be based on code
|
||||
found within this directory and its subdirectories.
|
||||
- **Style Authority:** Your source for writing guidance and style is the
|
||||
"Documentation contribution process" section in the root directory's
|
||||
`CONTRIBUTING.md` file, as well as any guidelines provided this section.
|
||||
- **Information Architecture Consideration:** Before proposing documentation
|
||||
changes, consider the information architecture. If a change adds significant
|
||||
new content to existing documents, evaluate if creating a new, more focused
|
||||
page or changes to `sidebar.json` would provide a better user experience.
|
||||
- **Proactive User Consideration:** The user experience should be a primary
|
||||
concern when making changes to documentation. Aim to fill gaps in existing
|
||||
knowledge whenever possible while keeping documentation concise and easy for
|
||||
users to understand. If changes might hinder user understanding or
|
||||
accessibility, proactively raise these concerns and propose alternatives.
|
||||
|
||||
## Comments policy
|
||||
|
||||
Only write high-value comments if at all. Avoid talking to the user through
|
||||
comments.
|
||||
|
||||
## General requirements
|
||||
|
||||
- If there is something you do not understand or is ambiguous, seek confirmation
|
||||
or clarification from the user before making changes based on assumptions.
|
||||
- Use hyphens instead of underscores in flag names (e.g. `my-flag` instead of
|
||||
`my_flag`).
|
||||
- Always refer to Gemini CLI as `Gemini CLI`, never `the Gemini CLI`.
|
||||
# Gemini CLI Project Context
|
||||
|
||||
Gemini CLI is an open-source AI agent that brings the power of Gemini directly
|
||||
into the terminal. It is designed to be a terminal-first, extensible, and
|
||||
powerful tool for developers.
|
||||
|
||||
## Project Overview
|
||||
|
||||
- **Purpose:** Provide a seamless terminal interface for Gemini models,
|
||||
supporting code understanding, generation, automation, and integration via MCP
|
||||
(Model Context Protocol).
|
||||
- **Main Technologies:**
|
||||
- **Runtime:** Node.js (>=20.0.0, recommended ~20.19.0 for development)
|
||||
- **Language:** TypeScript
|
||||
- **UI Framework:** React (using [Ink](https://github.com/vadimdemedes/ink)
|
||||
for CLI rendering)
|
||||
- **Testing:** Vitest
|
||||
- **Bundling:** esbuild
|
||||
- **Linting/Formatting:** ESLint, Prettier
|
||||
- **Architecture:** Monorepo structure using npm workspaces.
|
||||
- `packages/cli`: User-facing terminal UI, input processing, and display
|
||||
rendering.
|
||||
- `packages/core`: Backend logic, Gemini API orchestration, prompt
|
||||
construction, and tool execution.
|
||||
- `packages/core/src/tools/`: Built-in tools for file system, shell, and web
|
||||
operations.
|
||||
- `packages/a2a-server`: Experimental Agent-to-Agent server.
|
||||
- `packages/vscode-ide-companion`: VS Code extension pairing with the CLI.
|
||||
|
||||
## Building and Running
|
||||
|
||||
- **Install Dependencies:** `npm install`
|
||||
- **Build All:** `npm run build:all` (Builds packages, sandbox, and VS Code
|
||||
companion)
|
||||
- **Build Packages:** `npm run build`
|
||||
- **Run in Development:** `npm run start`
|
||||
- **Run in Debug Mode:** `npm run debug` (Enables Node.js inspector)
|
||||
- **Bundle Project:** `npm run bundle`
|
||||
- **Clean Artifacts:** `npm run clean`
|
||||
|
||||
## Testing and Quality
|
||||
|
||||
- **Test Commands:**
|
||||
- **Unit (All):** `npm run test`
|
||||
- **Integration (E2E):** `npm run test:e2e`
|
||||
- **Workspace-Specific:** `npm test -w <pkg> -- <path>` (Note: `<path>` must
|
||||
be relative to the workspace root, e.g.,
|
||||
`-w @google/gemini-cli-core -- src/routing/modelRouterService.test.ts`)
|
||||
- **Full Validation:** `npm run preflight` (Heaviest check; runs clean, install,
|
||||
build, lint, type check, and tests. Recommended before submitting PRs. Due to
|
||||
its long runtime, only run this at the very end of a code implementation task.
|
||||
If it fails, use faster, targeted commands (e.g., `npm run test`,
|
||||
`npm run lint`, or workspace-specific tests) to iterate on fixes before
|
||||
re-running `preflight`. For simple, non-code changes like documentation or
|
||||
prompting updates, skip `preflight` at the end of the task and wait for PR
|
||||
validation.)
|
||||
- **Individual Checks:** `npm run lint` / `npm run format` / `npm run typecheck`
|
||||
|
||||
## Development Conventions
|
||||
|
||||
- **Legacy Snippets:** `packages/core/src/prompts/snippets.legacy.ts` is a
|
||||
snapshot of an older system prompt. Avoid changing the prompting verbiage to
|
||||
preserve its historical behavior; however, structural changes to ensure
|
||||
compilation or simplify the code are permitted.
|
||||
- **Contributions:** Follow the process outlined in `CONTRIBUTING.md`. Requires
|
||||
signing the Google CLA.
|
||||
- **Pull Requests:** Keep PRs small, focused, and linked to an existing issue.
|
||||
Always activate the `pr-creator` skill for PR generation, even when using the
|
||||
`gh` CLI.
|
||||
- **Commit Messages:** Follow the
|
||||
[Conventional Commits](https://www.conventionalcommits.org/) standard.
|
||||
- **Coding Style:** Adhere to existing patterns in `packages/cli` (React/Ink)
|
||||
and `packages/core` (Backend logic).
|
||||
- **Imports:** Use specific imports and avoid restricted relative imports
|
||||
between packages (enforced by ESLint).
|
||||
- **License Headers:** For all new source code files (`.ts`, `.tsx`, `.js`),
|
||||
include the Apache-2.0 license header with the current year. (e.g.,
|
||||
`Copyright 2026 Google LLC`). This is enforced by ESLint.
|
||||
|
||||
## Testing Conventions
|
||||
|
||||
- **Environment Variables:** When testing code that depends on environment
|
||||
variables, use `vi.stubEnv('NAME', 'value')` in `beforeEach` and
|
||||
`vi.unstubAllEnvs()` in `afterEach`. Avoid modifying `process.env` directly as
|
||||
it can lead to test leakage and is less reliable. To "unset" a variable, use
|
||||
an empty string `vi.stubEnv('NAME', '')`.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Always use the `docs-writer` skill when you are asked to write, edit, or
|
||||
review any documentation.
|
||||
- Documentation is located in the `docs/` directory.
|
||||
- Suggest documentation updates when code changes render existing documentation
|
||||
obsolete or incomplete.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[](https://github.com/google-gemini/gemini-cli/actions/workflows/chained_e2e.yml)
|
||||
[](https://www.npmjs.com/package/@google/gemini-cli)
|
||||
[](https://github.com/google-gemini/gemini-cli/blob/main/LICENSE)
|
||||
[](https://codewiki.google/github.com/google-gemini/gemini-cli)
|
||||
[](https://codewiki.google/github.com/google-gemini/gemini-cli?utm_source=badge&utm_medium=github&utm_campaign=github.com/google-gemini/gemini-cli)
|
||||
|
||||

|
||||
|
||||
@@ -18,7 +18,8 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
|
||||
|
||||
- **🎯 Free tier**: 60 requests/min and 1,000 requests/day with personal Google
|
||||
account.
|
||||
- **🧠 Powerful Gemini 2.5 Pro**: Access to 1M token context window.
|
||||
- **🧠 Powerful Gemini 3 models**: Access to improved reasoning and 1M token
|
||||
context window.
|
||||
- **🔧 Built-in tools**: Google Search grounding, file operations, shell
|
||||
commands, web fetching.
|
||||
- **🔌 Extensible**: MCP (Model Context Protocol) support for custom
|
||||
@@ -28,10 +29,9 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
### Pre-requisites before installation
|
||||
|
||||
- Node.js version 20 or higher
|
||||
- macOS, Linux, or Windows
|
||||
See
|
||||
[Gemini CLI installation, execution, and releases](./docs/get-started/installation.md)
|
||||
for recommended system specifications and a detailed installation guide.
|
||||
|
||||
### Quick Install
|
||||
|
||||
@@ -39,7 +39,7 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
|
||||
|
||||
```bash
|
||||
# Using npx (no installation required)
|
||||
npx https://github.com/google-gemini/gemini-cli
|
||||
npx @google/gemini-cli
|
||||
```
|
||||
|
||||
#### Install globally with npm
|
||||
@@ -54,13 +54,30 @@ npm install -g @google/gemini-cli
|
||||
brew install gemini-cli
|
||||
```
|
||||
|
||||
#### Install globally with MacPorts (macOS)
|
||||
|
||||
```bash
|
||||
sudo port install gemini-cli
|
||||
```
|
||||
|
||||
#### Install with Anaconda (for restricted environments)
|
||||
|
||||
```bash
|
||||
# Create and activate a new environment
|
||||
conda create -y -n gemini_env -c conda-forge nodejs
|
||||
conda activate gemini_env
|
||||
|
||||
# Install Gemini CLI globally via npm (inside the environment)
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
## Release Cadence and Tags
|
||||
|
||||
See [Releases](./docs/releases.md) for more details.
|
||||
|
||||
### Preview
|
||||
|
||||
New preview releases will be published each week at UTC 2359 on Tuesdays. These
|
||||
New preview releases will be published each week at UTC 23:59 on Tuesdays. These
|
||||
releases will not have been fully vetted and may contain regressions or other
|
||||
outstanding issues. Please help us test and install with `preview` tag.
|
||||
|
||||
@@ -70,7 +87,7 @@ npm install -g @google/gemini-cli@preview
|
||||
|
||||
### Stable
|
||||
|
||||
- New stable releases will be published each week at UTC 2000 on Tuesdays, this
|
||||
- New stable releases will be published each week at UTC 20:00 on Tuesdays, this
|
||||
will be the full promotion of last week's `preview` release + any bug fixes
|
||||
and validations. Use `latest` tag.
|
||||
|
||||
@@ -80,7 +97,7 @@ npm install -g @google/gemini-cli@latest
|
||||
|
||||
### Nightly
|
||||
|
||||
- New releases will be published each day at UTC 0000. This will be all changes
|
||||
- New releases will be published each day at UTC 00:00. This will be all changes
|
||||
from the main branch as represented at time of release. It should be assumed
|
||||
there are pending validations and issues. Use `nightly` tag.
|
||||
|
||||
@@ -140,7 +157,7 @@ for details)
|
||||
**Benefits:**
|
||||
|
||||
- **Free tier**: 60 requests/min and 1,000 requests/day
|
||||
- **Gemini 2.5 Pro** with 1M token context window
|
||||
- **Gemini 3 models** with 1M token context window
|
||||
- **No API key management** - just sign in with your Google account
|
||||
- **Automatic updates** to latest models
|
||||
|
||||
@@ -164,7 +181,7 @@ gemini
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- **Free tier**: 100 requests/day with Gemini 2.5 Pro
|
||||
- **Free tier**: 1000 requests/day with Gemini 3 (mix of flash and pro)
|
||||
- **Model selection**: Choose specific Gemini models
|
||||
- **Usage-based billing**: Upgrade for higher limits when needed
|
||||
|
||||
@@ -265,14 +282,14 @@ gemini
|
||||
quickly.
|
||||
- [**Authentication Setup**](./docs/get-started/authentication.md) - Detailed
|
||||
auth configuration.
|
||||
- [**Configuration Guide**](./docs/get-started/configuration.md) - Settings and
|
||||
- [**Configuration Guide**](./docs/reference/configuration.md) - Settings and
|
||||
customization.
|
||||
- [**Keyboard Shortcuts**](./docs/cli/keyboard-shortcuts.md) - Productivity
|
||||
tips.
|
||||
- [**Keyboard Shortcuts**](./docs/reference/keyboard-shortcuts.md) -
|
||||
Productivity tips.
|
||||
|
||||
### Core Features
|
||||
|
||||
- [**Commands Reference**](./docs/cli/commands.md) - All slash commands
|
||||
- [**Commands Reference**](./docs/reference/commands.md) - All slash commands
|
||||
(`/help`, `/chat`, etc).
|
||||
- [**Custom Commands**](./docs/cli/custom-commands.md) - Create your own
|
||||
reusable commands.
|
||||
@@ -284,7 +301,7 @@ gemini
|
||||
|
||||
### Tools & Extensions
|
||||
|
||||
- [**Built-in Tools Overview**](./docs/tools/index.md)
|
||||
- [**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)
|
||||
@@ -306,15 +323,15 @@ gemini
|
||||
- [**Enterprise Guide**](./docs/cli/enterprise.md) - Deploy and manage in a
|
||||
corporate environment.
|
||||
- [**Telemetry & Monitoring**](./docs/cli/telemetry.md) - Usage tracking.
|
||||
- [**Tools API Development**](./docs/core/tools-api.md) - Create custom tools.
|
||||
- [**Tools reference**](./docs/reference/tools.md) - Built-in tools overview.
|
||||
- [**Local development**](./docs/local-development.md) - Local development
|
||||
tooling.
|
||||
|
||||
### Troubleshooting & Support
|
||||
|
||||
- [**Troubleshooting Guide**](./docs/troubleshooting.md) - Common issues and
|
||||
solutions.
|
||||
- [**FAQ**](./docs/faq.md) - Frequently asked questions.
|
||||
- [**Troubleshooting Guide**](./docs/resources/troubleshooting.md) - Common
|
||||
issues and solutions.
|
||||
- [**FAQ**](./docs/resources/faq.md) - Frequently asked questions.
|
||||
- Use `/bug` command to report issues directly from the CLI.
|
||||
|
||||
### Using MCP Servers
|
||||
@@ -360,12 +377,13 @@ for planned features and priorities.
|
||||
|
||||
### Uninstall
|
||||
|
||||
See the [Uninstall Guide](docs/cli/uninstall.md) for removal instructions.
|
||||
See the [Uninstall Guide](./docs/resources/uninstall.md) for removal
|
||||
instructions.
|
||||
|
||||
## 📄 Legal
|
||||
|
||||
- **License**: [Apache License 2.0](LICENSE)
|
||||
- **Terms of Service**: [Terms & Privacy](./docs/tos-privacy.md)
|
||||
- **Terms of Service**: [Terms & Privacy](./docs/resources/tos-privacy.md)
|
||||
- **Security**: [Security Policy](SECURITY.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# Enterprise Admin Controls
|
||||
|
||||
Gemini CLI empowers enterprise administrators to manage and enforce security
|
||||
policies and configuration settings across their entire organization. Secure
|
||||
defaults are enabled automatically for all enterprise users, but can be
|
||||
customized via the [Management Console](https://goo.gle/manage-gemini-cli).
|
||||
|
||||
**Enterprise Admin Controls are enforced globally and cannot be overridden by
|
||||
users locally**, ensuring a consistent security posture.
|
||||
|
||||
## Admin Controls vs. System Settings
|
||||
|
||||
While [System-wide settings](../cli/settings.md) act as convenient configuration
|
||||
overrides, they can still be modified by users with sufficient privileges. In
|
||||
contrast, admin controls are immutable at the local level, making them the
|
||||
preferred method for enforcing policy.
|
||||
|
||||
## Available Controls
|
||||
|
||||
### Strict Mode
|
||||
|
||||
**Enabled/Disabled** | Default: enabled
|
||||
|
||||
If enabled, users will not be able to enter yolo mode.
|
||||
|
||||
### Extensions
|
||||
|
||||
**Enabled/Disabled** | Default: disabled
|
||||
|
||||
If disabled, users will not be able to use or install extensions. See
|
||||
[Extensions](../extensions/index.md) for more details.
|
||||
|
||||
### MCP
|
||||
|
||||
#### Enabled/Disabled
|
||||
|
||||
**Enabled/Disabled** | Default: disabled
|
||||
|
||||
If disabled, users will not be able to use MCP servers. See
|
||||
[MCP Server Integration](../tools/mcp-server.md) for more details.
|
||||
|
||||
#### MCP Servers (preview)
|
||||
|
||||
**Default**: empty
|
||||
|
||||
Allows administrators to define an explicit allowlist of MCP servers. This
|
||||
guarantees that users can only connect to trusted MCP servers defined by the
|
||||
organization.
|
||||
|
||||
**Allowlist Format:**
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"external-provider": {
|
||||
"url": "https://api.mcp-provider.com",
|
||||
"type": "sse",
|
||||
"trust": true,
|
||||
"includeTools": ["toolA", "toolB"],
|
||||
"excludeTools": []
|
||||
},
|
||||
"internal-corp-tool": {
|
||||
"url": "https://mcp.internal-tool.corp",
|
||||
"type": "http",
|
||||
"includeTools": [],
|
||||
"excludeTools": ["adminTool"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Supported Fields:**
|
||||
|
||||
- `url`: (Required) The full URL of the MCP server endpoint.
|
||||
- `type`: (Required) The connection type (e.g., `sse` or `http`).
|
||||
- `trust`: (Optional) If set to `true`, the server is trusted and tool execution
|
||||
will not require user approval.
|
||||
- `includeTools`: (Optional) An explicit list of tool names to allow. If
|
||||
specified, only these tools will be available.
|
||||
- `excludeTools`: (Optional) A list of tool names to hide. These tools will be
|
||||
blocked.
|
||||
|
||||
**Client Enforcement Logic:**
|
||||
|
||||
- **Empty Allowlist**: If the admin allowlist is empty, the client uses the
|
||||
user’s local configuration as is (unless the MCP toggle above is disabled).
|
||||
- **Active Allowlist**: If the allowlist contains one or more servers, **all
|
||||
locally configured servers not present in the allowlist are ignored**.
|
||||
- **Configuration Merging**: For a server to be active, it must exist in
|
||||
**both** the admin allowlist and the user’s local configuration (matched by
|
||||
name). The client merges these definitions as follows:
|
||||
- **Override Fields**: The `url`, `type`, & `trust` are always taken from the
|
||||
admin allowlist, overriding any local values.
|
||||
- **Tools Filtering**: If `includeTools` or `excludeTools` are defined in the
|
||||
allowlist, the admin’s rules are used exclusively. If both are undefined in
|
||||
the admin allowlist, the client falls back to the user’s local tool
|
||||
settings.
|
||||
- **Cleared Fields**: To ensure security and consistency, the client
|
||||
automatically clears local execution fields (`command`, `args`, `env`,
|
||||
`cwd`, `httpUrl`, `tcp`). This prevents users from overriding the connection
|
||||
method.
|
||||
- **Other Fields**: All other MCP fields are pulled from the user’s local
|
||||
configuration.
|
||||
- **Missing Allowlisted Servers**: If a server appears in the admin allowlist
|
||||
but is missing from the local configuration, it will not be initialized. This
|
||||
ensures users maintain final control over which permitted servers are actually
|
||||
active in their environment.
|
||||
|
||||
### Unmanaged Capabilities
|
||||
|
||||
**Enabled/Disabled** | Default: disabled
|
||||
|
||||
If disabled, users will not be able to use certain features. Currently, this
|
||||
control disables Agent Skills. See [Agent Skills](../cli/skills.md) for more
|
||||
details.
|
||||
@@ -1,80 +0,0 @@
|
||||
# Gemini CLI Architecture Overview
|
||||
|
||||
This document provides a high-level overview of the Gemini CLI's architecture.
|
||||
|
||||
## Core components
|
||||
|
||||
The Gemini CLI is primarily composed of two main packages, along with a suite of
|
||||
tools that can be used by the system in the course of handling command-line
|
||||
input:
|
||||
|
||||
1. **CLI package (`packages/cli`):**
|
||||
- **Purpose:** This contains the user-facing portion of the Gemini CLI, such
|
||||
as handling the initial user input, presenting the final output, and
|
||||
managing the overall user experience.
|
||||
- **Key functions contained in the package:**
|
||||
- [Input processing](/docs/cli/commands.md)
|
||||
- History management
|
||||
- Display rendering
|
||||
- [Theme and UI customization](/docs/cli/themes.md)
|
||||
- [CLI configuration settings](/docs/get-started/configuration.md)
|
||||
|
||||
2. **Core package (`packages/core`):**
|
||||
- **Purpose:** This acts as the backend for the Gemini CLI. It receives
|
||||
requests sent from `packages/cli`, orchestrates interactions with the
|
||||
Gemini API, and manages the execution of available tools.
|
||||
- **Key functions contained in the package:**
|
||||
- API client for communicating with the Google Gemini API
|
||||
- Prompt construction and management
|
||||
- Tool registration and execution logic
|
||||
- State management for conversations or sessions
|
||||
- Server-side configuration
|
||||
|
||||
3. **Tools (`packages/core/src/tools/`):**
|
||||
- **Purpose:** These are individual modules that extend the capabilities of
|
||||
the Gemini model, allowing it to interact with the local environment
|
||||
(e.g., file system, shell commands, web fetching).
|
||||
- **Interaction:** `packages/core` invokes these tools based on requests
|
||||
from the Gemini model.
|
||||
|
||||
## Interaction flow
|
||||
|
||||
A typical interaction with the Gemini CLI follows this flow:
|
||||
|
||||
1. **User input:** The user types a prompt or command into the terminal, which
|
||||
is managed by `packages/cli`.
|
||||
2. **Request to core:** `packages/cli` sends the user's input to
|
||||
`packages/core`.
|
||||
3. **Request processed:** The core package:
|
||||
- Constructs an appropriate prompt for the Gemini API, possibly including
|
||||
conversation history and available tool definitions.
|
||||
- Sends the prompt to the Gemini API.
|
||||
4. **Gemini API response:** The Gemini API processes the prompt and returns a
|
||||
response. This response might be a direct answer or a request to use one of
|
||||
the available tools.
|
||||
5. **Tool execution (if applicable):**
|
||||
- When the Gemini API requests a tool, the core package prepares to execute
|
||||
it.
|
||||
- If the requested tool can modify the file system or execute shell
|
||||
commands, the user is first given details of the tool and its arguments,
|
||||
and the user must approve the execution.
|
||||
- Read-only operations, such as reading files, might not require explicit
|
||||
user confirmation to proceed.
|
||||
- Once confirmed, or if confirmation is not required, the core package
|
||||
executes the relevant action within the relevant tool, and the result is
|
||||
sent back to the Gemini API by the core package.
|
||||
- The Gemini API processes the tool result and generates a final response.
|
||||
6. **Response to CLI:** The core package sends the final response back to the
|
||||
CLI package.
|
||||
7. **Display to user:** The CLI package formats and displays the response to
|
||||
the user in the terminal.
|
||||
|
||||
## Key design principles
|
||||
|
||||
- **Modularity:** Separating the CLI (frontend) from the Core (backend) allows
|
||||
for independent development and potential future extensions (e.g., different
|
||||
frontends for the same backend).
|
||||
- **Extensibility:** The tool system is designed to be extensible, allowing new
|
||||
capabilities to be added.
|
||||
- **User experience:** The CLI focuses on providing a rich and interactive
|
||||
terminal experience.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 110 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
+278
-3
@@ -18,6 +18,279 @@ on GitHub.
|
||||
| [Preview](preview.md) | Experimental features ready for early feedback. |
|
||||
| [Stable](latest.md) | Stable, recommended for general use. |
|
||||
|
||||
## Announcements: v0.32.0 - 2026-03-03
|
||||
|
||||
- **Generalist Agent:** The generalist agent is now enabled to improve task
|
||||
delegation and routing
|
||||
([#19665](https://github.com/google-gemini/gemini-cli/pull/19665) by
|
||||
@joshualitt).
|
||||
- **Model Steering in Workspace:** Added support for model steering directly in
|
||||
the workspace
|
||||
([#20343](https://github.com/google-gemini/gemini-cli/pull/20343) by
|
||||
@joshualitt).
|
||||
- **Plan Mode Enhancements:** Users can now open and modify plans in an external
|
||||
editor, and the planning workflow has been adapted to handle complex tasks
|
||||
more effectively with multi-select options
|
||||
([#20348](https://github.com/google-gemini/gemini-cli/pull/20348) by @Adib234,
|
||||
[#20465](https://github.com/google-gemini/gemini-cli/pull/20465) by @jerop).
|
||||
- **Interactive Shell Autocompletion:** Introduced interactive shell
|
||||
autocompletion for a more seamless experience
|
||||
([#20082](https://github.com/google-gemini/gemini-cli/pull/20082) by
|
||||
@mrpmohiburrahman).
|
||||
- **Parallel Extension Loading:** Extensions are now loaded in parallel to
|
||||
improve startup times
|
||||
([#20229](https://github.com/google-gemini/gemini-cli/pull/20229) by
|
||||
@scidomino).
|
||||
|
||||
## Announcements: v0.31.0 - 2026-02-27
|
||||
|
||||
- **Gemini 3.1 Pro Preview:** Gemini CLI now supports the new Gemini 3.1 Pro
|
||||
Preview model
|
||||
([#19676](https://github.com/google-gemini/gemini-cli/pull/19676) by
|
||||
@sehoon38).
|
||||
- **Experimental Browser Agent:** We've introduced a new experimental browser
|
||||
agent to interact with web pages
|
||||
([#19284](https://github.com/google-gemini/gemini-cli/pull/19284) by
|
||||
@gsquared94).
|
||||
- **Policy Engine Updates:** The policy engine now supports project-level
|
||||
policies, MCP server wildcards, and tool annotation matching
|
||||
([#18682](https://github.com/google-gemini/gemini-cli/pull/18682) by
|
||||
@Abhijit-2592,
|
||||
[#20024](https://github.com/google-gemini/gemini-cli/pull/20024) by @jerop).
|
||||
- **Web Fetch Improvements:** We've implemented an experimental direct web fetch
|
||||
feature and added rate limiting to mitigate DDoS risks
|
||||
([#19557](https://github.com/google-gemini/gemini-cli/pull/19557) by @mbleigh,
|
||||
[#19567](https://github.com/google-gemini/gemini-cli/pull/19567) by
|
||||
@mattKorwel).
|
||||
|
||||
## Announcements: v0.30.0 - 2026-02-25
|
||||
|
||||
- **SDK & Custom Skills:** Introduced the initial SDK package, enabling dynamic
|
||||
system instructions, `SessionContext` for SDK tool calls, and support for
|
||||
custom skills
|
||||
([#18861](https://github.com/google-gemini/gemini-cli/pull/18861) by
|
||||
@mbleigh).
|
||||
- **Policy Engine Enhancements:** Added a new `--policy` flag for user-defined
|
||||
policies, introduced strict seatbelt profiles, and deprecated
|
||||
`--allowed-tools` in favor of the policy engine
|
||||
([#18500](https://github.com/google-gemini/gemini-cli/pull/18500) by
|
||||
@allenhutchison).
|
||||
- **UI & Themes:** Added a generic searchable list for settings and extensions,
|
||||
new Solarized themes, text wrapping for markdown tables, and a clean UI toggle
|
||||
prototype ([#19064](https://github.com/google-gemini/gemini-cli/pull/19064) by
|
||||
@rmedranollamas).
|
||||
- **Vim & Terminal Interaction:** Improved Vim support to feel more complete and
|
||||
added support for Ctrl-Z terminal suspension
|
||||
([#18755](https://github.com/google-gemini/gemini-cli/pull/18755) by
|
||||
@ppgranger, [#18931](https://github.com/google-gemini/gemini-cli/pull/18931)
|
||||
by @scidomino).
|
||||
|
||||
## Announcements: v0.29.0 - 2026-02-17
|
||||
|
||||
- **Plan Mode:** A new comprehensive planning capability with `/plan`,
|
||||
`enter_plan_mode` tool, and dedicated documentation
|
||||
([#17698](https://github.com/google-gemini/gemini-cli/pull/17698) by @Adib234,
|
||||
[#18324](https://github.com/google-gemini/gemini-cli/pull/18324) by @jerop).
|
||||
- **Gemini 3 Default:** We've removed the preview flag and enabled Gemini 3 by
|
||||
default for all users
|
||||
([#18414](https://github.com/google-gemini/gemini-cli/pull/18414) by
|
||||
@sehoon38).
|
||||
- **Extension Exploration:** New UI and settings to explore and manage
|
||||
extensions more easily
|
||||
([#18686](https://github.com/google-gemini/gemini-cli/pull/18686) by
|
||||
@sripasg).
|
||||
- **Admin Control:** Administrators can now allowlist specific MCP server
|
||||
configurations
|
||||
([#18311](https://github.com/google-gemini/gemini-cli/pull/18311) by
|
||||
@skeshive).
|
||||
|
||||
## Announcements: v0.28.0 - 2026-02-10
|
||||
|
||||
- **Slash Command:** We've added a new `/prompt-suggest` slash command to help
|
||||
you generate prompt suggestions
|
||||
([#17264](https://github.com/google-gemini/gemini-cli/pull/17264) by
|
||||
@NTaylorMullen).
|
||||
- **IDE Support:** Gemini CLI now supports the Positron IDE
|
||||
([#15047](https://github.com/google-gemini/gemini-cli/pull/15047) by
|
||||
@kapsner).
|
||||
- **Customization:** You can now use custom themes in extensions, and we've
|
||||
implemented automatic theme switching based on your terminal's background
|
||||
([#17327](https://github.com/google-gemini/gemini-cli/pull/17327) by
|
||||
@spencer426, [#17976](https://github.com/google-gemini/gemini-cli/pull/17976)
|
||||
by @Abhijit-2592).
|
||||
- **Authentication:** We've added interactive and non-interactive consent for
|
||||
OAuth, and you can now include your auth method in bug reports
|
||||
([#17699](https://github.com/google-gemini/gemini-cli/pull/17699) by
|
||||
@ehedlund, [#17569](https://github.com/google-gemini/gemini-cli/pull/17569) by
|
||||
@erikus).
|
||||
|
||||
## Announcements: v0.27.0 - 2026-02-03
|
||||
|
||||
- **Event-Driven Architecture:** The CLI now uses a new event-driven scheduler
|
||||
for tool execution, resulting in a more responsive and performant experience
|
||||
([#17078](https://github.com/google-gemini/gemini-cli/pull/17078) by
|
||||
@abhipatel12).
|
||||
- **Enhanced User Experience:** This release includes queued tool confirmations,
|
||||
and expandable large text pastes for a smoother workflow.
|
||||
- **New `/rewind` Command:** Easily navigate your session history with the new
|
||||
`/rewind` command
|
||||
([#15720](https://github.com/google-gemini/gemini-cli/pull/15720) by
|
||||
@Adib234).
|
||||
- **Linux Clipboard Support:** You can now paste images on Linux with Wayland
|
||||
and X11 ([#17144](https://github.com/google-gemini/gemini-cli/pull/17144) by
|
||||
@devr0306).
|
||||
|
||||
## Announcements: v0.26.0 - 2026-01-27
|
||||
|
||||
- **Agents and Skills:** We've introduced a new `skill-creator` skill
|
||||
([#16394](https://github.com/google-gemini/gemini-cli/pull/16394) by
|
||||
@NTaylorMullen), enabled agent skills by default, and added a generalist agent
|
||||
to improve task routing
|
||||
([#16638](https://github.com/google-gemini/gemini-cli/pull/16638) by
|
||||
@joshualitt).
|
||||
- **UI/UX Improvements:** You can now "Rewind" through your conversation history
|
||||
([#15717](https://github.com/google-gemini/gemini-cli/pull/15717) by @Adib234)
|
||||
and use a new `/introspect` command for debugging.
|
||||
- **Core and Scheduler Refactoring:** The core scheduler has been significantly
|
||||
refactored to improve performance and reliability
|
||||
([#16895](https://github.com/google-gemini/gemini-cli/pull/16895) by
|
||||
@abhipatel12), and numerous performance and stability fixes have been
|
||||
included.
|
||||
|
||||
## Announcements: v0.25.0 - 2026-01-20
|
||||
|
||||
- **Skills and Agents Improvements:** We've enhanced the `activate_skill` tool,
|
||||
added a new `pr-creator` skill
|
||||
([#16232](https://github.com/google-gemini/gemini-cli/pull/16232) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)), enabled skills by
|
||||
default, improved the `cli_help` agent
|
||||
([#16100](https://github.com/google-gemini/gemini-cli/pull/16100) by
|
||||
[@scidomino](https://github.com/scidomino)), and added a new `/agents refresh`
|
||||
command ([#16204](https://github.com/google-gemini/gemini-cli/pull/16204) by
|
||||
[@joshualitt](https://github.com/joshualitt)).
|
||||
- **UI/UX Refinements:** You'll notice more transparent feedback for skills
|
||||
([#15954](https://github.com/google-gemini/gemini-cli/pull/15954) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)), the ability to switch
|
||||
focus between the shell and input with Tab
|
||||
([#14332](https://github.com/google-gemini/gemini-cli/pull/14332) by
|
||||
[@jacob314](https://github.com/jacob314)), and dynamic terminal tab titles
|
||||
([#16378](https://github.com/google-gemini/gemini-cli/pull/16378) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)).
|
||||
- **Core Functionality & Performance:** This release includes support for
|
||||
built-in agent skills
|
||||
([#16045](https://github.com/google-gemini/gemini-cli/pull/16045) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)), refined Gemini 3 system
|
||||
instructions ([#16139](https://github.com/google-gemini/gemini-cli/pull/16139)
|
||||
by [@NTaylorMullen](https://github.com/NTaylorMullen)), caching for ignore
|
||||
instances to improve performance
|
||||
([#16185](https://github.com/google-gemini/gemini-cli/pull/16185) by
|
||||
[@EricRahm](https://github.com/EricRahm)), and enhanced retry mechanisms
|
||||
([#16489](https://github.com/google-gemini/gemini-cli/pull/16489) by
|
||||
[@sehoon38](https://github.com/sehoon38)).
|
||||
- **Bug Fixes and Stability:** We've squashed numerous bugs across the CLI,
|
||||
core, and workflows, addressing issues with subagent delegation, unicode
|
||||
character crashes, and sticky header regressions.
|
||||
|
||||
## Announcements: v0.24.0 - 2026-01-14
|
||||
|
||||
- **Agent Skills:** We've introduced significant advancements in Agent Skills.
|
||||
This includes initial documentation and tutorials to help you get started,
|
||||
alongside enhanced support for remote agents, allowing for more distributed
|
||||
and powerful automation within Gemini CLI.
|
||||
([#15869](https://github.com/google-gemini/gemini-cli/pull/15869) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)),
|
||||
([#16013](https://github.com/google-gemini/gemini-cli/pull/16013) by
|
||||
[@adamweidman](https://github.com/adamweidman))
|
||||
- **Improved UI/UX:** The user interface has received several updates, featuring
|
||||
visual indicators for hook execution, a more refined display for settings, and
|
||||
the ability to use the Tab key to effortlessly switch focus between the shell
|
||||
and input areas.
|
||||
([#15408](https://github.com/google-gemini/gemini-cli/pull/15408) by
|
||||
[@abhipatel12](https://github.com/abhipatel12)),
|
||||
([#14332](https://github.com/google-gemini/gemini-cli/pull/14332) by
|
||||
[@galz10](https://github.com/galz10))
|
||||
- **Enhanced Security:** Security has been a major focus, with default folder
|
||||
trust now set to untrusted for increased safety. The Policy Engine has been
|
||||
improved to allow specific modes in user and administrator policies, and
|
||||
granular allowlisting for shell commands has been implemented, providing finer
|
||||
control over tool execution.
|
||||
([#15943](https://github.com/google-gemini/gemini-cli/pull/15943) by
|
||||
[@galz10](https://github.com/galz10)),
|
||||
([#15977](https://github.com/google-gemini/gemini-cli/pull/15977) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen))
|
||||
- **Core Functionality:** This release includes a mandatory MessageBus
|
||||
injection, marking Phase 3 of a hard migration to a more robust internal
|
||||
communication system. We've also added support for built-in skills with the
|
||||
CLI itself, and enhanced model routing to effectively utilize subagents.
|
||||
([#15776](https://github.com/google-gemini/gemini-cli/pull/15776) by
|
||||
[@abhipatel12](https://github.com/abhipatel12)),
|
||||
([#16300](https://github.com/google-gemini/gemini-cli/pull/16300) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen))
|
||||
- **Terminal Features:** Terminal interactions are more seamless with new
|
||||
features like OSC 52 paste support, along with fixes for Windows clipboard
|
||||
paste issues and general improvements to pasting in Windows terminals.
|
||||
([#15336](https://github.com/google-gemini/gemini-cli/pull/15336) by
|
||||
[@scidomino](https://github.com/scidomino)),
|
||||
([#15932](https://github.com/google-gemini/gemini-cli/pull/15932) by
|
||||
[@scidomino](https://github.com/scidomino))
|
||||
- **New Commands:** To manage the new features, we've added several new
|
||||
commands: `/agents refresh` to update agent configurations, `/skills reload`
|
||||
to refresh skill definitions, and `/skills install/uninstall` for easier
|
||||
management of your Agent Skills.
|
||||
([#16204](https://github.com/google-gemini/gemini-cli/pull/16204) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)),
|
||||
([#15865](https://github.com/google-gemini/gemini-cli/pull/15865) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen)),
|
||||
([#16377](https://github.com/google-gemini/gemini-cli/pull/16377) by
|
||||
[@NTaylorMullen](https://github.com/NTaylorMullen))
|
||||
|
||||
## Announcements: v0.23.0 - 2026-01-07
|
||||
|
||||
- 🎉 **Experimental Agent Skills Support in Preview:** Gemini CLI now supports
|
||||
[Agent Skills](https://agentskills.io/home) in our preview builds. This is an
|
||||
early preview where we’re looking for feedback!
|
||||
- Install Preview: `npm install -g @google/gemini-cli@preview`
|
||||
- Enable in `/settings`
|
||||
- Docs:
|
||||
[https://geminicli.com/docs/cli/skills/](https://geminicli.com/docs/cli/skills/)
|
||||
- **Gemini CLI wrapped:** Run `npx gemini-wrapped` to visualize your usage
|
||||
stats, top models, languages, and more!
|
||||
- **Windows clipboard image support:** Windows users can now paste images
|
||||
directly from their clipboard into the CLI using `Alt`+`V`.
|
||||
([pr](https://github.com/google-gemini/gemini-cli/pull/13997) by
|
||||
[@sgeraldes](https://github.com/sgeraldes))
|
||||
- **Terminal background color detection:** Automatically optimizes your
|
||||
terminal's background color to select compatible themes and provide
|
||||
accessibility warnings.
|
||||
([pr](https://github.com/google-gemini/gemini-cli/pull/15132) by
|
||||
[@jacob314](https://github.com/jacob314))
|
||||
- **Session logout:** Use the new `/logout` command to instantly clear
|
||||
credentials and reset your authentication state for seamless account
|
||||
switching. ([pr](https://github.com/google-gemini/gemini-cli/pull/13383) by
|
||||
[@CN-Scars](https://github.com/CN-Scars))
|
||||
|
||||
## Announcements: v0.22.0 - 2025-12-22
|
||||
|
||||
- 🎉**Free Tier + Gemini 3:** Free tier users now all have access to Gemini 3
|
||||
Pro & Flash. Enable in `/settings` by toggling "Preview Features" to `true`.
|
||||
- 🎉**Gemini CLI + Colab:** Gemini CLI is now pre-installed. Can be used
|
||||
headlessly in notebook cells or interactively in the built-in terminal
|
||||
([pic](https://imgur.com/a/G0Tn7vi))
|
||||
- 🎉**Gemini CLI Extensions:**
|
||||
- **Conductor:** Planning++, Gemini works with you to build out a detailed
|
||||
plan, pull in extra details as needed, ultimately to give the LLM guardrails
|
||||
with artifacts. Measure twice, implement once!
|
||||
|
||||
`gemini extensions install https://github.com/gemini-cli-extensions/conductor`
|
||||
|
||||
Blog:
|
||||
[https://developers.googleblog.com/conductor-introducing-context-driven-development-for-gemini-cli/](https://developers.googleblog.com/conductor-introducing-context-driven-development-for-gemini-cli/)
|
||||
|
||||
- **Endor Labs:** Perform code analysis, vulnerability scanning, and
|
||||
dependency checks using natural language.
|
||||
|
||||
`gemini extensions install https://github.com/endorlabs/gemini-extension`
|
||||
|
||||
## Announcements: v0.21.0 - 2025-12-15
|
||||
|
||||
- **⚡️⚡️⚡️ Gemini 3 Flash + Gemini CLI:** Better, faster and cheaper than 2.5
|
||||
@@ -89,7 +362,8 @@ on GitHub.
|
||||
- **Experimental permission improvements:** We are now experimenting with a new
|
||||
policy engine in Gemini CLI. This allows users and administrators to create
|
||||
fine-grained policy for tool calls. Currently behind a flag. See
|
||||
[policy engine documentation](../core/policy-engine.md) for more information.
|
||||
[policy engine documentation](../reference/policy-engine.md) for more
|
||||
information.
|
||||
- Blog:
|
||||
[https://allen.hutchison.org/2025/11/26/the-guardrails-of-autonomy/](https://allen.hutchison.org/2025/11/26/the-guardrails-of-autonomy/)
|
||||
- **Gemini 3 support for paid:** Gemini 3 support has been rolled out to all API
|
||||
@@ -214,8 +488,9 @@ on GitHub.
|
||||
page in their default browser directly from the CLI using the `/extension`
|
||||
explore command. ([pr](https://github.com/google-gemini/gemini-cli/pull/11846)
|
||||
by [@JayadityaGit](https://github.com/JayadityaGit)).
|
||||
- **Configurable compression:** Users can modify the compression threshold in
|
||||
`/settings`. The default has been made more proactive
|
||||
- **Configurable compression:** Users can modify the context compression
|
||||
threshold in `/settings` (decimal with percentage display). The default has
|
||||
been made more proactive
|
||||
([pr](https://github.com/google-gemini/gemini-cli/pull/12317) by
|
||||
[@scidomino](https://github.com/scidomino)).
|
||||
- **API key authentication:** Users can now securely enter and store their
|
||||
|
||||
+192
-209
@@ -1,6 +1,6 @@
|
||||
# Latest stable release: v0.21.0 - v0.21.1
|
||||
# Latest stable release: v0.32.1
|
||||
|
||||
Released: December 16, 2025
|
||||
Released: March 4, 2026
|
||||
|
||||
For most users, our latest stable release is the recommended release. Install
|
||||
the latest stable version with:
|
||||
@@ -11,215 +11,198 @@ npm install -g @google/gemini-cli
|
||||
|
||||
## Highlights
|
||||
|
||||
- **⚡️⚡️⚡️ Gemini 3 Flash + Gemini CLI:** If you are a paid user, you can now
|
||||
enable Gemini 3 Pro and Gemini 3 Flash. Go to `/settings` and set **Preview
|
||||
Features** to `true` to enable Gemini 3. For more information:
|
||||
[Gemini 3 Flash is now available in Gemini CLI](https://developers.googleblog.com/gemini-3-flash-is-now-available-in-gemini-cli/).
|
||||
- **Plan Mode Enhancements**: Significant updates to Plan Mode, including the
|
||||
ability to open and modify plans in an external editor, adaptations for
|
||||
complex tasks with multi-select options, and integration tests for plan mode.
|
||||
- **Agent and Steering Improvements**: The generalist agent has been enabled to
|
||||
enhance task delegation, model steering is now supported directly within the
|
||||
workspace, and contiguous parallel admission is enabled for `Kind.Agent`
|
||||
tools.
|
||||
- **Interactive Shell**: Interactive shell autocompletion has been introduced,
|
||||
significantly enhancing the user experience.
|
||||
- **Core Stability and Performance**: Extensions are now loaded in parallel,
|
||||
fetch timeouts have been increased, robust A2A streaming reassembly was
|
||||
implemented, and orphaned processes when terminal closes have been prevented.
|
||||
- **Billing and Quota Handling**: Implemented G1 AI credits overage flow with
|
||||
billing telemetry and added support for quota error fallbacks across all
|
||||
authentication types.
|
||||
|
||||
## What's Changed
|
||||
|
||||
- refactor(stdio): always patch stdout and use createWorkingStdio for clean
|
||||
output by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14159
|
||||
- chore(release): bump version to 0.21.0-nightly.20251202.2d935b379 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14409
|
||||
- implement fuzzy search inside settings by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13864
|
||||
- feat: enable message bus integration by default by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14329
|
||||
- docs: Recommend using --debug intead of --verbose for CLI debugging by @bbiggs
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14334
|
||||
- feat: consolidate remote MCP servers to use `url` in config by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/13762
|
||||
- Restrict integration tests tools by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14403
|
||||
- track github repository names in telemetry events by @IamRiddhi in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13670
|
||||
- Allow telemetry exporters to GCP to utilize user's login credentials, if
|
||||
requested by @mboshernitsan in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13778
|
||||
- refactor(editor): use const assertion for editor types with single source of
|
||||
truth by @amsminn in https://github.com/google-gemini/gemini-cli/pull/8604
|
||||
- fix(security): Fix npm audit vulnerabilities in glob and body-parser by
|
||||
@afarber in https://github.com/google-gemini/gemini-cli/pull/14090
|
||||
- Add new enterprise instructions by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/8641
|
||||
- feat(hooks): Hook Session Lifecycle & Compression Integration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14151
|
||||
- Avoid triggering refreshStatic unless there really is a banner to display. by
|
||||
@jacob314 in https://github.com/google-gemini/gemini-cli/pull/14328
|
||||
- feat(hooks): Hooks Commands Panel, Enable/Disable, and Migrate by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14225
|
||||
- fix: Bundle default policies for npx distribution by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14457
|
||||
- feat(hooks): Hook System Documentation by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14307
|
||||
- Fix tests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14458
|
||||
- feat: add scheduled workflow to close stale issues by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14404
|
||||
- feat: Support Extension Hooks with Security Warning by @abhipatel12 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14460
|
||||
- feat: Add enableAgents experimental flag by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14371
|
||||
- docs: fix typo 'socus' to 'focus' in todos.md by @Viktor286 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14374
|
||||
- Markdown export: move the emoji to the end of the line by @mhansen in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12278
|
||||
- fix(acp): prevent unnecessary credential cache clearing on re-authent… by
|
||||
@h-michael in https://github.com/google-gemini/gemini-cli/pull/9410
|
||||
- fix(cli): Fix word navigation for CJK characters by @SandyTao520 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14475
|
||||
- Remove example extension by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14376
|
||||
- Add commands for listing and updating per-extension settings by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12664
|
||||
- chore(tests): remove obsolete test for hierarchical memory by @pareshjoshij in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13122
|
||||
- feat(cli): support /copy in remote sessions using OSC52 by @ismellpillows in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13471
|
||||
- Update setting search UX by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14451
|
||||
- Fix(cli): Improve Homebrew update instruction to specify gemini-cli by
|
||||
@DaanVersavel in https://github.com/google-gemini/gemini-cli/pull/14502
|
||||
- do not toggle the setting item when entering space by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14489
|
||||
- fix: improve retry logic for fetch errors and network codes by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14439
|
||||
- remove unused isSearching field by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14509
|
||||
- feat(mcp): add `--type` alias for `--transport` flag in gemini mcp add by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14503
|
||||
- feat(cli): Move key restore logic to core by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13013
|
||||
- feat: add auto-execute on Enter behavior to argumentless MCP prompts by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14510
|
||||
- fix(shell): cursor visibility when using interactive mode by @aswinashok44 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14095
|
||||
- Adding session id as part of json o/p by @MJjainam in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14504
|
||||
- fix(extensions): resolve GitHub API 415 error for source tarballs by
|
||||
@jpoehnelt in https://github.com/google-gemini/gemini-cli/pull/13319
|
||||
- fix(client): Correctly latch hasFailedCompressionAttempt flag by @pareshjoshij
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13002
|
||||
- Disable flaky extension reloading test on linux by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14528
|
||||
- Add support for MCP dynamic tool update by `notifications/tools/list_changed`
|
||||
by @Adib234 in https://github.com/google-gemini/gemini-cli/pull/14375
|
||||
- Fix privacy screen for legacy tier users by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14522
|
||||
- feat: Exclude maintainer labeled issues from stale issue closer by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14532
|
||||
- Grant chained workflows proper permission. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14534
|
||||
- Make trigger_e2e manually fireable. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14547
|
||||
- Write e2e status to local repo not forked repo by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14549
|
||||
- Fixes [API Error: Cannot read properties of undefined (reading 'error')] by
|
||||
@silviojr in https://github.com/google-gemini/gemini-cli/pull/14553
|
||||
- Trigger chained e2e tests on all pull requests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14551
|
||||
- Fix bug in the shellExecutionService resulting in both truncation and 3X bloat
|
||||
by @jacob314 in https://github.com/google-gemini/gemini-cli/pull/14545
|
||||
- Fix issue where we were passing the model content reflecting terminal line
|
||||
wrapping. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14566
|
||||
- chore/release: bump version to 0.21.0-nightly.20251204.3da4fd5f7 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14476
|
||||
- feat(sessions): use 1-line generated session summary to describe sessions by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14467
|
||||
- Use Robot PAT for chained e2e merge queue skipper by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14585
|
||||
- fix(core): improve API response error handling and retry logic by @mattKorwel
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14563
|
||||
- Docs: Model routing clarification by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14373
|
||||
- expose previewFeatures flag in a2a by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14550
|
||||
- Fix emoji width in debug console. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14593
|
||||
- Fully detach autoupgrade process by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14595
|
||||
- Docs: Update Gemini 3 on Gemini CLI documentation by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14601
|
||||
- Disallow floating promises. by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14605
|
||||
- chore/release: bump version to 0.21.0-nightly.20251207.025e450ac by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14662
|
||||
- feat(modelAvailabilityService): integrate model availability service into
|
||||
backend logic by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14470
|
||||
- Add prompt_id propagation in a2a-server task by @koxkox111 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14581
|
||||
- Fix: Prevent freezing in non-interactive Gemini CLI when debug mode is enabled
|
||||
by @parthasaradhie in https://github.com/google-gemini/gemini-cli/pull/14580
|
||||
- fix(audio): improve reading of audio files by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14658
|
||||
- Update automated triage workflow to stop assigning priority labels by
|
||||
@skeshive in https://github.com/google-gemini/gemini-cli/pull/14717
|
||||
- set failed status when chained e2e fails by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14725
|
||||
- feat(github action) Triage and Label Pull Requests by Size and Comple… by
|
||||
@DaanVersavel in https://github.com/google-gemini/gemini-cli/pull/5571
|
||||
- refactor(telemetry): Improve previous PR that allows telemetry to use the CLI
|
||||
auth and add testing by @mboshernitsan in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14589
|
||||
- Always set status in chained_e2e workflow by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14730
|
||||
- feat: Add OTEL log event `gemini_cli.startup_stats` for startup stats. by
|
||||
@kevin-ramdass in https://github.com/google-gemini/gemini-cli/pull/14734
|
||||
- feat: auto-execute on slash command completion functions by @jackwotherspoon
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14584
|
||||
- Docs: Proper release notes by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14405
|
||||
- Add support for user-scoped extension settings by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13748
|
||||
- refactor(core): Improve environment variable handling in shell execution by
|
||||
@galz10 in https://github.com/google-gemini/gemini-cli/pull/14742
|
||||
- Remove old E2E Workflows by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14749
|
||||
- fix: handle missing local extension config and skip hooks when disabled by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/14744
|
||||
- chore/release: bump version to 0.21.0-nightly.20251209.ec9a8c7a7 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14751
|
||||
- feat: Add support for MCP Resources by @MrLesk in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13178
|
||||
- Always set pending status in E2E tests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14756
|
||||
- fix(lint): upgrade pip and use public pypi for yamllint by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14746
|
||||
- fix: use Gemini API supported image formats for clipboard by @jackwotherspoon
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14762
|
||||
- feat(a2a): Introduce restore command for a2a server by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13015
|
||||
- allow final:true to be returned on a2a server edit calls. by @DavidAPierce in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14747
|
||||
- (fix) Automated pr labeller by @DaanVersavel in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14788
|
||||
- Update CODEOWNERS by @kklashtorny1 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14830
|
||||
- Docs: Fix errors preventing site rebuild. by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14842
|
||||
- chore(deps): bump express from 5.1.0 to 5.2.0 by @dependabot[bot] in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14325
|
||||
- fix(patch): cherry-pick 3f5f030 to release/v0.21.0-preview.0-pr-14843 to patch
|
||||
version v0.21.0-preview.0 and create version 0.21.0-preview.1 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14851
|
||||
- fix(patch): cherry-pick ee6556c to release/v0.21.0-preview.1-pr-14691 to patch
|
||||
version v0.21.0-preview.1 and create version 0.21.0-preview.2 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14908
|
||||
- fix(patch): cherry-pick 54de675 to release/v0.21.0-preview.2-pr-14961 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14968
|
||||
- fix(patch): cherry-pick 12cbe32 to release/v0.21.0-preview.3-pr-15000 to patch
|
||||
version v0.21.0-preview.3 and create version 0.21.0-preview.4 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15003
|
||||
- fix(patch): cherry-pick edbe548 to release/v0.21.0-preview.4-pr-15007 to patch
|
||||
version v0.21.0-preview.4 and create version 0.21.0-preview.5 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15015
|
||||
- fix(patch): cherry-pick 2995af6 to release/v0.21.0-preview.5-pr-15131 to patch
|
||||
version v0.21.0-preview.5 and create version 0.21.0-preview.6 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15153
|
||||
- fix(patch): cherry-pick 0659ad1 to release/v0.32.0-pr-21042 to patch version
|
||||
v0.32.0 and create version 0.32.1 by @gemini-cli-robot in
|
||||
[#21048](https://github.com/google-gemini/gemini-cli/pull/21048)
|
||||
- feat(plan): add integration tests for plan mode by @Adib234 in
|
||||
[#20214](https://github.com/google-gemini/gemini-cli/pull/20214)
|
||||
- fix(acp): update auth handshake to spec by @skeshive in
|
||||
[#19725](https://github.com/google-gemini/gemini-cli/pull/19725)
|
||||
- feat(core): implement robust A2A streaming reassembly and fix task continuity
|
||||
by @adamfweidman in
|
||||
[#20091](https://github.com/google-gemini/gemini-cli/pull/20091)
|
||||
- feat(cli): load extensions in parallel by @scidomino in
|
||||
[#20229](https://github.com/google-gemini/gemini-cli/pull/20229)
|
||||
- Plumb the maxAttempts setting through Config args by @kevinjwang1 in
|
||||
[#20239](https://github.com/google-gemini/gemini-cli/pull/20239)
|
||||
- fix(cli): skip 404 errors in setup-github file downloads by @h30s in
|
||||
[#20287](https://github.com/google-gemini/gemini-cli/pull/20287)
|
||||
- fix(cli): expose model.name setting in settings dialog for persistence by
|
||||
@achaljhawar in
|
||||
[#19605](https://github.com/google-gemini/gemini-cli/pull/19605)
|
||||
- docs: remove legacy cmd examples in favor of powershell by @scidomino in
|
||||
[#20323](https://github.com/google-gemini/gemini-cli/pull/20323)
|
||||
- feat(core): Enable model steering in workspace. by @joshualitt in
|
||||
[#20343](https://github.com/google-gemini/gemini-cli/pull/20343)
|
||||
- fix: remove trailing comma in issue triage workflow settings json by @Nixxx19
|
||||
in [#20265](https://github.com/google-gemini/gemini-cli/pull/20265)
|
||||
- feat(core): implement task tracker foundation and service by @anj-s in
|
||||
[#19464](https://github.com/google-gemini/gemini-cli/pull/19464)
|
||||
- test: support tests that include color information by @jacob314 in
|
||||
[#20220](https://github.com/google-gemini/gemini-cli/pull/20220)
|
||||
- feat(core): introduce Kind.Agent for sub-agent classification by @abhipatel12
|
||||
in [#20369](https://github.com/google-gemini/gemini-cli/pull/20369)
|
||||
- Changelog for v0.30.0 by @gemini-cli-robot in
|
||||
[#20252](https://github.com/google-gemini/gemini-cli/pull/20252)
|
||||
- Update changelog workflow to reject nightly builds by @g-samroberts in
|
||||
[#20248](https://github.com/google-gemini/gemini-cli/pull/20248)
|
||||
- Changelog for v0.31.0-preview.0 by @gemini-cli-robot in
|
||||
[#20249](https://github.com/google-gemini/gemini-cli/pull/20249)
|
||||
- feat(cli): hide workspace policy update dialog and auto-accept by default by
|
||||
@Abhijit-2592 in
|
||||
[#20351](https://github.com/google-gemini/gemini-cli/pull/20351)
|
||||
- feat(core): rename grep_search include parameter to include_pattern by
|
||||
@SandyTao520 in
|
||||
[#20328](https://github.com/google-gemini/gemini-cli/pull/20328)
|
||||
- feat(plan): support opening and modifying plan in external editor by @Adib234
|
||||
in [#20348](https://github.com/google-gemini/gemini-cli/pull/20348)
|
||||
- feat(cli): implement interactive shell autocompletion by @mrpmohiburrahman in
|
||||
[#20082](https://github.com/google-gemini/gemini-cli/pull/20082)
|
||||
- fix(core): allow /memory add to work in plan mode by @Jefftree in
|
||||
[#20353](https://github.com/google-gemini/gemini-cli/pull/20353)
|
||||
- feat(core): add HTTP 499 to retryable errors and map to RetryableQuotaError by
|
||||
@bdmorgan in [#20432](https://github.com/google-gemini/gemini-cli/pull/20432)
|
||||
- feat(core): Enable generalist agent by @joshualitt in
|
||||
[#19665](https://github.com/google-gemini/gemini-cli/pull/19665)
|
||||
- Updated tests in TableRenderer.test.tsx to use SVG snapshots by @devr0306 in
|
||||
[#20450](https://github.com/google-gemini/gemini-cli/pull/20450)
|
||||
- Refactor Github Action per b/485167538 by @google-admin in
|
||||
[#19443](https://github.com/google-gemini/gemini-cli/pull/19443)
|
||||
- fix(github): resolve actionlint and yamllint regressions from #19443 by @jerop
|
||||
in [#20467](https://github.com/google-gemini/gemini-cli/pull/20467)
|
||||
- fix: action var usage by @galz10 in
|
||||
[#20492](https://github.com/google-gemini/gemini-cli/pull/20492)
|
||||
- feat(core): improve A2A content extraction by @adamfweidman in
|
||||
[#20487](https://github.com/google-gemini/gemini-cli/pull/20487)
|
||||
- fix(cli): support quota error fallbacks for all authentication types by
|
||||
@sehoon38 in [#20475](https://github.com/google-gemini/gemini-cli/pull/20475)
|
||||
- fix(core): flush transcript for pure tool-call responses to ensure BeforeTool
|
||||
hooks see complete state by @krishdef7 in
|
||||
[#20419](https://github.com/google-gemini/gemini-cli/pull/20419)
|
||||
- feat(plan): adapt planning workflow based on complexity of task by @jerop in
|
||||
[#20465](https://github.com/google-gemini/gemini-cli/pull/20465)
|
||||
- fix: prevent orphaned processes from consuming 100% CPU when terminal closes
|
||||
by @yuvrajangadsingh in
|
||||
[#16965](https://github.com/google-gemini/gemini-cli/pull/16965)
|
||||
- feat(core): increase fetch timeout and fix [object Object] error
|
||||
stringification by @bdmorgan in
|
||||
[#20441](https://github.com/google-gemini/gemini-cli/pull/20441)
|
||||
- [Gemma x Gemini CLI] Add an Experimental Gemma Router that uses a LiteRT-LM
|
||||
shim into the Composite Model Classifier Strategy by @sidwan02 in
|
||||
[#17231](https://github.com/google-gemini/gemini-cli/pull/17231)
|
||||
- docs(plan): update documentation regarding supporting editing of plan files
|
||||
during plan approval by @Adib234 in
|
||||
[#20452](https://github.com/google-gemini/gemini-cli/pull/20452)
|
||||
- test(cli): fix flaky ToolResultDisplay overflow test by @jwhelangoog in
|
||||
[#20518](https://github.com/google-gemini/gemini-cli/pull/20518)
|
||||
- ui(cli): reduce length of Ctrl+O hint by @jwhelangoog in
|
||||
[#20490](https://github.com/google-gemini/gemini-cli/pull/20490)
|
||||
- fix(ui): correct styled table width calculations by @devr0306 in
|
||||
[#20042](https://github.com/google-gemini/gemini-cli/pull/20042)
|
||||
- Avoid overaggressive unescaping by @scidomino in
|
||||
[#20520](https://github.com/google-gemini/gemini-cli/pull/20520)
|
||||
- feat(telemetry) Instrument traces with more attributes and make them available
|
||||
to OTEL users by @heaventourist in
|
||||
[#20237](https://github.com/google-gemini/gemini-cli/pull/20237)
|
||||
- Add support for policy engine in extensions by @chrstnb in
|
||||
[#20049](https://github.com/google-gemini/gemini-cli/pull/20049)
|
||||
- Docs: Update to Terms of Service & FAQ by @jkcinouye in
|
||||
[#20488](https://github.com/google-gemini/gemini-cli/pull/20488)
|
||||
- Fix bottom border rendering for search and add a regression test. by @jacob314
|
||||
in [#20517](https://github.com/google-gemini/gemini-cli/pull/20517)
|
||||
- fix(core): apply retry logic to CodeAssistServer for all users by @bdmorgan in
|
||||
[#20507](https://github.com/google-gemini/gemini-cli/pull/20507)
|
||||
- Fix extension MCP server env var loading by @chrstnb in
|
||||
[#20374](https://github.com/google-gemini/gemini-cli/pull/20374)
|
||||
- feat(ui): add 'ctrl+o' hint to truncated content message by @jerop in
|
||||
[#20529](https://github.com/google-gemini/gemini-cli/pull/20529)
|
||||
- Fix flicker showing message to press ctrl-O again to collapse. by @jacob314 in
|
||||
[#20414](https://github.com/google-gemini/gemini-cli/pull/20414)
|
||||
- fix(cli): hide shortcuts hint while model is thinking or the user has typed a
|
||||
prompt + add debounce to avoid flicker by @jacob314 in
|
||||
[#19389](https://github.com/google-gemini/gemini-cli/pull/19389)
|
||||
- feat(plan): update planning workflow to encourage multi-select with
|
||||
descriptions of options by @Adib234 in
|
||||
[#20491](https://github.com/google-gemini/gemini-cli/pull/20491)
|
||||
- refactor(core,cli): useAlternateBuffer read from config by @psinha40898 in
|
||||
[#20346](https://github.com/google-gemini/gemini-cli/pull/20346)
|
||||
- fix(cli): ensure dialogs stay scrolled to bottom in alternate buffer mode by
|
||||
@jacob314 in [#20527](https://github.com/google-gemini/gemini-cli/pull/20527)
|
||||
- fix(core): revert auto-save of policies to user space by @Abhijit-2592 in
|
||||
[#20531](https://github.com/google-gemini/gemini-cli/pull/20531)
|
||||
- Demote unreliable test. by @gundermanc in
|
||||
[#20571](https://github.com/google-gemini/gemini-cli/pull/20571)
|
||||
- fix(core): handle optional response fields from code assist API by @sehoon38
|
||||
in [#20345](https://github.com/google-gemini/gemini-cli/pull/20345)
|
||||
- fix(cli): keep thought summary when loading phrases are off by @LyalinDotCom
|
||||
in [#20497](https://github.com/google-gemini/gemini-cli/pull/20497)
|
||||
- feat(cli): add temporary flag to disable workspace policies by @Abhijit-2592
|
||||
in [#20523](https://github.com/google-gemini/gemini-cli/pull/20523)
|
||||
- Disable expensive and scheduled workflows on personal forks by @dewitt in
|
||||
[#20449](https://github.com/google-gemini/gemini-cli/pull/20449)
|
||||
- Moved markdown parsing logic to a separate util file by @devr0306 in
|
||||
[#20526](https://github.com/google-gemini/gemini-cli/pull/20526)
|
||||
- fix(plan): prevent agent from using ask_user for shell command confirmation by
|
||||
@Adib234 in [#20504](https://github.com/google-gemini/gemini-cli/pull/20504)
|
||||
- fix(core): disable retries for code assist streaming requests by @sehoon38 in
|
||||
[#20561](https://github.com/google-gemini/gemini-cli/pull/20561)
|
||||
- feat(billing): implement G1 AI credits overage flow with billing telemetry by
|
||||
@gsquared94 in
|
||||
[#18590](https://github.com/google-gemini/gemini-cli/pull/18590)
|
||||
- feat: better error messages by @gsquared94 in
|
||||
[#20577](https://github.com/google-gemini/gemini-cli/pull/20577)
|
||||
- fix(ui): persist expansion in AskUser dialog when navigating options by @jerop
|
||||
in [#20559](https://github.com/google-gemini/gemini-cli/pull/20559)
|
||||
- fix(cli): prevent sub-agent tool calls from leaking into UI by @abhipatel12 in
|
||||
[#20580](https://github.com/google-gemini/gemini-cli/pull/20580)
|
||||
- fix(cli): Shell autocomplete polish by @jacob314 in
|
||||
[#20411](https://github.com/google-gemini/gemini-cli/pull/20411)
|
||||
- Changelog for v0.31.0-preview.1 by @gemini-cli-robot in
|
||||
[#20590](https://github.com/google-gemini/gemini-cli/pull/20590)
|
||||
- Add slash command for promoting behavioral evals to CI blocking by @gundermanc
|
||||
in [#20575](https://github.com/google-gemini/gemini-cli/pull/20575)
|
||||
- Changelog for v0.30.1 by @gemini-cli-robot in
|
||||
[#20589](https://github.com/google-gemini/gemini-cli/pull/20589)
|
||||
- Add low/full CLI error verbosity mode for cleaner UI by @LyalinDotCom in
|
||||
[#20399](https://github.com/google-gemini/gemini-cli/pull/20399)
|
||||
- Disable Gemini PR reviews on draft PRs. by @gundermanc in
|
||||
[#20362](https://github.com/google-gemini/gemini-cli/pull/20362)
|
||||
- Docs: FAQ update by @jkcinouye in
|
||||
[#20585](https://github.com/google-gemini/gemini-cli/pull/20585)
|
||||
- fix(core): reduce intrusive MCP errors and deduplicate diagnostics by
|
||||
@spencer426 in
|
||||
[#20232](https://github.com/google-gemini/gemini-cli/pull/20232)
|
||||
- docs: fix spelling typos in installation guide by @campox747 in
|
||||
[#20579](https://github.com/google-gemini/gemini-cli/pull/20579)
|
||||
- Promote stable tests to CI blocking. by @gundermanc in
|
||||
[#20581](https://github.com/google-gemini/gemini-cli/pull/20581)
|
||||
- feat(core): enable contiguous parallel admission for Kind.Agent tools by
|
||||
@abhipatel12 in
|
||||
[#20583](https://github.com/google-gemini/gemini-cli/pull/20583)
|
||||
- Enforce import/no-duplicates as error by @Nixxx19 in
|
||||
[#19797](https://github.com/google-gemini/gemini-cli/pull/19797)
|
||||
- fix: merge duplicate imports in sdk and test-utils packages (1/4) by @Nixxx19
|
||||
in [#19777](https://github.com/google-gemini/gemini-cli/pull/19777)
|
||||
- fix: merge duplicate imports in a2a-server package (2/4) by @Nixxx19 in
|
||||
[#19781](https://github.com/google-gemini/gemini-cli/pull/19781)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.20.2...v0.21.0
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.31.0...v0.32.1
|
||||
|
||||
+186
-114
@@ -1,6 +1,6 @@
|
||||
# Preview release: Release v0.22.0-preview.0
|
||||
# Preview release: v0.33.0-preview.4
|
||||
|
||||
Released: December 16, 2025
|
||||
Released: March 06, 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).
|
||||
@@ -11,119 +11,191 @@ To install the preview release:
|
||||
npm install -g @google/gemini-cli@preview
|
||||
```
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Plan Mode Enhancements**: Added support for annotating plans with feedback
|
||||
for iteration, enabling built-in research subagents in plan mode, and a new
|
||||
`copy` subcommand.
|
||||
- **Agent and Skill Improvements**: Introduced the new `github-issue-creator`
|
||||
skill, implemented HTTP authentication support for A2A remote agents, and
|
||||
added support for authenticated A2A agent card discovery.
|
||||
- **CLI UX/UI Updates**: Redesigned the header to be compact with an ASCII icon,
|
||||
inverted the context window display to show usage, and directly indicate auth
|
||||
required state for agents.
|
||||
- **Core and ACP Enhancements**: Implemented slash command handling in ACP (for
|
||||
`/memory`, `/init`, `/extensions`, and `/restore`), added a set models
|
||||
interface to ACP, and centralized `read_file` limits while truncating large
|
||||
MCP tool output.
|
||||
|
||||
## What's Changed
|
||||
|
||||
- feat(ide): fallback to GEMINI_CLI_IDE_AUTH_TOKEN env var by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14843
|
||||
- feat: display quota stats for unused models in /stats by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14764
|
||||
- feat: ensure codebase investigator uses preview model when main agent does by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/14412
|
||||
- chore: add closing reason to stale bug workflow by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14861
|
||||
- Send the model and CLI version with the user agent by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14865
|
||||
- refactor(sessions): move session summary generation to startup by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14691
|
||||
- Limit search depth in path corrector by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14869
|
||||
- Fix: Correct typo in code comment by @kuishou68 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14671
|
||||
- feat(core): Plumbing for late resolution of model configs. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14597
|
||||
- feat: attempt more error parsing by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14899
|
||||
- Add missing await. by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14910
|
||||
- feat(core): Add support for transcript_path in hooks for git-ai/Gemini
|
||||
extension by @svarlamov in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14663
|
||||
- refactor: implement DelegateToAgentTool with discriminated union by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/14769
|
||||
- feat: reset availabilityService on /auth by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14911
|
||||
- chore/release: bump version to 0.21.0-nightly.20251211.8c83e1ea9 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14924
|
||||
- Fix: Correctly detect MCP tool errors by @kevin-ramdass in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14937
|
||||
- increase labeler timeout by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14922
|
||||
- tool(cli): tweak the frontend tool to be aware of more core files from the cli
|
||||
by @jacob314 in https://github.com/google-gemini/gemini-cli/pull/14962
|
||||
- feat(cli): polish cached token stats and simplify stats display when quota is
|
||||
present. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14961
|
||||
- feat(settings-validation): add validation for settings schema by @lifefloating
|
||||
in https://github.com/google-gemini/gemini-cli/pull/12929
|
||||
- fix(ide): Update IDE extension to write auth token in env var by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14999
|
||||
- Revert "chore(deps): bump express from 5.1.0 to 5.2.0" by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14998
|
||||
- feat(a2a): Introduce /init command for a2a server by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13419
|
||||
- feat: support multi-file drag and drop of images by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14832
|
||||
- fix(policy): allow codebase_investigator by default in read-only policy by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/15000
|
||||
- refactor(ide ext): Update port file name + switch to 1-based index for
|
||||
characters + remove truncation text by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/10501
|
||||
- fix(vscode-ide-companion): correct license generation for workspace
|
||||
dependencies by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15004
|
||||
- fix: temp fix for subagent invocation until subagent delegation is merged to
|
||||
stable by @abhipatel12 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15007
|
||||
- test: update ide detection tests to make them more robust when run in an ide
|
||||
by @kevin-ramdass in https://github.com/google-gemini/gemini-cli/pull/15008
|
||||
- Remove flex from stats display. See snapshots for diffs. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14983
|
||||
- Add license field into package.json by @jb-perez in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14473
|
||||
- feat: Persistent "Always Allow" policies with granular shell & MCP support by
|
||||
@allenhutchison in https://github.com/google-gemini/gemini-cli/pull/14737
|
||||
- chore/release: bump version to 0.21.0-nightly.20251212.54de67536 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14969
|
||||
- fix(core): commandPrefix word boundary and compound command safety by
|
||||
@allenhutchison in https://github.com/google-gemini/gemini-cli/pull/15006
|
||||
- chore(docs): add 'Maintainers only' label info to CONTRIBUTING.md by @jacob314
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14914
|
||||
- Refresh hooks when refreshing extensions. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14918
|
||||
- Add clarity to error messages by @gsehgal in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14879
|
||||
- chore : remove a redundant tip by @JayadityaGit in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14947
|
||||
- chore/release: bump version to 0.21.0-nightly.20251213.977248e09 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15029
|
||||
- Disallow redundant typecasts. by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15030
|
||||
- fix(auth): prioritize GEMINI_API_KEY env var and skip unnecessary key… by
|
||||
@galz10 in https://github.com/google-gemini/gemini-cli/pull/14745
|
||||
- fix: use zod for safety check result validation by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15026
|
||||
- update(telemetry): add hashed_extension_name to field to extension events by
|
||||
@kiranani in https://github.com/google-gemini/gemini-cli/pull/15025
|
||||
- fix: similar to policy-engine, throw error in case of requiring tool execution
|
||||
confirmation for non-interactive mode by @MayV in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14702
|
||||
- Clean up processes in integration tests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15102
|
||||
- docs: update policy engine getting started and defaults by @NTaylorMullen in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15105
|
||||
- Fix tool output fragmentation by encapsulating content in functionResponse by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/13082
|
||||
- Simplify method signature. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15114
|
||||
- Show raw input token counts in json output. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15021
|
||||
- fix: Mark A2A requests as interactive by @MayV in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15108
|
||||
- use previewFeatures to determine which pro model to use for A2A by @sehoon38
|
||||
in https://github.com/google-gemini/gemini-cli/pull/15131
|
||||
- refactor(cli): fix settings merging so that settings using the new json format
|
||||
take priority over ones using the old format by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15116
|
||||
- fix(patch): cherry-pick 7ec477d to release/v0.33.0-preview.3-pr-21305 to patch
|
||||
version v0.33.0-preview.3 and create version 0.33.0-preview.4 by
|
||||
@gemini-cli-robot in
|
||||
[#21349](https://github.com/google-gemini/gemini-cli/pull/21349)
|
||||
- fix(patch): cherry-pick 0135b03 to release/v0.33.0-preview.2-pr-21171
|
||||
[CONFLICTS] by @gemini-cli-robot in
|
||||
[#21336](https://github.com/google-gemini/gemini-cli/pull/21336)
|
||||
- fix(patch): cherry-pick 173376b to release/v0.33.0-preview.1-pr-21157 to patch
|
||||
version v0.33.0-preview.1 and create version 0.33.0-preview.2 by
|
||||
@gemini-cli-robot in
|
||||
[#21300](https://github.com/google-gemini/gemini-cli/pull/21300)
|
||||
- fix(patch): cherry-pick 173376b to release/v0.33.0-preview.1-pr-21157 to patch
|
||||
version v0.33.0-preview.1 and create version 0.33.0-preview.2 by
|
||||
@gemini-cli-robot in
|
||||
[#21300](https://github.com/google-gemini/gemini-cli/pull/21300)
|
||||
- fix(patch): cherry-pick 0659ad1 to release/v0.33.0-preview.0-pr-21042 to patch
|
||||
version v0.33.0-preview.0 and create version 0.33.0-preview.1 by
|
||||
@gemini-cli-robot in
|
||||
[#21047](https://github.com/google-gemini/gemini-cli/pull/21047)
|
||||
- Docs: Update model docs to remove Preview Features. by @jkcinouye in
|
||||
[#20084](https://github.com/google-gemini/gemini-cli/pull/20084)
|
||||
- docs: fix typo in installation documentation by @AdityaSharma-Git3207 in
|
||||
[#20153](https://github.com/google-gemini/gemini-cli/pull/20153)
|
||||
- docs: add Windows PowerShell equivalents for environments and scripting by
|
||||
@scidomino in [#20333](https://github.com/google-gemini/gemini-cli/pull/20333)
|
||||
- fix(core): parse raw ASCII buffer strings in Gaxios errors by @sehoon38 in
|
||||
[#20626](https://github.com/google-gemini/gemini-cli/pull/20626)
|
||||
- chore(release): bump version to 0.33.0-nightly.20260227.ba149afa0 by @galz10
|
||||
in [#20637](https://github.com/google-gemini/gemini-cli/pull/20637)
|
||||
- fix(github): use robot PAT for automated PRs to pass CLA check by @galz10 in
|
||||
[#20641](https://github.com/google-gemini/gemini-cli/pull/20641)
|
||||
- chore/release: bump version to 0.33.0-nightly.20260228.1ca5c05d0 by
|
||||
@gemini-cli-robot in
|
||||
[#20644](https://github.com/google-gemini/gemini-cli/pull/20644)
|
||||
- Changelog for v0.31.0 by @gemini-cli-robot in
|
||||
[#20634](https://github.com/google-gemini/gemini-cli/pull/20634)
|
||||
- fix: use full paths for ACP diff payloads by @JagjeevanAK in
|
||||
[#19539](https://github.com/google-gemini/gemini-cli/pull/19539)
|
||||
- Changelog for v0.32.0-preview.0 by @gemini-cli-robot in
|
||||
[#20627](https://github.com/google-gemini/gemini-cli/pull/20627)
|
||||
- fix: acp/zed race condition between MCP initialisation and prompt by
|
||||
@kartikangiras in
|
||||
[#20205](https://github.com/google-gemini/gemini-cli/pull/20205)
|
||||
- fix(cli): reset themeManager between tests to ensure isolation by
|
||||
@NTaylorMullen in
|
||||
[#20598](https://github.com/google-gemini/gemini-cli/pull/20598)
|
||||
- refactor(core): Extract tool parameter names as constants by @SandyTao520 in
|
||||
[#20460](https://github.com/google-gemini/gemini-cli/pull/20460)
|
||||
- fix(cli): resolve autoThemeSwitching when background hasn't changed but theme
|
||||
mismatches by @sehoon38 in
|
||||
[#20706](https://github.com/google-gemini/gemini-cli/pull/20706)
|
||||
- feat(skills): add github-issue-creator skill by @sehoon38 in
|
||||
[#20709](https://github.com/google-gemini/gemini-cli/pull/20709)
|
||||
- fix(cli): allow sub-agent confirmation requests in UI while preventing
|
||||
background flicker by @abhipatel12 in
|
||||
[#20722](https://github.com/google-gemini/gemini-cli/pull/20722)
|
||||
- Merge User and Agent Card Descriptions #20849 by @adamfweidman in
|
||||
[#20850](https://github.com/google-gemini/gemini-cli/pull/20850)
|
||||
- fix(core): reduce LLM-based loop detection false positives by @SandyTao520 in
|
||||
[#20701](https://github.com/google-gemini/gemini-cli/pull/20701)
|
||||
- fix(plan): deflake plan mode integration tests by @Adib234 in
|
||||
[#20477](https://github.com/google-gemini/gemini-cli/pull/20477)
|
||||
- Add /unassign support by @scidomino in
|
||||
[#20864](https://github.com/google-gemini/gemini-cli/pull/20864)
|
||||
- feat(core): implement HTTP authentication support for A2A remote agents by
|
||||
@SandyTao520 in
|
||||
[#20510](https://github.com/google-gemini/gemini-cli/pull/20510)
|
||||
- feat(core): centralize read_file limits and update gemini-3 description by
|
||||
@aishaneeshah in
|
||||
[#20619](https://github.com/google-gemini/gemini-cli/pull/20619)
|
||||
- Do not block CI on evals by @gundermanc in
|
||||
[#20870](https://github.com/google-gemini/gemini-cli/pull/20870)
|
||||
- document node limitation for shift+tab by @scidomino in
|
||||
[#20877](https://github.com/google-gemini/gemini-cli/pull/20877)
|
||||
- Add install as an option when extension is selected. by @DavidAPierce in
|
||||
[#20358](https://github.com/google-gemini/gemini-cli/pull/20358)
|
||||
- Update CODEOWNERS for README.md reviewers by @g-samroberts in
|
||||
[#20860](https://github.com/google-gemini/gemini-cli/pull/20860)
|
||||
- feat(core): truncate large MCP tool output by @SandyTao520 in
|
||||
[#19365](https://github.com/google-gemini/gemini-cli/pull/19365)
|
||||
- Subagent activity UX. by @gundermanc in
|
||||
[#17570](https://github.com/google-gemini/gemini-cli/pull/17570)
|
||||
- style(cli) : Dialog pattern for /hooks Command by @AbdulTawabJuly in
|
||||
[#17930](https://github.com/google-gemini/gemini-cli/pull/17930)
|
||||
- feat: redesign header to be compact with ASCII icon by @keithguerin in
|
||||
[#18713](https://github.com/google-gemini/gemini-cli/pull/18713)
|
||||
- fix(core): ensure subagents use qualified MCP tool names by @abhipatel12 in
|
||||
[#20801](https://github.com/google-gemini/gemini-cli/pull/20801)
|
||||
- feat(core): support authenticated A2A agent card discovery by @SandyTao520 in
|
||||
[#20622](https://github.com/google-gemini/gemini-cli/pull/20622)
|
||||
- refactor(cli): fully remove React anti patterns, improve type safety and fix
|
||||
UX oversights in SettingsDialog.tsx by @psinha40898 in
|
||||
[#18963](https://github.com/google-gemini/gemini-cli/pull/18963)
|
||||
- Adding MCPOAuthProvider implementing the MCPSDK OAuthClientProvider by
|
||||
@Nayana-Parameswarappa in
|
||||
[#20121](https://github.com/google-gemini/gemini-cli/pull/20121)
|
||||
- feat(core): add tool name validation in TOML policy files by @allenhutchison
|
||||
in [#19281](https://github.com/google-gemini/gemini-cli/pull/19281)
|
||||
- docs: fix broken markdown links in main README.md by @Hamdanbinhashim in
|
||||
[#20300](https://github.com/google-gemini/gemini-cli/pull/20300)
|
||||
- refactor(core): replace manual syncPlanModeTools with declarative policy rules
|
||||
by @jerop in [#20596](https://github.com/google-gemini/gemini-cli/pull/20596)
|
||||
- fix(core): increase default headers timeout to 5 minutes by @gundermanc in
|
||||
[#20890](https://github.com/google-gemini/gemini-cli/pull/20890)
|
||||
- feat(admin): enable 30 day default retention for chat history & remove warning
|
||||
by @skeshive in
|
||||
[#20853](https://github.com/google-gemini/gemini-cli/pull/20853)
|
||||
- feat(plan): support annotating plans with feedback for iteration by @Adib234
|
||||
in [#20876](https://github.com/google-gemini/gemini-cli/pull/20876)
|
||||
- Add some dos and don'ts to behavioral evals README. by @gundermanc in
|
||||
[#20629](https://github.com/google-gemini/gemini-cli/pull/20629)
|
||||
- fix(core): skip telemetry logging for AbortError exceptions by @yunaseoul in
|
||||
[#19477](https://github.com/google-gemini/gemini-cli/pull/19477)
|
||||
- fix(core): restrict "System: Please continue" invalid stream retry to Gemini 2
|
||||
models by @SandyTao520 in
|
||||
[#20897](https://github.com/google-gemini/gemini-cli/pull/20897)
|
||||
- ci(evals): only run evals in CI if prompts or tools changed by @gundermanc in
|
||||
[#20898](https://github.com/google-gemini/gemini-cli/pull/20898)
|
||||
- Build binary by @aswinashok44 in
|
||||
[#18933](https://github.com/google-gemini/gemini-cli/pull/18933)
|
||||
- Code review fixes as a pr by @jacob314 in
|
||||
[#20612](https://github.com/google-gemini/gemini-cli/pull/20612)
|
||||
- fix(ci): handle empty APP_ID in stale PR closer by @bdmorgan in
|
||||
[#20919](https://github.com/google-gemini/gemini-cli/pull/20919)
|
||||
- feat(cli): invert context window display to show usage by @keithguerin in
|
||||
[#20071](https://github.com/google-gemini/gemini-cli/pull/20071)
|
||||
- fix(plan): clean up session directories and plans on deletion by @jerop in
|
||||
[#20914](https://github.com/google-gemini/gemini-cli/pull/20914)
|
||||
- fix(core): enforce optionality for API response fields in code_assist by
|
||||
@sehoon38 in [#20714](https://github.com/google-gemini/gemini-cli/pull/20714)
|
||||
- feat(extensions): add support for plan directory in extension manifest by
|
||||
@mahimashanware in
|
||||
[#20354](https://github.com/google-gemini/gemini-cli/pull/20354)
|
||||
- feat(plan): enable built-in research subagents in plan mode by @Adib234 in
|
||||
[#20972](https://github.com/google-gemini/gemini-cli/pull/20972)
|
||||
- feat(agents): directly indicate auth required state by @adamfweidman in
|
||||
[#20986](https://github.com/google-gemini/gemini-cli/pull/20986)
|
||||
- fix(cli): wait for background auto-update before relaunching by @scidomino in
|
||||
[#20904](https://github.com/google-gemini/gemini-cli/pull/20904)
|
||||
- fix: pre-load @scripts/copy_files.js references from external editor prompts
|
||||
by @kartikangiras in
|
||||
[#20963](https://github.com/google-gemini/gemini-cli/pull/20963)
|
||||
- feat(evals): add behavioral evals for ask_user tool by @Adib234 in
|
||||
[#20620](https://github.com/google-gemini/gemini-cli/pull/20620)
|
||||
- refactor common settings logic for skills,agents by @ishaanxgupta in
|
||||
[#17490](https://github.com/google-gemini/gemini-cli/pull/17490)
|
||||
- Update docs-writer skill with new resource by @g-samroberts in
|
||||
[#20917](https://github.com/google-gemini/gemini-cli/pull/20917)
|
||||
- fix(cli): pin clipboardy to ~5.2.x by @scidomino in
|
||||
[#21009](https://github.com/google-gemini/gemini-cli/pull/21009)
|
||||
- feat: Implement slash command handling in ACP for
|
||||
`/memory`,`/init`,`/extensions` and `/restore` by @sripasg in
|
||||
[#20528](https://github.com/google-gemini/gemini-cli/pull/20528)
|
||||
- Docs/add hooks reference by @AadithyaAle in
|
||||
[#20961](https://github.com/google-gemini/gemini-cli/pull/20961)
|
||||
- feat(plan): add copy subcommand to plan (#20491) by @ruomengz in
|
||||
[#20988](https://github.com/google-gemini/gemini-cli/pull/20988)
|
||||
- fix(core): sanitize and length-check MCP tool qualified names by @abhipatel12
|
||||
in [#20987](https://github.com/google-gemini/gemini-cli/pull/20987)
|
||||
- Format the quota/limit style guide. by @g-samroberts in
|
||||
[#21017](https://github.com/google-gemini/gemini-cli/pull/21017)
|
||||
- fix(core): send shell output to model on cancel by @devr0306 in
|
||||
[#20501](https://github.com/google-gemini/gemini-cli/pull/20501)
|
||||
- remove hardcoded tiername when missing tier by @sehoon38 in
|
||||
[#21022](https://github.com/google-gemini/gemini-cli/pull/21022)
|
||||
- feat(acp): add set models interface by @skeshive in
|
||||
[#20991](https://github.com/google-gemini/gemini-cli/pull/20991)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.21.0-preview.6...v0.22.0-preview.0
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.32.0-preview.0...v0.33.0-preview.4
|
||||
|
||||
@@ -1,896 +0,0 @@
|
||||
# Gemini CLI changelog
|
||||
|
||||
Gemini CLI has three major release channels: nightly, preview, and stable. For
|
||||
most users, we recommend the stable release.
|
||||
|
||||
On this page, you can find information regarding the current releases and
|
||||
highlights from each release.
|
||||
|
||||
For the full changelog, including nightly releases, refer to
|
||||
[Releases - google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli/releases)
|
||||
on GitHub.
|
||||
|
||||
## Current Releases
|
||||
|
||||
| Release channel | Notes |
|
||||
| :------------------------------------------ | :---------------------------------------------- |
|
||||
| Nightly | Nightly release with the most recent changes. |
|
||||
| [Preview](#release-v0220-preview-0-preview) | Experimental features ready for early feedback. |
|
||||
| [Latest](#release-v0210---v0211-latest) | Stable, recommended for general use. |
|
||||
|
||||
## Release v0.21.0 - v0.21.1 (Latest)
|
||||
|
||||
### Highlights
|
||||
|
||||
- **⚡️⚡️⚡️ Gemini 3 Flash + Gemini CLI:** If you are a paid user, you can now
|
||||
enable Gemini 3 Pro and Gemini 3 Flash. Go to `/settings` and set **Preview
|
||||
Features** to `true` to enable Gemini 3. For more information:
|
||||
[Gemini 3 Flash is now available in Gemini CLI](https://developers.googleblog.com/gemini-3-flash-is-now-available-in-gemini-cli/).
|
||||
|
||||
### What's Changed
|
||||
|
||||
- refactor(stdio): always patch stdout and use createWorkingStdio for clean
|
||||
output by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14159
|
||||
- chore(release): bump version to 0.21.0-nightly.20251202.2d935b379 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14409
|
||||
- implement fuzzy search inside settings by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13864
|
||||
- feat: enable message bus integration by default by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14329
|
||||
- docs: Recommend using --debug intead of --verbose for CLI debugging by @bbiggs
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14334
|
||||
- feat: consolidate remote MCP servers to use `url` in config by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/13762
|
||||
- Restrict integration tests tools by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14403
|
||||
- track github repository names in telemetry events by @IamRiddhi in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13670
|
||||
- Allow telemetry exporters to GCP to utilize user's login credentials, if
|
||||
requested by @mboshernitsan in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13778
|
||||
- refactor(editor): use const assertion for editor types with single source of
|
||||
truth by @amsminn in https://github.com/google-gemini/gemini-cli/pull/8604
|
||||
- fix(security): Fix npm audit vulnerabilities in glob and body-parser by
|
||||
@afarber in https://github.com/google-gemini/gemini-cli/pull/14090
|
||||
- Add new enterprise instructions by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/8641
|
||||
- feat(hooks): Hook Session Lifecycle & Compression Integration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14151
|
||||
- Avoid triggering refreshStatic unless there really is a banner to display. by
|
||||
@jacob314 in https://github.com/google-gemini/gemini-cli/pull/14328
|
||||
- feat(hooks): Hooks Commands Panel, Enable/Disable, and Migrate by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14225
|
||||
- fix: Bundle default policies for npx distribution by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14457
|
||||
- feat(hooks): Hook System Documentation by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14307
|
||||
- Fix tests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14458
|
||||
- feat: add scheduled workflow to close stale issues by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14404
|
||||
- feat: Support Extension Hooks with Security Warning by @abhipatel12 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14460
|
||||
- feat: Add enableAgents experimental flag by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14371
|
||||
- docs: fix typo 'socus' to 'focus' in todos.md by @Viktor286 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14374
|
||||
- Markdown export: move the emoji to the end of the line by @mhansen in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12278
|
||||
- fix(acp): prevent unnecessary credential cache clearing on re-authent… by
|
||||
@h-michael in https://github.com/google-gemini/gemini-cli/pull/9410
|
||||
- fix(cli): Fix word navigation for CJK characters by @SandyTao520 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14475
|
||||
- Remove example extension by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14376
|
||||
- Add commands for listing and updating per-extension settings by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12664
|
||||
- chore(tests): remove obsolete test for hierarchical memory by @pareshjoshij in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13122
|
||||
- feat(cli): support /copy in remote sessions using OSC52 by @ismellpillows in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13471
|
||||
- Update setting search UX by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14451
|
||||
- Fix(cli): Improve Homebrew update instruction to specify gemini-cli by
|
||||
@DaanVersavel in https://github.com/google-gemini/gemini-cli/pull/14502
|
||||
- do not toggle the setting item when entering space by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14489
|
||||
- fix: improve retry logic for fetch errors and network codes by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14439
|
||||
- remove unused isSearching field by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14509
|
||||
- feat(mcp): add `--type` alias for `--transport` flag in gemini mcp add by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14503
|
||||
- feat(cli): Move key restore logic to core by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13013
|
||||
- feat: add auto-execute on Enter behavior to argumentless MCP prompts by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14510
|
||||
- fix(shell): cursor visibility when using interactive mode by @aswinashok44 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14095
|
||||
- Adding session id as part of json o/p by @MJjainam in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14504
|
||||
- fix(extensions): resolve GitHub API 415 error for source tarballs by
|
||||
@jpoehnelt in https://github.com/google-gemini/gemini-cli/pull/13319
|
||||
- fix(client): Correctly latch hasFailedCompressionAttempt flag by @pareshjoshij
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13002
|
||||
- Disable flaky extension reloading test on linux by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14528
|
||||
- Add support for MCP dynamic tool update by `notifications/tools/list_changed`
|
||||
by @Adib234 in https://github.com/google-gemini/gemini-cli/pull/14375
|
||||
- Fix privacy screen for legacy tier users by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14522
|
||||
- feat: Exclude maintainer labeled issues from stale issue closer by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14532
|
||||
- Grant chained workflows proper permission. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14534
|
||||
- Make trigger_e2e manually fireable. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14547
|
||||
- Write e2e status to local repo not forked repo by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14549
|
||||
- Fixes [API Error: Cannot read properties of undefined (reading 'error')] by
|
||||
@silviojr in https://github.com/google-gemini/gemini-cli/pull/14553
|
||||
- Trigger chained e2e tests on all pull requests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14551
|
||||
- Fix bug in the shellExecutionService resulting in both truncation and 3X bloat
|
||||
by @jacob314 in https://github.com/google-gemini/gemini-cli/pull/14545
|
||||
- Fix issue where we were passing the model content reflecting terminal line
|
||||
wrapping. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14566
|
||||
- chore/release: bump version to 0.21.0-nightly.20251204.3da4fd5f7 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14476
|
||||
- feat(sessions): use 1-line generated session summary to describe sessions by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14467
|
||||
- Use Robot PAT for chained e2e merge queue skipper by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14585
|
||||
- fix(core): improve API response error handling and retry logic by @mattKorwel
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14563
|
||||
- Docs: Model routing clarification by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14373
|
||||
- expose previewFeatures flag in a2a by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14550
|
||||
- Fix emoji width in debug console. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14593
|
||||
- Fully detach autoupgrade process by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14595
|
||||
- Docs: Update Gemini 3 on Gemini CLI documentation by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14601
|
||||
- Disallow floating promises. by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14605
|
||||
- chore/release: bump version to 0.21.0-nightly.20251207.025e450ac by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14662
|
||||
- feat(modelAvailabilityService): integrate model availability service into
|
||||
backend logic by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14470
|
||||
- Add prompt_id propagation in a2a-server task by @koxkox111 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14581
|
||||
- Fix: Prevent freezing in non-interactive Gemini CLI when debug mode is enabled
|
||||
by @parthasaradhie in https://github.com/google-gemini/gemini-cli/pull/14580
|
||||
- fix(audio): improve reading of audio files by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14658
|
||||
- Update automated triage workflow to stop assigning priority labels by
|
||||
@skeshive in https://github.com/google-gemini/gemini-cli/pull/14717
|
||||
- set failed status when chained e2e fails by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14725
|
||||
- feat(github action) Triage and Label Pull Requests by Size and Comple… by
|
||||
@DaanVersavel in https://github.com/google-gemini/gemini-cli/pull/5571
|
||||
- refactor(telemetry): Improve previous PR that allows telemetry to use the CLI
|
||||
auth and add testing by @mboshernitsan in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14589
|
||||
- Always set status in chained_e2e workflow by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14730
|
||||
- feat: Add OTEL log event `gemini_cli.startup_stats` for startup stats. by
|
||||
@kevin-ramdass in https://github.com/google-gemini/gemini-cli/pull/14734
|
||||
- feat: auto-execute on slash command completion functions by @jackwotherspoon
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14584
|
||||
- Docs: Proper release notes by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14405
|
||||
- Add support for user-scoped extension settings by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13748
|
||||
- refactor(core): Improve environment variable handling in shell execution by
|
||||
@galz10 in https://github.com/google-gemini/gemini-cli/pull/14742
|
||||
- Remove old E2E Workflows by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14749
|
||||
- fix: handle missing local extension config and skip hooks when disabled by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/14744
|
||||
- chore/release: bump version to 0.21.0-nightly.20251209.ec9a8c7a7 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14751
|
||||
- feat: Add support for MCP Resources by @MrLesk in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13178
|
||||
- Always set pending status in E2E tests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14756
|
||||
- fix(lint): upgrade pip and use public pypi for yamllint by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14746
|
||||
- fix: use Gemini API supported image formats for clipboard by @jackwotherspoon
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14762
|
||||
- feat(a2a): Introduce restore command for a2a server by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13015
|
||||
- allow final:true to be returned on a2a server edit calls. by @DavidAPierce in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14747
|
||||
- (fix) Automated pr labeller by @DaanVersavel in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14788
|
||||
- Update CODEOWNERS by @kklashtorny1 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14830
|
||||
- Docs: Fix errors preventing site rebuild. by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14842
|
||||
- chore(deps): bump express from 5.1.0 to 5.2.0 by @dependabot[bot] in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14325
|
||||
- fix(patch): cherry-pick 3f5f030 to release/v0.21.0-preview.0-pr-14843 to patch
|
||||
version v0.21.0-preview.0 and create version 0.21.0-preview.1 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14851
|
||||
- fix(patch): cherry-pick ee6556c to release/v0.21.0-preview.1-pr-14691 to patch
|
||||
version v0.21.0-preview.1 and create version 0.21.0-preview.2 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14908
|
||||
- fix(patch): cherry-pick 54de675 to release/v0.21.0-preview.2-pr-14961 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14968
|
||||
- fix(patch): cherry-pick 12cbe32 to release/v0.21.0-preview.3-pr-15000 to patch
|
||||
version v0.21.0-preview.3 and create version 0.21.0-preview.4 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15003
|
||||
- fix(patch): cherry-pick edbe548 to release/v0.21.0-preview.4-pr-15007 to patch
|
||||
version v0.21.0-preview.4 and create version 0.21.0-preview.5 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15015
|
||||
- fix(patch): cherry-pick 2995af6 to release/v0.21.0-preview.5-pr-15131 to patch
|
||||
version v0.21.0-preview.5 and create version 0.21.0-preview.6 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15153
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.20.2...v0.21.0
|
||||
|
||||
## Release v0.22.0-preview-0 (Preview)
|
||||
|
||||
### What's Changed
|
||||
|
||||
- feat(ide): fallback to GEMINI_CLI_IDE_AUTH_TOKEN env var by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14843
|
||||
- feat: display quota stats for unused models in /stats by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14764
|
||||
- feat: ensure codebase investigator uses preview model when main agent does by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/14412
|
||||
- chore: add closing reason to stale bug workflow by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14861
|
||||
- Send the model and CLI version with the user agent by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14865
|
||||
- refactor(sessions): move session summary generation to startup by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/14691
|
||||
- Limit search depth in path corrector by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14869
|
||||
- Fix: Correct typo in code comment by @kuishou68 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14671
|
||||
- feat(core): Plumbing for late resolution of model configs. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14597
|
||||
- feat: attempt more error parsing by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14899
|
||||
- Add missing await. by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14910
|
||||
- feat(core): Add support for transcript_path in hooks for git-ai/Gemini
|
||||
extension by @svarlamov in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14663
|
||||
- refactor: implement DelegateToAgentTool with discriminated union by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/14769
|
||||
- feat: reset availabilityService on /auth by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14911
|
||||
- chore/release: bump version to 0.21.0-nightly.20251211.8c83e1ea9 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14924
|
||||
- Fix: Correctly detect MCP tool errors by @kevin-ramdass in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14937
|
||||
- increase labeler timeout by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14922
|
||||
- tool(cli): tweak the frontend tool to be aware of more core files from the cli
|
||||
by @jacob314 in https://github.com/google-gemini/gemini-cli/pull/14962
|
||||
- feat(cli): polish cached token stats and simplify stats display when quota is
|
||||
present. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14961
|
||||
- feat(settings-validation): add validation for settings schema by @lifefloating
|
||||
in https://github.com/google-gemini/gemini-cli/pull/12929
|
||||
- fix(ide): Update IDE extension to write auth token in env var by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14999
|
||||
- Revert "chore(deps): bump express from 5.1.0 to 5.2.0" by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14998
|
||||
- feat(a2a): Introduce /init command for a2a server by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13419
|
||||
- feat: support multi-file drag and drop of images by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14832
|
||||
- fix(policy): allow codebase_investigator by default in read-only policy by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/15000
|
||||
- refactor(ide ext): Update port file name + switch to 1-based index for
|
||||
characters + remove truncation text by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/10501
|
||||
- fix(vscode-ide-companion): correct license generation for workspace
|
||||
dependencies by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15004
|
||||
- fix: temp fix for subagent invocation until subagent delegation is merged to
|
||||
stable by @abhipatel12 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15007
|
||||
- test: update ide detection tests to make them more robust when run in an ide
|
||||
by @kevin-ramdass in https://github.com/google-gemini/gemini-cli/pull/15008
|
||||
- Remove flex from stats display. See snapshots for diffs. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14983
|
||||
- Add license field into package.json by @jb-perez in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14473
|
||||
- feat: Persistent "Always Allow" policies with granular shell & MCP support by
|
||||
@allenhutchison in https://github.com/google-gemini/gemini-cli/pull/14737
|
||||
- chore/release: bump version to 0.21.0-nightly.20251212.54de67536 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14969
|
||||
- fix(core): commandPrefix word boundary and compound command safety by
|
||||
@allenhutchison in https://github.com/google-gemini/gemini-cli/pull/15006
|
||||
- chore(docs): add 'Maintainers only' label info to CONTRIBUTING.md by @jacob314
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14914
|
||||
- Refresh hooks when refreshing extensions. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14918
|
||||
- Add clarity to error messages by @gsehgal in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14879
|
||||
- chore : remove a redundant tip by @JayadityaGit in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14947
|
||||
- chore/release: bump version to 0.21.0-nightly.20251213.977248e09 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/15029
|
||||
- Disallow redundant typecasts. by @gundermanc in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15030
|
||||
- fix(auth): prioritize GEMINI_API_KEY env var and skip unnecessary key… by
|
||||
@galz10 in https://github.com/google-gemini/gemini-cli/pull/14745
|
||||
- fix: use zod for safety check result validation by @allenhutchison in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15026
|
||||
- update(telemetry): add hashed_extension_name to field to extension events by
|
||||
@kiranani in https://github.com/google-gemini/gemini-cli/pull/15025
|
||||
- fix: similar to policy-engine, throw error in case of requiring tool execution
|
||||
confirmation for non-interactive mode by @MayV in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14702
|
||||
- Clean up processes in integration tests by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15102
|
||||
- docs: update policy engine getting started and defaults by @NTaylorMullen in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15105
|
||||
- Fix tool output fragmentation by encapsulating content in functionResponse by
|
||||
@abhipatel12 in https://github.com/google-gemini/gemini-cli/pull/13082
|
||||
- Simplify method signature. by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15114
|
||||
- Show raw input token counts in json output. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15021
|
||||
- fix: Mark A2A requests as interactive by @MayV in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15108
|
||||
- use previewFeatures to determine which pro model to use for A2A by @sehoon38
|
||||
in https://github.com/google-gemini/gemini-cli/pull/15131
|
||||
- refactor(cli): fix settings merging so that settings using the new json format
|
||||
take priority over ones using the old format by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/15116
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.21.0-preview.6...v0.22.0-preview.0
|
||||
|
||||
## Release v0.20.0 - v0.20.2
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Update error codes when process exiting the gemini cli by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13728
|
||||
- chore(release): bump version to 0.20.0-nightly.20251126.d2a6cff4d by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13835
|
||||
- feat(core): Improve request token calculation accuracy by @SandyTao520 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13824
|
||||
- Changes in system instruction to adapt to gemini 3.0 to ensure that the CLI
|
||||
explains its actions before calling tools by @silviojr in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13810
|
||||
- feat(hooks): Hook Tool Execution Integration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9108
|
||||
- Add support for MCP server instructions behind config option by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13432
|
||||
- Update System Instructions for interactive vs non-interactive mode. by
|
||||
@aishaneeshah in https://github.com/google-gemini/gemini-cli/pull/12315
|
||||
- Add consent flag to Link command by @kevinjwang1 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13832
|
||||
- feat(mcp): Inject GoogleCredentialProvider headers in McpClient by
|
||||
@sai-sunder-s in https://github.com/google-gemini/gemini-cli/pull/13783
|
||||
- feat(core): implement towards policy-driven model fallback mechanism by
|
||||
@adamfweidman in https://github.com/google-gemini/gemini-cli/pull/13781
|
||||
- feat(core): Add configurable inactivity timeout for shell commands by @galz10
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13531
|
||||
- fix(auth): improve API key authentication flow by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13829
|
||||
- feat(hooks): Hook LLM Request/Response Integration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9110
|
||||
- feat(ui): Show waiting MCP servers in ConfigInitDisplay by @werdnum in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13721
|
||||
- Add usage limit remaining in /stats by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13843
|
||||
- feat(shell): Standardize pager to 'cat' for shell execution by model by
|
||||
@galz10 in https://github.com/google-gemini/gemini-cli/pull/13878
|
||||
- chore/release: bump version to 0.20.0-nightly.20251127.5bed97064 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13877
|
||||
- Revert to default LICENSE (Revert #13449) by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13876
|
||||
- update(telemetry): OTel API response event with finish reasons by @kiranani in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13849
|
||||
- feat(hooks): Hooks Comprehensive Integration Testing by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9112
|
||||
- chore: fix session browser test and skip hook system tests by @jackwotherspoon
|
||||
in https://github.com/google-gemini/gemini-cli/pull/14099
|
||||
- feat(telemetry): Add Semantic logging for to ApiRequestEvents by @kiranani in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13912
|
||||
- test: Add verification for $schema property in settings schema by
|
||||
@maryamariyan in https://github.com/google-gemini/gemini-cli/pull/13497
|
||||
- Fixes `/clear` command to preserve input history for up-arrow navigation while
|
||||
still clearing the context window and screen by @korade-krushna in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14182
|
||||
- fix(core): handle EPIPE error in hook runner when writing to stdin by
|
||||
@SandyTao520 in https://github.com/google-gemini/gemini-cli/pull/14231
|
||||
- fix: Exclude web-fetch tool from executing in default non-interactive mode to
|
||||
avoid CLI hang. by @MayV in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14244
|
||||
- Always use MCP server instructions by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14297
|
||||
- feat: auto-execute simple slash commands on Enter by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13985
|
||||
- chore/release: bump version to 0.20.0-nightly.20251201.2fe609cb6 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14304
|
||||
- feat: Add startup profiler to measure and record application initialization
|
||||
phases. by @kevin-ramdass in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13638
|
||||
- bug(core): Avoid stateful tool use in `executor`. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14305
|
||||
- feat(themes): add built-in holiday theme 🎁 by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14301
|
||||
- Updated ToC on docs intro; updated title casing to match Google style by
|
||||
@pcoet in https://github.com/google-gemini/gemini-cli/pull/13717
|
||||
- feat(a2a): Urgent fix - Process modelInfo agent message by @cocosheng-g in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14315
|
||||
- feat(core): enhance availability routing with wrapped fallback and
|
||||
single-model policies by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13874
|
||||
- chore(logging): log the problematic event for #12122 by @briandealwis in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14092
|
||||
- fix: remove invalid type key in bug_report.yml by @fancive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13576
|
||||
- update screenshot by @Transient-Onlooker in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13976
|
||||
- docs: Fix grammar error in Release Cadence (Nightly section) by @JuanCS-Dev in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13866
|
||||
- fix(async): prevent missed async errors from bypassing catch handlers by
|
||||
@amsminn in https://github.com/google-gemini/gemini-cli/pull/13714
|
||||
- fix(zed-integration): remove extra field from acp auth request by
|
||||
@marcocondrache in https://github.com/google-gemini/gemini-cli/pull/13646
|
||||
- feat(cli): Documentation for model configs. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12967
|
||||
- fix(ui): misaligned markdown table rendering by @dumbbellcode in
|
||||
https://github.com/google-gemini/gemini-cli/pull/8336
|
||||
- docs: Update 4 files by @g-samroberts in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13628
|
||||
- fix: Conditionally add set -eEuo pipefail in setup-github command by @Smetalo
|
||||
in https://github.com/google-gemini/gemini-cli/pull/8550
|
||||
- fix(cli): fix issue updating a component while rendering a different component
|
||||
by @jacob314 in https://github.com/google-gemini/gemini-cli/pull/14319
|
||||
- Increase flakey test timeout by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14377
|
||||
- Remove references to deleted kind/bug label by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14383
|
||||
- Don't fail test if we can't cleanup by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14389
|
||||
- feat(core): Implement JIT context manager and setting by @SandyTao520 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14324
|
||||
- Use polling for extensions-reload integration test by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14391
|
||||
- Add docs directive to GEMINI.md by @g-samroberts in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14327
|
||||
- Hide sessions that don't have user messages by @bl-ue in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13994
|
||||
- chore(ci): mark GitHub release as pre-release if not on "latest" npm channel
|
||||
by @ljxfstorm in https://github.com/google-gemini/gemini-cli/pull/7386
|
||||
- fix(patch): cherry-pick d284fa6 to release/v0.20.0-preview.0-pr-14545
|
||||
[CONFLICTS] by @gemini-cli-robot in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14559
|
||||
- fix(patch): cherry-pick 828afe1 to release/v0.20.0-preview.1-pr-14159 to patch
|
||||
version v0.20.0-preview.1 and create version 0.20.0-preview.2 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14733
|
||||
- fix(patch): cherry-pick 171103a to release/v0.20.0-preview.2-pr-14742 to patch
|
||||
version v0.20.0-preview.2 and create version 0.20.0-preview.5 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/14752
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.19.4...v0.20.0
|
||||
|
||||
## Release v0.19.0 - v0.19.4
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Zed integration:** Users can now leverage Gemini 3 within the Zed
|
||||
integration after enabling "Preview Features" in their CLI’s `/settings`.
|
||||
- **Interactive shell:**
|
||||
- **Click-to-Focus:** Go to `/settings` and enable **Use Alternate Buffer**
|
||||
When "Use Alternate Buffer" setting is enabled users can click within the
|
||||
embedded shell output to focus it for input.
|
||||
- **Loading phrase:** Clearly indicates when the interactive shell is awaiting
|
||||
user input. ([vid](https://imgur.com/a/kjK8bUK)
|
||||
[pr](https://github.com/google-gemini/gemini-cli/pull/12535) by
|
||||
[@jackwotherspoon](https://github.com/jackwotherspoon))
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Use lenient MCP output schema validator by @cornmander in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13521
|
||||
- Update persistence state to track counts of messages instead of times banner
|
||||
has been displayed by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13428
|
||||
- update docs for http proxy by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13538
|
||||
- move stdio by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13528
|
||||
- chore(release): bump version to 0.19.0-nightly.20251120.8e531dc02 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13540
|
||||
- Skip pre-commit hooks for shadow repo (#13331) by @vishvananda in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13488
|
||||
- fix(ui): Correct mouse click cursor positioning for wide characters by
|
||||
@SandyTao520 in https://github.com/google-gemini/gemini-cli/pull/13537
|
||||
- fix(core): correct bash @P prompt transformation detection by @pyrytakala in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13544
|
||||
- Optimize and improve test coverage for cli/src/config by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13485
|
||||
- Improve code coverage for cli/src/ui/privacy package by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13493
|
||||
- docs: fix typos in source code and documentation by @fancive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13577
|
||||
- Improved code coverage for cli/src/zed-integration by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13570
|
||||
- feat(ui): build interactive session browser component by @bl-ue in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13351
|
||||
- Fix multiple bugs with auth flow including using the implemented but unused
|
||||
restart support. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13565
|
||||
- feat(core): add modelAvailabilityService for managing and tracking model
|
||||
health by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13426
|
||||
- docs: fix grammar typo "a MCP" to "an MCP" by @noahacgn in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13595
|
||||
- feat: custom loading phrase when interactive shell requires input by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/12535
|
||||
- docs: Update uninstall command to reflect multiple extension support by
|
||||
@JayadityaGit in https://github.com/google-gemini/gemini-cli/pull/13582
|
||||
- bug(core): Ensure we use thinking budget on fallback to 2.5 by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13596
|
||||
- Remove useModelRouter experimental flag by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13593
|
||||
- feat(docs): Ensure multiline JS objects are rendered properly. by @joshualitt
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13535
|
||||
- Fix exp id logging by @owenofbrien in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13430
|
||||
- Moved client id logging into createBasicLogEvent by @owenofbrien in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13607
|
||||
- Restore bracketed paste mode after external editor exit by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13606
|
||||
- feat(core): Add support for custom aliases for model configs. by @joshualitt
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13546
|
||||
- feat(core): Add `BaseLlmClient.generateContent`. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13591
|
||||
- Turn off alternate buffer mode by default. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13623
|
||||
- fix(cli): Prevent stdout/stderr patching for extension commands by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13600
|
||||
- Improve test coverage for cli/src/ui/components by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13598
|
||||
- Update ink version to 6.4.6 by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13631
|
||||
- chore/release: bump version to 0.19.0-nightly.20251122.42c2e1b21 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13637
|
||||
- chore/release: bump version to 0.19.0-nightly.20251123.dadd606c0 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13675
|
||||
- chore/release: bump version to 0.19.0-nightly.20251124.e177314a4 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13713
|
||||
- fix(core): Fix context window overflow warning for PDF files by @kkitase in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13548
|
||||
- feat :rephrasing the extension logging messages to run the explore command
|
||||
when there are no extensions installed by @JayadityaGit in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13740
|
||||
- Improve code coverage for cli package by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13724
|
||||
- Add session subtask in /stats command by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13750
|
||||
- feat(core): Migrate chatCompressionService to model configs. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12863
|
||||
- feat(hooks): Hook Telemetry Infrastructure by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9082
|
||||
- fix: (some minor improvements to configs and getPackageJson return behaviour)
|
||||
by @grMLEqomlkkU5Eeinz4brIrOVCUCkJuN in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12510
|
||||
- feat(hooks): Hook Event Handling by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9097
|
||||
- feat(hooks): Hook Agent Lifecycle Integration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9105
|
||||
- feat(core): Land bool for alternate system prompt. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13764
|
||||
- bug(core): Add default chat compression config. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13766
|
||||
- feat(model-availability): introduce ModelPolicy and PolicyCatalog by
|
||||
@adamfweidman in https://github.com/google-gemini/gemini-cli/pull/13751
|
||||
- feat(hooks): Hook System Orchestration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9102
|
||||
- feat(config): add isModelAvailabilityServiceEnabled setting by @adamfweidman
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13777
|
||||
- chore/release: bump version to 0.19.0-nightly.20251125.f6d97d448 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13782
|
||||
- chore: remove console.error by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13779
|
||||
- fix: Add $schema property to settings.schema.json by @sacrosanctic in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12763
|
||||
- fix(cli): allow non-GitHub SCP-styled URLs for extension installation by @m0ps
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13800
|
||||
- fix(resume): allow passing a prompt via stdin while resuming using --resume by
|
||||
@bl-ue in https://github.com/google-gemini/gemini-cli/pull/13520
|
||||
- feat(sessions): add /resume slash command to open the session browser by
|
||||
@bl-ue in https://github.com/google-gemini/gemini-cli/pull/13621
|
||||
- docs(sessions): add documentation for chat recording and session management by
|
||||
@bl-ue in https://github.com/google-gemini/gemini-cli/pull/13667
|
||||
- Fix TypeError: "URL.parse is not a function" for Node.js < v22 by @macarronesc
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13698
|
||||
- fallback to flash for TerminalQuota errors by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13791
|
||||
- Update Code Wiki README badge by @PatoBeltran in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13768
|
||||
- Add Databricks auth support and custom header option to gemini cli by
|
||||
@AarushiShah in https://github.com/google-gemini/gemini-cli/pull/11893
|
||||
- Update dependency for modelcontextprotocol/sdk to 1.23.0 by @bbiggs in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13827
|
||||
- fix(patch): cherry-pick 576fda1 to release/v0.19.0-preview.0-pr-14099
|
||||
[CONFLICTS] by @gemini-cli-robot in
|
||||
https://github.com/google-gemini/gemini-cli/pull/14402
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.18.4...v0.19.0
|
||||
|
||||
## Release v0.19.0-preview.0
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Use lenient MCP output schema validator by @cornmander in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13521
|
||||
- Update persistence state to track counts of messages instead of times banner
|
||||
has been displayed by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13428
|
||||
- update docs for http proxy by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13538
|
||||
- move stdio by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13528
|
||||
- chore(release): bump version to 0.19.0-nightly.20251120.8e531dc02 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13540
|
||||
- Skip pre-commit hooks for shadow repo (#13331) by @vishvananda in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13488
|
||||
- fix(ui): Correct mouse click cursor positioning for wide characters by
|
||||
@SandyTao520 in https://github.com/google-gemini/gemini-cli/pull/13537
|
||||
- fix(core): correct bash @P prompt transformation detection by @pyrytakala in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13544
|
||||
- Optimize and improve test coverage for cli/src/config by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13485
|
||||
- Improve code coverage for cli/src/ui/privacy package by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13493
|
||||
- docs: fix typos in source code and documentation by @fancive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13577
|
||||
- Improved code coverage for cli/src/zed-integration by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13570
|
||||
- feat(ui): build interactive session browser component by @bl-ue in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13351
|
||||
- Fix multiple bugs with auth flow including using the implemented but unused
|
||||
restart support. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13565
|
||||
- feat(core): add modelAvailabilityService for managing and tracking model
|
||||
health by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13426
|
||||
- docs: fix grammar typo "a MCP" to "an MCP" by @noahacgn in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13595
|
||||
- feat: custom loading phrase when interactive shell requires input by
|
||||
@jackwotherspoon in https://github.com/google-gemini/gemini-cli/pull/12535
|
||||
- docs: Update uninstall command to reflect multiple extension support by
|
||||
@JayadityaGit in https://github.com/google-gemini/gemini-cli/pull/13582
|
||||
- bug(core): Ensure we use thinking budget on fallback to 2.5 by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13596
|
||||
- Remove useModelRouter experimental flag by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13593
|
||||
- feat(docs): Ensure multiline JS objects are rendered properly. by @joshualitt
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13535
|
||||
- Fix exp id logging by @owenofbrien in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13430
|
||||
- Moved client id logging into createBasicLogEvent by @owenofbrien in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13607
|
||||
- Restore bracketed paste mode after external editor exit by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13606
|
||||
- feat(core): Add support for custom aliases for model configs. by @joshualitt
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13546
|
||||
- feat(core): Add `BaseLlmClient.generateContent`. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13591
|
||||
- Turn off alternate buffer mode by default. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13623
|
||||
- fix(cli): Prevent stdout/stderr patching for extension commands by @chrstnb in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13600
|
||||
- Improve test coverage for cli/src/ui/components by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13598
|
||||
- Update ink version to 6.4.6 by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13631
|
||||
- chore/release: bump version to 0.19.0-nightly.20251122.42c2e1b21 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13637
|
||||
- chore/release: bump version to 0.19.0-nightly.20251123.dadd606c0 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13675
|
||||
- chore/release: bump version to 0.19.0-nightly.20251124.e177314a4 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13713
|
||||
- fix(core): Fix context window overflow warning for PDF files by @kkitase in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13548
|
||||
- feat :rephrasing the extension logging messages to run the explore command
|
||||
when there are no extensions installed by @JayadityaGit in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13740
|
||||
- Improve code coverage for cli package by @megha1188 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13724
|
||||
- Add session subtask in /stats command by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13750
|
||||
- feat(core): Migrate chatCompressionService to model configs. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12863
|
||||
- feat(hooks): Hook Telemetry Infrastructure by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9082
|
||||
- fix: (some minor improvements to configs and getPackageJson return behaviour)
|
||||
by @grMLEqomlkkU5Eeinz4brIrOVCUCkJuN in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12510
|
||||
- feat(hooks): Hook Event Handling by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9097
|
||||
- feat(hooks): Hook Agent Lifecycle Integration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9105
|
||||
- feat(core): Land bool for alternate system prompt. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13764
|
||||
- bug(core): Add default chat compression config. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13766
|
||||
- feat(model-availability): introduce ModelPolicy and PolicyCatalog by
|
||||
@adamfweidman in https://github.com/google-gemini/gemini-cli/pull/13751
|
||||
- feat(hooks): Hook System Orchestration by @Edilmo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/9102
|
||||
- feat(config): add isModelAvailabilityServiceEnabled setting by @adamfweidman
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13777
|
||||
- chore/release: bump version to 0.19.0-nightly.20251125.f6d97d448 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13782
|
||||
- chore: remove console.error by @adamfweidman in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13779
|
||||
- fix: Add $schema property to settings.schema.json by @sacrosanctic in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12763
|
||||
- fix(cli): allow non-GitHub SCP-styled URLs for extension installation by @m0ps
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13800
|
||||
- fix(resume): allow passing a prompt via stdin while resuming using --resume by
|
||||
@bl-ue in https://github.com/google-gemini/gemini-cli/pull/13520
|
||||
- feat(sessions): add /resume slash command to open the session browser by
|
||||
@bl-ue in https://github.com/google-gemini/gemini-cli/pull/13621
|
||||
- docs(sessions): add documentation for chat recording and session management by
|
||||
@bl-ue in https://github.com/google-gemini/gemini-cli/pull/13667
|
||||
- Fix TypeError: "URL.parse is not a function" for Node.js < v22 by @macarronesc
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13698
|
||||
- fallback to flash for TerminalQuota errors by @sehoon38 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13791
|
||||
- Update Code Wiki README badge by @PatoBeltran in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13768
|
||||
- Add Databricks auth support and custom header option to gemini cli by
|
||||
@AarushiShah in https://github.com/google-gemini/gemini-cli/pull/11893
|
||||
- Update dependency for modelcontextprotocol/sdk to 1.23.0 by @bbiggs in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13827
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.18.0-preview.4...v0.19.0-preview.0
|
||||
|
||||
## Release v0.18.0 - v0.18.4
|
||||
|
||||
### Highlights
|
||||
|
||||
- **Experimental permission improvements**: We're experimenting with a new
|
||||
policy engine in Gemini CLI, letting users and administrators create
|
||||
fine-grained policies for tool calls. This setting is currently behind a flag.
|
||||
See our [policy engine documentation](../core/policy-engine.md) to learn how
|
||||
to use this feature.
|
||||
- **Gemini 3 support rolled out for some users**: Some users can now enable
|
||||
Gemini 3 by using the `/settings` flag and toggling **Preview Features**. See
|
||||
our [Gemini 3 on Gemini CLI documentation](../get-started/gemini-3.md) to find
|
||||
out more about using Gemini 3.
|
||||
- **Updated UI rollback:** We've temporarily rolled back a previous UI update,
|
||||
which enabled embedded scrolling and mouse support. This can be re-enabled by
|
||||
using the `/settings` command and setting **Use Alternate Screen Buffer** to
|
||||
`true`.
|
||||
- **Display your model in your chat history**: You can now go use `/settings`
|
||||
and turn on **Show Model in Chat** to display the model in your chat history.
|
||||
- **Uninstall multiple extensions**: You can uninstall multiple extensions with
|
||||
a single command: `gemini extensions uninstall`.
|
||||
|
||||

|
||||
|
||||
### What's changed
|
||||
|
||||
- Remove obsolete reference to "help wanted" label in CONTRIBUTING.md by
|
||||
@aswinashok44 in https://github.com/google-gemini/gemini-cli/pull/13291
|
||||
- chore(release): v0.18.0-nightly.20251118.86828bb56 by @skeshive in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13309
|
||||
- Docs: Access clarification. by @jkcinouye in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13304
|
||||
- Fix links in Gemini 3 Pro documentation by @gmackall in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13312
|
||||
- Improve keyboard code parsing by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13307
|
||||
- fix(core): Ensure `read_many_files` tool is available to zed. by @joshualitt
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13338
|
||||
- Support 3-parameter modifyOtherKeys sequences by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13342
|
||||
- Improve pty resize error handling for Windows by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13353
|
||||
- fix(ui): Clear input prompt on Escape key press by @SandyTao520 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13335
|
||||
- bug(ui) showLineNumbers had the wrong default value. by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13356
|
||||
- fix(cli): fix crash on startup in NO_COLOR mode (#13343) due to ungua… by
|
||||
@avilladsen in https://github.com/google-gemini/gemini-cli/pull/13352
|
||||
- fix: allow MCP prompts with spaces in name by @jackwotherspoon in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12910
|
||||
- Refactor createTransport to duplicate less code by @davidmcwherter in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13010
|
||||
- Followup from #10719 by @bl-ue in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13243
|
||||
- Capturing github action workflow name if present and send it to clearcut by
|
||||
@MJjainam in https://github.com/google-gemini/gemini-cli/pull/13132
|
||||
- feat(sessions): record interactive-only errors and warnings to chat recording
|
||||
JSON files by @bl-ue in https://github.com/google-gemini/gemini-cli/pull/13300
|
||||
- fix(zed-integration): Correctly handle cancellation errors by @benbrandt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13399
|
||||
- docs: Add Code Wiki link to README by @holtskinner in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13289
|
||||
- Restore keyboard mode when exiting the editor by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13350
|
||||
- feat(core, cli): Bump genai version to 1.30.0 by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13435
|
||||
- [cli-ui] Keep header ASCII art colored on non-gradient terminals (#13373) by
|
||||
@bniladridas in https://github.com/google-gemini/gemini-cli/pull/13374
|
||||
- Fix Copyright line in LICENSE by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13449
|
||||
- Fix typo in write_todos methodology instructions by @Smetalo in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13411
|
||||
- feat: update thinking mode support to exclude gemini-2.0 models and simplify
|
||||
logic. by @kevin-ramdass in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13454
|
||||
- remove unneeded log by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13456
|
||||
- feat: add click-to-focus support for interactive shell by @galz10 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13341
|
||||
- Add User email detail to about box by @ptone in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13459
|
||||
- feat(core): Wire up chat code path for model configs. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/12850
|
||||
- chore/release: bump version to 0.18.0-nightly.20251120.2231497b1 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13476
|
||||
- feat(core): Fix bug with incorrect model overriding. by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13477
|
||||
- Use synchronous writes when detecting keyboard modes by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13478
|
||||
- fix(cli): prevent race condition when restoring prompt after context overflow
|
||||
by @SandyTao520 in https://github.com/google-gemini/gemini-cli/pull/13473
|
||||
- Revert "feat(core): Fix bug with incorrect model overriding." by @adamfweidman
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13483
|
||||
- Fix: Update system instruction when GEMINI.md memory is loaded or refreshed by
|
||||
@lifefloating in https://github.com/google-gemini/gemini-cli/pull/12136
|
||||
- fix(zed-integration): Ensure that the zed integration is classified as
|
||||
interactive by @benbrandt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13394
|
||||
- Copy commands as part of setup-github by @gsehgal in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13464
|
||||
- Update banner design by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13420
|
||||
- Protect stdout and stderr so JavaScript code can't accidentally write to
|
||||
stdout corrupting ink rendering by @jacob314 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13247
|
||||
- Enable switching preview features on/off without restart by @Adib234 in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13515
|
||||
- feat(core): Use thinking level for Gemini 3 by @joshualitt in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13445
|
||||
- Change default compress threshold to 0.5 for api key users by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13517
|
||||
- remove duplicated mouse code by @scidomino in
|
||||
https://github.com/google-gemini/gemini-cli/pull/13525
|
||||
- feat(zed-integration): Use default model routing for Zed integration by
|
||||
@benbrandt in https://github.com/google-gemini/gemini-cli/pull/13398
|
||||
- feat(core): Incorporate Gemini 3 into model config hierarchy. by @joshualitt
|
||||
in https://github.com/google-gemini/gemini-cli/pull/13447
|
||||
- fix(patch): cherry-pick 5e218a5 to release/v0.18.0-preview.0-pr-13623 to patch
|
||||
version v0.18.0-preview.0 and create version 0.18.0-preview.1 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13626
|
||||
- fix(patch): cherry-pick d351f07 to release/v0.18.0-preview.1-pr-12535 to patch
|
||||
version v0.18.0-preview.1 and create version 0.18.0-preview.2 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13813
|
||||
- fix(patch): cherry-pick 3e50be1 to release/v0.18.0-preview.2-pr-13428 to patch
|
||||
version v0.18.0-preview.2 and create version 0.18.0-preview.3 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13821
|
||||
- fix(patch): cherry-pick d8a3d08 to release/v0.18.0-preview.3-pr-13791 to patch
|
||||
version v0.18.0-preview.3 and create version 0.18.0-preview.4 by
|
||||
@gemini-cli-robot in https://github.com/google-gemini/gemini-cli/pull/13826
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.17.1...v0.18.0
|
||||
@@ -1,3 +0,0 @@
|
||||
# Authentication setup
|
||||
|
||||
See: [Getting Started - Authentication Setup](../get-started/authentication.md).
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
The Gemini CLI includes a Checkpointing feature that automatically saves a
|
||||
snapshot of your project's state before any file modifications are made by
|
||||
AI-powered tools. This allows you to safely experiment with and apply code
|
||||
changes, knowing you can instantly revert back to the state before the tool was
|
||||
run.
|
||||
AI-powered tools. This lets you safely experiment with and apply code changes,
|
||||
knowing you can instantly revert back to the state before the tool was run.
|
||||
|
||||
## How it works
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
# Gemini CLI cheatsheet
|
||||
|
||||
This page provides a reference for commonly used Gemini CLI commands, options,
|
||||
and parameters.
|
||||
|
||||
## CLI commands
|
||||
|
||||
| Command | Description | Example |
|
||||
| ---------------------------------- | ---------------------------------- | ------------------------------------------------------------ |
|
||||
| `gemini` | Start interactive REPL | `gemini` |
|
||||
| `gemini -p "query"` | Query non-interactively | `gemini -p "summarize README.md"` |
|
||||
| `gemini "query"` | Query and continue interactively | `gemini "explain this project"` |
|
||||
| `cat file \| gemini` | Process piped content | `cat logs.txt \| gemini`<br>`Get-Content logs.txt \| gemini` |
|
||||
| `gemini -i "query"` | Execute and continue interactively | `gemini -i "What is the purpose of this project?"` |
|
||||
| `gemini -r "latest"` | Continue most recent session | `gemini -r "latest"` |
|
||||
| `gemini -r "latest" "query"` | Continue session with a new prompt | `gemini -r "latest" "Check for type errors"` |
|
||||
| `gemini -r "<session-id>" "query"` | Resume session by ID | `gemini -r "abc123" "Finish this PR"` |
|
||||
| `gemini update` | Update to latest version | `gemini update` |
|
||||
| `gemini extensions` | Manage extensions | See [Extensions Management](#extensions-management) |
|
||||
| `gemini mcp` | Configure MCP servers | See [MCP Server Management](#mcp-server-management) |
|
||||
|
||||
### Positional arguments
|
||||
|
||||
| Argument | Type | Description |
|
||||
| -------- | ----------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| `query` | string (variadic) | Positional prompt. Defaults to interactive mode in a TTY. Use `-p/--prompt` for non-interactive execution. |
|
||||
|
||||
## Interactive commands
|
||||
|
||||
These commands are available within the interactive REPL.
|
||||
|
||||
| Command | Description |
|
||||
| -------------------- | ---------------------------------------- |
|
||||
| `/skills reload` | Reload discovered skills from disk |
|
||||
| `/agents reload` | Reload the agent registry |
|
||||
| `/commands reload` | Reload custom slash commands |
|
||||
| `/memory reload` | Reload context files (e.g., `GEMINI.md`) |
|
||||
| `/mcp reload` | Restart and reload MCP servers |
|
||||
| `/extensions reload` | Reload all active extensions |
|
||||
| `/help` | Show help for all commands |
|
||||
| `/quit` | Exit the interactive session |
|
||||
|
||||
## CLI Options
|
||||
|
||||
| Option | Alias | Type | Default | Description |
|
||||
| -------------------------------- | ----- | ------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--debug` | `-d` | boolean | `false` | Run in debug mode with verbose logging |
|
||||
| `--version` | `-v` | - | - | Show CLI version number and exit |
|
||||
| `--help` | `-h` | - | - | Show help information |
|
||||
| `--model` | `-m` | string | `auto` | Model to use. See [Model Selection](#model-selection) for available values. |
|
||||
| `--prompt` | `-p` | string | - | Prompt text. Appended to stdin input if provided. Forces non-interactive mode. |
|
||||
| `--prompt-interactive` | `-i` | string | - | Execute prompt and continue in interactive mode |
|
||||
| `--sandbox` | `-s` | boolean | `false` | Run in a sandboxed environment for safer execution |
|
||||
| `--approval-mode` | - | string | `default` | Approval mode for tool execution. Choices: `default`, `auto_edit`, `yolo` |
|
||||
| `--yolo` | `-y` | boolean | `false` | **Deprecated.** Auto-approve all actions. Use `--approval-mode=yolo` instead. |
|
||||
| `--experimental-acp` | - | boolean | - | Start in ACP (Agent Code Pilot) mode. **Experimental feature.** |
|
||||
| `--experimental-zed-integration` | - | boolean | - | Run in Zed editor integration mode. **Experimental feature.** |
|
||||
| `--allowed-mcp-server-names` | - | array | - | Allowed MCP server names (comma-separated or multiple flags) |
|
||||
| `--allowed-tools` | - | array | - | **Deprecated.** Use the [Policy Engine](../reference/policy-engine.md) instead. Tools that are allowed to run without confirmation (comma-separated or multiple flags) |
|
||||
| `--extensions` | `-e` | array | - | List of extensions to use. If not provided, all extensions are enabled (comma-separated or multiple flags) |
|
||||
| `--list-extensions` | `-l` | boolean | - | List all available extensions and exit |
|
||||
| `--resume` | `-r` | string | - | Resume a previous session. Use `"latest"` for most recent or index number (e.g. `--resume 5`) |
|
||||
| `--list-sessions` | - | boolean | - | List available sessions for the current project and exit |
|
||||
| `--delete-session` | - | string | - | Delete a session by index number (use `--list-sessions` to see available sessions) |
|
||||
| `--include-directories` | - | array | - | Additional directories to include in the workspace (comma-separated or multiple flags) |
|
||||
| `--screen-reader` | - | boolean | - | Enable screen reader mode for accessibility |
|
||||
| `--output-format` | `-o` | string | `text` | The format of the CLI output. Choices: `text`, `json`, `stream-json` |
|
||||
|
||||
## Model selection
|
||||
|
||||
The `--model` (or `-m`) flag lets you specify which Gemini model to use. You can
|
||||
use either model aliases (user-friendly names) or concrete model names.
|
||||
|
||||
### Model aliases
|
||||
|
||||
These are convenient shortcuts that map to specific models:
|
||||
|
||||
| Alias | Resolves To | Description |
|
||||
| ------------ | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `auto` | `gemini-2.5-pro` or `gemini-3-pro-preview` | **Default.** Resolves to the preview model if preview features are enabled, otherwise resolves to the standard pro model. |
|
||||
| `pro` | `gemini-2.5-pro` or `gemini-3-pro-preview` | For complex reasoning tasks. Uses preview model if enabled. |
|
||||
| `flash` | `gemini-2.5-flash` | Fast, balanced model for most tasks. |
|
||||
| `flash-lite` | `gemini-2.5-flash-lite` | Fastest model for simple tasks. |
|
||||
|
||||
## Extensions management
|
||||
|
||||
| Command | Description | Example |
|
||||
| -------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------ |
|
||||
| `gemini extensions install <source>` | Install extension from Git URL or local path | `gemini extensions install https://github.com/user/my-extension` |
|
||||
| `gemini extensions install <source> --ref <ref>` | Install from specific branch/tag/commit | `gemini extensions install https://github.com/user/my-extension --ref develop` |
|
||||
| `gemini extensions install <source> --auto-update` | Install with auto-update enabled | `gemini extensions install https://github.com/user/my-extension --auto-update` |
|
||||
| `gemini extensions uninstall <name>` | Uninstall one or more extensions | `gemini extensions uninstall my-extension` |
|
||||
| `gemini extensions list` | List all installed extensions | `gemini extensions list` |
|
||||
| `gemini extensions update <name>` | Update a specific extension | `gemini extensions update my-extension` |
|
||||
| `gemini extensions update --all` | Update all extensions | `gemini extensions update --all` |
|
||||
| `gemini extensions enable <name>` | Enable an extension | `gemini extensions enable my-extension` |
|
||||
| `gemini extensions disable <name>` | Disable an extension | `gemini extensions disable my-extension` |
|
||||
| `gemini extensions link <path>` | Link local extension for development | `gemini extensions link /path/to/extension` |
|
||||
| `gemini extensions new <path>` | Create new extension from template | `gemini extensions new ./my-extension` |
|
||||
| `gemini extensions validate <path>` | Validate extension structure | `gemini extensions validate ./my-extension` |
|
||||
|
||||
See [Extensions Documentation](../extensions/index.md) for more details.
|
||||
|
||||
## MCP server management
|
||||
|
||||
| Command | Description | Example |
|
||||
| ------------------------------------------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `gemini mcp add <name> <command>` | Add stdio-based MCP server | `gemini mcp add github npx -y @modelcontextprotocol/server-github` |
|
||||
| `gemini mcp add <name> <url> --transport http` | Add HTTP-based MCP server | `gemini mcp add api-server http://localhost:3000 --transport http` |
|
||||
| `gemini mcp add <name> <command> --env KEY=value` | Add with environment variables | `gemini mcp add slack node server.js --env SLACK_TOKEN=xoxb-xxx` |
|
||||
| `gemini mcp add <name> <command> --scope user` | Add with user scope | `gemini mcp add db node db-server.js --scope user` |
|
||||
| `gemini mcp add <name> <command> --include-tools tool1,tool2` | Add with specific tools | `gemini mcp add github npx -y @modelcontextprotocol/server-github --include-tools list_repos,get_pr` |
|
||||
| `gemini mcp remove <name>` | Remove an MCP server | `gemini mcp remove github` |
|
||||
| `gemini mcp list` | List all configured MCP servers | `gemini mcp list` |
|
||||
|
||||
See [MCP Server Integration](../tools/mcp-server.md) for more details.
|
||||
|
||||
## Skills management
|
||||
|
||||
| Command | Description | Example |
|
||||
| -------------------------------- | ------------------------------------- | ------------------------------------------------- |
|
||||
| `gemini skills list` | List all discovered agent skills | `gemini skills list` |
|
||||
| `gemini skills install <source>` | Install skill from Git, path, or file | `gemini skills install https://github.com/u/repo` |
|
||||
| `gemini skills link <path>` | Link local agent skills via symlink | `gemini skills link /path/to/my-skills` |
|
||||
| `gemini skills uninstall <name>` | Uninstall an agent skill | `gemini skills uninstall my-skill` |
|
||||
| `gemini skills enable <name>` | Enable an agent skill | `gemini skills enable my-skill` |
|
||||
| `gemini skills disable <name>` | Disable an agent skill | `gemini skills disable my-skill` |
|
||||
| `gemini skills enable --all` | Enable all skills | `gemini skills enable --all` |
|
||||
| `gemini skills disable --all` | Disable all skills | `gemini skills disable --all` |
|
||||
|
||||
See [Agent Skills Documentation](./skills.md) for more details.
|
||||
@@ -1,354 +0,0 @@
|
||||
# CLI commands
|
||||
|
||||
Gemini CLI supports several built-in commands to help you manage your session,
|
||||
customize the interface, and control its behavior. These commands are prefixed
|
||||
with a forward slash (`/`), an at symbol (`@`), or an exclamation mark (`!`).
|
||||
|
||||
## Slash commands (`/`)
|
||||
|
||||
Slash commands provide meta-level control over the CLI itself.
|
||||
|
||||
### Built-in Commands
|
||||
|
||||
- **`/bug`**
|
||||
- **Description:** File an issue about Gemini CLI. By default, the issue is
|
||||
filed within the GitHub repository for Gemini CLI. The string you enter
|
||||
after `/bug` will become the headline for the bug being filed. The default
|
||||
`/bug` behavior can be modified using the `advanced.bugCommand` setting in
|
||||
your `.gemini/settings.json` files.
|
||||
|
||||
- **`/chat`**
|
||||
- **Description:** Save and resume conversation history for branching
|
||||
conversation state interactively, or resuming a previous state from a later
|
||||
session.
|
||||
- **Sub-commands:**
|
||||
- **`save`**
|
||||
- **Description:** Saves the current conversation history. You must add a
|
||||
`<tag>` for identifying the conversation state.
|
||||
- **Usage:** `/chat save <tag>`
|
||||
- **Details on checkpoint location:** The default locations for saved chat
|
||||
checkpoints are:
|
||||
- Linux/macOS: `~/.gemini/tmp/<project_hash>/`
|
||||
- Windows: `C:\Users\<YourUsername>\.gemini\tmp\<project_hash>\`
|
||||
- **Behavior:** Chats are saved into a project-specific directory,
|
||||
determined by where you run the CLI. Consequently, saved chats are
|
||||
only accessible when working within that same project.
|
||||
- **Note:** These checkpoints are for manually saving and resuming
|
||||
conversation states. For automatic checkpoints created before file
|
||||
modifications, see the
|
||||
[Checkpointing documentation](../cli/checkpointing.md).
|
||||
- **`resume`**
|
||||
- **Description:** Resumes a conversation from a previous save.
|
||||
- **Usage:** `/chat resume <tag>`
|
||||
- **Note:** You can only resume chats that were saved within the current
|
||||
project. To resume a chat from a different project, you must run the
|
||||
Gemini CLI from that project's directory.
|
||||
- **`list`**
|
||||
- **Description:** Lists available tags for chat state resumption.
|
||||
- **Note:** This command only lists chats saved within the current
|
||||
project. Because chat history is project-scoped, chats saved in other
|
||||
project directories will not be displayed.
|
||||
- **`delete`**
|
||||
- **Description:** Deletes a saved conversation checkpoint.
|
||||
- **Usage:** `/chat delete <tag>`
|
||||
- **`share`**
|
||||
- **Description** Writes the current conversation to a provided Markdown
|
||||
or JSON file.
|
||||
- **Usage** `/chat share file.md` or `/chat share file.json`. If no
|
||||
filename is provided, then the CLI will generate one.
|
||||
|
||||
- **`/clear`**
|
||||
- **Description:** Clear the terminal screen, including the visible session
|
||||
history and scrollback within the CLI. The underlying session data (for
|
||||
history recall) might be preserved depending on the exact implementation,
|
||||
but the visual display is cleared.
|
||||
- **Keyboard shortcut:** Press **Ctrl+L** at any time to perform a clear
|
||||
action.
|
||||
|
||||
- **`/compress`**
|
||||
- **Description:** Replace the entire chat context with a summary. This saves
|
||||
on tokens used for future tasks while retaining a high level summary of what
|
||||
has happened.
|
||||
|
||||
- **`/copy`**
|
||||
- **Description:** Copies the last output produced by Gemini CLI to your
|
||||
clipboard, for easy sharing or reuse.
|
||||
- **Note:** This command requires platform-specific clipboard tools to be
|
||||
installed.
|
||||
- On Linux, it requires `xclip` or `xsel`. You can typically install them
|
||||
using your system's package manager.
|
||||
- On macOS, it requires `pbcopy`, and on Windows, it requires `clip`. These
|
||||
tools are typically pre-installed on their respective systems.
|
||||
|
||||
- **`/directory`** (or **`/dir`**)
|
||||
- **Description:** Manage workspace directories for multi-directory support.
|
||||
- **Sub-commands:**
|
||||
- **`add`**:
|
||||
- **Description:** Add a directory to the workspace. The path can be
|
||||
absolute or relative to the current working directory. Moreover, the
|
||||
reference from home directory is supported as well.
|
||||
- **Usage:** `/directory add <path1>,<path2>`
|
||||
- **Note:** Disabled in restrictive sandbox profiles. If you're using
|
||||
that, use `--include-directories` when starting the session instead.
|
||||
- **`show`**:
|
||||
- **Description:** Display all directories added by `/directory add` and
|
||||
`--include-directories`.
|
||||
- **Usage:** `/directory show`
|
||||
|
||||
- **`/editor`**
|
||||
- **Description:** Open a dialog for selecting supported editors.
|
||||
|
||||
- **`/extensions`**
|
||||
- **Description:** Lists all active extensions in the current Gemini CLI
|
||||
session. See [Gemini CLI Extensions](../extensions/index.md).
|
||||
|
||||
- **`/help`** (or **`/?`**)
|
||||
- **Description:** Display help information about Gemini CLI, including
|
||||
available commands and their usage.
|
||||
|
||||
- **`/mcp`**
|
||||
- **Description:** Manage configured Model Context Protocol (MCP) servers.
|
||||
- **Sub-commands:**
|
||||
- **`list`** or **`ls`**:
|
||||
- **Description:** List configured MCP servers and tools. This is the
|
||||
default action if no subcommand is specified.
|
||||
- **`desc`**
|
||||
- **Description:** List configured MCP servers and tools with
|
||||
descriptions.
|
||||
- **`schema`**:
|
||||
- **Description:** List configured MCP servers and tools with descriptions
|
||||
and schemas.
|
||||
- **`auth`**:
|
||||
- **Description:** Authenticate with an OAuth-enabled MCP server.
|
||||
- **Usage:** `/mcp auth <server-name>`
|
||||
- **Details:** If `<server-name>` is provided, it initiates the OAuth flow
|
||||
for that server. If no server name is provided, it lists all configured
|
||||
servers that support OAuth authentication.
|
||||
- **`refresh`**:
|
||||
- **Description:** Restarts all MCP servers and re-discovers their
|
||||
available tools.
|
||||
|
||||
- [**`/model`**](./model.md)
|
||||
- **Description:** Opens a dialog to choose your Gemini model.
|
||||
|
||||
- **`/memory`**
|
||||
- **Description:** Manage the AI's instructional context (hierarchical memory
|
||||
loaded from `GEMINI.md` files).
|
||||
- **Sub-commands:**
|
||||
- **`add`**:
|
||||
- **Description:** Adds the following text to the AI's memory. Usage:
|
||||
`/memory add <text to remember>`
|
||||
- **`show`**:
|
||||
- **Description:** Display the full, concatenated content of the current
|
||||
hierarchical memory that has been loaded from all `GEMINI.md` files.
|
||||
This lets you inspect the instructional context being provided to the
|
||||
Gemini model.
|
||||
- **`refresh`**:
|
||||
- **Description:** Reload the hierarchical instructional memory from all
|
||||
`GEMINI.md` files found in the configured locations (global,
|
||||
project/ancestors, and sub-directories). This command updates the model
|
||||
with the latest `GEMINI.md` content.
|
||||
- **`list`**:
|
||||
- **Description:** Lists the paths of the GEMINI.md files in use for
|
||||
hierarchical memory.
|
||||
- **Note:** For more details on how `GEMINI.md` files contribute to
|
||||
hierarchical memory, see the
|
||||
[CLI Configuration documentation](../get-started/configuration.md).
|
||||
|
||||
- **`/restore`**
|
||||
- **Description:** Restores the project files to the state they were in just
|
||||
before a tool was executed. This is particularly useful for undoing file
|
||||
edits made by a tool. If run without a tool call ID, it will list available
|
||||
checkpoints to restore from.
|
||||
- **Usage:** `/restore [tool_call_id]`
|
||||
- **Note:** Only available if checkpointing is configured via
|
||||
[settings](../get-started/configuration.md). See
|
||||
[Checkpointing documentation](../cli/checkpointing.md) for more details.
|
||||
- **`/resume`**
|
||||
- **Description:** Browse and resume previous conversation sessions. Opens an
|
||||
interactive session browser where you can search, filter, and select from
|
||||
automatically saved conversations.
|
||||
- **Features:**
|
||||
- **Session Browser:** Interactive interface showing all saved sessions with
|
||||
timestamps, message counts, and first user message for context
|
||||
- **Search:** Use `/` to search through conversation content across all
|
||||
sessions
|
||||
- **Sorting:** Sort sessions by date or message count
|
||||
- **Management:** Delete unwanted sessions directly from the browser
|
||||
- **Resume:** Select any session to resume and continue the conversation
|
||||
- **Note:** All conversations are automatically saved as you chat - no manual
|
||||
saving required. See [Session Management](../cli/session-management.md) for
|
||||
complete details.
|
||||
|
||||
- [**`/settings`**](./settings.md)
|
||||
- **Description:** Open the settings editor to view and modify Gemini CLI
|
||||
settings.
|
||||
- **Details:** This command provides a user-friendly interface for changing
|
||||
settings that control the behavior and appearance of Gemini CLI. It is
|
||||
equivalent to manually editing the `.gemini/settings.json` file, but with
|
||||
validation and guidance to prevent errors. See the
|
||||
[settings documentation](./settings.md) for a full list of available
|
||||
settings.
|
||||
- **Usage:** Simply run `/settings` and the editor will open. You can then
|
||||
browse or search for specific settings, view their current values, and
|
||||
modify them as desired. Changes to some settings are applied immediately,
|
||||
while others require a restart.
|
||||
|
||||
- **`/stats`**
|
||||
- **Description:** Display detailed statistics for the current Gemini CLI
|
||||
session, including token usage, cached token savings (when available), and
|
||||
session duration. Note: Cached token information is only displayed when
|
||||
cached tokens are being used, which occurs with API key authentication but
|
||||
not with OAuth authentication at this time.
|
||||
|
||||
- [**`/theme`**](./themes.md)
|
||||
- **Description:** Open a dialog that lets you change the visual theme of
|
||||
Gemini CLI.
|
||||
|
||||
- **`/auth`**
|
||||
- **Description:** Open a dialog that lets you change the authentication
|
||||
method.
|
||||
|
||||
- **`/about`**
|
||||
- **Description:** Show version info. Please share this information when
|
||||
filing issues.
|
||||
|
||||
- [**`/tools`**](../tools/index.md)
|
||||
- **Description:** Display a list of tools that are currently available within
|
||||
Gemini CLI.
|
||||
- **Usage:** `/tools [desc]`
|
||||
- **Sub-commands:**
|
||||
- **`desc`** or **`descriptions`**:
|
||||
- **Description:** Show detailed descriptions of each tool, including each
|
||||
tool's name with its full description as provided to the model.
|
||||
- **`nodesc`** or **`nodescriptions`**:
|
||||
- **Description:** Hide tool descriptions, showing only the tool names.
|
||||
|
||||
- **`/privacy`**
|
||||
- **Description:** Display the Privacy Notice and allow users to select
|
||||
whether they consent to the collection of their data for service improvement
|
||||
purposes.
|
||||
|
||||
- **`/quit`** (or **`/exit`**)
|
||||
- **Description:** Exit Gemini CLI.
|
||||
|
||||
- **`/vim`**
|
||||
- **Description:** Toggle vim mode on or off. When vim mode is enabled, the
|
||||
input area supports vim-style navigation and editing commands in both NORMAL
|
||||
and INSERT modes.
|
||||
- **Features:**
|
||||
- **NORMAL mode:** Navigate with `h`, `j`, `k`, `l`; jump by words with `w`,
|
||||
`b`, `e`; go to line start/end with `0`, `$`, `^`; go to specific lines
|
||||
with `G` (or `gg` for first line)
|
||||
- **INSERT mode:** Standard text input with escape to return to NORMAL mode
|
||||
- **Editing commands:** Delete with `x`, change with `c`, insert with `i`,
|
||||
`a`, `o`, `O`; complex operations like `dd`, `cc`, `dw`, `cw`
|
||||
- **Count support:** Prefix commands with numbers (e.g., `3h`, `5w`, `10G`)
|
||||
- **Repeat last command:** Use `.` to repeat the last editing operation
|
||||
- **Persistent setting:** Vim mode preference is saved to
|
||||
`~/.gemini/settings.json` and restored between sessions
|
||||
- **Status indicator:** When enabled, shows `[NORMAL]` or `[INSERT]` in the
|
||||
footer
|
||||
|
||||
- **`/init`**
|
||||
- **Description:** To help users easily create a `GEMINI.md` file, this
|
||||
command analyzes the current directory and generates a tailored context
|
||||
file, making it simpler for them to provide project-specific instructions to
|
||||
the Gemini agent.
|
||||
|
||||
### Custom commands
|
||||
|
||||
Custom commands allow you to create personalized shortcuts for your most-used
|
||||
prompts. For detailed instructions on how to create, manage, and use them,
|
||||
please see the dedicated [Custom Commands documentation](./custom-commands.md).
|
||||
|
||||
## Input prompt shortcuts
|
||||
|
||||
These shortcuts apply directly to the input prompt for text manipulation.
|
||||
|
||||
- **Undo:**
|
||||
- **Keyboard shortcut:** Press **Ctrl+z** to undo the last action in the input
|
||||
prompt.
|
||||
|
||||
- **Redo:**
|
||||
- **Keyboard shortcut:** Press **Ctrl+Shift+Z** to redo the last undone action
|
||||
in the input prompt.
|
||||
|
||||
## At commands (`@`)
|
||||
|
||||
At commands are used to include the content of files or directories as part of
|
||||
your prompt to Gemini. These commands include git-aware filtering.
|
||||
|
||||
- **`@<path_to_file_or_directory>`**
|
||||
- **Description:** Inject the content of the specified file or files into your
|
||||
current prompt. This is useful for asking questions about specific code,
|
||||
text, or collections of files.
|
||||
- **Examples:**
|
||||
- `@path/to/your/file.txt Explain this text.`
|
||||
- `@src/my_project/ Summarize the code in this directory.`
|
||||
- `What is this file about? @README.md`
|
||||
- **Details:**
|
||||
- If a path to a single file is provided, the content of that file is read.
|
||||
- If a path to a directory is provided, the command attempts to read the
|
||||
content of files within that directory and any subdirectories.
|
||||
- Spaces in paths should be escaped with a backslash (e.g.,
|
||||
`@My\ Documents/file.txt`).
|
||||
- The command uses the `read_many_files` tool internally. The content is
|
||||
fetched and then inserted into your query before being sent to the Gemini
|
||||
model.
|
||||
- **Git-aware filtering:** By default, git-ignored files (like
|
||||
`node_modules/`, `dist/`, `.env`, `.git/`) are excluded. This behavior can
|
||||
be changed via the `context.fileFiltering` settings.
|
||||
- **File types:** The command is intended for text-based files. While it
|
||||
might attempt to read any file, binary files or very large files might be
|
||||
skipped or truncated by the underlying `read_many_files` tool to ensure
|
||||
performance and relevance. The tool indicates if files were skipped.
|
||||
- **Output:** The CLI will show a tool call message indicating that
|
||||
`read_many_files` was used, along with a message detailing the status and
|
||||
the path(s) that were processed.
|
||||
|
||||
- **`@` (Lone at symbol)**
|
||||
- **Description:** If you type a lone `@` symbol without a path, the query is
|
||||
passed as-is to the Gemini model. This might be useful if you are
|
||||
specifically talking _about_ the `@` symbol in your prompt.
|
||||
|
||||
### Error handling for `@` commands
|
||||
|
||||
- If the path specified after `@` is not found or is invalid, an error message
|
||||
will be displayed, and the query might not be sent to the Gemini model, or it
|
||||
will be sent without the file content.
|
||||
- If the `read_many_files` tool encounters an error (e.g., permission issues),
|
||||
this will also be reported.
|
||||
|
||||
## Shell mode and passthrough commands (`!`)
|
||||
|
||||
The `!` prefix lets you interact with your system's shell directly from within
|
||||
Gemini CLI.
|
||||
|
||||
- **`!<shell_command>`**
|
||||
- **Description:** Execute the given `<shell_command>` using `bash` on
|
||||
Linux/macOS or `powershell.exe -NoProfile -Command` on Windows (unless you
|
||||
override `ComSpec`). Any output or errors from the command are displayed in
|
||||
the terminal.
|
||||
- **Examples:**
|
||||
- `!ls -la` (executes `ls -la` and returns to Gemini CLI)
|
||||
- `!git status` (executes `git status` and returns to Gemini CLI)
|
||||
|
||||
- **`!` (Toggle shell mode)**
|
||||
- **Description:** Typing `!` on its own toggles shell mode.
|
||||
- **Entering shell mode:**
|
||||
- When active, shell mode uses a different coloring and a "Shell Mode
|
||||
Indicator".
|
||||
- While in shell mode, text you type is interpreted directly as a shell
|
||||
command.
|
||||
- **Exiting shell mode:**
|
||||
- When exited, the UI reverts to its standard appearance and normal Gemini
|
||||
CLI behavior resumes.
|
||||
|
||||
- **Caution for all `!` usage:** Commands you execute in shell mode have the
|
||||
same permissions and impact as if you ran them directly in your terminal.
|
||||
|
||||
- **Environment variable:** When a command is executed via `!` or in shell mode,
|
||||
the `GEMINI_CLI=1` environment variable is set in the subprocess's
|
||||
environment. This allows scripts or tools to detect if they are being run from
|
||||
within the Gemini CLI.
|
||||
@@ -1,780 +0,0 @@
|
||||
# Gemini CLI configuration
|
||||
|
||||
Gemini CLI offers several ways to configure its behavior, including environment
|
||||
variables, command-line arguments, and settings files. This document outlines
|
||||
the different configuration methods and available settings.
|
||||
|
||||
## Configuration layers
|
||||
|
||||
Configuration is applied in the following order of precedence (lower numbers are
|
||||
overridden by higher numbers):
|
||||
|
||||
1. **Default values:** Hardcoded defaults within the application.
|
||||
2. **User settings file:** Global settings for the current user.
|
||||
3. **Project settings file:** Project-specific settings.
|
||||
4. **System settings file:** System-wide settings.
|
||||
5. **Environment variables:** System-wide or session-specific variables,
|
||||
potentially loaded from `.env` files.
|
||||
6. **Command-line arguments:** Values passed when launching the CLI.
|
||||
|
||||
## Settings files
|
||||
|
||||
Gemini CLI uses `settings.json` files for persistent configuration. There are
|
||||
three locations for these files:
|
||||
|
||||
- **User settings file:**
|
||||
- **Location:** `~/.gemini/settings.json` (where `~` is your home directory).
|
||||
- **Scope:** Applies to all Gemini CLI sessions for the current user.
|
||||
- **Project settings file:**
|
||||
- **Location:** `.gemini/settings.json` within your project's root directory.
|
||||
- **Scope:** Applies only when running Gemini CLI from that specific project.
|
||||
Project settings override user settings.
|
||||
- **System settings file:**
|
||||
- **Location:** `/etc/gemini-cli/settings.json` (Linux),
|
||||
`C:\ProgramData\gemini-cli\settings.json` (Windows) or
|
||||
`/Library/Application Support/GeminiCli/settings.json` (macOS). The path can
|
||||
be overridden using the `GEMINI_CLI_SYSTEM_SETTINGS_PATH` environment
|
||||
variable.
|
||||
- **Scope:** Applies to all Gemini CLI sessions on the system, for all users.
|
||||
System settings override user and project settings. May be useful for system
|
||||
administrators at enterprises to have controls over users' Gemini CLI
|
||||
setups.
|
||||
|
||||
**Note on environment variables in settings:** String values within your
|
||||
`settings.json` files can reference environment variables using either
|
||||
`$VAR_NAME` or `${VAR_NAME}` syntax. These variables will be automatically
|
||||
resolved when the settings are loaded. For example, if you have an environment
|
||||
variable `MY_API_TOKEN`, you could use it in `settings.json` like this:
|
||||
`"apiKey": "$MY_API_TOKEN"`.
|
||||
|
||||
### The `.gemini` directory in your project
|
||||
|
||||
In addition to a project settings file, a project's `.gemini` directory can
|
||||
contain other project-specific files related to Gemini CLI's operation, such as:
|
||||
|
||||
- [Custom sandbox profiles](#sandboxing) (e.g.,
|
||||
`.gemini/sandbox-macos-custom.sb`, `.gemini/sandbox.Dockerfile`).
|
||||
|
||||
### Available settings in `settings.json`:
|
||||
|
||||
- **`contextFileName`** (string or array of strings):
|
||||
- **Description:** Specifies the filename for context files (e.g.,
|
||||
`GEMINI.md`, `AGENTS.md`). Can be a single filename or a list of accepted
|
||||
filenames.
|
||||
- **Default:** `GEMINI.md`
|
||||
- **Example:** `"contextFileName": "AGENTS.md"`
|
||||
|
||||
- **`bugCommand`** (object):
|
||||
- **Description:** Overrides the default URL for the `/bug` command.
|
||||
- **Default:**
|
||||
`"urlTemplate": "https://github.com/google-gemini/gemini-cli/issues/new?template=bug_report.yml&title={title}&info={info}"`
|
||||
- **Properties:**
|
||||
- **`urlTemplate`** (string): A URL that can contain `{title}` and `{info}`
|
||||
placeholders.
|
||||
- **Example:**
|
||||
```json
|
||||
"bugCommand": {
|
||||
"urlTemplate": "https://bug.example.com/new?title={title}&info={info}"
|
||||
}
|
||||
```
|
||||
|
||||
- **`fileFiltering`** (object):
|
||||
- **Description:** Controls git-aware file filtering behavior for @ commands
|
||||
and file discovery tools.
|
||||
- **Default:** `"respectGitIgnore": true, "enableRecursiveFileSearch": true`
|
||||
- **Properties:**
|
||||
- **`respectGitIgnore`** (boolean): Whether to respect .gitignore patterns
|
||||
when discovering files. When set to `true`, git-ignored files (like
|
||||
`node_modules/`, `dist/`, `.env`) are automatically excluded from @
|
||||
commands and file listing operations.
|
||||
- **`enableRecursiveFileSearch`** (boolean): Whether to enable searching
|
||||
recursively for filenames under the current tree when completing @
|
||||
prefixes in the prompt.
|
||||
- **Example:**
|
||||
```json
|
||||
"fileFiltering": {
|
||||
"respectGitIgnore": true,
|
||||
"enableRecursiveFileSearch": false
|
||||
}
|
||||
```
|
||||
|
||||
- **`coreTools`** (array of strings):
|
||||
- **Description:** Allows you to specify a list of core tool names that should
|
||||
be made available to the model. This can be used to restrict the set of
|
||||
built-in tools. See [Built-in Tools](../core/tools-api.md#built-in-tools)
|
||||
for a list of core tools. You can also specify command-specific restrictions
|
||||
for tools that support it, like the `ShellTool`. For example,
|
||||
`"coreTools": ["ShellTool(ls -l)"]` will only allow the `ls -l` command to
|
||||
be executed.
|
||||
- **Default:** All tools available for use by the Gemini model.
|
||||
- **Example:** `"coreTools": ["ReadFileTool", "GlobTool", "ShellTool(ls)"]`.
|
||||
|
||||
- **`excludeTools`** (array of strings):
|
||||
- **Description:** Allows you to specify a list of core tool names that should
|
||||
be excluded from the model. A tool listed in both `excludeTools` and
|
||||
`coreTools` is excluded. You can also specify command-specific restrictions
|
||||
for tools that support it, like the `ShellTool`. For example,
|
||||
`"excludeTools": ["ShellTool(rm -rf)"]` will block the `rm -rf` command.
|
||||
- **Default**: No tools excluded.
|
||||
- **Example:** `"excludeTools": ["run_shell_command", "findFiles"]`.
|
||||
- **Security Note:** Command-specific restrictions in `excludeTools` for
|
||||
`run_shell_command` are based on simple string matching and can be easily
|
||||
bypassed. This feature is **not a security mechanism** and should not be
|
||||
relied upon to safely execute untrusted code. It is recommended to use
|
||||
`coreTools` to explicitly select commands that can be executed.
|
||||
|
||||
- **`allowMCPServers`** (array of strings):
|
||||
- **Description:** Allows you to specify a list of MCP server names that
|
||||
should be made available to the model. This can be used to restrict the set
|
||||
of MCP servers to connect to. Note that this will be ignored if
|
||||
`--allowed-mcp-server-names` is set.
|
||||
- **Default:** All MCP servers are available for use by the Gemini model.
|
||||
- **Example:** `"allowMCPServers": ["myPythonServer"]`.
|
||||
- **Security Note:** This uses simple string matching on MCP server names,
|
||||
which can be modified. If you're a system administrator looking to prevent
|
||||
users from bypassing this, consider configuring the `mcpServers` at the
|
||||
system settings level such that the user will not be able to configure any
|
||||
MCP servers of their own. This should not be used as an airtight security
|
||||
mechanism.
|
||||
|
||||
- **`excludeMCPServers`** (array of strings):
|
||||
- **Description:** Allows you to specify a list of MCP server names that
|
||||
should be excluded from the model. A server listed in both
|
||||
`excludeMCPServers` and `allowMCPServers` is excluded. Note that this will
|
||||
be ignored if `--allowed-mcp-server-names` is set.
|
||||
- **Default**: No MCP servers excluded.
|
||||
- **Example:** `"excludeMCPServers": ["myNodeServer"]`.
|
||||
- **Security note:** This uses simple string matching on MCP server names,
|
||||
which can be modified. If you're a system administrator looking to prevent
|
||||
users from bypassing this, consider configuring the `mcpServers` at the
|
||||
system settings level such that the user will not be able to configure any
|
||||
MCP servers of their own. This should not be used as an airtight security
|
||||
mechanism.
|
||||
|
||||
- **`autoAccept`** (boolean):
|
||||
- **Description:** Controls whether the CLI automatically accepts and executes
|
||||
tool calls that are considered safe (e.g., read-only operations) without
|
||||
explicit user confirmation. If set to `true`, the CLI will bypass the
|
||||
confirmation prompt for tools deemed safe.
|
||||
- **Default:** `false`
|
||||
- **Example:** `"autoAccept": true`
|
||||
|
||||
- **`theme`** (string):
|
||||
- **Description:** Sets the visual [theme](./themes.md) for Gemini CLI.
|
||||
- **Default:** `"Default"`
|
||||
- **Example:** `"theme": "GitHub"`
|
||||
|
||||
- **`vimMode`** (boolean):
|
||||
- **Description:** Enables or disables vim mode for input editing. When
|
||||
enabled, the input area supports vim-style navigation and editing commands
|
||||
with NORMAL and INSERT modes. The vim mode status is displayed in the footer
|
||||
and persists between sessions.
|
||||
- **Default:** `false`
|
||||
- **Example:** `"vimMode": true`
|
||||
|
||||
- **`sandbox`** (boolean or string):
|
||||
- **Description:** Controls whether and how to use sandboxing for tool
|
||||
execution. If set to `true`, Gemini CLI uses a pre-built
|
||||
`gemini-cli-sandbox` Docker image. For more information, see
|
||||
[Sandboxing](#sandboxing).
|
||||
- **Default:** `false`
|
||||
- **Example:** `"sandbox": "docker"`
|
||||
|
||||
- **`toolDiscoveryCommand`** (string):
|
||||
- **Description:** Defines a custom shell command for discovering tools from
|
||||
your project. The shell command must return on `stdout` a JSON array of
|
||||
[function declarations](https://ai.google.dev/gemini-api/docs/function-calling#function-declarations).
|
||||
Tool wrappers are optional.
|
||||
- **Default:** Empty
|
||||
- **Example:** `"toolDiscoveryCommand": "bin/get_tools"`
|
||||
|
||||
- **`toolCallCommand`** (string):
|
||||
- **Description:** Defines a custom shell command for calling a specific tool
|
||||
that was discovered using `toolDiscoveryCommand`. The shell command must
|
||||
meet the following criteria:
|
||||
- It must take function `name` (exactly as in
|
||||
[function declaration](https://ai.google.dev/gemini-api/docs/function-calling#function-declarations))
|
||||
as first command line argument.
|
||||
- It must read function arguments as JSON on `stdin`, analogous to
|
||||
[`functionCall.args`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#functioncall).
|
||||
- It must return function output as JSON on `stdout`, analogous to
|
||||
[`functionResponse.response.content`](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#functionresponse).
|
||||
- **Default:** Empty
|
||||
- **Example:** `"toolCallCommand": "bin/call_tool"`
|
||||
|
||||
- **`mcpServers`** (object):
|
||||
- **Description:** Configures connections to one or more Model-Context
|
||||
Protocol (MCP) servers for discovering and using custom tools. Gemini CLI
|
||||
attempts to connect to each configured MCP server to discover available
|
||||
tools. If multiple MCP servers expose a tool with the same name, the tool
|
||||
names will be prefixed with the server alias you defined in the
|
||||
configuration (e.g., `serverAlias__actualToolName`) to avoid conflicts. Note
|
||||
that the system might strip certain schema properties from MCP tool
|
||||
definitions for compatibility.
|
||||
- **Default:** Empty
|
||||
- **Properties:**
|
||||
- **`<SERVER_NAME>`** (object): The server parameters for the named server.
|
||||
- `command` (string, required): The command to execute to start the MCP
|
||||
server.
|
||||
- `args` (array of strings, optional): Arguments to pass to the command.
|
||||
- `env` (object, optional): Environment variables to set for the server
|
||||
process.
|
||||
- `cwd` (string, optional): The working directory in which to start the
|
||||
server.
|
||||
- `timeout` (number, optional): Timeout in milliseconds for requests to
|
||||
this MCP server.
|
||||
- `trust` (boolean, optional): Trust this server and bypass all tool call
|
||||
confirmations.
|
||||
- `includeTools` (array of strings, optional): List of tool names to
|
||||
include from this MCP server. When specified, only the tools listed here
|
||||
will be available from this server (whitelist behavior). If not
|
||||
specified, all tools from the server are enabled by default.
|
||||
- `excludeTools` (array of strings, optional): List of tool names to
|
||||
exclude from this MCP server. Tools listed here will not be available to
|
||||
the model, even if they are exposed by the server. **Note:**
|
||||
`excludeTools` takes precedence over `includeTools` - if a tool is in
|
||||
both lists, it will be excluded.
|
||||
- **Example:**
|
||||
```json
|
||||
"mcpServers": {
|
||||
"myPythonServer": {
|
||||
"command": "python",
|
||||
"args": ["mcp_server.py", "--port", "8080"],
|
||||
"cwd": "./mcp_tools/python",
|
||||
"timeout": 5000,
|
||||
"includeTools": ["safe_tool", "file_reader"],
|
||||
},
|
||||
"myNodeServer": {
|
||||
"command": "node",
|
||||
"args": ["mcp_server.js"],
|
||||
"cwd": "./mcp_tools/node",
|
||||
"excludeTools": ["dangerous_tool", "file_deleter"]
|
||||
},
|
||||
"myDockerServer": {
|
||||
"command": "docker",
|
||||
"args": ["run", "-i", "--rm", "-e", "API_KEY", "ghcr.io/foo/bar"],
|
||||
"env": {
|
||||
"API_KEY": "$MY_API_TOKEN"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **`checkpointing`** (object):
|
||||
- **Description:** Configures the checkpointing feature, which allows you to
|
||||
save and restore conversation and file states. See the
|
||||
[Checkpointing documentation](./checkpointing.md) for more details.
|
||||
- **Default:** `{"enabled": false}`
|
||||
- **Properties:**
|
||||
- **`enabled`** (boolean): When `true`, the `/restore` command is available.
|
||||
|
||||
- **`preferredEditor`** (string):
|
||||
- **Description:** Specifies the preferred editor to use for viewing diffs.
|
||||
- **Default:** `vscode`
|
||||
- **Example:** `"preferredEditor": "vscode"`
|
||||
|
||||
- **`telemetry`** (object)
|
||||
- **Description:** Configures logging and metrics collection for Gemini CLI.
|
||||
For more information, see [Telemetry](./telemetry.md).
|
||||
- **Default:**
|
||||
`{"enabled": false, "target": "local", "otlpEndpoint": "http://localhost:4317", "logPrompts": true}`
|
||||
- **Properties:**
|
||||
- **`enabled`** (boolean): Whether or not telemetry is enabled.
|
||||
- **`target`** (string): The destination for collected telemetry. Supported
|
||||
values are `local` and `gcp`.
|
||||
- **`otlpEndpoint`** (string): The endpoint for the OTLP Exporter.
|
||||
- **`logPrompts`** (boolean): Whether or not to include the content of user
|
||||
prompts in the logs.
|
||||
- **Example:**
|
||||
```json
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
"target": "local",
|
||||
"otlpEndpoint": "http://localhost:16686",
|
||||
"logPrompts": false
|
||||
}
|
||||
```
|
||||
- **`usageStatisticsEnabled`** (boolean):
|
||||
- **Description:** Enables or disables the collection of usage statistics. See
|
||||
[Usage Statistics](#usage-statistics) for more information.
|
||||
- **Default:** `true`
|
||||
- **Example:**
|
||||
```json
|
||||
"usageStatisticsEnabled": false
|
||||
```
|
||||
|
||||
- **`hideTips`** (boolean):
|
||||
- **Description:** Enables or disables helpful tips in the CLI interface.
|
||||
- **Default:** `false`
|
||||
- **Example:**
|
||||
|
||||
```json
|
||||
"hideTips": true
|
||||
```
|
||||
|
||||
- **`hideBanner`** (boolean):
|
||||
- **Description:** Enables or disables the startup banner (ASCII art logo) in
|
||||
the CLI interface.
|
||||
- **Default:** `false`
|
||||
- **Example:**
|
||||
|
||||
```json
|
||||
"hideBanner": true
|
||||
```
|
||||
|
||||
- **`maxSessionTurns`** (number):
|
||||
- **Description:** Sets the maximum number of turns for a session. If the
|
||||
session exceeds this limit, the CLI will stop processing and start a new
|
||||
chat.
|
||||
- **Default:** `-1` (unlimited)
|
||||
- **Example:**
|
||||
```json
|
||||
"maxSessionTurns": 10
|
||||
```
|
||||
|
||||
- **`summarizeToolOutput`** (object):
|
||||
- **Description:** Enables or disables the summarization of tool output. You
|
||||
can specify the token budget for the summarization using the `tokenBudget`
|
||||
setting.
|
||||
- Note: Currently only the `run_shell_command` tool is supported.
|
||||
- **Default:** `{}` (Disabled by default)
|
||||
- **Example:**
|
||||
```json
|
||||
"summarizeToolOutput": {
|
||||
"run_shell_command": {
|
||||
"tokenBudget": 2000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **`excludedProjectEnvVars`** (array of strings):
|
||||
- **Description:** Specifies environment variables that should be excluded
|
||||
from being loaded from project `.env` files. This prevents project-specific
|
||||
environment variables (like `DEBUG=true`) from interfering with gemini-cli
|
||||
behavior. Variables from `.gemini/.env` files are never excluded.
|
||||
- **Default:** `["DEBUG", "DEBUG_MODE"]`
|
||||
- **Example:**
|
||||
```json
|
||||
"excludedProjectEnvVars": ["DEBUG", "DEBUG_MODE", "NODE_ENV"]
|
||||
```
|
||||
|
||||
- **`includeDirectories`** (array of strings):
|
||||
- **Description:** Specifies an array of additional absolute or relative paths
|
||||
to include in the workspace context. This allows you to work with files
|
||||
across multiple directories as if they were one. Paths can use `~` to refer
|
||||
to the user's home directory. This setting can be combined with the
|
||||
`--include-directories` command-line flag.
|
||||
- **Default:** `[]`
|
||||
- **Example:**
|
||||
```json
|
||||
"includeDirectories": [
|
||||
"/path/to/another/project",
|
||||
"../shared-library",
|
||||
"~/common-utils"
|
||||
]
|
||||
```
|
||||
|
||||
- **`loadMemoryFromIncludeDirectories`** (boolean):
|
||||
- **Description:** Controls the behavior of the `/memory refresh` command. If
|
||||
set to `true`, `GEMINI.md` files should be loaded from all directories that
|
||||
are added. If set to `false`, `GEMINI.md` should only be loaded from the
|
||||
current directory.
|
||||
- **Default:** `false`
|
||||
- **Example:**
|
||||
```json
|
||||
"loadMemoryFromIncludeDirectories": true
|
||||
```
|
||||
|
||||
### Example `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"theme": "GitHub",
|
||||
"sandbox": "docker",
|
||||
"toolDiscoveryCommand": "bin/get_tools",
|
||||
"toolCallCommand": "bin/call_tool",
|
||||
"mcpServers": {
|
||||
"mainServer": {
|
||||
"command": "bin/mcp_server.py"
|
||||
},
|
||||
"anotherServer": {
|
||||
"command": "node",
|
||||
"args": ["mcp_server.js", "--verbose"]
|
||||
}
|
||||
},
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
"target": "local",
|
||||
"otlpEndpoint": "http://localhost:4317",
|
||||
"logPrompts": true
|
||||
},
|
||||
"usageStatisticsEnabled": true,
|
||||
"hideTips": false,
|
||||
"hideBanner": false,
|
||||
"maxSessionTurns": 10,
|
||||
"summarizeToolOutput": {
|
||||
"run_shell_command": {
|
||||
"tokenBudget": 100
|
||||
}
|
||||
},
|
||||
"excludedProjectEnvVars": ["DEBUG", "DEBUG_MODE", "NODE_ENV"],
|
||||
"includeDirectories": ["path/to/dir1", "~/path/to/dir2", "../path/to/dir3"],
|
||||
"loadMemoryFromIncludeDirectories": true
|
||||
}
|
||||
```
|
||||
|
||||
## Shell history
|
||||
|
||||
The CLI keeps a history of shell commands you run. To avoid conflicts between
|
||||
different projects, this history is stored in a project-specific directory
|
||||
within your user's home folder.
|
||||
|
||||
- **Location:** `~/.gemini/tmp/<project_hash>/shell_history`
|
||||
- `<project_hash>` is a unique identifier generated from your project's root
|
||||
path.
|
||||
- The history is stored in a file named `shell_history`.
|
||||
|
||||
## Environment variables and `.env` files
|
||||
|
||||
Environment variables are a common way to configure applications, especially for
|
||||
sensitive information like API keys or for settings that might change between
|
||||
environments.
|
||||
|
||||
The CLI automatically loads environment variables from an `.env` file. The
|
||||
loading order is:
|
||||
|
||||
1. `.env` file in the current working directory.
|
||||
2. If not found, it searches upwards in parent directories until it finds an
|
||||
`.env` file or reaches the project root (identified by a `.git` folder) or
|
||||
the home directory.
|
||||
3. If still not found, it looks for `~/.env` (in the user's home directory).
|
||||
|
||||
**Environment variable exclusion:** Some environment variables (like `DEBUG` and
|
||||
`DEBUG_MODE`) are automatically excluded from being loaded from project `.env`
|
||||
files to prevent interference with gemini-cli behavior. Variables from
|
||||
`.gemini/.env` files are never excluded. You can customize this behavior using
|
||||
the `excludedProjectEnvVars` setting in your `settings.json` file.
|
||||
|
||||
- **`GEMINI_API_KEY`** (Required):
|
||||
- Your API key for the Gemini API.
|
||||
- **Crucial for operation.** The CLI will not function without it.
|
||||
- Set this in your shell profile (e.g., `~/.bashrc`, `~/.zshrc`) or an `.env`
|
||||
file.
|
||||
- **`GEMINI_MODEL`**:
|
||||
- Specifies the default Gemini model to use.
|
||||
- Overrides the hardcoded default
|
||||
- Example: `export GEMINI_MODEL="gemini-2.5-flash"`
|
||||
- **`GEMINI_CLI_CUSTOM_HEADERS`**:
|
||||
- Adds extra HTTP headers to Gemini API and Code Assist requests.
|
||||
- Accepts a comma-separated list of `Name: value` pairs.
|
||||
- Example:
|
||||
`export GEMINI_CLI_CUSTOM_HEADERS="X-My-Header: foo, X-Trace-ID: abc123"`.
|
||||
- **`GEMINI_API_KEY_AUTH_MECHANISM`**:
|
||||
- Specifies how the API key should be sent for authentication when using
|
||||
`AuthType.USE_GEMINI` or `AuthType.USE_VERTEX_AI`.
|
||||
- Valid values are `x-goog-api-key` (default) or `bearer`.
|
||||
- If set to `bearer`, the API key will be sent in the
|
||||
`Authorization: Bearer <key>` header.
|
||||
- Example: `export GEMINI_API_KEY_AUTH_MECHANISM="bearer"`
|
||||
- **`GOOGLE_API_KEY`**:
|
||||
- Your Google Cloud API key.
|
||||
- Required for using Vertex AI in express mode.
|
||||
- Ensure you have the necessary permissions.
|
||||
- Example: `export GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"`.
|
||||
- **`GOOGLE_CLOUD_PROJECT`**:
|
||||
- Your Google Cloud Project ID.
|
||||
- Required for using Code Assist or Vertex AI.
|
||||
- If using Vertex AI, ensure you have the necessary permissions in this
|
||||
project.
|
||||
- **Cloud shell note:** When running in a Cloud Shell environment, this
|
||||
variable defaults to a special project allocated for Cloud Shell users. If
|
||||
you have `GOOGLE_CLOUD_PROJECT` set in your global environment in Cloud
|
||||
Shell, it will be overridden by this default. To use a different project in
|
||||
Cloud Shell, you must define `GOOGLE_CLOUD_PROJECT` in a `.env` file.
|
||||
- Example: `export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"`.
|
||||
- **`GOOGLE_APPLICATION_CREDENTIALS`** (string):
|
||||
- **Description:** The path to your Google Application Credentials JSON file.
|
||||
- **Example:**
|
||||
`export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/credentials.json"`
|
||||
- **`OTLP_GOOGLE_CLOUD_PROJECT`**:
|
||||
- Your Google Cloud Project ID for Telemetry in Google Cloud
|
||||
- Example: `export OTLP_GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"`.
|
||||
- **`GOOGLE_CLOUD_LOCATION`**:
|
||||
- Your Google Cloud Project Location (e.g., us-central1).
|
||||
- Required for using Vertex AI in non express mode.
|
||||
- Example: `export GOOGLE_CLOUD_LOCATION="YOUR_PROJECT_LOCATION"`.
|
||||
- **`GEMINI_SANDBOX`**:
|
||||
- Alternative to the `sandbox` setting in `settings.json`.
|
||||
- Accepts `true`, `false`, `docker`, `podman`, or a custom command string.
|
||||
- **`HTTP_PROXY` / `HTTPS_PROXY`**:
|
||||
- Specifies the proxy server to use for outgoing HTTP/HTTPS requests.
|
||||
- Example: `export HTTPS_PROXY="http://proxy.example.com:8080"`
|
||||
- **`SEATBELT_PROFILE`** (macOS specific):
|
||||
- Switches the Seatbelt (`sandbox-exec`) profile on macOS.
|
||||
- `permissive-open`: (Default) Restricts writes to the project folder (and a
|
||||
few other folders, see
|
||||
`packages/cli/src/utils/sandbox-macos-permissive-open.sb`) but allows other
|
||||
operations.
|
||||
- `strict`: Uses a strict profile that declines operations by default.
|
||||
- `<profile_name>`: Uses a custom profile. To define a custom profile, create
|
||||
a file named `sandbox-macos-<profile_name>.sb` in your project's `.gemini/`
|
||||
directory (e.g., `my-project/.gemini/sandbox-macos-custom.sb`).
|
||||
- **`DEBUG` or `DEBUG_MODE`** (often used by underlying libraries or the CLI
|
||||
itself):
|
||||
- Set to `true` or `1` to enable verbose debug logging, which can be helpful
|
||||
for troubleshooting.
|
||||
- **Note:** These variables are automatically excluded from project `.env`
|
||||
files by default to prevent interference with gemini-cli behavior. Use
|
||||
`.gemini/.env` files if you need to set these for gemini-cli specifically.
|
||||
- **`NO_COLOR`**:
|
||||
- Set to any value to disable all color output in the CLI.
|
||||
- **`CLI_TITLE`**:
|
||||
- Set to a string to customize the title of the CLI.
|
||||
- **`CODE_ASSIST_ENDPOINT`**:
|
||||
- Specifies the endpoint for the code assist server.
|
||||
- This is useful for development and testing.
|
||||
- **`GEMINI_SYSTEM_MD`**:
|
||||
- Overrides the base system prompt with the contents of a Markdown file.
|
||||
- If set to `1` or `true`, it uses the file at `.gemini/system.md`.
|
||||
- If set to a file path, it uses that file. The path can be absolute or
|
||||
relative. `~` is supported for the home directory.
|
||||
- The specified file must exist.
|
||||
- **`GEMINI_WRITE_SYSTEM_MD`**:
|
||||
- Writes the default system prompt to a file. This is useful for getting a
|
||||
template to customize.
|
||||
- If set to `1` or `true`, it writes to `.gemini/system.md`.
|
||||
- If set to a file path, it writes to that path. The path can be absolute or
|
||||
relative. `~` is supported for the home directory. **Note: This will
|
||||
overwrite the file if it already exists.**
|
||||
|
||||
## Command-line arguments
|
||||
|
||||
Arguments passed directly when running the CLI can override other configurations
|
||||
for that specific session.
|
||||
|
||||
- **`--model <model_name>`** (**`-m <model_name>`**):
|
||||
- Specifies the Gemini model to use for this session.
|
||||
- Example: `npm start -- --model gemini-1.5-pro-latest`
|
||||
- **`--prompt <your_prompt>`** (**`-p <your_prompt>`**):
|
||||
- Used to pass a prompt directly to the command. This invokes Gemini CLI in a
|
||||
non-interactive mode.
|
||||
- **`--prompt-interactive <your_prompt>`** (**`-i <your_prompt>`**):
|
||||
- Starts an interactive session with the provided prompt as the initial input.
|
||||
- The prompt is processed within the interactive session, not before it.
|
||||
- Cannot be used when piping input from stdin.
|
||||
- Example: `gemini -i "explain this code"`
|
||||
- **`--sandbox`** (**`-s`**):
|
||||
- Enables sandbox mode for this session.
|
||||
- **`--sandbox-image`**:
|
||||
- Sets the sandbox image URI.
|
||||
- **`--debug`** (**`-d`**):
|
||||
- Enables debug mode for this session, providing more verbose output.
|
||||
- **`--all-files`** (**`-a`**):
|
||||
- If set, recursively includes all files within the current directory as
|
||||
context for the prompt.
|
||||
- **`--help`** (or **`-h`**):
|
||||
- Displays help information about command-line arguments.
|
||||
- **`--show-memory-usage`**:
|
||||
- Displays the current memory usage.
|
||||
- **`--yolo`**:
|
||||
- Enables YOLO mode, which automatically approves all tool calls.
|
||||
- **`--telemetry`**:
|
||||
- Enables [telemetry](./telemetry.md).
|
||||
- **`--telemetry-target`**:
|
||||
- Sets the telemetry target. See [telemetry](./telemetry.md) for more
|
||||
information.
|
||||
- **`--telemetry-otlp-endpoint`**:
|
||||
- Sets the OTLP endpoint for telemetry. See [telemetry](./telemetry.md) for
|
||||
more information.
|
||||
- **`--telemetry-log-prompts`**:
|
||||
- Enables logging of prompts for telemetry. See [telemetry](./telemetry.md)
|
||||
for more information.
|
||||
- **`--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.
|
||||
- **`--include-directories <dir1,dir2,...>`**:
|
||||
- Includes additional directories in the workspace for multi-directory
|
||||
support.
|
||||
- Can be specified multiple times or as comma-separated values.
|
||||
- 5 directories can be added at maximum.
|
||||
- Example: `--include-directories /path/to/project1,/path/to/project2` or
|
||||
`--include-directories /path/to/project1 --include-directories /path/to/project2`
|
||||
- **`--version`**:
|
||||
- Displays the version of the CLI.
|
||||
|
||||
## Context files (hierarchical instructional context)
|
||||
|
||||
While not strictly configuration for the CLI's _behavior_, context files
|
||||
(defaulting to `GEMINI.md` but configurable via the `contextFileName` setting)
|
||||
are crucial for configuring the _instructional context_ (also referred to as
|
||||
"memory") provided to the Gemini model. This powerful feature allows you to give
|
||||
project-specific instructions, coding style guides, or any relevant background
|
||||
information to the AI, making its responses more tailored and accurate to your
|
||||
needs. The CLI includes UI elements, such as an indicator in the footer showing
|
||||
the number of loaded context files, to keep you informed about the active
|
||||
context.
|
||||
|
||||
- **Purpose:** These Markdown files contain instructions, guidelines, or context
|
||||
that you want the Gemini model to be aware of during your interactions. The
|
||||
system is designed to manage this instructional context hierarchically.
|
||||
|
||||
### Example context file content (e.g., `GEMINI.md`)
|
||||
|
||||
Here's a conceptual example of what a context file at the root of a TypeScript
|
||||
project might contain:
|
||||
|
||||
```markdown
|
||||
# Project: My Awesome TypeScript Library
|
||||
|
||||
## General Instructions:
|
||||
|
||||
- When generating new TypeScript code, please follow the existing coding style.
|
||||
- Ensure all new functions and classes have JSDoc comments.
|
||||
- Prefer functional programming paradigms where appropriate.
|
||||
- All code should be compatible with TypeScript 5.0 and Node.js 20+.
|
||||
|
||||
## Coding Style:
|
||||
|
||||
- Use 2 spaces for indentation.
|
||||
- Interface names should be prefixed with `I` (e.g., `IUserService`).
|
||||
- Private class members should be prefixed with an underscore (`_`).
|
||||
- Always use strict equality (`===` and `!==`).
|
||||
|
||||
## Specific Component: `src/api/client.ts`
|
||||
|
||||
- This file handles all outbound API requests.
|
||||
- When adding new API call functions, ensure they include robust error handling
|
||||
and logging.
|
||||
- Use the existing `fetchWithRetry` utility for all GET requests.
|
||||
|
||||
## Regarding Dependencies:
|
||||
|
||||
- Avoid introducing new external dependencies unless absolutely necessary.
|
||||
- If a new dependency is required, please state the reason.
|
||||
```
|
||||
|
||||
This example demonstrates how you can provide general project context, specific
|
||||
coding conventions, and even notes about particular files or components. The
|
||||
more relevant and precise your context files are, the better the AI can assist
|
||||
you. Project-specific context files are highly encouraged to establish
|
||||
conventions and context.
|
||||
|
||||
- **Hierarchical loading and precedence:** The CLI implements a sophisticated
|
||||
hierarchical memory system by loading context files (e.g., `GEMINI.md`) from
|
||||
several locations. Content from files lower in this list (more specific)
|
||||
typically overrides or supplements content from files higher up (more
|
||||
general). The exact concatenation order and final context can be inspected
|
||||
using the `/memory show` command. The typical loading order is:
|
||||
1. **Global context file:**
|
||||
- Location: `~/.gemini/<contextFileName>` (e.g., `~/.gemini/GEMINI.md` in
|
||||
your user home directory).
|
||||
- Scope: Provides default instructions for all your projects.
|
||||
2. **Project root and ancestors context files:**
|
||||
- Location: The CLI searches for the configured context file in the
|
||||
current working directory and then in each parent directory up to either
|
||||
the project root (identified by a `.git` folder) or your home directory.
|
||||
- Scope: Provides context relevant to the entire project or a significant
|
||||
portion of it.
|
||||
3. **Sub-directory context files (contextual/local):**
|
||||
- Location: The CLI also scans for the configured context file in
|
||||
subdirectories _below_ the current working directory (respecting common
|
||||
ignore patterns like `node_modules`, `.git`, etc.). The breadth of this
|
||||
search is limited to 200 directories by default, but can be configured
|
||||
with a `memoryDiscoveryMaxDirs` field in your `settings.json` file.
|
||||
- Scope: Allows for highly specific instructions relevant to a particular
|
||||
component, module, or subsection of your project.
|
||||
- **Concatenation and UI indication:** The contents of all found context files
|
||||
are concatenated (with separators indicating their origin and path) and
|
||||
provided as part of the system prompt to the Gemini model. The CLI footer
|
||||
displays the count of loaded context files, giving you a quick visual cue
|
||||
about the active instructional context.
|
||||
- **Importing content:** You can modularize your context files by importing
|
||||
other Markdown files using the `@path/to/file.md` syntax. For more details,
|
||||
see the [Memory Import Processor documentation](../core/memport.md).
|
||||
- **Commands for memory management:**
|
||||
- Use `/memory refresh` to force a re-scan and reload of all context files
|
||||
from all configured locations. This updates the AI's instructional context.
|
||||
- Use `/memory show` to display the combined instructional context currently
|
||||
loaded, allowing you to verify the hierarchy and content being used by the
|
||||
AI.
|
||||
- See the [Commands documentation](./commands.md#memory) for full details on
|
||||
the `/memory` command and its sub-commands (`show` and `refresh`).
|
||||
|
||||
By understanding and utilizing these configuration layers and the hierarchical
|
||||
nature of context files, you can effectively manage the AI's memory and tailor
|
||||
the Gemini CLI's responses to your specific needs and projects.
|
||||
|
||||
## Sandboxing
|
||||
|
||||
The Gemini CLI can execute potentially unsafe operations (like shell commands
|
||||
and file modifications) within a sandboxed environment to protect your system.
|
||||
|
||||
Sandboxing is disabled by default, but you can enable it in a few ways:
|
||||
|
||||
- Using `--sandbox` or `-s` flag.
|
||||
- Setting `GEMINI_SANDBOX` environment variable.
|
||||
- Sandbox is enabled in `--yolo` mode by default.
|
||||
|
||||
By default, it uses a pre-built `gemini-cli-sandbox` Docker image.
|
||||
|
||||
For project-specific sandboxing needs, you can create a custom Dockerfile at
|
||||
`.gemini/sandbox.Dockerfile` in your project's root directory. This Dockerfile
|
||||
can be based on the base sandbox image:
|
||||
|
||||
```dockerfile
|
||||
FROM gemini-cli-sandbox
|
||||
|
||||
# Add your custom dependencies or configurations here
|
||||
# For example:
|
||||
# RUN apt-get update && apt-get install -y some-package
|
||||
# COPY ./my-config /app/my-config
|
||||
```
|
||||
|
||||
When `.gemini/sandbox.Dockerfile` exists, you can use `BUILD_SANDBOX`
|
||||
environment variable when running Gemini CLI to automatically build the custom
|
||||
sandbox image:
|
||||
|
||||
```bash
|
||||
BUILD_SANDBOX=1 gemini -s
|
||||
```
|
||||
|
||||
## Usage statistics
|
||||
|
||||
To help us improve the Gemini CLI, we collect anonymized usage statistics. This
|
||||
data helps us understand how the CLI is used, identify common issues, and
|
||||
prioritize new features.
|
||||
|
||||
**What we collect:**
|
||||
|
||||
- **Tool calls:** We log the names of the tools that are called, whether they
|
||||
succeed or fail, and how long they take to execute. We do not collect the
|
||||
arguments passed to the tools or any data returned by them.
|
||||
- **API requests:** We log the Gemini model used for each request, the duration
|
||||
of the request, and whether it was successful. We do not collect the content
|
||||
of the prompts or responses.
|
||||
- **Session information:** We collect information about the configuration of the
|
||||
CLI, such as the enabled tools and the approval mode.
|
||||
|
||||
**What we DON'T collect:**
|
||||
|
||||
- **Personally identifiable information (PII):** We do not collect any personal
|
||||
information, such as your name, email address, or API keys.
|
||||
- **Prompt and response content:** We do not log the content of your prompts or
|
||||
the responses from the Gemini model.
|
||||
- **File content:** We do not log the content of any files that are read or
|
||||
written by the CLI.
|
||||
|
||||
**How to opt out:**
|
||||
|
||||
You can opt out of usage statistics collection at any time by setting the
|
||||
`usageStatisticsEnabled` property to `false` in your `settings.json` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"usageStatisticsEnabled": false
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
# Creating Agent Skills
|
||||
|
||||
This guide provides an overview of how to create your own Agent Skills to extend
|
||||
the capabilities of Gemini CLI.
|
||||
|
||||
## Getting started: The `skill-creator` skill
|
||||
|
||||
The recommended way to create a new skill is to use the built-in `skill-creator`
|
||||
skill. To use it, ask Gemini CLI to create a new skill for you.
|
||||
|
||||
**Example prompt:**
|
||||
|
||||
> "create a new skill called 'code-reviewer'"
|
||||
|
||||
Gemini CLI will then use the `skill-creator` to generate the skill:
|
||||
|
||||
1. Generate a new directory for your skill (e.g., `my-new-skill/`).
|
||||
2. Create a `SKILL.md` file with the necessary YAML frontmatter (`name` and
|
||||
`description`).
|
||||
3. Create the standard resource directories: `scripts/`, `references/`, and
|
||||
`assets/`.
|
||||
|
||||
## Manual skill creation
|
||||
|
||||
If you prefer to create skills manually:
|
||||
|
||||
1. **Create a directory** for your skill (e.g., `my-new-skill/`).
|
||||
2. **Create a `SKILL.md` file** inside the new directory.
|
||||
|
||||
To add additional resources that support the skill, refer to the skill
|
||||
structure.
|
||||
|
||||
## Skill structure
|
||||
|
||||
A skill is a directory containing a `SKILL.md` file at its root.
|
||||
|
||||
### Folder structure
|
||||
|
||||
While a `SKILL.md` file is the only required component, we recommend the
|
||||
following structure for organizing your skill's resources:
|
||||
|
||||
```text
|
||||
my-skill/
|
||||
├── SKILL.md (Required) Instructions and metadata
|
||||
├── scripts/ (Optional) Executable scripts
|
||||
├── references/ (Optional) Static documentation
|
||||
└── assets/ (Optional) Templates and other resources
|
||||
```
|
||||
|
||||
### `SKILL.md` file
|
||||
|
||||
The `SKILL.md` file is the core of your skill. This file uses YAML frontmatter
|
||||
for metadata and Markdown for instructions. For example:
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: code-reviewer
|
||||
description:
|
||||
Use this skill to review code. It supports both local changes and remote Pull
|
||||
Requests.
|
||||
---
|
||||
|
||||
# Code Reviewer
|
||||
|
||||
This skill guides the agent in conducting thorough code reviews.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Determine Review Target
|
||||
|
||||
- **Remote PR**: If the user gives a PR number or URL, target that remote PR.
|
||||
- **Local Changes**: If changes are local... ...
|
||||
```
|
||||
|
||||
- **`name`**: A unique identifier for the skill. This should match the directory
|
||||
name.
|
||||
- **`description`**: A description of what the skill does and when Gemini should
|
||||
use it.
|
||||
- **Body**: The Markdown body of the file contains the instructions that guide
|
||||
the agent's behavior when the skill is active.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user