第 2 篇 核心 · 第 6 章
Plan Mode 與 todo 拆任務
複雜任務不要一開始就讓 Gemini 改檔。先請它規劃、列 todo、讓你審過方向,再分步執行與驗收,才是穩定使用 CLI agent 的基本功。
Plan Mode 與 model steering 仍屬快速演進區
官方文件把 Plan Mode 搭配 model steering 的教學標為 experimental,且可能需要在 /settings 啟用。請以你本機 /help、/settings 與官方文件為準。
6.1 什麼時候需要先規劃
只要任務會動到多個檔案、需要理解架構、可能影響資料或安全,就先規劃。常見例子:
- 把 JavaScript 專案逐步改成 TypeScript。
- 重構登入流程、權限檢查或付款流程。
- 新增一個跨前後端的功能。
- 修一個你還不確定根因的 bug。
我想把這個專案的錯誤處理統一。請先讀 @src/ 和 @package.json,列一份計畫與 todo。先不要改檔。
6.2 用 /plan 進入規劃語境
Gemini CLI 官方文件列出四種進入 Plan Mode 的方式,不是只有打 /plan 這一種官方。習慣的操作方式不同,適合的入口也不一樣:臨時想切一下,快捷鍵最快;每次都想先規劃,直接改設定一次到位。
進入 Plan Mode 的四種方式
| 方式 | 怎麼做 | 備註 |
|---|---|---|
| 指令列旗標 | gemini --approval-mode=plan | 啟動當下就直接進入 Plan Mode。 |
| 斜線指令 | /plan 或 /plan <目標> | 目標可以省略;接著打目標會直接送出那句需求,省一次來回。 |
| 快捷鍵循環 | Shift+Tab | 在 Default → Auto-Edit → Plan 三種模式間循環切換。 |
| 自然語言 | 直接說「幫我先規劃 xxx,不要動手改」 | 會觸發內部的 enter_plan_mode 工具;YOLO 模式下這條路不可用。 |
如果你幾乎每次都想先進 Plan Mode,不想每次手動切,可以在 /settings 裡把 Default Approval Mode 設成 Plan,之後啟動就直接是唯讀模式。上面的命令、按鍵組合與 UI 標籤,仍以你本機 /help、/settings 與官方文件當下顯示的為準——這塊隨版本調整的機率不低。
/plan
我想新增一個匯出 CSV 的功能。請先研究目前資料流、列出修改檔案、風險與驗收方式。
/plan 我想把這個專案從 npm scripts 改成 pnpm scripts,請先做遷移計畫,不要改檔。
好計畫通常包含:目標、已知脈絡、預計修改檔案、步驟順序、風險、驗收指令、需要你回答的問題。
退出 Plan Mode:三種收尾方式
最常見的收尾是核准最終計畫——一按下核准,Gemini 會自動退出 Plan Mode 並直接照計畫開始實作,中間不會再另外問你一次要不要離開規劃模式。規劃到一半改變主意,也可以隨時按 Shift+Tab 切走,或直接說「exit plan mode」「stop planning」讓它退出,不必等計畫寫完。
權限核准不是雙向對等的
在 Default 或 Auto-Edit 模式下核准過的工具權限,進 Plan Mode 之後不會沿用,該問的還是會重問一次;反過來,你在 Plan Mode 裡核准的權限,退出後會全域套用到其他模式。這種不對稱是刻意的安全設計,第一次遇到「怎麼又要重問一次同一個工具」不必懷疑是設定壞了。
6.3 todo 讓長任務有進度感
官方 task planning 教學說,明確要求 Gemini 先做 plan 時,它會使用 todo 工具產生結構化清單,執行時也會更新目前進度。你要看的不是「它很忙」,而是「它現在正在做哪一項」。
| todo 狀態 | 你要確認什麼 |
|---|---|
| Pending | 後續步驟是否完整,是否有多餘或危險步驟。 |
| In progress | 目前焦點是否符合你剛才批准的計畫。 |
| Completed | 完成是否有證據,例如測試輸出、diff 或檔案檢查。 |
長任務中 todo 可能被折疊;官方教學列出 Ctrl+T 可切換完整 todo 檢視。若你的版本快捷鍵不同,以本機 shortcut help 為準。
todo 背後的資料結構:一次只能有一項在進行
Gemini 產生 todo 清單時,背後呼叫的是一個叫 write_todos 的工具,參數只有一個陣列,每一項固定兩個欄位:
| 欄位 | 型別 | 說明 |
|---|---|---|
description | 字串 | 這一項任務的技術性描述,通常是一句可執行的動作。 |
status | 列舉 | pending / in_progress / completed / cancelled / blocked 五選一。 |
官方訂了一條硬性規則:同一時間只能有一項任務是 in_progress。這逼著 Gemini 一次只專心做一件事,你也比較容易對照「它現在在做的」跟「你剛才核准的範圍」是不是同一件事。中途想跳過某一步,不必手動改資料,直接用自然語言說「先跳過 xxx,風險太高」,Gemini 會自動把那一項標成 cancelled 再接續下一項。
todo 不會跨 session 記住
關掉這次對話,todo 清單就沒了
官方文件明寫 todo 狀態是 session-scoped:只活在目前這個對話的記憶體裡,不會存成檔案,也不會留到下次啟動官方。這是目前設計上的已知限制,不是 bug——社群端也有回報反映舊機制的代價:每一輪都得把完整歷史重新塞回 prompt 才能保住進度,既耗 token,session 一重開又整個忘光社群。跨天才能做完的大型任務,實務上更穩的做法是靠 session 的存檔/resume 機制延續到隔天,而不是每天開新對話重講一次。
進階:實驗性的 tracker_* 任務追蹤工具
任務之間有明確相依順序(例如「B 一定要等 A 做完才能開始」)時,官方另外在開發一組更完整的追蹤工具,目前標記研究預覽:tracker_create_task、tracker_update_task、tracker_list_tasks、tracker_add_dependency 等。任務分 epic/task/bug 三種類型,狀態有 open/in_progress/blocked/closed,可以用 tracker_add_dependency 建相依關係圖,Gemini 會依拓樸順序強制解鎖,不會讓後面的任務搶在前面之前開跑。啟用要在 settings.json 加 experimental.taskTracker: true 並重啟 CLI。它的狀態存在 .gemini/tmp/tracker/<session-id>——路徑看起來像持久化,但本質上仍是 per-session,跟前面 todo 的限制是同一個坑,只是換了包裝,並沒有真的解決「隔天接續」的問題。
6.4 審計畫:在它改檔前把方向拉正
看到計畫後,不要只回「OK」。你應該像 code review 一樣審它:
- 步驟是否太大?請它拆小。
- 有沒有先寫或更新測試?
- 有沒有碰到不該碰的資料夾?
- 驗收方式是否可執行?
- 它是否需要你補規格或權限資訊?
這份計畫先不要執行。請修改:
1. 每一步最多只改一到兩個檔案。
2. 先加測試或最小驗收案例。
3. 不要碰 legacy/ 和 generated/。
4. 每完成一步都停下來回報 diff 摘要。
計畫太長,改用外部編輯器修
步驟一多,在對話框裡一條一條口頭描述修改很累。按 Ctrl+X 可以把目前的計畫直接開到你熟悉的外部編輯器,用打字或註解直接改,存檔後 Gemini 會自動偵測差異、重新對齊後續策略,比整段重新口述快。已核准的計畫想留底或貼給別人看,/plan copy 可以直接把它複製到剪貼簿。
6.5 planning 中的 model steering
官方 Plan Mode steering 教學示範:當 Gemini 正在研究或草擬計畫時,你可以即時補充提示,讓它不要往錯方向挖。這類能力可能需要設定啟用,也可能因版本而變。
補充:請記得看 packages/common/queue,Redis 設定在那裡,不在 app/config。
steering 的重點是短、具體、可行:指出路徑、限制、架構選擇或錯誤假設。例如提醒它「這個專案的認證是套 Auth.js,不是自己刻的,規劃時可以省略自訂 middleware 那一步」,比等它規劃完才發現方向整個錯了划算。不要在它已經執行到一半時突然改整個需求。
6.6 什麼時候離開規劃並執行
當計畫滿足三個條件,才讓 Gemini 開始改檔:你看得懂每一步、你接受修改範圍、你知道怎麼驗收。批准時要明確限定第一步或下一步。
計畫可以。請只執行第 1 步:新增最小測試案例。完成後停下來,列出改了哪些檔案與如何跑測試。
不要一次批准整個大型計畫。分段執行能降低偏航成本,也讓你更容易用 Git diff、測試與人工 review 把關。
好 prompt 的固定句型
「先計畫,不改檔」用於探索;「只做第 N 步,完成後停下」用於執行;「列 diff 摘要與驗收指令」用於收尾。這三句可以反覆套用。
headless/CI 模式:沒人在場按核准時會發生什麼事
退出 Plan Mode 後預設會自動開始執行
非互動(headless/CI)模式下,enter_plan_mode 與 exit_plan_mode 都會自動核准,不會跳出互動確認;更重要的是,退出 Plan Mode 之後會自動切換成 YOLO 模式,接著把計畫直接付諸實作官方。如果你在腳本裡跑 Plan Mode 只是想拿一份唯讀分析報告,沒設好防護就可能在自己沒注意的情況下被真的動手改檔。
gemini --approval-mode plan -p "分析目前的 telemetry 並提出改善建議"
想在這種情境下安全地只拿到分析結果,除了在 prompt 裡明講「只要計畫、不要核准執行」,更保險的做法是額外寫一條 policy 規則把 exit_plan_mode 的非互動自動核准擋掉。怎麼寫這條規則,6.7 節會示範。
6.7 Plan Mode 到底鎖住了什麼:policy engine 速覽
Plan Mode 的唯讀限制不是寫死在程式邏輯裡的 if/else,而是由一套叫 policy engine 的規則引擎在背後判斷每一次工具呼叫該放行還是擋下官方。知道這件事的好處是:遇到「為什麼這個工具在 Plan Mode 可以用、那個不行」的疑問,答案永遠是查規則而不是猜行為;想客製化時,也不用等官方改程式,自己疊一層規則就好。
唯讀工具白名單,還有一個例外
官方文件列出 Plan Mode 允許呼叫的工具:read_file、list_directory、glob、grep_search、google_web_search、get_internal_docs,內建的兩個研究型 subagent codebase_investigator 與 cli_help,還有 ask_user、唯讀的 MCP 工具與資源工具,以及 activate_skill。你自訂的 subagent 預設不在名單裡——只有這兩個內建 subagent 被官方白名單放行,其他自訂 subagent 要在 Plan Mode 裡能用,得自己另外寫規則授權。寫入類工具只有一個例外:write_file 和 replace 可以用,但只能拿來把計畫存成計畫目錄底下的 .md 檔,碰原始碼一律被擋。
web_fetch 不是自動放行
google_web_search 能直接用,但 web_fetch 即使在 Plan Mode 裡仍然需要你額外確認一次才會執行——它跟 ask_user、activate_skill 歸在同一條「問使用者」規則,不是自動 allow。第一次看到它卡住跳出確認,不代表出了 bug,是設計上刻意留的一道關卡。
想知道原理:官方 plan.toml 長什麼樣子?
Plan Mode 的核心規則放在官方原始碼一個叫 plan.toml 的檔案裡,運作邏輯是「先用一條萬用規則擋光所有工具,再用比較高的 priority 選擇性放行」。精簡後大致長這樣:
[[rule]]
toolName = "*"
decision = "deny"
priority = 40
modes = ["plan"]
denyMessage = "You are in Plan Mode with access to read-only tools. Execution of scripts (including those from skills) is blocked."
[[rule]]
toolName = ["write_file", "replace"]
decision = "deny"
priority = 65
modes = ["plan"]
denyMessage = "You are in Plan Mode and cannot modify source code. You may ONLY use write_file or replace to save plans to the designated plans directory as .md files."
第一條規則(priority 40)先把所有工具通通擋掉;唯讀工具清單再靠另一條較高 priority 的規則明確放行,數字愈大愈晚判定,也就愈優先生效。第二條規則(priority 65)專門盯 write_file 和 replace,把它們的使用範圍收窄到只剩存計畫這一件事。不需要背熟這份檔案,但知道「擋光再選擇性開」這個骨架,之後看到任何工具在 Plan Mode 的行為,都能照這個邏輯推理。
計畫檔放在哪裡、要不要自動換模型
計畫檔預設存在 ~/.gemini/tmp/<project-hash>/<session-id>/plans/*.md,按專案跟 session 分開放。想換位置,在 settings.json 指定 general.plan.directory;自訂路徑限制在專案根目錄之內,而且光改設定不夠,還得自己另外寫一條 policy 規則授權該路徑可寫,不然一樣會被前面那條 priority 65 的規則擋下。
另外 Plan Mode 預設會自動切換模型:規劃階段用推理能力比較強的模型把計畫想清楚,核准進入實作階段後就自動換成回應更快的輕量模型逐項執行官方。官方部落格點名過具體用哪個模型規劃、哪個執行,但型號迭代速度很快,這裡刻意不寫死——實際對應以你當下的官方頁面或 gemini --help 為準。不想要這個自動切換,設 general.plan.modelRouting: false 就能關掉。
進階:自己寫規則客製化 Plan Mode
不想動官方內建的 plan.toml,可以在 ~/.gemini/policies/*.toml 疊加自己的規則。規則生效順序由五層 tier 決定:Default(官方內建)=1、Extension=2、Workspace=3、User=4、Admin=5,換算成最終優先度的公式是 final_priority = tier_base + (toml_priority / 1000)。toml_priority 除以 1000 後最多只貢獻不到 1 的差距,所以只是同一層內自己人比大小,永遠蓋不過高一層的 tier——你自己寫在 ~/.gemini/policies/ 底下的規則屬於 User 層,不用刻意把數字設很大,天然就穩贏官方內建的 Default 層。舉例,想在 Plan Mode 裡讓 git status、git diff 這類唯讀指令免確認直接跑:
[[rule]]
toolName = "run_shell_command"
commandPrefix = ["git status", "git diff"]
decision = "allow"
priority = 100
modes = ["plan"]
接了不少唯讀 MCP 工具、不想一個個列名字,也可以用萬用規則一次放行所有標了 readOnlyHint 的工具:
[[rule]]
toolName = "*"
mcpName = "*"
toolAnnotations = { readOnlyHint = true }
decision = "allow"
priority = 100
modes = ["plan"]
這正是 6.6 節提到「擋掉 headless 情境下 exit_plan_mode 自動核准」的同一套機制——把 decision 換成 deny 或 ask_user、toolName 換成 exit_plan_mode,優先度設得比預設規則高,就能在腳本情境下強制留住人工核准這一關。
6.8 常見卡關與排除法
Plan Mode 與 todo 都還在快速迭代,社群回報的問題不少帶著官方 issue 編號,代表已經有人正式追蹤。下面整理幾個比較可能撞到、而且有具體排除法的狀況;版本細節變動快,實際行為仍以你當下的 CLI 版本與官方 issue 追蹤狀態為準。
| 症狀 | 常見原因 | 處理 |
|---|---|---|
Shift+Tab 切換模式沒反應(Windows Terminal 尤其常見) | 終端機送出的跳脫序列跟 CLI 預期的不一樣,通常與 Node.js 版本有關;社群已有多起回報(issue #20417、#24562、#25584)。 | 先把 Node.js 與 Gemini CLI 都升到最新版,不少人回報升級後就解決;仍無效就在 ~/.gemini/keybindings.json 把 CYCLE_APPROVAL_MODE 另外綁一個不衝突的鍵;或改在 WSL 裡跑。 |
--yolo 全自動模式跑到一半,遇到 todo 就卡住不動 | 已知問題(issue #16496),write_todos 與非互動流程搭配時特別容易卡。 | 手動連按兩次以上「Continue」通常能恢復;腳本/CI 情境回報時附上這個前提比較好追。 |
| 請它建 todo 卻一直重試、迴圈跳不出來 | 已知問題(issue #13164、#12808),根因未定;有回報者懷疑同時開多個分頁動同一批相關專案是誘因之一。 | 目前沒有官方根治法,手動 Ctrl+C 中斷、重開一個新 session 是唯一實務解法。 |
| 明講「先只做調查,不要動手改」,它卻跳過規劃、直接給一份太簡略的修復計畫 | Plan Mode 目前調校偏向「動手前先規劃」,對本身就是唯讀性質的診斷任務比較不擅長(issue #21200)。 | 別丟一句籠統要求,改用明確、逐步拆解的指令引導,例如先列要檢查哪幾個檔案,再列要比對哪些症狀。 |
| 進 Plan Mode 後卡在「思考中」,遲遲沒有輸出 | 官方難以只靠這個現象分診,通常是回報資訊不夠完整(issue #25438)。 | 卡住時先跑 /about 把版本與登入方式記下來,附在回報裡再送出。 |
| 換成 Gemini 3 系列模型後 todo 工具整個不能用,切回 2.5 也沒恢復 | todo 功能是否可用,目前跟當下選用的模型版本綁定(issue #16275)。 | 重開一個新 session;模型與功能的對應關係變動快,以官方當下說明為準。 |
自動化掛的 hook 沒反應,先確認觸發路徑對不對
在 enter_plan_mode/exit_plan_mode 上掛的 BeforeTool/AfterTool hook,只在這兩個工具「被呼叫」時才會觸發。直接按 Shift+Tab 或打 /plan 手動切模式,並不會經過這兩個工具的呼叫路徑,掛在上面的 hook 自然不會跑。遇到「明明寫了自動化卻沒作用」,先確認自己是用哪種方式切模式,而不是急著懷疑 hook 壞了。
本章小結
Plan Mode 與 todo 的目的,是把複雜任務從「黑箱一次跑完」變成「先看計畫、再分步批准、持續驗收」。快速小改可以直接做;會跨檔案、跨系統或有風險的任務,先規劃是基本安全動作。搞懂背後的 policy engine 怎麼擋、todo 為什麼不會跨 session 記住、headless 模式退出後會自動接著執行,能幫你在把有風險的任務交給它之前,先把護欄立好,而不是出事後才回頭查原因。
動手試試
- 在
gemini-cli-lab內建立兩三個小檔案,模擬一個專案。 - 用
/plan請 Gemini 先規劃「新增 README 的使用說明」,要求不要改檔。 - 審計畫後,只批准第一步。
- 用
Ctrl+T或本機等價方式查看 todo 進度,再用 diff 驗收。 - 核准前先按
Ctrl+X把計畫開到外部編輯器,練習直接改一行步驟再存檔,看 Gemini 怎麼重新對齊。 - 查一下你本機
~/.gemini/底下有沒有policies/資料夾;跑一次/settings,找找 Default Approval Mode 設在哪裡。