mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-23 00:01:24 -07:00
Compare commits
538 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9ee227277 | |||
| f26d1f1a36 | |||
| 754e82a0e8 | |||
| 443fd1d325 | |||
| 7cd228f5af | |||
| 8a3fde4c33 | |||
| 1a894c18ea | |||
| 54f1e8c6d7 | |||
| f51391a0f2 | |||
| 1238dcfe91 | |||
| 90e7155971 | |||
| 9d0860bd0f | |||
| 014bfeb89b | |||
| 5890f50496 | |||
| 6b9b778d82 | |||
| f86e0ee418 | |||
| 01635ddb83 | |||
| 12c8469b34 | |||
| 43dda31549 | |||
| dfec94869b | |||
| f42d4e3c16 | |||
| 838f6f8c18 | |||
| 2cad5db770 | |||
| 3805640530 | |||
| 2d10691acb | |||
| 38a9dd18d3 | |||
| ebeea7570d | |||
| c52acebaa2 | |||
| 16e345831b | |||
| 3a0b19d900 | |||
| 451bf32c82 | |||
| 4fd411afe3 | |||
| ac31e80984 | |||
| 49456e4e15 | |||
| a809bc7c51 | |||
| 90304b279c | |||
| 4a10751b49 | |||
| 20b5a4cf46 | |||
| bb4224fdff | |||
| a38f393af7 | |||
| feae856d6e | |||
| e4242edf61 | |||
| 7fb5146c6b | |||
| 897a4d7f83 | |||
| 5155221bbe | |||
| 02995ba939 | |||
| 97a2bd7507 | |||
| 80e091a8e1 | |||
| 82f6ea5b61 | |||
| 469092a72c | |||
| 80d2690540 | |||
| e039fcdf2a | |||
| 3627f4777f | |||
| d8f2a89865 | |||
| f29eb9a569 | |||
| f17cfb2a71 | |||
| 0218817fe3 | |||
| 0803007c8f | |||
| f5c0977e96 | |||
| e80d7cc083 | |||
| 7cc19c2a1b | |||
| 1d72a120fb | |||
| 8f0edcd64f | |||
| 04e875c5c8 | |||
| a79da4f3a9 | |||
| 56809d7069 | |||
| 5dfbb739e5 | |||
| f87072f4e3 | |||
| 6a3175e973 | |||
| 4d1ca92a19 | |||
| b6fc583b0c | |||
| 0d6bd29752 | |||
| 78877942ec | |||
| 493b555646 | |||
| 75a8de83fc | |||
| a7beb890d0 | |||
| 60a6a47d56 | |||
| d313cd7dde | |||
| 77f4be1f3d | |||
| 0da1a2026a | |||
| 37edd1d4df | |||
| 165efa8a38 | |||
| 790f2cf815 | |||
| 704be5a418 | |||
| 9de8c8aadb | |||
| 0657d315fb | |||
| 88bdadc9c6 | |||
| 30c324dec7 | |||
| 40aa7397b6 | |||
| ab48aad213 | |||
| 4fa2c95c59 | |||
| 4e175527a2 | |||
| 40b384de2c | |||
| de8fdcfa16 | |||
| 408afd3c5a | |||
| a93d2a1d1c | |||
| dc5b3114c0 | |||
| 9380e13f6d | |||
| 363854172f | |||
| 7dea5b47a1 | |||
| 997f461cad | |||
| b14a29efa2 | |||
| f496354884 | |||
| 76d1a73606 | |||
| 8fb1b5aa01 | |||
| 9cb48020e1 | |||
| 8943640a71 | |||
| 7213822e84 | |||
| d9f273e440 | |||
| b3e6c28933 | |||
| 4e81f48646 | |||
| 2e3090b6d9 | |||
| c427bd442f | |||
| caa0466416 | |||
| f497240f7e | |||
| 892c8a720d | |||
| 80e3bb9689 | |||
| d494195602 | |||
| 2f0c7518ad | |||
| a03ec92436 | |||
| e67631132d | |||
| 778da08ee1 | |||
| 7125d2cd65 | |||
| 84616626f5 | |||
| ef040eb392 | |||
| 8c1e255ac0 | |||
| 0af13141b2 | |||
| 90895efb29 | |||
| 84875ce911 | |||
| c94edcd862 | |||
| 0f1077076e | |||
| 9a98b0e56c | |||
| 071e2923bb | |||
| 487fb219cc | |||
| d743c6fae6 | |||
| a15568e013 | |||
| 0ccc5ce58f | |||
| 1834ad0298 | |||
| a2d10b7b99 | |||
| 8cec567064 | |||
| fa1a7c10bd | |||
| 49988fc05c | |||
| d6ce310901 | |||
| 2194da2b02 | |||
| dce13019b9 | |||
| 88626f37e3 | |||
| 3aedbbc067 | |||
| 99235fc59d | |||
| 25f422d0e4 | |||
| 6dec6720de | |||
| 3bc56d0ef5 | |||
| 011c0f9bc0 | |||
| 2cf0c75a04 | |||
| 7ab932c8bf | |||
| c2e5b28e94 | |||
| c7d5fcff95 | |||
| 6d99113936 | |||
| fbd8aaad57 | |||
| 9e7c924f7b | |||
| 4edd7c745c | |||
| 12a77da45c | |||
| 8cfebb9e31 | |||
| f8603e990b | |||
| 59b2dea0e5 | |||
| c841070582 | |||
| 4b8d5e7624 | |||
| 7a3f7c383e | |||
| 8e1cecac06 | |||
| b0ffa3b51e | |||
| 58a57b72ae | |||
| 54b7586106 | |||
| c17400b830 | |||
| 47bca39eeb | |||
| 07506dcd0d | |||
| 6cc0b1b136 | |||
| 820a4e3c92 | |||
| 7d08f84305 | |||
| 31337b9269 | |||
| b1a50a58af | |||
| 71f313b51a | |||
| 98aca28985 | |||
| 2de81902c3 | |||
| 1cdfeb6633 | |||
| 743518e1b8 | |||
| 42587de733 | |||
| a5b030b424 | |||
| 2e0641c83b | |||
| 048bf6e514 | |||
| ed469e492b | |||
| cfd7541ad4 | |||
| c4b38a5aef | |||
| 3dc8e7e13c | |||
| 571ca5a555 | |||
| d4c5333dcf | |||
| 1f73ec70c5 | |||
| 69150e87b2 | |||
| 27927c55e5 | |||
| c024064f47 | |||
| ff28d55100 | |||
| dba9b9a0ff | |||
| a007f64d20 | |||
| d1c91f5267 | |||
| aa05b4583d | |||
| 5318610c1d | |||
| 9c0a6864da | |||
| 2e12c34009 | |||
| 2a52611e71 | |||
| 1c43deee07 | |||
| 0758a5eb28 | |||
| 607180bfb2 | |||
| 6edfba481f | |||
| ffb28c772b | |||
| d6f88f8720 | |||
| 194c779f9b | |||
| 189c0ac0a0 | |||
| c47233a474 | |||
| 8999a885f0 | |||
| 93a8d9001c | |||
| cdc5cccc13 | |||
| a4e98c0a4c | |||
| c260550146 | |||
| 7f8f3309a6 | |||
| ebebbbfc20 | |||
| 27344833cb | |||
| aee2cde1a3 | |||
| 2c14954010 | |||
| a38e2f0048 | |||
| 1d383a4a8e | |||
| 6afc47f81c | |||
| 4b2091d402 | |||
| c627d09326 | |||
| 0e5c5b6f49 | |||
| 8573650253 | |||
| 220888ac2d | |||
| b2f775921d | |||
| f7b2632939 | |||
| 8379099e85 | |||
| 3061555d28 | |||
| 22fb83320e | |||
| 63e4bb985b | |||
| fe890429a4 | |||
| 655165cde4 | |||
| 17557b1aeb | |||
| 9600da2c8f | |||
| 2b6dab6136 | |||
| ac9025e9fc | |||
| fafe3e35d2 | |||
| f16f1cced3 | |||
| 963631a3d4 | |||
| 6d7974f1ef | |||
| 34a9d6e421 | |||
| 00b7781c3c | |||
| e827cfdf83 | |||
| cb35ee6710 | |||
| cb289e0724 | |||
| c5ad0abb5d | |||
| e664cc20fe | |||
| 485f3d92d8 | |||
| 5333e5ab20 | |||
| 166845d933 | |||
| 55620235c0 | |||
| 366f9e4766 | |||
| 06e7621b26 | |||
| 8d05bdbe49 | |||
| 5b1f7375a3 | |||
| d613dd05db | |||
| a6d43cba2d | |||
| 161ba28966 | |||
| 05aa1465fe | |||
| 8f6edc50c1 | |||
| 88ddcab616 | |||
| 02792264ed | |||
| 059d9175eb | |||
| 212edf31ed | |||
| 1bb41262b0 | |||
| daf5006237 | |||
| 706d4d4707 | |||
| 24f9ec51d2 | |||
| 050c30330e | |||
| a172b328e2 | |||
| a4318f22ec | |||
| 82e8d67a78 | |||
| 95944ec5af | |||
| ea36ccb567 | |||
| a05c5ed56a | |||
| 0d6d5d90b9 | |||
| b91d177bde | |||
| 36dca862cc | |||
| a5f7b453ca | |||
| 26f04c9d9a | |||
| 5d8bd41937 | |||
| 6b6ea56437 | |||
| 0179726222 | |||
| 0957f7d3e2 | |||
| 773567c6ca | |||
| 58901207bd | |||
| 21e1c60922 | |||
| 35907057ad | |||
| e2a5231e30 | |||
| db6943fbee | |||
| 128e3567cb | |||
| a74bb603c0 | |||
| 565eafc1ec | |||
| 7bba7f437c | |||
| b499562921 | |||
| 86f5a198bd | |||
| 31069329bb | |||
| 3b7c17a22c | |||
| 1d36309f5f | |||
| 7d1de3bccc | |||
| f6c08a114b | |||
| c1fd6027e2 | |||
| 0fd0851e1a | |||
| 5fc8fea8d7 | |||
| 43b93e9e1b | |||
| e09410b6e5 | |||
| 69bf2d75ef | |||
| 96cc8a0dad | |||
| 55db77bb91 | |||
| de628b04fc | |||
| 451edb3ea6 | |||
| 0f7f7be4ef | |||
| f744913584 | |||
| 45100f7c0e | |||
| a7a091360e | |||
| 20113ee595 | |||
| 2a5f798863 | |||
| 570f0235f8 | |||
| e406856343 | |||
| f387e456be | |||
| a9b5c693ca | |||
| 0690192d45 | |||
| 5bcb6b619d | |||
| b238a453e3 | |||
| 6686c8ee4c | |||
| 5724d6be0f | |||
| 615e078341 | |||
| faa7a9da30 | |||
| 5d589946ad | |||
| 464bac270c | |||
| f1bb2af6de | |||
| bc3ed61adb | |||
| 9c4e17b7ce | |||
| d06dba3538 | |||
| 80764c8bb5 | |||
| 14b2f35677 | |||
| 1023c5b7a6 | |||
| af3638640c | |||
| c7b920717f | |||
| 15f7b24312 | |||
| 18cb7fd46c | |||
| 8b01d78512 | |||
| 56c2397e78 | |||
| d1a062bcc4 | |||
| a39461718c | |||
| 3df99d8bcb | |||
| a837b39f8d | |||
| 4ebc43bc66 | |||
| 34b4f1c6e4 | |||
| e77b22e638 | |||
| 1b3e7d674f | |||
| e7f8d9cf1a | |||
| 651ad63ed6 | |||
| cbacdc67d0 | |||
| 7e1938c1bc | |||
| b9f1d832c8 | |||
| 47c5d25d93 | |||
| 28efab483f | |||
| 9fd92c0eea | |||
| 16768c08f2 | |||
| 1aa798dd18 | |||
| f96d5f98fe | |||
| 3c5b5db034 | |||
| 986293bd38 | |||
| adf7b3b717 | |||
| 9637fb3990 | |||
| 06fcdc231c | |||
| d29da15427 | |||
| ab3075feb9 | |||
| 5588000e93 | |||
| 68fef8745e | |||
| e432f7c009 | |||
| 846051f716 | |||
| 1c22c5b37b | |||
| 1762c9c509 | |||
| 0025978d76 | |||
| 4c5e887732 | |||
| 83096c68b0 | |||
| d2b775f9a7 | |||
| 0a8da988ed | |||
| 984f02c180 | |||
| df67f973ed | |||
| 7872d6d7fe | |||
| e116aa34f4 | |||
| ad98294352 | |||
| 2353a6d253 | |||
| 8ac560d2c9 | |||
| c6a9d3de13 | |||
| 8f131ffef7 | |||
| 70f6d6a992 | |||
| c96cb09e09 | |||
| 15298b28c2 | |||
| 7311e242ec | |||
| 21a3925f99 | |||
| ec35ebbe57 | |||
| 65024d4538 | |||
| 4fb3790051 | |||
| 4a040931ef | |||
| e74efc5c0b | |||
| d5a5995281 | |||
| 893ae4d29a | |||
| 370c45de67 | |||
| a93a1ebd65 | |||
| 3f12c1d7c7 | |||
| 61719a3926 | |||
| beaa2a968b | |||
| ca0e6f9bd9 | |||
| 7a70ab9a5d | |||
| e54eecca51 | |||
| 7de3e4dcf9 | |||
| 8c215c7a88 | |||
| fe4fcf89d9 | |||
| 1f5d7014c6 | |||
| 1ae0499e5d | |||
| 9d741abdba | |||
| f54bccfe03 | |||
| 1db169bc66 | |||
| b9b7bba48d | |||
| 29caa52bb7 | |||
| e5adeaca80 | |||
| 6fb58bd31f | |||
| 7c3469713d | |||
| 64c928fce7 | |||
| 61b21e3d63 | |||
| 77027dff82 | |||
| c0dfa1aec3 | |||
| 06173c0885 | |||
| 08b926796c | |||
| b80234aa3e | |||
| efbddcbf98 | |||
| 63cc363606 | |||
| e0044f2868 | |||
| beff8c91aa | |||
| f510394721 | |||
| 811a383d50 | |||
| 8d171e0200 | |||
| 7b6ab50138 | |||
| 44c8b43328 | |||
| 242afd49a1 | |||
| 66c07d7296 | |||
| 40b73c9447 | |||
| 973092df50 | |||
| e446733b53 | |||
| 3344f6849c | |||
| 84936dc85d | |||
| 18cdbbf81a | |||
| 13ccc16457 | |||
| ca78a0f177 | |||
| cb7f7d6c72 | |||
| 0d7e778e08 | |||
| b5f568fefe | |||
| d00b43733c | |||
| 55f5d3923c | |||
| 2d432c1489 | |||
| 597778e55f | |||
| 4e21e5b8a3 | |||
| d9d51ba15b | |||
| aed85725b6 | |||
| 43cf63e189 | |||
| bda4491616 | |||
| 6b303a13eb | |||
| 16468a855d | |||
| 377e834e03 | |||
| 3a32d9723e | |||
| bf3ac20da0 | |||
| a3ef87e6e2 | |||
| 4c4d8bc411 | |||
| f938a3f51d | |||
| c61506bbc1 | |||
| 6a8a0d4faa | |||
| 066da2a1d1 | |||
| 7d1848d578 | |||
| eb95e99b3d | |||
| ca43f8c291 | |||
| dcf5afafda | |||
| 9f76f34049 | |||
| 7c5cd693ce | |||
| c9ed5e41b1 | |||
| 8ae5b56b5b | |||
| 1b265f343f | |||
| fd5c103f99 | |||
| cdc602edd7 | |||
| 782bb4e4bd | |||
| 94f9480a3a | |||
| 9364dd8a49 | |||
| 6d48a12efe | |||
| beab7cc053 | |||
| 6cade3eaec | |||
| c8d18eb2ac | |||
| 91400c5b0b | |||
| 554a5a36a3 | |||
| 7e117ac0ac | |||
| 6f053dd8b9 | |||
| 25af91e4df | |||
| 1edc542b55 | |||
| 119dff3b73 | |||
| 7c4b497a84 | |||
| 65ee6171e7 | |||
| 9cb09ccf8e | |||
| a79f2f81ae | |||
| 140c2b9914 | |||
| 6805e818f7 | |||
| 07e2053e12 | |||
| f9a93a1337 | |||
| 3982a252bb | |||
| e293424bb4 | |||
| 21ad42f677 | |||
| 561418c554 | |||
| d0d3639e16 | |||
| 2f7f967189 | |||
| 46d6b119b6 | |||
| 80929c48c5 | |||
| 35efdfc409 | |||
| bea57a2f3d | |||
| 1df5c98b33 | |||
| 3e95b8ec59 | |||
| 5b5f87abc7 | |||
| 991dca4c40 | |||
| dfba0e91e2 | |||
| 117a2d3844 | |||
| 4b20d93e1d | |||
| 44cdb3e376 | |||
| 9cf410478c | |||
| a255529c6b | |||
| d9d2ce36f2 | |||
| da8c841ef4 | |||
| b7c86b5497 | |||
| 3eebb75b7a |
@@ -0,0 +1,17 @@
|
||||
# Git history - not needed in build context
|
||||
.git
|
||||
|
||||
# Root node_modules - reinstalled inside container via npm ci
|
||||
node_modules
|
||||
|
||||
# Package-level node_modules - reinstalled inside container
|
||||
packages/*/node_modules
|
||||
|
||||
# Development and IDE files
|
||||
.github
|
||||
.vscode
|
||||
npm-debug.log*
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
*.tmp
|
||||
@@ -53,11 +53,27 @@ Gemini CLI project.
|
||||
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.
|
||||
- **State**: Ensure state initialization is explicit (e.g., use `undefined`
|
||||
rather than `true` as a default if the state is truly unknown). Prefer a
|
||||
reducer whenever practical. NEVER disable `react-hooks/exhaustive-deps`; fix
|
||||
the code to correctly declare dependencies instead. Evaluate all the React
|
||||
states in a component and ensure that the `useState` calls are necessary and
|
||||
not cases where values could be derived on render. Ensure there are no stale
|
||||
closures that are relying on a value from a previous render. React Components
|
||||
that modify Settings should effectively use the `useSettingsStore` pattern.
|
||||
Components that configure application Settings (e.g settings.json) are the
|
||||
only reasonable case for unsaved changes to drive UX; in these cases, the
|
||||
Settings store should only be written to on save. If the user experience does
|
||||
not utilize unsaved changes because there is no option to exit without saving
|
||||
or reverting the unsaved changes, then the component should directly read from
|
||||
and write to the Settings store without holding pending changes in component
|
||||
level UI state.
|
||||
- **Effect**: `useEffect` should not be used to synchronize React states, it
|
||||
should only be used for genuine side effects that occur outside of React.
|
||||
Contributors should be able to strongly justify the need for an effect.
|
||||
Consider whether the effect should instead be inside an event handler, or
|
||||
whether it is better off being computed on render. Carefully manage
|
||||
`useEffect` dependencies.
|
||||
- **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.
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
{
|
||||
"experimental": {
|
||||
"plan": true,
|
||||
"extensionReloading": true,
|
||||
"modelSteering": true,
|
||||
"memoryManager": true
|
||||
"autoMemory": true,
|
||||
"memoryManager": true,
|
||||
"topicUpdateNarration": true,
|
||||
"voiceMode": true
|
||||
},
|
||||
"general": {
|
||||
"devtools": true
|
||||
|
||||
@@ -1,190 +1,194 @@
|
||||
#!/bin/bash
|
||||
|
||||
notify() {
|
||||
local title="$1"
|
||||
local message="$2"
|
||||
local pr="$3"
|
||||
local title="${1}"
|
||||
local message="${2}"
|
||||
local pr="${3}"
|
||||
# Terminal escape sequence
|
||||
printf "\e]9;%s | PR #%s | %s\a" "$title" "$pr" "$message"
|
||||
printf "\e]9;%s | PR #%s | %s\a" "${title}" "${pr}" "${message}"
|
||||
# Native macOS notification
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
osascript -e "display notification \"$message\" with title \"$title\" subtitle \"PR #$pr\""
|
||||
os_type="$(uname || true)"
|
||||
if [[ "${os_type}" == "Darwin" ]]; then
|
||||
osascript -e "display notification \"${message}\" with title \"${title}\" subtitle \"PR #${pr}\""
|
||||
fi
|
||||
}
|
||||
|
||||
pr_number=$1
|
||||
if [[ -z "$pr_number" ]]; then
|
||||
pr_number="${1}"
|
||||
if [[ -z "${pr_number}" ]]; then
|
||||
echo "Usage: async-review <pr_number>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
base_dir=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
if [[ -z "$base_dir" ]]; then
|
||||
base_dir="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
||||
if [[ -z "${base_dir}" ]]; then
|
||||
echo "❌ Must be run from within a git repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use the repository's local .gemini/tmp directory for ephemeral worktrees and logs
|
||||
pr_dir="$base_dir/.gemini/tmp/async-reviews/pr-$pr_number"
|
||||
target_dir="$pr_dir/worktree"
|
||||
log_dir="$pr_dir/logs"
|
||||
pr_dir="${base_dir}/.gemini/tmp/async-reviews/pr-${pr_number}"
|
||||
target_dir="${pr_dir}/worktree"
|
||||
log_dir="${pr_dir}/logs"
|
||||
|
||||
cd "$base_dir" || exit 1
|
||||
cd "${base_dir}" || exit 1
|
||||
|
||||
mkdir -p "$log_dir"
|
||||
rm -f "$log_dir/setup.exit" "$log_dir/final-assessment.exit" "$log_dir/final-assessment.md"
|
||||
mkdir -p "${log_dir}"
|
||||
rm -f "${log_dir}/setup.exit" "${log_dir}/final-assessment.exit" "${log_dir}/final-assessment.md"
|
||||
|
||||
echo "🧹 Cleaning up previous worktree if it exists..." | tee -a "$log_dir/setup.log"
|
||||
git worktree remove -f "$target_dir" >> "$log_dir/setup.log" 2>&1 || true
|
||||
git branch -D "gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1 || true
|
||||
git worktree prune >> "$log_dir/setup.log" 2>&1 || true
|
||||
echo "🧹 Cleaning up previous worktree if it exists..." | tee -a "${log_dir}/setup.log"
|
||||
git worktree remove -f "${target_dir}" >> "${log_dir}/setup.log" 2>&1 || true
|
||||
git branch -D "gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1 || true
|
||||
git worktree prune >> "${log_dir}/setup.log" 2>&1 || true
|
||||
|
||||
echo "📡 Fetching PR #$pr_number..." | tee -a "$log_dir/setup.log"
|
||||
if ! git fetch origin -f "pull/$pr_number/head:gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1; then
|
||||
echo 1 > "$log_dir/setup.exit"
|
||||
echo "❌ Fetch failed. Check $log_dir/setup.log"
|
||||
notify "Async Review Failed" "Fetch failed." "$pr_number"
|
||||
echo "📡 Fetching PR #${pr_number}..." | tee -a "${log_dir}/setup.log"
|
||||
if ! git fetch origin -f "pull/${pr_number}/head:gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1; then
|
||||
echo 1 > "${log_dir}/setup.exit"
|
||||
echo "❌ Fetch failed. Check ${log_dir}/setup.log"
|
||||
notify "Async Review Failed" "Fetch failed." "${pr_number}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d "$target_dir" ]]; then
|
||||
echo "🧹 Pruning missing worktrees..." | tee -a "$log_dir/setup.log"
|
||||
git worktree prune >> "$log_dir/setup.log" 2>&1
|
||||
echo "🌿 Creating worktree in $target_dir..." | tee -a "$log_dir/setup.log"
|
||||
if ! git worktree add "$target_dir" "gemini-async-pr-$pr_number" >> "$log_dir/setup.log" 2>&1; then
|
||||
echo 1 > "$log_dir/setup.exit"
|
||||
echo "❌ Worktree creation failed. Check $log_dir/setup.log"
|
||||
notify "Async Review Failed" "Worktree creation failed." "$pr_number"
|
||||
if [[ ! -d "${target_dir}" ]]; then
|
||||
echo "🧹 Pruning missing worktrees..." | tee -a "${log_dir}/setup.log"
|
||||
git worktree prune >> "${log_dir}/setup.log" 2>&1
|
||||
echo "🌿 Creating worktree in ${target_dir}..." | tee -a "${log_dir}/setup.log"
|
||||
if ! git worktree add "${target_dir}" "gemini-async-pr-${pr_number}" >> "${log_dir}/setup.log" 2>&1; then
|
||||
echo 1 > "${log_dir}/setup.exit"
|
||||
echo "❌ Worktree creation failed. Check ${log_dir}/setup.log"
|
||||
notify "Async Review Failed" "Worktree creation failed." "${pr_number}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "🌿 Worktree already exists." | tee -a "$log_dir/setup.log"
|
||||
echo "🌿 Worktree already exists." | tee -a "${log_dir}/setup.log"
|
||||
fi
|
||||
echo 0 > "$log_dir/setup.exit"
|
||||
echo 0 > "${log_dir}/setup.exit"
|
||||
|
||||
cd "$target_dir" || exit 1
|
||||
cd "${target_dir}" || exit 1
|
||||
|
||||
echo "🚀 Launching background tasks. Logs saving to: $log_dir"
|
||||
echo "🚀 Launching background tasks. Logs saving to: ${log_dir}"
|
||||
|
||||
echo " ↳ [1/5] Grabbing PR diff..."
|
||||
rm -f "$log_dir/pr-diff.exit"
|
||||
{ gh pr diff "$pr_number" > "$log_dir/pr-diff.diff" 2>&1; echo $? > "$log_dir/pr-diff.exit"; } &
|
||||
rm -f "${log_dir}/pr-diff.exit"
|
||||
{ gh pr diff "${pr_number}" > "${log_dir}/pr-diff.diff" 2>&1; echo $? > "${log_dir}/pr-diff.exit"; } &
|
||||
|
||||
echo " ↳ [2/5] Starting build and lint..."
|
||||
rm -f "$log_dir/build-and-lint.exit"
|
||||
{ { npm run clean && npm ci && npm run format && npm run build && npm run lint:ci && npm run typecheck; } > "$log_dir/build-and-lint.log" 2>&1; echo $? > "$log_dir/build-and-lint.exit"; } &
|
||||
rm -f "${log_dir}/build-and-lint.exit"
|
||||
{ { npm run clean && npm ci && npm run format && npm run build && npm run lint:ci && npm run typecheck; } > "${log_dir}/build-and-lint.log" 2>&1; echo $? > "${log_dir}/build-and-lint.exit"; } &
|
||||
|
||||
# Dynamically resolve gemini binary (fallback to your nightly path)
|
||||
GEMINI_CMD=$(which gemini || echo "$HOME/.gcli/nightly/node_modules/.bin/gemini")
|
||||
GEMINI_CMD="$(command -v gemini || echo "${HOME}/.gcli/nightly/node_modules/.bin/gemini")"
|
||||
# shellcheck disable=SC2312
|
||||
POLICY_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/policy.toml"
|
||||
|
||||
echo " ↳ [3/5] Starting Gemini code review..."
|
||||
rm -f "$log_dir/review.exit"
|
||||
{ "$GEMINI_CMD" --policy "$POLICY_PATH" -p "/review-frontend $pr_number" > "$log_dir/review.md" 2>&1; echo $? > "$log_dir/review.exit"; } &
|
||||
rm -f "${log_dir}/review.exit"
|
||||
{ "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "/review-frontend ${pr_number}" > "${log_dir}/review.md" 2>&1; echo $? > "${log_dir}/review.exit"; } &
|
||||
|
||||
echo " ↳ [4/5] Starting automated tests (waiting for build and lint)..."
|
||||
rm -f "$log_dir/npm-test.exit"
|
||||
rm -f "${log_dir}/npm-test.exit"
|
||||
{
|
||||
while [ ! -f "$log_dir/build-and-lint.exit" ]; do sleep 1; done
|
||||
if [ "$(cat "$log_dir/build-and-lint.exit")" == "0" ]; then
|
||||
gh pr checks "$pr_number" > "$log_dir/ci-checks.log" 2>&1
|
||||
while [[ ! -f "${log_dir}/build-and-lint.exit" ]]; do sleep 1; done
|
||||
read -r build_exit < "${log_dir}/build-and-lint.exit" || build_exit=""
|
||||
if [[ "${build_exit}" == "0" ]]; then
|
||||
gh pr checks "${pr_number}" > "${log_dir}/ci-checks.log" 2>&1
|
||||
ci_status=$?
|
||||
|
||||
if [ "$ci_status" -eq 0 ]; then
|
||||
echo "CI checks passed. Skipping local npm tests." > "$log_dir/npm-test.log"
|
||||
echo 0 > "$log_dir/npm-test.exit"
|
||||
elif [ "$ci_status" -eq 8 ]; then
|
||||
echo "CI checks are still pending. Skipping local npm tests to avoid duplicate work. Please check GitHub for final results." > "$log_dir/npm-test.log"
|
||||
echo 0 > "$log_dir/npm-test.exit"
|
||||
if [[ "${ci_status}" -eq 0 ]]; then
|
||||
echo "CI checks passed. Skipping local npm tests." > "${log_dir}/npm-test.log"
|
||||
echo 0 > "${log_dir}/npm-test.exit"
|
||||
elif [[ "${ci_status}" -eq 8 ]]; then
|
||||
echo "CI checks are still pending. Skipping local npm tests to avoid duplicate work. Please check GitHub for final results." > "${log_dir}/npm-test.log"
|
||||
echo 0 > "${log_dir}/npm-test.exit"
|
||||
else
|
||||
echo "CI checks failed. Failing checks:" > "$log_dir/npm-test.log"
|
||||
gh pr checks "$pr_number" --json name,bucket -q '.[] | select(.bucket=="fail") | .name' >> "$log_dir/npm-test.log" 2>&1
|
||||
echo "CI checks failed. Failing checks:" > "${log_dir}/npm-test.log"
|
||||
gh pr checks "${pr_number}" --json name,bucket -q '.[] | select(.bucket=="fail") | .name' >> "${log_dir}/npm-test.log" 2>&1
|
||||
|
||||
echo "Attempting to extract failing test files from CI logs..." >> "$log_dir/npm-test.log"
|
||||
pr_branch=$(gh pr view "$pr_number" --json headRefName -q '.headRefName' 2>/dev/null)
|
||||
run_id=$(gh run list --branch "$pr_branch" --workflow ci.yml --json databaseId -q '.[0].databaseId' 2>/dev/null)
|
||||
echo "Attempting to extract failing test files from CI logs..." >> "${log_dir}/npm-test.log"
|
||||
pr_branch="$(gh pr view "${pr_number}" --json headRefName -q '.headRefName' 2>/dev/null || true)"
|
||||
run_id="$(gh run list --branch "${pr_branch}" --workflow ci.yml --json databaseId -q '.[0].databaseId' 2>/dev/null || true)"
|
||||
|
||||
failed_files=""
|
||||
if [[ -n "$run_id" ]]; then
|
||||
failed_files=$(gh run view "$run_id" --log-failed 2>/dev/null | grep -o -E '(packages/[a-zA-Z0-9_-]+|integration-tests|evals)/[a-zA-Z0-9_/-]+\.test\.ts(x)?' | sort | uniq)
|
||||
if [[ -n "${run_id}" ]]; then
|
||||
failed_files="$(gh run view "${run_id}" --log-failed 2>/dev/null | grep -o -E '(packages/[a-zA-Z0-9_-]+|integration-tests|evals)/[a-zA-Z0-9_/-]+\.test\.ts(x)?' | sort | uniq || true)"
|
||||
fi
|
||||
|
||||
if [[ -n "$failed_files" ]]; then
|
||||
echo "Found failing test files from CI:" >> "$log_dir/npm-test.log"
|
||||
for f in $failed_files; do echo " - $f" >> "$log_dir/npm-test.log"; done
|
||||
echo "Running ONLY failing tests locally..." >> "$log_dir/npm-test.log"
|
||||
if [[ -n "${failed_files}" ]]; then
|
||||
echo "Found failing test files from CI:" >> "${log_dir}/npm-test.log"
|
||||
for f in ${failed_files}; do echo " - ${f}" >> "${log_dir}/npm-test.log"; done
|
||||
echo "Running ONLY failing tests locally..." >> "${log_dir}/npm-test.log"
|
||||
|
||||
exit_code=0
|
||||
for file in $failed_files; do
|
||||
if [[ "$file" == packages/* ]]; then
|
||||
ws_dir=$(echo "$file" | cut -d'/' -f1,2)
|
||||
for file in ${failed_files}; do
|
||||
if [[ "${file}" == packages/* ]]; then
|
||||
ws_dir="$(echo "${file}" | cut -d'/' -f1,2)"
|
||||
else
|
||||
ws_dir=$(echo "$file" | cut -d'/' -f1)
|
||||
ws_dir="$(echo "${file}" | cut -d'/' -f1)"
|
||||
fi
|
||||
rel_file=${file#$ws_dir/}
|
||||
rel_file="${file#"${ws_dir}"/}"
|
||||
|
||||
echo "--- Running $rel_file in workspace $ws_dir ---" >> "$log_dir/npm-test.log"
|
||||
if ! npm run test:ci -w "$ws_dir" -- "$rel_file" >> "$log_dir/npm-test.log" 2>&1; then
|
||||
echo "--- Running ${rel_file} in workspace ${ws_dir} ---" >> "${log_dir}/npm-test.log"
|
||||
if ! npm run test:ci -w "${ws_dir}" -- "${rel_file}" >> "${log_dir}/npm-test.log" 2>&1; then
|
||||
exit_code=1
|
||||
fi
|
||||
done
|
||||
echo $exit_code > "$log_dir/npm-test.exit"
|
||||
echo "${exit_code}" > "${log_dir}/npm-test.exit"
|
||||
else
|
||||
echo "Could not extract specific failing files. Skipping full local test suite as it takes too long. Please check CI logs manually." >> "$log_dir/npm-test.log"
|
||||
echo 1 > "$log_dir/npm-test.exit"
|
||||
echo "Could not extract specific failing files. Skipping full local test suite as it takes too long. Please check CI logs manually." >> "${log_dir}/npm-test.log"
|
||||
echo 1 > "${log_dir}/npm-test.exit"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Skipped due to build-and-lint failure" > "$log_dir/npm-test.log"
|
||||
echo 1 > "$log_dir/npm-test.exit"
|
||||
echo "Skipped due to build-and-lint failure" > "${log_dir}/npm-test.log"
|
||||
echo 1 > "${log_dir}/npm-test.exit"
|
||||
fi
|
||||
} &
|
||||
|
||||
echo " ↳ [5/5] Starting Gemini test execution (waiting for build and lint)..."
|
||||
rm -f "$log_dir/test-execution.exit"
|
||||
rm -f "${log_dir}/test-execution.exit"
|
||||
{
|
||||
while [ ! -f "$log_dir/build-and-lint.exit" ]; do sleep 1; done
|
||||
if [ "$(cat "$log_dir/build-and-lint.exit")" == "0" ]; then
|
||||
"$GEMINI_CMD" --policy "$POLICY_PATH" -p "Analyze the diff for PR $pr_number using 'gh pr diff $pr_number'. Instead of running the project's automated test suite (like 'npm test'), physically exercise the newly changed code in the terminal (e.g., by writing a temporary script to call the new functions, or testing the CLI command directly). Verify the feature's behavior works as expected. IMPORTANT: Do NOT modify any source code to fix errors. Just exercise the code and log the results, reporting any failures clearly. Do not ask for user confirmation." > "$log_dir/test-execution.log" 2>&1; echo $? > "$log_dir/test-execution.exit"
|
||||
while [[ ! -f "${log_dir}/build-and-lint.exit" ]]; do sleep 1; done
|
||||
read -r build_exit < "${log_dir}/build-and-lint.exit" || build_exit=""
|
||||
if [[ "${build_exit}" == "0" ]]; then
|
||||
"${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "Analyze the diff for PR ${pr_number} using 'gh pr diff ${pr_number}'. Instead of running the project's automated test suite (like 'npm test'), physically exercise the newly changed code in the terminal (e.g., by writing a temporary script to call the new functions, or testing the CLI command directly). Verify the feature's behavior works as expected. IMPORTANT: Do NOT modify any source code to fix errors. Just exercise the code and log the results, reporting any failures clearly. Do not ask for user confirmation." > "${log_dir}/test-execution.log" 2>&1; echo $? > "${log_dir}/test-execution.exit"
|
||||
else
|
||||
echo "Skipped due to build-and-lint failure" > "$log_dir/test-execution.log"
|
||||
echo 1 > "$log_dir/test-execution.exit"
|
||||
echo "Skipped due to build-and-lint failure" > "${log_dir}/test-execution.log"
|
||||
echo 1 > "${log_dir}/test-execution.exit"
|
||||
fi
|
||||
} &
|
||||
|
||||
echo "✅ All tasks dispatched!"
|
||||
echo "You can monitor progress with: tail -f $log_dir/*.log"
|
||||
echo "Read your review later at: $log_dir/review.md"
|
||||
echo "You can monitor progress with: tail -f ${log_dir}/*.log"
|
||||
echo "Read your review later at: ${log_dir}/review.md"
|
||||
|
||||
# Polling loop to wait for all background tasks to finish
|
||||
tasks=("pr-diff" "build-and-lint" "review" "npm-test" "test-execution")
|
||||
log_files=("pr-diff.diff" "build-and-lint.log" "review.md" "npm-test.log" "test-execution.log")
|
||||
|
||||
declare -A task_done
|
||||
for t in "${tasks[@]}"; do task_done[$t]=0; done
|
||||
for t in "${tasks[@]}"; do task_done[${t}]=0; done
|
||||
|
||||
all_done=0
|
||||
while [[ $all_done -eq 0 ]]; do
|
||||
while [[ "${all_done}" -eq 0 ]]; do
|
||||
clear
|
||||
echo "=================================================="
|
||||
echo "🚀 Async PR Review Status for PR #$pr_number"
|
||||
echo "🚀 Async PR Review Status for PR #${pr_number}"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
|
||||
all_done=1
|
||||
for i in "${!tasks[@]}"; do
|
||||
t="${tasks[$i]}"
|
||||
t="${tasks[${i}]}"
|
||||
|
||||
if [[ -f "$log_dir/$t.exit" ]]; then
|
||||
exit_code=$(cat "$log_dir/$t.exit")
|
||||
if [[ "$exit_code" == "0" ]]; then
|
||||
echo " ✅ $t: SUCCESS"
|
||||
if [[ -f "${log_dir}/${t}.exit" ]]; then
|
||||
read -r task_exit < "${log_dir}/${t}.exit" || task_exit=""
|
||||
if [[ "${task_exit}" == "0" ]]; then
|
||||
echo " ✅ ${t}: SUCCESS"
|
||||
else
|
||||
echo " ❌ $t: FAILED (exit code $exit_code)"
|
||||
echo " ❌ ${t}: FAILED (exit code ${task_exit})"
|
||||
fi
|
||||
task_done[$t]=1
|
||||
task_done[${t}]=1
|
||||
else
|
||||
echo " ⏳ $t: RUNNING"
|
||||
echo " ⏳ ${t}: RUNNING"
|
||||
all_done=0
|
||||
fi
|
||||
done
|
||||
@@ -195,47 +199,47 @@ while [[ $all_done -eq 0 ]]; do
|
||||
echo "=================================================="
|
||||
|
||||
for i in "${!tasks[@]}"; do
|
||||
t="${tasks[$i]}"
|
||||
log_file="${log_files[$i]}"
|
||||
t="${tasks[${i}]}"
|
||||
log_file="${log_files[${i}]}"
|
||||
|
||||
if [[ ${task_done[$t]} -eq 0 ]]; then
|
||||
if [[ -f "$log_dir/$log_file" ]]; then
|
||||
if [[ "${task_done[${t}]}" -eq 0 ]]; then
|
||||
if [[ -f "${log_dir}/${log_file}" ]]; then
|
||||
echo ""
|
||||
echo "--- $t ---"
|
||||
tail -n 5 "$log_dir/$log_file"
|
||||
echo "--- ${t} ---"
|
||||
tail -n 5 "${log_dir}/${log_file}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $all_done -eq 0 ]]; then
|
||||
if [[ "${all_done}" -eq 0 ]]; then
|
||||
sleep 3
|
||||
fi
|
||||
done
|
||||
|
||||
clear
|
||||
echo "=================================================="
|
||||
echo "🚀 Async PR Review Status for PR #$pr_number"
|
||||
echo "🚀 Async PR Review Status for PR #${pr_number}"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
for t in "${tasks[@]}"; do
|
||||
exit_code=$(cat "$log_dir/$t.exit")
|
||||
if [[ "$exit_code" == "0" ]]; then
|
||||
echo " ✅ $t: SUCCESS"
|
||||
read -r task_exit < "${log_dir}/${t}.exit" || task_exit=""
|
||||
if [[ "${task_exit}" == "0" ]]; then
|
||||
echo " ✅ ${t}: SUCCESS"
|
||||
else
|
||||
echo " ❌ $t: FAILED (exit code $exit_code)"
|
||||
echo " ❌ ${t}: FAILED (exit code ${task_exit})"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "⏳ Tasks complete! Synthesizing final assessment..."
|
||||
if ! "$GEMINI_CMD" --policy "$POLICY_PATH" -p "Read the review at $log_dir/review.md, the automated test logs at $log_dir/npm-test.log, and the manual test execution logs at $log_dir/test-execution.log. Summarize the results, state whether the build and tests passed based on $log_dir/build-and-lint.exit and $log_dir/npm-test.exit, and give a final recommendation for PR $pr_number." > "$log_dir/final-assessment.md" 2>&1; then
|
||||
echo $? > "$log_dir/final-assessment.exit"
|
||||
if ! "${GEMINI_CMD}" --policy "${POLICY_PATH}" -p "Read the review at ${log_dir}/review.md, the automated test logs at ${log_dir}/npm-test.log, and the manual test execution logs at ${log_dir}/test-execution.log. Summarize the results, state whether the build and tests passed based on ${log_dir}/build-and-lint.exit and ${log_dir}/npm-test.exit, and give a final recommendation for PR ${pr_number}." > "${log_dir}/final-assessment.md" 2>&1; then
|
||||
echo $? > "${log_dir}/final-assessment.exit"
|
||||
echo "❌ Final assessment synthesis failed!"
|
||||
echo "Check $log_dir/final-assessment.md for details."
|
||||
notify "Async Review Failed" "Final assessment synthesis failed." "$pr_number"
|
||||
echo "Check ${log_dir}/final-assessment.md for details."
|
||||
notify "Async Review Failed" "Final assessment synthesis failed." "${pr_number}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 0 > "$log_dir/final-assessment.exit"
|
||||
echo "✅ Final assessment complete! Check $log_dir/final-assessment.md"
|
||||
notify "Async Review Complete" "Review and test execution finished successfully." "$pr_number"
|
||||
echo 0 > "${log_dir}/final-assessment.exit"
|
||||
echo "✅ Final assessment complete! Check ${log_dir}/final-assessment.md"
|
||||
notify "Async Review Complete" "Review and test execution finished successfully." "${pr_number}"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#!/bin/bash
|
||||
pr_number=$1
|
||||
pr_number="${1}"
|
||||
|
||||
if [[ -z "$pr_number" ]]; then
|
||||
if [[ -z "${pr_number}" ]]; then
|
||||
echo "Usage: check-async-review <pr_number>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
base_dir=$(git rev-parse --show-toplevel 2>/dev/null)
|
||||
if [[ -z "$base_dir" ]]; then
|
||||
base_dir="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
||||
if [[ -z "${base_dir}" ]]; then
|
||||
echo "❌ Must be run from within a git repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_dir="$base_dir/.gemini/tmp/async-reviews/pr-$pr_number/logs"
|
||||
log_dir="${base_dir}/.gemini/tmp/async-reviews/pr-${pr_number}/logs"
|
||||
|
||||
if [[ ! -d "$log_dir" ]]; then
|
||||
if [[ ! -d "${log_dir}" ]]; then
|
||||
echo "STATUS: NOT_FOUND"
|
||||
echo "❌ No logs found for PR #$pr_number in $log_dir"
|
||||
echo "❌ No logs found for PR #${pr_number} in ${log_dir}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -34,32 +34,32 @@ all_done=true
|
||||
echo "STATUS: CHECKING"
|
||||
|
||||
for task_info in "${tasks[@]}"; do
|
||||
IFS="|" read -r task_name log_file <<< "$task_info"
|
||||
IFS="|" read -r task_name log_file <<< "${task_info}"
|
||||
|
||||
file_path="$log_dir/$log_file"
|
||||
exit_file="$log_dir/$task_name.exit"
|
||||
file_path="${log_dir}/${log_file}"
|
||||
exit_file="${log_dir}/${task_name}.exit"
|
||||
|
||||
if [[ -f "$exit_file" ]]; then
|
||||
exit_code=$(cat "$exit_file")
|
||||
if [[ "$exit_code" == "0" ]]; then
|
||||
echo "✅ $task_name: SUCCESS"
|
||||
if [[ -f "${exit_file}" ]]; then
|
||||
read -r exit_code < "${exit_file}" || exit_code=""
|
||||
if [[ "${exit_code}" == "0" ]]; then
|
||||
echo "✅ ${task_name}: SUCCESS"
|
||||
else
|
||||
echo "❌ $task_name: FAILED (exit code $exit_code)"
|
||||
echo " Last lines of $file_path:"
|
||||
tail -n 3 "$file_path" | sed 's/^/ /'
|
||||
echo "❌ ${task_name}: FAILED (exit code ${exit_code})"
|
||||
echo " Last lines of ${file_path}:"
|
||||
tail -n 3 "${file_path}" | sed 's/^/ /' || true
|
||||
fi
|
||||
elif [[ -f "$file_path" ]]; then
|
||||
echo "⏳ $task_name: RUNNING"
|
||||
elif [[ -f "${file_path}" ]]; then
|
||||
echo "⏳ ${task_name}: RUNNING"
|
||||
all_done=false
|
||||
else
|
||||
echo "➖ $task_name: NOT STARTED"
|
||||
echo "➖ ${task_name}: NOT STARTED"
|
||||
all_done=false
|
||||
fi
|
||||
done
|
||||
|
||||
if $all_done; then
|
||||
if [[ "${all_done}" == "true" ]]; then
|
||||
echo "STATUS: COMPLETE"
|
||||
echo "LOG_DIR: $log_dir"
|
||||
echo "LOG_DIR: ${log_dir}"
|
||||
else
|
||||
echo "STATUS: IN_PROGRESS"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -33,6 +33,35 @@ evaluation.
|
||||
- **Warning**: Do not lose test fidelity by making prompts too direct/easy.
|
||||
- **Primary Fix Trigger**: Adjust tool descriptions, system prompts
|
||||
(`snippets.ts`), or **modules that contribute to the prompt template**.
|
||||
- Fixes should generally try to improve the prompt
|
||||
`@packages/core/src/prompts/snippets.ts` first.
|
||||
- **Instructional Generality**: Changes to the system prompt should aim to
|
||||
be as general as possible while still accomplishing the goal. Specificity
|
||||
should be added only as needed.
|
||||
- **Principle**: Instead of creating "forbidden lists" for specific syntax
|
||||
(e.g., "Don't use `Object.create()`"), formulate a broader engineering
|
||||
principle that covers the underlying issue (e.g., "Prioritize explicit
|
||||
composition over hidden prototype manipulation"). This improves
|
||||
steerability across a wider range of similar scenarios.
|
||||
- _Low Specificity_: "Follow ecosystem best practices"
|
||||
- _Medium Specificity_: "Utilize OOP and functional best practices, as
|
||||
applicable"
|
||||
- _High Specificity_: Provide ecosystem-specific hints as examples of a
|
||||
broader principle rather than direct instructions. e.g., "NEVER use
|
||||
hacks like bypassing the type system or employing 'hidden' logic (e.g.:
|
||||
reflection, prototype manipulation). Instead, use explicit and idiomatic
|
||||
language features (e.g.: type guards, explicit class instantiation, or
|
||||
object spread) that maintain structural integrity."
|
||||
- **Prompt Simplification**: Once the test is passing, use `ask_user` to
|
||||
determine if prompt simplification is desired.
|
||||
- **Criteria**: Simplification should be attempted only if there are
|
||||
related clauses that can be de-duplicated or reparented under a single
|
||||
heading.
|
||||
- **Verification**: As part of simplification, you MUST identify and run
|
||||
any behavioral eval tests that might be affected by the changes to
|
||||
ensure no regressions are introduced.
|
||||
- Test fixes should not "cheat" by changing a test's `GEMINI.md` file or by
|
||||
updating the test's prompt to instruct it to not repro the bug.
|
||||
- **Warning**: Prompts have multiple configurations; ensure your fix targets
|
||||
the correct config for the model in question.
|
||||
4. **Architecture Options**: If prompt or instruction tuning triggers no
|
||||
|
||||
@@ -162,5 +162,7 @@ instructions for the other section.
|
||||
|
||||
## Finalize
|
||||
|
||||
- After making changes, run `npm run format` ONLY to ensure consistency.
|
||||
- After making changes, if `npm run format` fails, it may be necessary to run
|
||||
`npm install` first to ensure all formatting dependencies are available.
|
||||
Then, run `npm run format` to ensure consistency.
|
||||
- Delete any temporary files created during the process.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: docs-writer
|
||||
description:
|
||||
Always use this skill when the task involves writing, reviewing, or editing
|
||||
Always use this skill when the task involves writing, reviewing, or editing
|
||||
files in the `/docs` directory or any `.md` files in the repository.
|
||||
---
|
||||
|
||||
@@ -24,7 +24,7 @@ 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.
|
||||
- **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.
|
||||
@@ -47,8 +47,8 @@ Write precisely to ensure your instructions are unambiguous.
|
||||
"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.
|
||||
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
|
||||
@@ -85,17 +85,25 @@ accessible.
|
||||
|
||||
- **Callouts**: Use GitHub-flavored markdown alerts to highlight important
|
||||
information. To ensure the formatting is preserved by `npm run format`, place
|
||||
an empty line, then the `<!-- prettier-ignore -->` comment directly before
|
||||
the callout block. The callout type (`[!TYPE]`) should be on the first line,
|
||||
followed by a newline, and then the content, with each subsequent line of
|
||||
content starting with `>`. Available types are `NOTE`, `TIP`, `IMPORTANT`,
|
||||
`WARNING`, and `CAUTION`.
|
||||
an empty line, then a prettier ignore comment directly before the callout
|
||||
block. Use `<!-- prettier-ignore -->` for standard Markdown files (`.md`) and
|
||||
`{/* prettier-ignore */}` for MDX files (`.mdx`). The callout type (`[!TYPE]`)
|
||||
should be on the first line, followed by a newline, and then the content, with
|
||||
each subsequent line of content starting with `>`. Available types are `NOTE`,
|
||||
`TIP`, `IMPORTANT`, `WARNING`, and `CAUTION`.
|
||||
|
||||
Example:
|
||||
Example (.md):
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> This is an example of a multi-line note that will be preserved
|
||||
> by Prettier.
|
||||
|
||||
Example (.mdx):
|
||||
|
||||
{/* prettier-ignore */}
|
||||
> [!NOTE]
|
||||
> This is an example of a multi-line note that will be preserved
|
||||
> by Prettier.
|
||||
|
||||
### Links
|
||||
@@ -118,9 +126,10 @@ accessible.
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> This is an experimental feature currently under active development.
|
||||
(Note: Use `{/* prettier-ignore */}` if editing an `.mdx` file.)
|
||||
|
||||
- **Headings:** Use hierarchical headings to support the user journey.
|
||||
- **Procedures:**
|
||||
- **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.
|
||||
@@ -134,7 +143,7 @@ accessible.
|
||||
|
||||
## Phase 2: Preparation
|
||||
Before modifying any documentation, thoroughly investigate the request and the
|
||||
surrounding context.
|
||||
surrounding context.
|
||||
|
||||
1. **Clarify:** Understand the core request. Differentiate between writing new
|
||||
content and editing existing content. If the request is ambiguous (e.g.,
|
||||
@@ -145,6 +154,8 @@ surrounding context.
|
||||
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.
|
||||
6. **Audit Docset:** If asked to audit the documentation, follow the procedural
|
||||
guide in [docs-auditing.md](./references/docs-auditing.md).
|
||||
|
||||
## Phase 3: Execution
|
||||
Implement your plan by either updating existing files or creating new ones
|
||||
@@ -157,7 +168,7 @@ 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
|
||||
- **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.
|
||||
@@ -168,15 +179,16 @@ documentation.
|
||||
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.
|
||||
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.
|
||||
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:** If `npm run format` fails, it may be necessary to run `npm
|
||||
install` first to ensure all formatting dependencies are available. 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,195 @@
|
||||
# Procedural Guide: Auditing the Docset
|
||||
|
||||
This guide outlines the process for auditing the Gemini CLI documentation for
|
||||
correctness and adherence to style guidelines. This process involves both an
|
||||
"Editor" and "Technical Writer" phase.
|
||||
|
||||
## Objective
|
||||
|
||||
To ensure all public-facing documentation is accurate, up-to-date, adheres to
|
||||
the Gemini CLI documentation style guide, and reflects the current state of the
|
||||
codebase.
|
||||
|
||||
## Phase 1: Editor Audit
|
||||
|
||||
**Role:** The editor is responsible for identifying potential issues based on
|
||||
style guide violations and technical inaccuracies.
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Identify Documentation Scope:**
|
||||
- Read `docs/sidebar.json` to get a list of all viewable documentation
|
||||
pages.
|
||||
- For each entry with a `slug`, convert it into a file path (e.g., `docs` ->
|
||||
`docs/index.md`, `docs/get-started` -> `docs/get-started.md`). Ignore
|
||||
entries with `link` properties.
|
||||
|
||||
2. **Prepare Audit Results File:**
|
||||
- Create a new Markdown file named `audit-results-[YYYY-MM-DD].md` (e.g.,
|
||||
`audit-results-2026-03-13.md`). This file will contain all identified
|
||||
violations and recommendations.
|
||||
|
||||
3. **Retrieve Style Guidelines:**
|
||||
- Familiarize yourself with the `docs-writer` skill instructions and the
|
||||
included style guidelines.
|
||||
|
||||
4. **Audit Each Document:**
|
||||
- For each documentation file identified in Step 1, read its content.
|
||||
- **Review against Style Guide:**
|
||||
- **Voice and Tone Violations:**
|
||||
- **Unprofessional Tone:** Identify phrasing that is overly casual,
|
||||
defensive, or lacks a professional and friendly demeanor.
|
||||
- **Indirectness or Vagueness:** Identify sentences that are
|
||||
unnecessarily wordy or fail to be concise and direct.
|
||||
- **Incorrect Pronoun:** Identify any use of third-person pronouns
|
||||
(e.g., "we," "they," "the user") when referring to the reader, instead
|
||||
of the second-person pronoun **"you"**.
|
||||
- **Passive Voice:** Identify sentences written in the passive voice.
|
||||
- **Incorrect Tense:** Identify the use of past or future tense verbs,
|
||||
instead of the **present tense**.
|
||||
- **Poor Vocabulary:** Identify the use of jargon, slang, or overly
|
||||
informal language.
|
||||
- **Language and Grammar Violations:**
|
||||
- **Lack of Conciseness:** Identify unnecessarily long phrases or
|
||||
sentences.
|
||||
- **Punctuation Errors:** Identify incorrect or missing punctuation.
|
||||
- **Ambiguous Dates:** Identify dates that could be misinterpreted
|
||||
(e.g., "next Monday" instead of "April 15, 2026").
|
||||
- **Abbreviation Usage:** Identify the use of abbreviations that should
|
||||
be spelled out (e.g., "e.g." instead of "for example").
|
||||
- **Terminology:** Check for incorrect or inconsistent use of
|
||||
product-specific terms (e.g., "quota" vs. "limit").
|
||||
- **Formatting and Syntax Violations:**
|
||||
- **Missing Overview:** Check for the absence of a brief overview
|
||||
paragraph at the start of the document.
|
||||
- **Line Length:** Identify any lines of text that exceed **80
|
||||
characters** (text wrap violation).
|
||||
- **Casing:** Identify incorrect casing for headings, titles, or named
|
||||
entities (e.g., product names like `Gemini CLI`).
|
||||
- **List Formatting:** Identify incorrectly formatted lists (e.g.,
|
||||
inconsistent indentation or numbering).
|
||||
- **Incorrect Emphasis:** Identify incorrect use of bold text (should
|
||||
only be used for UI elements) or code font (should be used for code,
|
||||
file names, or command-line input).
|
||||
- **Link Quality:** Identify links with non-descriptive anchor text
|
||||
(e.g., "click here").
|
||||
- **Image Alt Text:** Identify images with missing or poor-quality
|
||||
(non-descriptive) alt text.
|
||||
- **Structure Violations:**
|
||||
- **Missing BLUF:** Check for the absence of a "Bottom Line Up Front"
|
||||
summary at the start of complex sections or documents.
|
||||
- **Experimental Feature Notes:** Identify experimental features that
|
||||
are not clearly labeled with a standard note.
|
||||
- **Heading Hierarchy:** Check for skipped heading levels (e.g., going
|
||||
from `##` to `####`).
|
||||
- **Procedure Clarity:** Check for procedural steps that do not start
|
||||
with an imperative verb or where a condition is placed _after_ the
|
||||
instruction.
|
||||
- **Element Misuse:** Identify the incorrect or inappropriate use of
|
||||
special elements (e.g., Notes, Warnings, Cautions).
|
||||
- **Table of Contents:** Identify the presence of a dynamically
|
||||
generated or manually included table of contents.
|
||||
- **Missing Next Steps:** Check for procedural documents that lack a
|
||||
"Next steps" section (if applicable).
|
||||
- **Verify Code Accuracy (if applicable):**
|
||||
- If the document contains code snippets (e.g., shell commands, API calls,
|
||||
file paths, Docker image versions), use `grep_search` and `read_file`
|
||||
within the `packages/` directory (or other relevant parts of the
|
||||
codebase) to ensure the code is still accurate and up-to-date. Pay close
|
||||
attention to version numbers, package names, and command syntax.
|
||||
- **Record Findings:** For each **violation** or inaccuracy found:
|
||||
- Note the file path.
|
||||
- Describe the violation (e.g., "Violation (Language and Grammar): Uses
|
||||
'e.g.'").
|
||||
- Provide a clear and actionable recommendation to correct the issue.
|
||||
(e.g., "Recommendation: Replace 'e.g.' with 'for example'." or
|
||||
"Recommendation: Replace '...' with '...' in active voice.).
|
||||
- Append these findings to `audit-results-[YYYY-MM-DD].md`.
|
||||
|
||||
## Phase 2: Software Engineer Audit
|
||||
|
||||
**Role:** The software engineer is responsible for finding undocumented features
|
||||
by auditing the codebase and recent changelogs, and passing these findings to
|
||||
the technical writer.
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Proactive Codebase Audit:**
|
||||
- Audit high-signal areas of the codebase to identify undocumented features.
|
||||
You MUST review:
|
||||
- `packages/cli/src/commands/`
|
||||
- `packages/core/src/tools/`
|
||||
- `packages/cli/src/config/settings.ts`
|
||||
|
||||
2. **Review Recent Updates:**
|
||||
- Check recent changelogs in stable and announcements within the
|
||||
documentation to see if newly introduced features are documented properly.
|
||||
|
||||
3. **Evaluate and Record Findings:**
|
||||
- Determine if these features are adequately covered in the docs. They do
|
||||
not need to be documented word for word, but major features that customers
|
||||
should care about probably should have an article.
|
||||
- Append your findings to the `audit-results-[YYYY-MM-DD].md` file,
|
||||
providing a brief description of the feature and where it should be
|
||||
documented.
|
||||
|
||||
## Phase 3: Technical Writer Implementation
|
||||
|
||||
**Role:** The technical writer handles input from both the editor and the
|
||||
software engineer, makes appropriate decisions about what to change, and
|
||||
implements the approved changes.
|
||||
|
||||
### Steps
|
||||
|
||||
1. **Review Audit Results:**
|
||||
- Read `audit-results-[YYYY-MM-DD].md` to understand all identified issues,
|
||||
undocumented features, and recommendations from both the Editor and
|
||||
Software Engineer phases.
|
||||
|
||||
2. **Make Decisions and Log Reasoning:**
|
||||
- Create or update an implementation log (e.g.,
|
||||
`audit-implementation-log-[YYYY-MM-DD].md`).
|
||||
- Make sure the logs are updated for all steps, documenting your reasoning
|
||||
for each recommendation (why it was accepted, modified, or rejected). This
|
||||
is required for a final check by a human in the PR.
|
||||
|
||||
3. **Implement Changes:**
|
||||
- For each approved recommendation:
|
||||
- Read the target documentation file.
|
||||
- Apply the recommended change using the `replace` tool. Pay close
|
||||
attention to `old_string` for exact matches, including whitespace and
|
||||
newlines. For multiple occurrences of the same simple string (e.g.,
|
||||
"e.g."), use `allow_multiple: true`.
|
||||
- **String replacement safeguards:** When applying these fixes across the
|
||||
docset, you must verify the following:
|
||||
- **Preserve Code Blocks:** Explicitly verify that no code blocks,
|
||||
inline code snippets, terminal commands, or file paths have been
|
||||
erroneously capitalized or modified.
|
||||
- **Preserve Literal Strings:** Never alter the wording of literal error
|
||||
messages, UI quotes, or system logs. For example, if a style rule says
|
||||
to remove the word "please", you must NOT remove it if it appears
|
||||
inside a quoted error message (e.g.,
|
||||
`Error: Please contact your administrator`).
|
||||
- **Verify Sentence Casing:** When removing filler words (like "please")
|
||||
from the beginning of a sentence or list item, always verify that the
|
||||
new first word of the sentence is properly capitalized.
|
||||
- For structural changes (e.g., adding an overview paragraph), use
|
||||
`replace` or `write_file` as appropriate.
|
||||
- For broken links, determine the correct new path or update the link
|
||||
text.
|
||||
- For creating new files (e.g., `docs/get-started.md` to fix a broken
|
||||
link, or a new feature article), use `write_file`.
|
||||
|
||||
4. **Execute Auto-Generation Scripts:**
|
||||
- Some documentation pages are auto-generated from the codebase and should
|
||||
be updated using npm scripts rather than manual edits. After implementing
|
||||
manual changes (especially if you edited settings or configurations based
|
||||
on SWE recommendations), ensure you run:
|
||||
- `npm run docs:settings` to generate/update the configuration reference.
|
||||
- `npm run docs:keybindings` to generate/update the keybindings reference.
|
||||
|
||||
5. **Format Code:**
|
||||
- **Dependencies:** If `npm run format` fails, it may be necessary to run
|
||||
`npm install` first to ensure all formatting dependencies are available.
|
||||
- After all changes have been implemented, run `npm run format` to ensure
|
||||
consistent formatting across the project.
|
||||
@@ -0,0 +1,23 @@
|
||||
name: 'Download Mac Binaries'
|
||||
description: 'Downloads the unsigned macOS binaries (x64 and arm64)'
|
||||
inputs:
|
||||
path:
|
||||
description: 'The base path to download the binaries to'
|
||||
required: true
|
||||
default: 'dist'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: 'Download macOS arm64 binary'
|
||||
uses: 'actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806' # ratchet:actions/download-artifact@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: 'gemini-darwin-arm64-unsigned'
|
||||
path: '${{ inputs.path }}/darwin-arm64'
|
||||
|
||||
- name: 'Download macOS x64 binary'
|
||||
uses: 'actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806' # ratchet:actions/download-artifact@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: 'gemini-darwin-x64-unsigned'
|
||||
path: '${{ inputs.path }}/darwin-x64'
|
||||
@@ -175,7 +175,9 @@ runs:
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_CORE_PACKAGE_NAME}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${INPUTS_CORE_PACKAGE_NAME} false
|
||||
if [[ "${INPUTS_DRY_RUN}" == "false" ]]; then
|
||||
npm dist-tag rm ${INPUTS_CORE_PACKAGE_NAME} false
|
||||
fi
|
||||
|
||||
- name: '🔗 Install latest core package'
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
@@ -193,7 +195,7 @@ runs:
|
||||
INPUTS_A2A_PACKAGE_NAME: '${{ inputs.a2a-package-name }}'
|
||||
|
||||
- name: '📦 Prepare bundled CLI for npm release'
|
||||
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/' && inputs.npm-tag != 'latest'"
|
||||
if: "inputs.npm-registry-url != 'https://npm.pkg.github.com/'"
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
@@ -248,7 +250,9 @@ runs:
|
||||
--dry-run="${INPUTS_DRY_RUN}" \
|
||||
--workspace="${INPUTS_A2A_PACKAGE_NAME}" \
|
||||
--no-tag
|
||||
npm dist-tag rm ${INPUTS_A2A_PACKAGE_NAME} false
|
||||
if [[ "${INPUTS_DRY_RUN}" == "false" ]]; then
|
||||
npm dist-tag rm ${INPUTS_A2A_PACKAGE_NAME} false
|
||||
fi
|
||||
|
||||
- name: '🔬 Verify NPM release by version'
|
||||
uses: './.github/actions/verify-release'
|
||||
@@ -287,8 +291,38 @@ runs:
|
||||
INPUTS_PREVIOUS_TAG: '${{ inputs.previous-tag }}'
|
||||
shell: 'bash'
|
||||
run: |
|
||||
rm -f gemini-cli-bundle.zip
|
||||
(cd bundle && chmod +x gemini.js && zip -r ../gemini-cli-bundle.zip .)
|
||||
|
||||
echo "Testing the generated bundle archive..."
|
||||
rm -rf test-bundle
|
||||
mkdir -p test-bundle
|
||||
unzip -q gemini-cli-bundle.zip -d test-bundle
|
||||
|
||||
# Verify it runs and outputs a version
|
||||
BUNDLE_VERSION=$(node test-bundle/gemini.js --version | xargs)
|
||||
echo "Bundle version output: ${BUNDLE_VERSION}"
|
||||
if [[ -z "${BUNDLE_VERSION}" ]]; then
|
||||
echo "Error: Bundle failed to execute or return version."
|
||||
exit 1
|
||||
fi
|
||||
rm -rf test-bundle
|
||||
|
||||
RELEASE_ASSETS=("gemini-cli-bundle.zip")
|
||||
|
||||
# Check for and prepare macOS binaries if they exist
|
||||
for arch in arm64 x64; do
|
||||
BINARY_PATH="dist/darwin-${arch}/gemini"
|
||||
if [[ -f "$BINARY_PATH" ]]; then
|
||||
chmod +x "$BINARY_PATH"
|
||||
ZIP_NAME="gemini-darwin-${arch}-unsigned.zip"
|
||||
zip -j "$ZIP_NAME" "$BINARY_PATH"
|
||||
RELEASE_ASSETS+=("$ZIP_NAME")
|
||||
fi
|
||||
done
|
||||
|
||||
gh release create "${INPUTS_RELEASE_TAG}" \
|
||||
bundle/gemini.js \
|
||||
"${RELEASE_ASSETS[@]}" \
|
||||
--target "${STEPS_RELEASE_BRANCH_OUTPUTS_BRANCH_NAME}" \
|
||||
--title "Release ${INPUTS_RELEASE_TAG}" \
|
||||
--notes-start-tag "${INPUTS_PREVIOUS_TAG}" \
|
||||
|
||||
@@ -18,9 +18,17 @@ runs:
|
||||
env:
|
||||
JSON_INPUTS: '${{ toJSON(inputs) }}'
|
||||
run: 'echo "$JSON_INPUTS"'
|
||||
- name: 'Install system dependencies'
|
||||
if: "runner.os == 'Linux'"
|
||||
run: |
|
||||
sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq bubblewrap
|
||||
# Ubuntu 24.04+ requires this to allow bwrap to function in CI
|
||||
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true
|
||||
shell: 'bash'
|
||||
- name: 'Run Tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ inputs.gemini_api_key }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
run: |-
|
||||
echo "::group::Build"
|
||||
|
||||
@@ -98,6 +98,7 @@ runs:
|
||||
working-directory: '${{ inputs.working-directory }}'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ inputs.gemini_api_key }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
INTEGRATION_TEST_USE_INSTALLED_GEMINI: 'true'
|
||||
# We must diable CI mode here because it interferes with interactive tests.
|
||||
# See https://github.com/google-gemini/gemini-cli/issues/10517
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
const rawLabels = process.env.LABELS_OUTPUT;
|
||||
core.info(`Raw labels JSON: ${rawLabels}`);
|
||||
let parsedLabels;
|
||||
try {
|
||||
// First, try to parse the raw output as JSON.
|
||||
parsedLabels = JSON.parse(rawLabels);
|
||||
} catch (jsonError) {
|
||||
// If that fails, check for a markdown code block.
|
||||
core.warning(
|
||||
`Direct JSON parsing failed: ${jsonError.message}. Trying to extract from a markdown block.`,
|
||||
);
|
||||
const jsonMatch = rawLabels.match(/```json\s*([\s\S]*?)\s*```/);
|
||||
if (jsonMatch && jsonMatch[1]) {
|
||||
try {
|
||||
parsedLabels = JSON.parse(jsonMatch[1].trim());
|
||||
} catch (markdownError) {
|
||||
core.setFailed(
|
||||
`Failed to parse JSON even after extracting from markdown block: ${markdownError.message}\nRaw output: ${rawLabels}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// If no markdown block, try to find a raw JSON array in the output.
|
||||
// The CLI may include debug/log lines (e.g. telemetry init, YOLO mode)
|
||||
// before the actual JSON response.
|
||||
const jsonArrayMatch = rawLabels.match(
|
||||
/\[\s*\{\s*"issue_number"[\s\S]*\}\s*\]/,
|
||||
);
|
||||
if (jsonArrayMatch) {
|
||||
try {
|
||||
parsedLabels = JSON.parse(jsonArrayMatch[0]);
|
||||
} catch (extractError) {
|
||||
// It's possible the regex matched from a `[STARTUP]` log all the way to the end
|
||||
// of the JSON array. We need to be more aggressive and find the FIRST `[ { "issue_number"`
|
||||
core.warning(
|
||||
`Strict array match failed: ${extractError.message}. Attempting to clean leading noisy brackets.`,
|
||||
);
|
||||
const fallbackMatch = rawLabels.match(
|
||||
/(\[\s*\{\s*"issue_number"[\s\S]*)/,
|
||||
);
|
||||
if (fallbackMatch) {
|
||||
try {
|
||||
// We might have grabbed trailing noise too, so we find the last closing bracket
|
||||
const cleaned = fallbackMatch[0].substring(
|
||||
0,
|
||||
fallbackMatch[0].lastIndexOf(']') + 1,
|
||||
);
|
||||
parsedLabels = JSON.parse(cleaned);
|
||||
} catch (fallbackError) {
|
||||
core.setFailed(
|
||||
`Found JSON-like content but failed to parse: ${fallbackError.message}\nRaw output: ${rawLabels}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
core.setFailed(
|
||||
`Found JSON-like content but failed to parse: ${extractError.message}\nRaw output: ${rawLabels}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
core.setFailed(
|
||||
`Output is not valid JSON and does not contain extractable JSON.\nRaw output: ${rawLabels}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
core.info(`Parsed labels JSON: ${JSON.stringify(parsedLabels)}`);
|
||||
|
||||
for (const entry of parsedLabels) {
|
||||
const issueNumber = entry.issue_number;
|
||||
if (!issueNumber) {
|
||||
core.info(
|
||||
`Skipping entry with no issue number: ${JSON.stringify(entry)}`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const labelsToAdd = entry.labels_to_add || [];
|
||||
labelsToAdd.push('status/bot-triaged');
|
||||
|
||||
let labelsToRemove = entry.labels_to_remove || [];
|
||||
labelsToRemove.push('status/need-triage');
|
||||
// Deduplicate array
|
||||
labelsToRemove = [...new Set(labelsToRemove)];
|
||||
|
||||
if (labelsToAdd.length > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
labels: labelsToAdd,
|
||||
});
|
||||
|
||||
const explanation = entry.explanation ? ` - ${entry.explanation}` : '';
|
||||
core.info(
|
||||
`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}${explanation}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (labelsToRemove.length > 0) {
|
||||
for (const label of labelsToRemove) {
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
name: label,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.status !== 404) {
|
||||
core.warning(
|
||||
`Failed to remove label ${label} from #${issueNumber}: ${e.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
core.info(
|
||||
`Successfully removed labels for #${issueNumber}: ${labelsToRemove.join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (entry.explanation || entry.effort_analysis) {
|
||||
let commentBody = '';
|
||||
if (entry.explanation) {
|
||||
commentBody += entry.explanation;
|
||||
}
|
||||
if (entry.effort_analysis) {
|
||||
if (commentBody) commentBody += '\n\n';
|
||||
commentBody += `**Effort Analysis:**\n${entry.effort_analysis}`;
|
||||
}
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
body: commentBody,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
(!entry.labels_to_add || entry.labels_to_add.length === 0) &&
|
||||
(!entry.labels_to_remove || entry.labels_to_remove.length === 0)
|
||||
) {
|
||||
core.info(
|
||||
`No labels to add or remove for #${issueNumber}, leaving as is`,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
let issuesToCleanup = [];
|
||||
try {
|
||||
const fileContent = fs.readFileSync('issues_to_cleanup.json', 'utf8');
|
||||
issuesToCleanup = JSON.parse(fileContent);
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
core.info('No issues found to clean up.');
|
||||
return;
|
||||
}
|
||||
core.setFailed(`Failed to read issues_to_cleanup.json: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const issue of issuesToCleanup) {
|
||||
try {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
name: 'status/need-triage',
|
||||
});
|
||||
core.info(
|
||||
`Successfully removed status/need-triage from #${issue.number}`,
|
||||
);
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
core.info(
|
||||
`Label status/need-triage not found on #${issue.number}, skipping.`,
|
||||
);
|
||||
} else {
|
||||
core.warning(
|
||||
`Failed to remove label from #${issue.number}: ${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.info(
|
||||
`Cleaned up status/need-triage from ${issuesToCleanup.length} issues.`,
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gemini Scheduled Lifecycle Manager Script
|
||||
* @param {object} param0
|
||||
* @param {import('@octokit/rest').Octokit} param0.github
|
||||
* @param {import('@actions/github/lib/context').Context} param0.context
|
||||
* @param {import('@actions/core')} param0.core
|
||||
*/
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
const dryRun = process.env.DRY_RUN === 'true';
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
|
||||
const STALE_LABEL = 'stale';
|
||||
const NEED_INFO_LABEL = 'status/need-information';
|
||||
const EXEMPT_LABELS = [
|
||||
'pinned',
|
||||
'security',
|
||||
'🔒 maintainer only',
|
||||
'help wanted',
|
||||
'🗓️ Public Roadmap',
|
||||
];
|
||||
|
||||
const STALE_DAYS = 60;
|
||||
const CLOSE_DAYS = 14;
|
||||
const NO_RESPONSE_DAYS = 14;
|
||||
|
||||
const now = new Date();
|
||||
const staleThreshold = new Date(
|
||||
now.getTime() - STALE_DAYS * 24 * 60 * 60 * 1000,
|
||||
);
|
||||
const closeThreshold = new Date(
|
||||
now.getTime() - CLOSE_DAYS * 24 * 60 * 60 * 1000,
|
||||
);
|
||||
const noResponseThreshold = new Date(
|
||||
now.getTime() - NO_RESPONSE_DAYS * 24 * 60 * 60 * 1000,
|
||||
);
|
||||
|
||||
const maintainerCache = new Map();
|
||||
async function isMaintainer(user, association) {
|
||||
if (user?.type === 'Bot') return true;
|
||||
if (['OWNER', 'MEMBER', 'COLLABORATOR'].includes(association)) return true;
|
||||
|
||||
const username = user?.login;
|
||||
if (!username) return false;
|
||||
|
||||
if (maintainerCache.has(username)) {
|
||||
return maintainerCache.get(username);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner,
|
||||
repo,
|
||||
username,
|
||||
});
|
||||
// Permission can be admin, write, read, none.
|
||||
// Roles like 'maintain' or 'triage' often map to 'write' or 'read' in the top-level field.
|
||||
const isM =
|
||||
['admin', 'write'].includes(data.permission) ||
|
||||
['admin', 'maintain', 'write'].includes(data.role_name);
|
||||
|
||||
maintainerCache.set(username, isM);
|
||||
return isM;
|
||||
} catch (err) {
|
||||
core.warning(
|
||||
`Could not check permissions for ${username}: ${err.message}`,
|
||||
);
|
||||
maintainerCache.set(username, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function processItems(query, callback) {
|
||||
core.info(`Searching: ${query}`);
|
||||
try {
|
||||
const response = await github.rest.search.issuesAndPullRequests({
|
||||
q: query,
|
||||
per_page: 100,
|
||||
sort: 'updated',
|
||||
order: 'asc',
|
||||
});
|
||||
const items = response.data.items;
|
||||
core.info(`Found ${items.length} items (batch limited).`);
|
||||
for (const item of items) {
|
||||
try {
|
||||
await callback(item);
|
||||
} catch (err) {
|
||||
core.error(`Error processing #${item.number}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
core.error(`Search failed: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Handle No-Response (status/need-information)
|
||||
// Removal: Check issues updated in the last 48h that have the label
|
||||
const twoDaysAgo = new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000);
|
||||
await processItems(
|
||||
`repo:${owner}/${repo} is:open label:"${NEED_INFO_LABEL}" updated:>${twoDaysAgo.toISOString()}`,
|
||||
async (item) => {
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
sort: 'created',
|
||||
direction: 'desc',
|
||||
per_page: 5,
|
||||
});
|
||||
|
||||
// Check if the last comment is from a non-maintainer
|
||||
const lastComment = comments[0];
|
||||
if (
|
||||
lastComment &&
|
||||
!(await isMaintainer(lastComment.user, lastComment.author_association))
|
||||
) {
|
||||
core.info(
|
||||
`Removing ${NEED_INFO_LABEL} from #${item.number} due to contributor response.`,
|
||||
);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues
|
||||
.removeLabel({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
name: NEED_INFO_LABEL,
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Closure: Check issues with the label that haven't been updated in 14 days
|
||||
await processItems(
|
||||
`repo:${owner}/${repo} is:open label:"${NEED_INFO_LABEL}" updated:<${noResponseThreshold.toISOString()}`,
|
||||
async (item) => {
|
||||
core.info(
|
||||
`Closing #${item.number} due to no response for ${NO_RESPONSE_DAYS} days.`,
|
||||
);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
body: `This item was marked as needing more information and has not received a response in ${NO_RESPONSE_DAYS} days. Closing it for now. If you still face this problem, feel free to reopen with more details. Thank you!`,
|
||||
});
|
||||
await github.rest.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
state: 'closed',
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 2. Handle Stale Mark (60 days inactivity, no stale label)
|
||||
const exemptQuery = EXEMPT_LABELS.map((l) => `-label:"${l}"`).join(' ');
|
||||
await processItems(
|
||||
`repo:${owner}/${repo} is:open -label:"${STALE_LABEL}" ${exemptQuery} updated:<${staleThreshold.toISOString()}`,
|
||||
async (item) => {
|
||||
core.info(`Marking #${item.number} as stale.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
labels: [STALE_LABEL],
|
||||
});
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
body: `This item has been automatically marked as stale due to ${STALE_DAYS} days of inactivity. It will be closed in ${CLOSE_DAYS} days if no further activity occurs. Thank you!`,
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 3. Handle Stale Close (14 days with stale label)
|
||||
await processItems(
|
||||
`repo:${owner}/${repo} is:open label:"${STALE_LABEL}" ${exemptQuery} updated:<${closeThreshold.toISOString()}`,
|
||||
async (item) => {
|
||||
core.info(`Closing stale item #${item.number}.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
body: `This item has been closed due to ${CLOSE_DAYS} additional days of inactivity after being marked as stale. If you believe this is still relevant, feel free to comment or reopen. Thank you!`,
|
||||
});
|
||||
await github.rest.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: item.number,
|
||||
state: 'closed',
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 4. Handle PR Contribution Policy (Nudge at 7d, Close at 14d)
|
||||
const PR_NUDGE_DAYS = 7;
|
||||
const PR_CLOSE_DAYS = 14;
|
||||
const nudgeThreshold = new Date(
|
||||
now.getTime() - PR_NUDGE_DAYS * 24 * 60 * 60 * 1000,
|
||||
);
|
||||
const prCloseThreshold = new Date(
|
||||
now.getTime() - PR_CLOSE_DAYS * 24 * 60 * 60 * 1000,
|
||||
);
|
||||
|
||||
// Nudge
|
||||
await processItems(
|
||||
`repo:${owner}/${repo} is:open is:pr -label:"help wanted" -label:"🔒 maintainer only" -label:"status/pr-nudge-sent" created:${prCloseThreshold.toISOString()}..${nudgeThreshold.toISOString()}`,
|
||||
async (pr) => {
|
||||
if (await isMaintainer(pr.user, pr.author_association)) return;
|
||||
|
||||
core.info(`Nudging PR #${pr.number} for contribution policy.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
labels: ['status/pr-nudge-sent'],
|
||||
});
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
body: "Hi there! Thank you for your interest in contributing to Gemini CLI. \n\nTo ensure we maintain high code quality and focus on our prioritized roadmap, we only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'. \n\nThis PR will be closed in 7 days if it remains without that designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.",
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Close
|
||||
await processItems(
|
||||
`repo:${owner}/${repo} is:open is:pr -label:"help wanted" -label:"🔒 maintainer only" created:<${prCloseThreshold.toISOString()}`,
|
||||
async (pr) => {
|
||||
if (await isMaintainer(pr.user, pr.author_association)) return;
|
||||
|
||||
core.info(
|
||||
`Closing PR #${pr.number} per contribution policy (no 'help wanted').`,
|
||||
);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
body: "This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.",
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed',
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
const query = `
|
||||
query($owner: String!, $repo: String!) {
|
||||
repository(owner: $owner, name: $repo) {
|
||||
issues(first: 50, states: OPEN, orderBy: {field: UPDATED_AT, direction: DESC}) {
|
||||
nodes {
|
||||
id
|
||||
number
|
||||
title
|
||||
body
|
||||
issueType {
|
||||
name
|
||||
}
|
||||
labels(first: 20) {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
try {
|
||||
const result = await github.graphql(query, {
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
});
|
||||
|
||||
const issues = result.repository.issues.nodes;
|
||||
const issuesNeedingAnalysis = [];
|
||||
let syncedCount = 0;
|
||||
|
||||
for (const issue of issues) {
|
||||
if (issue.issueType === null) {
|
||||
const labelNames = issue.labels.nodes.map((l) => l.name);
|
||||
const hasBug = labelNames.includes('kind/bug');
|
||||
const hasFeature =
|
||||
labelNames.includes('kind/feature') ||
|
||||
labelNames.includes('kind/enhancement');
|
||||
|
||||
let issueTypeId = null;
|
||||
if (hasBug) {
|
||||
issueTypeId = 'IT_kwDOCaSVvs4BR7vP'; // Bug
|
||||
} else if (hasFeature) {
|
||||
issueTypeId = 'IT_kwDOCaSVvs4BR7vQ'; // Feature
|
||||
}
|
||||
|
||||
if (issueTypeId) {
|
||||
await github.graphql(
|
||||
`
|
||||
mutation($issueId: ID!, $issueTypeId: ID!) {
|
||||
updateIssue(input: {id: $issueId, issueTypeId: $issueTypeId}) {
|
||||
issue {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
{
|
||||
issueId: issue.id,
|
||||
issueTypeId: issueTypeId,
|
||||
},
|
||||
);
|
||||
core.info(`Successfully synced Issue Type for #${issue.number}`);
|
||||
syncedCount++;
|
||||
} else {
|
||||
// Needs analysis to determine kind/type
|
||||
issuesNeedingAnalysis.push({
|
||||
number: issue.number,
|
||||
title: issue.title,
|
||||
body: issue.body,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write issues needing analysis to a file so the AI can process them
|
||||
fs.writeFileSync(
|
||||
'no_type_issues.json',
|
||||
JSON.stringify(issuesNeedingAnalysis),
|
||||
);
|
||||
core.info(`Synced ${syncedCount} issues from labels.`);
|
||||
core.info(
|
||||
`Found ${issuesNeedingAnalysis.length} issues missing both type and kind label to be analyzed.`,
|
||||
);
|
||||
} catch (error) {
|
||||
core.setFailed(`Failed to sync issue types: ${error.message}`);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,132 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||
|
||||
name: 'Agent Session Drift Check'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
paths:
|
||||
- 'packages/cli/src/nonInteractiveCli.ts'
|
||||
- 'packages/cli/src/nonInteractiveCliAgentSession.ts'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check-drift:
|
||||
name: 'Check Agent Session Drift'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
permissions:
|
||||
contents: 'read'
|
||||
pull-requests: 'write'
|
||||
steps:
|
||||
- name: 'Detect drift and comment'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea' # ratchet:actions/github-script@v8
|
||||
with:
|
||||
script: |-
|
||||
// === Pair configuration — append here to cover more pairs ===
|
||||
const PAIRS = [
|
||||
{
|
||||
legacy: 'packages/cli/src/nonInteractiveCli.ts',
|
||||
session: 'packages/cli/src/nonInteractiveCliAgentSession.ts',
|
||||
label: 'non-interactive CLI',
|
||||
},
|
||||
// Future pairs can be added here. Remember to also add both
|
||||
// paths to the `paths:` filter at the top of this workflow.
|
||||
// Example:
|
||||
// {
|
||||
// legacy: 'packages/core/src/agents/local-invocation.ts',
|
||||
// session: 'packages/core/src/agents/local-session-invocation.ts',
|
||||
// label: 'local subagent invocation',
|
||||
// },
|
||||
];
|
||||
// ============================================================
|
||||
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const { owner, repo } = context.repo;
|
||||
|
||||
// Use the API to list changed files — no checkout/git diff needed.
|
||||
const files = await github.paginate(github.rest.pulls.listFiles, {
|
||||
owner,
|
||||
repo,
|
||||
pull_number: prNumber,
|
||||
per_page: 100,
|
||||
});
|
||||
const changed = new Set(files.map((f) => f.filename));
|
||||
|
||||
const warnings = [];
|
||||
for (const { legacy, session, label } of PAIRS) {
|
||||
const legacyChanged = changed.has(legacy);
|
||||
const sessionChanged = changed.has(session);
|
||||
if (legacyChanged && !sessionChanged) {
|
||||
warnings.push(
|
||||
`**${label}**: \`${legacy}\` was modified but \`${session}\` was not.`,
|
||||
);
|
||||
} else if (!legacyChanged && sessionChanged) {
|
||||
warnings.push(
|
||||
`**${label}**: \`${session}\` was modified but \`${legacy}\` was not.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const MARKER = '<!-- agent-session-drift-check -->';
|
||||
|
||||
// Look up our existing drift comment (for upsert/cleanup).
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
per_page: 100,
|
||||
});
|
||||
const existing = comments.find(
|
||||
(c) => c.user?.type === 'Bot' && c.body?.includes(MARKER),
|
||||
);
|
||||
|
||||
if (warnings.length === 0) {
|
||||
core.info('No drift detected.');
|
||||
// If drift was previously flagged and is now resolved, remove the comment.
|
||||
if (existing) {
|
||||
await github.rest.issues.deleteComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: existing.id,
|
||||
});
|
||||
core.info(`Deleted stale drift comment ${existing.id}.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const body = [
|
||||
MARKER,
|
||||
'### ⚠️ Invocation Drift Warning',
|
||||
'',
|
||||
'The following file pairs should generally be kept in sync during the AgentSession migration:',
|
||||
'',
|
||||
...warnings.map((w) => `- ${w}`),
|
||||
'',
|
||||
'If this is intentional (e.g., a bug fix specific to one implementation), you can ignore this comment.',
|
||||
'',
|
||||
'_This check will be removed once the legacy implementations are deleted._',
|
||||
].join('\n');
|
||||
|
||||
if (existing) {
|
||||
core.info(`Updating existing drift comment ${existing.id}.`);
|
||||
await github.rest.issues.updateComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: existing.id,
|
||||
body,
|
||||
});
|
||||
} else {
|
||||
core.info('Creating new drift comment.');
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
body,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
name: 'Build Unsigned Mac Binaries'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'The branch, tag, or SHA to build from.'
|
||||
required: true
|
||||
type: 'string'
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: 'bash'
|
||||
|
||||
jobs:
|
||||
build-mac:
|
||||
name: 'Build Unsigned (${{ matrix.arch }})'
|
||||
runs-on: 'macos-latest'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: ['x64', 'arm64']
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5' # ratchet:actions/checkout@v4
|
||||
with:
|
||||
ref: '${{ inputs.ref || github.ref }}'
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
architecture: '${{ matrix.arch }}'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build Binary'
|
||||
env:
|
||||
SKIP_SIGNING: 'true'
|
||||
run: 'npm run build:binary'
|
||||
|
||||
- name: 'Verify Output Exists'
|
||||
run: |
|
||||
if [ -f "dist/darwin-${{ matrix.arch }}/gemini" ]; then
|
||||
echo "Binary found at dist/darwin-${{ matrix.arch }}/gemini"
|
||||
else
|
||||
echo "Error: Binary not found in dist/darwin-${{ matrix.arch }}/"
|
||||
ls -R dist/
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: 'Upload Artifact'
|
||||
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'gemini-darwin-${{ matrix.arch }}-unsigned'
|
||||
path: 'dist/darwin-${{ matrix.arch }}/gemini'
|
||||
retention-days: 14
|
||||
@@ -167,6 +167,7 @@ jobs:
|
||||
- name: 'Run E2E tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
KEEP_OUTPUT: 'true'
|
||||
VERBOSE: 'true'
|
||||
BUILD_SANDBOX_FLAGS: '--cache-from type=gha --cache-to type=gha,mode=max'
|
||||
@@ -183,7 +184,7 @@ jobs:
|
||||
needs:
|
||||
- 'merge_queue_skipper'
|
||||
- 'parse_run_context'
|
||||
runs-on: 'macos-latest'
|
||||
runs-on: 'macos-latest-large'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && always() && (needs.merge_queue_skipper.result !='success' || needs.merge_queue_skipper.outputs.skip != 'true')
|
||||
steps:
|
||||
@@ -212,6 +213,7 @@ jobs:
|
||||
if: "${{runner.os != 'Windows'}}"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
KEEP_OUTPUT: 'true'
|
||||
SANDBOX: 'sandbox:none'
|
||||
VERBOSE: 'true'
|
||||
@@ -288,6 +290,7 @@ jobs:
|
||||
- name: 'Run E2E tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
KEEP_OUTPUT: 'true'
|
||||
SANDBOX: 'sandbox:none'
|
||||
VERBOSE: 'true'
|
||||
@@ -334,7 +337,10 @@ jobs:
|
||||
if: "${{ steps.check_evals.outputs.should_run == 'true' }}"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
GEMINI_MODEL: 'gemini-3-pro-preview'
|
||||
# Only run always passes behavioral tests.
|
||||
EVAL_SUITE_TYPE: 'behavioral'
|
||||
# Disable Vitest internal retries to avoid double-retrying;
|
||||
# custom retry logic is handled in evals/test-helper.ts
|
||||
VITEST_RETRY: 0
|
||||
|
||||
@@ -102,6 +102,12 @@ jobs:
|
||||
- name: 'Run yamllint'
|
||||
run: 'node scripts/lint.js --yamllint'
|
||||
|
||||
- name: 'Build project for typecheck'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Run typecheck'
|
||||
run: 'npm run typecheck'
|
||||
|
||||
- name: 'Run Prettier'
|
||||
run: 'node scripts/lint.js --prettier'
|
||||
|
||||
@@ -173,12 +179,13 @@ jobs:
|
||||
- name: 'Run tests and generate reports'
|
||||
env:
|
||||
NO_COLOR: true
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
run: |
|
||||
if [[ "${{ matrix.shard }}" == "cli" ]]; then
|
||||
npm run test:ci --workspace @google/gemini-cli
|
||||
npm run test:ci --workspace "@google/gemini-cli"
|
||||
else
|
||||
# Explicitly list non-cli packages to ensure they are sharded correctly
|
||||
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
|
||||
npm run test:ci --workspace "@google/gemini-cli-core" --workspace "@google/gemini-cli-a2a-server" --workspace "gemini-cli-vscode-ide-companion" --workspace "@google/gemini-cli-test-utils" --if-present -- --coverage.enabled=false
|
||||
npm run test:scripts
|
||||
fi
|
||||
|
||||
@@ -224,7 +231,7 @@ jobs:
|
||||
|
||||
test_mac:
|
||||
name: 'Test (Mac) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
|
||||
runs-on: 'macos-latest'
|
||||
runs-on: 'macos-latest-large'
|
||||
needs:
|
||||
- 'merge_queue_skipper'
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && needs.merge_queue_skipper.outputs.skip == 'false'"
|
||||
@@ -261,12 +268,13 @@ jobs:
|
||||
- name: 'Run tests and generate reports'
|
||||
env:
|
||||
NO_COLOR: true
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
run: |
|
||||
if [[ "${{ matrix.shard }}" == "cli" ]]; then
|
||||
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
|
||||
npm run test:ci --workspace "@google/gemini-cli" -- --coverage.enabled=false
|
||||
else
|
||||
# Explicitly list non-cli packages to ensure they are sharded correctly
|
||||
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
|
||||
npm run test:ci --workspace "@google/gemini-cli-core" --workspace "@google/gemini-cli-a2a-server" --workspace "gemini-cli-vscode-ide-companion" --workspace "@google/gemini-cli-test-utils" --if-present -- --coverage.enabled=false
|
||||
npm run test:scripts
|
||||
fi
|
||||
|
||||
@@ -424,16 +432,20 @@ jobs:
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
NO_COLOR: true
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
NODE_OPTIONS: '--max-old-space-size=32768 --max-semi-space-size=256'
|
||||
UV_THREADPOOL_SIZE: '32'
|
||||
NODE_ENV: 'test'
|
||||
run: |
|
||||
if ("${{ matrix.shard }}" -eq "cli") {
|
||||
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
|
||||
npm run test:ci --workspace "@google/gemini-cli" -- --coverage.enabled=false
|
||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||
} else {
|
||||
# Explicitly list non-cli packages to ensure they are sharded correctly
|
||||
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
|
||||
npm run test:ci --workspace "@google/gemini-cli-core" --workspace "@google/gemini-cli-a2a-server" --workspace "gemini-cli-vscode-ide-companion" --workspace "@google/gemini-cli-test-utils" --if-present -- --coverage.enabled=false
|
||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||
npm run test:scripts
|
||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||
}
|
||||
shell: 'pwsh'
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ jobs:
|
||||
- name: 'Run E2E tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
IS_DOCKER: "${{ matrix.sandbox == 'sandbox:docker' }}"
|
||||
KEEP_OUTPUT: 'true'
|
||||
RUNS: '${{ github.event.inputs.runs }}'
|
||||
@@ -77,7 +78,7 @@ jobs:
|
||||
|
||||
deflake_e2e_mac:
|
||||
name: 'E2E Test (macOS)'
|
||||
runs-on: 'macos-latest'
|
||||
runs-on: 'macos-latest-large'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
@@ -105,6 +106,7 @@ jobs:
|
||||
if: "runner.os != 'Windows'"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
KEEP_OUTPUT: 'true'
|
||||
RUNS: '${{ github.event.inputs.runs }}'
|
||||
SANDBOX: 'sandbox:none'
|
||||
@@ -159,6 +161,7 @@ jobs:
|
||||
- name: 'Run E2E tests'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
KEEP_OUTPUT: 'true'
|
||||
SANDBOX: 'sandbox:none'
|
||||
VERBOSE: 'true'
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
name: 'Automated Documentation Audit'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Runs every Monday at 00:00 UTC
|
||||
- cron: '0 0 * * MON'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
audit-docs:
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
contents: 'write'
|
||||
pull-requests: 'write'
|
||||
|
||||
steps:
|
||||
- name: 'Checkout repository'
|
||||
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: 'main'
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020'
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: 'Run Docs Audit with Gemini'
|
||||
id: 'run_gemini'
|
||||
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31'
|
||||
env:
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
with:
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
prompt: |
|
||||
Activate the 'docs-writer' skill.
|
||||
|
||||
**Task:** Execute the docs audit procedure, as defined in your 'docs-auditing.md' reference.
|
||||
Provide a detailed summary of the changes you make.
|
||||
|
||||
- name: 'Get current date'
|
||||
id: 'date'
|
||||
run: |
|
||||
echo "date=$(date +'%Y-%m-%d')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Create Pull Request with Audit Results'
|
||||
uses: 'peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c'
|
||||
with:
|
||||
token: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
commit-message: 'docs: weekly audit results for ${{ github.run_id }}'
|
||||
title: 'Docs audit: ${{ steps.date.outputs.date }}'
|
||||
body: |
|
||||
This PR contains the auto-generated documentation audit for the week. It includes a new `audit-results-*.md` file with findings and any direct fixes applied by the agent.
|
||||
|
||||
### Audit Summary:
|
||||
${{ steps.run_gemini.outputs.summary || 'No summary provided.' }}
|
||||
|
||||
Please review the suggestions and merge.
|
||||
|
||||
Related to #25152
|
||||
branch: 'docs-audit-${{ github.run_id }}'
|
||||
base: 'main'
|
||||
team-reviewers: 'gemini-cli-docs, gemini-cli-maintainers'
|
||||
delete-branch: true
|
||||
@@ -1,69 +0,0 @@
|
||||
name: 'Evals: PR Guidance'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'packages/core/src/**/*.ts'
|
||||
- '!**/*.test.ts'
|
||||
- '!**/*.test.tsx'
|
||||
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
contents: 'read'
|
||||
|
||||
jobs:
|
||||
provide-guidance:
|
||||
name: 'Model Steering Guidance'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Detect Steering Changes'
|
||||
id: 'detect'
|
||||
run: |
|
||||
STEERING_DETECTED=$(node scripts/changed_prompt.js --steering-only)
|
||||
echo "STEERING_DETECTED=$STEERING_DETECTED" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Analyze PR Content'
|
||||
if: "steps.detect.outputs.STEERING_DETECTED == 'true'"
|
||||
id: 'analysis'
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: |
|
||||
# Check for behavioral eval changes
|
||||
EVAL_CHANGES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep "^evals/" || true)
|
||||
if [ -z "$EVAL_CHANGES" ]; then
|
||||
echo "MISSING_EVALS=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Check if user is a maintainer (has write/admin access)
|
||||
USER_PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission')
|
||||
if [[ "$USER_PERMISSION" == "admin" || "$USER_PERMISSION" == "write" ]]; then
|
||||
echo "IS_MAINTAINER=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: 'Post Guidance Comment'
|
||||
if: "steps.detect.outputs.STEERING_DETECTED == 'true'"
|
||||
uses: 'thollander/actions-comment-pull-request@65f9e5c9a1f2cd378bd74b2e057c9736982a8e74' # ratchet:thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment-tag: 'eval-guidance-bot'
|
||||
message: |
|
||||
### 🧠 Model Steering Guidance
|
||||
|
||||
This PR modifies files that affect the model's behavior (prompts, tools, or instructions).
|
||||
|
||||
${{ steps.analysis.outputs.MISSING_EVALS == 'true' && '- ⚠️ **Consider adding Evals:** No behavioral evaluations (`evals/*.eval.ts`) were added or updated in this PR. Consider adding a test case to verify the new behavior and prevent regressions.' || '' }}
|
||||
${{ steps.analysis.outputs.IS_MAINTAINER == 'true' && '- 🚀 **Maintainer Reminder:** Please ensure that these changes do not regress results on benchmark evals before merging.' || '' }}
|
||||
|
||||
---
|
||||
*This is an automated guidance message triggered by steering logic signatures.*
|
||||
@@ -0,0 +1,209 @@
|
||||
name: 'Evals: PR Evaluation & Regression'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: ['opened', 'synchronize', 'reopened', 'ready_for_review']
|
||||
paths:
|
||||
- 'packages/core/src/prompts/**'
|
||||
- 'packages/core/src/tools/**'
|
||||
- 'packages/core/src/agents/**'
|
||||
- 'evals/**'
|
||||
- '!**/*.test.ts'
|
||||
- '!**/*.test.tsx'
|
||||
workflow_dispatch:
|
||||
|
||||
# Prevents multiple runs for the same PR simultaneously (saves tokens)
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
contents: 'read'
|
||||
actions: 'read'
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
name: 'Detect Steering Changes'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
# Security: pull_request_target allows secrets, so we must gate carefully.
|
||||
# Detection should not run code from the fork.
|
||||
if: "github.repository == 'google-gemini/gemini-cli' && github.event.pull_request.draft == false"
|
||||
outputs:
|
||||
SHOULD_RUN: '${{ steps.detect.outputs.SHOULD_RUN }}'
|
||||
STEERING_DETECTED: '${{ steps.detect.outputs.STEERING_DETECTED }}'
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
# Check out the trusted code from main for detection
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Detect Steering Changes'
|
||||
id: 'detect'
|
||||
env:
|
||||
# Use the PR's head SHA for comparison without checking it out
|
||||
PR_HEAD_SHA: '${{ github.event.pull_request.head.sha }}'
|
||||
run: |
|
||||
# Fetch the fork's PR branch for analysis
|
||||
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-head
|
||||
|
||||
# Run the trusted script from main
|
||||
SHOULD_RUN=$(node scripts/changed_prompt.js)
|
||||
STEERING_DETECTED=$(node scripts/changed_prompt.js --steering-only)
|
||||
echo "SHOULD_RUN=$SHOULD_RUN" >> "$GITHUB_OUTPUT"
|
||||
echo "STEERING_DETECTED=$STEERING_DETECTED" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Notify Approval Required'
|
||||
if: "steps.detect.outputs.SHOULD_RUN == 'true'"
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: |
|
||||
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
COMMENT_BODY="### 🛑 Action Required: Evaluation Approval
|
||||
|
||||
Steering changes have been detected in this PR. To prevent regressions, a maintainer must approve the evaluation run before this PR can be merged.
|
||||
|
||||
**Maintainers:**
|
||||
1. Go to the [**Workflow Run Summary**]($RUN_URL).
|
||||
2. Click the yellow **'Review deployments'** button.
|
||||
3. Select the **'eval-gate'** environment and click **'Approve'**.
|
||||
|
||||
Once approved, the evaluation results will be posted here automatically.
|
||||
|
||||
<!-- eval-approval-notification -->"
|
||||
|
||||
# Check if comment already exists to avoid spamming
|
||||
COMMENT_ID=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains("<!-- eval-approval-notification -->")) | .url' | grep -oE "[0-9]+$" | head -n 1)
|
||||
|
||||
if [ -z "$COMMENT_ID" ]; then
|
||||
gh pr comment ${{ github.event.pull_request.number }} --body "$COMMENT_BODY"
|
||||
else
|
||||
echo "Updating existing notification comment $COMMENT_ID..."
|
||||
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -F body="$COMMENT_BODY"
|
||||
fi
|
||||
|
||||
pr-evaluation:
|
||||
name: 'Evaluate Steering & Regressions'
|
||||
needs: 'detect-changes'
|
||||
if: "needs.detect-changes.outputs.SHOULD_RUN == 'true'"
|
||||
# Manual approval gate via environment
|
||||
environment: 'eval-gate'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
env:
|
||||
# CENTRALIZED MODEL LIST
|
||||
MODEL_LIST: 'gemini-3-flash-preview'
|
||||
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
# Check out the fork's PR code for the actual evaluation
|
||||
# This only runs AFTER manual approval
|
||||
ref: '${{ github.event.pull_request.head.sha }}'
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Remove Approval Notification'
|
||||
# Run even if other steps fail, to ensure we clean up the "Action Required" message
|
||||
if: 'always()'
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
PR_NUMBER: '${{ github.event.pull_request.number }}'
|
||||
run: |
|
||||
echo "Debug: PR_NUMBER is '$PR_NUMBER'"
|
||||
# Search for the notification comment by its hidden tag
|
||||
COMMENT_ID=$(gh pr view "$PR_NUMBER" --json comments --jq '.comments[] | select(.body | contains("<!-- eval-approval-notification -->")) | .url' | grep -oE "[0-9]+$" | head -n 1)
|
||||
if [ -n "$COMMENT_ID" ]; then
|
||||
echo "Removing notification comment $COMMENT_ID now that run is approved..."
|
||||
gh api -X DELETE "repos/${{ github.repository }}/issues/comments/$COMMENT_ID"
|
||||
fi
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Analyze PR Content (Guidance)'
|
||||
if: "needs.detect-changes.outputs.STEERING_DETECTED == 'true'"
|
||||
id: 'analysis'
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: |
|
||||
# Check for behavioral eval changes
|
||||
EVAL_CHANGES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep "^evals/" || true)
|
||||
if [ -z "$EVAL_CHANGES" ]; then
|
||||
echo "MISSING_EVALS=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Check if user is a maintainer
|
||||
USER_PERMISSION=$(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission --jq '.permission')
|
||||
if [[ "$USER_PERMISSION" == "admin" || "$USER_PERMISSION" == "write" ]]; then
|
||||
echo "IS_MAINTAINER=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: 'Execute Regression Check'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
MODEL_LIST: '${{ env.MODEL_LIST }}'
|
||||
run: |
|
||||
# Run the regression check loop. The script saves the report to a file.
|
||||
node scripts/run_eval_regression.js
|
||||
|
||||
# Use the generated report file if it exists
|
||||
if [[ -f eval_regression_report.md ]]; then
|
||||
echo "REPORT_FILE=eval_regression_report.md" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: 'Post or Update PR Comment'
|
||||
if: "always() && (needs.detect-changes.outputs.STEERING_DETECTED == 'true' || env.REPORT_FILE != '')"
|
||||
env:
|
||||
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: |
|
||||
# 1. Build the full comment body
|
||||
{
|
||||
if [[ -f eval_regression_report.md ]]; then
|
||||
cat eval_regression_report.md
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ "${{ needs.detect-changes.outputs.STEERING_DETECTED }}" == "true" ]]; then
|
||||
echo "### 🧠 Model Steering Guidance"
|
||||
echo ""
|
||||
echo "This PR modifies files that affect the model's behavior (prompts, tools, or instructions)."
|
||||
echo ""
|
||||
|
||||
if [[ "${{ steps.analysis.outputs.MISSING_EVALS }}" == "true" ]]; then
|
||||
echo "- ⚠️ **Consider adding Evals:** No behavioral evaluations (\`evals/*.eval.ts\`) were added or updated in this PR. Consider [adding a test case](https://github.com/google-gemini/gemini-cli/blob/main/evals/README.md#creating-an-evaluation) to verify the new behavior and prevent regressions."
|
||||
fi
|
||||
|
||||
if [[ "${{ steps.analysis.outputs.IS_MAINTAINER }}" == "true" ]]; then
|
||||
echo "- 🚀 **Maintainer Reminder:** Please ensure that these changes do not regress results on benchmark evals before merging."
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "*This is an automated guidance message triggered by steering logic signatures.*"
|
||||
echo "<!-- eval-pr-report -->"
|
||||
} > full_comment.md
|
||||
|
||||
# 2. Find if a comment with our unique tag already exists
|
||||
# We extract the numeric ID from the URL to ensure compatibility with the REST API
|
||||
COMMENT_ID=$(gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains("<!-- eval-pr-report -->")) | .url' | grep -oE "[0-9]+$" | head -n 1)
|
||||
|
||||
# 3. Update or Create the comment
|
||||
if [ -n "$COMMENT_ID" ]; then
|
||||
echo "Updating existing comment $COMMENT_ID via API..."
|
||||
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$COMMENT_ID" -F body=@full_comment.md
|
||||
else
|
||||
echo "Creating new PR comment..."
|
||||
gh pr comment ${{ github.event.pull_request.number }} --body-file full_comment.md
|
||||
fi
|
||||
@@ -5,10 +5,18 @@ on:
|
||||
- cron: '0 1 * * *' # Runs at 1 AM every day
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_all:
|
||||
description: 'Run all evaluations (including usually passing)'
|
||||
type: 'boolean'
|
||||
default: true
|
||||
suite_type:
|
||||
description: 'Suite type to run'
|
||||
type: 'choice'
|
||||
options:
|
||||
- 'behavioral'
|
||||
- 'component-level'
|
||||
- 'hero-scenario'
|
||||
default: 'behavioral'
|
||||
suite_name:
|
||||
description: 'Specific suite name to run'
|
||||
required: false
|
||||
type: 'string'
|
||||
test_name_pattern:
|
||||
description: 'Test name pattern or file name'
|
||||
required: false
|
||||
@@ -58,8 +66,11 @@ jobs:
|
||||
continue-on-error: true
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
GEMINI_MODEL: '${{ matrix.model }}'
|
||||
RUN_EVALS: "${{ github.event.inputs.run_all != 'false' }}"
|
||||
RUN_EVALS: 'true'
|
||||
EVAL_SUITE_TYPE: "${{ github.event.inputs.suite_type || 'behavioral' }}"
|
||||
EVAL_SUITE_NAME: '${{ github.event.inputs.suite_name }}'
|
||||
TEST_NAME_PATTERN: '${{ github.event.inputs.test_name_pattern }}'
|
||||
# Disable Vitest internal retries to avoid double-retrying;
|
||||
# custom retry logic is handled in evals/test-helper.ts
|
||||
|
||||
@@ -129,19 +129,29 @@ jobs:
|
||||
core.info(`Found ${labelNames.length} labels: ${labelNames.join(', ')}`);
|
||||
return labelNames;
|
||||
|
||||
- name: 'Prepare Issue Data'
|
||||
id: 'prepare_issue_data'
|
||||
env:
|
||||
ISSUE_TITLE: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.title || github.event.issue.title }}
|
||||
ISSUE_BODY: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.body || github.event.issue.body }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "Title: ${ISSUE_TITLE}" > issue_context.md
|
||||
echo "Body:" >> issue_context.md
|
||||
echo "${ISSUE_BODY}" >> issue_context.md
|
||||
|
||||
- name: 'Run Gemini Issue Analysis'
|
||||
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
|
||||
ISSUE_TITLE: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.title || github.event.issue.title }}
|
||||
ISSUE_BODY: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && steps.get_issue_data.outputs.body || github.event.issue.body }}
|
||||
ISSUE_NUMBER: >-
|
||||
${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.issue_number || inputs.issue_number) || github.event.issue.number }}
|
||||
REPOSITORY: '${{ github.repository }}'
|
||||
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: 'true'
|
||||
with:
|
||||
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
|
||||
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
|
||||
@@ -158,7 +168,8 @@ jobs:
|
||||
"target": "gcp"
|
||||
},
|
||||
"coreTools": [
|
||||
"run_shell_command(echo)"
|
||||
"run_shell_command(echo)",
|
||||
"read_file"
|
||||
]
|
||||
}
|
||||
prompt: |-
|
||||
@@ -167,7 +178,7 @@ jobs:
|
||||
You are an issue triage assistant. Your role is to analyze a GitHub issue and determine the single most appropriate area/ label based on the definitions provided.
|
||||
|
||||
## Steps
|
||||
1. Review the issue title and body: ${{ env.ISSUE_TITLE }} and ${{ env.ISSUE_BODY }}.
|
||||
1. Use the read_file tool to read the file "issue_context.md" which contains the issue title and body.
|
||||
2. Review the available labels: ${{ env.AVAILABLE_LABELS }}.
|
||||
3. Select exactly one area/ label that best matches the issue based on Reference 1: Area Definitions.
|
||||
4. Fallback Logic:
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
name: '🧠 Gemini CLI Bot: Brain'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # Every 24 hours
|
||||
issue_comment:
|
||||
types: ['created']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_interactive:
|
||||
description: 'Run interactive flow (requires issue_number)'
|
||||
type: 'boolean'
|
||||
default: false
|
||||
issue_number:
|
||||
description: 'Issue/PR number to simulate context from'
|
||||
type: 'string'
|
||||
required: false
|
||||
comment_id:
|
||||
description: 'Specific comment ID to simulate'
|
||||
type: 'string'
|
||||
required: false
|
||||
clear_memory:
|
||||
description: 'Clear memory (drops learnings from previous runs)'
|
||||
type: 'boolean'
|
||||
default: false
|
||||
enable_prs:
|
||||
description: 'Enable PRs (automatically promote changes to PRs)'
|
||||
type: 'boolean'
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number || github.event.inputs.issue_number || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
reasoning:
|
||||
name: 'Brain (Reasoning Layer)'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: |
|
||||
github.repository == 'google-gemini/gemini-cli' && (
|
||||
github.event_name == 'schedule' ||
|
||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.run_interactive != 'true') ||
|
||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.run_interactive == 'true') ||
|
||||
(github.event_name == 'issue_comment' && github.event.comment.user.login != 'gemini-cli[bot]' && contains(github.event.comment.body, '@gemini-cli') && contains(fromJSON('["COLLABORATOR", "MEMBER", "OWNER"]'), github.event.comment.author_association)) ||
|
||||
(github.event_name == 'pull_request_review_comment' && github.event.comment.user.login != 'gemini-cli[bot]' && contains(github.event.comment.body, '@gemini-cli') && contains(fromJSON('["COLLABORATOR", "MEMBER", "OWNER"]'), github.event.comment.author_association))
|
||||
)
|
||||
# The reasoning phase is strictly readonly.
|
||||
permissions:
|
||||
contents: 'read'
|
||||
issues: 'read'
|
||||
pull-requests: 'read'
|
||||
actions: 'read'
|
||||
env:
|
||||
GEMINI_CLI_TRUST_WORKSPACE: 'true'
|
||||
steps:
|
||||
- name: 'Determine Checkout Ref'
|
||||
id: 'determine_ref'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
ISSUE_NUMBER: '${{ github.event.issue.number || github.event.pull_request.number || github.event.inputs.issue_number }}'
|
||||
run: |
|
||||
REF="${{ github.ref }}"
|
||||
if [ -n "$ISSUE_NUMBER" ]; then
|
||||
PR_HEAD=$(gh pr view "$ISSUE_NUMBER" --repo "${{ github.repository }}" --json headRefName --jq .headRefName 2>/dev/null || echo "")
|
||||
if [ -n "$PR_HEAD" ]; then
|
||||
REF="$PR_HEAD"
|
||||
fi
|
||||
fi
|
||||
echo "ref=$REF" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ steps.determine_ref.outputs.ref }}'
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Setup Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build Gemini CLI'
|
||||
run: 'npm run bundle'
|
||||
|
||||
- name: 'Download Previous State'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: |
|
||||
if [ "${{ github.event.inputs.clear_memory }}" = "true" ]; then
|
||||
echo "Memory clear requested. Skipping previous state download."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Find the last successful run of this workflow
|
||||
LAST_RUN_ID=$(gh run list --workflow "${{ github.workflow }}" --status success --limit 1 --json databaseId --jq '.[0].databaseId')
|
||||
|
||||
if [ -n "$LAST_RUN_ID" ]; then
|
||||
echo "Found previous successful run: $LAST_RUN_ID"
|
||||
|
||||
# Download brain memory to a temp dir so we can selectively restore only persistent state
|
||||
mkdir -p .temp_brain_data
|
||||
gh run download "$LAST_RUN_ID" -n brain-data -D .temp_brain_data || echo "brain-data not found"
|
||||
|
||||
# Restore only persistent memory files
|
||||
cp .temp_brain_data/tools/gemini-cli-bot/lessons-learned.md tools/gemini-cli-bot/lessons-learned.md 2>/dev/null || true
|
||||
mkdir -p tools/gemini-cli-bot/history/
|
||||
cp .temp_brain_data/tools/gemini-cli-bot/history/*.csv tools/gemini-cli-bot/history/ 2>/dev/null || true
|
||||
rm -rf .temp_brain_data
|
||||
else
|
||||
echo "No previous successful run found."
|
||||
fi
|
||||
|
||||
- name: 'Collect Current Metrics'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: 'npx tsx tools/gemini-cli-bot/metrics/index.ts'
|
||||
|
||||
- name: 'Run Brain Phases'
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
GEMINI_MODEL: 'gemini-3-flash-preview'
|
||||
ENABLE_PRS: "${{ github.event.inputs.enable_prs || 'false' }}"
|
||||
TRIGGER_ISSUE_NUMBER: '${{ github.event.issue.number || github.event.inputs.issue_number }}'
|
||||
TRIGGER_COMMENT_ID: '${{ github.event.comment.id || github.event.inputs.comment_id }}'
|
||||
run: |
|
||||
PROMPT_PATH="tools/gemini-cli-bot/brain/metrics.md"
|
||||
if [ "${{ github.event_name }}" = "issue_comment" ] || [ "${{ github.event.inputs.run_interactive }}" = "true" ]; then
|
||||
PROMPT_PATH="tools/gemini-cli-bot/brain/interactive.md"
|
||||
export ENABLE_PRS="true"
|
||||
fi
|
||||
|
||||
touch trigger_context.md
|
||||
if [ -n "$TRIGGER_ISSUE_NUMBER" ]; then
|
||||
echo "<untrusted_context>" > trigger_context.md
|
||||
echo "# Interactive Trigger Context" >> trigger_context.md
|
||||
echo "You were invoked by a user in issue/PR #$TRIGGER_ISSUE_NUMBER." >> trigger_context.md
|
||||
|
||||
if [ -n "$TRIGGER_COMMENT_ID" ]; then
|
||||
echo "## User Comment" >> trigger_context.md
|
||||
gh api "repos/${{ github.repository }}/issues/comments/$TRIGGER_COMMENT_ID" -q '.body' >> trigger_context.md 2>/dev/null || gh api "repos/${{ github.repository }}/pulls/comments/$TRIGGER_COMMENT_ID" -q '.body' >> trigger_context.md
|
||||
echo "" >> trigger_context.md
|
||||
fi
|
||||
|
||||
echo "## Issue/PR Context" >> trigger_context.md
|
||||
gh issue view "$TRIGGER_ISSUE_NUMBER" >> trigger_context.md 2>/dev/null || gh pr view "$TRIGGER_ISSUE_NUMBER" >> trigger_context.md
|
||||
echo "</untrusted_context>" >> trigger_context.md
|
||||
fi
|
||||
|
||||
cat trigger_context.md "$PROMPT_PATH" tools/gemini-cli-bot/brain/common.md > combined_prompt.md
|
||||
|
||||
node bundle/gemini.js --policy tools/gemini-cli-bot/ci-policy.toml -p "$(cat combined_prompt.md)"
|
||||
|
||||
if [ -n "$TRIGGER_ISSUE_NUMBER" ] && [ ! -s "issue-comment.md" ] && [ ! -s "pr-comment.md" ]; then
|
||||
echo "Agent failed to respond. Generating fallback error message."
|
||||
echo "⚠️ **Gemini CLI Bot failed to generate a response.**" > "issue-comment.md"
|
||||
echo "" >> "issue-comment.md"
|
||||
echo "I encountered an error or failed to generate a complete response to your request. You can check the [GitHub Actions Run Log](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details on what went wrong." >> "issue-comment.md"
|
||||
fi
|
||||
|
||||
- name: 'Run Critique Phase'
|
||||
if: "${{ github.event.inputs.enable_prs == 'true' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event.inputs.run_interactive == 'true' }}"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
GEMINI_MODEL: 'gemini-3-flash-preview'
|
||||
run: |
|
||||
if git diff --staged --quiet; then
|
||||
echo "No changes staged. Skipping critique."
|
||||
echo "[APPROVED]" > critique_result.txt
|
||||
else
|
||||
node bundle/gemini.js --policy tools/gemini-cli-bot/ci-policy.toml -p "$(cat tools/gemini-cli-bot/brain/critique.md)" 2>&1 | tee critique_output.log
|
||||
|
||||
if [ "${PIPESTATUS[0]}" -eq 0 ] && grep -q "\[APPROVED\]" critique_output.log && ! grep -q "\[REJECTED\]" critique_output.log; then
|
||||
echo "[APPROVED]" > critique_result.txt
|
||||
else
|
||||
echo "Critique failed, rejected, or did not explicitly approve changes. Skipping PR creation."
|
||||
echo "[REJECTED]" > critique_result.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: 'Generate Patch'
|
||||
if: "${{ github.event.inputs.enable_prs == 'true' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event.inputs.run_interactive == 'true' }}"
|
||||
run: |
|
||||
touch bot-changes.patch
|
||||
touch pr-description.md
|
||||
if [ -f critique_result.txt ] && grep -q "\[APPROVED\]" critique_result.txt && ! grep -q "\[REJECTED\]" critique_result.txt; then
|
||||
git diff --staged > bot-changes.patch
|
||||
else
|
||||
echo "Critique did not approve. Skipping patch generation."
|
||||
fi
|
||||
|
||||
- name: 'Archive Brain Data'
|
||||
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'brain-data'
|
||||
path: |
|
||||
tools/gemini-cli-bot/lessons-learned.md
|
||||
tools/gemini-cli-bot/history/*.csv
|
||||
bot-changes.patch
|
||||
pr-description.md
|
||||
branch-name.txt
|
||||
pr-comment.md
|
||||
pr-number.txt
|
||||
issue-comment.md
|
||||
retention-days: 90
|
||||
|
||||
publish:
|
||||
name: 'Publish Artifacts (Archive Layer)'
|
||||
needs: 'reasoning'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
# The publish phase is for archiving artifacts and optionally creating PRs.
|
||||
permissions:
|
||||
contents: 'write'
|
||||
pull-requests: 'write'
|
||||
actions: 'write'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token 🔑'
|
||||
id: 'generate_token'
|
||||
if: "${{ github.event.inputs.enable_prs == 'true' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event.inputs.run_interactive == 'true' }}"
|
||||
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 }}'
|
||||
owner: '${{ github.repository_owner }}'
|
||||
repositories: '${{ github.event.repository.name }}'
|
||||
permission-contents: 'write'
|
||||
permission-pull-requests: 'write'
|
||||
permission-issues: 'write'
|
||||
|
||||
- name: 'Determine Checkout Ref'
|
||||
id: 'determine_ref'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
ISSUE_NUMBER: '${{ github.event.issue.number || github.event.pull_request.number || github.event.inputs.issue_number }}'
|
||||
run: |
|
||||
REF="main"
|
||||
if [ -n "$ISSUE_NUMBER" ]; then
|
||||
PR_HEAD=$(gh pr view "$ISSUE_NUMBER" --repo "${{ github.repository }}" --json headRefName --jq .headRefName 2>/dev/null || echo "")
|
||||
if [ -n "$PR_HEAD" ]; then
|
||||
REF="$PR_HEAD"
|
||||
fi
|
||||
fi
|
||||
echo "ref=$REF" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
ref: '${{ steps.determine_ref.outputs.ref }}'
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Download Brain Data'
|
||||
uses: 'actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093' # ratchet:actions/download-artifact@v4
|
||||
with:
|
||||
name: 'brain-data'
|
||||
path: '${{ runner.temp }}/brain-data/'
|
||||
|
||||
- name: 'Create or Update PR'
|
||||
if: "${{ github.event.inputs.enable_prs == 'true' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event.inputs.run_interactive == 'true' }}"
|
||||
env:
|
||||
GH_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
||||
FALLBACK_PAT: '${{ secrets.GEMINI_CLI_ROBOT_GITHUB_PAT }}'
|
||||
run: |
|
||||
if [ -s "${{ runner.temp }}/brain-data/bot-changes.patch" ]; then
|
||||
git config user.name "gemini-cli[bot]"
|
||||
git config user.email "gemini-cli[bot]@users.noreply.github.com"
|
||||
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
|
||||
|
||||
BRANCH_NAME="bot/productivity-updates-$(date +'%Y%m%d%H%M%S')-${{ github.run_id }}"
|
||||
if [ -f "${{ runner.temp }}/brain-data/branch-name.txt" ]; then
|
||||
BRANCH_NAME=$(cat "${{ runner.temp }}/brain-data/branch-name.txt")
|
||||
fi
|
||||
|
||||
if [[ ! "$BRANCH_NAME" =~ ^bot/ ]]; then
|
||||
echo "Error: Branch name '$BRANCH_NAME' does not start with 'bot/'. Safety abort."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git checkout -B "$BRANCH_NAME"
|
||||
git apply "${{ runner.temp }}/brain-data/bot-changes.patch"
|
||||
git add .
|
||||
|
||||
if [ -s "${{ runner.temp }}/brain-data/pr-description.md" ]; then
|
||||
git commit -F "${{ runner.temp }}/brain-data/pr-description.md"
|
||||
else
|
||||
git commit -m "🤖 Gemini Bot Productivity Optimizations"
|
||||
fi
|
||||
|
||||
PR_TITLE="🤖 Gemini Bot Productivity Optimizations"
|
||||
if [ -s "${{ runner.temp }}/brain-data/pr-description.md" ]; then
|
||||
PR_TITLE=$(head -n 1 "${{ runner.temp }}/brain-data/pr-description.md")
|
||||
fi
|
||||
|
||||
if ! git push origin "$BRANCH_NAME" --force; then
|
||||
echo "Push failed. Retrying with FALLBACK_PAT..."
|
||||
export GH_TOKEN="$FALLBACK_PAT"
|
||||
git remote set-url origin "https://x-access-token:${FALLBACK_PAT}@github.com/${{ github.repository }}.git"
|
||||
git push origin "$BRANCH_NAME" --force
|
||||
fi
|
||||
|
||||
if ! gh pr view "$BRANCH_NAME" > /dev/null 2>&1; then
|
||||
gh pr create --draft --title "$PR_TITLE" --body-file "${{ runner.temp }}/brain-data/pr-description.md" --head "$BRANCH_NAME" --base main || \
|
||||
gh pr create --draft --title "🤖 Gemini Bot Productivity Optimizations" --body "Automated changes generated by Gemini CLI Bot." --head "$BRANCH_NAME" --base main
|
||||
else
|
||||
PR_STATE=$(gh pr view "$BRANCH_NAME" --json state --jq .state)
|
||||
if [ "$PR_STATE" = "CLOSED" ]; then
|
||||
NEW_BRANCH_NAME="${BRANCH_NAME}-retry-${{ github.run_id }}"
|
||||
git checkout -b "$NEW_BRANCH_NAME"
|
||||
git push origin "$NEW_BRANCH_NAME" --force
|
||||
gh pr create --draft --title "$PR_TITLE" --body-file "${{ runner.temp }}/brain-data/pr-description.md" --head "$NEW_BRANCH_NAME" --base main || \
|
||||
gh pr create --draft --title "🤖 Gemini Bot Productivity Optimizations" --body "Automated changes generated by Gemini CLI Bot." --head "$NEW_BRANCH_NAME" --base main
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: 'Post PR/Issue Comment'
|
||||
env:
|
||||
GH_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
||||
TRIGGER_ISSUE_NUMBER: '${{ github.event.issue.number || github.event.inputs.issue_number }}'
|
||||
run: |
|
||||
if [ -s "${{ runner.temp }}/brain-data/issue-comment.md" ] && [ -n "$TRIGGER_ISSUE_NUMBER" ]; then
|
||||
echo "Posting comment to triggering issue #$TRIGGER_ISSUE_NUMBER"
|
||||
# Use REST API (gh api) instead of GraphQL (gh issue comment) to ensure robot identity
|
||||
# while avoiding potential GraphQL-specific authorization hurdles with PATs.
|
||||
gh api "repos/${{ github.repository }}/issues/$TRIGGER_ISSUE_NUMBER/comments" -F body=@"${{ runner.temp }}/brain-data/issue-comment.md"
|
||||
fi
|
||||
|
||||
if [ -s "${{ runner.temp }}/brain-data/pr-comment.md" ] && [ -f "${{ runner.temp }}/brain-data/pr-number.txt" ]; then
|
||||
PR_NUM=$(cat "${{ runner.temp }}/brain-data/pr-number.txt")
|
||||
|
||||
# Using GitHub App, so author check is no longer valid against gemini-cli-robot
|
||||
# Skipping author validation here to let the app post.
|
||||
|
||||
# Use REST API (gh api) for consistency and robot identity
|
||||
gh api "repos/${{ github.repository }}/issues/$PR_NUM/comments" -F body=@"${{ runner.temp }}/brain-data/pr-comment.md"
|
||||
fi
|
||||
@@ -0,0 +1,48 @@
|
||||
name: '🔄 Gemini CLI Bot: Pulse'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '*/30 * * * *' # Every 30 minutes
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-${{ github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: 'write'
|
||||
issues: 'write'
|
||||
pull-requests: 'write'
|
||||
|
||||
jobs:
|
||||
pulse:
|
||||
name: 'Pulse (Reflex Layer)'
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 'Setup Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Run Reflex Processes'
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
run: |
|
||||
if [ -d "tools/gemini-cli-bot/reflexes/scripts" ] && [ "$(ls -A tools/gemini-cli-bot/reflexes/scripts)" ]; then
|
||||
for script in tools/gemini-cli-bot/reflexes/scripts/*.ts; do
|
||||
echo "Running reflex script: $script"
|
||||
npx tsx "$script"
|
||||
done
|
||||
else
|
||||
echo "No reflex scripts found."
|
||||
fi
|
||||
@@ -0,0 +1,45 @@
|
||||
name: '🔄 Gemini Scheduled Lifecycle Manager'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *' # Once a day
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Run in dry-run mode (no changes applied)'
|
||||
required: false
|
||||
default: false
|
||||
type: 'boolean'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
issues: 'write'
|
||||
pull-requests: 'write'
|
||||
|
||||
jobs:
|
||||
manage-lifecycle:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet:actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
|
||||
- name: 'Checkout repository'
|
||||
uses: 'actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # ratchet:actions/checkout@v4
|
||||
|
||||
- name: 'Lifecycle Management'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
env:
|
||||
DRY_RUN: '${{ inputs.dry_run }}'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |
|
||||
const script = require('./.github/scripts/gemini-lifecycle-manager.cjs');
|
||||
await script({github, context, core});
|
||||
@@ -23,7 +23,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
triage-issues:
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 60
|
||||
if: |-
|
||||
${{ github.repository == 'google-gemini/gemini-cli' }}
|
||||
runs-on: 'ubuntu-latest'
|
||||
@@ -47,10 +47,20 @@ jobs:
|
||||
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 "$ISSUE_EVENT" | jq -c '[{number: .number, title: .title, body: .body}]' > issues_to_triage.json
|
||||
echo "has_issues=true" >> "${GITHUB_OUTPUT}"
|
||||
echo "✅ Found issue #${{ github.event.issue.number }} from event to triage! 🎯"
|
||||
|
||||
- name: 'Sync Issue Types'
|
||||
if: |-
|
||||
${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |-
|
||||
const syncIssueTypes = require('./.github/scripts/sync-issue-types.cjs');
|
||||
await syncIssueTypes({ github, context, core });
|
||||
|
||||
- name: 'Find untriaged issues'
|
||||
if: |-
|
||||
${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
|
||||
@@ -62,26 +72,48 @@ jobs:
|
||||
set -euo pipefail
|
||||
|
||||
echo '🔍 Finding issues missing area labels...'
|
||||
NO_AREA_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:area/core -label:area/agent -label:area/enterprise -label:area/non-interactive -label:area/security -label:area/platform -label:area/extensions -label:area/documentation -label:area/unknown' --limit 100 --json number,title,body)"
|
||||
gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:status/bot-triaged -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 50 --json number,title,body > no_area_issues.json
|
||||
|
||||
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)"
|
||||
gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:status/bot-triaged -label:kind/bug -label:kind/enhancement -label:kind/customer-issue -label:kind/question' --limit 50 --json number,title,body > no_kind_issues.json
|
||||
|
||||
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)"
|
||||
gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:status/bot-triaged -label:priority/p0 -label:priority/p1 -label:priority/p2 -label:priority/p3 -label:priority/unknown' --limit 50 --json number,title,body > no_priority_issues.json
|
||||
|
||||
echo '📏 Finding issues missing effort labels...'
|
||||
gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue -label:status/bot-triaged -label:effort/small -label:effort/medium -label:effort/large label:area/core,area/extensions,area/site,area/non-interactive' --limit 20 --json number,title,body > no_effort_issues.json
|
||||
|
||||
echo '🔄 Merging and deduplicating issues...'
|
||||
ISSUES="$(echo "${NO_AREA_ISSUES}" "${NO_KIND_ISSUES}" "${NO_PRIORITY_ISSUES}" | jq -c -s 'add | unique_by(.number)')"
|
||||
jq -c -s 'add | unique_by(.number)' no_area_issues.json no_kind_issues.json no_priority_issues.json no_effort_issues.json no_type_issues.json > issues_to_triage.json
|
||||
|
||||
echo '📝 Setting output for GitHub Actions...'
|
||||
echo "issues_to_triage=${ISSUES}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
ISSUE_COUNT="$(echo "${ISSUES}" | jq 'length')"
|
||||
ISSUE_COUNT="$(jq 'length' issues_to_triage.json)"
|
||||
if [ "$ISSUE_COUNT" -gt 0 ]; then
|
||||
echo "has_issues=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "has_issues=false" >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
echo "✅ Found ${ISSUE_COUNT} unique issues to triage! 🎯"
|
||||
|
||||
- name: 'Create Gemini CLI Experiments Override'
|
||||
if: |-
|
||||
steps.get_issue_from_event.outputs.has_issues == 'true' || steps.find_issues.outputs.has_issues == 'true'
|
||||
run: |
|
||||
cat << 'EOF' > gemini_exp.json
|
||||
{
|
||||
"flags": [
|
||||
{
|
||||
"flagId": 45750526,
|
||||
"boolValue": false
|
||||
}
|
||||
],
|
||||
"experimentIds": []
|
||||
}
|
||||
EOF
|
||||
|
||||
- name: 'Get Repository Labels'
|
||||
id: 'get_labels'
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
@@ -99,15 +131,16 @@ jobs:
|
||||
|
||||
- name: 'Run Gemini Issue Analysis'
|
||||
if: |-
|
||||
(steps.get_issue_from_event.outputs.issues_to_triage != '' && steps.get_issue_from_event.outputs.issues_to_triage != '[]') ||
|
||||
(steps.find_issues.outputs.issues_to_triage != '' && steps.find_issues.outputs.issues_to_triage != '[]')
|
||||
steps.get_issue_from_event.outputs.has_issues == 'true' || steps.find_issues.outputs.has_issues == 'true'
|
||||
uses: 'google-github-actions/run-gemini-cli@a3bf79042542528e91937b3a3a6fbc4967ee3c31' # ratchet:google-github-actions/run-gemini-cli@v0
|
||||
id: 'gemini_issue_analysis'
|
||||
env:
|
||||
GITHUB_TOKEN: '' # Do not pass any auth token here since this runs on untrusted inputs
|
||||
ISSUES_TO_TRIAGE: '${{ steps.get_issue_from_event.outputs.issues_to_triage || steps.find_issues.outputs.issues_to_triage }}'
|
||||
REPOSITORY: '${{ github.repository }}'
|
||||
AVAILABLE_LABELS: '${{ steps.get_labels.outputs.available_labels }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: 'true'
|
||||
GEMINI_EXP: 'gemini_exp.json'
|
||||
GEMINI_STRICT_TELEMETRY_LIMITS: 'true'
|
||||
with:
|
||||
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
|
||||
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
|
||||
@@ -120,7 +153,10 @@ jobs:
|
||||
{
|
||||
"maxSessionTurns": 25,
|
||||
"coreTools": [
|
||||
"run_shell_command(echo)"
|
||||
"run_shell_command(echo)",
|
||||
"grep_search",
|
||||
"glob",
|
||||
"read_file"
|
||||
],
|
||||
"telemetry": {
|
||||
"enabled": true,
|
||||
@@ -136,26 +172,29 @@ jobs:
|
||||
|
||||
## Steps
|
||||
|
||||
1. You are only able to use the echo command. Review the available labels in the environment variable: "${AVAILABLE_LABELS}".
|
||||
2. Check environment variable for issues to triage: $ISSUES_TO_TRIAGE (JSON array of issues)
|
||||
3. Review the issue title, body and any comments provided in the environment variables.
|
||||
4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/* and priority/*.
|
||||
1. You are only able to use the echo and read_file commands. Review the available labels in the environment variable: "${AVAILABLE_LABELS}".
|
||||
2. Use the read_file tool to read the file "issues_to_triage.json" which contains the JSON array of issues to triage.
|
||||
3. Review the issue title, body and any comments provided in the JSON file.
|
||||
4. Identify the most relevant labels from the existing labels, specifically focusing on area/*, kind/*, priority/*, and effort/*.
|
||||
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 the issue already has an effort/ label, do not change it.
|
||||
- If the issue is missing an effort/ label AND its area is area/core, area/extensions, area/site, or area/non-interactive, you must evaluate the architectural complexity to determine the effort level. You MUST NOT guess the root cause. You MUST actively use your codebase search tools (grep_search and glob) to search for keywords from the issue and explore the codebase. You must identify the specific files and components involved before deciding the effort. Do NOT evaluate or assign an effort/ label to issues in any other areas (such as area/agent).
|
||||
- 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. 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:
|
||||
and the labels to add and remove, along with an explanation. If you assigned an effort/ label, you MUST also include an effort_analysis field. This effort_analysis must be highly detailed, technical, and empirical. It MUST NOT contain vague guesses (e.g., avoid words like "likely points to" or "possibly"). You must explicitly cite the specific file paths and architectural mechanisms you discovered using your search tools, explain the root cause, and then explicitly state how that complexity maps to the chosen effort level guidelines. For example:
|
||||
```
|
||||
[
|
||||
{
|
||||
"issue_number": 123,
|
||||
"labels_to_add": ["area/core", "kind/bug", "priority/p2"],
|
||||
"labels_to_add": ["area/core", "kind/bug", "priority/p2", "effort/small"],
|
||||
"labels_to_remove": ["status/need-triage"],
|
||||
"explanation": "This issue is a UI bug that needs to be addressed with medium priority."
|
||||
"explanation": "This issue is a UI bug that needs to be addressed with medium priority.",
|
||||
"effort_analysis": "The `vscode-ide-companion` extension indiscriminately tracks active text editors via `vscode.window.onDidChangeActiveTextEditor` in `open-files-manager.ts`. When a user opens `.vscode/settings.json`, its content is sent to the CLI's context. The fix is highly localized to the VS Code companion extension's event listener. It involves adding a simple conditional check to exclude specific configuration files from the active editor tracking logic, which is a trivial logic adjustment with a clear root cause."
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -179,6 +218,23 @@ jobs:
|
||||
- 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 (Effort):
|
||||
effort/small (1 day or less):
|
||||
- Trivial Logic & Config: Schema updates (Zod), feature flag toggles, adding missing fields to package.json or settings.json.
|
||||
- UI/Aesthetic Adjustments: Fixing minor layout bugs in Ink components (e.g., adding flexShrink, correcting padding in a single Box), text color changes.
|
||||
- Documentation & Strings: Typos, log message updates, CLI argument descriptions.
|
||||
- Localized Bug Fixes: Single-file logic errors, straightforward promise rejections (e.g., wrapping a known failure in a try/catch), simple regex or string parsing fixes.
|
||||
effort/medium (2-3 days):
|
||||
- React/Ink State Management: Debugging useState/useEffect/useReducer bugs, component lifecycle issues (memory leaks in the UI), terminal redraw flickering, or state synchronization between the CLI's internal input buffer and the interactive React components.
|
||||
- Asynchronous Flow & Integration: Resolving complex Promise chains, ERR_STREAM_PREMATURE_CLOSE, debugging IDE companion extensions (VS Code, Android Studio) or resolving hanging HTTP requests/IPC between the CLI and external plugins, timeouts in non-interactive/ACP modes.
|
||||
- Tooling & Output Parsers: Modifying how tools parse streaming stdout/stderr buffers, adding new built-in tools that don't require native bindings.
|
||||
- Cross-Component Refactors: Changes that span across packages/cli and packages/core to pass new data models or telemetry state.
|
||||
effort/large (3+ days):
|
||||
- Platform-Specific Complexities (PTY/Signals): Any issue involving node-pty, child_process.spawn, OS-level shell behavior (Windows vs Linux vs macOS), pseudo-terminal exhaustion (ENXIO), raw mode terminal desyncs, or POSIX signal forwarding (SIGINT/SIGTERM).
|
||||
- Core Architecture & Protocols: Refactoring the Scheduler, Agent-to-Agent (A2A) protocol implementation, low-level MCP (Model Context Protocol) transport mechanisms.
|
||||
- Performance & Memory: Diagnosing massive disk/memory leaks, severe boot time regressions, high-throughput streaming optimizations (e.g., voice streaming pipelines).
|
||||
Note: Any bug that is described as intermittent, flickering, difficult to reproduce, platform-specific, or requiring cross-environment setups (e.g., involving the VS Code IDE companion, GCA plugin, or Android Studio) MUST NOT be rated as effort/small because of the increased overhead of testing and reproducing.
|
||||
|
||||
Categorization Guidelines (Priority):
|
||||
P0 - Urgent Blocking Issues:
|
||||
- DO NOT APPLY THIS LABEL AUTOMATICALLY. Use status/manual-triage instead.
|
||||
@@ -227,53 +283,37 @@ jobs:
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |-
|
||||
const rawLabels = process.env.LABELS_OUTPUT;
|
||||
core.info(`Raw labels JSON: ${rawLabels}`);
|
||||
let parsedLabels;
|
||||
try {
|
||||
const jsonMatch = rawLabels.match(/```json\s*([\s\S]*?)\s*```/);
|
||||
if (!jsonMatch || !jsonMatch[1]) {
|
||||
throw new Error("Could not find a ```json ... ``` block in the output.");
|
||||
}
|
||||
const jsonString = jsonMatch[1].trim();
|
||||
parsedLabels = JSON.parse(jsonString);
|
||||
core.info(`Parsed labels JSON: ${JSON.stringify(parsedLabels)}`);
|
||||
} catch (err) {
|
||||
core.setFailed(`Failed to parse labels JSON from Gemini output: ${err.message}\nRaw output: ${rawLabels}`);
|
||||
return;
|
||||
}
|
||||
const applyLabels = require('./.github/scripts/apply-issue-labels.cjs');
|
||||
await applyLabels({ github, context, core });
|
||||
|
||||
for (const entry of parsedLabels) {
|
||||
const issueNumber = entry.issue_number;
|
||||
if (!issueNumber) {
|
||||
core.info(`Skipping entry with no issue number: ${JSON.stringify(entry)}`);
|
||||
continue;
|
||||
}
|
||||
- name: 'Sync Issue Types (Post-Analysis)'
|
||||
if: |-
|
||||
always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |-
|
||||
const syncIssueTypes = require('./.github/scripts/sync-issue-types.cjs');
|
||||
await syncIssueTypes({ github, context, core });
|
||||
|
||||
const labelsToAdd = entry.labels_to_add || [];
|
||||
labelsToAdd.push('status/bot-triaged');
|
||||
- name: 'Find Triaged Issues to Clean Up'
|
||||
if: |-
|
||||
always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ steps.generate_token.outputs.token }}'
|
||||
GITHUB_REPOSITORY: '${{ github.repository }}'
|
||||
run: |-
|
||||
set -euo pipefail
|
||||
echo '🧹 Finding issues that have both bot-triaged and need-triage labels...'
|
||||
gh issue list --repo "${GITHUB_REPOSITORY}" \
|
||||
--search 'is:open is:issue label:status/bot-triaged label:status/need-triage' --limit 50 --json number > issues_to_cleanup.json
|
||||
|
||||
if (labelsToAdd.length > 0) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
labels: labelsToAdd
|
||||
});
|
||||
const explanation = entry.explanation ? ` - ${entry.explanation}` : '';
|
||||
core.info(`Successfully added labels for #${issueNumber}: ${labelsToAdd.join(', ')}${explanation}`);
|
||||
}
|
||||
|
||||
if (entry.explanation) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
body: entry.explanation,
|
||||
});
|
||||
}
|
||||
|
||||
if ((!entry.labels_to_add || entry.labels_to_add.length === 0) && (!entry.labels_to_remove || entry.labels_to_remove.length === 0)) {
|
||||
core.info(`No labels to add or remove for #${issueNumber}, leaving as is`);
|
||||
}
|
||||
}
|
||||
- name: 'Clean Up Triage Labels'
|
||||
if: |-
|
||||
always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|
||||
uses: 'actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |-
|
||||
const cleanupLabels = require('./.github/scripts/cleanup-triage-labels.cjs');
|
||||
await cleanupLabels({ github, context, core });
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
name: '🔒 Gemini Scheduled Stale Issue Closer'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # Every Sunday at midnight UTC
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Run in dry-run mode (no changes applied)'
|
||||
required: false
|
||||
default: false
|
||||
type: 'boolean'
|
||||
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: 'bash'
|
||||
|
||||
jobs:
|
||||
close-stale-issues:
|
||||
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@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet:actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
permission-issues: 'write'
|
||||
|
||||
- name: 'Process Stale Issues'
|
||||
uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # ratchet:actions/github-script@v7
|
||||
env:
|
||||
DRY_RUN: '${{ inputs.dry_run }}'
|
||||
with:
|
||||
github-token: '${{ steps.generate_token.outputs.token }}'
|
||||
script: |
|
||||
const dryRun = process.env.DRY_RUN === 'true';
|
||||
if (dryRun) {
|
||||
core.info('DRY RUN MODE ENABLED: No changes will be applied.');
|
||||
}
|
||||
const batchLabel = 'Stale';
|
||||
|
||||
const threeMonthsAgo = new Date();
|
||||
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
|
||||
|
||||
const tenDaysAgo = new Date();
|
||||
tenDaysAgo.setDate(tenDaysAgo.getDate() - 10);
|
||||
|
||||
core.info(`Cutoff date for creation: ${threeMonthsAgo.toISOString()}`);
|
||||
core.info(`Cutoff date for updates: ${tenDaysAgo.toISOString()}`);
|
||||
|
||||
const query = `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open created:<${threeMonthsAgo.toISOString()}`;
|
||||
core.info(`Searching with query: ${query}`);
|
||||
|
||||
const itemsToCheck = await github.paginate(github.rest.search.issuesAndPullRequests, {
|
||||
q: query,
|
||||
sort: 'created',
|
||||
order: 'asc',
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
core.info(`Found ${itemsToCheck.length} open issues to check.`);
|
||||
|
||||
let processedCount = 0;
|
||||
|
||||
for (const issue of itemsToCheck) {
|
||||
const createdAt = new Date(issue.created_at);
|
||||
const updatedAt = new Date(issue.updated_at);
|
||||
const reactionCount = issue.reactions.total_count;
|
||||
|
||||
// Basic thresholds
|
||||
if (reactionCount >= 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if it has a maintainer, help wanted, or Public Roadmap label
|
||||
const rawLabels = issue.labels.map((l) => l.name);
|
||||
const lowercaseLabels = rawLabels.map((l) => l.toLowerCase());
|
||||
if (
|
||||
lowercaseLabels.some((l) => l.includes('maintainer')) ||
|
||||
lowercaseLabels.includes('help wanted') ||
|
||||
rawLabels.includes('🗓️ Public Roadmap')
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let isStale = updatedAt < tenDaysAgo;
|
||||
|
||||
// If apparently active, check if it's only bot activity
|
||||
if (!isStale) {
|
||||
try {
|
||||
const comments = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
per_page: 100,
|
||||
sort: 'created',
|
||||
direction: 'desc'
|
||||
});
|
||||
|
||||
const lastHumanComment = comments.data.find(comment => comment.user.type !== 'Bot');
|
||||
if (lastHumanComment) {
|
||||
isStale = new Date(lastHumanComment.created_at) < tenDaysAgo;
|
||||
} else {
|
||||
// No human comments. Check if creator is human.
|
||||
if (issue.user.type !== 'Bot') {
|
||||
isStale = createdAt < tenDaysAgo;
|
||||
} else {
|
||||
isStale = true; // Bot created, only bot comments
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
core.warning(`Failed to fetch comments for issue #${issue.number}: ${error.message}`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isStale) {
|
||||
processedCount++;
|
||||
const message = `Closing stale issue #${issue.number}: "${issue.title}" (${issue.html_url})`;
|
||||
core.info(message);
|
||||
|
||||
if (!dryRun) {
|
||||
// Add label
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
labels: [batchLabel]
|
||||
});
|
||||
|
||||
// Add comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: 'Hello! As part of our effort to keep our backlog manageable and focus on the most active issues, we are tidying up older reports.\n\nIt looks like this issue hasn\'t been active for a while, so we are closing it for now. However, if you are still experiencing this bug on the latest stable build, please feel free to comment on this issue or create a new one with updated details.\n\nThank you for your contribution!'
|
||||
});
|
||||
|
||||
// Close issue
|
||||
await github.rest.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
state: 'closed',
|
||||
state_reason: 'not_planned'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.info(`\nTotal issues processed: ${processedCount}`);
|
||||
@@ -1,254 +0,0 @@
|
||||
name: 'Gemini Scheduled Stale PR Closer'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # Every day at 2 AM UTC
|
||||
pull_request:
|
||||
types: ['opened', 'edited']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Run in dry-run mode'
|
||||
required: false
|
||||
default: false
|
||||
type: 'boolean'
|
||||
|
||||
jobs:
|
||||
close-stale-prs:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
issues: 'write'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
env:
|
||||
APP_ID: '${{ secrets.APP_ID }}'
|
||||
if: |-
|
||||
${{ env.APP_ID != '' }}
|
||||
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet:actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: '${{ secrets.APP_ID }}'
|
||||
private-key: '${{ secrets.PRIVATE_KEY }}'
|
||||
|
||||
- name: 'Process Stale PRs'
|
||||
uses: 'actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b' # ratchet: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 fourteenDaysAgo = new Date();
|
||||
fourteenDaysAgo.setDate(fourteenDaysAgo.getDate() - 14);
|
||||
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) {
|
||||
// Silently skip if permissions are insufficient; we will rely on author_association
|
||||
core.debug(`Skipped team fetch for ${team_slug}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const isMaintainer = async (login, assoc) => {
|
||||
// Reliably identify maintainers using authorAssociation (provided by GitHub)
|
||||
// and organization membership (if available).
|
||||
const isTeamMember = maintainerLogins.has(login.toLowerCase());
|
||||
const isRepoMaintainer = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(assoc);
|
||||
|
||||
if (isTeamMember || isRepoMaintainer) return true;
|
||||
|
||||
// Fallback: Check if user belongs to the 'google' or 'googlers' orgs (requires permission)
|
||||
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) {
|
||||
// Gracefully ignore failures here
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// 2. Fetch all open PRs
|
||||
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]');
|
||||
if (maintainerPr || isBot) continue;
|
||||
|
||||
// Helper: Fetch labels and linked issues via GraphQL
|
||||
const prDetailsQuery = `query($owner:String!, $repo:String!, $number:Int!) {
|
||||
repository(owner:$owner, name:$repo) {
|
||||
pullRequest(number:$number) {
|
||||
closingIssuesReferences(first: 10) {
|
||||
nodes {
|
||||
number
|
||||
labels(first: 20) {
|
||||
nodes { name }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
let linkedIssues = [];
|
||||
try {
|
||||
const res = await github.graphql(prDetailsQuery, {
|
||||
owner: context.repo.owner, repo: context.repo.repo, number: pr.number
|
||||
});
|
||||
linkedIssues = res.repository.pullRequest.closingIssuesReferences.nodes;
|
||||
} catch (e) {
|
||||
core.warning(`GraphQL fetch failed for PR #${pr.number}: ${e.message}`);
|
||||
}
|
||||
|
||||
// Check for mentions in body as fallback (regex)
|
||||
const body = pr.body || '';
|
||||
const mentionRegex = /(?:#|https:\/\/github\.com\/[^\/]+\/[^\/]+\/issues\/)(\d+)/i;
|
||||
const matches = body.match(mentionRegex);
|
||||
if (matches && linkedIssues.length === 0) {
|
||||
const issueNumber = parseInt(matches[1]);
|
||||
try {
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber
|
||||
});
|
||||
linkedIssues = [{ number: issueNumber, labels: { nodes: issue.labels.map(l => ({ name: l.name })) } }];
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// 3. Enforcement Logic
|
||||
const prLabels = pr.labels.map(l => l.name.toLowerCase());
|
||||
const hasHelpWanted = prLabels.includes('help wanted') ||
|
||||
linkedIssues.some(issue => issue.labels.nodes.some(l => l.name.toLowerCase() === 'help wanted'));
|
||||
|
||||
const hasMaintainerOnly = prLabels.includes('🔒 maintainer only') ||
|
||||
linkedIssues.some(issue => issue.labels.nodes.some(l => l.name.toLowerCase() === '🔒 maintainer only'));
|
||||
|
||||
const hasLinkedIssue = linkedIssues.length > 0;
|
||||
|
||||
// Closure Policy: No help-wanted label = Close after 14 days
|
||||
if (pr.state === 'open' && !hasHelpWanted && !hasMaintainerOnly) {
|
||||
const prCreatedAt = new Date(pr.created_at);
|
||||
|
||||
// We give a 14-day grace period for non-help-wanted PRs to be manually reviewed/labeled by an EM
|
||||
if (prCreatedAt > fourteenDaysAgo) {
|
||||
core.info(`PR #${pr.number} is new and lacks 'help wanted'. Giving 14-day grace period for EM review.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
core.info(`PR #${pr.number} is older than 14 days and lacks 'help wanted' association. Closing.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: "Hi there! Thank you for your interest in contributing to Gemini CLI. \n\nTo ensure we maintain high code quality and focus on our prioritized roadmap, we have updated our contribution policy (see [Discussion #17383](https://github.com/google-gemini/gemini-cli/discussions/17383)). \n\n**We only *guarantee* review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'.** All other community pull requests are subject to closure after 14 days if they do not align with our current focus areas. For this reason, we strongly recommend that contributors only submit pull requests against issues explicitly labeled as **'help-wanted'**. \n\nThis pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding and for being part of our community!"
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed'
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Also check for linked issue even if it has help wanted (redundant but safe)
|
||||
if (pr.state === 'open' && !hasLinkedIssue) {
|
||||
// Already covered by hasHelpWanted check above, but good for future-proofing
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4. Staleness Check (Scheduled only)
|
||||
if (pr.state === 'open' && context.eventName !== 'pull_request') {
|
||||
// Skip PRs that were created less than 30 days ago - they cannot be stale yet
|
||||
const prCreatedAt = new Date(pr.created_at);
|
||||
if (prCreatedAt > thirtyDaysAgo) continue;
|
||||
|
||||
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) {}
|
||||
|
||||
if (lastActivity < thirtyDaysAgo) {
|
||||
const labels = pr.labels.map(l => l.name.toLowerCase());
|
||||
const isProtected = labels.includes('help wanted') || labels.includes('🔒 maintainer only');
|
||||
if (isProtected) {
|
||||
core.info(`PR #${pr.number} is stale but has a protected label. Skipping closure.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
core.info(`PR #${pr.number} is stale (no maintainer activity for 30+ days). Closing.`);
|
||||
if (!dryRun) {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: "Hi there! Thank you for your contribution. To keep our backlog manageable, we are closing pull requests that haven't seen maintainer activity for 30 days. If you're still working on this, please let us know!"
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
name: 'Memory Tests: Nightly'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # Runs at 2 AM every day
|
||||
workflow_dispatch: # Allow manual trigger
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
jobs:
|
||||
memory-test:
|
||||
name: 'Run Memory Usage Tests'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Run Memory Tests'
|
||||
run: 'npm run test:memory'
|
||||
@@ -1,33 +0,0 @@
|
||||
name: 'No Response'
|
||||
|
||||
# Run as a daily cron at 1:45 AM
|
||||
on:
|
||||
schedule:
|
||||
- cron: '45 1 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
no-response:
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: |-
|
||||
${{ github.repository == 'google-gemini/gemini-cli' }}
|
||||
permissions:
|
||||
issues: 'write'
|
||||
pull-requests: 'write'
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-no-response'
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: 'actions/stale@5bef64f19d7facfb25b37b414482c7164d639639' # ratchet:actions/stale@v9
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
days-before-stale: -1
|
||||
days-before-close: 14
|
||||
stale-issue-label: 'status/need-information'
|
||||
close-issue-message: >-
|
||||
This issue was marked as needing more information and has not received a response in 14 days.
|
||||
Closing it for now. If you still face this problem, feel free to reopen with more details. Thank you!
|
||||
stale-pr-label: 'status/need-information'
|
||||
close-pr-message: >-
|
||||
This pull request was marked as needing more information and has had no updates in 14 days.
|
||||
Closing it for now. You are welcome to reopen with the required info. Thanks for contributing!
|
||||
@@ -0,0 +1,33 @@
|
||||
name: 'Performance Tests: Nightly'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *' # Runs at 3 AM every day
|
||||
workflow_dispatch: # Allow manual trigger
|
||||
|
||||
permissions:
|
||||
contents: 'read'
|
||||
|
||||
jobs:
|
||||
perf-test:
|
||||
name: 'Run Performance Usage Tests'
|
||||
runs-on: 'gemini-cli-ubuntu-16-core'
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
steps:
|
||||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
|
||||
|
||||
- name: 'Set up Node.js'
|
||||
uses: 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' # ratchet:actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Build project'
|
||||
run: 'npm run build'
|
||||
|
||||
- name: 'Run Performance Tests'
|
||||
run: 'npm run test:perf'
|
||||
@@ -1,133 +0,0 @@
|
||||
name: '🏷️ PR Contribution Guidelines Notifier'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- 'opened'
|
||||
|
||||
jobs:
|
||||
notify-process-change:
|
||||
runs-on: 'ubuntu-latest'
|
||||
if: |-
|
||||
github.repository == 'google-gemini/gemini-cli' || github.repository == 'google-gemini/maintainers-gemini-cli'
|
||||
permissions:
|
||||
pull-requests: 'write'
|
||||
steps:
|
||||
- name: 'Generate GitHub App Token'
|
||||
id: 'generate_token'
|
||||
env:
|
||||
APP_ID: '${{ secrets.APP_ID }}'
|
||||
if: |-
|
||||
${{ env.APP_ID != '' }}
|
||||
uses: 'actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349' # ratchet: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
|
||||
});
|
||||
@@ -46,8 +46,15 @@ on:
|
||||
default: 'prod'
|
||||
|
||||
jobs:
|
||||
build-mac:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
uses: './.github/workflows/build-unsigned-mac-binaries.yml'
|
||||
with:
|
||||
ref: '${{ github.event.inputs.ref }}'
|
||||
|
||||
release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
needs: ['build-mac']
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
@@ -83,6 +90,11 @@ jobs:
|
||||
working-directory: './release'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Download macOS Binaries'
|
||||
uses: './.github/actions/download-mac-binaries'
|
||||
with:
|
||||
path: 'release/dist'
|
||||
|
||||
- name: 'Prepare Release Info'
|
||||
id: 'release_info'
|
||||
working-directory: './release'
|
||||
|
||||
@@ -30,8 +30,15 @@ on:
|
||||
default: 'prod'
|
||||
|
||||
jobs:
|
||||
build-mac:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
uses: './.github/workflows/build-unsigned-mac-binaries.yml'
|
||||
with:
|
||||
ref: '${{ github.event.inputs.ref }}'
|
||||
|
||||
release:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
needs: ['build-mac']
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
runs-on: 'ubuntu-latest'
|
||||
permissions:
|
||||
@@ -62,6 +69,11 @@ jobs:
|
||||
working-directory: './release'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Download macOS Binaries'
|
||||
uses: './.github/actions/download-mac-binaries'
|
||||
with:
|
||||
path: 'release/dist'
|
||||
|
||||
- name: 'Print Inputs'
|
||||
shell: 'bash'
|
||||
env:
|
||||
|
||||
@@ -70,6 +70,8 @@ jobs:
|
||||
- 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
|
||||
env:
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
with:
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
prompt: |
|
||||
|
||||
@@ -197,9 +197,15 @@ jobs:
|
||||
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
|
||||
working-directory: './release'
|
||||
|
||||
build-mac:
|
||||
if: "github.repository == 'google-gemini/gemini-cli'"
|
||||
uses: './.github/workflows/build-unsigned-mac-binaries.yml'
|
||||
with:
|
||||
ref: '${{ github.event.inputs.ref }}'
|
||||
|
||||
publish-preview:
|
||||
name: 'Publish preview'
|
||||
needs: ['calculate-versions', 'test']
|
||||
needs: ['calculate-versions', 'test', 'build-mac']
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
@@ -229,6 +235,11 @@ jobs:
|
||||
working-directory: './release'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Download macOS Binaries'
|
||||
uses: './.github/actions/download-mac-binaries'
|
||||
with:
|
||||
path: 'release/dist'
|
||||
|
||||
- name: 'Publish Release'
|
||||
uses: './.github/actions/publish-release'
|
||||
with:
|
||||
@@ -266,7 +277,7 @@ jobs:
|
||||
|
||||
publish-stable:
|
||||
name: 'Publish stable'
|
||||
needs: ['calculate-versions', 'test', 'publish-preview']
|
||||
needs: ['calculate-versions', 'test', 'publish-preview', 'build-mac']
|
||||
runs-on: 'ubuntu-latest'
|
||||
environment: "${{ github.event.inputs.environment || 'prod' }}"
|
||||
permissions:
|
||||
@@ -296,6 +307,11 @@ jobs:
|
||||
working-directory: './release'
|
||||
run: 'npm ci'
|
||||
|
||||
- name: 'Download macOS Binaries'
|
||||
uses: './.github/actions/download-mac-binaries'
|
||||
with:
|
||||
path: 'release/dist'
|
||||
|
||||
- name: 'Publish Release'
|
||||
uses: './.github/actions/publish-release'
|
||||
with:
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
name: 'Mark stale issues and pull requests'
|
||||
|
||||
# Run as a daily cron at 1:30 AM
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
runner:
|
||||
- 'ubuntu-latest' # GitHub-hosted
|
||||
runs-on: '${{ matrix.runner }}'
|
||||
if: |-
|
||||
${{ github.repository == 'google-gemini/gemini-cli' }}
|
||||
permissions:
|
||||
issues: 'write'
|
||||
pull-requests: 'write'
|
||||
concurrency:
|
||||
group: '${{ github.workflow }}-stale'
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- uses: 'actions/stale@5bef64f19d7facfb25b37b414482c7164d639639' # ratchet:actions/stale@v9
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
stale-issue-message: >-
|
||||
This issue has been automatically marked as stale due to 60 days of inactivity.
|
||||
It will be closed in 14 days if no further activity occurs.
|
||||
stale-pr-message: >-
|
||||
This pull request has been automatically marked as stale due to 60 days of inactivity.
|
||||
It will be closed in 14 days if no further activity occurs.
|
||||
close-issue-message: >-
|
||||
This issue has been closed due to 14 additional days of inactivity after being marked as stale.
|
||||
If you believe this is still relevant, feel free to comment or reopen the issue. Thank you!
|
||||
close-pr-message: >-
|
||||
This pull request has been closed due to 14 additional days of inactivity after being marked as stale.
|
||||
If this is still relevant, you are welcome to reopen or leave a comment. Thanks for contributing!
|
||||
days-before-stale: 60
|
||||
days-before-close: 14
|
||||
exempt-issue-labels: 'pinned,security,🔒 maintainer only,help wanted,🗓️ Public Roadmap'
|
||||
exempt-pr-labels: 'pinned,security,🔒 maintainer only,help wanted,🗓️ Public Roadmap'
|
||||
@@ -141,6 +141,7 @@ jobs:
|
||||
if: "github.event_name != 'pull_request'"
|
||||
env:
|
||||
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
|
||||
GEMINI_CLI_TRUST_WORKSPACE: true
|
||||
run: |
|
||||
echo "Running integration tests with binary..."
|
||||
if [[ "${{ matrix.os }}" == 'windows-latest' ]]; then
|
||||
|
||||
@@ -48,6 +48,7 @@ packages/cli/src/generated/
|
||||
packages/core/src/generated/
|
||||
packages/devtools/src/_client-assets.ts
|
||||
.integration-tests/
|
||||
.perf-tests/
|
||||
packages/vscode-ide-companion/*.vsix
|
||||
packages/cli/download-ripgrep*/
|
||||
|
||||
@@ -64,3 +65,6 @@ gemini-debug.log
|
||||
evals/logs/
|
||||
|
||||
temp_agents/
|
||||
|
||||
# conductor extension and planning directories
|
||||
conductor/
|
||||
|
||||
@@ -22,3 +22,4 @@ Thumbs.db
|
||||
.pytest_cache
|
||||
**/SKILL.md
|
||||
packages/sdk/test-data/*.json
|
||||
*.mdx
|
||||
|
||||
+11
-6
@@ -110,7 +110,9 @@ 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.
|
||||
time and that only
|
||||
[issues labeled "help wanted"](https://github.com/google-gemini/gemini-cli/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22)
|
||||
may be self-assigned.
|
||||
|
||||
### Pull request guidelines
|
||||
|
||||
@@ -346,9 +348,11 @@ npm run lint
|
||||
|
||||
- Please adhere to the coding style, patterns, and conventions used throughout
|
||||
the existing codebase.
|
||||
- Consult [GEMINI.md](../GEMINI.md) (typically found in the project root) for
|
||||
specific instructions related to AI-assisted development, including
|
||||
conventions for React, comments, and Git usage.
|
||||
- Consult
|
||||
[GEMINI.md](https://github.com/google-gemini/gemini-cli/blob/main/GEMINI.md)
|
||||
(typically found in the project root) for specific instructions related to
|
||||
AI-assisted development, including conventions for React, comments, and Git
|
||||
usage.
|
||||
- **Imports:** Pay special attention to import paths. The project uses ESLint to
|
||||
enforce restrictions on relative imports between packages.
|
||||
|
||||
@@ -505,8 +509,9 @@ code.
|
||||
|
||||
### Documentation structure
|
||||
|
||||
Our documentation is organized using [sidebar.json](/docs/sidebar.json) as the
|
||||
table of contents. When adding new documentation:
|
||||
Our documentation is organized using
|
||||
[sidebar.json](https://github.com/google-gemini/gemini-cli/blob/main/docs/sidebar.json)
|
||||
as the table of contents. When adding new documentation:
|
||||
|
||||
1. Create your markdown file **in the appropriate directory** under `/docs`.
|
||||
2. Add an entry to `sidebar.json` in the relevant section.
|
||||
|
||||
+44
-3
@@ -1,3 +1,44 @@
|
||||
# ---- Stage 1: Builder ----
|
||||
FROM docker.io/library/node:20-slim AS builder
|
||||
|
||||
# Install git (needed by generate-git-commit-info.js script)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends git \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy only package.json files first for better layer caching
|
||||
# Dependencies only re-install when package files change, not source files
|
||||
COPY package*.json ./
|
||||
COPY packages/cli/package*.json ./packages/cli/
|
||||
COPY packages/core/package*.json ./packages/core/
|
||||
COPY packages/vscode-ide-companion/package*.json ./packages/vscode-ide-companion/
|
||||
COPY packages/vscode-ide-companion/scripts/ ./packages/vscode-ide-companion/scripts/
|
||||
COPY packages/devtools/package*.json ./packages/devtools/
|
||||
COPY packages/sdk/package*.json ./packages/sdk/
|
||||
COPY packages/test-utils/package*.json ./packages/test-utils/
|
||||
COPY packages/a2a-server/package*.json ./packages/a2a-server/
|
||||
|
||||
# Use npm ci for consistent, reliable builds (respects package-lock.json)
|
||||
RUN HUSKY=0 npm ci --ignore-scripts
|
||||
|
||||
# Now copy the rest of the source (after install for better caching)
|
||||
COPY packages/ ./packages/
|
||||
COPY tsconfig*.json ./
|
||||
COPY eslint.config.js ./
|
||||
COPY scripts/ ./scripts/
|
||||
COPY esbuild.config.js ./
|
||||
|
||||
# Pass git commit hash as build arg instead of copying entire .git directory
|
||||
ARG GIT_COMMIT=unknown
|
||||
ENV GIT_COMMIT=$GIT_COMMIT
|
||||
|
||||
# Build and pack artifacts
|
||||
RUN HUSKY=0 npm run build && \
|
||||
npm pack -w packages/core --pack-destination packages/core/dist/ && \
|
||||
npm pack -w packages/cli --pack-destination packages/cli/dist/
|
||||
|
||||
# ---- Stage 2: Runtime ----
|
||||
FROM docker.io/library/node:20-slim
|
||||
|
||||
ARG SANDBOX_NAME="gemini-cli-sandbox"
|
||||
@@ -40,8 +81,8 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin
|
||||
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
|
||||
COPY --chown=node:node packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz
|
||||
COPY --chown=node:node packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz
|
||||
RUN npm install -g /tmp/gemini-core.tgz \
|
||||
&& npm install -g /tmp/gemini-cli.tgz \
|
||||
&& node -e "const fs=require('node:fs'); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json','utf8')); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json','utf8'));" \
|
||||
@@ -50,4 +91,4 @@ RUN npm install -g /tmp/gemini-core.tgz \
|
||||
&& rm -f /tmp/gemini-{cli,core}.tgz
|
||||
|
||||
# default entrypoint when none specified
|
||||
CMD ["gemini"]
|
||||
ENTRYPOINT ["/usr/local/share/npm-global/bin/gemini"]
|
||||
@@ -44,6 +44,13 @@ powerful tool for developers.
|
||||
- **Test Commands:**
|
||||
- **Unit (All):** `npm run test`
|
||||
- **Integration (E2E):** `npm run test:e2e`
|
||||
- > **NOTE**: Please run the memory and perf tests locally **only if** you are
|
||||
> implementing changes related to those test areas. Otherwise skip these
|
||||
> tests locally and rely on CI to run them on nightly builds.
|
||||
- **Memory (Nightly):** `npm run test:memory` (Runs memory regression tests
|
||||
against baselines. Excluded from `preflight`, run nightly.)
|
||||
- **Performance (Nightly):** `npm run test:perf` (Runs CPU performance
|
||||
regression tests against baselines. Excluded from `preflight`, run nightly.)
|
||||
- **Workspace-Specific:** `npm test -w <pkg> -- <path>` (Note: `<path>` must
|
||||
be relative to the workspace root, e.g.,
|
||||
`-w @google/gemini-cli-core -- src/routing/modelRouterService.test.ts`)
|
||||
@@ -71,6 +78,19 @@ powerful tool for developers.
|
||||
- **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.
|
||||
- **Configuration Lifecycle Tracing:** When modifying state, credentials, or
|
||||
network options, thoroughly trace the data traversal pipeline from initial
|
||||
environment capture down to the target consumer option layer, ensuring
|
||||
rigorous validation and sanitization to prevent downstream conditional mapping
|
||||
from undermining intended states or introducing vulnerabilities.
|
||||
- **Architectural Consistency:** Centralize shared configuration logic (such as
|
||||
auth inference) inside common configuration modules rather than isolating
|
||||
inference to specific entry points, ensuring absolute uniformity across
|
||||
interactive CLI usage, background jobs, and programmatic SDK embeddings.
|
||||
- **Partner & Client Invariants:** Treat established integration profiles and
|
||||
edge-case workarounds as stable contracts. Ensure new validation routes fall
|
||||
back to or preserve legacy mapping where safe to prevent behavioral
|
||||
regressions for active sidecars while allowing for critical security fixes.
|
||||
|
||||
## Testing Conventions
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Learn all about Gemini CLI in our [documentation](https://geminicli.com/docs/).
|
||||
## 📦 Installation
|
||||
|
||||
See
|
||||
[Gemini CLI installation, execution, and releases](./docs/get-started/installation.md)
|
||||
[Gemini CLI installation, execution, and releases](https://www.geminicli.com/docs/get-started/installation)
|
||||
for recommended system specifications and a detailed installation guide.
|
||||
|
||||
### Quick Install
|
||||
@@ -71,9 +71,9 @@ conda activate gemini_env
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
## Release Cadence and Tags
|
||||
## Release Channels
|
||||
|
||||
See [Releases](./docs/releases.md) for more details.
|
||||
See [Releases](https://www.geminicli.com/docs/changelogs) for more details.
|
||||
|
||||
### Preview
|
||||
|
||||
@@ -209,7 +209,7 @@ gemini
|
||||
```
|
||||
|
||||
For Google Workspace accounts and other authentication methods, see the
|
||||
[authentication guide](./docs/get-started/authentication.md).
|
||||
[authentication guide](https://www.geminicli.com/docs/get-started/authentication).
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
@@ -278,59 +278,64 @@ gemini
|
||||
|
||||
### Getting Started
|
||||
|
||||
- [**Quickstart Guide**](./docs/get-started/index.md) - Get up and running
|
||||
quickly.
|
||||
- [**Authentication Setup**](./docs/get-started/authentication.md) - Detailed
|
||||
auth configuration.
|
||||
- [**Configuration Guide**](./docs/reference/configuration.md) - Settings and
|
||||
customization.
|
||||
- [**Keyboard Shortcuts**](./docs/reference/keyboard-shortcuts.md) -
|
||||
- [**Quickstart Guide**](https://www.geminicli.com/docs/get-started) - Get up
|
||||
and running quickly.
|
||||
- [**Authentication Setup**](https://www.geminicli.com/docs/get-started/authentication) -
|
||||
Detailed auth configuration.
|
||||
- [**Configuration Guide**](https://www.geminicli.com/docs/reference/configuration) -
|
||||
Settings and customization.
|
||||
- [**Keyboard Shortcuts**](https://www.geminicli.com/docs/reference/keyboard-shortcuts) -
|
||||
Productivity tips.
|
||||
|
||||
### Core Features
|
||||
|
||||
- [**Commands Reference**](./docs/reference/commands.md) - All slash commands
|
||||
(`/help`, `/chat`, etc).
|
||||
- [**Custom Commands**](./docs/cli/custom-commands.md) - Create your own
|
||||
reusable commands.
|
||||
- [**Context Files (GEMINI.md)**](./docs/cli/gemini-md.md) - Provide persistent
|
||||
context to Gemini CLI.
|
||||
- [**Checkpointing**](./docs/cli/checkpointing.md) - Save and resume
|
||||
conversations.
|
||||
- [**Token Caching**](./docs/cli/token-caching.md) - Optimize token usage.
|
||||
- [**Commands Reference**](https://www.geminicli.com/docs/reference/commands) -
|
||||
All slash commands (`/help`, `/chat`, etc).
|
||||
- [**Custom Commands**](https://www.geminicli.com/docs/cli/custom-commands) -
|
||||
Create your own reusable commands.
|
||||
- [**Context Files (GEMINI.md)**](https://www.geminicli.com/docs/cli/gemini-md) -
|
||||
Provide persistent context to Gemini CLI.
|
||||
- [**Checkpointing**](https://www.geminicli.com/docs/cli/checkpointing) - Save
|
||||
and resume conversations.
|
||||
- [**Token Caching**](https://www.geminicli.com/docs/cli/token-caching) -
|
||||
Optimize token usage.
|
||||
|
||||
### Tools & Extensions
|
||||
|
||||
- [**Built-in Tools Overview**](./docs/reference/tools.md)
|
||||
- [File System Operations](./docs/tools/file-system.md)
|
||||
- [Shell Commands](./docs/tools/shell.md)
|
||||
- [Web Fetch & Search](./docs/tools/web-fetch.md)
|
||||
- [**MCP Server Integration**](./docs/tools/mcp-server.md) - Extend with custom
|
||||
tools.
|
||||
- [**Custom Extensions**](./docs/extensions/index.md) - Build and share your own
|
||||
commands.
|
||||
- [**Built-in Tools Overview**](https://www.geminicli.com/docs/reference/tools)
|
||||
- [File System Operations](https://www.geminicli.com/docs/tools/file-system)
|
||||
- [Shell Commands](https://www.geminicli.com/docs/tools/shell)
|
||||
- [Web Fetch & Search](https://www.geminicli.com/docs/tools/web-fetch)
|
||||
- [**MCP Server Integration**](https://www.geminicli.com/docs/tools/mcp-server) -
|
||||
Extend with custom tools.
|
||||
- [**Custom Extensions**](https://geminicli.com/docs/extensions/writing-extensions) -
|
||||
Build and share your own commands.
|
||||
|
||||
### Advanced Topics
|
||||
|
||||
- [**Headless Mode (Scripting)**](./docs/cli/headless.md) - Use Gemini CLI in
|
||||
automated workflows.
|
||||
- [**IDE Integration**](./docs/ide-integration/index.md) - VS Code companion.
|
||||
- [**Sandboxing & Security**](./docs/cli/sandbox.md) - Safe execution
|
||||
environments.
|
||||
- [**Trusted Folders**](./docs/cli/trusted-folders.md) - Control execution
|
||||
policies by folder.
|
||||
- [**Enterprise Guide**](./docs/cli/enterprise.md) - Deploy and manage in a
|
||||
corporate environment.
|
||||
- [**Telemetry & Monitoring**](./docs/cli/telemetry.md) - Usage tracking.
|
||||
- [**Tools reference**](./docs/reference/tools.md) - Built-in tools overview.
|
||||
- [**Local development**](./docs/local-development.md) - Local development
|
||||
tooling.
|
||||
- [**Headless Mode (Scripting)**](https://www.geminicli.com/docs/cli/headless) -
|
||||
Use Gemini CLI in automated workflows.
|
||||
- [**IDE Integration**](https://www.geminicli.com/docs/ide-integration) - VS
|
||||
Code companion.
|
||||
- [**Sandboxing & Security**](https://www.geminicli.com/docs/cli/sandbox) - Safe
|
||||
execution environments.
|
||||
- [**Trusted Folders**](https://www.geminicli.com/docs/cli/trusted-folders) -
|
||||
Control execution policies by folder.
|
||||
- [**Enterprise Guide**](https://www.geminicli.com/docs/cli/enterprise) - Deploy
|
||||
and manage in a corporate environment.
|
||||
- [**Telemetry & Monitoring**](https://www.geminicli.com/docs/cli/telemetry) -
|
||||
Usage tracking.
|
||||
- [**Tools reference**](https://www.geminicli.com/docs/reference/tools) -
|
||||
Built-in tools overview.
|
||||
- [**Local development**](https://www.geminicli.com/docs/local-development) -
|
||||
Local development tooling.
|
||||
|
||||
### Troubleshooting & Support
|
||||
|
||||
- [**Troubleshooting Guide**](./docs/resources/troubleshooting.md) - Common
|
||||
issues and solutions.
|
||||
- [**FAQ**](./docs/resources/faq.md) - Frequently asked questions.
|
||||
- [**Troubleshooting Guide**](https://www.geminicli.com/docs/resources/troubleshooting) -
|
||||
Common issues and solutions.
|
||||
- [**FAQ**](https://www.geminicli.com/docs/resources/faq) - Frequently asked
|
||||
questions.
|
||||
- Use `/bug` command to report issues directly from the CLI.
|
||||
|
||||
### Using MCP Servers
|
||||
@@ -344,8 +349,9 @@ custom tools:
|
||||
> @database Run a query to find inactive users
|
||||
```
|
||||
|
||||
See the [MCP Server Integration guide](./docs/tools/mcp-server.md) for setup
|
||||
instructions.
|
||||
See the
|
||||
[MCP Server Integration guide](https://www.geminicli.com/docs/tools/mcp-server)
|
||||
for setup instructions.
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
@@ -365,8 +371,11 @@ for planned features and priorities.
|
||||
|
||||
## 📖 Resources
|
||||
|
||||
- **[Free Course](https://learn.deeplearning.ai/courses/gemini-cli-code-and-create-with-an-open-source-agent/information)** -
|
||||
Learn the basics.
|
||||
- **[Official Roadmap](./ROADMAP.md)** - See what's coming next.
|
||||
- **[Changelog](./docs/changelogs/index.md)** - See recent notable updates.
|
||||
- **[Changelog](https://www.geminicli.com/docs/changelogs)** - See recent
|
||||
notable updates.
|
||||
- **[NPM Package](https://www.npmjs.com/package/@google/gemini-cli)** - Package
|
||||
registry.
|
||||
- **[GitHub Issues](https://github.com/google-gemini/gemini-cli/issues)** -
|
||||
@@ -376,15 +385,26 @@ for planned features and priorities.
|
||||
|
||||
### Uninstall
|
||||
|
||||
See the [Uninstall Guide](./docs/resources/uninstall.md) for removal
|
||||
instructions.
|
||||
See the [Uninstall Guide](https://www.geminicli.com/docs/resources/uninstall)
|
||||
for removal instructions.
|
||||
|
||||
## 📄 Legal
|
||||
|
||||
- **License**: [Apache License 2.0](LICENSE)
|
||||
- **Terms of Service**: [Terms & Privacy](./docs/resources/tos-privacy.md)
|
||||
- **Terms of Service**:
|
||||
[Terms & Privacy](https://www.geminicli.com/docs/resources/tos-privacy)
|
||||
- **Security**: [Security Policy](SECURITY.md)
|
||||
|
||||
<p align="left">
|
||||
<a href="https://www.star-history.com/google-gemini/gemini-cli">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/badge?repo=google-gemini/gemini-cli&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/badge?repo=google-gemini/gemini-cli" />
|
||||
<img alt="Star History Rank" src="https://api.star-history.com/badge?repo=google-gemini/gemini-cli" />
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
|
||||
@@ -72,7 +72,7 @@ organization.
|
||||
**Supported Fields:**
|
||||
|
||||
- `url`: (Required) The full URL of the MCP server endpoint.
|
||||
- `type`: (Required) The connection type (e.g., `sse` or `http`).
|
||||
- `type`: (Required) The connection type (for example, `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
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@@ -18,6 +18,123 @@ on GitHub.
|
||||
| [Preview](preview.md) | Experimental features ready for early feedback. |
|
||||
| [Stable](latest.md) | Stable, recommended for general use. |
|
||||
|
||||
## Announcements: v0.41.0 - 2026-05-05
|
||||
|
||||
- **Real-time Voice Mode:** Implemented real-time voice mode with cloud and
|
||||
local backends
|
||||
([#24174](https://github.com/google-gemini/gemini-cli/pull/24174) by
|
||||
@Abhijit-2592).
|
||||
- **Secure Environment Loading:** Enforced workspace trust and secured .env
|
||||
loading in headless mode
|
||||
([#25814](https://github.com/google-gemini/gemini-cli/pull/25814) by
|
||||
@ehedlund).
|
||||
- **Advanced Shell Validation:** Enhanced shell command validation and added
|
||||
core tools allowlist for improved security
|
||||
([#25720](https://github.com/google-gemini/gemini-cli/pull/25720) by @galz10).
|
||||
|
||||
## Announcements: v0.40.0 - 2026-04-28
|
||||
|
||||
- **Offline Search and Themes:** Bundled ripgrep for offline search support and
|
||||
added GitHub-style colorblind themes
|
||||
([#25342](https://github.com/google-gemini/gemini-cli/pull/25342) by
|
||||
@scidomino, [#15504](https://github.com/google-gemini/gemini-cli/pull/15504)
|
||||
by @Z1xus).
|
||||
- **Advanced Resource and Memory Management:** Introduced MCP resource tools and
|
||||
transitioned to a prompt-driven, four-tier memory management system
|
||||
([#25395](https://github.com/google-gemini/gemini-cli/pull/25395) by
|
||||
@ruomengz, [#25716](https://github.com/google-gemini/gemini-cli/pull/25716) by
|
||||
@SandyTao520).
|
||||
- **UX and Local Models:** Enabled topic update narrations by default and
|
||||
streamlined Gemma local model setup with `gemini gemma`
|
||||
([#25586](https://github.com/google-gemini/gemini-cli/pull/25586) by
|
||||
@gundermanc, [#25498](https://github.com/google-gemini/gemini-cli/pull/25498)
|
||||
by @Samee24).
|
||||
|
||||
## Announcements: v0.39.0 - 2026-04-23
|
||||
|
||||
- **Skill Management:** Added a new `/memory` inbox command for reviewing and
|
||||
patching skills extracted during sessions
|
||||
([#24544](https://github.com/google-gemini/gemini-cli/pull/24544) by
|
||||
@SandyTao520, [#25148](https://github.com/google-gemini/gemini-cli/pull/25148)
|
||||
by @SandyTao520).
|
||||
- **Improved Transparency:** Plan Mode now requires confirmation for skill
|
||||
activation and allows plan inspection
|
||||
([#24946](https://github.com/google-gemini/gemini-cli/pull/24946),
|
||||
[#25058](https://github.com/google-gemini/gemini-cli/pull/25058) by
|
||||
@ruomengz).
|
||||
- **Architecture & Reliability:** Introduced a decoupled `ContextManager`
|
||||
architecture and resolved several critical memory leaks and PTY exhaustion
|
||||
issues ([#24752](https://github.com/google-gemini/gemini-cli/pull/24752) by
|
||||
@joshualitt, [#25079](https://github.com/google-gemini/gemini-cli/pull/25079)
|
||||
by @spencer426).
|
||||
|
||||
## Announcements: v0.38.0 - 2026-04-14
|
||||
|
||||
- **Chapters Narrative Flow:** Group agent interactions into "Chapters" based on
|
||||
intent and tool usage for better session structure
|
||||
([#23150](https://github.com/google-gemini/gemini-cli/pull/23150) by
|
||||
@Abhijit-2592,
|
||||
[#24079](https://github.com/google-gemini/gemini-cli/pull/24079) by
|
||||
@gundermanc).
|
||||
- **Context Compression Service:** Advanced context management to efficiently
|
||||
distill conversation history
|
||||
([#24483](https://github.com/google-gemini/gemini-cli/pull/24483) by
|
||||
@joshualitt).
|
||||
- **UI Flicker & UX Enhancements:** Solved rendering flicker with "Terminal
|
||||
Buffer" mode and introduced selective topic expansion
|
||||
([#24512](https://github.com/google-gemini/gemini-cli/pull/24512) by
|
||||
@jacob314, [#24793](https://github.com/google-gemini/gemini-cli/pull/24793) by
|
||||
@Abhijit-2592).
|
||||
- **Persistent Policy Approvals:** Implemented context-aware persistent
|
||||
approvals for tool execution
|
||||
([#23257](https://github.com/google-gemini/gemini-cli/pull/23257) by @jerop).
|
||||
|
||||
## Announcements: v0.37.0 - 2026-04-08
|
||||
|
||||
- **Dynamic Sandbox Expansion:** Implemented dynamic sandbox expansion and
|
||||
worktree support for Linux and Windows, improving developer workflows in
|
||||
isolated environments
|
||||
([#23692](https://github.com/google-gemini/gemini-cli/pull/23692) by @galz10,
|
||||
[#23691](https://github.com/google-gemini/gemini-cli/pull/23691) by
|
||||
@scidomino).
|
||||
- **Chapters Narrative Flow:** Introduced tool-based topic grouping ("Chapters")
|
||||
to provide better session structure and narrative continuity
|
||||
([#23150](https://github.com/google-gemini/gemini-cli/pull/23150) by
|
||||
@Abhijit-2592,
|
||||
[#24079](https://github.com/google-gemini/gemini-cli/pull/24079) by
|
||||
@gundermanc).
|
||||
- **Advanced Browser Capabilities:** Enhanced the browser agent with persistent
|
||||
sessions and dynamic tool discovery
|
||||
([#21306](https://github.com/google-gemini/gemini-cli/pull/21306) by
|
||||
@kunal-10-cloud,
|
||||
[#23805](https://github.com/google-gemini/gemini-cli/pull/23805) by
|
||||
@cynthialong0-0).
|
||||
|
||||
## Announcements: v0.36.0 - 2026-04-01
|
||||
|
||||
- **Multi-Registry Architecture and Sandboxing:** Introduced a multi-registry
|
||||
architecture and implemented native macOS Seatbelt and Windows sandboxing for
|
||||
enhanced subagent security
|
||||
([#22712](https://github.com/google-gemini/gemini-cli/pull/22712),
|
||||
[#22718](https://github.com/google-gemini/gemini-cli/pull/22718) by @akh64bit,
|
||||
[#22832](https://github.com/google-gemini/gemini-cli/pull/22832) by @ehedlund,
|
||||
[#21807](https://github.com/google-gemini/gemini-cli/pull/21807) by
|
||||
@mattKorwel).
|
||||
- **Refreshed Composer UX:** Implemented a refreshed user experience for the
|
||||
Composer layout and improved terminal interaction robustness
|
||||
([#21212](https://github.com/google-gemini/gemini-cli/pull/21212),
|
||||
[#23286](https://github.com/google-gemini/gemini-cli/pull/23286) by
|
||||
@jwhelangoog).
|
||||
- **Git Worktree Support:** Added native support for Git worktrees, allowing for
|
||||
isolated parallel sessions
|
||||
([#22973](https://github.com/google-gemini/gemini-cli/pull/22973),
|
||||
[#23265](https://github.com/google-gemini/gemini-cli/pull/23265) by @jerop).
|
||||
- **Subagent Context and Feedback:** Enhanced subagents with JIT context
|
||||
injection and resilient tool rejection with contextual feedback
|
||||
([#23032](https://github.com/google-gemini/gemini-cli/pull/23032),
|
||||
[#22951](https://github.com/google-gemini/gemini-cli/pull/22951) by
|
||||
@abhipatel12).
|
||||
|
||||
## Announcements: v0.35.0 - 2026-03-24
|
||||
|
||||
- **Customizable Keyboard Shortcuts:** Users can now customize their keyboard
|
||||
|
||||
+107
-366
@@ -1,6 +1,6 @@
|
||||
# Latest stable release: v0.35.2
|
||||
# Latest stable release: v0.41.0
|
||||
|
||||
Released: March 26, 2026
|
||||
Released: May 05, 2026
|
||||
|
||||
For most users, our latest stable release is the recommended release. Install
|
||||
the latest stable version with:
|
||||
@@ -11,378 +11,119 @@ npm install -g @google/gemini-cli
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Customizable Keyboard Shortcuts:** Significant improvements to input
|
||||
flexibility with support for custom keybindings, literal character bindings,
|
||||
and extended terminal protocol keys.
|
||||
- **Vim Mode Enhancements:** Further refinement of the Vim modal editing
|
||||
experience, adding common motions like \`X\`, \`~\`, \`r\`, and \`f/F/t/T\`,
|
||||
along with yank and paste support.
|
||||
- **Enhanced Security through Sandboxing:** Introduction of a unified
|
||||
\`SandboxManager\` and integration of Linux-native sandboxing (bubblewrap and
|
||||
seccomp) to isolate tool execution and improve system security.
|
||||
- **JIT Context Discovery:** Improved performance and accuracy by enabling
|
||||
Just-In-Time context loading for file system tools, ensuring the model has the
|
||||
most relevant information without overwhelming the context.
|
||||
- **Subagent & Performance Updates:** Subagents are now enabled by default,
|
||||
supported by a model-driven parallel tool scheduler and code splitting for
|
||||
faster startup and more efficient task execution.
|
||||
- **Real-time Voice Mode:** Introduced support for real-time voice interaction
|
||||
with both cloud-based and local processing backends.
|
||||
- **Enhanced Security:** Implemented mandatory workspace trust for headless
|
||||
environments and secured the loading of `.env` configuration files.
|
||||
- **Advanced Shell Validation:** Added a robust shell command validation layer
|
||||
and a core tools allowlist to prevent unauthorized execution.
|
||||
- **Improved Context Management:** Integrated a new `ContextManager` and
|
||||
`AgentChatHistory` to provide more reliable and efficient session handling.
|
||||
- **Auto-Memory Persistence:** Enabled the persistence of the auto-memory
|
||||
scratchpad, allowing for seamless skill extraction across turns.
|
||||
|
||||
## What's Changed
|
||||
|
||||
- fix(core): allow disabling environment variable redaction by @galz10 in
|
||||
[#23927](https://github.com/google-gemini/gemini-cli/pull/23927)
|
||||
- fix(a2a-server): A2A server should execute ask policies in interactive mode by
|
||||
@keith.schaab in
|
||||
[#23831](https://github.com/google-gemini/gemini-cli/pull/23831)
|
||||
- feat(cli): customizable keyboard shortcuts by @scidomino in
|
||||
[#21945](https://github.com/google-gemini/gemini-cli/pull/21945)
|
||||
- feat(core): Thread `AgentLoopContext` through core. by @joshualitt in
|
||||
[#21944](https://github.com/google-gemini/gemini-cli/pull/21944)
|
||||
- chore(release): bump version to 0.35.0-nightly.20260311.657f19c1f by
|
||||
- chore(release): bump version to 0.41.0-nightly.20260423.gaa05b4583 by
|
||||
@gemini-cli-robot in
|
||||
[#21966](https://github.com/google-gemini/gemini-cli/pull/21966)
|
||||
- refactor(a2a): remove legacy CoreToolScheduler by @adamfweidman in
|
||||
[#21955](https://github.com/google-gemini/gemini-cli/pull/21955)
|
||||
- feat(ui): add missing vim mode motions (X, ~, r, f/F/t/T, df/dt and friends)
|
||||
by @aanari in [#21932](https://github.com/google-gemini/gemini-cli/pull/21932)
|
||||
- Feat/retry fetch notifications by @aishaneeshah in
|
||||
[#21813](https://github.com/google-gemini/gemini-cli/pull/21813)
|
||||
- fix(core): remove OAuth check from handle fallback and clean up stray file by
|
||||
@sehoon38 in [#21962](https://github.com/google-gemini/gemini-cli/pull/21962)
|
||||
- feat(cli): support literal character keybindings and extended Kitty protocol
|
||||
keys by @scidomino in
|
||||
[#21972](https://github.com/google-gemini/gemini-cli/pull/21972)
|
||||
- fix(ui): clamp cursor to last char after all NORMAL mode deletes by @aanari in
|
||||
[#21973](https://github.com/google-gemini/gemini-cli/pull/21973)
|
||||
- test(core): add missing tests for prompts/utils.ts by @krrishverma1805-web in
|
||||
[#19941](https://github.com/google-gemini/gemini-cli/pull/19941)
|
||||
- fix(cli): allow scrolling keys in copy mode (Ctrl+S selection mode) by
|
||||
@nsalerni in [#19933](https://github.com/google-gemini/gemini-cli/pull/19933)
|
||||
- docs(cli): add custom keybinding documentation by @scidomino in
|
||||
[#21980](https://github.com/google-gemini/gemini-cli/pull/21980)
|
||||
- docs: fix misleading YOLO mode description in defaultApprovalMode by
|
||||
@Gyanranjan-Priyam in
|
||||
[#21878](https://github.com/google-gemini/gemini-cli/pull/21878)
|
||||
- fix: clean up /clear and /resume by @jackwotherspoon in
|
||||
[#22007](https://github.com/google-gemini/gemini-cli/pull/22007)
|
||||
- fix(core)#20941: reap orphaned descendant processes on PTY abort by @manavmax
|
||||
in [#21124](https://github.com/google-gemini/gemini-cli/pull/21124)
|
||||
- fix(core): update language detection to use LSP 3.18 identifiers by @yunaseoul
|
||||
in [#21931](https://github.com/google-gemini/gemini-cli/pull/21931)
|
||||
- feat(cli): support removing keybindings via '-' prefix by @scidomino in
|
||||
[#22042](https://github.com/google-gemini/gemini-cli/pull/22042)
|
||||
- feat(policy): add --admin-policy flag for supplemental admin policies by
|
||||
@galz10 in [#20360](https://github.com/google-gemini/gemini-cli/pull/20360)
|
||||
- merge duplicate imports packages/cli/src subtask1 by @Nixxx19 in
|
||||
[#22040](https://github.com/google-gemini/gemini-cli/pull/22040)
|
||||
- perf(core): parallelize user quota and experiments fetching in refreshAuth by
|
||||
@sehoon38 in [#21648](https://github.com/google-gemini/gemini-cli/pull/21648)
|
||||
- Changelog for v0.34.0-preview.0 by @gemini-cli-robot in
|
||||
[#21965](https://github.com/google-gemini/gemini-cli/pull/21965)
|
||||
- Changelog for v0.33.0 by @gemini-cli-robot in
|
||||
[#21967](https://github.com/google-gemini/gemini-cli/pull/21967)
|
||||
- fix(core): handle EISDIR in robustRealpath on Windows by @sehoon38 in
|
||||
[#21984](https://github.com/google-gemini/gemini-cli/pull/21984)
|
||||
- feat(core): include initiationMethod in conversation interaction telemetry by
|
||||
@yunaseoul in [#22054](https://github.com/google-gemini/gemini-cli/pull/22054)
|
||||
- feat(ui): add vim yank/paste (y/p/P) with unnamed register by @aanari in
|
||||
[#22026](https://github.com/google-gemini/gemini-cli/pull/22026)
|
||||
- fix(core): enable numerical routing for api key users by @sehoon38 in
|
||||
[#21977](https://github.com/google-gemini/gemini-cli/pull/21977)
|
||||
- feat(telemetry): implement retry attempt telemetry for network related retries
|
||||
by @aishaneeshah in
|
||||
[#22027](https://github.com/google-gemini/gemini-cli/pull/22027)
|
||||
- fix(policy): remove unnecessary escapeRegex from pattern builders by
|
||||
@spencer426 in
|
||||
[#21921](https://github.com/google-gemini/gemini-cli/pull/21921)
|
||||
- fix(core): preserve dynamic tool descriptions on session resume by @sehoon38
|
||||
in [#18835](https://github.com/google-gemini/gemini-cli/pull/18835)
|
||||
- chore: allow 'gemini-3.1' in sensitive keyword linter by @scidomino in
|
||||
[#22065](https://github.com/google-gemini/gemini-cli/pull/22065)
|
||||
- feat(core): support custom base URL via env vars by @junaiddshaukat in
|
||||
[#21561](https://github.com/google-gemini/gemini-cli/pull/21561)
|
||||
- merge duplicate imports packages/cli/src subtask2 by @Nixxx19 in
|
||||
[#22051](https://github.com/google-gemini/gemini-cli/pull/22051)
|
||||
- fix(core): silently retry API errors up to 3 times before halting session by
|
||||
@spencer426 in
|
||||
[#21989](https://github.com/google-gemini/gemini-cli/pull/21989)
|
||||
- feat(core): simplify subagent success UI and improve early termination display
|
||||
by @abhipatel12 in
|
||||
[#21917](https://github.com/google-gemini/gemini-cli/pull/21917)
|
||||
- merge duplicate imports packages/cli/src subtask3 by @Nixxx19 in
|
||||
[#22056](https://github.com/google-gemini/gemini-cli/pull/22056)
|
||||
- fix(hooks): fix BeforeAgent/AfterAgent inconsistencies (#18514) by @krishdef7
|
||||
in [#21383](https://github.com/google-gemini/gemini-cli/pull/21383)
|
||||
- feat(core): implement SandboxManager interface and config schema by @galz10 in
|
||||
[#21774](https://github.com/google-gemini/gemini-cli/pull/21774)
|
||||
- docs: document npm deprecation warnings as safe to ignore by @h30s in
|
||||
[#20692](https://github.com/google-gemini/gemini-cli/pull/20692)
|
||||
- fix: remove status/need-triage from maintainer-only issues by @SandyTao520 in
|
||||
[#22044](https://github.com/google-gemini/gemini-cli/pull/22044)
|
||||
- fix(core): propagate subagent context to policy engine by @NTaylorMullen in
|
||||
[#22086](https://github.com/google-gemini/gemini-cli/pull/22086)
|
||||
- fix(cli): resolve skill uninstall failure when skill name is updated by
|
||||
@NTaylorMullen in
|
||||
[#22085](https://github.com/google-gemini/gemini-cli/pull/22085)
|
||||
- docs(plan): clarify interactive plan editing with Ctrl+X by @Adib234 in
|
||||
[#22076](https://github.com/google-gemini/gemini-cli/pull/22076)
|
||||
- fix(policy): ensure user policies are loaded when policyPaths is empty by
|
||||
@NTaylorMullen in
|
||||
[#22090](https://github.com/google-gemini/gemini-cli/pull/22090)
|
||||
- Docs: Add documentation for model steering (experimental). by @jkcinouye in
|
||||
[#21154](https://github.com/google-gemini/gemini-cli/pull/21154)
|
||||
- Add issue for automated changelogs by @g-samroberts in
|
||||
[#21912](https://github.com/google-gemini/gemini-cli/pull/21912)
|
||||
- fix(core): secure argsPattern and revert WEB_FETCH_TOOL_NAME escalation by
|
||||
@spencer426 in
|
||||
[#22104](https://github.com/google-gemini/gemini-cli/pull/22104)
|
||||
- feat(core): differentiate User-Agent for a2a-server and ACP clients by
|
||||
@bdmorgan in [#22059](https://github.com/google-gemini/gemini-cli/pull/22059)
|
||||
- refactor(core): extract ExecutionLifecycleService for tool backgrounding by
|
||||
@adamfweidman in
|
||||
[#21717](https://github.com/google-gemini/gemini-cli/pull/21717)
|
||||
- feat: Display pending and confirming tool calls by @sripasg in
|
||||
[#22106](https://github.com/google-gemini/gemini-cli/pull/22106)
|
||||
- feat(browser): implement input blocker overlay during automation by
|
||||
@kunal-10-cloud in
|
||||
[#21132](https://github.com/google-gemini/gemini-cli/pull/21132)
|
||||
- fix: register themes on extension load not start by @jackwotherspoon in
|
||||
[#22148](https://github.com/google-gemini/gemini-cli/pull/22148)
|
||||
- feat(ui): Do not show Ultra users /upgrade hint (#22154) by @sehoon38 in
|
||||
[#22156](https://github.com/google-gemini/gemini-cli/pull/22156)
|
||||
- chore: remove unnecessary log for themes by @jackwotherspoon in
|
||||
[#22165](https://github.com/google-gemini/gemini-cli/pull/22165)
|
||||
- fix(core): resolve MCP tool FQN validation, schema export, and wildcards in
|
||||
subagents by @abhipatel12 in
|
||||
[#22069](https://github.com/google-gemini/gemini-cli/pull/22069)
|
||||
- fix(cli): validate --model argument at startup by @JaisalJain in
|
||||
[#21393](https://github.com/google-gemini/gemini-cli/pull/21393)
|
||||
- fix(core): handle policy ALLOW for exit_plan_mode by @backnotprop in
|
||||
[#21802](https://github.com/google-gemini/gemini-cli/pull/21802)
|
||||
- feat(telemetry): add Clearcut instrumentation for AI credits billing events by
|
||||
@gsquared94 in
|
||||
[#22153](https://github.com/google-gemini/gemini-cli/pull/22153)
|
||||
- feat(core): add google credentials provider for remote agents by @adamfweidman
|
||||
in [#21024](https://github.com/google-gemini/gemini-cli/pull/21024)
|
||||
- test(cli): add integration test for node deprecation warnings by @Nixxx19 in
|
||||
[#20215](https://github.com/google-gemini/gemini-cli/pull/20215)
|
||||
- feat(cli): allow safe tools to execute concurrently while agent is busy by
|
||||
@spencer426 in
|
||||
[#21988](https://github.com/google-gemini/gemini-cli/pull/21988)
|
||||
- feat(core): implement model-driven parallel tool scheduler by @abhipatel12 in
|
||||
[#21933](https://github.com/google-gemini/gemini-cli/pull/21933)
|
||||
- update vulnerable deps by @scidomino in
|
||||
[#22180](https://github.com/google-gemini/gemini-cli/pull/22180)
|
||||
- fix(core): fix startup stats to use int values for timestamps and durations by
|
||||
@yunaseoul in [#22201](https://github.com/google-gemini/gemini-cli/pull/22201)
|
||||
- fix(core): prevent duplicate tool schemas for instantiated tools by
|
||||
@abhipatel12 in
|
||||
[#22204](https://github.com/google-gemini/gemini-cli/pull/22204)
|
||||
- fix(core): add proxy routing support for remote A2A subagents by @adamfweidman
|
||||
in [#22199](https://github.com/google-gemini/gemini-cli/pull/22199)
|
||||
- fix(core/ide): add Antigravity CLI fallbacks by @apfine in
|
||||
[#22030](https://github.com/google-gemini/gemini-cli/pull/22030)
|
||||
- fix(browser): fix duplicate function declaration error in browser agent by
|
||||
@gsquared94 in
|
||||
[#22207](https://github.com/google-gemini/gemini-cli/pull/22207)
|
||||
- feat(core): implement Stage 1 improvements for webfetch tool by @aishaneeshah
|
||||
in [#21313](https://github.com/google-gemini/gemini-cli/pull/21313)
|
||||
- Changelog for v0.34.0-preview.1 by @gemini-cli-robot in
|
||||
[#22194](https://github.com/google-gemini/gemini-cli/pull/22194)
|
||||
- perf(cli): enable code splitting and deferred UI loading by @sehoon38 in
|
||||
[#22117](https://github.com/google-gemini/gemini-cli/pull/22117)
|
||||
- fix: remove unused img.png from project root by @SandyTao520 in
|
||||
[#22222](https://github.com/google-gemini/gemini-cli/pull/22222)
|
||||
- docs(local model routing): add docs on how to use Gemma for local model
|
||||
routing by @douglas-reid in
|
||||
[#21365](https://github.com/google-gemini/gemini-cli/pull/21365)
|
||||
- feat(a2a): enable native gRPC support and protocol routing by @alisa-alisa in
|
||||
[#21403](https://github.com/google-gemini/gemini-cli/pull/21403)
|
||||
- fix(cli): escape @ symbols on paste to prevent unintended file expansion by
|
||||
@krishdef7 in [#21239](https://github.com/google-gemini/gemini-cli/pull/21239)
|
||||
- feat(core): add trajectoryId to ConversationOffered telemetry by @yunaseoul in
|
||||
[#22214](https://github.com/google-gemini/gemini-cli/pull/22214)
|
||||
- docs: clarify that tools.core is an allowlist for ALL built-in tools by
|
||||
@hobostay in [#18813](https://github.com/google-gemini/gemini-cli/pull/18813)
|
||||
- docs(plan): document hooks with plan mode by @ruomengz in
|
||||
[#22197](https://github.com/google-gemini/gemini-cli/pull/22197)
|
||||
- Changelog for v0.33.1 by @gemini-cli-robot in
|
||||
[#22235](https://github.com/google-gemini/gemini-cli/pull/22235)
|
||||
- build(ci): fix false positive evals trigger on merge commits by @gundermanc in
|
||||
[#22237](https://github.com/google-gemini/gemini-cli/pull/22237)
|
||||
- fix(core): explicitly pass messageBus to policy engine for MCP tool saves by
|
||||
@abhipatel12 in
|
||||
[#22255](https://github.com/google-gemini/gemini-cli/pull/22255)
|
||||
- feat(core): Fully migrate packages/core to AgentLoopContext. by @joshualitt in
|
||||
[#22115](https://github.com/google-gemini/gemini-cli/pull/22115)
|
||||
- feat(core): increase sub-agent turn and time limits by @bdmorgan in
|
||||
[#22196](https://github.com/google-gemini/gemini-cli/pull/22196)
|
||||
- feat(core): instrument file system tools for JIT context discovery by
|
||||
@SandyTao520 in
|
||||
[#22082](https://github.com/google-gemini/gemini-cli/pull/22082)
|
||||
- refactor(ui): extract pure session browser utilities by @abhipatel12 in
|
||||
[#22256](https://github.com/google-gemini/gemini-cli/pull/22256)
|
||||
- fix(plan): Fix AskUser evals by @Adib234 in
|
||||
[#22074](https://github.com/google-gemini/gemini-cli/pull/22074)
|
||||
- fix(settings): prevent j/k navigation keys from intercepting edit buffer input
|
||||
by @student-ankitpandit in
|
||||
[#21865](https://github.com/google-gemini/gemini-cli/pull/21865)
|
||||
- feat(skills): improve async-pr-review workflow and logging by @mattKorwel in
|
||||
[#21790](https://github.com/google-gemini/gemini-cli/pull/21790)
|
||||
- refactor(cli): consolidate getErrorMessage utility to core by @scidomino in
|
||||
[#22190](https://github.com/google-gemini/gemini-cli/pull/22190)
|
||||
- fix(core): show descriptive error messages when saving settings fails by
|
||||
@afarber in [#18095](https://github.com/google-gemini/gemini-cli/pull/18095)
|
||||
- docs(core): add authentication guide for remote subagents by @adamfweidman in
|
||||
[#22178](https://github.com/google-gemini/gemini-cli/pull/22178)
|
||||
- docs: overhaul subagents documentation and add /agents command by @abhipatel12
|
||||
in [#22345](https://github.com/google-gemini/gemini-cli/pull/22345)
|
||||
- refactor(ui): extract SessionBrowser static ui components by @abhipatel12 in
|
||||
[#22348](https://github.com/google-gemini/gemini-cli/pull/22348)
|
||||
- test: add Object.create context regression test and tool confirmation
|
||||
integration test by @gsquared94 in
|
||||
[#22356](https://github.com/google-gemini/gemini-cli/pull/22356)
|
||||
- feat(tracker): return TodoList display for tracker tools by @anj-s in
|
||||
[#22060](https://github.com/google-gemini/gemini-cli/pull/22060)
|
||||
- feat(agent): add allowed domain restrictions for browser agent by
|
||||
[#25847](https://github.com/google-gemini/gemini-cli/pull/25847)
|
||||
- fix(core): only show `list` suggestion if the partial input is empty by
|
||||
@cynthialong0-0 in
|
||||
[#21775](https://github.com/google-gemini/gemini-cli/pull/21775)
|
||||
- chore/release: bump version to 0.35.0-nightly.20260313.bb060d7a9 by
|
||||
@gemini-cli-robot in
|
||||
[#22251](https://github.com/google-gemini/gemini-cli/pull/22251)
|
||||
- Move keychain fallback to keychain service by @chrstnb in
|
||||
[#22332](https://github.com/google-gemini/gemini-cli/pull/22332)
|
||||
- feat(core): integrate SandboxManager to sandbox all process-spawning tools by
|
||||
@galz10 in [#22231](https://github.com/google-gemini/gemini-cli/pull/22231)
|
||||
- fix(cli): support CJK input and full Unicode scalar values in terminal
|
||||
protocols by @scidomino in
|
||||
[#22353](https://github.com/google-gemini/gemini-cli/pull/22353)
|
||||
- Promote stable tests. by @gundermanc in
|
||||
[#22253](https://github.com/google-gemini/gemini-cli/pull/22253)
|
||||
- feat(tracker): add tracker policy by @anj-s in
|
||||
[#22379](https://github.com/google-gemini/gemini-cli/pull/22379)
|
||||
- feat(security): add disableAlwaysAllow setting to disable auto-approvals by
|
||||
@galz10 in [#21941](https://github.com/google-gemini/gemini-cli/pull/21941)
|
||||
- Revert "fix(cli): validate --model argument at startup" by @sehoon38 in
|
||||
[#22378](https://github.com/google-gemini/gemini-cli/pull/22378)
|
||||
- fix(mcp): handle equivalent root resource URLs in OAuth validation by @galz10
|
||||
in [#20231](https://github.com/google-gemini/gemini-cli/pull/20231)
|
||||
- fix(core): use session-specific temp directory for task tracker by @anj-s in
|
||||
[#22382](https://github.com/google-gemini/gemini-cli/pull/22382)
|
||||
- Fix issue where config was undefined. by @gundermanc in
|
||||
[#22397](https://github.com/google-gemini/gemini-cli/pull/22397)
|
||||
- fix(core): deduplicate project memory when JIT context is enabled by
|
||||
@SandyTao520 in
|
||||
[#22234](https://github.com/google-gemini/gemini-cli/pull/22234)
|
||||
- feat(prompts): implement Topic-Action-Summary model for verbosity reduction by
|
||||
[#25821](https://github.com/google-gemini/gemini-cli/pull/25821)
|
||||
- feat(cli): secure .env loading and enforce workspace trust in headless mode by
|
||||
@ehedlund in [#25814](https://github.com/google-gemini/gemini-cli/pull/25814)
|
||||
- fix: fatal hard-crash on loop detection via unhandled AbortError by @hsm207 in
|
||||
[#20108](https://github.com/google-gemini/gemini-cli/pull/20108)
|
||||
- update package-lock.json by @ehedlund in
|
||||
[#25876](https://github.com/google-gemini/gemini-cli/pull/25876)
|
||||
- feat(core): enhance shell command validation and add core tools allowlist by
|
||||
@galz10 in [#25720](https://github.com/google-gemini/gemini-cli/pull/25720)
|
||||
- fix(ui): corrected background color check in user message components by
|
||||
@devr0306 in [#25880](https://github.com/google-gemini/gemini-cli/pull/25880)
|
||||
- perf(core): fix slow boot by fetching experiments and quota asynchronously by
|
||||
@spencer426 in
|
||||
[#25758](https://github.com/google-gemini/gemini-cli/pull/25758)
|
||||
- feat(core,cli): add support for Gemma 4 models (experimental) by @Abhijit-2592
|
||||
in [#25604](https://github.com/google-gemini/gemini-cli/pull/25604)
|
||||
- update FatalUntrustedWorkspaceError message to include doc link by @ehedlund
|
||||
in [#25874](https://github.com/google-gemini/gemini-cli/pull/25874)
|
||||
- docs: add Gemini CLI course link to README by @JayadityaGit in
|
||||
[#25925](https://github.com/google-gemini/gemini-cli/pull/25925)
|
||||
- feat(repo): add gemini-cli-bot metrics and workflows by @gundermanc in
|
||||
[#25888](https://github.com/google-gemini/gemini-cli/pull/25888)
|
||||
- fix(cli): allow output redirection for cli commands by @spencer426 in
|
||||
[#25894](https://github.com/google-gemini/gemini-cli/pull/25894)
|
||||
- fix(core): fail closed in YOLO mode when shell parsing fails for restricted
|
||||
rules by @ehedlund in
|
||||
[#25935](https://github.com/google-gemini/gemini-cli/pull/25935)
|
||||
- fix(cli-ui): revert backspace handling to fix Windows regression by @scidomino
|
||||
in [#25941](https://github.com/google-gemini/gemini-cli/pull/25941)
|
||||
- feat(voice): implement real-time voice mode with cloud and local backends by
|
||||
@Abhijit-2592 in
|
||||
[#21503](https://github.com/google-gemini/gemini-cli/pull/21503)
|
||||
- fix(core): fix manual deletion of subagent histories by @abhipatel12 in
|
||||
[#22407](https://github.com/google-gemini/gemini-cli/pull/22407)
|
||||
- Add registry var by @kevinjwang1 in
|
||||
[#22224](https://github.com/google-gemini/gemini-cli/pull/22224)
|
||||
- Add ModelDefinitions to ModelConfigService by @kevinjwang1 in
|
||||
[#22302](https://github.com/google-gemini/gemini-cli/pull/22302)
|
||||
- fix(cli): improve command conflict handling for skills by @NTaylorMullen in
|
||||
[#21942](https://github.com/google-gemini/gemini-cli/pull/21942)
|
||||
- fix(core): merge user settings with extension-provided MCP servers by
|
||||
@abhipatel12 in
|
||||
[#22484](https://github.com/google-gemini/gemini-cli/pull/22484)
|
||||
- fix(core): skip discovery for incomplete MCP configs and resolve merge race
|
||||
condition by @abhipatel12 in
|
||||
[#22494](https://github.com/google-gemini/gemini-cli/pull/22494)
|
||||
- fix(automation): harden stale PR closer permissions and maintainer detection
|
||||
by @bdmorgan in
|
||||
[#22558](https://github.com/google-gemini/gemini-cli/pull/22558)
|
||||
- fix(automation): evaluate staleness before checking protected labels by
|
||||
@bdmorgan in [#22561](https://github.com/google-gemini/gemini-cli/pull/22561)
|
||||
- feat(agent): replace the runtime npx for browser agent chrome devtool mcp with
|
||||
pre-built bundle by @cynthialong0-0 in
|
||||
[#22213](https://github.com/google-gemini/gemini-cli/pull/22213)
|
||||
- perf: optimize TrackerService dependency checks by @anj-s in
|
||||
[#22384](https://github.com/google-gemini/gemini-cli/pull/22384)
|
||||
- docs(policy): remove trailing space from commandPrefix examples by @kawasin73
|
||||
in [#22264](https://github.com/google-gemini/gemini-cli/pull/22264)
|
||||
- fix(a2a-server): resolve unsafe assignment lint errors by @ehedlund in
|
||||
[#22661](https://github.com/google-gemini/gemini-cli/pull/22661)
|
||||
- fix: Adjust ToolGroupMessage filtering to hide Confirming and show Canceled
|
||||
tool calls. by @sripasg in
|
||||
[#22230](https://github.com/google-gemini/gemini-cli/pull/22230)
|
||||
- Disallow Object.create() and reflect. by @gundermanc in
|
||||
[#22408](https://github.com/google-gemini/gemini-cli/pull/22408)
|
||||
- Guard pro model usage by @sehoon38 in
|
||||
[#22665](https://github.com/google-gemini/gemini-cli/pull/22665)
|
||||
- refactor(core): Creates AgentSession abstraction for consolidated agent
|
||||
interface. by @mbleigh in
|
||||
[#22270](https://github.com/google-gemini/gemini-cli/pull/22270)
|
||||
- docs(changelog): remove internal commands from release notes by
|
||||
@jackwotherspoon in
|
||||
[#22529](https://github.com/google-gemini/gemini-cli/pull/22529)
|
||||
- feat: enable subagents by @abhipatel12 in
|
||||
[#22386](https://github.com/google-gemini/gemini-cli/pull/22386)
|
||||
- feat(extensions): implement cryptographic integrity verification for extension
|
||||
updates by @ehedlund in
|
||||
[#21772](https://github.com/google-gemini/gemini-cli/pull/21772)
|
||||
- feat(tracker): polish UI sorting and formatting by @anj-s in
|
||||
[#22437](https://github.com/google-gemini/gemini-cli/pull/22437)
|
||||
- Changelog for v0.34.0-preview.2 by @gemini-cli-robot in
|
||||
[#22220](https://github.com/google-gemini/gemini-cli/pull/22220)
|
||||
- fix(core): fix three JIT context bugs in read_file, read_many_files, and
|
||||
memoryDiscovery by @SandyTao520 in
|
||||
[#22679](https://github.com/google-gemini/gemini-cli/pull/22679)
|
||||
- refactor(core): introduce InjectionService with source-aware injection and
|
||||
backend-native background completions by @adamfweidman in
|
||||
[#22544](https://github.com/google-gemini/gemini-cli/pull/22544)
|
||||
- Linux sandbox bubblewrap by @DavidAPierce in
|
||||
[#22680](https://github.com/google-gemini/gemini-cli/pull/22680)
|
||||
- feat(core): increase thought signature retry resilience by @bdmorgan in
|
||||
[#22202](https://github.com/google-gemini/gemini-cli/pull/22202)
|
||||
- feat(core): implement Stage 2 security and consistency improvements for
|
||||
web_fetch by @aishaneeshah in
|
||||
[#22217](https://github.com/google-gemini/gemini-cli/pull/22217)
|
||||
- refactor(core): replace positional execute params with ExecuteOptions bag by
|
||||
@adamfweidman in
|
||||
[#22674](https://github.com/google-gemini/gemini-cli/pull/22674)
|
||||
- feat(config): enable JIT context loading by default by @SandyTao520 in
|
||||
[#22736](https://github.com/google-gemini/gemini-cli/pull/22736)
|
||||
- fix(config): ensure discoveryMaxDirs is passed to global config during
|
||||
initialization by @kevin-ramdass in
|
||||
[#22744](https://github.com/google-gemini/gemini-cli/pull/22744)
|
||||
- fix(plan): allowlist get_internal_docs in Plan Mode by @Adib234 in
|
||||
[#22668](https://github.com/google-gemini/gemini-cli/pull/22668)
|
||||
- Changelog for v0.34.0-preview.3 by @gemini-cli-robot in
|
||||
[#22393](https://github.com/google-gemini/gemini-cli/pull/22393)
|
||||
- feat(core): add foundation for subagent tool isolation by @akh64bit in
|
||||
[#22708](https://github.com/google-gemini/gemini-cli/pull/22708)
|
||||
- fix(core): handle surrogate pairs in truncateString by @sehoon38 in
|
||||
[#22754](https://github.com/google-gemini/gemini-cli/pull/22754)
|
||||
- fix(cli): override j/k navigation in settings dialog to fix search input
|
||||
conflict by @sehoon38 in
|
||||
[#22800](https://github.com/google-gemini/gemini-cli/pull/22800)
|
||||
- feat(plan): add 'All the above' option to multi-select AskUser questions by
|
||||
@Adib234 in [#22365](https://github.com/google-gemini/gemini-cli/pull/22365)
|
||||
- docs: distribute package-specific GEMINI.md context to each package by
|
||||
[#24174](https://github.com/google-gemini/gemini-cli/pull/24174)
|
||||
- Changelog for v0.39.0 by @gemini-cli-robot in
|
||||
[#25848](https://github.com/google-gemini/gemini-cli/pull/25848)
|
||||
- feat(memory): persist auto-memory scratchpad for skill extraction by
|
||||
@SandyTao520 in
|
||||
[#22734](https://github.com/google-gemini/gemini-cli/pull/22734)
|
||||
- fix(cli): clean up stale pasted placeholder metadata after word/line deletions
|
||||
by @Jomak-x in
|
||||
[#20375](https://github.com/google-gemini/gemini-cli/pull/20375)
|
||||
- refactor(core): align JIT memory placement with tiered context model by
|
||||
@SandyTao520 in
|
||||
[#22766](https://github.com/google-gemini/gemini-cli/pull/22766)
|
||||
- Linux sandbox seccomp by @DavidAPierce in
|
||||
[#22815](https://github.com/google-gemini/gemini-cli/pull/22815)
|
||||
- fix(patch): cherry-pick 4e5dfd0 to release/v0.35.0-preview.1-pr-23074 to patch
|
||||
version v0.35.0-preview.1 and create version 0.35.0-preview.2 by
|
||||
[#25873](https://github.com/google-gemini/gemini-cli/pull/25873)
|
||||
- fix(cli): add missing response key to custom theme text schema by @gaurav0107
|
||||
in [#25822](https://github.com/google-gemini/gemini-cli/pull/25822)
|
||||
- fix(cli): provide manual update command when automatic update fails by
|
||||
@cocosheng-g in
|
||||
[#26052](https://github.com/google-gemini/gemini-cli/pull/26052)
|
||||
- test(cli): add unit tests for restore ACP command (#23402) by @cocosheng-g in
|
||||
[#26053](https://github.com/google-gemini/gemini-cli/pull/26053)
|
||||
- fix(ui): better error messages for ECONNRESET and ETIMEDOUT by @devr0306 in
|
||||
[#26059](https://github.com/google-gemini/gemini-cli/pull/26059)
|
||||
- feat(core): wire up the new ContextManager and AgentChatHistory by @joshualitt
|
||||
in [#25409](https://github.com/google-gemini/gemini-cli/pull/25409)
|
||||
- fix(cli): ensure sandbox proxy cleanup and remove handler leaks by @ehedlund
|
||||
in [#26065](https://github.com/google-gemini/gemini-cli/pull/26065)
|
||||
- fix(cli): correct alternate buffer warning logic for JetBrains by @Adib234 in
|
||||
[#26067](https://github.com/google-gemini/gemini-cli/pull/26067)
|
||||
- fix(cli): make MCP ping optional in list command and use configured timeout by
|
||||
@cocosheng-g in
|
||||
[#26068](https://github.com/google-gemini/gemini-cli/pull/26068)
|
||||
- fix(core): better error message for failed cloudshell-gca auth by @devr0306 in
|
||||
[#26079](https://github.com/google-gemini/gemini-cli/pull/26079)
|
||||
- feat(cli): provide manual session UUID via command line arg by @cocosheng-g in
|
||||
[#26060](https://github.com/google-gemini/gemini-cli/pull/26060)
|
||||
- Changelog for v0.40.0-preview.2 by @gemini-cli-robot in
|
||||
[#25846](https://github.com/google-gemini/gemini-cli/pull/25846)
|
||||
- (docs) update sandboxing documentation by @g-samroberts in
|
||||
[#25930](https://github.com/google-gemini/gemini-cli/pull/25930)
|
||||
- fix(core): enforce parallel task tracker updates by @anj-s in
|
||||
[#24477](https://github.com/google-gemini/gemini-cli/pull/24477)
|
||||
- Update policy so transient errors are not marked terminal by @DavidAPierce in
|
||||
[#26066](https://github.com/google-gemini/gemini-cli/pull/26066)
|
||||
- Implement bot that performs time-series metric analysis and suggests repo
|
||||
management improvements by @gundermanc in
|
||||
[#25945](https://github.com/google-gemini/gemini-cli/pull/25945)
|
||||
- fix(core): handle non-string model flags in resolution by @Adib234 in
|
||||
[#26069](https://github.com/google-gemini/gemini-cli/pull/26069)
|
||||
- fix(ux): added error message for ENOTDIR by @devr0306 in
|
||||
[#26128](https://github.com/google-gemini/gemini-cli/pull/26128)
|
||||
- Changelog for v0.40.0-preview.3 by @gemini-cli-robot in
|
||||
[#25904](https://github.com/google-gemini/gemini-cli/pull/25904)
|
||||
- fix(cli): prevent ACP stdout pollution from SessionEnd hooks by @cocosheng-g
|
||||
in [#26125](https://github.com/google-gemini/gemini-cli/pull/26125)
|
||||
- feat(cli): support boolean and number casting for env vars in settings.json by
|
||||
@cocosheng-g in
|
||||
[#26118](https://github.com/google-gemini/gemini-cli/pull/26118)
|
||||
- fix(cli): preserve Request headers in DevTools activity logger by @Adib234 in
|
||||
[#26078](https://github.com/google-gemini/gemini-cli/pull/26078)
|
||||
- fix(patch): cherry-pick 2194da2 to release/v0.41.0-preview.0-pr-26153 to patch
|
||||
version v0.41.0-preview.0 and create version 0.41.0-preview.1 by
|
||||
@gemini-cli-robot in
|
||||
[#23134](https://github.com/google-gemini/gemini-cli/pull/23134)
|
||||
- fix(patch): cherry-pick daf3691 to release/v0.35.0-preview.2-pr-23558 to patch
|
||||
version v0.35.0-preview.2 and create version 0.35.0-preview.3 by
|
||||
[#26269](https://github.com/google-gemini/gemini-cli/pull/26269)
|
||||
- fix(patch): cherry-pick 1d72a12 to release/v0.41.0-preview.1-pr-26479 to patch
|
||||
version v0.41.0-preview.1 and create version 0.41.0-preview.2 by
|
||||
@gemini-cli-robot in
|
||||
[#23565](https://github.com/google-gemini/gemini-cli/pull/23565)
|
||||
- fix(patch): cherry-pick b2d6dc4 to release/v0.35.0-preview.4-pr-23546
|
||||
[CONFLICTS] by @gemini-cli-robot in
|
||||
[#23585](https://github.com/google-gemini/gemini-cli/pull/23585)
|
||||
[#26508](https://github.com/google-gemini/gemini-cli/pull/26508)
|
||||
- fix(patch): cherry-pick 7cc19c2 to release/v0.41.0-preview.2-pr-26507 to patch
|
||||
version v0.41.0-preview.2 and create version 0.41.0-preview.3 by
|
||||
@gemini-cli-robot in
|
||||
[#26530](https://github.com/google-gemini/gemini-cli/pull/26530)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.34.0...v0.35.2
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.40.1...v0.41.0
|
||||
|
||||
+227
-371
@@ -1,6 +1,6 @@
|
||||
# Preview release: v0.36.0-preview.5
|
||||
# Preview release: v0.42.0-preview.2
|
||||
|
||||
Released: March 27, 2026
|
||||
Released: May 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).
|
||||
@@ -13,377 +13,233 @@ npm install -g @google/gemini-cli@preview
|
||||
|
||||
## Highlights
|
||||
|
||||
- **Subagent Architecture Enhancements:** Significant updates to subagents,
|
||||
including local execution, tool isolation, multi-registry discovery, dynamic
|
||||
tool filtering, and JIT context injection.
|
||||
- **Enhanced Security & Sandboxing:** Implemented strict macOS sandboxing using
|
||||
Seatbelt allowlist, native Windows sandboxing, and support for
|
||||
"Write-Protected" governance files.
|
||||
- **Agent Context & State Management:** Introduced task tracker protocol
|
||||
integration, 'blocked' statuses for tasks/todos, and `AgentSession` for
|
||||
improved state management and replay semantics.
|
||||
- **Browser & ACP Capabilities:** Added privacy consent for the browser agent,
|
||||
sensitive action controls, improved API token usage metadata, and gateway auth
|
||||
support via ACP.
|
||||
- **CLI & UX Improvements:** Implemented a refreshed Composer layout, expanded
|
||||
terminal fallback warnings, dynamic model resolution, and Git worktree support
|
||||
for isolated parallel sessions.
|
||||
- **Auto Memory Enhancements:** Introduced an Auto Memory inbox flow with a
|
||||
canonical-patch contract for better memory management.
|
||||
- **Improved Voice Mode:** Added a wave animation, microphone icon updates, and
|
||||
privacy/compliance UX warnings for the Gemini Live backend.
|
||||
- **New CLI Commands & Flags:** Added a `--delete` flag to the `/exit` command
|
||||
for session deletion, a `list` subcommand to `/commands`, and a `/bug-memory`
|
||||
command for heap snapshots.
|
||||
- **Expanded Model Support:** Gemma 4 models are now enabled by default via the
|
||||
Gemini API.
|
||||
- **Enhanced Core Resilience:** Improved API resilience with reduced timeouts,
|
||||
automatic retries for stream errors, and better handling of invalid stream
|
||||
events.
|
||||
|
||||
## What's Changed
|
||||
|
||||
- fix(a2a-server): A2A server should execute ask policies in interactive mode by
|
||||
@kschaab in [#23831](https://github.com/google-gemini/gemini-cli/pull/23831)
|
||||
- docs(core): document agent_card_json string literal options for remote agents
|
||||
by @adamfweidman in
|
||||
[#23797](https://github.com/google-gemini/gemini-cli/pull/23797)
|
||||
- feat(core): support inline agentCardJson for remote agents by @adamfweidman in
|
||||
[#23743](https://github.com/google-gemini/gemini-cli/pull/23743)
|
||||
- fix(patch): cherry-pick 055ff92 to release/v0.36.0-preview.0-pr-23672 to patch
|
||||
version v0.36.0-preview.0 and create version 0.36.0-preview.1 by
|
||||
@gemini-cli-robot in
|
||||
[#23723](https://github.com/google-gemini/gemini-cli/pull/23723)
|
||||
- Changelog for v0.33.2 by @gemini-cli-robot in
|
||||
[#22730](https://github.com/google-gemini/gemini-cli/pull/22730)
|
||||
- feat(core): multi-registry architecture and tool filtering for subagents by
|
||||
@akh64bit in [#22712](https://github.com/google-gemini/gemini-cli/pull/22712)
|
||||
- Changelog for v0.34.0-preview.4 by @gemini-cli-robot in
|
||||
[#22752](https://github.com/google-gemini/gemini-cli/pull/22752)
|
||||
- fix(devtools): use theme-aware text colors for console warnings and errors by
|
||||
@SandyTao520 in
|
||||
[#22181](https://github.com/google-gemini/gemini-cli/pull/22181)
|
||||
- Add support for dynamic model Resolution to ModelConfigService by @kevinjwang1
|
||||
in [#22578](https://github.com/google-gemini/gemini-cli/pull/22578)
|
||||
- chore(release): bump version to 0.36.0-nightly.20260317.2f90b4653 by
|
||||
@gemini-cli-robot in
|
||||
[#22858](https://github.com/google-gemini/gemini-cli/pull/22858)
|
||||
- fix(cli): use active sessionId in useLogger and improve resume robustness by
|
||||
@mattKorwel in
|
||||
[#22606](https://github.com/google-gemini/gemini-cli/pull/22606)
|
||||
- fix(cli): expand tilde in policy paths from settings.json by @abhipatel12 in
|
||||
[#22772](https://github.com/google-gemini/gemini-cli/pull/22772)
|
||||
- fix(core): add actionable warnings for terminal fallbacks (#14426) by
|
||||
@spencer426 in
|
||||
[#22211](https://github.com/google-gemini/gemini-cli/pull/22211)
|
||||
- feat(tracker): integrate task tracker protocol into core system prompt by
|
||||
@anj-s in [#22442](https://github.com/google-gemini/gemini-cli/pull/22442)
|
||||
- chore: add posttest build hooks and fix missing dependencies by @NTaylorMullen
|
||||
in [#22865](https://github.com/google-gemini/gemini-cli/pull/22865)
|
||||
- feat(a2a): add agent acknowledgment command and enhance registry discovery by
|
||||
@alisa-alisa in
|
||||
[#22389](https://github.com/google-gemini/gemini-cli/pull/22389)
|
||||
- fix(cli): automatically add all VSCode workspace folders to Gemini context by
|
||||
@sakshisemalti in
|
||||
[#21380](https://github.com/google-gemini/gemini-cli/pull/21380)
|
||||
- feat: add 'blocked' status to tasks and todos by @anj-s in
|
||||
[#22735](https://github.com/google-gemini/gemini-cli/pull/22735)
|
||||
- refactor(cli): remove extra newlines in ShellToolMessage.tsx by @NTaylorMullen
|
||||
in [#22868](https://github.com/google-gemini/gemini-cli/pull/22868)
|
||||
- fix(cli): lazily load settings in onModelChange to prevent stale closure data
|
||||
loss by @KumarADITHYA123 in
|
||||
[#20403](https://github.com/google-gemini/gemini-cli/pull/20403)
|
||||
- feat(core): subagent local execution and tool isolation by @akh64bit in
|
||||
[#22718](https://github.com/google-gemini/gemini-cli/pull/22718)
|
||||
- fix(cli): resolve subagent grouping and UI state persistence by @abhipatel12
|
||||
in [#22252](https://github.com/google-gemini/gemini-cli/pull/22252)
|
||||
- refactor(ui): extract SessionBrowser search and navigation components by
|
||||
@abhipatel12 in
|
||||
[#22377](https://github.com/google-gemini/gemini-cli/pull/22377)
|
||||
- fix: updates Docker image reference for GitHub MCP server by @jhhornn in
|
||||
[#22938](https://github.com/google-gemini/gemini-cli/pull/22938)
|
||||
- refactor(cli): group subagent trajectory deletion and use native filesystem
|
||||
testing by @abhipatel12 in
|
||||
[#22890](https://github.com/google-gemini/gemini-cli/pull/22890)
|
||||
- refactor(cli): simplify keypress and mouse providers and update tests by
|
||||
@scidomino in [#22853](https://github.com/google-gemini/gemini-cli/pull/22853)
|
||||
- Changelog for v0.34.0 by @gemini-cli-robot in
|
||||
[#22860](https://github.com/google-gemini/gemini-cli/pull/22860)
|
||||
- test(cli): simplify createMockSettings calls by @scidomino in
|
||||
[#22952](https://github.com/google-gemini/gemini-cli/pull/22952)
|
||||
- feat(ui): format multi-line banner warnings with a bold title by @keithguerin
|
||||
in [#22955](https://github.com/google-gemini/gemini-cli/pull/22955)
|
||||
- Docs: Remove references to stale Gemini CLI file structure info by
|
||||
@g-samroberts in
|
||||
[#22976](https://github.com/google-gemini/gemini-cli/pull/22976)
|
||||
- feat(ui): remove write todo list tool from UI tips by @aniruddhaadak80 in
|
||||
[#22281](https://github.com/google-gemini/gemini-cli/pull/22281)
|
||||
- Fix issue where subagent thoughts are appended. by @gundermanc in
|
||||
[#22975](https://github.com/google-gemini/gemini-cli/pull/22975)
|
||||
- Feat/browser privacy consent by @kunal-10-cloud in
|
||||
[#21119](https://github.com/google-gemini/gemini-cli/pull/21119)
|
||||
- fix(core): explicitly map execution context in LocalAgentExecutor by @akh64bit
|
||||
in [#22949](https://github.com/google-gemini/gemini-cli/pull/22949)
|
||||
- feat(plan): support plan mode in non-interactive mode by @ruomengz in
|
||||
[#22670](https://github.com/google-gemini/gemini-cli/pull/22670)
|
||||
- feat(core): implement strict macOS sandboxing using Seatbelt allowlist by
|
||||
@ehedlund in [#22832](https://github.com/google-gemini/gemini-cli/pull/22832)
|
||||
- docs: add additional notes by @abhipatel12 in
|
||||
[#23008](https://github.com/google-gemini/gemini-cli/pull/23008)
|
||||
- fix(cli): resolve duplicate footer on tool cancel via ESC (#21743) by
|
||||
@ruomengz in [#21781](https://github.com/google-gemini/gemini-cli/pull/21781)
|
||||
- Changelog for v0.35.0-preview.1 by @gemini-cli-robot in
|
||||
[#23012](https://github.com/google-gemini/gemini-cli/pull/23012)
|
||||
- fix(ui): fix flickering on small terminal heights by @devr0306 in
|
||||
[#21416](https://github.com/google-gemini/gemini-cli/pull/21416)
|
||||
- fix(acp): provide more meta in tool_call_update by @Mervap in
|
||||
[#22663](https://github.com/google-gemini/gemini-cli/pull/22663)
|
||||
- docs: add FAQ entry for checking Gemini CLI version by @surajsahani in
|
||||
[#21271](https://github.com/google-gemini/gemini-cli/pull/21271)
|
||||
- feat(core): resilient subagent tool rejection with contextual feedback by
|
||||
@abhipatel12 in
|
||||
[#22951](https://github.com/google-gemini/gemini-cli/pull/22951)
|
||||
- fix(cli): correctly handle auto-update for standalone binaries by @bdmorgan in
|
||||
[#23038](https://github.com/google-gemini/gemini-cli/pull/23038)
|
||||
- feat(core): add content-utils by @adamfweidman in
|
||||
[#22984](https://github.com/google-gemini/gemini-cli/pull/22984)
|
||||
- fix: circumvent genai sdk requirement for api key when using gateway auth via
|
||||
ACP by @sripasg in
|
||||
[#23042](https://github.com/google-gemini/gemini-cli/pull/23042)
|
||||
- fix(core): don't persist browser consent sentinel in non-interactive mode by
|
||||
@jasonmatthewsuhari in
|
||||
[#23073](https://github.com/google-gemini/gemini-cli/pull/23073)
|
||||
- fix(core): narrow browser agent description to prevent stealing URL tasks from
|
||||
web_fetch by @gsquared94 in
|
||||
[#23086](https://github.com/google-gemini/gemini-cli/pull/23086)
|
||||
- feat(cli): Partial threading of AgentLoopContext. by @joshualitt in
|
||||
[#22978](https://github.com/google-gemini/gemini-cli/pull/22978)
|
||||
- fix(browser-agent): enable "Allow all server tools" session policy by
|
||||
@cynthialong0-0 in
|
||||
[#22343](https://github.com/google-gemini/gemini-cli/pull/22343)
|
||||
- refactor(cli): integrate real config loading into async test utils by
|
||||
@scidomino in [#23040](https://github.com/google-gemini/gemini-cli/pull/23040)
|
||||
- feat(core): inject memory and JIT context into subagents by @abhipatel12 in
|
||||
[#23032](https://github.com/google-gemini/gemini-cli/pull/23032)
|
||||
- Fix logging and virtual list. by @jacob314 in
|
||||
[#23080](https://github.com/google-gemini/gemini-cli/pull/23080)
|
||||
- feat(core): cap JIT context upward traversal at git root by @SandyTao520 in
|
||||
[#23074](https://github.com/google-gemini/gemini-cli/pull/23074)
|
||||
- Docs: Minor style updates from initial docs audit. by @g-samroberts in
|
||||
[#22872](https://github.com/google-gemini/gemini-cli/pull/22872)
|
||||
- feat(core): add experimental memory manager agent to replace save_memory tool
|
||||
by @SandyTao520 in
|
||||
[#22726](https://github.com/google-gemini/gemini-cli/pull/22726)
|
||||
- Changelog for v0.35.0-preview.2 by @gemini-cli-robot in
|
||||
[#23142](https://github.com/google-gemini/gemini-cli/pull/23142)
|
||||
- Update website issue template for label and title by @g-samroberts in
|
||||
[#23036](https://github.com/google-gemini/gemini-cli/pull/23036)
|
||||
- fix: upgrade ACP SDK from 0.12 to 0.16.1 by @sripasg in
|
||||
[#23132](https://github.com/google-gemini/gemini-cli/pull/23132)
|
||||
- Update callouts to work on github. by @g-samroberts in
|
||||
[#22245](https://github.com/google-gemini/gemini-cli/pull/22245)
|
||||
- feat: ACP: Add token usage metadata to the `send` method's return value by
|
||||
@sripasg in [#23148](https://github.com/google-gemini/gemini-cli/pull/23148)
|
||||
- fix(plan): clarify that plan mode policies are combined with normal mode by
|
||||
@ruomengz in [#23158](https://github.com/google-gemini/gemini-cli/pull/23158)
|
||||
- Add ModelChain support to ModelConfigService and make ModelDialog dynamic by
|
||||
@kevinjwang1 in
|
||||
[#22914](https://github.com/google-gemini/gemini-cli/pull/22914)
|
||||
- Ensure that copied extensions are writable in the user's local directory by
|
||||
@kevinjwang1 in
|
||||
[#23016](https://github.com/google-gemini/gemini-cli/pull/23016)
|
||||
- feat(core): implement native Windows sandboxing by @mattKorwel in
|
||||
[#21807](https://github.com/google-gemini/gemini-cli/pull/21807)
|
||||
- feat(core): add support for admin-forced MCP server installations by
|
||||
@gsquared94 in
|
||||
[#23163](https://github.com/google-gemini/gemini-cli/pull/23163)
|
||||
- chore(lint): ignore .gemini directory and recursive node_modules by
|
||||
@mattKorwel in
|
||||
[#23211](https://github.com/google-gemini/gemini-cli/pull/23211)
|
||||
- feat(cli): conditionally exclude ask_user tool in ACP mode by @nmcnamara-eng
|
||||
in [#23045](https://github.com/google-gemini/gemini-cli/pull/23045)
|
||||
- feat(core): introduce AgentSession and rename stream events to agent events by
|
||||
@mbleigh in [#23159](https://github.com/google-gemini/gemini-cli/pull/23159)
|
||||
- feat(worktree): add Git worktree support for isolated parallel sessions by
|
||||
@jerop in [#22973](https://github.com/google-gemini/gemini-cli/pull/22973)
|
||||
- Add support for linking in the extension registry by @kevinjwang1 in
|
||||
[#23153](https://github.com/google-gemini/gemini-cli/pull/23153)
|
||||
- feat(extensions): add --skip-settings flag to install command by @Ratish1 in
|
||||
[#17212](https://github.com/google-gemini/gemini-cli/pull/17212)
|
||||
- feat(telemetry): track if session is running in a Git worktree by @jerop in
|
||||
[#23265](https://github.com/google-gemini/gemini-cli/pull/23265)
|
||||
- refactor(core): use absolute paths in GEMINI.md context markers by
|
||||
@SandyTao520 in
|
||||
[#23135](https://github.com/google-gemini/gemini-cli/pull/23135)
|
||||
- fix(core): add sanitization to sub agent thoughts and centralize utilities by
|
||||
@devr0306 in [#22828](https://github.com/google-gemini/gemini-cli/pull/22828)
|
||||
- feat(core): refine User-Agent for VS Code traffic (unified format) by
|
||||
@sehoon38 in [#23256](https://github.com/google-gemini/gemini-cli/pull/23256)
|
||||
- Fix schema for ModelChains by @kevinjwang1 in
|
||||
[#23284](https://github.com/google-gemini/gemini-cli/pull/23284)
|
||||
- test(cli): refactor tests for async render utilities by @scidomino in
|
||||
[#23252](https://github.com/google-gemini/gemini-cli/pull/23252)
|
||||
- feat(core): add security prompt for browser agent by @cynthialong0-0 in
|
||||
[#23241](https://github.com/google-gemini/gemini-cli/pull/23241)
|
||||
- refactor(ide): replace dynamic undici import with static fetch import by
|
||||
@cocosheng-g in
|
||||
[#23268](https://github.com/google-gemini/gemini-cli/pull/23268)
|
||||
- test(cli): address unresolved feedback from PR #23252 by @scidomino in
|
||||
[#23303](https://github.com/google-gemini/gemini-cli/pull/23303)
|
||||
- feat(browser): add sensitive action controls and read-only noise reduction by
|
||||
@cynthialong0-0 in
|
||||
[#22867](https://github.com/google-gemini/gemini-cli/pull/22867)
|
||||
- Disabling failing test while investigating by @alisa-alisa in
|
||||
[#23311](https://github.com/google-gemini/gemini-cli/pull/23311)
|
||||
- fix broken extension link in hooks guide by @Indrapal-70 in
|
||||
[#21728](https://github.com/google-gemini/gemini-cli/pull/21728)
|
||||
- fix(core): fix agent description indentation by @abhipatel12 in
|
||||
[#23315](https://github.com/google-gemini/gemini-cli/pull/23315)
|
||||
- Wrap the text under TOML rule for easier readability in policy-engine.md… by
|
||||
@CogitationOps in
|
||||
[#23076](https://github.com/google-gemini/gemini-cli/pull/23076)
|
||||
- fix(extensions): revert broken extension removal behavior by @ehedlund in
|
||||
[#23317](https://github.com/google-gemini/gemini-cli/pull/23317)
|
||||
- feat(core): set up onboarding telemetry by @yunaseoul in
|
||||
[#23118](https://github.com/google-gemini/gemini-cli/pull/23118)
|
||||
- Retry evals on API error. by @gundermanc in
|
||||
[#23322](https://github.com/google-gemini/gemini-cli/pull/23322)
|
||||
- fix(evals): remove tool restrictions and add compile-time guards by
|
||||
@SandyTao520 in
|
||||
[#23312](https://github.com/google-gemini/gemini-cli/pull/23312)
|
||||
- fix(hooks): support 'ask' decision for BeforeTool hooks by @gundermanc in
|
||||
[#21146](https://github.com/google-gemini/gemini-cli/pull/21146)
|
||||
- feat(browser): add warning message for session mode 'existing' by
|
||||
@cynthialong0-0 in
|
||||
[#23288](https://github.com/google-gemini/gemini-cli/pull/23288)
|
||||
- chore(lint): enforce zero warnings and cleanup syntax restrictions by
|
||||
@alisa-alisa in
|
||||
[#22902](https://github.com/google-gemini/gemini-cli/pull/22902)
|
||||
- fix(cli): add Esc instruction to HooksDialog footer by @abhipatel12 in
|
||||
[#23258](https://github.com/google-gemini/gemini-cli/pull/23258)
|
||||
- Disallow and suppress misused spread operator. by @gundermanc in
|
||||
[#23294](https://github.com/google-gemini/gemini-cli/pull/23294)
|
||||
- fix(core): refine CliHelpAgent description for better delegation by
|
||||
@abhipatel12 in
|
||||
[#23310](https://github.com/google-gemini/gemini-cli/pull/23310)
|
||||
- fix(core): enable global session and persistent approval for web_fetch by
|
||||
@NTaylorMullen in
|
||||
[#23295](https://github.com/google-gemini/gemini-cli/pull/23295)
|
||||
- fix(plan): add state transition override to prevent plan mode freeze by
|
||||
@Adib234 in [#23020](https://github.com/google-gemini/gemini-cli/pull/23020)
|
||||
- fix(cli): record skill activation tool calls in chat history by @NTaylorMullen
|
||||
in [#23203](https://github.com/google-gemini/gemini-cli/pull/23203)
|
||||
- fix(core): ensure subagent tool updates apply configuration overrides
|
||||
immediately by @abhipatel12 in
|
||||
[#23161](https://github.com/google-gemini/gemini-cli/pull/23161)
|
||||
- fix(cli): resolve flicker at boundaries of list in BaseSelectionList by
|
||||
@jackwotherspoon in
|
||||
[#23298](https://github.com/google-gemini/gemini-cli/pull/23298)
|
||||
- test(cli): force generic terminal in tests to fix snapshot failures by
|
||||
@abhipatel12 in
|
||||
[#23499](https://github.com/google-gemini/gemini-cli/pull/23499)
|
||||
- Evals: PR Guidance adding workflow by @alisa-alisa in
|
||||
[#23164](https://github.com/google-gemini/gemini-cli/pull/23164)
|
||||
- feat(core): refactor SandboxManager to a stateless architecture and introduce
|
||||
explicit Deny interface by @ehedlund in
|
||||
[#23141](https://github.com/google-gemini/gemini-cli/pull/23141)
|
||||
- feat(core): add event-translator and update agent types by @adamfweidman in
|
||||
[#22985](https://github.com/google-gemini/gemini-cli/pull/22985)
|
||||
- perf(cli): parallelize and background startup cleanup tasks by @sehoon38 in
|
||||
[#23545](https://github.com/google-gemini/gemini-cli/pull/23545)
|
||||
- fix: "allow always" for commands with paths by @scidomino in
|
||||
[#23558](https://github.com/google-gemini/gemini-cli/pull/23558)
|
||||
- fix(cli): prevent terminal escape sequences from leaking on exit by
|
||||
@mattKorwel in
|
||||
[#22682](https://github.com/google-gemini/gemini-cli/pull/22682)
|
||||
- feat(cli): implement full "GEMINI CLI" logo for logged-out state by
|
||||
@keithguerin in
|
||||
[#22412](https://github.com/google-gemini/gemini-cli/pull/22412)
|
||||
- fix(plan): reserve minimum height for selection list in AskUserDialog by
|
||||
@ruomengz in [#23280](https://github.com/google-gemini/gemini-cli/pull/23280)
|
||||
- fix(core): harden AgentSession replay semantics by @adamfweidman in
|
||||
[#23548](https://github.com/google-gemini/gemini-cli/pull/23548)
|
||||
- test(core): migrate hook tests to scheduler by @abhipatel12 in
|
||||
[#23496](https://github.com/google-gemini/gemini-cli/pull/23496)
|
||||
- chore(config): disable agents by default by @abhipatel12 in
|
||||
[#23546](https://github.com/google-gemini/gemini-cli/pull/23546)
|
||||
- fix(ui): make tool confirmations take up entire terminal height by @devr0306
|
||||
in [#22366](https://github.com/google-gemini/gemini-cli/pull/22366)
|
||||
- fix(core): prevent redundant remote agent loading on model switch by
|
||||
@adamfweidman in
|
||||
[#23576](https://github.com/google-gemini/gemini-cli/pull/23576)
|
||||
- refactor(core): update production type imports from coreToolScheduler by
|
||||
@abhipatel12 in
|
||||
[#23498](https://github.com/google-gemini/gemini-cli/pull/23498)
|
||||
- feat(cli): always prefix extension skills with colon separator by
|
||||
@NTaylorMullen in
|
||||
[#23566](https://github.com/google-gemini/gemini-cli/pull/23566)
|
||||
- fix(core): properly support allowRedirect in policy engine by @scidomino in
|
||||
[#23579](https://github.com/google-gemini/gemini-cli/pull/23579)
|
||||
- fix(cli): prevent subcommand shadowing and skip auth for commands by
|
||||
@mattKorwel in
|
||||
[#23177](https://github.com/google-gemini/gemini-cli/pull/23177)
|
||||
- fix(test): move flaky tests to non-blocking suite by @mattKorwel in
|
||||
[#23259](https://github.com/google-gemini/gemini-cli/pull/23259)
|
||||
- Changelog for v0.35.0-preview.3 by @gemini-cli-robot in
|
||||
[#23574](https://github.com/google-gemini/gemini-cli/pull/23574)
|
||||
- feat(skills): add behavioral-evals skill with fixing and promoting guides by
|
||||
@abhipatel12 in
|
||||
[#23349](https://github.com/google-gemini/gemini-cli/pull/23349)
|
||||
- refactor(core): delete obsolete coreToolScheduler by @abhipatel12 in
|
||||
[#23502](https://github.com/google-gemini/gemini-cli/pull/23502)
|
||||
- Changelog for v0.35.0-preview.4 by @gemini-cli-robot in
|
||||
[#23581](https://github.com/google-gemini/gemini-cli/pull/23581)
|
||||
- feat(core): add LegacyAgentSession by @adamfweidman in
|
||||
[#22986](https://github.com/google-gemini/gemini-cli/pull/22986)
|
||||
- feat(test-utils): add TestMcpServerBuilder and support in TestRig by
|
||||
@abhipatel12 in
|
||||
[#23491](https://github.com/google-gemini/gemini-cli/pull/23491)
|
||||
- fix(core)!: Force policy config to specify toolName by @kschaab in
|
||||
[#23330](https://github.com/google-gemini/gemini-cli/pull/23330)
|
||||
- eval(save_memory): add multi-turn interactive evals for memoryManager by
|
||||
@SandyTao520 in
|
||||
[#23572](https://github.com/google-gemini/gemini-cli/pull/23572)
|
||||
- fix(telemetry): patch memory leak and enforce logPrompts privacy by
|
||||
@spencer426 in
|
||||
[#23281](https://github.com/google-gemini/gemini-cli/pull/23281)
|
||||
- perf(cli): background IDE client to speed up initialization by @sehoon38 in
|
||||
[#23603](https://github.com/google-gemini/gemini-cli/pull/23603)
|
||||
- fix(cli): prevent Ctrl+D exit when input buffer is not empty by @wtanaka in
|
||||
[#23306](https://github.com/google-gemini/gemini-cli/pull/23306)
|
||||
- fix: ACP: separate conversational text from execute tool command title by
|
||||
@sripasg in [#23179](https://github.com/google-gemini/gemini-cli/pull/23179)
|
||||
- feat(evals): add behavioral evaluations for subagent routing by @Samee24 in
|
||||
[#23272](https://github.com/google-gemini/gemini-cli/pull/23272)
|
||||
- refactor(cli,core): foundational layout, identity management, and type safety
|
||||
by @jwhelangoog in
|
||||
[#23286](https://github.com/google-gemini/gemini-cli/pull/23286)
|
||||
- fix(core): accurately reflect subagent tool failure in UI by @abhipatel12 in
|
||||
[#23187](https://github.com/google-gemini/gemini-cli/pull/23187)
|
||||
- Changelog for v0.35.0-preview.5 by @gemini-cli-robot in
|
||||
[#23606](https://github.com/google-gemini/gemini-cli/pull/23606)
|
||||
- feat(ui): implement refreshed UX for Composer layout by @jwhelangoog in
|
||||
[#21212](https://github.com/google-gemini/gemini-cli/pull/21212)
|
||||
- fix: API key input dialog user interaction when selected Gemini API Key by
|
||||
@kartikangiras in
|
||||
[#21057](https://github.com/google-gemini/gemini-cli/pull/21057)
|
||||
- docs: update `/mcp refresh` to `/mcp reload` by @adamfweidman in
|
||||
[#23631](https://github.com/google-gemini/gemini-cli/pull/23631)
|
||||
- Implementation of sandbox "Write-Protected" Governance Files by @DavidAPierce
|
||||
in [#23139](https://github.com/google-gemini/gemini-cli/pull/23139)
|
||||
- feat(sandbox): dynamic macOS sandbox expansion and worktree support by @galz10
|
||||
in [#23301](https://github.com/google-gemini/gemini-cli/pull/23301)
|
||||
- fix(acp): Pass the cwd to `AcpFileSystemService` to avoid looping failures in
|
||||
asking for perms to write plan md file by @sripasg in
|
||||
[#23612](https://github.com/google-gemini/gemini-cli/pull/23612)
|
||||
- fix(plan): sandbox path resolution in Plan Mode to prevent hallucinations by
|
||||
@Adib234 in [#22737](https://github.com/google-gemini/gemini-cli/pull/22737)
|
||||
- feat(ui): allow immediate user input during startup by @sehoon38 in
|
||||
[#23661](https://github.com/google-gemini/gemini-cli/pull/23661)
|
||||
- refactor(sandbox): reorganize Windows sandbox files by @galz10 in
|
||||
[#23645](https://github.com/google-gemini/gemini-cli/pull/23645)
|
||||
- fix(core): improve remote agent streaming UI and UX by @adamfweidman in
|
||||
[#23633](https://github.com/google-gemini/gemini-cli/pull/23633)
|
||||
- perf(cli): optimize --version startup time by @sehoon38 in
|
||||
[#23671](https://github.com/google-gemini/gemini-cli/pull/23671)
|
||||
- refactor(core): stop gemini CLI from producing unsafe casts by @gundermanc in
|
||||
[#23611](https://github.com/google-gemini/gemini-cli/pull/23611)
|
||||
- use enableAutoUpdate in test rig by @scidomino in
|
||||
[#23681](https://github.com/google-gemini/gemini-cli/pull/23681)
|
||||
- feat(core): change user-facing auth type from oauth2 to oauth by @adamfweidman
|
||||
in [#23639](https://github.com/google-gemini/gemini-cli/pull/23639)
|
||||
- chore(deps): fix npm audit vulnerabilities by @scidomino in
|
||||
[#23679](https://github.com/google-gemini/gemini-cli/pull/23679)
|
||||
- test(evals): fix overlapping act() deadlock in app-test-helper by @Adib234 in
|
||||
[#23666](https://github.com/google-gemini/gemini-cli/pull/23666)
|
||||
- fix(cli): prevent automatic updates from switching to less stable channels in
|
||||
[#26132](https://github.com/google-gemini/gemini-cli/pull/26132)
|
||||
- chore(release): bump version to 0.42.0-nightly.20260428.g59b2dea0e in
|
||||
[#26142](https://github.com/google-gemini/gemini-cli/pull/26142)
|
||||
- fix(cli): pass node arguments via NODE_OPTIONS during relaunch to support SEA
|
||||
in [#26130](https://github.com/google-gemini/gemini-cli/pull/26130)
|
||||
- fix(cli): handle DECKPAM keypad Enter sequences in terminal in
|
||||
[#26092](https://github.com/google-gemini/gemini-cli/pull/26092)
|
||||
- docs(cli): point plan-mode session retention to actual /settings labels in
|
||||
[#25978](https://github.com/google-gemini/gemini-cli/pull/25978)
|
||||
- fix(core): add missing oauth fields support in subagent parsing in
|
||||
[#26141](https://github.com/google-gemini/gemini-cli/pull/26141)
|
||||
- fix(core): disconnect extension-backed MCP clients in stopExtension in
|
||||
[#26136](https://github.com/google-gemini/gemini-cli/pull/26136)
|
||||
- Update documentation workflows with workspace trust in
|
||||
[#26150](https://github.com/google-gemini/gemini-cli/pull/26150)
|
||||
- refactor(acp): modularize monolithic acpClient into specialized files in
|
||||
[#26143](https://github.com/google-gemini/gemini-cli/pull/26143)
|
||||
- test: fix failures due to antigravity environment leakage in
|
||||
[#26162](https://github.com/google-gemini/gemini-cli/pull/26162)
|
||||
- fix(core): add explicit empty log guard in A2A pushMessage in
|
||||
[#26198](https://github.com/google-gemini/gemini-cli/pull/26198)
|
||||
- feat(cli): add --delete flag to /exit command for session deletion in
|
||||
[#19332](https://github.com/google-gemini/gemini-cli/pull/19332)
|
||||
- test(core): add regression test for issue for ToolConfirmationResponse in
|
||||
[#26194](https://github.com/google-gemini/gemini-cli/pull/26194)
|
||||
- Add the ability to @ mention the gemini robot. in
|
||||
[#26207](https://github.com/google-gemini/gemini-cli/pull/26207)
|
||||
- test(evals): add EvalMetadata JSDoc annotations to older tests in
|
||||
[#26147](https://github.com/google-gemini/gemini-cli/pull/26147)
|
||||
- fix(core): reduce default API timeout to 60s and enable retries for undici
|
||||
timeouts in [#26191](https://github.com/google-gemini/gemini-cli/pull/26191)
|
||||
- fix(core): distinguish fallback chains and fix maxAttempts for auto vs
|
||||
explicit model selection in
|
||||
[#26163](https://github.com/google-gemini/gemini-cli/pull/26163)
|
||||
- fix(cli): handle InvalidStream event gracefully without throwing in
|
||||
[#26218](https://github.com/google-gemini/gemini-cli/pull/26218)
|
||||
- ci(github-actions): switch to github app token and fix bot self-trigger in
|
||||
[#26223](https://github.com/google-gemini/gemini-cli/pull/26223)
|
||||
- Respect logPrompts flag for logging sensitive fields in
|
||||
[#26153](https://github.com/google-gemini/gemini-cli/pull/26153)
|
||||
- fix: correct API key validation logic in handleApiKeySubmit in
|
||||
[#25453](https://github.com/google-gemini/gemini-cli/pull/25453)
|
||||
- fix(agent): prevent exit_plan_mode from being called via shell in
|
||||
[#26230](https://github.com/google-gemini/gemini-cli/pull/26230)
|
||||
- # Fix: Inconsistent Case-Sensitivity in GrepTool in [#26235](https://github.com/google-gemini/gemini-cli/pull/26235)
|
||||
- docs(core): add automated gemma setup guide in
|
||||
[#26233](https://github.com/google-gemini/gemini-cli/pull/26233)
|
||||
- Allow non-https proxy urls to support container environments in
|
||||
[#26234](https://github.com/google-gemini/gemini-cli/pull/26234)
|
||||
- fix(bot): productivity and backlog optimizations in
|
||||
[#26236](https://github.com/google-gemini/gemini-cli/pull/26236)
|
||||
- refactor(acp): delegate prompt turn processing logic to GeminiClient in
|
||||
[#26222](https://github.com/google-gemini/gemini-cli/pull/26222)
|
||||
- fix(cli): refine platform-specific undo/redo and smart bubbling for WSL in
|
||||
[#26202](https://github.com/google-gemini/gemini-cli/pull/26202)
|
||||
- fix: suppress duplicate extension warnings during startup in
|
||||
[#26208](https://github.com/google-gemini/gemini-cli/pull/26208)
|
||||
- fix(cli): use byte length instead of string length for readStdin size limits
|
||||
in [#26224](https://github.com/google-gemini/gemini-cli/pull/26224)
|
||||
- fix(ui): made shell tool header wrap on Ctrl+O in
|
||||
[#26229](https://github.com/google-gemini/gemini-cli/pull/26229)
|
||||
- Changelog for v0.41.0-preview.0 in
|
||||
[#26244](https://github.com/google-gemini/gemini-cli/pull/26244)
|
||||
- Skip binary CLI relaunch in
|
||||
[#26261](https://github.com/google-gemini/gemini-cli/pull/26261)
|
||||
- fix(cli): do not override GOOGLE_CLOUD_PROJECT in Cloud Shell when using
|
||||
Vertex AI in [#24455](https://github.com/google-gemini/gemini-cli/pull/24455)
|
||||
- docs(cli): add skill discovery troubleshooting checklist to tutorial in
|
||||
[#26018](https://github.com/google-gemini/gemini-cli/pull/26018)
|
||||
- docs(policy-engine): link to tools reference for tool names and args in
|
||||
[#22081](https://github.com/google-gemini/gemini-cli/pull/22081)
|
||||
- Fix posting invalid response to a comment in
|
||||
[#26266](https://github.com/google-gemini/gemini-cli/pull/26266)
|
||||
- fix(cli): prevent informational logs from polluting json output in
|
||||
[#26264](https://github.com/google-gemini/gemini-cli/pull/26264)
|
||||
- feat(ui): added microphone and updated placeholder for voice mode in
|
||||
[#26270](https://github.com/google-gemini/gemini-cli/pull/26270)
|
||||
- feat(cli): Add 'list' subcommand to '/commands' in
|
||||
[#22324](https://github.com/google-gemini/gemini-cli/pull/22324)
|
||||
- fix(core): ensure tool output cleanup on session deletion for legacy files in
|
||||
[#26263](https://github.com/google-gemini/gemini-cli/pull/26263)
|
||||
- Docs: Update Agent Skills documentation in
|
||||
[#22388](https://github.com/google-gemini/gemini-cli/pull/22388)
|
||||
- test(acp): add missing coverage for extensions command error paths in
|
||||
[#25313](https://github.com/google-gemini/gemini-cli/pull/25313)
|
||||
- Changelog for v0.40.0 in
|
||||
[#26245](https://github.com/google-gemini/gemini-cli/pull/26245)
|
||||
- fix: report AgentExecutionBlocked in non-interactive programmatic modes in
|
||||
[#26262](https://github.com/google-gemini/gemini-cli/pull/26262)
|
||||
- feat(extensions): add 'delete' as an alias for /extensions uninstall in
|
||||
[#25660](https://github.com/google-gemini/gemini-cli/pull/25660)
|
||||
- fix(core): silently skip GEMINI.md paths that are directories (EISDIR) in
|
||||
[#25662](https://github.com/google-gemini/gemini-cli/pull/25662)
|
||||
- fix(ci): checkout PR branch instead of main in bot workflow in
|
||||
[#26289](https://github.com/google-gemini/gemini-cli/pull/26289)
|
||||
- fix(cli): use resolved sandbox state for auto-update check in
|
||||
[#26285](https://github.com/google-gemini/gemini-cli/pull/26285)
|
||||
- # Metrics Integrity & Standardized Reporting (BT-01) in [#26240](https://github.com/google-gemini/gemini-cli/pull/26240)
|
||||
- Add Star History section to README in
|
||||
[#26290](https://github.com/google-gemini/gemini-cli/pull/26290)
|
||||
- Add Star History section to README in
|
||||
[#26308](https://github.com/google-gemini/gemini-cli/pull/26308)
|
||||
- Remove Star History section from README in
|
||||
[#26309](https://github.com/google-gemini/gemini-cli/pull/26309)
|
||||
- test(evals): add behavioral eval for file creation and write_file tool
|
||||
selection in [#26292](https://github.com/google-gemini/gemini-cli/pull/26292)
|
||||
- feat(config): enable Gemma 4 models by default via Gemini API in
|
||||
[#26307](https://github.com/google-gemini/gemini-cli/pull/26307)
|
||||
- fix(cli): insert voice transcription at cursor position instead of ap… in
|
||||
[#26287](https://github.com/google-gemini/gemini-cli/pull/26287)
|
||||
- fix(ui): fix issue with box edges in
|
||||
[#26148](https://github.com/google-gemini/gemini-cli/pull/26148)
|
||||
- fix(cli): respect .env override for GOOGLE_CLOUD_PROJECT in
|
||||
[#26288](https://github.com/google-gemini/gemini-cli/pull/26288)
|
||||
- fix(ci): robust version checking in release verification in
|
||||
[#26337](https://github.com/google-gemini/gemini-cli/pull/26337)
|
||||
- fix(cli): enable daemon relaunch in binary and bundle keytar in
|
||||
[#26333](https://github.com/google-gemini/gemini-cli/pull/26333)
|
||||
- fix(core): discourage unprompted git add . in prompt snippets in
|
||||
[#26220](https://github.com/google-gemini/gemini-cli/pull/26220)
|
||||
- feat(ui): added wave animation for voice mode in
|
||||
[#26284](https://github.com/google-gemini/gemini-cli/pull/26284)
|
||||
- fix(cli): prevent Escape from clearing input buffer (#17083) in
|
||||
[#26339](https://github.com/google-gemini/gemini-cli/pull/26339)
|
||||
- fix(cli): undeprecate --prompt and correct positional query docs in
|
||||
[#26329](https://github.com/google-gemini/gemini-cli/pull/26329)
|
||||
- Metrics updates in
|
||||
[#26348](https://github.com/google-gemini/gemini-cli/pull/26348)
|
||||
- fix(core): remove "System: Please continue." injection on InvalidStream events
|
||||
in [#26340](https://github.com/google-gemini/gemini-cli/pull/26340)
|
||||
- docs(policy-engine): add tool argument keys reference and shell policy
|
||||
cross-links in
|
||||
[#25292](https://github.com/google-gemini/gemini-cli/pull/25292)
|
||||
- fix(cli): resolve Ghostty/raw-mode False Cancellation in oauth flow in
|
||||
[#25026](https://github.com/google-gemini/gemini-cli/pull/25026)
|
||||
- fix(core): reset session-scoped state on resumption in
|
||||
[#26342](https://github.com/google-gemini/gemini-cli/pull/26342)
|
||||
- Fix bulk of remaining issues with generalist profile in
|
||||
[#26073](https://github.com/google-gemini/gemini-cli/pull/26073)
|
||||
- fix(core): make subagents aware of active approval modes in
|
||||
[#23608](https://github.com/google-gemini/gemini-cli/pull/23608)
|
||||
- fix(acp): resolve agent mode disconnect and improve mode awareness in
|
||||
[#26332](https://github.com/google-gemini/gemini-cli/pull/26332)
|
||||
- docs(sdk): add JSDoc to exported interfaces in packages/sdk/src/types.ts in
|
||||
[#26441](https://github.com/google-gemini/gemini-cli/pull/26441)
|
||||
- perf: skip redundant GEMINI.md loading in partialConfig in
|
||||
[#26443](https://github.com/google-gemini/gemini-cli/pull/26443)
|
||||
- Enhance React guidelines in
|
||||
[#22667](https://github.com/google-gemini/gemini-cli/pull/22667)
|
||||
- feat(core): reinforce Inquiry constraints to prevent unauthorized changes in
|
||||
[#26310](https://github.com/google-gemini/gemini-cli/pull/26310)
|
||||
- revert: fix(ci): robust version checking in release verification (#26337) in
|
||||
[#26450](https://github.com/google-gemini/gemini-cli/pull/26450)
|
||||
- refactor(UI): created constants file for ThemeDialog in
|
||||
[#26446](https://github.com/google-gemini/gemini-cli/pull/26446)
|
||||
- docs: fix GitHub capitalization in releases guide in
|
||||
[#26379](https://github.com/google-gemini/gemini-cli/pull/26379)
|
||||
- fix(cli): ensure branch indicator updates in sub-directories and worktrees in
|
||||
[#26330](https://github.com/google-gemini/gemini-cli/pull/26330)
|
||||
- feat: add minimal V8 heap snapshot utility for memory diagnostics in
|
||||
[#26440](https://github.com/google-gemini/gemini-cli/pull/26440)
|
||||
- fix(hooks): preserve non-text parts in fromHookLLMRequest in
|
||||
[#26275](https://github.com/google-gemini/gemini-cli/pull/26275)
|
||||
- fix(cli): allow early stdout when config is undefined in
|
||||
[#26453](https://github.com/google-gemini/gemini-cli/pull/26453)
|
||||
- fix(cli)#21297: clear skills consent dialog before reload in
|
||||
[#26431](https://github.com/google-gemini/gemini-cli/pull/26431)
|
||||
- fix(cli): render LaTeX-style output as Unicode in the TUI in
|
||||
[#25802](https://github.com/google-gemini/gemini-cli/pull/25802)
|
||||
- fix(core): use close event instead of exit in child_process fallback in
|
||||
[#25695](https://github.com/google-gemini/gemini-cli/pull/25695)
|
||||
- feat(voice): add privacy and compliance UX warning for Gemini Live backend in
|
||||
[#26454](https://github.com/google-gemini/gemini-cli/pull/26454)
|
||||
- feat(memory): add Auto Memory inbox flow with canonical-patch contract in
|
||||
[#26338](https://github.com/google-gemini/gemini-cli/pull/26338)
|
||||
- test(cleanup): fix temporary directory leaks in test suites in
|
||||
[#26217](https://github.com/google-gemini/gemini-cli/pull/26217)
|
||||
- feat: add ignoreLocalEnv setting and --ignore-env flag (#2493) in
|
||||
[#26445](https://github.com/google-gemini/gemini-cli/pull/26445)
|
||||
- docs(sdk): add JSDoc to all exported interfaces and types in
|
||||
[#26277](https://github.com/google-gemini/gemini-cli/pull/26277)
|
||||
- feat(cli): improve /agents refresh logging in
|
||||
[#26442](https://github.com/google-gemini/gemini-cli/pull/26442)
|
||||
- Fix: make Dockerfile self-contained with multi-stage build in
|
||||
[#24277](https://github.com/google-gemini/gemini-cli/pull/24277)
|
||||
- fix(core): filter unsupported multimodal types from tool responses in
|
||||
[#26352](https://github.com/google-gemini/gemini-cli/pull/26352)
|
||||
- fix(core): properly format markdown in AskUser tool by unescaping newlines in
|
||||
[#26349](https://github.com/google-gemini/gemini-cli/pull/26349)
|
||||
- feat(bot): add actions spend metric script in
|
||||
[#26463](https://github.com/google-gemini/gemini-cli/pull/26463)
|
||||
- feat(cli): add /bug-memory command and auto-capture heap snapshot in /bug in
|
||||
[#25639](https://github.com/google-gemini/gemini-cli/pull/25639)
|
||||
- fix(cli): make SkillInboxDialog fit and scroll in alternate buffer in
|
||||
[#26455](https://github.com/google-gemini/gemini-cli/pull/26455)
|
||||
- Robust Scale-Safe Lifecycle Consolidation in
|
||||
[#26355](https://github.com/google-gemini/gemini-cli/pull/26355)
|
||||
- fix(ci): respect exempt labels when closing stale items in
|
||||
[#26475](https://github.com/google-gemini/gemini-cli/pull/26475)
|
||||
- fix(cli): use os.homedir() for home directory warning check in
|
||||
[#25890](https://github.com/google-gemini/gemini-cli/pull/25890)
|
||||
- fix(a2a-server): resolve tool approval race condition and improve status
|
||||
reporting in [#26479](https://github.com/google-gemini/gemini-cli/pull/26479)
|
||||
- fix(cli): prevent settings dialog border clipping using maxHeight in
|
||||
[#26507](https://github.com/google-gemini/gemini-cli/pull/26507)
|
||||
- feat: allow queuing messages during compression (#24071) in
|
||||
[#26506](https://github.com/google-gemini/gemini-cli/pull/26506)
|
||||
- fix(core): retry on ERR_STREAM_PREMATURE_CLOSE errors in
|
||||
[#26519](https://github.com/google-gemini/gemini-cli/pull/26519)
|
||||
- fix(core): Minor fixes for generalist profile. in
|
||||
[#26357](https://github.com/google-gemini/gemini-cli/pull/26357)
|
||||
|
||||
**Full Changelog**:
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.35.0-preview.5...v0.36.0-preview.5
|
||||
https://github.com/google-gemini/gemini-cli/compare/v0.41.0-preview.3...v0.42.0-preview.2
|
||||
|
||||
@@ -44,8 +44,8 @@ and Gemini CLI (the server).
|
||||
|
||||
- **Communication:** The entire communication happens over standard input/output
|
||||
(stdio) using the JSON-RPC 2.0 protocol.
|
||||
- **Client's role:** The client is responsible for sending requests (e.g.,
|
||||
prompts) and handling responses and notifications from Gemini CLI.
|
||||
- **Client's role:** The client is responsible for sending requests (for
|
||||
example, prompts) and handling responses and notifications from Gemini CLI.
|
||||
- **Gemini CLI's role:** In ACP mode, Gemini CLI listens for incoming JSON-RPC
|
||||
requests, processes them, and sends back responses.
|
||||
|
||||
@@ -72,8 +72,8 @@ leverage the IDE's capabilities to perform tasks. The MCP client logic is in
|
||||
|
||||
## Capabilities and supported methods
|
||||
|
||||
The ACP protocol exposes a number of methods for ACP clients (e.g. IDEs) to
|
||||
control Gemini CLI.
|
||||
The ACP protocol exposes a number of methods for ACP clients (for example IDEs)
|
||||
to control Gemini CLI.
|
||||
|
||||
### Core methods
|
||||
|
||||
@@ -87,8 +87,8 @@ control Gemini CLI.
|
||||
|
||||
### Session control
|
||||
|
||||
- `setSessionMode`: Allows changing the approval level for tool calls (e.g., to
|
||||
`auto-approve`).
|
||||
- `setSessionMode`: Allows changing the approval level for tool calls (for
|
||||
example, to `auto-approve`).
|
||||
- `unstable_setSessionModel`: Changes the model for the current session.
|
||||
|
||||
### File system proxy
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# Auto Memory
|
||||
|
||||
Auto Memory is an experimental feature that mines your past Gemini CLI sessions
|
||||
in the background and proposes durable memory updates and reusable
|
||||
[Agent Skills](./skills.md). You review each candidate before it becomes
|
||||
available to future sessions: apply memory updates, promote skills, or discard
|
||||
anything you do not want.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> This is an experimental feature currently under active development.
|
||||
|
||||
## Overview
|
||||
|
||||
Every session you run with Gemini CLI is recorded locally as a transcript. Auto
|
||||
Memory scans those transcripts for durable facts, preferences, workflow
|
||||
constraints, and procedural patterns that recur across sessions. It can draft
|
||||
memory updates as unified diff `.patch` files and draft reusable procedures as
|
||||
`SKILL.md` files. All candidates are held in a project-local inbox until you
|
||||
approve or discard them.
|
||||
|
||||
You'll use Auto Memory when you want to:
|
||||
|
||||
- **Capture team workflows** that you find yourself walking the agent through
|
||||
more than once.
|
||||
- **Preserve durable project context** such as repeated verification commands,
|
||||
local constraints, or personal project notes.
|
||||
- **Codify hard-won fixes** for project-specific landmines so future sessions
|
||||
avoid them.
|
||||
- **Bootstrap a skills library** without writing every `SKILL.md` by hand.
|
||||
|
||||
Auto Memory complements—but does not replace—the
|
||||
[`save_memory` tool](../tools/memory.md), which captures single facts into
|
||||
`GEMINI.md` when the agent explicitly calls it. Auto Memory infers candidates
|
||||
from past sessions, writes reviewable patches or skill drafts, and never applies
|
||||
them without your approval.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Gemini CLI installed and authenticated.
|
||||
- At least one idle project session with 10 or more user messages. Auto Memory
|
||||
ignores active, trivial, and sub-agent sessions.
|
||||
|
||||
## How to enable Auto Memory
|
||||
|
||||
Auto Memory is off by default. Enable it in your settings file:
|
||||
|
||||
1. Open your global settings file at `~/.gemini/settings.json`. If you only
|
||||
want Auto Memory in one project, edit `.gemini/settings.json` in that
|
||||
project instead.
|
||||
|
||||
2. Add the experimental flag:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"autoMemory": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Restart Gemini CLI. The flag requires a restart because the extraction
|
||||
service starts during session boot.
|
||||
|
||||
## How Auto Memory works
|
||||
|
||||
Auto Memory runs as a background task on session startup. It does not block the
|
||||
UI, consume your interactive turns, or surface tool prompts.
|
||||
|
||||
1. **Eligibility scan.** The service indexes recent sessions from
|
||||
`~/.gemini/tmp/<project>/chats/`. Sessions are eligible only if they have
|
||||
been idle for at least three hours and contain at least 10 user messages.
|
||||
2. **Lock acquisition.** A lock file in the project's memory directory
|
||||
coordinates across multiple CLI instances so extraction runs at most once at
|
||||
a time. A state file records processed session versions, and extraction is
|
||||
throttled so short back-to-back CLI launches do not repeatedly scan history.
|
||||
3. **Candidate extraction.** A background extraction agent reviews the session
|
||||
index, reads any sessions that look like they contain durable memory or
|
||||
repeated procedural workflows, and drafts candidates. It defaults to
|
||||
creating no artifacts unless the evidence is strong, so many runs produce no
|
||||
inbox items.
|
||||
4. **Safety boundaries.** Auto Memory writes candidates to a review inbox. It
|
||||
cannot directly edit active memory files, settings, credentials, or project
|
||||
`GEMINI.md` files.
|
||||
5. **Patch validation.** Skill update patches are parsed and dry-run before
|
||||
they are surfaced. Memory patches are parsed, target-allowlisted, and
|
||||
applied atomically only when you approve them from the inbox.
|
||||
6. **Notification.** When a run produces new candidates, Gemini CLI surfaces an
|
||||
inline message telling you how many items are waiting.
|
||||
|
||||
## How to review extracted items
|
||||
|
||||
Use the `/memory inbox` slash command to open the inbox dialog at any time:
|
||||
|
||||
**Command:** `/memory inbox`
|
||||
|
||||
The dialog groups pending items into new skills, skill updates, and memory
|
||||
updates. From there you can:
|
||||
|
||||
- **Read** the full `SKILL.md` body before deciding.
|
||||
- **Promote** a skill to your user (`~/.gemini/skills/`) or workspace
|
||||
(`.gemini/skills/`) directory.
|
||||
- **Discard** a skill you do not want.
|
||||
- **Apply** or reject a `.patch` proposal against an existing skill.
|
||||
- **Review** memory diffs before they touch active files.
|
||||
- **Apply** or dismiss private and global memory patches. Private patches target
|
||||
the project memory directory; global patches target only your personal
|
||||
`~/.gemini/GEMINI.md` file.
|
||||
|
||||
Promoted skills become discoverable in the next session and follow the standard
|
||||
[skill discovery precedence](./skills.md#skill-discovery-tiers). Applied memory
|
||||
patches update the underlying memory files and reload memory for the current
|
||||
session.
|
||||
|
||||
## How to disable Auto Memory
|
||||
|
||||
To turn off background extraction, set the flag back to `false` in your settings
|
||||
file and restart Gemini CLI:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"autoMemory": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Disabling the flag stops the background service immediately on the next session
|
||||
start. Existing inbox items remain on disk; you can either drain them with
|
||||
`/memory inbox` first or remove the project memory directory manually.
|
||||
|
||||
## Data and privacy
|
||||
|
||||
- Auto Memory only reads session files that already exist locally on your
|
||||
machine.
|
||||
- Auto Memory uses model calls to analyze selected local transcript content
|
||||
during extraction. No candidates are applied automatically, but transcript
|
||||
excerpts may be sent to the configured model as part of those calls.
|
||||
- The extraction agent is instructed to redact secrets, tokens, and credentials
|
||||
it encounters and to never copy large tool outputs verbatim.
|
||||
- Drafted skills and memory patches live in your project's memory directory
|
||||
until you promote, apply, dismiss, or discard them. They are not automatically
|
||||
loaded into any session.
|
||||
|
||||
## Limitations
|
||||
|
||||
- The extraction agent runs on a preview Gemini Flash model. Extraction quality
|
||||
depends on the model's ability to recognize durable patterns versus one-off
|
||||
incidents.
|
||||
- Auto Memory does not extract memory or skills from the current session. It
|
||||
only considers sessions that have been idle for three hours or more.
|
||||
- Project or workspace shared instructions in project `GEMINI.md` files are not
|
||||
auto-extractable. Auto Memory can propose private project memory, global
|
||||
personal memory, and skills.
|
||||
- Inbox items are stored per project. Skills extracted in one workspace are not
|
||||
visible from another until you promote them to the user-scope skills
|
||||
directory.
|
||||
|
||||
## Next steps
|
||||
|
||||
- Learn how skills are discovered and activated in [Agent Skills](./skills.md).
|
||||
- Explore the [memory management tutorial](./tutorials/memory-management.md) for
|
||||
the complementary explicit-memory and `GEMINI.md` workflows.
|
||||
- Review the experimental settings catalog in
|
||||
[Settings](./settings.md#experimental).
|
||||
@@ -1,9 +1,9 @@
|
||||
# Checkpointing
|
||||
|
||||
The Gemini CLI includes a Checkpointing feature that automatically saves a
|
||||
snapshot of your project's state before any file modifications are made by
|
||||
AI-powered tools. This lets you safely experiment with and apply code changes,
|
||||
knowing you can instantly revert back to the state before the tool was run.
|
||||
Gemini CLI includes a Checkpointing feature that automatically saves a snapshot
|
||||
of your project's state before any file modifications are made by AI-powered
|
||||
tools. This lets you safely experiment with and apply code changes, knowing you
|
||||
can instantly revert back to the state before the tool was run.
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -72,7 +72,7 @@ To see a list of all saved checkpoints for the current project, simply run:
|
||||
|
||||
The CLI will display a list of available checkpoint files. These file names are
|
||||
typically composed of a timestamp, the name of the file being modified, and the
|
||||
name of the tool that was about to be run (e.g.,
|
||||
name of the tool that was about to be run (for example,
|
||||
`2025-06-22T10-00-00_000Z-my-file.txt-write_file`).
|
||||
|
||||
### Restore a specific checkpoint
|
||||
|
||||
+15
-13
@@ -9,7 +9,7 @@ and parameters.
|
||||
| ---------------------------------- | ---------------------------------- | ------------------------------------------------------------ |
|
||||
| `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"` |
|
||||
| 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"` |
|
||||
@@ -29,16 +29,17 @@ and parameters.
|
||||
|
||||
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 |
|
||||
| Command | Description |
|
||||
| -------------------- | ----------------------------------------------- |
|
||||
| `/skills reload` | Reload discovered skills from disk |
|
||||
| `/agents reload` | Reload the agent registry |
|
||||
| `/commands list` | List available custom slash commands |
|
||||
| `/commands reload` | Reload custom slash commands |
|
||||
| `/memory reload` | Reload context files (for example, `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
|
||||
|
||||
@@ -52,7 +53,8 @@ These commands are available within the interactive REPL.
|
||||
| `--prompt-interactive` | `-i` | string | - | Execute prompt and continue in interactive mode |
|
||||
| `--worktree` | `-w` | string | - | Start Gemini in a new git worktree. If no name is provided, one is generated automatically. Requires `experimental.worktrees: true` in settings. |
|
||||
| `--sandbox` | `-s` | boolean | `false` | Run in a sandboxed environment for safer execution |
|
||||
| `--approval-mode` | - | string | `default` | Approval mode for tool execution. Choices: `default`, `auto_edit`, `yolo` |
|
||||
| `--skip-trust` | - | boolean | `false` | Trust the current workspace for this session, skipping the folder trust check. |
|
||||
| `--approval-mode` | - | string | `default` | Approval mode for tool execution. Choices: `default`, `auto_edit`, `yolo`, `plan` |
|
||||
| `--yolo` | `-y` | boolean | `false` | **Deprecated.** Auto-approve all actions. Use `--approval-mode=yolo` instead. |
|
||||
| `--experimental-acp` | - | boolean | - | Start in ACP (Agent Code Pilot) mode. **Experimental feature.** |
|
||||
| `--experimental-zed-integration` | - | boolean | - | Run in Zed editor integration mode. **Experimental feature.** |
|
||||
@@ -60,7 +62,7 @@ These commands are available within the interactive REPL.
|
||||
| `--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`) |
|
||||
| `--resume` | `-r` | string | - | Resume a previous session. Use `"latest"` for most recent or index number (for example `--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) |
|
||||
|
||||
+171
-44
@@ -1,43 +1,138 @@
|
||||
# Creating Agent Skills
|
||||
|
||||
This guide provides an overview of how to create your own Agent Skills to extend
|
||||
the capabilities of Gemini CLI.
|
||||
Agent Skills let you extend Gemini CLI with specialized expertise, procedural
|
||||
workflows, and task-specific resources. This guide walks you through both
|
||||
automated and manual methods for creating and organizing your skills.
|
||||
|
||||
## Getting started: The `skill-creator` skill
|
||||
## Quickstart: Create a skill with a prompt
|
||||
|
||||
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.
|
||||
The fastest way to create a new skill is to use the built-in `skill-creator`.
|
||||
This meta-skill guides you through designing, scaffolding, and validating your
|
||||
expertise.
|
||||
|
||||
**Example prompt:**
|
||||
Simply ask Gemini CLI to create a skill for you:
|
||||
|
||||
> "create a new skill called 'code-reviewer'"
|
||||
> "Create a new skill called 'code-reviewer' that analyzes local files for
|
||||
> common errors and style violations."
|
||||
|
||||
Gemini CLI will then use the `skill-creator` to generate the skill:
|
||||
Gemini will then:
|
||||
|
||||
1. Generate a new directory for your skill (e.g., `my-new-skill/`).
|
||||
1. Generate a new directory for your skill (for example, `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
|
||||
Once created, you can find your new skill in `.gemini/skills/code-reviewer/`.
|
||||
|
||||
If you prefer to create skills manually:
|
||||
## Manual creation
|
||||
|
||||
1. **Create a directory** for your skill (e.g., `my-new-skill/`).
|
||||
1. **Create a directory** for your skill (for example, `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.
|
||||
### 1. Create the directory structure
|
||||
|
||||
## Skill structure
|
||||
The first step is to create the necessary folders for your skill and its
|
||||
scripts.
|
||||
|
||||
A skill is a directory containing a `SKILL.md` file at its root.
|
||||
**macOS/Linux**
|
||||
|
||||
### Folder structure
|
||||
```bash
|
||||
mkdir -p .gemini/skills/code-reviewer/scripts
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path ".gemini\skills\code-reviewer\scripts"
|
||||
```
|
||||
|
||||
### 2. Define the skill (`SKILL.md`)
|
||||
|
||||
The `SKILL.md` file defines the skill's purpose and instructions for the agent.
|
||||
Create a file at `.gemini/skills/code-reviewer/SKILL.md`.
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: code-reviewer
|
||||
description:
|
||||
Expertise in reviewing code changes for correctness, security, and style. Use
|
||||
when the user asks to "review" their code or a PR.
|
||||
---
|
||||
|
||||
# Code Reviewer Instructions
|
||||
|
||||
You act as a senior software engineer specialized in code quality. When this
|
||||
skill is active, you MUST:
|
||||
|
||||
1. **Analyze**: Review the provided code for logical errors, security
|
||||
vulnerabilities, and style violations.
|
||||
2. **Review**: Use the bundled `scripts/review.js` utility to perform an
|
||||
automated check.
|
||||
3. **Feedback**: Provide constructive feedback, clearly distinguishing between
|
||||
critical issues and minor improvements.
|
||||
```
|
||||
|
||||
### 3. Add the tool logic
|
||||
|
||||
Skills can bundle resources like scripts to perform deterministic tasks. Create
|
||||
a file at `.gemini/skills/code-reviewer/scripts/review.js`.
|
||||
|
||||
```javascript
|
||||
// .gemini/skills/code-reviewer/scripts/review.js
|
||||
const file = process.argv[2];
|
||||
|
||||
if (!file) {
|
||||
console.error('Usage: node review.js <file>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Reviewing ${file}...`);
|
||||
// Simple mock review logic
|
||||
setTimeout(() => {
|
||||
console.log(`Result: Success (No major issues found in ${file})`);
|
||||
}, 500);
|
||||
```
|
||||
|
||||
### 4. Test the skill
|
||||
|
||||
Gemini CLI automatically discovers skills in the `.gemini/skills` directory.
|
||||
|
||||
1. Start a new session and ask a question that triggers the skill's
|
||||
description: "Can you review index.js"
|
||||
2. Gemini identifies the request matches the `code-reviewer` description and
|
||||
asks for permission to activate it.
|
||||
3. Once you approve, Gemini executes the bundled script:
|
||||
`node .gemini/skills/code-reviewer/scripts/review.js index.js`
|
||||
|
||||
To determine whether your skill has been correctly loaded, run the command:
|
||||
|
||||
```bash
|
||||
/skills
|
||||
```
|
||||
|
||||
### 5. Optional: Share your skill
|
||||
|
||||
You can share your skills in several ways depending on your target audience.
|
||||
|
||||
- **Workspace skills**: Commit your skill to a `.gemini/skills/` directory in
|
||||
your project repository.
|
||||
- **Extensions**: Bundle your skill within a
|
||||
[Gemini CLI extension](../extensions/writing-extensions.md).
|
||||
- **Git repositories**: Share the skill directory as a standalone Git repo and
|
||||
install it using `gemini skills install <url>`.
|
||||
|
||||
---
|
||||
|
||||
## Core concepts
|
||||
|
||||
Now that you've built your first skill, let's explore the core components and
|
||||
workflows for developing more complex expertise.
|
||||
|
||||
### Skill structure
|
||||
|
||||
While a `SKILL.md` file is the only required component, we recommend the
|
||||
following structure for organizing your skill's resources:
|
||||
following structure for organizing your skill's resources.
|
||||
|
||||
```text
|
||||
my-skill/
|
||||
@@ -47,34 +142,66 @@ my-skill/
|
||||
└── assets/ (Optional) Templates and other resources
|
||||
```
|
||||
|
||||
### `SKILL.md` file
|
||||
When a skill is activated, the model is granted access to this entire directory.
|
||||
You can instruct the model to use the tools and files found within these
|
||||
folders.
|
||||
|
||||
The `SKILL.md` file is the core of your skill. This file uses YAML frontmatter
|
||||
for metadata and Markdown for instructions. For example:
|
||||
### Metadata and triggers
|
||||
|
||||
```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... ...
|
||||
```
|
||||
The `SKILL.md` file uses YAML frontmatter for metadata.
|
||||
|
||||
- **`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.
|
||||
- **`description`**: **CRITICAL.** This is how Gemini decides when to use the
|
||||
skill. Be specific about the tasks it handles and the keywords that should
|
||||
trigger it.
|
||||
|
||||
### Discovery tiers
|
||||
|
||||
Gemini CLI discovers skills from several locations, following a specific order
|
||||
of precedence (lowest to highest):
|
||||
|
||||
1. **Built-in Skills**: Included with Gemini CLI (pre-approved).
|
||||
2. **Extension Skills**: Bundled within [extensions](../extensions/).
|
||||
3. **User Skills**: `~/.gemini/skills/` or the `~/.agents/skills/` alias.
|
||||
4. **Workspace Skills**: `.gemini/skills/` or the `.agents/skills/` alias.
|
||||
|
||||
### Discovery aliases
|
||||
|
||||
You can use `.agents/skills` as an alternative to `.gemini/skills`. This alias
|
||||
is compatible with other AI agent tools following the
|
||||
[Agent Skills](https://agentskills.io) standard.
|
||||
|
||||
## Advanced development
|
||||
|
||||
Once you've built a basic skill, you can use specialized scripts and workflows
|
||||
to streamline your development process.
|
||||
|
||||
### Creation scripts
|
||||
|
||||
If you are developing a skill and want to use the same scripts the built-in
|
||||
tools use, you can find them in the core package. These scripts help automate
|
||||
the initialization, validation, and packaging of skills.
|
||||
|
||||
- **Initialize**: `node scripts/init_skill.cjs <name> --path <dir>`
|
||||
- **Validate**: `node scripts/validate_skill.cjs <path/to/skill>`
|
||||
- **Package**: `node scripts/package_skill.cjs <path/to/skill>` (Creates a
|
||||
`.skill` zip file)
|
||||
|
||||
### Linking for local development
|
||||
|
||||
If you are developing a skill in a separate directory, you can link it to your
|
||||
user skills directory for testing:
|
||||
|
||||
```bash
|
||||
gemini skills link .
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Skill best practices](./skills-best-practices.md): Learn strategies for
|
||||
building reliable and effective skills.
|
||||
- [Agent Skills overview](./skills.md): Deep dive into discovery tiers and the
|
||||
skill lifecycle.
|
||||
- [Get started with Agent Skills](./tutorials/skills-getting-started.md): A
|
||||
quick walkthrough of triggering and using skills.
|
||||
|
||||
+16
-14
@@ -34,6 +34,7 @@ separator (`/` or `\`) being converted to a colon (`:`).
|
||||
> [!TIP]
|
||||
> After creating or modifying `.toml` command files, run
|
||||
> `/commands reload` to pick up your changes without restarting the CLI.
|
||||
> To see all available command files, run `/commands list`.
|
||||
|
||||
## TOML file format (v1)
|
||||
|
||||
@@ -85,8 +86,8 @@ The model receives:
|
||||
**B. Using arguments in shell commands (inside `!{...}` blocks)**
|
||||
|
||||
When you use `{{args}}` inside a shell injection block (`!{...}`), the arguments
|
||||
are automatically **shell-escaped** before replacement. This allows you to
|
||||
safely pass arguments to shell commands, ensuring the resulting command is
|
||||
are automatically **shell-escaped** before replacement. This lets you safely
|
||||
pass arguments to shell commands, ensuring the resulting command is
|
||||
syntactically correct and secure while preventing command injection
|
||||
vulnerabilities.
|
||||
|
||||
@@ -105,8 +106,8 @@ When you run `/grep-code It's complicated`:
|
||||
|
||||
1. The CLI sees `{{args}}` used both outside and inside `!{...}`.
|
||||
2. Outside: The first `{{args}}` is replaced raw with `It's complicated`.
|
||||
3. Inside: The second `{{args}}` is replaced with the escaped version (e.g., on
|
||||
Linux: `"It\'s complicated"`).
|
||||
3. Inside: The second `{{args}}` is replaced with the escaped version (for
|
||||
example, on Linux: `"It\'s complicated"`).
|
||||
4. The command executed is `grep -r "It's complicated" .`.
|
||||
5. The CLI prompts you to confirm this exact, secure command before execution.
|
||||
6. The final prompt is sent.
|
||||
@@ -116,13 +117,13 @@ When you run `/grep-code It's complicated`:
|
||||
If your `prompt` does **not** contain the special placeholder `{{args}}`, the
|
||||
CLI uses a default behavior for handling arguments.
|
||||
|
||||
If you provide arguments to the command (e.g., `/mycommand arg1`), the CLI will
|
||||
append the full command you typed to the end of the prompt, separated by two
|
||||
newlines. This allows the model to see both the original instructions and the
|
||||
specific arguments you just provided.
|
||||
If you provide arguments to the command (for example, `/mycommand arg1`), the
|
||||
CLI will append the full command you typed to the end of the prompt, separated
|
||||
by two newlines. This allows the model to see both the original instructions and
|
||||
the specific arguments you just provided.
|
||||
|
||||
If you do **not** provide any arguments (e.g., `/mycommand`), the prompt is sent
|
||||
to the model exactly as it is, with nothing appended.
|
||||
If you do **not** provide any arguments (for example, `/mycommand`), the prompt
|
||||
is sent to the model exactly as it is, with nothing appended.
|
||||
|
||||
**Example (`changelog.toml`):**
|
||||
|
||||
@@ -188,7 +189,7 @@ ensure that only intended commands can be run.
|
||||
dialog will appear showing the exact command(s) to be executed.
|
||||
5. **Execution and error reporting:** The command is executed. If the command
|
||||
fails, the output injected into the prompt will include the error messages
|
||||
(stderr) followed by a status line, e.g.,
|
||||
(stderr) followed by a status line, for example,
|
||||
`[Shell command exited with code 1]`. This helps the model understand the
|
||||
context of the failure.
|
||||
|
||||
@@ -229,9 +230,10 @@ operate on specific files.
|
||||
|
||||
- **File injection**: `@{path/to/file.txt}` is replaced by the content of
|
||||
`file.txt`.
|
||||
- **Multimodal support**: If the path points to a supported image (e.g., PNG,
|
||||
JPEG), PDF, audio, or video file, it will be correctly encoded and injected as
|
||||
multimodal input. Other binary files are handled gracefully and skipped.
|
||||
- **Multimodal support**: If the path points to a supported image (for example,
|
||||
PNG, JPEG), PDF, audio, or video file, it will be correctly encoded and
|
||||
injected as multimodal input. Other binary files are handled gracefully and
|
||||
skipped.
|
||||
- **Directory listing**: `@{path/to/dir}` is traversed and each file present
|
||||
within the directory and all subdirectories is inserted into the prompt. This
|
||||
respects `.gitignore` and `.geminiignore` if enabled.
|
||||
|
||||
+17
-14
@@ -175,8 +175,8 @@ the enterprise settings are always loaded with the highest precedence.
|
||||
**Example wrapper script:**
|
||||
|
||||
Administrators can create a script named `gemini` and place it in a directory
|
||||
that appears earlier in the user's `PATH` than the actual Gemini CLI binary
|
||||
(e.g., `/usr/local/bin/gemini`).
|
||||
that appears earlier in the user's `PATH` than the actual Gemini CLI binary (for
|
||||
example, `/usr/local/bin/gemini`).
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
@@ -325,9 +325,9 @@ User. When it comes to the `mcpServers` object, these configurations are
|
||||
1. **Merging:** The lists of servers from all three levels are combined into a
|
||||
single list.
|
||||
2. **Precedence:** If a server with the **same name** is defined at multiple
|
||||
levels (e.g., a server named `corp-api` exists in both system and user
|
||||
settings), the definition from the highest-precedence level is used. The
|
||||
order of precedence is: **System > Workspace > User**.
|
||||
levels (for example, a server named `corp-api` exists in both system and
|
||||
user settings), the definition from the highest-precedence level is used.
|
||||
The order of precedence is: **System > Workspace > User**.
|
||||
|
||||
This means a user **cannot** override the definition of a server that is already
|
||||
defined in the system-level settings. However, they **can** add new servers with
|
||||
@@ -343,8 +343,8 @@ canonical servers and adding their names to an allowlist.
|
||||
For even greater security, especially when dealing with third-party MCP servers,
|
||||
you can restrict which specific tools from a server are exposed to the model.
|
||||
This is done using the `includeTools` and `excludeTools` properties within a
|
||||
server's definition. This allows you to use a subset of tools from a server
|
||||
without allowing potentially dangerous ones.
|
||||
server's definition. This lets you use a subset of tools from a server without
|
||||
allowing potentially dangerous ones.
|
||||
|
||||
Following the principle of least privilege, it is highly recommended to use
|
||||
`includeTools` to create an allowlist of only the necessary tools.
|
||||
@@ -481,9 +481,8 @@ an environment variable, but it can also be enforced for custom tools via the
|
||||
## Telemetry and auditing
|
||||
|
||||
For auditing and monitoring purposes, you can configure Gemini CLI to send
|
||||
telemetry data to a central location. This allows you to track tool usage and
|
||||
other events. For more information, see the
|
||||
[telemetry documentation](./telemetry.md).
|
||||
telemetry data to a central location. This lets you track tool usage and other
|
||||
events. For more information, see the [telemetry documentation](./telemetry.md).
|
||||
|
||||
**Example:** Enable telemetry and send it to a local OTLP collector. If
|
||||
`otlpEndpoint` is not specified, it defaults to `http://localhost:4317`.
|
||||
@@ -506,15 +505,19 @@ other events. For more information, see the
|
||||
## Authentication
|
||||
|
||||
You can enforce a specific authentication method for all users by setting the
|
||||
`enforcedAuthType` in the system-level `settings.json` file. This prevents users
|
||||
from choosing a different authentication method. See the
|
||||
[Authentication docs](../get-started/authentication.md) for more details.
|
||||
`security.auth.enforcedType` in the system-level `settings.json` file. This
|
||||
prevents users from choosing a different authentication method. See the
|
||||
[Authentication docs](../get-started/authentication.mdx) for more details.
|
||||
|
||||
**Example:** Enforce the use of Google login for all users.
|
||||
|
||||
```json
|
||||
{
|
||||
"enforcedAuthType": "oauth-personal"
|
||||
"security": {
|
||||
"auth": {
|
||||
"enforcedType": "oauth-personal"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Ignoring files
|
||||
|
||||
This document provides an overview of the Gemini Ignore (`.geminiignore`)
|
||||
feature of the Gemini CLI.
|
||||
feature of Gemini CLI.
|
||||
|
||||
The Gemini CLI includes the ability to automatically ignore files, similar to
|
||||
Gemini CLI includes the ability to automatically ignore files, similar to
|
||||
`.gitignore` (used by Git) and `.aiexclude` (used by Gemini Code Assist). Adding
|
||||
paths to your `.geminiignore` file will exclude them from tools that support
|
||||
this feature, although they will still be visible to other services (such as
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
# Advanced Model Configuration
|
||||
|
||||
This guide details the Model Configuration system within the Gemini CLI.
|
||||
Designed for researchers, AI quality engineers, and advanced users, this system
|
||||
provides a rigorous framework for managing generative model hyperparameters and
|
||||
This guide details the Model Configuration system within Gemini CLI. Designed
|
||||
for researchers, AI quality engineers, and advanced users, this system provides
|
||||
a rigorous framework for managing generative model hyperparameters and
|
||||
behaviors.
|
||||
|
||||
> **Warning**: This is a power-user feature. Configuration values are passed
|
||||
<!-- prettier-ignore -->
|
||||
> [!WARNING]
|
||||
> This is a power-user feature. Configuration values are passed
|
||||
> directly to the model provider with minimal validation. Incorrect settings
|
||||
> (e.g., incompatible parameter combinations) may result in runtime errors from
|
||||
> the API.
|
||||
> (for example, incompatible parameter combinations) may result in runtime
|
||||
> errors from the API.
|
||||
|
||||
## 1. System Overview
|
||||
|
||||
The Model Configuration system (`ModelConfigService`) enables deterministic
|
||||
control over model generation. It decouples the requested model identifier
|
||||
(e.g., a CLI flag or agent request) from the underlying API configuration. This
|
||||
allows for:
|
||||
control over model generation. It decouples the requested model identifier (for
|
||||
example, a CLI flag or agent request) from the underlying API configuration.
|
||||
This allows for:
|
||||
|
||||
- **Precise Hyperparameter Tuning**: Direct control over `temperature`, `topP`,
|
||||
`thinkingBudget`, and other SDK-level parameters.
|
||||
- **Environment-Specific Behavior**: Distinct configurations for different
|
||||
operating contexts (e.g., testing vs. production).
|
||||
operating contexts (for example, testing vs. production).
|
||||
- **Agent-Scoped Customization**: Applying specific settings only when a
|
||||
particular agent is active.
|
||||
|
||||
@@ -71,7 +73,7 @@ context. They are evaluated dynamically for each model request.
|
||||
specified `match` properties.
|
||||
- `model`: Matches the requested model name or alias.
|
||||
- `overrideScope`: Matches the distinct scope of the request (typically the
|
||||
agent name, e.g., `codebaseInvestigator`).
|
||||
agent name, for example, `codebaseInvestigator`).
|
||||
|
||||
**Example Override**:
|
||||
|
||||
@@ -113,8 +115,8 @@ and `overrideScope`).
|
||||
1. **Filtering**: All matching overrides are identified.
|
||||
2. **Sorting**: Matches are prioritized by **specificity** (the number of
|
||||
matched keys in the `match` object).
|
||||
- Specific matches (e.g., `model` + `overrideScope`) override broad matches
|
||||
(e.g., `model` only).
|
||||
- Specific matches (for example, `model` + `overrideScope`) override broad
|
||||
matches (for example, `model` only).
|
||||
- Tie-breaking: If specificity is equal, the order of definition in the
|
||||
`overrides` array is preserved (last one wins).
|
||||
3. **Merging**: The configurations from the sorted overrides are merged
|
||||
@@ -128,10 +130,10 @@ The configuration follows the `ModelConfigServiceConfig` interface.
|
||||
|
||||
Defines the actual parameters for the model.
|
||||
|
||||
| Property | Type | Description |
|
||||
| :---------------------- | :------- | :----------------------------------------------------------------- |
|
||||
| `model` | `string` | The identifier of the model to be called (e.g., `gemini-2.5-pro`). |
|
||||
| `generateContentConfig` | `object` | The configuration object passed to the `@google/genai` SDK. |
|
||||
| Property | Type | Description |
|
||||
| :---------------------- | :------- | :------------------------------------------------------------------------ |
|
||||
| `model` | `string` | The identifier of the model to be called (for example, `gemini-2.5-pro`). |
|
||||
| `generateContentConfig` | `object` | The configuration object passed to the `@google/genai` SDK. |
|
||||
|
||||
### `GenerateContentConfig` (Common Parameters)
|
||||
|
||||
@@ -142,7 +144,7 @@ Directly maps to the SDK's `GenerateContentConfig`. Common parameters include:
|
||||
- **`topP`**: (`number`) Nucleus sampling probability.
|
||||
- **`maxOutputTokens`**: (`number`) Limit on generated response length.
|
||||
- **`thinkingConfig`**: (`object`) Configuration for models with reasoning
|
||||
capabilities (e.g., `thinkingBudget`, `includeThoughts`).
|
||||
capabilities (for example, `thinkingBudget`, `includeThoughts`).
|
||||
|
||||
## 5. Practical Examples
|
||||
|
||||
@@ -170,7 +172,7 @@ configuration but enforcing zero temperature.
|
||||
### Agent-Specific Parameter Injection
|
||||
|
||||
Enforce extended thinking budgets for a specific agent without altering the
|
||||
global default, e.g. for the `codebaseInvestigator`.
|
||||
global default, for example for the `codebaseInvestigator`.
|
||||
|
||||
```json
|
||||
"modelConfigs": {
|
||||
|
||||
@@ -10,8 +10,8 @@ Model routing is managed by the `ModelAvailabilityService`, which monitors model
|
||||
health and automatically routes requests to available models based on defined
|
||||
policies.
|
||||
|
||||
1. **Model failure:** If the currently selected model fails (e.g., due to quota
|
||||
or server errors), the CLI will initiate the fallback process.
|
||||
1. **Model failure:** If the currently selected model fails (for example, due
|
||||
to quota or server errors), the CLI will initiate the fallback process.
|
||||
|
||||
2. **User consent:** Depending on the failure and the model's policy, the CLI
|
||||
may prompt you to switch to a fallback model (by default always prompts
|
||||
@@ -34,11 +34,11 @@ Gemini CLI will use a locally-running **Gemma** model to make routing decisions
|
||||
reduce costs associated with hosted model usage while offering similar routing
|
||||
decision latency and quality.
|
||||
|
||||
In order to use this feature, the local Gemma model **must** be served behind a
|
||||
Gemini API and accessible via HTTP at an endpoint configured in `settings.json`.
|
||||
The easiest way to set this up is using the automated `gemini gemma setup`
|
||||
command.
|
||||
|
||||
For more details on how to configure local model routing, see
|
||||
[Local Model Routing](../core/local-model-routing.md).
|
||||
[`gemini gemma` — Local Model Routing Setup](../core/gemma-setup.md).
|
||||
|
||||
### Model selection precedence
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Model steering is an experimental feature and is disabled by default. You can
|
||||
enable it using the `/settings` command or by updating your `settings.json`
|
||||
file.
|
||||
|
||||
1. Type `/settings` in the Gemini CLI.
|
||||
1. Type `/settings` in Gemini CLI.
|
||||
2. Search for **Model Steering**.
|
||||
3. Set the value to **true**.
|
||||
|
||||
|
||||
+40
-18
@@ -39,7 +39,9 @@ To start Plan Mode while using Gemini CLI:
|
||||
the rotation when Gemini CLI is actively processing or showing confirmation
|
||||
dialogs.
|
||||
|
||||
- **Command:** Type `/plan` in the input box.
|
||||
- **Command:** Type `/plan [goal]` in the input box. The `[goal]` is optional;
|
||||
for example, `/plan implement authentication` will switch to Plan Mode and
|
||||
immediately submit the prompt to the model.
|
||||
|
||||
- **Natural Language:** Ask Gemini CLI to "start a plan for...". Gemini CLI
|
||||
calls the
|
||||
@@ -54,19 +56,21 @@ Gemini CLI takes action.
|
||||
|
||||
1. **Provide a goal:** Start by describing what you want to achieve. Gemini CLI
|
||||
will then enter Plan Mode (if it's not already) to research the task.
|
||||
2. **Review research and provide input:** As Gemini CLI analyzes your codebase,
|
||||
it may ask you questions or present different implementation options using
|
||||
[`ask_user`](../tools/ask-user.md). Provide your preferences to help guide
|
||||
the design.
|
||||
3. **Review the plan:** Once Gemini CLI has a proposed strategy, it creates a
|
||||
detailed implementation plan as a Markdown file in your plans directory.
|
||||
2. **Discuss and agree on strategy:** As Gemini CLI analyzes your codebase, it
|
||||
will discuss its findings and proposed strategy with you to ensure
|
||||
alignment. It may ask you questions or present different implementation
|
||||
options using [`ask_user`](../tools/ask-user.md). **Gemini CLI will stop and
|
||||
wait for your confirmation** before drafting the formal plan. You should
|
||||
reach an informal agreement on the approach before proceeding.
|
||||
3. **Review the plan:** Once you've agreed on the strategy, Gemini CLI creates
|
||||
a detailed implementation plan as a Markdown file in your plans directory.
|
||||
- **View:** You can open and read this file to understand the proposed
|
||||
changes.
|
||||
- **Edit:** Press `Ctrl+X` to open the plan directly in your configured
|
||||
external editor.
|
||||
|
||||
4. **Approve or iterate:** Gemini CLI will present the finalized plan for your
|
||||
approval.
|
||||
formal approval.
|
||||
- **Approve:** If you're satisfied with the plan, approve it to start the
|
||||
implementation immediately: **Yes, automatically accept edits** or **Yes,
|
||||
manually accept edits**.
|
||||
@@ -119,13 +123,16 @@ These are the only allowed tools:
|
||||
[`glob`](../tools/file-system.md#4-glob-findfiles)
|
||||
- **Search:** [`grep_search`](../tools/file-system.md#5-grep_search-searchtext),
|
||||
[`google_web_search`](../tools/web-search.md),
|
||||
[`web_fetch`](../tools/web-fetch.md) (requires explicit confirmation),
|
||||
[`get_internal_docs`](../tools/internal-docs.md)
|
||||
- **Research Subagents:**
|
||||
[`codebase_investigator`](../core/subagents.md#codebase-investigator),
|
||||
[`cli_help`](../core/subagents.md#cli-help-agent)
|
||||
- **Interaction:** [`ask_user`](../tools/ask-user.md)
|
||||
- **MCP tools (Read):** Read-only [MCP tools](../tools/mcp-server.md) (for
|
||||
example, `github_read_issue`, `postgres_read_schema`) are allowed.
|
||||
example, `github_read_issue`, `postgres_read_schema`) and core
|
||||
[MCP resource tools](../tools/mcp-resources.md) (`list_mcp_resources`,
|
||||
`read_mcp_resource`) are allowed.
|
||||
- **Planning (Write):**
|
||||
[`write_file`](../tools/file-system.md#3-write_file-writefile) and
|
||||
[`replace`](../tools/file-system.md#6-replace-edit) only allowed for `.md`
|
||||
@@ -176,9 +183,16 @@ As described in the
|
||||
rule that does not explicitly specify `modes` is considered "always active" and
|
||||
will apply to Plan Mode as well.
|
||||
|
||||
If you want a rule to apply to other modes but _not_ to Plan Mode, you must
|
||||
explicitly specify the target modes. For example, to allow `npm test` in default
|
||||
and Auto-Edit modes but not in Plan Mode:
|
||||
To maintain the integrity of Plan Mode as a safe research environment,
|
||||
persistent tool approvals are context-aware. Approvals granted in modes like
|
||||
Default or Auto-Edit do not apply to Plan Mode, ensuring that tools trusted for
|
||||
implementation don't automatically execute while you're researching. However,
|
||||
approvals granted while in Plan Mode are treated as intentional choices for
|
||||
global trust and apply to all modes.
|
||||
|
||||
If you want to manually restrict a rule to other modes but _not_ to Plan Mode,
|
||||
you must explicitly specify the target modes. For example, to allow `npm test`
|
||||
in default and Auto-Edit modes but not in Plan Mode:
|
||||
|
||||
```toml
|
||||
[[rule]]
|
||||
@@ -302,8 +316,8 @@ Hooks such as `BeforeTool` or `AfterTool` can be configured to intercept the
|
||||
> [!WARNING] When hooks are triggered by **tool executions**, they do **not**
|
||||
> run when you manually toggle Plan Mode using the `/plan` command or the
|
||||
> `Shift+Tab` keyboard shortcut. If you need hooks to execute on mode changes,
|
||||
> ensure the transition is initiated by the agent (e.g., by asking "start a plan
|
||||
> for...").
|
||||
> ensure the transition is initiated by the agent (for example, by asking "start
|
||||
> a plan for...").
|
||||
|
||||
#### Example: Archive approved plans to GCS (`AfterTool`)
|
||||
|
||||
@@ -315,8 +329,11 @@ Storage whenever Gemini CLI exits Plan Mode to start the implementation.
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# Extract the plan path from the tool input JSON
|
||||
plan_path=$(jq -r '.tool_input.plan_path // empty')
|
||||
# Extract the plan filename from the tool input JSON
|
||||
plan_filename=$(jq -r '.tool_input.plan_filename // empty')
|
||||
|
||||
# Construct the absolute path using the GEMINI_PLANS_DIR environment variable
|
||||
plan_path="$GEMINI_PLANS_DIR/$plan_filename"
|
||||
|
||||
if [ -f "$plan_path" ]; then
|
||||
# Generate a unique filename using a timestamp
|
||||
@@ -342,7 +359,7 @@ To register this `AfterTool` hook, add it to your `settings.json`:
|
||||
{
|
||||
"name": "archive-plan",
|
||||
"type": "command",
|
||||
"command": "./.gemini/hooks/archive-plan.sh"
|
||||
"command": "~/.gemini/hooks/archive-plan.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -429,6 +446,10 @@ on the current phase of your task:
|
||||
switches to a high-speed **Flash** model. This provides a faster, more
|
||||
responsive experience during the implementation of the plan.
|
||||
|
||||
If the high-reasoning model is unavailable or you don't have access to it,
|
||||
Gemini CLI automatically and silently falls back to a faster model to ensure
|
||||
your workflow isn't interrupted.
|
||||
|
||||
This behavior is enabled by default to provide the best balance of quality and
|
||||
performance. You can disable this automatic switching in your settings:
|
||||
|
||||
@@ -449,7 +470,8 @@ associated plan files and task trackers.
|
||||
|
||||
- **Default behavior:** Sessions (and their plans) are retained for **30 days**.
|
||||
- **Configuration:** You can customize this behavior via the `/settings` command
|
||||
(search for **Session Retention**) or in your `settings.json` file. See
|
||||
(search for **Enable Session Cleanup** or **Keep chat history**) or in your
|
||||
`settings.json` file. See
|
||||
[session retention](../cli/session-management.md#session-retention) for more
|
||||
details.
|
||||
|
||||
|
||||
+216
-45
@@ -1,11 +1,11 @@
|
||||
# Sandboxing in the Gemini CLI
|
||||
# Sandboxing in Gemini CLI
|
||||
|
||||
This document provides a guide to sandboxing in the Gemini CLI, including
|
||||
This document provides a guide to sandboxing in Gemini CLI, including
|
||||
prerequisites, quickstart, and configuration.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before using sandboxing, you need to install and set up the Gemini CLI:
|
||||
Before using sandboxing, you need to install and set up Gemini CLI:
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli
|
||||
@@ -31,6 +31,53 @@ The benefits of sandboxing include:
|
||||
- **Safety**: Reduce risk when working with untrusted code or experimental
|
||||
commands.
|
||||
|
||||
## Quickstart
|
||||
|
||||
You can enable sandboxing using a command flag, environment variable, or
|
||||
configuration file.
|
||||
|
||||
### Using the command flag
|
||||
|
||||
```bash
|
||||
gemini -s -p "analyze the code structure"
|
||||
```
|
||||
|
||||
### Using an environment variable
|
||||
|
||||
**macOS/Linux**
|
||||
|
||||
```bash
|
||||
export GEMINI_SANDBOX=true
|
||||
gemini -p "run the test suite"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
|
||||
```powershell
|
||||
$env:GEMINI_SANDBOX="true"
|
||||
gemini -p "run the test suite"
|
||||
```
|
||||
|
||||
### Configuring via settings.json
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"sandbox": "docker"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Enable sandboxing using one of the following methods (in order of precedence):
|
||||
|
||||
1. **Command flag**: `-s` or `--sandbox`
|
||||
2. **Environment variable**:
|
||||
`GEMINI_SANDBOX=true|docker|podman|sandbox-exec|runsc|lxc`
|
||||
3. **Settings file**: `"sandbox": true` in the `tools` object of your
|
||||
`settings.json` file (for example, `{"tools": {"sandbox": true}}`).
|
||||
|
||||
## Sandboxing methods
|
||||
|
||||
Your ideal method of sandboxing may differ depending on your platform and your
|
||||
@@ -43,12 +90,92 @@ Lightweight, built-in sandboxing using `sandbox-exec`.
|
||||
**Default profile**: `permissive-open` - restricts writes outside project
|
||||
directory but allows most other operations.
|
||||
|
||||
Built-in profiles (set via `SEATBELT_PROFILE` env var):
|
||||
|
||||
- `permissive-open` (default): Write restrictions, network allowed
|
||||
- `permissive-proxied`: Write restrictions, network via proxy
|
||||
- `restrictive-open`: Strict restrictions, network allowed
|
||||
- `restrictive-proxied`: Strict restrictions, network via proxy
|
||||
- `strict-open`: Read and write restrictions, network allowed
|
||||
- `strict-proxied`: Read and write restrictions, network via proxy
|
||||
|
||||
### 2. Container-based (Docker/Podman)
|
||||
|
||||
Cross-platform sandboxing with complete process isolation.
|
||||
Cross-platform sandboxing with complete process isolation using container
|
||||
technology. By default, it uses the `ghcr.io/google/gemini-cli:latest` image.
|
||||
|
||||
**Note**: Requires building the sandbox image locally or using a published image
|
||||
from your organization's registry.
|
||||
**Prerequisites:**
|
||||
|
||||
- Docker or Podman must be installed and running on your system.
|
||||
|
||||
**How it works (Workspace directory):**
|
||||
|
||||
Inside the sandbox container, your current working directory is mounted at the
|
||||
**exact same absolute path** as it is on your host machine. For example, if you
|
||||
run the CLI from `/Users/you/project` on your host machine, the sandbox will
|
||||
mount your local project folder and operate within `/Users/you/project` inside
|
||||
the container. This allows the AI to seamlessly read and modify your project
|
||||
files while remaining isolated from the rest of your system.
|
||||
|
||||
**Quick setup:**
|
||||
|
||||
To enable Docker sandboxing, run Gemini CLI with the sandbox flag and specify
|
||||
Docker as the provider:
|
||||
|
||||
```bash
|
||||
# Using the environment variable (Recommended)
|
||||
export GEMINI_SANDBOX=docker
|
||||
gemini -p "build the project"
|
||||
|
||||
# Or configure it permanently in your settings.json
|
||||
# {"tools": {"sandbox": "docker"}}
|
||||
```
|
||||
|
||||
**Customizing the Sandbox Image:**
|
||||
|
||||
If your project requires specific dependencies, you can specify a custom image
|
||||
name or have Gemini CLI build one for you automatically. You can use any Docker
|
||||
or Podman image as your sandbox, provided it has standard shell utilities (like
|
||||
`bash`) available.
|
||||
|
||||
**Option A: Using an existing custom image (e.g., Artifact Registry)**
|
||||
|
||||
To configure a custom image that is hosted on a registry (or built locally),
|
||||
update your `settings.json` to use an object for the sandbox configuration, or
|
||||
set the `GEMINI_SANDBOX_IMAGE` environment variable.
|
||||
|
||||
_Example: Configuring via `settings.json`_
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"sandbox": {
|
||||
"command": "docker",
|
||||
"image": "us-central1-docker.pkg.dev/my-project/my-repo/my-custom-sandbox:latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
_Example: Configuring via environment variable_
|
||||
|
||||
```bash
|
||||
export GEMINI_SANDBOX_IMAGE="us-central1-docker.pkg.dev/my-project/my-repo/my-custom-sandbox:latest"
|
||||
```
|
||||
|
||||
**Option B: Building a local custom image automatically**
|
||||
|
||||
If you prefer to define your environment as code, you can provide a Dockerfile
|
||||
and Gemini CLI will build the image automatically.
|
||||
|
||||
1. Create a `.gemini/sandbox.Dockerfile` in your project root.
|
||||
2. Ensure you have the `gh` CLI installed and authenticated (if you are using
|
||||
the default `ghcr.io/google/gemini-cli` image as a base).
|
||||
3. Run your command with the `BUILD_SANDBOX` environment variable set:
|
||||
|
||||
```bash
|
||||
BUILD_SANDBOX=1 GEMINI_SANDBOX=docker gemini -p "run my custom build"
|
||||
```
|
||||
|
||||
### 3. Windows Native Sandbox (Windows only)
|
||||
|
||||
@@ -136,59 +263,101 @@ gemini -p "build the snap"
|
||||
absolute path — the path must be writable inside the container.
|
||||
- Used with tools like Snapcraft or Rockcraft that require a full system.
|
||||
|
||||
## Quickstart
|
||||
## Tool sandboxing
|
||||
|
||||
```bash
|
||||
# Enable sandboxing with command flag
|
||||
gemini -s -p "analyze the code structure"
|
||||
```
|
||||
Tool-level sandboxing provides granular isolation for individual tool executions
|
||||
(like `shell_exec` and `write_file`) instead of sandboxing the entire Gemini CLI
|
||||
process.
|
||||
|
||||
**Use environment variable**
|
||||
This approach offers better integration with your local environment for non-tool
|
||||
tasks (like UI rendering and configuration loading) while still providing
|
||||
security for tool-driven operations.
|
||||
|
||||
**macOS/Linux**
|
||||
### How to turn off tool sandboxing
|
||||
|
||||
```bash
|
||||
export GEMINI_SANDBOX=true
|
||||
gemini -p "run the test suite"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
|
||||
```powershell
|
||||
$env:GEMINI_SANDBOX="true"
|
||||
gemini -p "run the test suite"
|
||||
```
|
||||
|
||||
**Configure in settings.json**
|
||||
If you experience issues with tool sandboxing or prefer full-process isolation,
|
||||
you can disable it by setting `security.toolSandboxing` to `false` in your
|
||||
`settings.json` file.
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"sandbox": "docker"
|
||||
"security": {
|
||||
"toolSandboxing": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> Changing the `security.toolSandboxing` setting requires a restart of Gemini
|
||||
> CLI to take effect.
|
||||
|
||||
### Enable sandboxing (in order of precedence)
|
||||
## Sandbox expansion
|
||||
|
||||
1. **Command flag**: `-s` or `--sandbox`
|
||||
2. **Environment variable**:
|
||||
`GEMINI_SANDBOX=true|docker|podman|sandbox-exec|runsc|lxc`
|
||||
3. **Settings file**: `"sandbox": true` in the `tools` object of your
|
||||
`settings.json` file (e.g., `{"tools": {"sandbox": true}}`).
|
||||
Sandbox expansion is a dynamic permission system that lets Gemini CLI request
|
||||
additional permissions for a command when needed.
|
||||
|
||||
### macOS Seatbelt profiles
|
||||
When a sandboxed command fails due to permission restrictions (like restricted
|
||||
file paths or network access), or when a command is proactively identified as
|
||||
requiring extra permissions (like `npm install`), Gemini CLI will present you
|
||||
with a "Sandbox Expansion Request."
|
||||
|
||||
Built-in profiles (set via `SEATBELT_PROFILE` env var):
|
||||
### How sandbox expansion works
|
||||
|
||||
- `permissive-open` (default): Write restrictions, network allowed
|
||||
- `permissive-proxied`: Write restrictions, network via proxy
|
||||
- `restrictive-open`: Strict restrictions, network allowed
|
||||
- `restrictive-proxied`: Strict restrictions, network via proxy
|
||||
- `strict-open`: Read and write restrictions, network allowed
|
||||
- `strict-proxied`: Read and write restrictions, network via proxy
|
||||
1. **Detection**: Gemini CLI detects a sandbox denial or proactively identifies
|
||||
a command that requires extra permissions.
|
||||
2. **Request**: A modal dialog is shown, explaining which additional
|
||||
permissions (e.g., specific directories or network access) are required.
|
||||
3. **Approval**: If you approve the expansion, the command is executed with the
|
||||
extended permissions for that specific run.
|
||||
|
||||
This mechanism ensures you don't have to manually re-run commands with more
|
||||
permissive sandbox settings, while still maintaining control over what the AI
|
||||
can access.
|
||||
|
||||
### Including files outside the workspace
|
||||
|
||||
By default, the sandbox only has access to the current project workspace. If you
|
||||
need the sandbox to have permission to operate on certain files or directories
|
||||
from the local file system outside of the project workspace, you can mount them
|
||||
using the `SANDBOX_MOUNTS` environment variable.
|
||||
|
||||
Provide a comma-separated list of mount definitions in the format
|
||||
`from:to:opts`. If `to` is omitted, it defaults to the same path as `from`. If
|
||||
`opts` is omitted, it defaults to `ro` (read-only). Note that the `from` path
|
||||
must be an absolute path.
|
||||
|
||||
**Example**:
|
||||
|
||||
```bash
|
||||
export SANDBOX_MOUNTS="/path/on/host:/path/in/container:rw,/another/path:ro"
|
||||
```
|
||||
|
||||
## Running inside a Docker container
|
||||
|
||||
If you are running Gemini CLI itself from within an official or custom Docker
|
||||
container and want to enable sandboxing, you must share the host's Docker socket
|
||||
and ensure your workspace paths align.
|
||||
|
||||
1. **Mount the Docker socket**: Map `/var/run/docker.sock` so the CLI can spawn
|
||||
sibling sandbox containers via the host's Docker daemon.
|
||||
2. **Align workspace paths**: The path to your workspace inside the container
|
||||
must exactly match the absolute path on the host. Because the sandbox
|
||||
container is spawned by the host's Docker daemon, it resolves volume mounts
|
||||
against the host file system.
|
||||
|
||||
**Example**:
|
||||
|
||||
```bash
|
||||
docker run -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v /absolute/path/on/host/project:/absolute/path/on/host/project \
|
||||
-w /absolute/path/on/host/project \
|
||||
-e GEMINI_SANDBOX=docker \
|
||||
ghcr.io/google/gemini-cli:latest
|
||||
```
|
||||
|
||||
## Advanced settings
|
||||
|
||||
### Custom sandbox flags
|
||||
|
||||
@@ -227,7 +396,7 @@ export SANDBOX_FLAGS="--flag1 --flag2=value"
|
||||
$env:SANDBOX_FLAGS="--flag1 --flag2=value"
|
||||
```
|
||||
|
||||
## Linux UID/GID handling
|
||||
### Linux UID/GID handling
|
||||
|
||||
The sandbox automatically handles user permissions on Linux. Override these
|
||||
permissions with:
|
||||
@@ -257,7 +426,9 @@ $env:SANDBOX_SET_UID_GID="false" # Disable UID/GID mapping
|
||||
|
||||
**Missing commands**
|
||||
|
||||
- Add to custom Dockerfile.
|
||||
- Add to a custom Dockerfile. Automatic `BUILD_SANDBOX` builds are only
|
||||
available when running Gemini CLI from source; npm installs need a prebuilt
|
||||
image instead.
|
||||
- Install via `sandbox.bashrc`.
|
||||
|
||||
**Network issues**
|
||||
|
||||
+76
-65
@@ -24,19 +24,22 @@ they appear in the UI.
|
||||
|
||||
### General
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ----------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
|
||||
| Default Approval Mode | `general.defaultApprovalMode` | The default approval mode for tool execution. 'default' prompts for approval, 'auto_edit' auto-approves edit tools, and 'plan' is read-only mode. YOLO mode (auto-approve all actions) can only be enabled via command line (--yolo or --approval-mode=yolo). | `"default"` |
|
||||
| Enable Auto Update | `general.enableAutoUpdate` | Enable automatic updates. | `true` |
|
||||
| Enable Notifications | `general.enableNotifications` | Enable run-event notifications for action-required prompts and session completion. | `false` |
|
||||
| Plan Directory | `general.plan.directory` | The directory where planning artifacts are stored. If not specified, defaults to the system temporary directory. A custom directory requires a policy to allow write access in Plan Mode. | `undefined` |
|
||||
| Plan Model Routing | `general.plan.modelRouting` | Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pro for the planning phase and Flash for the implementation phase. | `true` |
|
||||
| Retry Fetch Errors | `general.retryFetchErrors` | Retry on "exception TypeError: fetch failed sending request" errors. | `true` |
|
||||
| Max Chat Model Attempts | `general.maxAttempts` | Maximum number of attempts for requests to the main chat model. Cannot exceed 10. | `10` |
|
||||
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
|
||||
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `true` |
|
||||
| Keep chat history | `general.sessionRetention.maxAge` | Automatically delete chats older than this time period (e.g., "30d", "7d", "24h", "1w") | `"30d"` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ----------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| Vim Mode | `general.vimMode` | Enable Vim keybindings | `false` |
|
||||
| Default Approval Mode | `general.defaultApprovalMode` | The default approval mode for tool execution. 'default' prompts for approval, 'auto_edit' auto-approves edit tools, and 'plan' is read-only mode. YOLO mode (auto-approve all actions) can only be enabled via command line (--yolo or --approval-mode=yolo). | `"default"` |
|
||||
| Enable Auto Update | `general.enableAutoUpdate` | Enable automatic updates. | `true` |
|
||||
| Enable Terminal Notifications | `general.enableNotifications` | Enable terminal run-event notifications for action-required prompts and session completion. | `false` |
|
||||
| Terminal Notification Method | `general.notificationMethod` | How to send terminal notifications. | `"auto"` |
|
||||
| Enable Plan Mode | `general.plan.enabled` | Enable Plan Mode for read-only safety during planning. | `true` |
|
||||
| Plan Directory | `general.plan.directory` | The directory where planning artifacts are stored. If not specified, defaults to the system temporary directory. A custom directory requires a policy to allow write access in Plan Mode. | `undefined` |
|
||||
| Plan Model Routing | `general.plan.modelRouting` | Automatically switch between Pro and Flash models based on Plan Mode status. Uses Pro for the planning phase and Flash for the implementation phase. | `true` |
|
||||
| Retry Fetch Errors | `general.retryFetchErrors` | Retry on "exception TypeError: fetch failed sending request" errors. | `true` |
|
||||
| Max Chat Model Attempts | `general.maxAttempts` | Maximum number of attempts for requests to the main chat model. Cannot exceed 10. | `10` |
|
||||
| Debug Keystroke Logging | `general.debugKeystrokeLogging` | Enable debug logging of keystrokes to the console. | `false` |
|
||||
| Enable Session Cleanup | `general.sessionRetention.enabled` | Enable automatic session cleanup | `true` |
|
||||
| Keep chat history | `general.sessionRetention.maxAge` | Automatically delete chats older than this time period (e.g., "30d", "7d", "24h", "1w") | `"30d"` |
|
||||
| Topic & Update Narration | `general.topicUpdateNarration` | Enable the Topic & Update communication model for reduced chattiness and structured progress reporting. | `true` |
|
||||
|
||||
### Output
|
||||
|
||||
@@ -46,38 +49,41 @@ they appear in the UI.
|
||||
|
||||
### UI
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
|
||||
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
|
||||
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
|
||||
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
|
||||
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
|
||||
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
|
||||
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
|
||||
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
|
||||
| Show Compatibility Warnings | `ui.showCompatibilityWarnings` | Show warnings about terminal or OS compatibility issues. | `true` |
|
||||
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
|
||||
| Escape Pasted @ Symbols | `ui.escapePastedAtSymbols` | When enabled, @ symbols in pasted text are escaped to prevent unintended @path expansion. | `false` |
|
||||
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
|
||||
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
|
||||
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
|
||||
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory in the footer. | `false` |
|
||||
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
|
||||
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
|
||||
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window usage percentage. | `true` |
|
||||
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
|
||||
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
|
||||
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
|
||||
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
|
||||
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
|
||||
| Show User Identity | `ui.showUserIdentity` | Show the signed-in user's identity (e.g. email) in the UI. | `true` |
|
||||
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
|
||||
| Use Background Color | `ui.useBackgroundColor` | Whether to use background colors in the UI. | `true` |
|
||||
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
|
||||
| Show Spinner | `ui.showSpinner` | Show the spinner during operations. | `true` |
|
||||
| Loading Phrases | `ui.loadingPhrases` | What to show while the model is working: tips, witty comments, both, or nothing. | `"tips"` |
|
||||
| Error Verbosity | `ui.errorVerbosity` | Controls whether recoverable errors are hidden (low) or fully shown (full). | `"low"` |
|
||||
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Auto Theme Switching | `ui.autoThemeSwitching` | Automatically switch between default light and dark themes based on terminal background color. | `true` |
|
||||
| Terminal Background Polling Interval | `ui.terminalBackgroundPollingInterval` | Interval in seconds to poll the terminal background color. | `60` |
|
||||
| Hide Window Title | `ui.hideWindowTitle` | Hide the window title bar | `false` |
|
||||
| Inline Thinking | `ui.inlineThinkingMode` | Display model thinking inline: off or full. | `"off"` |
|
||||
| Show Thoughts in Title | `ui.showStatusInTitle` | Show Gemini CLI model thoughts in the terminal window title during the working phase | `false` |
|
||||
| Dynamic Window Title | `ui.dynamicWindowTitle` | Update the terminal window title with current status icons (Ready: ◇, Action Required: ✋, Working: ✦) | `true` |
|
||||
| Show Home Directory Warning | `ui.showHomeDirectoryWarning` | Show a warning when running Gemini CLI in the home directory. | `true` |
|
||||
| Show Compatibility Warnings | `ui.showCompatibilityWarnings` | Show warnings about terminal or OS compatibility issues. | `true` |
|
||||
| Hide Tips | `ui.hideTips` | Hide helpful tips in the UI | `false` |
|
||||
| Escape Pasted @ Symbols | `ui.escapePastedAtSymbols` | When enabled, @ symbols in pasted text are escaped to prevent unintended @path expansion. | `false` |
|
||||
| Show Shortcuts Hint | `ui.showShortcutsHint` | Show the "? for shortcuts" hint above the input. | `true` |
|
||||
| Compact Tool Output | `ui.compactToolOutput` | Display tool outputs (like directory listings and file reads) in a compact, structured format. | `true` |
|
||||
| Hide Banner | `ui.hideBanner` | Hide the application banner | `false` |
|
||||
| Hide Context Summary | `ui.hideContextSummary` | Hide the context summary (GEMINI.md, MCP servers) above the input. | `false` |
|
||||
| Hide CWD | `ui.footer.hideCWD` | Hide the current working directory in the footer. | `false` |
|
||||
| Hide Sandbox Status | `ui.footer.hideSandboxStatus` | Hide the sandbox status indicator in the footer. | `false` |
|
||||
| Hide Model Info | `ui.footer.hideModelInfo` | Hide the model name and context usage in the footer. | `false` |
|
||||
| Hide Context Window Percentage | `ui.footer.hideContextPercentage` | Hides the context window usage percentage. | `true` |
|
||||
| Hide Footer | `ui.hideFooter` | Hide the footer from the UI | `false` |
|
||||
| Show Memory Usage | `ui.showMemoryUsage` | Display memory usage information in the UI | `false` |
|
||||
| Show Line Numbers | `ui.showLineNumbers` | Show line numbers in the chat. | `true` |
|
||||
| Show Citations | `ui.showCitations` | Show citations for generated text in the chat. | `false` |
|
||||
| Show Model Info In Chat | `ui.showModelInfoInChat` | Show the model name in the chat for each model turn. | `false` |
|
||||
| Show User Identity | `ui.showUserIdentity` | Show the signed-in user's identity (e.g. email) in the UI. | `true` |
|
||||
| Use Alternate Screen Buffer | `ui.useAlternateBuffer` | Use an alternate screen buffer for the UI, preserving shell history. | `false` |
|
||||
| Render Process | `ui.renderProcess` | Enable Ink render process for the UI. | `true` |
|
||||
| Terminal Buffer | `ui.terminalBuffer` | Use the new terminal buffer architecture for rendering. | `false` |
|
||||
| Use Background Color | `ui.useBackgroundColor` | Whether to use background colors in the UI. | `true` |
|
||||
| Incremental Rendering | `ui.incrementalRendering` | Enable incremental rendering for the UI. This option will reduce flickering but may cause rendering artifacts. Only supported when useAlternateBuffer is enabled. | `true` |
|
||||
| Show Spinner | `ui.showSpinner` | Show the spinner during operations. | `true` |
|
||||
| Loading Phrases | `ui.loadingPhrases` | What to show while the model is working: tips, witty comments, all, or off. | `"off"` |
|
||||
| Error Verbosity | `ui.errorVerbosity` | Controls whether recoverable errors are hidden (low) or fully shown (full). | `"low"` |
|
||||
| Screen Reader Mode | `ui.accessibility.screenReader` | Render output in plain-text to be more screen reader accessible | `false` |
|
||||
|
||||
### IDE
|
||||
|
||||
@@ -127,7 +133,7 @@ they appear in the UI.
|
||||
| Sandbox Allowed Paths | `tools.sandboxAllowedPaths` | List of additional paths that the sandbox is allowed to access. | `[]` |
|
||||
| Sandbox Network Access | `tools.sandboxNetworkAccess` | Whether the sandbox is allowed to access the network. | `false` |
|
||||
| Enable Interactive Shell | `tools.shell.enableInteractiveShell` | Use node-pty for an interactive shell experience. Fallback to child_process still applies. | `true` |
|
||||
| Show Color | `tools.shell.showColor` | Show color in shell output. | `false` |
|
||||
| Show Color | `tools.shell.showColor` | Show color in shell output. | `true` |
|
||||
| Use Ripgrep | `tools.useRipgrep` | Use ripgrep for file content search instead of the fallback implementation. Provides faster search performance. | `true` |
|
||||
| Tool Output Truncation Threshold | `tools.truncateToolOutputThreshold` | Maximum characters to show when truncating large tool outputs. Set to 0 or negative to disable truncation. | `40000` |
|
||||
| Disable LLM Correction | `tools.disableLLMCorrection` | Disable LLM-based error correction for edit tools. When enabled, tools will fail immediately if exact string matches are not found, instead of attempting to self-correct. | `true` |
|
||||
@@ -136,7 +142,7 @@ they appear in the UI.
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
||||
| Tool Sandboxing | `security.toolSandboxing` | Experimental tool-level sandboxing (implementation in progress). | `false` |
|
||||
| Tool Sandboxing | `security.toolSandboxing` | Tool-level sandboxing. Isolates individual tools instead of the entire CLI process. | `false` |
|
||||
| Disable YOLO Mode | `security.disableYoloMode` | Disable YOLO mode, even if enabled by a flag. | `false` |
|
||||
| Disable Always Allow | `security.disableAlwaysAllow` | Disable "Always allow" options in tool confirmation dialogs. | `false` |
|
||||
| Allow Permanent Tool Approval | `security.enablePermanentToolApproval` | Enable the "Allow for all future sessions" option in tool confirmation dialogs. | `false` |
|
||||
@@ -149,27 +155,32 @@ they appear in the UI.
|
||||
|
||||
### Advanced
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| --------------------------------- | ------------------------------ | --------------------------------------------- | ------- |
|
||||
| Auto Configure Max Old Space Size | `advanced.autoConfigureMemory` | Automatically configure Node.js memory limits | `false` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| --------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Auto Configure Max Old Space Size | `advanced.autoConfigureMemory` | Automatically configure Node.js memory limits. Note: Because memory is allocated during the initial process boot, this setting is only read from the global user settings file and ignores workspace-level overrides. | `true` |
|
||||
| Ignore Local .env | `advanced.ignoreLocalEnv` | Whether to ignore generic .env files in the project directory. | `false` |
|
||||
|
||||
### Experimental
|
||||
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ---------------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Enable Tool Output Masking | `experimental.toolOutputMasking.enabled` | Enables tool output masking to save tokens. | `true` |
|
||||
| Enable Git Worktrees | `experimental.worktrees` | Enable automated Git worktree management for parallel work. | `false` |
|
||||
| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 for pasting. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
|
||||
| Use OSC 52 Copy | `experimental.useOSC52Copy` | Use OSC 52 for copying. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
|
||||
| Plan | `experimental.plan` | Enable Plan Mode. | `true` |
|
||||
| Model Steering | `experimental.modelSteering` | Enable model steering (user hints) to guide the model during tool execution. | `false` |
|
||||
| Direct Web Fetch | `experimental.directWebFetch` | Enable web fetch behavior that bypasses LLM summarization. | `false` |
|
||||
| Memory Manager Agent | `experimental.memoryManager` | Replace the built-in save_memory tool with a memory manager subagent that supports adding, removing, de-duplicating, and organizing memories. | `false` |
|
||||
| Agent History Truncation | `experimental.agentHistoryTruncation` | Enable truncation window logic for the Agent History Provider. | `false` |
|
||||
| Agent History Truncation Threshold | `experimental.agentHistoryTruncationThreshold` | The maximum number of messages before history is truncated. | `30` |
|
||||
| Agent History Retained Messages | `experimental.agentHistoryRetainedMessages` | The number of recent messages to retain after truncation. | `15` |
|
||||
| Agent History Summarization | `experimental.agentHistorySummarization` | Enable summarization of truncated content via a small model for the Agent History Provider. | `false` |
|
||||
| Topic & Update Narration | `experimental.topicUpdateNarration` | Enable the experimental Topic & Update communication model for reduced chattiness and structured progress reporting. | `false` |
|
||||
| UI Label | Setting | Description | Default |
|
||||
| ---------------------------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
||||
| Gemma Models | `experimental.gemma` | Enable access to Gemma 4 models via Gemini API. | `true` |
|
||||
| Voice Mode | `experimental.voiceMode` | Enable experimental voice dictation and commands (/voice, /voice model). | `false` |
|
||||
| Voice Activation Mode | `experimental.voice.activationMode` | How to trigger voice recording with the Space key. | `"push-to-talk"` |
|
||||
| Voice Transcription Backend | `experimental.voice.backend` | The backend to use for voice transcription. Note: When using the Gemini Live backend, voice recordings are sent to Google Cloud for transcription. | `"gemini-live"` |
|
||||
| Whisper Model | `experimental.voice.whisperModel` | The Whisper model to use for local transcription. | `"ggml-base.en.bin"` |
|
||||
| Voice Stop Grace Period (ms) | `experimental.voice.stopGracePeriodMs` | How long to wait for final transcription after stopping recording. | `4000` |
|
||||
| Enable Git Worktrees | `experimental.worktrees` | Enable automated Git worktree management for parallel work. | `false` |
|
||||
| Use OSC 52 Paste | `experimental.useOSC52Paste` | Use OSC 52 for pasting. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
|
||||
| Use OSC 52 Copy | `experimental.useOSC52Copy` | Use OSC 52 for copying. This may be more robust than the default system when using remote terminal sessions (if your terminal is configured to allow it). | `false` |
|
||||
| Model Steering | `experimental.modelSteering` | Enable model steering (user hints) to guide the model during tool execution. | `false` |
|
||||
| Direct Web Fetch | `experimental.directWebFetch` | Enable web fetch behavior that bypasses LLM summarization. | `false` |
|
||||
| Enable Gemma Model Router | `experimental.gemmaModelRouter.enabled` | Enable the Gemma Model Router (experimental). Requires a local endpoint serving Gemma via the Gemini API using LiteRT-LM shim. | `false` |
|
||||
| Auto-start LiteRT Server | `experimental.gemmaModelRouter.autoStartServer` | Automatically start the LiteRT-LM server when Gemini CLI starts and the Gemma router is enabled. | `false` |
|
||||
| Memory v2 | `experimental.memoryV2` | Disable the built-in save_memory tool and let the main agent persist project context by editing markdown files directly with edit/write_file. Route facts across four tiers: team-shared conventions go to project GEMINI.md files, project-specific personal notes go to the per-project private memory folder (MEMORY.md as index + sibling .md files for detail), and cross-project personal preferences go to the global ~/.gemini/GEMINI.md (the only file under ~/.gemini/ that the agent can edit — settings, credentials, etc. remain off-limits). Set to false to fall back to the legacy save_memory tool. | `true` |
|
||||
| Auto Memory | `experimental.autoMemory` | Automatically extract memory patches and skills from past sessions in the background. Every change is written as a unified diff `.patch` file under `<projectMemoryDir>/.inbox/<kind>/` and held for review in /memory inbox; nothing is applied until you approve it. | `false` |
|
||||
| Use the generalist profile to manage agent contexts. | `experimental.generalistProfile` | Suitable for general coding and software development tasks. | `false` |
|
||||
| Enable Context Management | `experimental.contextManagement` | Enable logic for context management. | `false` |
|
||||
|
||||
### Skills
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# Agent Skill best practices
|
||||
|
||||
Create high-quality, reliable Agent Skills by following these established design
|
||||
principles and patterns.
|
||||
|
||||
## Design for discovery
|
||||
|
||||
The most important part of a skill is its `description`. This is the only
|
||||
information the model has before activation.
|
||||
|
||||
- **Be specific**: Use keywords that are likely to appear in user prompts (for
|
||||
example, "audit," "security," "refactor," "migration").
|
||||
- **Define the trigger**: Clearly state _when_ the skill should be used (for
|
||||
example, "Use this skill when the user asks to review a PR for performance
|
||||
regressions").
|
||||
- **Avoid overlap**: Ensure your skill descriptions are distinct from one
|
||||
another and from the general capabilities of the model.
|
||||
|
||||
## Progressive disclosure
|
||||
|
||||
The "context window" is a shared resource. Use a three-level loading system to
|
||||
manage context efficiently.
|
||||
|
||||
1. **Metadata (name + description)**: Always in context (~100 words).
|
||||
2. **`SKILL.md` body**: Loaded only after the skill triggers (<5k words).
|
||||
3. **Bundled resources**: Loaded only as needed by the model.
|
||||
|
||||
**Best practice**: Keep the `SKILL.md` body focused on core procedural
|
||||
instructions. Move detailed reference material, schemas, and examples into
|
||||
separate files in a `references/` directory.
|
||||
|
||||
## Degrees of freedom
|
||||
|
||||
Match the level of instruction specificity to the task's fragility.
|
||||
|
||||
- **High freedom (text-based instructions)**: Use when multiple approaches are
|
||||
valid or decisions depend heavily on context.
|
||||
- **Medium freedom (pseudocode or scripts with parameters)**: Use when a
|
||||
preferred pattern exists but some variation is acceptable.
|
||||
- **Low freedom (specific scripts, few parameters)**: Use when operations are
|
||||
fragile and error-prone, or a specific sequence MUST be followed.
|
||||
|
||||
## Bundle resources effectively
|
||||
|
||||
Leverage the skill's ability to include scripts and assets to extend the agent's
|
||||
capabilities.
|
||||
|
||||
- **Use scripts for deterministic tasks**: If a task can be automated with a
|
||||
script (for example, running a linter, fetching data from an API), bundle it
|
||||
in the `scripts/` folder.
|
||||
- **Agentic ergonomics**: Ensure scripts output LLM-friendly stdout. Suppress
|
||||
verbose tracebacks and provide clear, concise success/failure messages.
|
||||
- **Provide templates**: Include common file headers or boilerplate code in the
|
||||
`assets/` folder to ensure the agent produces consistent output.
|
||||
|
||||
## Anatomy of a great skill
|
||||
|
||||
A well-structured skill directory organizes its resources into specialized
|
||||
sub-folders.
|
||||
|
||||
```text
|
||||
my-skill/
|
||||
├── SKILL.md (Required) Core instructions and metadata
|
||||
├── scripts/ (Optional) Executable logic (Node.js, Python, etc.)
|
||||
├── references/ (Optional) Documentation to be loaded as needed
|
||||
└── assets/ (Optional) Templates and non-executable resources
|
||||
```
|
||||
|
||||
## Security and privacy
|
||||
|
||||
Design your skills with security in mind to protect your workspace and data.
|
||||
|
||||
- **Avoid hardcoded secrets**: Never include API keys or passwords in your
|
||||
skill's scripts or documentation.
|
||||
- **Review third-party skills**: Inspect the `SKILL.md` and scripts of any skill
|
||||
before installing it from an untrusted source.
|
||||
- **Limit scope**: Design skills to be as focused as possible to minimize the
|
||||
potential impact of errors.
|
||||
+113
-108
@@ -1,112 +1,21 @@
|
||||
# Agent Skills
|
||||
|
||||
Agent Skills allow you to extend Gemini CLI with specialized expertise,
|
||||
procedural workflows, and task-specific resources. Based on the
|
||||
Agent Skills let you extend Gemini CLI with specialized expertise, procedural
|
||||
workflows, and task-specific resources. Based on the
|
||||
[Agent Skills](https://agentskills.io) open standard, a "skill" is a
|
||||
self-contained directory that packages instructions and assets into a
|
||||
discoverable capability.
|
||||
|
||||
## Overview
|
||||
|
||||
Unlike general context files ([`GEMINI.md`](./gemini-md.md)), which provide
|
||||
Unlike general context files ([GEMINI.md](./gemini-md.md)), which provide
|
||||
persistent workspace-wide background, Skills represent **on-demand expertise**.
|
||||
This allows Gemini to maintain a vast library of specialized capabilities—such
|
||||
as security auditing, cloud deployments, or codebase migrations—without
|
||||
cluttering the model's immediate context window.
|
||||
This lets Gemini CLI maintain a vast library of specialized capabilities—such as
|
||||
security auditing, cloud deployments, or codebase migrations—without cluttering
|
||||
the model's immediate context window.
|
||||
|
||||
Gemini autonomously decides when to employ a skill based on your request and the
|
||||
skill's description. When a relevant skill is identified, the model "pulls in"
|
||||
the full instructions and resources required to complete the task using the
|
||||
`activate_skill` tool.
|
||||
## How it works
|
||||
|
||||
## Key Benefits
|
||||
|
||||
- **Shared Expertise:** Package complex workflows (like a specific team's PR
|
||||
review process) into a folder that anyone can use.
|
||||
- **Repeatable Workflows:** Ensure complex multi-step tasks are performed
|
||||
consistently by providing a procedural framework.
|
||||
- **Resource Bundling:** Include scripts, templates, or example data alongside
|
||||
instructions so the agent has everything it needs.
|
||||
- **Progressive Disclosure:** Only skill metadata (name and description) is
|
||||
loaded initially. Detailed instructions and resources are only disclosed when
|
||||
the model explicitly activates the skill, saving context tokens.
|
||||
|
||||
## Skill Discovery Tiers
|
||||
|
||||
Gemini CLI discovers skills from three primary locations:
|
||||
|
||||
1. **Workspace Skills**: Located in `.gemini/skills/` or the `.agents/skills/`
|
||||
alias. Workspace skills are typically committed to version control and
|
||||
shared with the team.
|
||||
2. **User Skills**: Located in `~/.gemini/skills/` or the `~/.agents/skills/`
|
||||
alias. These are personal skills available across all your workspaces.
|
||||
3. **Extension Skills**: Skills bundled within installed
|
||||
[extensions](../extensions/index.md).
|
||||
|
||||
**Precedence:** If multiple skills share the same name, higher-precedence
|
||||
locations override lower ones: **Workspace > User > Extension**.
|
||||
|
||||
Within the same tier (user or workspace), the `.agents/skills/` alias takes
|
||||
precedence over the `.gemini/skills/` directory. This generic alias provides an
|
||||
intuitive path for managing agent-specific expertise that remains compatible
|
||||
across different AI agent tools.
|
||||
|
||||
## Managing Skills
|
||||
|
||||
### In an Interactive Session
|
||||
|
||||
Use the `/skills` slash command to view and manage available expertise:
|
||||
|
||||
- `/skills list` (default): Shows all discovered skills and their status.
|
||||
- `/skills link <path>`: Links agent skills from a local directory via symlink.
|
||||
- `/skills disable <name>`: Prevents a specific skill from being used.
|
||||
- `/skills enable <name>`: Re-enables a disabled skill.
|
||||
- `/skills reload`: Refreshes the list of discovered skills from all tiers.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> `/skills disable` and `/skills enable` default to the `user` scope. Use
|
||||
> `--scope workspace` to manage workspace-specific settings.
|
||||
|
||||
### From the Terminal
|
||||
|
||||
The `gemini skills` command provides management utilities:
|
||||
|
||||
```bash
|
||||
# List all discovered skills
|
||||
gemini skills list
|
||||
|
||||
# Link agent skills from a local directory via symlink
|
||||
# Discovers skills (SKILL.md or */SKILL.md) and creates symlinks in ~/.gemini/skills
|
||||
# (or ~/.agents/skills)
|
||||
gemini skills link /path/to/my-skills-repo
|
||||
|
||||
# Link to the workspace scope (.gemini/skills or .agents/skills)
|
||||
gemini skills link /path/to/my-skills-repo --scope workspace
|
||||
|
||||
# Install a skill from a Git repository, local directory, or zipped skill file (.skill)
|
||||
# Uses the user scope by default (~/.gemini/skills or ~/.agents/skills)
|
||||
gemini skills install https://github.com/user/repo.git
|
||||
gemini skills install /path/to/local/skill
|
||||
gemini skills install /path/to/local/my-expertise.skill
|
||||
|
||||
# Install a specific skill from a monorepo or subdirectory using --path
|
||||
gemini skills install https://github.com/my-org/my-skills.git --path skills/frontend-design
|
||||
|
||||
# Install to the workspace scope (.gemini/skills or .agents/skills)
|
||||
gemini skills install /path/to/skill --scope workspace
|
||||
|
||||
# Uninstall a skill by name
|
||||
gemini skills uninstall my-expertise --scope workspace
|
||||
|
||||
# Enable a skill (globally)
|
||||
gemini skills enable my-expertise
|
||||
|
||||
# Disable a skill. Can use --scope to specify workspace or user (defaults to workspace)
|
||||
gemini skills disable my-expertise --scope workspace
|
||||
```
|
||||
|
||||
## How it Works
|
||||
The lifecycle of an Agent Skill involves discovery, activation, and conditional
|
||||
resource access.
|
||||
|
||||
1. **Discovery**: At the start of a session, Gemini CLI scans the discovery
|
||||
tiers and injects the name and description of all enabled skills into the
|
||||
@@ -123,14 +32,110 @@ gemini skills disable my-expertise --scope workspace
|
||||
5. **Execution**: The model proceeds with the specialized expertise active. It
|
||||
is instructed to prioritize the skill's procedural guidance within reason.
|
||||
|
||||
### Skill activation
|
||||
## Discovery tiers
|
||||
|
||||
Once a skill is activated (typically by Gemini identifying a task that matches
|
||||
the skill's description and your approval), its specialized instructions and
|
||||
resources are loaded into the agent's context. A skill remains active and its
|
||||
guidance is prioritized for the duration of the session.
|
||||
Gemini CLI discovers skills from several locations, following a specific order
|
||||
of precedence (lowest to highest):
|
||||
|
||||
## Creating your own skills
|
||||
1. **Built-in skills**: Standard skills included with Gemini CLI that provide
|
||||
foundational capabilities.
|
||||
2. **Extension skills**: Skills bundled within installed
|
||||
[extensions](../extensions/index.md).
|
||||
3. **User skills**: Located in `~/.gemini/skills/` or the `~/.agents/skills/`
|
||||
alias.
|
||||
4. **Workspace skills**: Located in `.gemini/skills/` or the `.agents/skills/`
|
||||
alias. Workspace skills are shared with your team via version control.
|
||||
|
||||
To create your own skills, see the [Create Agent Skills](./creating-skills.md)
|
||||
guide.
|
||||
### Precedence and aliases
|
||||
|
||||
If multiple skills share the same name, the version from the higher-precedence
|
||||
location is used. Within the same tier (user or workspace), the
|
||||
`.agents/skills/` alias takes precedence over the `.gemini/skills/` directory.
|
||||
|
||||
The `.agents/skills/` alias provides an interoperable path for managing
|
||||
agent-specific expertise that remains compatible across different AI tools.
|
||||
|
||||
## Key benefits
|
||||
|
||||
Agent Skills provide several advantages for managing specialized knowledge and
|
||||
complex workflows.
|
||||
|
||||
- **Shared expertise**: Package complex workflows (like a specific team's PR
|
||||
review process) into a folder that anyone can use.
|
||||
- **Repeatable workflows**: Ensure complex multi-step tasks are performed
|
||||
consistently by providing a procedural framework.
|
||||
- **Resource bundling**: Include scripts, templates, or example data alongside
|
||||
instructions so the agent has everything it needs.
|
||||
- **Progressive disclosure**: Only skill metadata (name and description) is
|
||||
loaded initially. Detailed instructions and resources are only disclosed when
|
||||
the model explicitly activates the skill, saving context tokens.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> `/skills disable` and `/skills enable` default to the `user` scope. Use
|
||||
> `--scope workspace` to manage workspace-specific settings.
|
||||
|
||||
To see all available skills in your current session, use the `/skills list`
|
||||
command.
|
||||
|
||||
## Managing skills
|
||||
|
||||
You can manage Agent Skills through interactive session commands or directly
|
||||
from your terminal.
|
||||
|
||||
### In an interactive session
|
||||
|
||||
Use the `/skills` slash command to view and manage available expertise:
|
||||
|
||||
- `/skills list [all] [nodesc]`: Shows discovered skills. Use `all` to include
|
||||
built-in skills and `nodesc` to hide descriptions.
|
||||
- `/skills link <path> [--scope user|workspace]`: Links skills from a local
|
||||
directory.
|
||||
- `/skills disable <name>`: Prevents a specific skill from being used.
|
||||
- `/skills enable <name>`: Re-enables a disabled skill.
|
||||
- `/skills reload` (or `/skills refresh`): Refreshes the list of discovered
|
||||
skills from all tiers.
|
||||
|
||||
### From the terminal
|
||||
|
||||
The `gemini skills` command provides management utilities:
|
||||
|
||||
```bash
|
||||
# List all discovered skills. Use --all to include built-in skills.
|
||||
gemini skills list --all
|
||||
|
||||
# Install a skill from a Git repository or local directory.
|
||||
# Use --consent to skip the security confirmation prompt.
|
||||
gemini skills install https://github.com/user/repo.git --consent
|
||||
|
||||
# Uninstall a skill.
|
||||
gemini skills uninstall my-skill --scope workspace
|
||||
```
|
||||
|
||||
#### Command options
|
||||
|
||||
The skill management commands support several global and command-specific
|
||||
options.
|
||||
|
||||
- `--scope`: Either `user` (global, default) or `workspace` (local to the
|
||||
project).
|
||||
- `--path`: The sub-directory within a Git repository containing the skill.
|
||||
- `--consent`: Acknowledge security risks and skip the interactive confirmation
|
||||
during installation.
|
||||
|
||||
For more details on CLI commands, see the
|
||||
[CLI reference](./cli-reference.md#skills-management).
|
||||
|
||||
## Next steps
|
||||
|
||||
Explore these resources to refine your skills and understand the framework
|
||||
better.
|
||||
|
||||
- [Get started with Agent Skills](./tutorials/skills-getting-started.md): A
|
||||
quick walkthrough of triggering and using skills.
|
||||
- [Creating Agent Skills](./creating-skills.md): Create your first skill and
|
||||
bundle custom logic.
|
||||
- [Using Agent Skills](./using-agent-skills.md): Learn how to leverage built-in
|
||||
and custom skills.
|
||||
- [Best practices](./skills-best-practices.md): Learn strategies for building
|
||||
effective skills.
|
||||
|
||||
@@ -24,7 +24,7 @@ project-specific behavior or create a customized persona.
|
||||
|
||||
You can set the environment variable temporarily in your shell, or persist it
|
||||
via a `.gemini/.env` file. See
|
||||
[Persisting Environment Variables](../get-started/authentication.md#persisting-environment-variables).
|
||||
[Persisting Environment Variables](../get-started/authentication.mdx#persisting-environment-variables).
|
||||
|
||||
- Use the project default path (`.gemini/system.md`):
|
||||
- `GEMINI_SYSTEM_MD=true` or `GEMINI_SYSTEM_MD=1`
|
||||
@@ -35,7 +35,7 @@ via a `.gemini/.env` file. See
|
||||
- `GEMINI_SYSTEM_MD=/absolute/path/to/my-system.md`
|
||||
- Relative paths are supported and resolved from the current working
|
||||
directory.
|
||||
- Tilde expansion is supported (e.g., `~/my-system.md`).
|
||||
- Tilde expansion is supported (for example, `~/my-system.md`).
|
||||
|
||||
- Disable the override (use built‑in prompt):
|
||||
- `GEMINI_SYSTEM_MD=false` or `GEMINI_SYSTEM_MD=0` or unset the variable.
|
||||
@@ -51,7 +51,7 @@ error with: `missing system prompt file '<path>'`.
|
||||
- Create `.gemini/system.md`, then add to `.gemini/.env`:
|
||||
- `GEMINI_SYSTEM_MD=1`
|
||||
- Use a custom file under your home directory:
|
||||
- `GEMINI_SYSTEM_MD=~/prompts/SYSTEM.md gemini`
|
||||
- `GEMINI_SYSTEM_MD=~/prompts/system.md gemini`
|
||||
|
||||
## UI indicator
|
||||
|
||||
@@ -70,7 +70,7 @@ dynamically include built-in content:
|
||||
- `${AvailableTools}`: Injects a bulleted list of all currently enabled tool
|
||||
names.
|
||||
- Tool Name Variables: Injects the actual name of a tool using the pattern:
|
||||
`${toolName}_ToolName` (e.g., `${write_file_ToolName}`,
|
||||
`${toolName}_ToolName` (for example, `${write_file_ToolName}`,
|
||||
`${run_shell_command_ToolName}`).
|
||||
|
||||
This pattern is generated dynamically for all available tools.
|
||||
@@ -102,17 +102,17 @@ safety and workflow rules.
|
||||
|
||||
This creates the file and writes the current built‑in system prompt to it.
|
||||
|
||||
## Best practices: SYSTEM.md vs GEMINI.md
|
||||
## Best practices: system.md vs GEMINI.md
|
||||
|
||||
- SYSTEM.md (firmware):
|
||||
- system.md (firmware):
|
||||
- Non‑negotiable operational rules: safety, tool‑use protocols, approvals, and
|
||||
mechanics that keep the CLI reliable.
|
||||
- Stable across tasks and projects (or per project when needed).
|
||||
- GEMINI.md (strategy):
|
||||
- Persona, goals, methodologies, and project/domain context.
|
||||
- Evolves per task; relies on SYSTEM.md for safe execution.
|
||||
- Evolves per task; relies on system.md for safe execution.
|
||||
|
||||
Keep SYSTEM.md minimal but complete for safety and tool operation. Keep
|
||||
Keep system.md minimal but complete for safety and tool operation. Keep
|
||||
GEMINI.md focused on high‑level guidance and project specifics.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
+18
-11
@@ -35,17 +35,18 @@ The observability system provides:
|
||||
You control telemetry behavior through the `.gemini/settings.json` file.
|
||||
Environment variables can override these settings.
|
||||
|
||||
| Setting | Environment Variable | Description | Values | Default |
|
||||
| -------------- | -------------------------------- | --------------------------------------------------- | ----------------- | ----------------------- |
|
||||
| `enabled` | `GEMINI_TELEMETRY_ENABLED` | Enable or disable telemetry | `true`/`false` | `false` |
|
||||
| `target` | `GEMINI_TELEMETRY_TARGET` | Where to send telemetry data | `"gcp"`/`"local"` | `"local"` |
|
||||
| `otlpEndpoint` | `GEMINI_TELEMETRY_OTLP_ENDPOINT` | OTLP collector endpoint | URL string | `http://localhost:4317` |
|
||||
| `otlpProtocol` | `GEMINI_TELEMETRY_OTLP_PROTOCOL` | OTLP transport protocol | `"grpc"`/`"http"` | `"grpc"` |
|
||||
| `outfile` | `GEMINI_TELEMETRY_OUTFILE` | Save telemetry to file (overrides `otlpEndpoint`) | file path | - |
|
||||
| `logPrompts` | `GEMINI_TELEMETRY_LOG_PROMPTS` | Include prompts in telemetry logs | `true`/`false` | `true` |
|
||||
| `useCollector` | `GEMINI_TELEMETRY_USE_COLLECTOR` | Use external OTLP collector (advanced) | `true`/`false` | `false` |
|
||||
| `useCliAuth` | `GEMINI_TELEMETRY_USE_CLI_AUTH` | Use CLI credentials for telemetry (GCP target only) | `true`/`false` | `false` |
|
||||
| - | `GEMINI_CLI_SURFACE` | Optional custom label for traffic reporting | string | - |
|
||||
| Setting | Environment Variable | Description | Values | Default |
|
||||
| -------------- | --------------------------------- | --------------------------------------------------- | ----------------- | ----------------------- |
|
||||
| `enabled` | `GEMINI_TELEMETRY_ENABLED` | Enable or disable telemetry | `true`/`false` | `false` |
|
||||
| `traces` | `GEMINI_TELEMETRY_TRACES_ENABLED` | Enable detailed attribute tracing | `true`/`false` | `false` |
|
||||
| `target` | `GEMINI_TELEMETRY_TARGET` | Where to send telemetry data | `"gcp"`/`"local"` | `"local"` |
|
||||
| `otlpEndpoint` | `GEMINI_TELEMETRY_OTLP_ENDPOINT` | OTLP collector endpoint | URL string | `http://localhost:4317` |
|
||||
| `otlpProtocol` | `GEMINI_TELEMETRY_OTLP_PROTOCOL` | OTLP transport protocol | `"grpc"`/`"http"` | `"grpc"` |
|
||||
| `outfile` | `GEMINI_TELEMETRY_OUTFILE` | Save telemetry to file (overrides `otlpEndpoint`) | file path | - |
|
||||
| `logPrompts` | `GEMINI_TELEMETRY_LOG_PROMPTS` | Include prompts in telemetry logs | `true`/`false` | `true` |
|
||||
| `useCollector` | `GEMINI_TELEMETRY_USE_COLLECTOR` | Use external OTLP collector (advanced) | `true`/`false` | `false` |
|
||||
| `useCliAuth` | `GEMINI_TELEMETRY_USE_CLI_AUTH` | Use CLI credentials for telemetry (GCP target only) | `true`/`false` | `false` |
|
||||
| - | `GEMINI_CLI_SURFACE` | Optional custom label for traffic reporting | string | - |
|
||||
|
||||
**Note on boolean environment variables:** For boolean settings like `enabled`,
|
||||
setting the environment variable to `true` or `1` enables the feature.
|
||||
@@ -1235,6 +1236,12 @@ These metrics follow standard [OpenTelemetry GenAI semantic conventions].
|
||||
Traces provide an "under-the-hood" view of agent and backend operations. Use
|
||||
traces to debug tool interactions and optimize performance.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> Detailed trace attributes (like full prompts and tool outputs) are disabled by default
|
||||
> to minimize overhead. You must explicitly set `telemetry.traces` to `true` (or set
|
||||
> `GEMINI_TELEMETRY_TRACES_ENABLED=true`) to capture them.
|
||||
|
||||
Every trace captures rich metadata via standard span attributes.
|
||||
|
||||
<details open>
|
||||
|
||||
+7
-2
@@ -19,6 +19,7 @@ using the `/theme` command within Gemini CLI:
|
||||
- `Holiday`
|
||||
- `Shades Of Purple`
|
||||
- `Solarized Dark`
|
||||
- `Tokyo Night`
|
||||
- **Light themes:**
|
||||
- `ANSI Light`
|
||||
- `Ayu Light`
|
||||
@@ -116,8 +117,8 @@ least `background.primary`, `text.primary`, `text.secondary`, and the various
|
||||
accent colors via `text.link`, `text.accent`, and `status` to ensure a cohesive
|
||||
UI.
|
||||
|
||||
You can use either hex codes (e.g., `#FF0000`) **or** standard CSS color names
|
||||
(e.g., `coral`, `teal`, `blue`) for any color value. See
|
||||
You can use either hex codes (for example, `#FF0000`) **or** standard CSS color
|
||||
names (for example, `coral`, `teal`, `blue`) for any color value. See
|
||||
[CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#color_keywords)
|
||||
for a full list of supported names.
|
||||
|
||||
@@ -252,6 +253,10 @@ identify their source, for example: `shades-of-green (green-extension)`.
|
||||
|
||||
<img src="/docs/assets/theme-solarized-dark.png" alt="Solarized Dark theme" width="600">
|
||||
|
||||
### Tokyo Night
|
||||
|
||||
<img src="/docs/assets/theme-tokyonight-dark.png" alt="Tokyo Night theme" width="600">
|
||||
|
||||
## Light themes
|
||||
|
||||
### ANSI Light
|
||||
|
||||
+42
-14
@@ -1,7 +1,7 @@
|
||||
# Trusted Folders
|
||||
|
||||
The Trusted Folders feature is a security setting that gives you control over
|
||||
which projects can use the full capabilities of the Gemini CLI. It prevents
|
||||
which projects can use the full capabilities of Gemini CLI. It prevents
|
||||
potentially malicious code from running by asking you to approve a folder before
|
||||
the CLI loads any project-specific configurations from it.
|
||||
|
||||
@@ -24,12 +24,12 @@ Add the following to your user `settings.json` file:
|
||||
|
||||
## How it works: The trust dialog
|
||||
|
||||
Once the feature is enabled, the first time you run the Gemini CLI from a
|
||||
folder, a dialog will automatically appear, prompting you to make a choice:
|
||||
Once the feature is enabled, the first time you run Gemini CLI from a folder, a
|
||||
dialog will automatically appear, prompting you to make a choice:
|
||||
|
||||
- **Trust folder**: Grants full trust to the current folder (e.g.,
|
||||
- **Trust folder**: Grants full trust to the current folder (for example,
|
||||
`my-project`).
|
||||
- **Trust parent folder**: Grants trust to the parent directory (e.g.,
|
||||
- **Trust parent folder**: Grants trust to the parent directory (for example,
|
||||
`safe-projects`), which automatically trusts all of its subdirectories as
|
||||
well. This is useful if you keep all your safe projects in one place.
|
||||
- **Don't trust**: Marks the folder as untrusted. The CLI will operate in a
|
||||
@@ -40,9 +40,9 @@ will only be asked once per folder.
|
||||
|
||||
## Understanding folder contents: The discovery phase
|
||||
|
||||
Before you make a choice, the Gemini CLI performs a **discovery phase** to scan
|
||||
the folder for potential configurations. This information is displayed in the
|
||||
trust dialog to help you make an informed decision.
|
||||
Before you make a choice, Gemini CLI performs a **discovery phase** to scan the
|
||||
folder for potential configurations. This information is displayed in the trust
|
||||
dialog to help you make an informed decision.
|
||||
|
||||
The discovery UI lists the following categories of items found in the project:
|
||||
|
||||
@@ -63,16 +63,16 @@ attention:
|
||||
settings, such as auto-approving certain tools or disabling the security
|
||||
sandbox.
|
||||
- **Discovery Errors**: If the CLI encounters issues while scanning the folder
|
||||
(e.g., a malformed `settings.json` file), these errors will be displayed
|
||||
prominently.
|
||||
(for example, a malformed `settings.json` file), these errors will be
|
||||
displayed prominently.
|
||||
|
||||
By reviewing these details, you can ensure that you only grant trust to projects
|
||||
that you know are safe.
|
||||
|
||||
## Why trust matters: The impact of an untrusted workspace
|
||||
|
||||
When a folder is **untrusted**, the Gemini CLI runs in a restricted "safe mode"
|
||||
to protect you. In this mode, the following features are disabled:
|
||||
When a folder is **untrusted**, Gemini CLI runs in a restricted "safe mode" to
|
||||
protect you. In this mode, the following features are disabled:
|
||||
|
||||
1. **Workspace settings are ignored**: The CLI will **not** load the
|
||||
`.gemini/settings.json` file from the project. This prevents the loading of
|
||||
@@ -97,8 +97,36 @@ to protect you. In this mode, the following features are disabled:
|
||||
commands from .toml files, including both project-specific and global user
|
||||
commands.
|
||||
|
||||
Granting trust to a folder unlocks the full functionality of the Gemini CLI for
|
||||
that workspace.
|
||||
Granting trust to a folder unlocks the full functionality of Gemini CLI for that
|
||||
workspace.
|
||||
|
||||
## Headless and automated environments
|
||||
|
||||
When running Gemini CLI in a headless environment (for example, a CI/CD
|
||||
pipeline) where interactive prompts are not possible, the trust dialog cannot be
|
||||
displayed. If the folder is untrusted and the Folder Trust feature is enabled,
|
||||
the CLI will throw a `FatalUntrustedWorkspaceError` and exit.
|
||||
|
||||
To proceed in these environments, you can bypass the trust check using one of
|
||||
the following methods:
|
||||
|
||||
- **Command-line flag:** Run the CLI with the `--skip-trust` flag.
|
||||
- **Environment variable:** Set the `GEMINI_CLI_TRUST_WORKSPACE=true`
|
||||
environment variable.
|
||||
|
||||
These methods will trust the current workspace for the duration of the session
|
||||
without prompting.
|
||||
|
||||
For detailed instructions on managing folder trust within CI/CD workflows,
|
||||
review the
|
||||
[Gemini CLI trust guidance for GitHub Actions](https://github.com/google-github-actions/run-gemini-cli/blob/main/docs/trust-guidance.md).
|
||||
|
||||
## Overriding the trust file location
|
||||
|
||||
By default, trust settings are saved to `~/.gemini/trustedFolders.json`. If you
|
||||
need to store this file in a different location, you can set the
|
||||
`GEMINI_CLI_TRUSTED_FOLDERS_PATH` environment variable to the desired absolute
|
||||
file path.
|
||||
|
||||
## Managing your trust settings
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ The agent will:
|
||||
## Troubleshooting
|
||||
|
||||
- **Server won't start?** Try running the docker command manually in your
|
||||
terminal to see if it prints an error (e.g., "image not found").
|
||||
terminal to see if it prints an error (for example, "image not found").
|
||||
- **Tools not found?** Run `/mcp reload` to force the CLI to re-query the server
|
||||
for its capabilities.
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ loaded into every conversation.
|
||||
|
||||
### Scenario: Using the hierarchy
|
||||
|
||||
Context is loaded hierarchically. This allows you to have general rules for
|
||||
Context is loaded hierarchically. This lets you have general rules for
|
||||
everything and specific rules for sub-projects.
|
||||
|
||||
1. **Global:** `~/.gemini/GEMINI.md` (Rules for _every_ project you work on).
|
||||
@@ -124,3 +124,5 @@ immediately. Force a reload with:
|
||||
- Explore the [Command reference](../../reference/commands.md) for more
|
||||
`/memory` options.
|
||||
- Read the technical spec for [Project context](../../cli/gemini-md.md).
|
||||
- Try the experimental [Auto Memory](../auto-memory.md) feature to extract
|
||||
memory updates and reusable skills from your past sessions automatically.
|
||||
|
||||
@@ -79,8 +79,8 @@ each step with higher confidence and fewer errors.
|
||||
- **Steer early:** Providing feedback during the research phase is more
|
||||
efficient than waiting for the final plan to be drafted.
|
||||
- **Use for context:** Steering is a great way to provide knowledge that might
|
||||
not be obvious from reading the code (e.g., "We are planning to deprecate this
|
||||
module next month").
|
||||
not be obvious from reading the code (for example, "We are planning to
|
||||
deprecate this module next month").
|
||||
|
||||
## Next steps
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ browser.
|
||||
|
||||
This opens a searchable list of all your past sessions. You'll see:
|
||||
|
||||
- A timestamp (e.g., "2 hours ago").
|
||||
- A timestamp (for example, "2 hours ago").
|
||||
- The first user message (helping you identify the topic).
|
||||
- The number of turns in the conversation.
|
||||
|
||||
@@ -61,6 +61,19 @@ gemini --list-sessions
|
||||
gemini --delete-session 1
|
||||
```
|
||||
|
||||
### Scenario: Delete session on exit
|
||||
|
||||
If you're doing a one-off task and don't want to leave any session history
|
||||
behind, use the `--delete` flag when exiting:
|
||||
|
||||
```
|
||||
/exit --delete
|
||||
```
|
||||
|
||||
This removes the current session's conversation history and tool output files
|
||||
before exiting. It's useful for privacy-sensitive tasks or quick one-off
|
||||
interactions.
|
||||
|
||||
## How to rewind time (Undo mistakes)
|
||||
|
||||
Gemini CLI's **Rewind** feature is like `Ctrl+Z` for your workflow.
|
||||
|
||||
@@ -58,7 +58,7 @@ watchers.
|
||||
|
||||
**Prompt:** `Start the React dev server in the background.`
|
||||
|
||||
Gemini will run the command (e.g., `npm run dev`) and detach it.
|
||||
Gemini will run the command (for example, `npm run dev`) and detach it.
|
||||
|
||||
### Scenario: Viewing active shells
|
||||
|
||||
|
||||
@@ -1,110 +1,158 @@
|
||||
# Get started with Agent Skills
|
||||
|
||||
Agent Skills extend Gemini CLI with specialized expertise. In this guide, you'll
|
||||
learn how to create your first skill, bundle custom scripts, and activate them
|
||||
during a session.
|
||||
Agent Skills extend Gemini CLI with specialized expertise. In this tutorial,
|
||||
you'll learn how to create your first skill, bundle custom logic, and activate
|
||||
it during a session.
|
||||
|
||||
## How to create a skill
|
||||
## Create your first skill
|
||||
|
||||
A skill is defined by a directory containing a `SKILL.md` file. Let's create an
|
||||
**API Auditor** skill that helps you verify if local or remote endpoints are
|
||||
responding correctly.
|
||||
A skill is defined by a directory containing a `SKILL.md` file and
|
||||
subdirectories containing reference materials or scripts used by the skill.
|
||||
Let's create an **API Auditor** skill that runs a script to help you verify if
|
||||
local or remote endpoints are responding correctly.
|
||||
|
||||
### Create the directory structure
|
||||
### 1. Create the directory structure
|
||||
|
||||
1. Run the following command to create the folders:
|
||||
The first step is to create the necessary folders for your skill and its
|
||||
scripts.
|
||||
|
||||
**macOS/Linux**
|
||||
**macOS/Linux**
|
||||
|
||||
```bash
|
||||
mkdir -p .gemini/skills/api-auditor/scripts
|
||||
```
|
||||
```bash
|
||||
mkdir -p .gemini/skills/api-auditor/scripts
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
**Windows (PowerShell)**
|
||||
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path ".gemini\skills\api-auditor\scripts"
|
||||
```
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path ".gemini\skills\api-auditor\scripts"
|
||||
```
|
||||
|
||||
### Create the definition
|
||||
### 2. Create the definition (`SKILL.md`)
|
||||
|
||||
1. Create a file at `.gemini/skills/api-auditor/SKILL.md`. This tells the agent
|
||||
_when_ to use the skill and _how_ to behave.
|
||||
The `SKILL.md` file defines the skill's purpose and instructions for the agent.
|
||||
Create a file at `.gemini/skills/api-auditor/SKILL.md`. This tells the agent
|
||||
_when_ to use the skill and _how_ to behave.
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: api-auditor
|
||||
description:
|
||||
Expertise in auditing and testing API endpoints. Use when the user asks to
|
||||
"check", "test", or "audit" a URL or API.
|
||||
---
|
||||
```markdown
|
||||
---
|
||||
name: api-auditor
|
||||
description:
|
||||
Expertise in auditing and testing API endpoints. Use when the user asks to
|
||||
"check", "test", or "audit" a URL or API.
|
||||
---
|
||||
|
||||
# API Auditor Instructions
|
||||
# API Auditor Instructions
|
||||
|
||||
You act as a QA engineer specialized in API reliability. When this skill is
|
||||
active, you MUST:
|
||||
You act as a QA engineer specialized in API reliability. When this skill is
|
||||
active, you MUST:
|
||||
|
||||
1. **Audit**: Use the bundled `scripts/audit.js` utility to check the
|
||||
status of the provided URL.
|
||||
2. **Report**: Analyze the output (status codes, latency) and explain any
|
||||
failures in plain English.
|
||||
3. **Secure**: Remind the user if they are testing a sensitive endpoint
|
||||
without an `https://` protocol.
|
||||
```
|
||||
1. **Audit**: Use the bundled `scripts/audit.js` utility to check the status of
|
||||
the provided URL.
|
||||
2. **Report**: Analyze the output (status codes, latency) and explain any
|
||||
failures in plain English.
|
||||
3. **Secure**: Remind the user if they are testing a sensitive endpoint without
|
||||
an `https://` protocol.
|
||||
```
|
||||
|
||||
### Add the tool logic
|
||||
### 3. Add the tool logic
|
||||
|
||||
Skills can bundle resources like scripts.
|
||||
Skills can bundle resources like scripts to perform deterministic tasks. Create
|
||||
a file at `.gemini/skills/api-auditor/scripts/audit.js`. This is the code the
|
||||
agent will run.
|
||||
|
||||
1. Create a file at `.gemini/skills/api-auditor/scripts/audit.js`. This is the
|
||||
code the agent will run.
|
||||
```javascript
|
||||
// .gemini/skills/api-auditor/scripts/audit.js
|
||||
const url = process.argv[2];
|
||||
|
||||
```javascript
|
||||
// .gemini/skills/api-auditor/scripts/audit.js
|
||||
const url = process.argv[2];
|
||||
if (!url) {
|
||||
console.error('Usage: node audit.js <url>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
console.error('Usage: node audit.js <url>');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`Auditing ${url}...`);
|
||||
fetch(url, { method: 'HEAD' })
|
||||
.then((r) => console.log(`Result: Success (Status ${r.status})`))
|
||||
.catch((e) => console.error(`Result: Failed (${e.message})`));
|
||||
```
|
||||
|
||||
console.log(`Auditing ${url}...`);
|
||||
fetch(url, { method: 'HEAD' })
|
||||
.then((r) => console.log(`Result: Success (Status ${r.status})`))
|
||||
.catch((e) => console.error(`Result: Failed (${e.message})`));
|
||||
```
|
||||
## Verify discovery
|
||||
|
||||
## How to verify discovery
|
||||
Gemini CLI automatically discovers skills in the `.gemini/skills` directory (as
|
||||
well as the `.agents/skills` alias).
|
||||
|
||||
Gemini CLI automatically discovers skills in the `.gemini/skills` directory. You
|
||||
can also use `.agents/skills` as a more generic alternative. Check that it found
|
||||
your new skill.
|
||||
To check if Gemini CLI found your new skill, use the `/skills list` command
|
||||
within an interactive session:
|
||||
|
||||
**Command:** `/skills list`
|
||||
```bash
|
||||
/skills list
|
||||
```
|
||||
|
||||
You should see `api-auditor` in the list of available skills.
|
||||
You should see `api-auditor` in the list of available skills. If you just added
|
||||
the files, you can run `/skills reload` to refresh the list without restarting
|
||||
the session.
|
||||
|
||||
### If your skill doesn't appear
|
||||
|
||||
If `/skills list` doesn't show your skill, check the following:
|
||||
|
||||
1. **The folder must be trusted (workspace skills only).** Skills under
|
||||
`<workspace>/.gemini/skills/` are only loaded when the workspace folder is
|
||||
marked as trusted. Run `/trust` and restart the session if needed. Skills
|
||||
under `~/.gemini/skills/` (user scope) are not affected by trust.
|
||||
2. **Check the path layout.** `SKILL.md` is discovered either at the root of
|
||||
the skills directory (`.gemini/skills/SKILL.md`) or one directory deep
|
||||
(`.gemini/skills/<skill-name>/SKILL.md`). The recommended layout uses a
|
||||
subdirectory per skill so you can bundle scripts and other resources
|
||||
alongside it. Files nested more than one directory deep are not discovered.
|
||||
3. **The filename must be exactly `SKILL.md`.** Capitalization matters on
|
||||
case-sensitive filesystems (Linux, and macOS when configured as such):
|
||||
`skill.md` or `Skill.md` will be ignored.
|
||||
4. **Frontmatter must include both `name:` and `description:`, and must be the
|
||||
first thing in the file.** A `SKILL.md` is silently skipped if either field
|
||||
is missing, if the delimiters (`---` on their own lines) are absent, or if
|
||||
any text (an H1 title, a comment, even a blank line) appears before the
|
||||
opening `---`.
|
||||
5. **The skill name comes from the `name:` field, not the directory name.** If
|
||||
your frontmatter says `name: foo`, the skill appears as `foo` in
|
||||
`/skills list` regardless of what its parent directory is called. The
|
||||
characters `: \ / < > * ? " |` in the name are replaced with `-`.
|
||||
|
||||
## How to use the skill
|
||||
|
||||
Now, try it out. Start a new session and ask a question that triggers the
|
||||
skill's description.
|
||||
Now that the skill is discovered, you can trigger its activation by asking a
|
||||
relevant question.
|
||||
|
||||
**User:** "Can you audit http://geminicli.com"
|
||||
1. **Trigger**: Start a new session and ask: "Can you audit https://google.com"
|
||||
2. **Activation**: Gemini identifies that the request matches the `api-auditor`
|
||||
description and calls the `activate_skill` tool.
|
||||
3. **Consent**: You will see a confirmation prompt. Type **y** to approve.
|
||||
4. **Execution**: Once activated, Gemini uses the `run_shell_command` tool to
|
||||
execute your bundled script:
|
||||
`node .gemini/skills/api-auditor/scripts/audit.js https://google.com`
|
||||
|
||||
Gemini recognizes the request matches the `api-auditor` description and asks for
|
||||
permission to activate it.
|
||||
## Pro tip: Use the skill-creator
|
||||
|
||||
**Model:** (After calling `activate_skill`) "I've activated the **api-auditor**
|
||||
skill. I'll run the audit script now..."
|
||||
If you don't want to create the files manually, you can use the built-in
|
||||
`skill-creator` skill. Simply ask Gemini:
|
||||
|
||||
Gemini then uses the `run_shell_command` tool to execute your bundled Node
|
||||
script:
|
||||
> "Create a new skill called 'api-auditor' that tests if URLs are responding."
|
||||
|
||||
`node .gemini/skills/api-auditor/scripts/audit.js http://geminili.com`
|
||||
The `skill-creator` will handle the directory structure and boilerplate for you.
|
||||
|
||||
## Manage skills
|
||||
|
||||
You can also manage skills using the `gemini skills` command from your terminal:
|
||||
|
||||
- **Install**: `gemini skills install <url-or-path>`
|
||||
- **Link**: `gemini skills link <path>` (useful for local development)
|
||||
- **Uninstall**: `gemini skills uninstall <name>`
|
||||
|
||||
## Next steps
|
||||
|
||||
- Explore the
|
||||
[Agent Skills Authoring Guide](../../cli/skills.md#creating-a-skill) to learn
|
||||
about more advanced features.
|
||||
- Learn how to share skills via [Extensions](../../extensions/index.md).
|
||||
- [Creating Agent Skills](../creating-skills.md): Detailed guide on advanced
|
||||
skill features and metadata.
|
||||
- [Using Agent Skills](../using-agent-skills.md): More ways to discover and
|
||||
manage your skill library.
|
||||
- [Skill best practices](../skills-best-practices.md): Learn how to design
|
||||
reliable and effective expertise.
|
||||
|
||||
@@ -7,7 +7,7 @@ progress with the todo list.
|
||||
## Prerequisites
|
||||
|
||||
- Gemini CLI installed and authenticated.
|
||||
- A complex task in mind (e.g., a multi-file refactor or new feature).
|
||||
- A complex task in mind (for example, a multi-file refactor or new feature).
|
||||
|
||||
## Why use task planning?
|
||||
|
||||
@@ -58,7 +58,7 @@ Tell the agent to proceed.
|
||||
As the agent works, you'll see the todo list update in real-time above the input
|
||||
box.
|
||||
|
||||
- **Current focus:** The active task is highlighted (e.g.,
|
||||
- **Current focus:** The active task is highlighted (for example,
|
||||
`[IN_PROGRESS] Create tsconfig.json`).
|
||||
- **Progress:** Completed tasks are marked as done.
|
||||
|
||||
@@ -90,4 +90,4 @@ living document, not a static text block.
|
||||
- See the [Todo tool reference](../../tools/todos.md) for technical schema
|
||||
details.
|
||||
- Learn about [Memory management](memory-management.md) to persist planning
|
||||
preferences (e.g., "Always create a test plan first").
|
||||
preferences (for example, "Always create a test plan first").
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
# Managing Agent Skills
|
||||
|
||||
Agent Skills provide Gemini CLI with specialized expertise on demand. This guide
|
||||
covers advanced management techniques, including using slash commands, terminal
|
||||
utilities, and understanding discovery tiers.
|
||||
|
||||
## Discovery tiers
|
||||
|
||||
Gemini CLI discovers skills from several locations, following a specific order
|
||||
of precedence (lowest to highest):
|
||||
|
||||
1. **Built-in Skills**: Included with Gemini CLI and always available.
|
||||
2. **Extension Skills**: Bundled within [extensions](../extensions/index.md).
|
||||
3. **User Skills**: Located in `~/.gemini/skills/` or the `~/.agents/skills/`
|
||||
alias. These are available across all your projects.
|
||||
4. **Workspace Skills**: Located in `.gemini/skills/` or the `.agents/skills/`
|
||||
alias within your current directory. These are project-specific.
|
||||
|
||||
> **Tip:** If multiple skills share the same name, the version from the
|
||||
> higher-precedence location is used.
|
||||
|
||||
## In-session management
|
||||
|
||||
Use the `/skills` slash command during an interactive session to manage your
|
||||
available expertise.
|
||||
|
||||
- **List skills**: `/skills list` (shows discovered skills).
|
||||
- Use `/skills list all` to include internal built-in skills.
|
||||
- Use `/skills list nodesc` to hide descriptions.
|
||||
- **Reload skills**: `/skills reload` (or `/skills refresh`) to scan for new or
|
||||
modified skills without restarting the CLI.
|
||||
- **Toggle status**:
|
||||
- `/skills disable <name>`: Prevents a skill from being triggered.
|
||||
- `/skills enable <name>`: Re-enables a disabled skill.
|
||||
- **Link local skills**: `/skills link <path> [--scope user|workspace]` to
|
||||
immediately use a skill you are developing.
|
||||
|
||||
## Terminal utilities
|
||||
|
||||
The `gemini skills` command provides management utilities directly from your
|
||||
system shell.
|
||||
|
||||
### Install a skill
|
||||
|
||||
To install a skill from a remote repository or a local `.skill` package:
|
||||
|
||||
```bash
|
||||
gemini skills install https://github.com/user/my-awesome-skill
|
||||
```
|
||||
|
||||
By default, this installs to your **user profile**. Use `--scope workspace` to
|
||||
install it only for the current project.
|
||||
|
||||
### Link for development
|
||||
|
||||
If you are developing a skill, use the `link` command to create a reference to
|
||||
your local directory:
|
||||
|
||||
```bash
|
||||
gemini skills link ./path/to/my-skill
|
||||
```
|
||||
|
||||
### Uninstall a skill
|
||||
|
||||
To completely remove an installed or linked skill:
|
||||
|
||||
```bash
|
||||
gemini skills uninstall <name>
|
||||
```
|
||||
|
||||
## Security and consent
|
||||
|
||||
Agent Skills can execute scripts and access your files. To protect your
|
||||
environment:
|
||||
|
||||
1. **Installation consent**: When installing from a remote URL, you will be
|
||||
asked to confirm the source.
|
||||
2. **Activation consent**: Every time a skill is triggered during a session,
|
||||
the agent must ask for permission to activate it and gain access to its
|
||||
resources.
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Get started with Agent Skills](./tutorials/skills-getting-started.md): A
|
||||
walkthrough for creating your first skill.
|
||||
- [Creating Agent Skills](./creating-skills.md): Detailed guide on bundling
|
||||
scripts and assets.
|
||||
- [Skill best practices](./skills-best-practices.md): Strategies for building
|
||||
reliable expertise.
|
||||
@@ -0,0 +1,83 @@
|
||||
# `gemini gemma` — Automated Local Model Routing Setup
|
||||
|
||||
Local model routing uses a local Gemma 3 1B model running on your machine to
|
||||
classify and route user requests. It routes simple requests (like file reads) to
|
||||
Gemini Flash and complex requests (like architecture discussions) to Gemini Pro.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> This is an experimental feature currently under active development.
|
||||
|
||||
## What is this?
|
||||
|
||||
This feature saves cloud API costs by using local inference for task
|
||||
classification instead of a cloud-based classifier. It adds a few milliseconds
|
||||
of local latency but can significantly reduce the overall token usage for hosted
|
||||
models.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
# One command does everything: downloads runtime, pulls model, configures settings, starts server
|
||||
gemini gemma setup
|
||||
```
|
||||
|
||||
You'll be prompted to accept the Gemma Terms of Use. The model is ~1 GB.
|
||||
|
||||
After setup, **just use the CLI normally** — routing happens automatically on
|
||||
every request.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | What it does |
|
||||
| --------------------- | -------------------------------------------------------------- |
|
||||
| `gemini gemma setup` | Full install (binary + model + settings + server start) |
|
||||
| `gemini gemma status` | Health check — shows what's installed and running |
|
||||
| `gemini gemma start` | Start the LiteRT server (auto-starts on CLI launch by default) |
|
||||
| `gemini gemma stop` | Stop the LiteRT server |
|
||||
| `gemini gemma logs` | Tail the server logs to see routing requests live |
|
||||
| `/gemma` | In-session status check (type it inside the CLI) |
|
||||
|
||||
## Verifying it works
|
||||
|
||||
1. Run `gemini gemma status` — all checks should show green
|
||||
2. Open two terminals:
|
||||
- Terminal 1: `gemini gemma logs` (watch for incoming requests)
|
||||
- Terminal 2: use the CLI normally
|
||||
3. You should see classification requests appear in the logs as you interact
|
||||
with the CLI
|
||||
4. The `/gemma` slash command inside a session shows a quick status panel
|
||||
|
||||
## Setup flags
|
||||
|
||||
```bash
|
||||
gemini gemma setup --port 8080 # custom port
|
||||
gemini gemma setup --no-start # don't start server after install
|
||||
gemini gemma setup --force # re-download everything
|
||||
gemini gemma setup --skip-model # binary only, skip the 1GB model download
|
||||
```
|
||||
|
||||
## How it works under the hood
|
||||
|
||||
- Local Gemma classifies each request as "simple" or "complex" (~100ms)
|
||||
- Simple → Flash, Complex → Pro
|
||||
- If the local server is down, the CLI silently falls back to the cloud
|
||||
classifier — no errors, no disruption
|
||||
|
||||
## Disabling
|
||||
|
||||
Set `enabled: false` in settings or just run `gemini gemma stop` to turn off the
|
||||
server:
|
||||
|
||||
```json
|
||||
{ "experimental": { "gemmaModelRouter": { "enabled": false } } }
|
||||
```
|
||||
|
||||
## Advanced setup
|
||||
|
||||
If you are in an environment where the `gemini gemma setup` command cannot
|
||||
automatically download binaries (for example, behind a strict corporate
|
||||
firewall), you can perform the setup manually.
|
||||
|
||||
For more information, see the
|
||||
[Manual Local Model Routing Setup guide](./local-model-routing.md).
|
||||
+10
-10
@@ -7,16 +7,17 @@ requests sent from `packages/cli`. For a general overview of Gemini CLI, see the
|
||||
|
||||
## Navigating this section
|
||||
|
||||
- **[Sub-agents (experimental)](./subagents.md):** Learn how to create and use
|
||||
specialized sub-agents for complex tasks.
|
||||
- **[Sub-agents](./subagents.md):** Learn how to create and use specialized
|
||||
sub-agents for complex tasks.
|
||||
- **[Core tools reference](../reference/tools.md):** Information on how tools
|
||||
are defined, registered, and used by the core.
|
||||
- **[Memory Import Processor](../reference/memport.md):** Documentation for the
|
||||
modular GEMINI.md import feature using @file.md syntax.
|
||||
- **[Policy Engine](../reference/policy-engine.md):** Use the Policy Engine for
|
||||
fine-grained control over tool execution.
|
||||
- **[Local Model Routing (experimental)](./local-model-routing.md):** Learn how
|
||||
to enable use of a local Gemma model for model routing decisions.
|
||||
- **[Local Model Routing (experimental)](./gemma-setup.md):** Learn how to
|
||||
enable use of a local Gemma model for model routing decisions using the
|
||||
automated setup command.
|
||||
|
||||
## Role of the core
|
||||
|
||||
@@ -29,7 +30,7 @@ While the `packages/cli` portion of Gemini CLI provides the user interface,
|
||||
potentially incorporating conversation history, tool definitions, and
|
||||
instructional context from `GEMINI.md` files.
|
||||
- **Tool management & orchestration:**
|
||||
- Registering available tools (e.g., file system tools, shell command
|
||||
- Registering available tools (for example, file system tools, shell command
|
||||
execution).
|
||||
- Interpreting tool use requests from the Gemini model.
|
||||
- Executing the requested tools with the provided arguments.
|
||||
@@ -45,7 +46,7 @@ The core plays a vital role in security:
|
||||
|
||||
- **API key management:** It handles the `GEMINI_API_KEY` and ensures it's used
|
||||
securely when communicating with the Gemini API.
|
||||
- **Tool execution:** When tools interact with the local system (e.g.,
|
||||
- **Tool execution:** When tools interact with the local system (for example,
|
||||
`run_shell_command`), the core (and its underlying tool implementations) must
|
||||
do so with appropriate caution, often involving sandboxing mechanisms to
|
||||
prevent unintended modifications.
|
||||
@@ -70,7 +71,7 @@ to use the CLI even if the default "pro" model is rate-limited.
|
||||
|
||||
If you are using the default "pro" model and the CLI detects that you are being
|
||||
rate-limited, it automatically switches to the "flash" model for the current
|
||||
session. This allows you to continue working without interruption.
|
||||
session. This lets you continue working without interruption.
|
||||
|
||||
Internal utility calls that use `gemini-2.5-flash-lite` (for example, prompt
|
||||
completion and classification) silently fall back to `gemini-2.5-flash` and
|
||||
@@ -90,9 +91,8 @@ in a hierarchical manner, starting from the current working directory and moving
|
||||
up to the project root and the user's home directory. It also searches in
|
||||
subdirectories.
|
||||
|
||||
This allows you to have global, project-level, and component-level context
|
||||
files, which are all combined to provide the model with the most relevant
|
||||
information.
|
||||
This lets you have global, project-level, and component-level context files,
|
||||
which are all combined to provide the model with the most relevant information.
|
||||
|
||||
You can use the [`/memory` command](../reference/commands.md) to `show`, `add`,
|
||||
and `refresh` the content of loaded `GEMINI.md` files.
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
# Local Model Routing (experimental)
|
||||
# Manual Local Model Routing Setup (experimental)
|
||||
|
||||
Gemini CLI supports using a local model for
|
||||
[routing decisions](../cli/model-routing.md). When configured, Gemini CLI will
|
||||
use a locally-running **Gemma** model to make routing decisions (instead of
|
||||
sending routing decisions to a hosted model).
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> This is an experimental feature currently under active development.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!IMPORTANT]
|
||||
> **Recommended:** We now provide a fully automated setup command. We recommend
|
||||
> using the [`gemini gemma` Setup Guide](./gemma-setup.md) instead of following
|
||||
> these manual steps.
|
||||
|
||||
This feature can help reduce costs associated with hosted model usage while
|
||||
offering similar routing decision latency and quality.
|
||||
|
||||
> **Note: Local model routing is currently an experimental feature.**
|
||||
|
||||
## Setup
|
||||
## Manual Setup
|
||||
|
||||
Using a Gemma model for routing decisions requires that an implementation of a
|
||||
Gemma model be running locally on your machine, served behind an HTTP endpoint
|
||||
and accessed via the Gemini API.
|
||||
|
||||
To serve the Gemma model, follow these steps:
|
||||
and accessed via the Gemini API. If you cannot use the `gemini gemma setup`
|
||||
command, follow these manual steps:
|
||||
|
||||
### Download the LiteRT-LM runtime
|
||||
|
||||
@@ -108,7 +115,7 @@ Download complete.
|
||||
$ ./lit.lit.macos_arm64 pull gemma3-1b-gpu-custom
|
||||
|
||||
[Legal] The model you are about to download is governed by
|
||||
the Gemma Terms of Use and Prohibited Use Policy. Please review these terms and ensure you agree before continuing.
|
||||
the Gemma Terms of Use and Prohibited Use Policy. Review these terms and ensure you agree before continuing.
|
||||
|
||||
Full Terms: https://ai.google.dev/gemma/terms
|
||||
Prohibited Use Policy: https://ai.google.dev/gemma/prohibited_use_policy
|
||||
|
||||
+15
-19
@@ -1,4 +1,4 @@
|
||||
# Remote Subagents (experimental)
|
||||
# Remote Subagents
|
||||
|
||||
Gemini CLI supports connecting to remote subagents using the Agent-to-Agent
|
||||
(A2A) protocol. This allows Gemini CLI to interact with other agents, expanding
|
||||
@@ -10,23 +10,6 @@ agents in the following repositories:
|
||||
- [ADK Samples (Python)](https://github.com/google/adk-samples/tree/main/python)
|
||||
- [ADK Python Contributing Samples](https://github.com/google/adk-python/tree/main/contributing/samples)
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> Remote subagents are currently an experimental feature.
|
||||
|
||||
## Configuration
|
||||
|
||||
To use remote subagents, you must explicitly enable them in your
|
||||
`settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"enableAgents": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Proxy support
|
||||
|
||||
Gemini CLI routes traffic to remote agents through an HTTP/HTTPS proxy if one is
|
||||
@@ -447,7 +430,7 @@ both behind auth.
|
||||
|
||||
## Managing Subagents
|
||||
|
||||
Users can manage subagents using the following commands within the Gemini CLI:
|
||||
Users can manage subagents using the following commands within Gemini CLI:
|
||||
|
||||
- `/agents list`: Displays all available local and remote subagents.
|
||||
- `/agents reload`: Reloads the agent registry. Use this after adding or
|
||||
@@ -459,3 +442,16 @@ Users can manage subagents using the following commands within the Gemini CLI:
|
||||
> [!TIP]
|
||||
> You can use the `@cli_help` agent within Gemini CLI for assistance
|
||||
> with configuring subagents.
|
||||
|
||||
## Disabling remote agents
|
||||
|
||||
Remote subagents are enabled by default. To disable them, set `enableAgents` to
|
||||
`false` in your `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"enableAgents": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
+228
-51
@@ -1,23 +1,10 @@
|
||||
# Subagents (experimental)
|
||||
# Subagents
|
||||
|
||||
Subagents are specialized agents that operate within your main Gemini CLI
|
||||
session. They are designed to handle specific, complex tasks—like deep codebase
|
||||
analysis, documentation lookup, or domain-specific reasoning—without cluttering
|
||||
the main agent's context or toolset.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> Subagents are currently an experimental feature.
|
||||
>
|
||||
To use custom subagents, you must ensure they are enabled in your
|
||||
`settings.json` (enabled by default):
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": { "enableAgents": true }
|
||||
}
|
||||
```
|
||||
|
||||
## What are subagents?
|
||||
|
||||
Subagents are "specialists" that the main Gemini agent can hire for a specific
|
||||
@@ -100,11 +87,23 @@ Gemini CLI comes with the following built-in subagents:
|
||||
|
||||
### Generalist Agent
|
||||
|
||||
- **Name:** `generalist_agent`
|
||||
- **Purpose:** Route tasks to the appropriate specialized subagent.
|
||||
- **When to use:** Implicitly used by the main agent for routing. Not directly
|
||||
invoked by the user.
|
||||
- **Configuration:** Enabled by default. No specific configuration options.
|
||||
- **Name:** `generalist`
|
||||
- **Purpose:** A general, all-purpose subagent that uses the inherited tool
|
||||
access and configurations from the main agent. Useful for executing broad,
|
||||
resource-heavy subtasks in an isolated conversation, optimizing your main
|
||||
agent's context by returning only the final result of that given task.
|
||||
- **When to use:** Use this agent when a task requires many steps, handles large
|
||||
volumes of information, or requires the same full capabilities as the main
|
||||
agent. It is ideal for:
|
||||
- **Multi-file modifications:** Applying refactors or fixing errors across
|
||||
several files at once.
|
||||
- **High-volume execution:** Running commands or tests that produce extensive
|
||||
terminal output.
|
||||
- **Action-oriented research:** Investigations where the agent needs to both
|
||||
search code and run commands or make edits to find a solution. By delegating
|
||||
these tasks, you prevent your main conversation from becoming cluttered or
|
||||
slow. You can invoke it explicitly using `@generalist`.
|
||||
- **Configuration:** Enabled by default.
|
||||
|
||||
### Browser Agent (experimental)
|
||||
|
||||
@@ -124,10 +123,12 @@ Gemini CLI comes with the following built-in subagents:
|
||||
|
||||
The browser agent requires:
|
||||
|
||||
- **Chrome** version 144 or later (any recent stable release will work).
|
||||
- **Node.js** with `npx` available (used to launch the
|
||||
[`chrome-devtools-mcp`](https://www.npmjs.com/package/chrome-devtools-mcp)
|
||||
server).
|
||||
- **Chrome** version 144 or later (any recent stable release works).
|
||||
|
||||
The underlying
|
||||
[`chrome-devtools-mcp`](https://www.npmjs.com/package/chrome-devtools-mcp)
|
||||
server is bundled with Gemini CLI and launched automatically — no separate
|
||||
installation is needed.
|
||||
|
||||
#### Enabling the browser agent
|
||||
|
||||
@@ -173,26 +174,58 @@ The available modes are:
|
||||
| `isolated` | Launches Chrome with a temporary profile that is deleted after each session. Use this for clean-state automation. |
|
||||
| `existing` | Attaches to an already-running Chrome instance. You must enable remote debugging first by navigating to `chrome://inspect/#remote-debugging` in Chrome. No new browser process is launched. |
|
||||
|
||||
#### First-run consent
|
||||
|
||||
The first time the browser agent is invoked, Gemini CLI displays a consent
|
||||
dialog. You must accept before the browser session starts. This dialog only
|
||||
appears once.
|
||||
|
||||
#### Configuration reference
|
||||
|
||||
All browser-specific settings go under `agents.browser` in your `settings.json`.
|
||||
For full details, see the
|
||||
[`agents.browser` configuration reference](../reference/configuration.md#agents).
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| :------------ | :-------- | :------------- | :---------------------------------------------------------------------------------------------- |
|
||||
| `sessionMode` | `string` | `"persistent"` | How Chrome is managed: `"persistent"`, `"isolated"`, or `"existing"`. |
|
||||
| `headless` | `boolean` | `false` | Run Chrome in headless mode (no visible window). |
|
||||
| `profilePath` | `string` | — | Custom path to a browser profile directory. |
|
||||
| `visualModel` | `string` | — | Model override for the visual agent (for example, `"gemini-2.5-computer-use-preview-10-2025"`). |
|
||||
| Setting | Type | Default | Description |
|
||||
| :------------------------ | :--------- | :------------- | :------------------------------------------------------------------------------ |
|
||||
| `sessionMode` | `string` | `"persistent"` | How Chrome is managed: `"persistent"`, `"isolated"`, or `"existing"`. |
|
||||
| `headless` | `boolean` | `false` | Run Chrome in headless mode (no visible window). |
|
||||
| `profilePath` | `string` | — | Custom path to a browser profile directory. |
|
||||
| `visualModel` | `string` | — | Model override for the visual agent. |
|
||||
| `allowedDomains` | `string[]` | — | Restrict navigation to specific domains (for example, `["github.com"]`). |
|
||||
| `disableUserInput` | `boolean` | `true` | Disable user input on the browser window during automation (non-headless only). |
|
||||
| `maxActionsPerTask` | `number` | `100` | Maximum tool calls per task. The agent is terminated when the limit is reached. |
|
||||
| `confirmSensitiveActions` | `boolean` | `false` | Require manual confirmation for `upload_file` and `evaluate_script`. |
|
||||
| `blockFileUploads` | `boolean` | `false` | Hard-block all file upload requests from the agent. |
|
||||
|
||||
#### Automation overlay and input blocking
|
||||
|
||||
In non-headless mode, the browser agent injects a visual overlay into the
|
||||
browser window to indicate that automation is in progress. By default, user
|
||||
input (keyboard and mouse) is also blocked to prevent accidental interference.
|
||||
You can disable this by setting `disableUserInput` to `false`.
|
||||
|
||||
#### Security
|
||||
|
||||
The browser agent enforces the following security restrictions:
|
||||
The browser agent enforces several layers of security:
|
||||
|
||||
- **Blocked URL patterns:** `file://`, `javascript:`, `data:text/html`,
|
||||
`chrome://extensions`, and `chrome://settings/passwords` are always blocked.
|
||||
- **Sensitive action confirmation:** Actions like form filling, file uploads,
|
||||
and form submissions require user confirmation through the standard policy
|
||||
engine.
|
||||
- **Domain restrictions:** When `allowedDomains` is set, the agent can only
|
||||
navigate to the listed domains (and their subdomains when using `*.` prefix).
|
||||
Attempting to visit a disallowed domain throws a fatal error that immediately
|
||||
terminates the agent. The agent also attempts to detect and block the use of
|
||||
allowed domains as proxies (e.g., via query parameters or fragments) to access
|
||||
restricted content.
|
||||
- **Blocked URL patterns:** The underlying MCP server blocks dangerous URL
|
||||
schemes including `file://`, `javascript:`, `data:text/html`,
|
||||
`chrome://extensions`, and `chrome://settings/passwords`.
|
||||
- **Sensitive action confirmation:** Form filling (`fill`, `fill_form`) always
|
||||
requires user confirmation through the policy engine, regardless of approval
|
||||
mode. When `confirmSensitiveActions` is `true`, `upload_file` and
|
||||
`evaluate_script` also require confirmation.
|
||||
- **File upload blocking:** Set `blockFileUploads` to `true` to hard-block all
|
||||
file upload requests, preventing the agent from uploading any files.
|
||||
- **Action rate limiting:** The `maxActionsPerTask` setting (default: 100)
|
||||
limits the total number of tool calls per task to prevent runaway execution.
|
||||
|
||||
#### Visual agent
|
||||
|
||||
@@ -226,19 +259,65 @@ the `click_at` tool for precise, coordinate-based interactions.
|
||||
> The visual agent requires API key or Vertex AI authentication. It is
|
||||
> not available when using "Sign in with Google".
|
||||
|
||||
#### Sandbox support
|
||||
|
||||
The browser agent adjusts its behavior automatically when running inside a
|
||||
sandbox.
|
||||
|
||||
##### macOS seatbelt (`sandbox-exec`)
|
||||
|
||||
When the CLI runs under the macOS seatbelt sandbox, `persistent` and `isolated`
|
||||
session modes are forced to `isolated` with `headless` enabled. This avoids
|
||||
permission errors caused by seatbelt file-system restrictions on persistent
|
||||
browser profiles. If `sessionMode` is set to `existing`, no override is applied.
|
||||
|
||||
##### Container sandboxes (Docker / Podman)
|
||||
|
||||
Chrome is not available inside the container, so the browser agent is
|
||||
**disabled** unless `sessionMode` is set to `"existing"`. When enabled with
|
||||
`existing` mode, the agent automatically connects to Chrome on the host via the
|
||||
resolved IP of `host.docker.internal:9222` instead of using local pipe
|
||||
discovery. Port `9222` is currently hardcoded and cannot be customized.
|
||||
|
||||
To use the browser agent in a Docker sandbox:
|
||||
|
||||
1. Start Chrome on the host with remote debugging enabled:
|
||||
|
||||
```bash
|
||||
# Option A: Launch Chrome from the command line
|
||||
google-chrome --remote-debugging-port=9222
|
||||
|
||||
# Option B: Enable in Chrome settings
|
||||
# Navigate to chrome://inspect/#remote-debugging and enable
|
||||
```
|
||||
|
||||
2. Configure `sessionMode` and allowed domains in your project's
|
||||
`.gemini/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"overrides": {
|
||||
"browser_agent": { "enabled": true }
|
||||
},
|
||||
"browser": {
|
||||
"sessionMode": "existing",
|
||||
"allowedDomains": ["example.com"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Launch the CLI with port forwarding:
|
||||
|
||||
```bash
|
||||
GEMINI_SANDBOX=docker SANDBOX_PORTS=9222 gemini
|
||||
```
|
||||
|
||||
## Creating custom subagents
|
||||
|
||||
You can create your own subagents to automate specific workflows or enforce
|
||||
specific personas. To use custom subagents, you must enable them in your
|
||||
`settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": {
|
||||
"enableAgents": true
|
||||
}
|
||||
}
|
||||
```
|
||||
specific personas.
|
||||
|
||||
### Agent definition files
|
||||
|
||||
@@ -290,7 +369,8 @@ it yourself; just report it.
|
||||
| `description` | string | Yes | Short description of what the agent does. This is visible to the main agent to help it decide when to call this subagent. |
|
||||
| `kind` | string | No | `local` (default) or `remote`. |
|
||||
| `tools` | array | No | List of tool names this agent can use. Supports wildcards: `*` (all tools), `mcp_*` (all MCP tools), `mcp_server_*` (all tools from a server). **If omitted, it inherits all tools from the parent session.** |
|
||||
| `model` | string | No | Specific model to use (e.g., `gemini-3-preview`). Defaults to `inherit` (uses the main session model). |
|
||||
| `mcpServers` | object | No | Configuration for inline Model Context Protocol (MCP) servers isolated to this specific agent. |
|
||||
| `model` | string | No | Specific model to use (for example, `gemini-3-preview`). Defaults to `inherit` (uses the main session model). |
|
||||
| `temperature` | number | No | Model temperature (0.0 - 2.0). Defaults to `1`. |
|
||||
| `max_turns` | number | No | Maximum number of conversation turns allowed for this agent before it must return. Defaults to `30`. |
|
||||
| `timeout_mins` | number | No | Maximum execution time in minutes. Defaults to `10`. |
|
||||
@@ -317,6 +397,78 @@ Each subagent runs in its own isolated context loop. This means:
|
||||
subagents **cannot** call other subagents. If a subagent is granted the `*`
|
||||
tool wildcard, it will still be unable to see or invoke other agents.
|
||||
|
||||
## Subagent tool isolation
|
||||
|
||||
Subagent tool isolation moves Gemini CLI away from a single global tool
|
||||
registry. By providing isolated execution environments, you can ensure that
|
||||
subagents only interact with the parts of the system they are designed for. This
|
||||
prevents unintended side effects, improves reliability by avoiding state
|
||||
contamination, and enables fine-grained permission control.
|
||||
|
||||
With this feature, you can:
|
||||
|
||||
- **Specify tool access:** Define exactly which tools an agent can access using
|
||||
a `tools` list in the agent definition.
|
||||
- **Define inline MCP servers:** Configure Model Context Protocol (MCP) servers
|
||||
(which provide a standardized way to connect AI models to external tools and
|
||||
data sources) directly in the subagent's markdown frontmatter, isolating them
|
||||
to that specific agent.
|
||||
- **Maintain state isolation:** Ensure that subagents only interact with their
|
||||
own set of tools and servers, preventing side effects and state contamination.
|
||||
- **Apply subagent-specific policies:** Enforce granular rules in your
|
||||
[Policy Engine](../reference/policy-engine.md) TOML configuration based on the
|
||||
executing subagent's name.
|
||||
|
||||
### Configuring isolated tools and servers
|
||||
|
||||
You can configure tool isolation for a subagent by updating its markdown
|
||||
frontmatter. This lets you explicitly state which tools the subagent can use,
|
||||
rather than relying on the global registry.
|
||||
|
||||
Add an `mcpServers` object to define inline MCP servers that are unique to the
|
||||
agent.
|
||||
|
||||
**Example:**
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: my-isolated-agent
|
||||
tools:
|
||||
- grep_search
|
||||
- read_file
|
||||
mcpServers:
|
||||
my-custom-server:
|
||||
command: 'node'
|
||||
args: ['path/to/server.js']
|
||||
---
|
||||
```
|
||||
|
||||
### Subagent-specific policies
|
||||
|
||||
You can enforce fine-grained control over subagents using the
|
||||
[Policy Engine's](../reference/policy-engine.md) TOML configuration. This allows
|
||||
you to grant or restrict permissions specifically for an agent, without
|
||||
affecting the rest of your CLI session.
|
||||
|
||||
To restrict a policy rule to a specific subagent, add the `subagent` property to
|
||||
the `[[rules]]` block in your `policy.toml` file.
|
||||
|
||||
**Example:**
|
||||
|
||||
```toml
|
||||
[[rules]]
|
||||
name = "Allow pr-creator to push code"
|
||||
subagent = "pr-creator"
|
||||
description = "Permit pr-creator to push branches automatically."
|
||||
action = "allow"
|
||||
toolName = "run_shell_command"
|
||||
commandPrefix = "git push"
|
||||
```
|
||||
|
||||
In this configuration, the policy rule only triggers if the executing subagent's
|
||||
name matches `pr-creator`. Rules without the `subagent` property apply
|
||||
universally to all agents.
|
||||
|
||||
## Managing subagents
|
||||
|
||||
You can manage subagents interactively using the `/agents` command or
|
||||
@@ -381,6 +533,24 @@ field.
|
||||
}
|
||||
```
|
||||
|
||||
#### Safety policies (TOML)
|
||||
|
||||
You can restrict access to specific subagents using the CLI's **Policy Engine**.
|
||||
Subagents are treated as virtual tool names for policy matching purposes.
|
||||
|
||||
To govern access to a subagent, create a `.toml` file in your policy directory
|
||||
(e.g., `~/.gemini/policies/`):
|
||||
|
||||
```toml
|
||||
[[rule]]
|
||||
toolName = "codebase_investigator"
|
||||
decision = "deny"
|
||||
deny_message = "Deep codebase analysis is restricted for this session."
|
||||
```
|
||||
|
||||
For more information on setting up fine-grained safety guardrails, see the
|
||||
[Policy Engine reference](../reference/policy-engine.md#special-syntax-for-subagents).
|
||||
|
||||
### Optimizing your subagent
|
||||
|
||||
The main agent's system prompt encourages it to use an expert subagent when one
|
||||
@@ -406,15 +576,11 @@ If you need to further tune your subagent, you can do so by selecting the model
|
||||
to optimize for with `/model` and then asking the model why it does not think
|
||||
that your subagent was called with a specific prompt and the given description.
|
||||
|
||||
## Remote subagents (Agent2Agent) (experimental)
|
||||
## Remote subagents (Agent2Agent)
|
||||
|
||||
Gemini CLI can also delegate tasks to remote subagents using the Agent-to-Agent
|
||||
(A2A) protocol.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> Remote subagents are currently an experimental feature.
|
||||
|
||||
See the [Remote Subagents documentation](remote-agents) for detailed
|
||||
configuration, authentication, and usage instructions.
|
||||
|
||||
@@ -423,3 +589,14 @@ configuration, authentication, and usage instructions.
|
||||
Extensions can bundle and distribute subagents. See the
|
||||
[Extensions documentation](../extensions/index.md#subagents) for details on how
|
||||
to package agents within an extension.
|
||||
|
||||
## Disabling subagents
|
||||
|
||||
Subagents are enabled by default. To disable them, set `enableAgents` to `false`
|
||||
in your `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"experimental": { "enableAgents": false }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -117,8 +117,9 @@ for your users.
|
||||
Follow [Semantic Versioning (SemVer)](https://semver.org/) to communicate
|
||||
changes clearly.
|
||||
|
||||
- **Major:** Breaking changes (e.g., renaming tools or changing arguments).
|
||||
- **Minor:** New features (e.g., adding new tools or commands).
|
||||
- **Major:** Breaking changes (for example, renaming tools or changing
|
||||
arguments).
|
||||
- **Minor:** New features (for example, adding new tools or commands).
|
||||
- **Patch:** Bug fixes and performance improvements.
|
||||
|
||||
### Release channels
|
||||
@@ -182,7 +183,7 @@ If your tools aren't working as expected:
|
||||
If a custom command isn't responding:
|
||||
|
||||
- **Check precedence:** Remember that user and project commands take precedence
|
||||
over extension commands. Use the prefixed name (e.g., `/extension.command`) to
|
||||
verify the extension's version.
|
||||
over extension commands. Use the prefixed name (for example,
|
||||
`/extension.command`) to verify the extension's version.
|
||||
- **Help command:** Run `/help` to see a list of all available commands and
|
||||
their sources.
|
||||
|
||||
@@ -88,12 +88,12 @@ gemini extensions new <path> [template]
|
||||
```
|
||||
|
||||
- `<path>`: The directory to create.
|
||||
- `[template]`: The template to use (e.g., `mcp-server`, `context`,
|
||||
- `[template]`: The template to use (for example, `mcp-server`, `context`,
|
||||
`custom-commands`).
|
||||
|
||||
### Link a local extension
|
||||
|
||||
Create a symbolic link between your development directory and the Gemini CLI
|
||||
Create a symbolic link between your development directory and Gemini CLI
|
||||
extensions directory. This lets you test changes immediately without
|
||||
reinstalling.
|
||||
|
||||
@@ -244,7 +244,7 @@ agent definition files (`.md`) to an `agents/` directory in your extension root.
|
||||
|
||||
### <a id="policy-engine"></a>Policy Engine
|
||||
|
||||
Extensions can contribute policy rules and safety checkers to the Gemini CLI
|
||||
Extensions can contribute policy rules and safety checkers to Gemini CLI
|
||||
[Policy Engine](../reference/policy-engine.md). These rules are defined in
|
||||
`.toml` files and take effect when the extension is activated.
|
||||
|
||||
@@ -324,13 +324,14 @@ defined in the `themes` array in `gemini-extension.json`.
|
||||
Custom themes provided by extensions can be selected using the `/theme` command
|
||||
or by setting the `ui.theme` property in your `settings.json` file. Note that
|
||||
when referring to a theme from an extension, the extension name is appended to
|
||||
the theme name in parentheses, e.g., `shades-of-green (my-green-extension)`.
|
||||
the theme name in parentheses, for example,
|
||||
`shades-of-green (my-green-extension)`.
|
||||
|
||||
### Conflict resolution
|
||||
|
||||
Extension commands have the lowest precedence. If an extension command name
|
||||
conflicts with a user or project command, the extension command is prefixed with
|
||||
the extension name (e.g., `/gcp.deploy`) using a dot separator.
|
||||
the extension name (for example, `/gcp.deploy`) using a dot separator.
|
||||
|
||||
## Variables
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Release extensions
|
||||
|
||||
Release Gemini CLI extensions to your users through a Git repository or GitHub
|
||||
Releases.
|
||||
Releases. This guide explains how to share your work, list it in the gallery,
|
||||
and manage updates.
|
||||
|
||||
Git repository releases are the simplest approach and offer the most flexibility
|
||||
for managing development branches. GitHub Releases are more efficient for
|
||||
@@ -98,7 +99,7 @@ Use these values for the placeholders:
|
||||
**Examples:**
|
||||
|
||||
- `darwin.arm64.my-tool.tar.gz` (specific to Apple Silicon Macs)
|
||||
- `darwin.my-tool.tar.gz` (fallback for all Macs, e.g. Intel)
|
||||
- `darwin.my-tool.tar.gz` (fallback for all Macs, for example Intel)
|
||||
- `linux.x64.my-tool.tar.gz`
|
||||
- `win32.my-tool.zip`
|
||||
|
||||
@@ -153,28 +154,62 @@ jobs:
|
||||
release/win32.arm64.my-tool.zip
|
||||
```
|
||||
|
||||
## Migrating an Extension Repository
|
||||
## Migrate an extension repository
|
||||
|
||||
If you need to move your extension to a new repository (e.g., from a personal
|
||||
account to an organization) or rename it, you can use the `migratedTo` property
|
||||
in your `gemini-extension.json` file to seamlessly transition your users.
|
||||
If you move your extension to a new repository or rename it, use the
|
||||
`migratedTo` property in `gemini-extension.json` to seamlessly transition your
|
||||
users.
|
||||
|
||||
1. **Create the new repository**: Setup your extension in its new location.
|
||||
2. **Update the old repository**: In your original repository, update the
|
||||
`gemini-extension.json` file to include the `migratedTo` property, pointing
|
||||
to the new repository URL, and bump the version number. You can optionally
|
||||
change the `name` of your extension at this time in the new repository.
|
||||
```json
|
||||
{
|
||||
"name": "my-extension",
|
||||
"version": "1.1.0",
|
||||
"migratedTo": "https://github.com/new-owner/new-extension-repo"
|
||||
}
|
||||
```
|
||||
3. **Release the update**: Publish this new version in your old repository.
|
||||
1. **Create the new repository:** Set up your extension in its new location.
|
||||
2. **Update the old repository:** In your original repository, update the
|
||||
`gemini-extension.json` file to include the `migratedTo` property pointing
|
||||
to the new repository URL, and increment the version number.
|
||||
```json
|
||||
{
|
||||
"name": "my-extension",
|
||||
"version": "1.1.0",
|
||||
"migratedTo": "https://github.com/new-owner/new-extension-repo"
|
||||
}
|
||||
```
|
||||
3. **Release the update:** Publish this new version in your old repository.
|
||||
|
||||
When users check for updates, the Gemini CLI will detect the `migratedTo` field,
|
||||
verify that the new repository contains a valid extension update, and
|
||||
automatically update their local installation to track the new source and name
|
||||
moving forward. All extension settings will automatically migrate to the new
|
||||
installation.
|
||||
When users check for updates, Gemini CLI detects the `migratedTo` field,
|
||||
verifies the new repository, and automatically updates their local installation
|
||||
to track the new source. All settings migrate automatically.
|
||||
|
||||
## How updates work
|
||||
|
||||
Gemini CLI automatically checks for extension updates based on the installation
|
||||
method. Understanding these mechanisms helps you ensure your users always have
|
||||
the latest version.
|
||||
|
||||
### Sync manifest and tags
|
||||
|
||||
For GitHub releases, always ensure the `version` in `gemini-extension.json`
|
||||
matches your GitHub release tag. While the CLI uses tags for update detection,
|
||||
it displays the manifest version in the UI. Keeping them in sync prevents
|
||||
confusion.
|
||||
|
||||
### Update mechanisms
|
||||
|
||||
<details>
|
||||
<summary>Technical update details</summary>
|
||||
|
||||
The CLI uses different strategies depending on the installation type:
|
||||
|
||||
- **GitHub releases:** The CLI queries the GitHub API for the latest release
|
||||
tag. It ignores the `version` field in the manifest for detection.
|
||||
- **Git clones:** The CLI runs `git ls-remote` to compare the latest remote
|
||||
commit hash with your local `HEAD`.
|
||||
- **Local extensions:** The CLI compares the `version` field in the source
|
||||
directory's manifest with the installed version.
|
||||
|
||||
To verify an extension's installation type, inspect the `type` field in the
|
||||
metadata file at `~/.gemini/extensions/<name>/.gemini-extension-install.json`.
|
||||
|
||||
</details>
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!IMPORTANT]
|
||||
> The `migratedTo` flow requires at least one release on the new repository for
|
||||
> the CLI to recognize it as a valid update source.
|
||||
|
||||
@@ -7,22 +7,22 @@ linking it for local development.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you start, ensure you have the Gemini CLI installed and a basic
|
||||
understanding of Node.js.
|
||||
Before you start, ensure you have Gemini CLI installed and a basic understanding
|
||||
of Node.js.
|
||||
|
||||
## Extension features
|
||||
|
||||
Extensions offer several ways to customize Gemini CLI. Use this table to decide
|
||||
which features your extension needs.
|
||||
|
||||
| Feature | What it is | When to use it | Invoked by |
|
||||
| :------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------- |
|
||||
| **[MCP server](reference.md#mcp-servers)** | A standard way to expose new tools and data sources to the model. | Use this when you want the model to be able to _do_ new things, like fetching data from an internal API, querying a database, or controlling a local application. We also support MCP resources (which can replace custom commands) and system instructions (which can replace custom context) | Model |
|
||||
| **[Custom commands](../cli/custom-commands.md)** | A shortcut (like `/my-cmd`) that executes a pre-defined prompt or shell command. | Use this for repetitive tasks or to save long, complex prompts that you use frequently. Great for automation. | User |
|
||||
| **[Context file (`GEMINI.md`)](reference.md#contextfilename)** | A markdown file containing instructions that are loaded into the model's context at the start of every session. | Use this to define the "personality" of your extension, set coding standards, or provide essential knowledge that the model should always have. | CLI provides to model |
|
||||
| **[Agent skills](../cli/skills.md)** | A specialized set of instructions and workflows that the model activates only when needed. | Use this for complex, occasional tasks (like "create a PR" or "audit security") to avoid cluttering the main context window when the skill isn't being used. | Model |
|
||||
| **[Hooks](../hooks/index.md)** | A way to intercept and customize the CLI's behavior at specific lifecycle events (e.g., before/after a tool call). | Use this when you want to automate actions based on what the model is doing, like validating tool arguments, logging activity, or modifying the model's input/output. | CLI |
|
||||
| **[Custom themes](reference.md#themes)** | A set of color definitions to personalize the CLI UI. | Use this to provide a unique visual identity for your extension or to offer specialized high-contrast or thematic color schemes. | User (via /theme) |
|
||||
| Feature | What it is | When to use it | Invoked by |
|
||||
| :------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------- |
|
||||
| **[MCP server](reference.md#mcp-servers)** | A standard way to expose new tools and data sources to the model. | Use this when you want the model to be able to _do_ new things, like fetching data from an internal API, querying a database, or controlling a local application. We also support MCP resources (which can replace custom commands) and system instructions (which can replace custom context) | Model |
|
||||
| **[Custom commands](../cli/custom-commands.md)** | A shortcut (like `/my-cmd`) that executes a pre-defined prompt or shell command. | Use this for repetitive tasks or to save long, complex prompts that you use frequently. Great for automation. | User |
|
||||
| **[Context file (`GEMINI.md`)](reference.md#contextfilename)** | A markdown file containing instructions that are loaded into the model's context at the start of every session. | Use this to define the "personality" of your extension, set coding standards, or provide essential knowledge that the model should always have. | CLI provides to model |
|
||||
| **[Agent skills](../cli/skills.md)** | A specialized set of instructions and workflows that the model activates only when needed. | Use this for complex, occasional tasks (like "create a PR" or "audit security") to avoid cluttering the main context window when the skill isn't being used. | Model |
|
||||
| **[Hooks](../hooks/index.md)** | A way to intercept and customize the CLI's behavior at specific lifecycle events (for example, before/after a tool call). | Use this when you want to automate actions based on what the model is doing, like validating tool arguments, logging activity, or modifying the model's input/output. | CLI |
|
||||
| **[Custom themes](reference.md#themes)** | A set of color definitions to personalize the CLI UI. | Use this to provide a unique visual identity for your extension or to offer specialized high-contrast or thematic color schemes. | User (via /theme) |
|
||||
|
||||
## Step 1: Create a new extension
|
||||
|
||||
@@ -172,7 +172,7 @@ Link your extension to your Gemini CLI installation for local development.
|
||||
|
||||
2. **Link the extension:**
|
||||
|
||||
The `link` command creates a symbolic link from the Gemini CLI extensions
|
||||
The `link` command creates a symbolic link from Gemini CLI extensions
|
||||
directory to your development directory. Changes you make are reflected
|
||||
immediately.
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Tabs, TabItem } from '@astrojs/starlight/components';
|
||||
|
||||
# Gemini CLI authentication setup
|
||||
|
||||
To use Gemini CLI, you'll need to authenticate with Google. This guide helps you
|
||||
quickly find the best way to sign in based on your account type and how you're
|
||||
using the CLI.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!TIP]
|
||||
> Looking for a high-level comparison of all available subscriptions?
|
||||
> To compare features and find the right quota for your needs, see our
|
||||
@@ -23,7 +24,7 @@ Select the authentication method that matches your situation in the table below:
|
||||
| Organization users with a company, school, or Google Workspace account | [Sign in with Google](#login-google) | [Yes](#set-gcp) |
|
||||
| AI Studio user with a Gemini API key | [Use Gemini API Key](#gemini-api) | No |
|
||||
| Google Cloud Vertex AI user | [Vertex AI](#vertex-ai) | [Yes](#set-gcp) |
|
||||
| [Headless mode](#headless) | [Use Gemini API Key](#gemini-api) or<br> [Vertex AI](#vertex-ai) | No (for Gemini API Key)<br> [Yes](#set-gcp) (for Vertex AI) |
|
||||
| [Headless mode](#headless) | [Use Gemini API Key](#gemini-api) or<br /> [Vertex AI](#vertex-ai) | No (for Gemini API Key)<br /> [Yes](#set-gcp) (for Vertex AI) |
|
||||
|
||||
### What is my Google account type?
|
||||
|
||||
@@ -84,19 +85,24 @@ To authenticate and use Gemini CLI with a Gemini API key:
|
||||
|
||||
2. Set the `GEMINI_API_KEY` environment variable to your key. For example:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
# Replace YOUR_GEMINI_API_KEY with the key from AI Studio
|
||||
export GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
|
||||
```
|
||||
```bash
|
||||
# Replace YOUR_GEMINI_API_KEY with the key from AI Studio
|
||||
export GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
# Replace YOUR_GEMINI_API_KEY with the key from AI Studio
|
||||
$env:GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
|
||||
```
|
||||
```powershell
|
||||
# Replace YOUR_GEMINI_API_KEY with the key from AI Studio
|
||||
$env:GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
To make this setting persistent, see
|
||||
[Persisting Environment Variables](#persisting-vars).
|
||||
@@ -109,7 +115,6 @@ To authenticate and use Gemini CLI with a Gemini API key:
|
||||
|
||||
4. Select **Use Gemini API key**.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!WARNING]
|
||||
> Treat API keys, especially for services like Gemini, as sensitive
|
||||
> credentials. Protect them to prevent unauthorized access and potential misuse
|
||||
@@ -131,21 +136,26 @@ or the location where you want to run your jobs.
|
||||
|
||||
For example:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
```bash
|
||||
# Replace with your project ID and desired location (for example, us-central1)
|
||||
export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
|
||||
export GOOGLE_CLOUD_LOCATION="YOUR_PROJECT_LOCATION"
|
||||
```
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
```powershell
|
||||
# Replace with your project ID and desired location (for example, us-central1)
|
||||
$env:GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
|
||||
$env:GOOGLE_CLOUD_LOCATION="YOUR_PROJECT_LOCATION"
|
||||
```
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
To make any Vertex AI environment variable settings persistent, see
|
||||
[Persisting Environment Variables](#persisting-vars).
|
||||
@@ -157,17 +167,22 @@ Consider this authentication method if you have Google Cloud CLI installed.
|
||||
If you have previously set `GOOGLE_API_KEY` or `GEMINI_API_KEY`, you must unset
|
||||
them to use ADC.
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
```bash
|
||||
unset GOOGLE_API_KEY GEMINI_API_KEY
|
||||
```
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
```powershell
|
||||
Remove-Item Env:\GOOGLE_API_KEY, Env:\GEMINI_API_KEY -ErrorAction Ignore
|
||||
```
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
1. Verify you have a Google Cloud project and Vertex AI API is enabled.
|
||||
|
||||
@@ -195,17 +210,22 @@ pipelines, or if your organization restricts user-based ADC or API key creation.
|
||||
If you have previously set `GOOGLE_API_KEY` or `GEMINI_API_KEY`, you must unset
|
||||
them:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
```bash
|
||||
unset GOOGLE_API_KEY GEMINI_API_KEY
|
||||
```
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
```powershell
|
||||
Remove-Item Env:\GOOGLE_API_KEY, Env:\GEMINI_API_KEY -ErrorAction Ignore
|
||||
```
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
1. [Create a service account and key](https://cloud.google.com/iam/docs/keys-create-delete)
|
||||
and download the provided JSON file. Assign the "Vertex AI User" role to the
|
||||
@@ -214,19 +234,24 @@ Remove-Item Env:\GOOGLE_API_KEY, Env:\GEMINI_API_KEY -ErrorAction Ignore
|
||||
2. Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the JSON
|
||||
file's absolute path. For example:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
# Replace /path/to/your/keyfile.json with the actual path
|
||||
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/keyfile.json"
|
||||
```
|
||||
```bash
|
||||
# Replace /path/to/your/keyfile.json with the actual path
|
||||
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/keyfile.json"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
# Replace C:\path\to\your\keyfile.json with the actual path
|
||||
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\path\to\your\keyfile.json"
|
||||
```
|
||||
```powershell
|
||||
# Replace C:\path\to\your\keyfile.json with the actual path
|
||||
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\path\to\your\keyfile.json"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
3. [Configure your Google Cloud Project](#set-gcp).
|
||||
|
||||
@@ -238,7 +263,6 @@ Remove-Item Env:\GOOGLE_API_KEY, Env:\GEMINI_API_KEY -ErrorAction Ignore
|
||||
|
||||
5. Select **Vertex AI**.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!WARNING]
|
||||
> Protect your service account key file as it gives access to
|
||||
> your resources.
|
||||
@@ -250,19 +274,24 @@ Remove-Item Env:\GOOGLE_API_KEY, Env:\GEMINI_API_KEY -ErrorAction Ignore
|
||||
|
||||
2. Set the `GOOGLE_API_KEY` environment variable:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
# Replace YOUR_GOOGLE_API_KEY with your Vertex AI API key
|
||||
export GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"
|
||||
```
|
||||
```bash
|
||||
# Replace YOUR_GOOGLE_API_KEY with your Vertex AI API key
|
||||
export GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
# Replace YOUR_GOOGLE_API_KEY with your Vertex AI API key
|
||||
$env:GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"
|
||||
```
|
||||
```powershell
|
||||
# Replace YOUR_GOOGLE_API_KEY with your Vertex AI API key
|
||||
$env:GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
If you see errors like `"API keys are not supported by this API..."`, your
|
||||
organization might restrict API key usage for this service. Try the other
|
||||
@@ -280,7 +309,6 @@ Remove-Item Env:\GOOGLE_API_KEY, Env:\GEMINI_API_KEY -ErrorAction Ignore
|
||||
|
||||
## Set your Google Cloud project <a id="set-gcp"></a>
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!IMPORTANT]
|
||||
> Most individual Google accounts (free and paid) don't require a
|
||||
> Google Cloud project for authentication.
|
||||
@@ -308,19 +336,24 @@ To configure Gemini CLI to use a Google Cloud project, do the following:
|
||||
|
||||
For example, to set the `GOOGLE_CLOUD_PROJECT_ID` variable:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
# Replace YOUR_PROJECT_ID with your actual Google Cloud project ID
|
||||
export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
|
||||
```
|
||||
```bash
|
||||
# Replace YOUR_PROJECT_ID with your actual Google Cloud project ID
|
||||
export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
# Replace YOUR_PROJECT_ID with your actual Google Cloud project ID
|
||||
$env:GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
|
||||
```
|
||||
```powershell
|
||||
# Replace YOUR_PROJECT_ID with your actual Google Cloud project ID
|
||||
$env:GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
To make this setting persistent, see
|
||||
[Persisting Environment Variables](#persisting-vars).
|
||||
@@ -333,21 +366,29 @@ persist them with the following methods:
|
||||
1. **Add your environment variables to your shell configuration file:** Append
|
||||
the environment variable commands to your shell's startup file.
|
||||
|
||||
**macOS/Linux** (for example, `~/.bashrc`, `~/.zshrc`, or `~/.profile`):
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
echo 'export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
(for example, `~/.bashrc`, `~/.zshrc`, or `~/.profile`):
|
||||
|
||||
**Windows (PowerShell)** (for example, `$PROFILE`):
|
||||
```bash
|
||||
echo 'export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
```powershell
|
||||
Add-Content -Path $PROFILE -Value '$env:GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"'
|
||||
. $PROFILE
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
(for example, `$PROFILE`):
|
||||
|
||||
```powershell
|
||||
Add-Content -Path $PROFILE -Value '$env:GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"'
|
||||
. $PROFILE
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!WARNING]
|
||||
> Be aware that when you export API keys or service account
|
||||
> paths in your shell configuration file, any process launched from that
|
||||
@@ -361,25 +402,30 @@ persist them with the following methods:
|
||||
|
||||
Example for user-wide settings:
|
||||
|
||||
**macOS/Linux**
|
||||
<Tabs>
|
||||
<TabItem label="macOS/Linux">
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.gemini
|
||||
cat >> ~/.gemini/.env <<'EOF'
|
||||
GOOGLE_CLOUD_PROJECT="your-project-id"
|
||||
# Add other variables like GEMINI_API_KEY as needed
|
||||
EOF
|
||||
```
|
||||
```bash
|
||||
mkdir -p ~/.gemini
|
||||
cat >> ~/.gemini/.env <<'EOF'
|
||||
GOOGLE_CLOUD_PROJECT="your-project-id"
|
||||
# Add other variables like GEMINI_API_KEY as needed
|
||||
EOF
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**
|
||||
</TabItem>
|
||||
<TabItem label="Windows (PowerShell)">
|
||||
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.gemini"
|
||||
@"
|
||||
GOOGLE_CLOUD_PROJECT="your-project-id"
|
||||
# Add other variables like GEMINI_API_KEY as needed
|
||||
"@ | Out-File -FilePath "$env:USERPROFILE\.gemini\.env" -Encoding utf8 -Append
|
||||
```
|
||||
```powershell
|
||||
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.gemini"
|
||||
@"
|
||||
GOOGLE_CLOUD_PROJECT="your-project-id"
|
||||
# Add other variables like GEMINI_API_KEY as needed
|
||||
"@ | Out-File -FilePath "$env:USERPROFILE\.gemini\.env" -Encoding utf8 -Append
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Variables are loaded from the first file found, not merged.
|
||||
|
||||
@@ -398,8 +444,8 @@ on this page.
|
||||
|
||||
## Running in headless mode <a id="headless"></a>
|
||||
|
||||
[Headless mode](../cli/headless) will use your existing authentication method,
|
||||
if an existing authentication credential is cached.
|
||||
[Headless mode](../cli/headless.md) will use your existing authentication
|
||||
method, if an existing authentication credential is cached.
|
||||
|
||||
If you have not already signed in with an authentication credential, you must
|
||||
configure authentication using environment variables:
|
||||
@@ -60,7 +60,7 @@ or fallback to Gemini 2.5 Pro.
|
||||
> [!NOTE]
|
||||
> The **Keep trying** option uses exponential backoff, in which Gemini
|
||||
> CLI waits longer between each retry, when the system is busy. If the retry
|
||||
> doesn't happen immediately, please wait a few minutes for the request to
|
||||
> doesn't happen immediately, wait a few minutes for the request to
|
||||
> process.
|
||||
|
||||
### Model selection and routing types
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Get started with Gemini CLI
|
||||
|
||||
Welcome to Gemini CLI! This guide will help you install, configure, and start
|
||||
using the Gemini CLI to enhance your workflow right from your terminal.
|
||||
using Gemini CLI to enhance your workflow right from your terminal.
|
||||
|
||||
## Quickstart: Install, authenticate, configure, and use Gemini CLI
|
||||
|
||||
@@ -24,7 +24,8 @@ Once Gemini CLI is installed, run Gemini CLI from your command line:
|
||||
gemini
|
||||
```
|
||||
|
||||
For more installation options, see [Gemini CLI Installation](./installation.md).
|
||||
For more installation options, see
|
||||
[Gemini CLI Installation](./installation.mdx).
|
||||
|
||||
## Authenticate
|
||||
|
||||
@@ -46,7 +47,7 @@ cases, you can log in with your existing Google account:
|
||||
|
||||
Certain account types may require you to configure a Google Cloud project. For
|
||||
more information, including other authentication methods, see
|
||||
[Gemini CLI Authentication Setup](./authentication.md).
|
||||
[Gemini CLI Authentication Setup](./authentication.mdx).
|
||||
|
||||
## Configure
|
||||
|
||||
@@ -132,7 +133,7 @@ colors. After analyzing the source code, here's how it works:
|
||||
getters. The `red` getter adds the red color code, and the `bold` getter adds
|
||||
the bold code.
|
||||
|
||||
- **Output generation:** When the chain is treated as a string (e.g., in
|
||||
- **Output generation:** When the chain is treated as a string (for example, in
|
||||
`console.log`), a final `toString()` method is called. This method joins all
|
||||
the stored ANSI codes, wraps them around the input string ('Hello'), and adds
|
||||
a reset code at the end. This produces the final, styled string that the
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
# Gemini CLI installation, execution, and releases
|
||||
|
||||
This document provides an overview of Gemini CLI's system requirements,
|
||||
installation methods, and release types.
|
||||
|
||||
## Recommended system specifications
|
||||
|
||||
- **Operating System:**
|
||||
- macOS 15+
|
||||
- Windows 11 24H2+
|
||||
- Ubuntu 20.04+
|
||||
- **Hardware:**
|
||||
- "Casual" usage: 4GB+ RAM (short sessions, common tasks and edits)
|
||||
- "Power" usage: 16GB+ RAM (long sessions, large codebases, deep context)
|
||||
- **Runtime:** Node.js 20.0.0+
|
||||
- **Shell:** Bash, Zsh, or PowerShell
|
||||
- **Location:**
|
||||
[Gemini Code Assist supported locations](https://developers.google.com/gemini-code-assist/resources/available-locations#americas)
|
||||
- **Internet connection required**
|
||||
|
||||
## Install Gemini CLI
|
||||
|
||||
We recommend most users install Gemini CLI using one of the following
|
||||
installation methods:
|
||||
|
||||
- npm
|
||||
- Homebrew
|
||||
- MacPorts
|
||||
- Anaconda
|
||||
|
||||
Note that Gemini CLI comes pre-installed on
|
||||
[**Cloud Shell**](https://docs.cloud.google.com/shell/docs) and
|
||||
[**Cloud Workstations**](https://cloud.google.com/workstations).
|
||||
|
||||
### Install globally with npm
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
### Install globally with Homebrew (macOS/Linux)
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||
## Run Gemini CLI
|
||||
|
||||
For most users, we recommend running Gemini CLI with the `gemini` command:
|
||||
|
||||
```bash
|
||||
gemini
|
||||
```
|
||||
|
||||
For a list of options and additional commands, see the
|
||||
[CLI cheatsheet](../cli/cli-reference.md).
|
||||
|
||||
You can also run Gemini CLI using one of the following advanced methods:
|
||||
|
||||
- Run instantly with npx. You can run Gemini CLI without permanent installation.
|
||||
- In a sandbox. This method offers increased security and isolation.
|
||||
- From the source. This is recommended for contributors to the project.
|
||||
|
||||
### Run instantly with npx
|
||||
|
||||
```bash
|
||||
# Using npx (no installation required)
|
||||
npx @google/gemini-cli
|
||||
```
|
||||
|
||||
You can also execute the CLI directly from the main branch on GitHub, which is
|
||||
helpful for testing features still in development:
|
||||
|
||||
```bash
|
||||
npx https://github.com/google-gemini/gemini-cli
|
||||
```
|
||||
|
||||
### Run in a sandbox (Docker/Podman)
|
||||
|
||||
For security and isolation, Gemini CLI can be run inside a container. This is
|
||||
the default way that the CLI executes tools that might have side effects.
|
||||
|
||||
- **Directly from the registry:** You can run the published sandbox image
|
||||
directly. This is useful for environments where you only have Docker and want
|
||||
to run the CLI.
|
||||
```bash
|
||||
# Run the published sandbox image
|
||||
docker run --rm -it us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.1.1
|
||||
```
|
||||
- **Using the `--sandbox` flag:** If you have Gemini CLI installed locally
|
||||
(using the standard installation described above), you can instruct it to run
|
||||
inside the sandbox container.
|
||||
```bash
|
||||
gemini --sandbox -y -p "your prompt here"
|
||||
```
|
||||
|
||||
### Run from source (recommended for Gemini CLI contributors)
|
||||
|
||||
Contributors to the project will want to run the CLI directly from the source
|
||||
code.
|
||||
|
||||
- **Development mode:** This method provides hot-reloading and is useful for
|
||||
active development.
|
||||
```bash
|
||||
# From the root of the repository
|
||||
npm run start
|
||||
```
|
||||
- **Production-like mode (linked package):** This method simulates a global
|
||||
installation by linking your local package. It's useful for testing a local
|
||||
build in a production workflow.
|
||||
|
||||
```bash
|
||||
# Link the local cli package to your global node_modules
|
||||
npm link packages/cli
|
||||
|
||||
# Now you can run your local version using the `gemini` command
|
||||
gemini
|
||||
```
|
||||
|
||||
## Releases
|
||||
|
||||
Gemini CLI has three release channels: nightly, preview, and stable. For most
|
||||
users, we recommend the stable release, which is the default installation.
|
||||
|
||||
### Stable
|
||||
|
||||
New stable releases are published each week. The stable release is the promotion
|
||||
of last week's `preview` release along with any bug fixes. The stable release
|
||||
uses `latest` tag, but omitting the tag also installs the latest stable release
|
||||
by default:
|
||||
|
||||
```bash
|
||||
# Both commands install the latest stable release.
|
||||
npm install -g @google/gemini-cli
|
||||
npm install -g @google/gemini-cli@latest
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
||||
New preview releases will be published each week. These releases are not fully
|
||||
vetted and may contain regressions or other outstanding issues. Try out the
|
||||
preview release by using the `preview` tag:
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli@preview
|
||||
```
|
||||
|
||||
### Nightly
|
||||
|
||||
Nightly releases are published every day. The nightly release includes all
|
||||
changes from the main branch at time of release. It should be assumed there are
|
||||
pending validations and issues. You can help test the latest changes by
|
||||
installing with the `nightly` tag:
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli@nightly
|
||||
```
|
||||
@@ -0,0 +1,201 @@
|
||||
import { Tabs, TabItem } from '@astrojs/starlight/components';
|
||||
|
||||
# Gemini CLI installation, execution, and releases
|
||||
|
||||
This document provides an overview of Gemini CLI's system requirements,
|
||||
installation methods, and release types.
|
||||
|
||||
## Recommended system specifications
|
||||
|
||||
- **Operating System:**
|
||||
- macOS 15+
|
||||
- Windows 11 24H2+
|
||||
- Ubuntu 20.04+
|
||||
- **Hardware:**
|
||||
- "Casual" usage: 4GB+ RAM (short sessions, common tasks and edits)
|
||||
- "Power" usage: 16GB+ RAM (long sessions, large codebases, deep context)
|
||||
- **Runtime:** Node.js 20.0.0+
|
||||
- **Shell:** Bash, Zsh, or PowerShell
|
||||
- **Location:**
|
||||
[Gemini Code Assist supported locations](https://developers.google.com/gemini-code-assist/resources/available-locations#americas)
|
||||
- **Internet connection required**
|
||||
|
||||
## Install Gemini CLI
|
||||
|
||||
We recommend most users install Gemini CLI using one of the following
|
||||
installation methods. Note that Gemini CLI comes pre-installed on
|
||||
[**Cloud Shell**](https://docs.cloud.google.com/shell/docs) and
|
||||
[**Cloud Workstations**](https://cloud.google.com/workstations).
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="npm">
|
||||
|
||||
Install globally with npm:
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Homebrew (macOS/Linux)">
|
||||
|
||||
Install globally with Homebrew:
|
||||
|
||||
```bash
|
||||
brew install gemini-cli
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="MacPorts (macOS)">
|
||||
|
||||
Install globally with MacPorts:
|
||||
|
||||
```bash
|
||||
sudo port install gemini-cli
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Anaconda">
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Run Gemini CLI
|
||||
|
||||
For most users, we recommend running Gemini CLI with the `gemini` command:
|
||||
|
||||
```bash
|
||||
gemini
|
||||
```
|
||||
|
||||
For a list of options and additional commands, see the
|
||||
[CLI cheatsheet](../cli/cli-reference.md).
|
||||
|
||||
You can also run Gemini CLI using one of the following advanced methods:
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="npx">
|
||||
|
||||
Run instantly with npx. You can run Gemini CLI without permanent installation.
|
||||
|
||||
```bash
|
||||
# Using npx (no installation required)
|
||||
npx @google/gemini-cli
|
||||
```
|
||||
|
||||
You can also execute the CLI directly from the main branch on GitHub, which is
|
||||
helpful for testing features still in development:
|
||||
|
||||
```bash
|
||||
npx https://github.com/google-gemini/gemini-cli
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Docker/Podman Sandbox">
|
||||
|
||||
For security and isolation, Gemini CLI can be run inside a container. This is
|
||||
the default way that the CLI executes tools that might have side effects.
|
||||
|
||||
- **Directly from the registry:** You can run the published sandbox image
|
||||
directly. This is useful for environments where you only have Docker and want
|
||||
to run the CLI.
|
||||
```bash
|
||||
# Run the published sandbox image
|
||||
docker run --rm -it us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.1.1
|
||||
```
|
||||
- **Using the `--sandbox` flag:** If you have Gemini CLI installed locally
|
||||
(using the standard installation described above), you can instruct it to run
|
||||
inside the sandbox container.
|
||||
```bash
|
||||
gemini --sandbox -y -p "your prompt here"
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="From source">
|
||||
|
||||
Contributors to the project will want to run the CLI directly from the source
|
||||
code.
|
||||
|
||||
- **Development mode:** This method provides hot-reloading and is useful for
|
||||
active development.
|
||||
```bash
|
||||
# From the root of the repository
|
||||
npm run start
|
||||
```
|
||||
- **Production mode (React optimizations):** This method runs the CLI with React
|
||||
production mode enabled, which is useful for testing performance without
|
||||
development overhead.
|
||||
```bash
|
||||
# From the root of the repository
|
||||
npm run start:prod
|
||||
```
|
||||
- **Production-like mode (linked package):** This method simulates a global
|
||||
installation by linking your local package. It's useful for testing a local
|
||||
build in a production workflow.
|
||||
|
||||
```bash
|
||||
# Link the local cli package to your global node_modules
|
||||
npm link packages/cli
|
||||
|
||||
# Now you can run your local version using the `gemini` command
|
||||
gemini
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Releases
|
||||
|
||||
Gemini CLI has three release channels: stable, preview, and nightly. For most
|
||||
users, we recommend the stable release, which is the default installation.
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Stable">
|
||||
|
||||
Stable releases are published each week. A stable release is created from the
|
||||
previous week's preview release along with any bug fixes. The stable release
|
||||
uses the `latest` tag. Omitting the tag also installs the latest stable
|
||||
release by default.
|
||||
|
||||
```bash
|
||||
# Both commands install the latest stable release.
|
||||
npm install -g @google/gemini-cli
|
||||
npm install -g @google/gemini-cli@latest
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Preview">
|
||||
|
||||
New preview releases will be published each week. These releases are not fully
|
||||
vetted and may contain regressions or other outstanding issues. Try out the
|
||||
preview release by using the `preview` tag:
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli@preview
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Nightly">
|
||||
|
||||
Nightly releases are published every day. The nightly release includes all
|
||||
changes from the main branch at time of release. It should be assumed there are
|
||||
pending validations and issues. You can help test the latest changes by
|
||||
installing with the `nightly` tag:
|
||||
|
||||
```bash
|
||||
npm install -g @google/gemini-cli@nightly
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -367,7 +367,7 @@ chmod +x .gemini/hooks/*.js
|
||||
```
|
||||
|
||||
**Windows Note**: On Windows, PowerShell scripts (`.ps1`) don't use `chmod`, but
|
||||
you may need to ensure your execution policy allows them to run (e.g.,
|
||||
you may need to ensure your execution policy allows them to run (for example,
|
||||
`Set-ExecutionPolicy RemoteSigned -Scope CurrentUser`).
|
||||
|
||||
### Version control
|
||||
@@ -401,12 +401,12 @@ git add .gemini/settings.json
|
||||
Understanding where hooks come from and what they can do is critical for secure
|
||||
usage.
|
||||
|
||||
| Hook Source | Description |
|
||||
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **System** | Configured by system administrators (e.g., `/etc/gemini-cli/settings.json`, `/Library/...`). Assumed to be the **safest**. |
|
||||
| **User** (`~/.gemini/...`) | Configured by you. You are responsible for ensuring they are safe. |
|
||||
| **Extensions** | You explicitly approve and install these. Security depends on the extension source (integrity). |
|
||||
| **Project** (`./.gemini/...`) | **Untrusted by default.** Safest in trusted internal repos; higher risk in third-party/public repos. |
|
||||
| Hook Source | Description |
|
||||
| :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **System** | Configured by system administrators (for example, `/etc/gemini-cli/settings.json`, `/Library/...`). Assumed to be the **safest**. |
|
||||
| **User** (`~/.gemini/...`) | Configured by you. You are responsible for ensuring they are safe. |
|
||||
| **Extensions** | You explicitly approve and install these. Security depends on the extension source (integrity). |
|
||||
| **Project** (`./.gemini/...`) | **Untrusted by default.** Safest in trusted internal repos; higher risk in third-party/public repos. |
|
||||
|
||||
#### Project Hook Security
|
||||
|
||||
@@ -422,9 +422,10 @@ When you open a project with hooks defined in `.gemini/settings.json`:
|
||||
5. **Trust**: The hook is marked as "trusted" for this project.
|
||||
|
||||
> **Modification detection**: If the `command` string of a project hook is
|
||||
> changed (e.g., by a `git pull`), its identity changes. Gemini CLI will treat
|
||||
> it as a **new, untrusted hook** and warn you again. This prevents malicious
|
||||
> actors from silently swapping a verified command for a malicious one.
|
||||
> changed (for example, by a `git pull`), its identity changes. Gemini CLI will
|
||||
> treat it as a **new, untrusted hook** and warn you again. This prevents
|
||||
> malicious actors from silently swapping a verified command for a malicious
|
||||
> one.
|
||||
|
||||
### Risks
|
||||
|
||||
@@ -441,17 +442,17 @@ When you open a project with hooks defined in `.gemini/settings.json`:
|
||||
**Verify the source** of any project hooks or extensions before enabling them.
|
||||
|
||||
- For open-source projects, a quick review of the hook scripts is recommended.
|
||||
- For extensions, ensure you trust the author or publisher (e.g., verified
|
||||
publishers, well-known community members).
|
||||
- For extensions, ensure you trust the author or publisher (for example,
|
||||
verified publishers, well-known community members).
|
||||
- Be cautious with obfuscated scripts or compiled binaries from unknown sources.
|
||||
|
||||
#### Sanitize environment
|
||||
|
||||
Hooks inherit the environment of the Gemini CLI process, which may include
|
||||
sensitive API keys. Gemini CLI provides a
|
||||
Hooks inherit the environment of Gemini CLI process, which may include sensitive
|
||||
API keys. Gemini CLI provides a
|
||||
[redaction system](../reference/configuration.md#environment-variable-redaction)
|
||||
that automatically filters variables matching sensitive patterns (e.g., `KEY`,
|
||||
`TOKEN`).
|
||||
that automatically filters variables matching sensitive patterns (for example,
|
||||
`KEY`, `TOKEN`).
|
||||
|
||||
> **Disabled by Default**: Environment redaction is currently **OFF by
|
||||
> default**. We strongly recommend enabling it if you are running third-party
|
||||
@@ -511,7 +512,7 @@ chmod +x .gemini/hooks/my-hook.sh
|
||||
```
|
||||
|
||||
**Windows Note**: On Windows, ensure your execution policy allows running
|
||||
scripts (e.g., `Get-ExecutionPolicy`).
|
||||
scripts (for example, `Get-ExecutionPolicy`).
|
||||
|
||||
**Verify script path:** Ensure the path in `settings.json` resolves correctly.
|
||||
|
||||
|
||||
+16
-14
@@ -22,11 +22,11 @@ With hooks, you can:
|
||||
|
||||
### Getting started
|
||||
|
||||
- **[Writing hooks guide](../hooks/writing-hooks)**: A tutorial on creating your
|
||||
first hook with comprehensive examples.
|
||||
- **[Best practices](../hooks/best-practices)**: Guidelines on security,
|
||||
- **[Writing hooks guide](../hooks/writing-hooks.md)**: A tutorial on creating
|
||||
your first hook with comprehensive examples.
|
||||
- **[Best practices](../hooks/best-practices.md)**: Guidelines on security,
|
||||
performance, and debugging.
|
||||
- **[Hooks reference](../hooks/reference)**: The definitive technical
|
||||
- **[Hooks reference](../hooks/reference.md)**: The definitive technical
|
||||
specification of I/O schemas and exit codes.
|
||||
|
||||
## Core concepts
|
||||
@@ -63,9 +63,9 @@ Hooks communicate via `stdin` (Input) and `stdout` (Output).
|
||||
2. **Pollution = Failure**: If `stdout` contains non-JSON text, parsing will
|
||||
fail. The CLI will default to "Allow" and treat the entire output as a
|
||||
`systemMessage`.
|
||||
3. **Debug via Stderr**: Use `stderr` for **all** logging and debugging (e.g.,
|
||||
`echo "debug" >&2`). Gemini CLI captures `stderr` but never attempts to parse
|
||||
it as JSON.
|
||||
3. **Debug via Stderr**: Use `stderr` for **all** logging and debugging (for
|
||||
example, `echo "debug" >&2`). Gemini CLI captures `stderr` but never attempts
|
||||
to parse it as JSON.
|
||||
|
||||
#### Exit codes
|
||||
|
||||
@@ -74,7 +74,7 @@ execution:
|
||||
|
||||
| Exit Code | Label | Behavioral Impact |
|
||||
| --------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **0** | **Success** | The `stdout` is parsed as JSON. **Preferred code** for all logic, including intentional blocks (e.g., `{"decision": "deny"}`). |
|
||||
| **0** | **Success** | The `stdout` is parsed as JSON. **Preferred code** for all logic, including intentional blocks (for example, `{"decision": "deny"}`). |
|
||||
| **2** | **System Block** | **Critical Block**. The target action (tool, turn, or stop) is aborted. `stderr` is used as the rejection reason. High severity; used for security stops or script failures. |
|
||||
| **Other** | **Warning** | Non-fatal failure. A warning is shown, but the interaction proceeds using original parameters. |
|
||||
|
||||
@@ -84,8 +84,9 @@ You can filter which specific tools or triggers fire your hook using the
|
||||
`matcher` field.
|
||||
|
||||
- **Tool events** (`BeforeTool`, `AfterTool`): Matchers are **Regular
|
||||
Expressions**. (e.g., `"write_.*"`).
|
||||
- **Lifecycle events**: Matchers are **Exact Strings**. (e.g., `"startup"`).
|
||||
Expressions**. (for example, `"write_.*"`).
|
||||
- **Lifecycle events**: Matchers are **Exact Strings**. (for example,
|
||||
`"startup"`).
|
||||
- **Wildcards**: `"*"` or `""` (empty string) matches all occurrences.
|
||||
|
||||
## Configuration
|
||||
@@ -137,6 +138,7 @@ multiple layers in the following order of precedence (highest to lowest):
|
||||
Hooks are executed with a sanitized environment.
|
||||
|
||||
- `GEMINI_PROJECT_DIR`: The absolute path to the project root.
|
||||
- `GEMINI_PLANS_DIR`: The absolute path to the plans directory.
|
||||
- `GEMINI_SESSION_ID`: The unique ID for the current session.
|
||||
- `GEMINI_CWD`: The current working directory.
|
||||
- `CLAUDE_PROJECT_DIR`: (Alias) Provided for compatibility.
|
||||
@@ -151,11 +153,11 @@ Hooks are executed with a sanitized environment.
|
||||
|
||||
**Project-level hooks** are particularly risky when opening untrusted projects.
|
||||
Gemini CLI **fingerprints** project hooks. If a hook's name or command changes
|
||||
(e.g., via `git pull`), it is treated as a **new, untrusted hook** and you will
|
||||
be warned before it executes.
|
||||
(for example, via `git pull`), it is treated as a **new, untrusted hook** and
|
||||
you will be warned before it executes.
|
||||
|
||||
See [Security Considerations](../hooks/best-practices#using-hooks-securely) for
|
||||
a detailed threat model.
|
||||
See [Security Considerations](../hooks/best-practices.md#using-hooks-securely)
|
||||
for a detailed threat model.
|
||||
|
||||
## Managing hooks
|
||||
|
||||
|
||||
+10
-10
@@ -20,8 +20,8 @@ including JSON schemas and API details.
|
||||
|
||||
## Configuration schema
|
||||
|
||||
Hooks are defined in `settings.json` within the `hooks` object. Each event
|
||||
(e.g., `BeforeTool`) contains an array of **hook definitions**.
|
||||
Hooks are defined in `settings.json` within the `hooks` object. Each event (for
|
||||
example, `BeforeTool`) contains an array of **hook definitions**.
|
||||
|
||||
### Hook definition
|
||||
|
||||
@@ -52,7 +52,7 @@ All hooks receive these common fields via `stdin`:
|
||||
"session_id": string, // Unique ID for the current session
|
||||
"transcript_path": string, // Absolute path to session transcript JSON
|
||||
"cwd": string, // Current working directory
|
||||
"hook_event_name": string, // The firing event (e.g. "BeforeTool")
|
||||
"hook_event_name": string, // The firing event (for example "BeforeTool")
|
||||
"timestamp": string // ISO 8601 execution time
|
||||
}
|
||||
```
|
||||
@@ -81,12 +81,12 @@ Most hooks support these fields in their `stdout` JSON:
|
||||
For `BeforeTool` and `AfterTool` events, the `matcher` field in your settings is
|
||||
compared against the name of the tool being executed.
|
||||
|
||||
- **Built-in Tools**: You can match any built-in tool (e.g., `read_file`,
|
||||
- **Built-in Tools**: You can match any built-in tool (for example, `read_file`,
|
||||
`run_shell_command`). See the [Tools Reference](../reference/tools) for a full
|
||||
list of available tool names.
|
||||
- **MCP Tools**: Tools from MCP servers follow the naming pattern
|
||||
`mcp_<server_name>_<tool_name>`.
|
||||
- **Regex Support**: Matchers support regular expressions (e.g.,
|
||||
- **Regex Support**: Matchers support regular expressions (for example,
|
||||
`matcher: "read_.*"` matches all file reading tools).
|
||||
|
||||
### `BeforeTool`
|
||||
@@ -194,7 +194,7 @@ request format.
|
||||
(generation params).
|
||||
- **Relevant Output Fields**:
|
||||
- `hookSpecificOutput.llm_request`: An object that **overrides** parts of the
|
||||
outgoing request (e.g., changing models or temperature).
|
||||
outgoing request (for example, changing models or temperature).
|
||||
- `hookSpecificOutput.llm_response`: A **Synthetic Response** object. If
|
||||
provided, the CLI skips the LLM call entirely and uses this as the response.
|
||||
- `decision`: Set to `"deny"` to block the request and abort the turn.
|
||||
@@ -271,14 +271,14 @@ telemetry.
|
||||
|
||||
### `Notification`
|
||||
|
||||
Fires when the CLI emits a system alert (e.g., Tool Permissions). Used for
|
||||
external logging or cross-platform alerts.
|
||||
Fires when the CLI emits a system alert (for example, Tool Permissions). Used
|
||||
for external logging or cross-platform alerts.
|
||||
|
||||
- **Input Fields**:
|
||||
- `notification_type`: (`"ToolPermission"`)
|
||||
- `message`: Summary of the alert.
|
||||
- `details`: JSON object with alert-specific metadata (e.g., tool name, file
|
||||
path).
|
||||
- `details`: JSON object with alert-specific metadata (for example, tool name,
|
||||
file path).
|
||||
- **Relevant Output Fields**:
|
||||
- `systemMessage`: Displayed alongside the system alert.
|
||||
- **Observability Only**: This hook **cannot** block alerts or grant permissions
|
||||
|
||||
@@ -20,9 +20,9 @@ Protocol (MCP)**.
|
||||
|
||||
- **Protocol:** The server must be a valid MCP server. We recommend using an
|
||||
existing MCP SDK for your language of choice if available.
|
||||
- **Endpoint:** The server should expose a single endpoint (e.g., `/mcp`) for
|
||||
all MCP communication.
|
||||
- **Port:** The server **MUST** listen on a dynamically assigned port (i.e.,
|
||||
- **Endpoint:** The server should expose a single endpoint (for example, `/mcp`)
|
||||
for all MCP communication.
|
||||
- **Port:** The server **MUST** listen on a dynamically assigned port (that is,
|
||||
listen on port `0`).
|
||||
|
||||
### 2. Discovery mechanism: The port file
|
||||
@@ -68,15 +68,15 @@ creating a "discovery file."
|
||||
The CLI will include this token in an `Authorization: Bearer <token>` header
|
||||
on all requests.
|
||||
- `ideInfo` (object, required): Information about the IDE.
|
||||
- `name` (string, required): A short, lowercase identifier for the IDE
|
||||
(e.g., `vscode`, `jetbrains`).
|
||||
- `displayName` (string, required): A user-friendly name for the IDE (e.g.,
|
||||
`VS Code`, `JetBrains IDE`).
|
||||
- `name` (string, required): A short, lowercase identifier for the IDE (for
|
||||
example, `vscode`, `jetbrains`).
|
||||
- `displayName` (string, required): A user-friendly name for the IDE (for
|
||||
example, `VS Code`, `JetBrains IDE`).
|
||||
|
||||
- **Authentication:** To secure the connection, the plugin **MUST** generate a
|
||||
unique, secret token and include it in the discovery file. The CLI will then
|
||||
include this token in the `Authorization` header for all requests to the MCP
|
||||
server (e.g., `Authorization: Bearer a-very-secret-token`). Your server
|
||||
server (for example, `Authorization: Bearer a-very-secret-token`). Your server
|
||||
**MUST** validate this token on every request and reject any that are
|
||||
unauthorized.
|
||||
- **Tie-breaking with environment variables (recommended):** For the most
|
||||
@@ -135,7 +135,7 @@ to the CLI whenever the user's context changes.
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> The `openFiles` list should only include files that exist on disk.
|
||||
> Virtual files (e.g., unsaved files without a path, editor settings pages)
|
||||
> Virtual files (for example, unsaved files without a path, editor settings pages)
|
||||
> **MUST** be excluded.
|
||||
|
||||
### How the CLI uses this context
|
||||
@@ -188,7 +188,7 @@ The plugin **MUST** register an `openDiff` tool on its MCP server.
|
||||
`CallToolResult` to acknowledge the request and report whether the diff view
|
||||
was successfully opened.
|
||||
- On Success: If the diff view was opened successfully, the response **MUST**
|
||||
contain empty content (i.e., `content: []`).
|
||||
contain empty content (that is, `content: []`).
|
||||
- On Failure: If an error prevented the diff view from opening, the response
|
||||
**MUST** have `isError: true` and include a `TextContent` block in the
|
||||
`content` array describing the error.
|
||||
@@ -223,9 +223,9 @@ The plugin **MUST** register a `closeDiff` tool on its MCP server.
|
||||
|
||||
### `ide/diffAccepted` notification
|
||||
|
||||
When the user accepts the changes in a diff view (e.g., by clicking an "Apply"
|
||||
or "Save" button), the plugin **MUST** send an `ide/diffAccepted` notification
|
||||
to the CLI.
|
||||
When the user accepts the changes in a diff view (for example, by clicking an
|
||||
"Apply" or "Save" button), the plugin **MUST** send an `ide/diffAccepted`
|
||||
notification to the CLI.
|
||||
|
||||
- **Payload:** The notification parameters **MUST** include the file path and
|
||||
the final content of the file. The content may differ from the original
|
||||
@@ -242,7 +242,7 @@ to the CLI.
|
||||
|
||||
### `ide/diffRejected` notification
|
||||
|
||||
When the user rejects the changes (e.g., by closing the diff view without
|
||||
When the user rejects the changes (for example, by closing the diff view without
|
||||
accepting), the plugin **MUST** send an `ide/diffRejected` notification to the
|
||||
CLI.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user