☰
Firstmate 中的 Grok Build Harness 适配:启动、操作事实、Composer 识别与 Turn-End 守卫集成指南
2026/9/29 7:30:55 网站建设 项目流程

【免费下载链接】firstmate

Talk to one agent. Ship with a crew.

项目地址:https://gitcode.com/gh_mirrors/fi/firstmate
点击查看免费下载

Grok Build(xAI 的grokTUI)是 Firstmate 舰队中一个经过完整验证的 harness:它以 Claude-Code 兼容形态工作,被用作 crewmate/secondmate 运行时,也可作为 primary 挂载 turn-end 守卫。本文基于 .agents/skills/harness-adapters/references/harness/grok.md 整理出完整的操作事实表、启动/提交/信任门/隐私边界处理方案,并结合bin/下可执行所有者与tests/中的回归用例,解释每条规则背后的源码级依据。读完你可以按 Firstmate 的既有规范可靠地 spawn、发送、中断、恢复与验证 Grok 工作进程,并在 primary 模式下正确接线 turn-end 钩子。

一、Grok Build 的适配定位与验证基线

Grok Build 是 xAI 的grokTUI 程序,被 Firstmate 判定为Claude-Code 兼容(Claude-Code-compatible)。这意味着它的很多行为(项目设置加载、hook 机制、composer 交互)与 Claude 高度相似,但又有自己独立的差异点,因此需要单独一份 harness 参考记录。

适配器经过多轮实机验证,时间线如下:

  • 2026-06-29:验证于0.2.73
  • 2026-07-03:slash 提交验证于0.2.82
  • 2026-07-13:effort 参数验证于0.2.99
  • 2026-07-19:退出行为验证于0.2.103
  • 2026-07-28:primary 集成验证于0.2.112(同时保留对原生 pre-native0.2.73的验证)
  • 2026-09-24:文件夹信任、训练 opt-in、未发送 composer 投递验证于1.0.0/1.0.41

启动形态(launch shape)固定为:

grok --always-approve "$(cat <brief>)"

其中<brief>是任务简报文件路径,--always-approve提供无人值守的自主性。这个启动形态与 Firstmate 的bin/fm-spawn.sh对 worker 的启动约定保持一致。

该参考文件属于.agents/skills/harness-adapters/SKILL.md技能路由体系(SKILL.md),按其中给出的harness-adapter-routing-v1矩阵,grok被登记为独立 harness 条目,任何涉及 spawn、recovery、primary 集成、model/effort 选择的操作都会按需加载本参考与references/common/下的公共参考。

二、操作事实表(Operating Facts)

原文档用一张事实表固化了 Grok harness 的关键交互语义,这是任何自动化脚本(busy 判定、生命周期控制、发送)的输入依据:

FactValue
Busy state使用"最后渲染尾部回退"(last rendered-tail fallback),并隔离到 Grok 专用语义:ASCII 形式的回合中提示Ctrl+c:cancel;空闲栏中无Shift+Tab:mode │ Ctrl+.:shortcuts;绝不使用对 locale 敏感的 braille 旋转器
Exit/exit打印Resume this session with: grok --resume <session-id>;回退方式是 1000ms 内连按两次Ctrl+Q;在 VS Code 系终端中Ctrl+D退出;Ctrl+C中断
Interrupt单次Ctrl+C;Escape 只滚动 scrollback
Skill/<skill>形式,例如/no-mistakes,具备端到端的用户技能发现、调用与真实no-mistakes axi run证据;popup 可能吞掉 Enter 并填充一个参数占位符,需要真实的第二次 Enter
Autonomy--always-approve,footer 显示· always-approve,已实测无人值守可用;--permission-mode bypassPermissions是更强的等价项
Marker0.2.73的 child/tool 进程带GROK_AGENT=1且无CLAUDECODE;而1.0.0的 hook 进程带GROK_HOOK_EVENT、GROK_HOOK_NAME、GROK_SESSION_ID、GROK_WORKSPACE_ROOT却没有GROK_AGENT,因此判定身份必须看进程祖先链(ancestry)
Resumegrok --resume <session-id>;grok -c/--continue恢复 cwd 最近会话;--fork-session创建新 id
Model--model <model>;用grok models发现当前账号可用模型
Effort--reasoning-effort <low\|medium\|high>,别名--effort;0.2.99会拒绝xhigh和max,报错use one of: high, medium, low

这里的关键点在于busy 判定与 marker 都是版本演进的:旧版(0.2.73)只在 child 进程注入GROK_AGENT,新版(1.0.0)的 hook 进程改注入GROK_HOOK_*系列变量。任何"只看单一环境变量"的守卫都会在升级后失效(详见第七节)。

