# Headless 模式 · 同一个 agent，脱掉 TUI

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

- 作者：David（道雾轩）
- 专栏：Grok Build 源码解读（https://daiw.org/manual/grok-build.md）
- 最后更新：2026-09-15
- 原文：https://daiw.org/manual/grok-build/headless
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# Headless 模式 · 同一个 agent，脱掉 TUI

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

## 「TUI 减去渲染」

最值得记的一点：headless **不是另一条 agent 路径**。它复用和 [TUI](https://daiw.org/manual/grok-build/tui-architecture) **完全相同**的会话启动 SSOT(`session_startup.rs`)和**同一个 [SessionActor](https://daiw.org/manual/grok-build/agent-loop)**，只是不套 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`(见[认证章](https://daiw.org/manual/grok-build/auth-config))、或缓存凭据。`GROK_HOME` 可换配置目录；`~/.grok` 只读时持久化**静默变临时**。
- **stdin 不进 prompt**：必须用 `$(...)` 或 `--prompt-file`——一个容易踩的点。
- 还有 `--max-turns`、`--json-schema`(结构化输出)、`--tools`/`--disallowed-tools`(内置工具白/黑名单)这些 headless 专用 flag。写作时还在的 `--self-verify`、`--best-of-n` 已从 CLI 删掉。

<Callout type="info">
  headless 和 TUI 共用会话启动与内核，意味着**行为一致**：你在 CI 里 `grok -p` 跑出来的东西，和你在终端里手跑是同一套逻辑，连 resume、fork、compaction 都通用。「一套内核，多种前端(TUI/headless/[ACP](https://daiw.org/manual/grok-build/acp))」是这一部分反复出现的主题。
</Callout>

## 和《从 LLM 到 Coding Agent》对照

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

---

上一篇：[Plan mode](https://daiw.org/manual/grok-build/plan-mode) · 下一篇：[ACP · 编辑器后端](https://daiw.org/manual/grok-build/acp)
