Gemini CLI 任务规划实战:用 write_todos 让复杂任务按步骤落地并全程可追踪
Gemini CLI 内置的 task planning(任务规划)机制,让你在提出复杂任务前就能预览 Agent 的执行计划,并在执行过程中实时跟踪每一步状态。读完本文,你将掌握如何显式请求规划、审阅并迭代计划、执行计划、用 Ctrl+T 查看完整待办清单,以及处理计划中途变更;同时会理解底层 write_todos 工具的参数结构、校验规则与 UI 渲染链路,做到“既会用,又懂原理”。
前置条件
开始之前,请确保:
- 已安装并完成认证(authentication)的 Gemini CLI;
- 你手里有一个足够复杂的任务,例如多文件重构或一个全新特性——规划机制对这类任务的价值最大。
为什么需要任务规划?
标准 LLM 的上下文窗口有限,在连续十余轮代码生成之后,Agent 可能“忘记”最初的总体目标。任务规划用一份结构化的 todo 清单来解决这个问题,它提供三方面收益:
- 可见性(Visibility):在 Agent 动手之前,你就能精确看到它打算做什么;
- 聚焦(Focus):Agent 始终清楚当前正在执行哪一步;
- 韧性(Resilience):当 Agent 中途卡住时,计划可以帮助它回到正轨。
如何请求生成计划
最可靠的方式是显式要求规划。推荐提示词:
I want to migrate this project from JavaScript to TypeScript. Please make a plan first.
Gemini 会先分析你的代码库,然后调用 write_todos 工具生成一份结构化清单。例如针对上述迁移任务,典型计划是:
- [ ] Create
tsconfig.json. - [ ] Rename
.jsfiles to.ts. - [ ] Fix type errors in
utils.js. - [ ] Fix type errors in
server.js. - [ ] Verify build passes.
从源码看,write_todos 执行时会将清单渲染为带序号与状态的文本回传给模型,格式为 1. [status] description(见 write-todos.ts 中 execute 的 todoListString 拼接逻辑),因此模型在后续轮次里“看到”的正是这种带状态的列表,这也是它能持续跟踪进度的原因。
如何审阅并迭代计划
计划生成后会显示在 CLI 中,先审阅再放行:
- 有遗漏步骤? 直接指出,例如:“You forgot to add a step for installing
@types/node.” - 顺序不对? 例如:“Let's verify the build after each file, not just at the end.”
Agent 会动态更新 todo 清单,而不是从头重做。这一机制的关键在于:write_todos 每次传入的是完整清单,会整体覆盖旧列表(write-todos.ts 中 WriteTodosToolParams.todos 的注释明确写着 “This will overwrite any existing list”)。因此“迭代”在实现上就是模型重写整份带最新状态的清单。
如何执行计划
审阅通过后,提示 Agent 开始即可:
Looks good. Start with the first step.
执行过程中,你会看到输入框上方的 todo 清单实时更新:
- 当前焦点:正在进行中的任务会被高亮,例如
[IN_PROGRESS] Create tsconfig.json; - 进度:已完成的步骤会被标记为 done。
如何用 Ctrl+T 监控完整进度
在长任务中,完整 todo 列表可能被收起以节省屏幕空间。随时按下 Ctrl+T 可以切换完整视图,显示包括 pending、in-progress、completed 在内的所有条目——这是不用往上翻历史就能回答“还剩多少没做?”的好办法。
这一快捷键在源码中的链路非常清晰:
- 键位定义:keyBindings.ts 将
ctrl+t绑定到Command.SHOW_FULL_TODOS,命令说明为 “Toggle the full TODO list.”; - UI 状态:
showFullTodos是 AppContainer.tsx 中的状态变量,切换后注入 UIStateContext; - 渲染:Todo.tsx 中的
TodoTray将uiState.showFullTodos传给Checklist的isExpanded,并展示 “Ctrl+T to toggle” 提示。
从 UI 实现看,TodoTray 会从历史末尾向前扫描,取最近一次输出了 todos 的工具结果(例如 write_todos 的调用)作为当前清单(Todo.tsx)。这意味着多次调用 write_todos 后,界面永远只展示最新那份清单,与“整表覆盖”的语义一致。
如何处理计划中的意外变更
计划会变——比如做到一半发现某个库不兼容。此时只需说明:
Actually, let's skip the 'server.js' refactor for now. It's too risky.
Agent 会把该任务标记为 cancelled 或直接移除,然后继续下一项。这种动态调整正是 todo 系统的价值所在——它是一份“活文档”(living document),而不是一块静态文本。
write_todos 的状态机与校验规则
todo 条目支持 5 种状态:pending、in_progress、completed、cancelled、blocked。这一约束由工具实现层强制执行,从源码看:
- 合法状态常量定义在 write-todos.ts 的
TODO_STATUSES; validateToolParamValues会逐条校验:todos必须是数组、每项description必须是非空字符串、状态必须落在上述枚举内;- 排他性约束:同一时刻最多只能有一个任务处于
in_progress,否则直接返回错误 “Only one task can be 'in_progress' at a time.”(write-todos.ts)。这与工具参考文档 todos.md 中 “Only one task can be markedin_progressat any time” 的说明一致。
参数层面的技术规格(来自 todos.md):
| 参数 | 类型 | 说明 |
|---|---|---|
todos |
object 数组,必填 | 完整任务列表,整体覆盖现有清单 |
todos[].description |
string | 任务描述 |
todos[].status |
enum | pending / in_progress / completed / cancelled / blocked |
其他技术行为要点:
- 界面:更新位于 CLI 输入提示符上方的进度指示器;
- 排他性:任意时刻仅一个任务可为
in_progress; - 持久化:todo 状态仅限当前会话(session 作用域),清空会话或重新开始时不再保留。
工具名与声明的注册位置可追溯到 base-declarations.ts 中的 WRITE_TODOS_TOOL_NAME = 'write_todos',工具在不同模型族下有各自的 schema 变体(如 default-legacy.ts 与 gemini-3.ts),由 getSchema 按 modelId 动态解析。其调用与校验行为有对应测试覆盖,见 write-todos.test.ts。
典型工作流小结
- 请求规划:在提示词末尾加 “Please make a plan first.”;
- 审阅迭代:用自然语言指出遗漏或顺序问题,让 Agent 重写清单;
- 放行执行:“Looks good. Start with the first step.”;
- 跟踪进度:默认查看输入框上方摘要,Ctrl+T 展开完整清单;
- 应对变更:中途调整需求时直接说明,任务会被标记
cancelled或移除。
下一步
- 了解 Session management:保存当前计划,明天继续执行;
- 查阅 Todo 工具参考:
write_todos的完整技术规格; - 学习 Memory management:持久化规划偏好,例如 “Always create a test plan first”。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00