Effort 的兜底与非法值处理由公共参考 references/common/model-and-effort.md 拥有:若请求的 effort 超出适配器接受集合,spawn 只在任务元数据里记录effort=而不下发该 flag,从而保住启动成功而不是传入已知非法值;max永远不允许通过 fallback 选择,只有显式的 per-task 或常驻 captain 偏好才允许。

三、身份标记契约:为什么 hook marker 与 child 快路径都要管

Grok 的可靠规则必须同时覆盖两类进程:hook 进程的 marker与child 进程的快路径。两者注入的环境变量不同(GROK_AGENTvsGROK_HOOK_EVENT/GROK_HOOK_NAME/GROK_SESSION_ID/GROK_WORKSPACE_ROOT),所以"marker 命名了 harness,但结构祖先才是证明谁拥有进程树"的原则在此尤为重要——一个 marker 只是普通环境状态,可能被子进程或多路复用器保留,而祖先链才能证明进程归属。

marker 契约由 docs/turnend-guard.md 的 "Harness integrations" 一节拥有。该文档记录了这样一个真实事故:grok 1.0.0的 hook 进程不再带GROK_AGENT,一个只按GROK_AGENT键控的守卫因此停止触发,导致 Claude-only 的 auto-arm 在 Grok 下同步运行。由于 Grok 没有 Claude 的asyncRewake,它会在前台等待 watcher 长达声明的 28800 秒超时,Grok 回合永远不结束。因此:

  • 守卫必须同时接受GROK_AGENT与GROK_HOOK_EVENT两个标记;
  • 不得把守卫扩大到GROK_SESSION_ID——Grok 把它注入每个 child 进程,它可能存续到 Grok 启动的 Claude 会话里,静默禁用 Claude 自身的连续性。

四、技能调用与自主性

技能调用:使用/<skill>形式,例如/no-mistakes。验证证据链完整:技能发现(discovery)→ 调用(invocation)→ 真实的no-mistakes axi run输出证据。有一个交互陷阱:技能 popup 可能吞掉第一次 Enter 并填充一个参数占位符(如/no-mistakes的可选任务参数、/compact的 compaction 指令),此时并没有真正提交,需要补发第二次真实的 Enter。

自主性(autonomy):--always-approve是经过无人值守实测的授权方式,footer 会显示· always-approve;更强的等价项是--permission-mode bypassPermissions。两者可按部署要求选择,但都需要在 spawn 时作为具体 flag 传入(Firstmate 的bin/fm-spawn.sh只接受具体轴值,从不解析自然语言规则)。

五、提交与启动的三个真实陷阱

5.1 Slash 自动补全吞掉 Enter

斜杠自动补全可能把第一次 Enter 变成"选择 + 参数提示",并不构成提交。2026-07-03 的一次真实事故中,两个 Grok 0.2.82 的 Herdr worker 把/no-mistakes留在输入框里数分钟,而 send 却返回了成功——旧 Herdr 逻辑把任何 pane 增量都当成提交(包括 popup 关闭和占位符填充)。

修复后,Tmux 与 Herdr 的采集都经过 bin/fm-composer-lib.sh 的共享分类器,在每条"已证明内容行"上分类真实文本;边界由 docs/herdr-backend.md 拥有,回归覆盖在 tests/fm-backend-herdr.test.sh。

5.2 发送成功 ≠ 送达

2026-09-24 在 Grok 加入舰队后的首次派发中,一条指令落到了 Grok 1.0.41 的 composer 里而未发送,pane 显示Enter:send now,文本保持 pending。教训:对任何时间敏感的内容,必须 peeking pane 验证投递,而不是信任 send 的返回值——一个"静默未送达"的 hold 是最糟的消息丢失。这也呼应了公共参考 references/common/control-and-recovery.md 的原则:发送或按键返回成功不是提交的证据,必须要求工具特定的后置条件。

