Headless 模式 · 同一个 agent,脱掉 TUI

grok -p 让同一个 agent 内核脱掉终端界面,在脚本和 CI 里跑。这一章看 headless 怎么复用 TUI 那套会话启动与 SessionActor(「TUI 减去渲染」)、四种输出格式,以及给 CI 的退出码与鉴权。

作者 David更新于 第 51 篇(共 60 篇)

Headless 模式 · 同一个 agent,脱掉 TUI

grok -p "修一下这个 bug" 让同一个 agent 在没有界面的情况下跑一轮——脚本、CI、管道。核心在 headless.rs。

「TUI 减去渲染」

最值得记的一点:headless 不是另一条 agent 路径。它复用和 TUI 完全相同的会话启动 SSOT(session_startup.rs)和同一个 SessionActor,只是不套 ratatui。run_single_turn 用 spawn_grok_shell 在进程内拉起 agent、开一条 ACP 通道,走一遍 initialize(由 build_headless_init_request 构造:clientType 取 HEADLESS_CLIENT_TYPE,值是 "grok-shell";startupHints{nonInteractive, skipGitStatus, skipProjectLayout}——省掉界面才需要的东西)→ 开/恢复会话 → prompt → 流式收尾。同一个大脑,脱掉一层皮。

四种输出格式

--output-format(headless/cli.rs 里的 OutputFormat):

  • plain(默认):文本到 stdout,错误和进度到 stderr——保证 stdout 干净,好被管道消费。
  • json:跑完输出一个对象,含 text、stopReason(snake_case,如 end_turn)、sessionId、usage(各类 token)、total_cost_usd(不完整时连同各模型的 cost 一起省略,不给你半个数)。
  • streaming-json:NDJSON 事件流,按 type 分派:除了 text/thought/end/error,现在还有 tool_call、tool_call_update、每次模型响应一行的 usage、plan 等,end 总在最后。
  • streaming-messages-json(写作之后新增):按 Messages API 的 stream-json 线格式输出(system/init → assistant/user → result),加 --include-partial-messages 还能拿到原始流事件;缺数据的用量字段回落为 0,宁少报、不多报。

给 CI 的细节

  • 退出码:0 成功 / 1 出错 / 130 SIGINT / 143 SIGTERM。收到信号时状态存到最后一次完成的工具调用,但文件改动不回滚——resume 可续。
  • 鉴权:XAI_API_KEY、grok login --device-auth(见认证章)、或缓存凭据。GROK_HOME 可换配置目录;~/.grok 只读时持久化静默变临时。
  • stdin 不进 prompt:必须用 $(...) 或 --prompt-file——一个容易踩的点。
  • 还有 --max-turns、--json-schema(结构化输出)、--tools/--disallowed-tools(内置工具白/黑名单)这些 headless 专用 flag。写作时还在的 --self-verify、--best-of-n 已从 CLI 删掉。

headless 和 TUI 共用会话启动与内核,意味着行为一致:你在 CI 里 grok -p 跑出来的东西,和你在终端里手跑是同一套逻辑,连 resume、fork、compaction 都通用。「一套内核,多种前端(TUI/headless/ACP)」是这一部分反复出现的主题。

和《从 LLM 到 Coding Agent》对照

对照 Claude Code 的 headless(-p):两者思路一致——把交互式 agent 变成可脚本化的一次性调用。grok 的实现干净在「TUI 减去渲染」:不复制逻辑,只抽掉渲染层。下一章看它怎么当编辑器后端(ACP)。


上一篇:Plan mode · 下一篇:ACP · 编辑器后端

本页目录