5.3 项目选择器与文件夹信任门

  • "Run Grok Build in a project directory?" 选择器只在项目目录之外(home、Desktop、Downloads、/tmp)出现。spawn 总是从隔离的 git 根启动,因此该选择器不会出现、无需按键;无法避免的非项目启动场景,可用~/.grok/config.toml中的[hints] project_picker_disabled = true抑制。项目选择器与文件夹信任门是两个独立对话框。
  • 文件夹信任门:2026-09-24 的首次派发中,Grok 1.0.41 在 linked git worktree 里弹出了信任门。对话框打印的是 primary checkout 路径(linked worktree 的 git root 解析到主 checkout),因此文本读起来像是"隔离被破坏",而隔离实际完好。正确做法是:用/proc/<pid>/cwd检查 worker 真实位置,绝不信对话框打印的路径。
  • 用 bin/fm-send.sh 以按键路径 Enter 应答该门(fm-send.sh <target> --key Enter)。fm-send.sh只携带 Escape、Enter、C-c 三种键,字面y没有合规投递途径。
  • 信任决策持久化到~/.grok/trusted_folders.toml,键是对话框打印的路径。这正是bin/fm-spawn.sh故意不写、称之为"高爆炸半径写入"的同一存储:在 linked worktree 里信任会落在 primary checkout 而非一次性副本,并对之后每次 Grok 运行持续生效,等于静默开启该 checkout 的 Grok 项目 hooks。应答信任门仍是合规途径(因为fm-send.sh没有其他办法清除它),这是对"避免写该存储"立场的知情例外,因此该文件出现新条目是预期行为,不是疏忽。

六、训练 Opt-in:必须保持关闭的隐私边界

2026-09-24 的首次派发中,Grok 1.0.41 弹出了 "Help improve Grok" 训练 opt-in。该 opt-in 会把 prompts、traces 和 metrics 保留用于训练。

  • 它默认关闭,必须保持关闭;
  • 理由:本舰队对外发布的客户隐私声明承诺客户数据和音频不用于训练。一边向第三方 provider 发送自己的 prompts/traces 用于训练,一边对外发布这样的声明,不是可以悄悄做的交易。

这是把 harness 适配落到合规事实的一节:适配一个外部 TUI 不只是按键与状态机,还包括对隐私边界的事前决策。

七、Composer 状态识别:TRUECOLOR 幽灵文本

Grok 的 composer 输入框带边框,新会话占位符Type a message...用暗色 24-bit TRUECOLOR渲染(而非主题无关的 SGR-2)。这让旧的"按 SGR-2 剥离幽灵文本"逻辑失效——Grok 的占位符走的是38;2;...真彩色序列。

Firstmate 的解法集中在 bin/fm-composer-lib.sh 的fm_composer_strip_ghost:它是全舰队唯一 ANSI 感知的"真实键入文本"提取器,丢弃 dim/faint 以及亮度低于FM_COMPOSER_GHOST_LUMA_MAX(默认 128)的 TRUECOLOR 文本。实测数据(Grok 0.2.93):

  • 真实输入38;2;224;222;244亮度约 225,被保留;
  • 边框与占位符38;2;50;47;70至38;2;110;106;134,亮度约 51–110,被丢弃。

代价是这条真彩色规则假设舰队使用深色主题(SGR-2 才是主题无关的);提高FM_COMPOSER_GHOST_LUMA_MAX不是免费的——例如 muse 的⟩提示符亮度可能跨过阈值。回归覆盖在 tests/fm-composer-ghost.test.sh 与 tests/fm-backend-herdr.test.sh(后者包含 "grok dark-truecolor placeholder reads empty" 与 "grok bright real text reads pending" 两个用例)。

Tmux 侧还有一点:#{cursor_y}可能指向干净 composer 的底部边框,但共享分类器定位完整边框盒与所有内容行,所以边框光标与多行 composer 都不需要适配器偏移。

八、Worker Turn-End Hook:回合结束的可靠落盘

Grok 每个回合都会触发Stop事件。但项目级 hooks 需要~/.grok/trusted_folders.toml中的文件夹信任(spawn 不编辑该文件,不过应答上面那个信任门会写入它);全局~/.grok/hooks/则始终受信任。

因此 spawn 安装的是受守卫的全局fm-turn-end.json与fm-turn-end.sh:

  • 它们只在 workspace 的.fm-grok-turnend与~/.grok/hooks/fm-turn-end.d/下的注册表匹配时行动;
  • 然后通过始终设置的GROK_WORKSPACE_ROOT(等于 worktree)触摸任务的state/<id>.turn-ended;
  • 整个机制留在 worktree 之外、无需信任授予、只写 Firstmate 自己的文件。

bin/fm-teardown.sh会在池化前移除 gitignored 的指针;secondmate 跳过该 hook,因为 idle 是健康状态且普通 stale-pane 检测不适用。

九、Primary 集成:Turn-End 守卫与 Claude 设置兼容

Primary 模式验证于 2026-07-28(0.2.112,同时保留对 pre-native 0.2.73 的验证)。.grok/hooks/fm-primary-turnend-guard.json调用 bin/fm-turnend-guard-grok.sh。

9.1 Native 能力选择与 legacy 回退

该脚本用精确的正在运行的 Stop payload选择路径(源码见 bin/fm-turnend-guard-grok.sh):

  • payload 中出现stopHookActive(或 snake_casestop_hook_active)且为布尔值 →native路径:直接把 payload 交给共享守卫bin/fm-turnend-guard.sh,并把退出码(0 或 2)原样传回该 Grok 进程(0.2.112具备的同进程继续能力);
  • 无该字段 →legacy路径(0.2.73缺少 native 能力):当共享守卫返回 2("回合不能盲结束")时,编码一条 operational input,执行一次受守卫的grok --resume "$SESSION_ID" --cwd "$ROOT" --output-format plain -p "$PROMPT"作为回退;
  • payload 无效或不可读时两条路径都不启动;Camel case 优先于旧的 snake_case 拼写。

bin/fm-turnend-guard.sh存在且可执行、ROOT取自GROK_WORKSPACE_ROOT(回退CLAUDE_PROJECT_DIR)等前置条件都在脚本内逐条校验,任何一步不满足就静默退出。自适应与畸形输入行为由 docs/turnend-guard.md 拥有。

9.2 Claude 设置加载与标记守退

Grok 也加载 Claude 的项目设置(.claude/settings.json),所以被 Grok 覆盖的 Claude 事件条目在GROK_AGENT或GROK_HOOK_EVENT出现时必须stand down(守退),否则会产生第二条继续路径。两个 marker 都要检查,因为 Grok 不会给每种进程注入相同的变量。被守退的集合是:两个Stop条目、SessionStart条目、两个PreToolUseBash 条目;唯一刻意不守退的例外是bin/fm-subagent-pretool-check.sh——没有任何 Grok 注册覆盖 subagent-spawn 事件,见 docs/subagent-guard.md 的 "Known residual gap"。tests/fm-turnend-guard.test.sh固定了这个清单,任何一方都不能静默变化。

9.3 信任授予、守卫告警与 watcher 监督

  • 项目级 hooks 需要启动时的--trust;没有它,守卫让位,下一命令告警由 bin/fm-guard.sh 承担。
  • Watcher 监督保持"跟踪的后台通知"形态,围绕 bin/fm-watch-arm.sh,不是 Pi 风格的扩展所有权。
  • 在启用了config/supervision-host的 home 里,session-start 块把这个后台调用渲染为bin/fm-supervision-host.sh park,以 Claude 的 print mode 作为无头引擎;宿主由 docs/supervision-host.md 拥有。
  • PreToolUse 直接阻塞,但 hook 命令里的每个$VAR都需要内联:-default默认值,否则 Grok 拒绝该 hook——这是写 Grok hook JSON 时必须遵守的硬性语法约束。

十、配套验证与回归证据

  • 发送能力边界:bin/fm-send.sh只携带 Escape、Enter、C-c(无字面y路径),对应公共参考 references/common/control-and-recovery.md 的"生命周期动作只能走控制面"原则。
  • busy 语义:bin/fm-busy-lib.sh是语义 busy 的唯一所有者;Grok 的Ctrl+c:cancel/Shift+Tab:mode │ Ctrl+.:shortcuts判定是记录在该工具参考中的经验事实。
  • 测试覆盖:tests/fm-backend-herdr.test.sh 固定了 Grok 暗色 TRUECOLOR 占位符读作empty、亮色真实输入读作pending的判定;tests/fm-arm-pretool-check.test.sh 固定了 Grok 形态的 PreToolUse 拒绝(toolInput.commandschema 拒绝、Grok 形态 stdout JSON);tests/fm-afk-launch.test.sh 覆盖了 grok 等 harness 在 away 模式下不启动 daemon;tests/fm-agy-harness.test.sh 断言harness=grok绝不借用 agy 的 esc token,反之亦然。

十一、结语:把 Grok 当"Claude 兼容但不是 Claude"来对待

Grok Build 的适配经验可以浓缩为三条原则:兼容不等于相同(Claude 设置会加载,但 marker、asyncRewake、信任门、composer 渲染各自不同);投递必须验证(send 成功不代表送达,pane 里的真实状态才是证据);身份看祖先(GROK_AGENT与GROK_HOOK_EVENT因版本而异,结构祖先链才是进程归属的证明)。围绕这些事实,.agents/skills/harness-adapters/references/harness/grok.md 与bin/、tests/、docs/中的所有者共同构成一个可复制、可回归、可升级验证的 harness 适配闭环。

【免费下载链接】firstmate

Talk to one agent. Ship with a crew.

项目地址:https://gitcode.com/gh_mirrors/fi/firstmate
点击查看免费下载
上一篇:GetQzonehistory|一键备份QQ空间历史说说|跑完得到 6 个 Excel 和 1 个网页版
下一篇:Copilot for Obsidian 预发布(Prerelease)版本管理实战:从 semver 语义到 GitHub Actions 自动化发布

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询