跳到正文

Grok Build

Grok Build 是 SpaceXAI 的终端编码 agent:一个全屏、可用鼠标操作、可扩展的 TUI,套在一个会读代码库、改文件、跑 shell 命令、搜网页、并让长任务活下去的 harness 上。同一个二进制也能无界面地跑脚本与 CI,并通过 Agent Client Protocol 接进编辑器;它的扩展面是 hooks、插件、skills 与 MCP,它会主动收下竞争对手的配置,而它公开出来的这份代码树不接受任何外部贡献。

Screenshot of Grok Build
编辑截图, 1 Oct 2026Grok Build ↗

这是什么

Grok Build 是 SpaceXAI 放在终端里的编码 agent,而这个仓库就是 agent 本身,不是套在别人外面的壳:107 个 workspace 成员、4,487 个文件,全是 Rust,最终编译出一个叫 xai-grok-pager 的二进制,发给用户时叫 grok。交互面是一个全屏 TUI,有 scrollback、输入框、各种模态对话框、斜杠命令注册表和状态行;剩下的都是 harness——工具实现、读 Markdown agent 定义的构建器、会话存储、代码库图、沙箱、出口代理、支持写时复制与快照的 worktree 管理,以及无界面入口。hooks、带自己市场的插件、skills 与 MCP 都能扩展它,而它还会去读项目里已经存在的 Claude Code、Cursor 与 Codex 配置。它公开出来的样子才是反常的那部分:27,172 个星、5,112 个 fork、241 个 watcher,以及零 issue、零 pull request、零 discussion,贡献者只有一个机器人账号。

谁做的这个仓库属于一个组织账号,公开出来的贡献者只有一个、提交只有 51 次。而这 51 次——作者与提交者两个字段——全部是一个名叫 grokkybara 的 GitHub App,它在日志里显示为「grokkybara[bot]」,邮箱是 304785771+grokkybara[bot]@users.noreply.github.com,应用页面在 github.com/apps/grokkybara。没有任何一次提交挂着人名,也没有任何共同作者尾注。这些提交是同步清单而不是有人写的改动:标题都叫「Synced from monorepo」,正文是一串单行改动,末尾一条「Source-Revision:」指向 monorepo 的那次提交,而仓库根目录那个 41 字节的 SOURCE_REV 文件一字不差地重复了它。

它是怎么搭起来的

组成 · 6

一层终端界面加一个 agent harness,打成一个二进制;界面与 harness 拆成不同 crate,于是 TUI、无界面脚本、以及通过 Agent Client Protocol 接入的编辑器都跑同一份会话代码。TUI 是一套 Elm 式循环——输入变成 Action,dispatcher 把它变成 Effect,Effect 更新状态——而它不接管终端:它不切到备用屏幕,而是往正常屏幕打印,把视口钉在底部,于是对话落进终端自己的 scrollback,用户用终端滚动而不是用程序滚动。这个决定把异常多的活推到了底层渲染上,所以要够到视口内部状态就得 fork 一份 ratatui 的 Terminal,所以 resize 的做法是清屏、清 scrollback、重发历史,而不是相信回流。其余一切都从文件里发现而不是在代码里配置:agent 定义是带 YAML frontmatter 的 Markdown,hooks 与插件是目录,模型与 MCP 是配置,而同一套发现逻辑还会去走竞争对手的配置,让已经存在的项目原样可用。

crates/codegen/
103 个 crate,也就是整个产品。它们覆盖会话运行时、agent 定义与提示词拼装、工具实现、配置与受管策略、认证与 OIDC、模型采样器与采样类型、JSONL 会话存储、记忆、代码库图、MCP、沙箱与出口代理、遥测、崩溃处理器、诊断、语音采集,以及更新路径——此外还有七个只为被依赖而存在的 crate,比如文件锁、熔断器、token 估算与模糊文件搜索。
crates/codegen/xai-grok-pager/ 及其同族
界面本身:pager 这条 crate 装应用状态、dispatch、effects、views、斜杠命令注册表、主题与 ACP 客户端状态;一条 render crate 装终端、输入、鼠标、剪贴板、主题与图片叠层;一条 minimal crate 实现精简的非全屏模式;还有一套 pty harness 用真实伪终端驱动真正的二进制,包含 301 个测试文件(其中 218 个端到端)、45 份 YAML 场景与按平台的帧时长基线。组装根是另一个包,它的 main 文件一个就有 157 KB。
crates/codegen/xai-grok-shell/
agent 运行时与会话宿主,内部按 agent handlers、subagents、workflows、config、extensions、leader 与 relay 模式、tools、uploads 和会话存储分块。项目自己的历史也存在这里:166 组从 0.2.0 到 1.0.45 的 changelog,一份 151 KB 的汇总 changelog,以及一份 111 KB、兼作长篇用户手册的 README。
crates/codegen/xai-grok-agent/ 与 xai-grok-tools/
把 agent 做成一个可移植对象:带 YAML frontmatter 的 Markdown 定义、一个构建器、用自定义定界符渲染的提示词模板,以及按来源分组的工具实现——第一方一套、一个 hashline 编辑变体、另一家 agent 的文件与搜索工具移植、再一家 agent 的 shell、edit、glob、grep、read 工具移植,还有一份带 Kotlin 与 Swift 生成绑定的 protobuf 工具协议。
crates/codegen/xai-fast-worktree/ 与工作区各 crate
把 worktree 当基础设施做:写时复制与独立复制两套引擎、Btrfs 与 overlay 快照探测、一层会推理可达性与工作树的 git 安全代码、一个会扫描进程的垃圾回收器、一个记录数据库,以及生命周期基准测试。它周边是 agent 真正会碰的宿主文件系统、权限与自动模式分类器、沙箱与上传等 crate。
third_party/ 与文档
四个内置的第三方 crate——一套 Mermaid 转 SVG 的移植,连同它的 dagre、graphlib 与有序 map 依赖——理由是模型输出不可信,图形栈必须钉住版本并且可审计;旁边配了声明索引、升级清单,还特意说明 Apache 那几个 crate 的许可证文件用英式拼写是故意的。文档是另一大块面积:26 章编号用户指南加一份索引、9 页教程,以及单独的 hook 与插件指南。

取舍,以及它替代了什么

  • 往终端正常屏幕打印,把历史留在它自己的 scrollback 里 替代 用备用缓冲把整个屏幕接管过来

    内置的那份显示 crate 把设计直接写了出来:视口钉在终端底部,上方内容成为原生 scrollback 的一部分,用户用终端滚动,不用备用屏幕、也不做按终端区分的绕行。代价是 fork 一份控件库、再手写一条 resize 路径;换来的是 scrollback、复制与搜索全都属于用户本来就已经配好的那个终端。

  • fork 终端控件库,而不是照着公开接口用 替代 在 upstream 的 Terminal API 里想办法

    fork 的 README 列出了公开接口不暴露、而底部视口又需要的东西:当前视口位置与尺寸、直接设置视口位置、后台缓冲重置与前一缓冲访问、以及 resize 期间的缓冲状态。fork 保留 upstream 的 API 再补上这些,许可证与署名记在声明索引里。

  • resize 时清屏、清 scrollback,再重新输出历史 替代 让终端自己回流、并信任库的自动 resize

    这条以「问题—方案」的形式写明:在主屏幕上终端会在应用收到信号之前就重排内容,旧视口边界会变成乱码文本,内置的自动 resize 会破坏 scrollback,光标位置查询在快速 resize 时会打架,而且各终端回流方式不同。替代做法是写清屏、清 scrollback、光标归位,再把整段历史重新输出;不用 RIS,因为它在 iTerm 与 Terminal.app 里不清 scrollback。

  • 公开源码,但拒绝贡献 替代 开一个接受补丁的开放仓库

    688 字节里写得很清楚:本仓库不接受外部 pull request,也不接受未经请求的补丁;软件在内部开发,这棵树按 Apache-2.0 发布是为了源码透明与本地构建,这也是不提供贡献者许可协议的原因。仓库元数据与之一致:issue、pull request 与 discussion 全部关闭。

  • 直接读其他 agent 的配置,而不是让用户做迁移 替代 提供一个导入器加一份转换文档

    文档承诺设置、规则与技能都会跟过来:从 Claude Code 的位置读技能、agents、插件、已安装插件与市场索引、项目规则与权限;从 Cursor 读规则、技能与 MCP 配置;还读与 Codex 共用的 AGENTS.md 约定——并配了一次导入设置的辅助命令、接着别的工具里留下的会话继续跑的辅助命令,以及按来源各留一段开关的配置。

依据根目录的 Cargo.toml(自动生成,107 个 workspace 成员)、README.md(5,757 字节)、CONTRIBUTING.md、SECURITY.md、SOURCE_REV、clippy.toml、.cargo/config.toml、rust-toolchain.toml、crates/codegen/xai-grok-pager/README.md、docs/user-guide/README.md、docs/user-guide/21-terminal-support.md、docs/hooks-and-plugins.md、docs/tutorial/01-coming-from-another-tool.md、crates/codegen/xai-ratatui-inline/README.md、crates/codegen/xai-grok-agent/README.md、crates/codegen/xai-grok-shell/README.md(111 KB)、crates/codegen/xai-crash-handler/README.md、crates/codegen/xai-grok-pager-pty-harness/benches/pty_baselines/README.md、third_party/README.md、third_party/NOTICE、crates/codegen/xai-grok-pager/npm/grok/README.md、四个抽样 changelog 文件,以及完整的 4,487 个文件树及其体积。

制作过程

5 个阶段
  1. 01

    两万七千个星、五十一次提交,两个字段里是同一个机器人

    仓库建于 2026-07-14,最后一次推送是 2026-09-29;在这段窗口里它攒到了 27,172 个星、5,112 个 fork 和 241 个 watcher,而提交一共只有 51 次——七月 17 次、八月 24 次、九月 10 次。第一次提交标题是「Publish harness and TUI open-source」,日期 2026-07-16;此后每一次的标题都是「Synced from monorepo」。这份日志里最值钱的信息是「谁写的」,而答案是没有一个可见的人:API 对这 51 次提交返回的作者与提交者都是「grokkybara[bot]」,邮箱 304785771+grokkybara[bot]@users.noreply.github.com,应用页面是 github.com/apps/grokkybara,贡献者列表只有一项,就是这个应用。没有一条共同作者尾注,所以公开的历史里没有任何东西归到某个人名下,也没有任何东西点名归到某个模型名下。提交正文是发版清单:一串单行的「Changes:」条目——最新那条 11 条,最近十六条在 11 到 69 条之间——末尾跟着一条「Source-Revision:」指向 monorepo 的提交,而那个 41 字节的 SOURCE_REV 文件一字不差地重复了它。release 与 tag 都是空的;版本史活在 166 个 changelog 文件加 166 个 JSON 副本里,从 0.2.0 到 1.0.45,跳过了 0.2.48,日期分别是 0.2.120 的 2026-08-03、1.0.0 的 2026-08-07 与 1.0.45 的 2026-09-29。

  2. 02

    一个有 5,112 个 fork、却无处提交补丁的仓库

    社区入口是故意关掉的,而且关掉这件事有文件为证。688 字节的 CONTRIBUTING.md 写着:本仓库不接受外部 pull request,也不接受未经请求的补丁;SpaceXAI 在内部开发这份软件,公开的代码树是为了源码透明与本地构建,按 Apache-2.0 发布;它还说因为不接受外部贡献,所以也不提供贡献者许可协议。API 与这段话一致:issue、pull request、discussion、wiki、pages 和下载页全部关闭,pull request 策略设成只有协作者能开,于是 5,112 个 fork 只能产出本地副本。安全问题另有出路——166 字节的 SECURITY.md 把漏洞报告指向公司的 HackerOne 项目,并请求不要开公开 issue。在源码里找到的唯一产品内反馈通道也是朝内的:TUI 有一个 feedback 模态框,报告一路接到 Slack,包括从终端贴进去的图片附件;另有一条同步清单提到从 Slack 提示里找回超时的 git tag。留给公众的只有 docs.x.ai/build/overview 上的文档、一个 changelog 页面,以及一个从未记录过任何用户提问的仓库。

  3. 03

    一个把 scrollback 还给终端的 TUI

    界面是一个进程,形状故意很无聊——pager 这条 crate 自己写了它是一套 Elm 式循环:输入变成 Action,dispatcher 把 Action 变成 Effect,Effect 更新状态;AppView 管欢迎页与会话,每个会话一个 AgentView,管输入框、scrollback、工具面板与各种模态框——但它做了一个决定,把剩下的渲染代码全定死了。它往正常屏幕里打印,而不是接管终端,把视口钉在底部,于是上方所有内容都落进终端自己的 scrollback,用户用终端滚动,而不是用这个程序滚动。为了做到这一点,项目内置了一份 ratatui 的 fork,因为公开的 Terminal API 不暴露视口位置、后台缓冲和 resize 内部状态;这份 fork 还打开了 DCS 同步输出,让一批更新作为一帧到达屏幕。代价体现在 resize 上:代码清屏、清 scrollback、再把整段历史重新输出,而不是相信终端会正确回流;它还特意不用 RIS,因为那个转义序列在 iTerm 与 Terminal.app 里并不清 scrollback。同样的克制也出现在按键表里——它写明 Esc 永不取消一轮对话,回合进行中只会提示用户改用 Ctrl+C——也出现在一套用真实伪终端驱动程序的测试里:pager 测试目录下 301 个文件,其中 218 个是端到端,另有 45 份 YAML 场景与按平台存放的帧时长基线,某个场景的 p99 涨过 15% 就会让持续集成失败。

  4. 04

    把对手的配置直接收下,而不是要求用户做迁移

    扩展能力都收在一个模态框的三个标签页里——hooks、插件、市场——每一页都由文件驱动:hooks 来自全局目录、项目目录、插件或指定路径;插件是打包 skills、agents、hooks 与 MCP 的目录,作用域可以是用户、项目、命令行或某个市场来源;市场源可以用 git URL、owner/repo 简写或本地路径添加。接下来这一部分值得记下来,因为它是竞争决策而不是技术决策。这个 agent 会去读它对手的配置:从 Claude Code 的技能、agents、插件、已安装插件与市场索引、项目规则乃至权限设置里读;从 Cursor 的规则、技能与 MCP 配置里读;以及读与 Codex 共用的 AGENTS.md 约定;另外配了一键导入配置、以及接着那些工具里留下的会话继续跑的辅助命令,配置里还为每个来源各留一段开关。shell 的文档专门用一节列出 Claude Code 兼容表,代码里有专门处理外来会话与外部 agent 迁移的 crate,工具实现里有一部分是另一家 agent 工具的在树移植,并按许可证要求附了改动声明。于是已经为竞品配好环境的项目完全不需要迁移——这比写一个导入器更省事。

  5. 05

    文档自己承认了什么,又在哪里自相矛盾

    这些文件罕见地愿意写明什么东西不管用。沙箱那一章用自己的话列了两条限制:强制手段在 Linux 上是 Landlock、在 macOS 上是 Seatbelt,而如果沙箱没能生效——内核太旧、缺少 entitlement——Grok 会记一条警告然后不带强制继续跑;网络限制也只是部分的,因为配置只在子进程里断网,而网页搜索与模型 API 这类进程内 HTTP 完全不受影响,原因是 agent 本来就需要网络才能工作。崩溃处理器写明帧捕获是尽力而为,在编译器省略帧指针的 release 构建里可能为空;它还写明备用信号栈是按线程安装的,所以 Tokio 的工作线程并不受保护。根 README 说 macOS 与 Linux 是受支持的构建主机,Windows 构建是尽力而为、而且不在这棵树里测试;它还把根 Cargo.toml 标为自动生成、只读。那份自动生成的清单自己放行了一条 lint,并附了一段解释:项目没有 merge queue,于是别人合并进来的违规会进入 main,把所有人的构建搞坏。还有两处更小的不一致,出现在代码树与它自己的文档之间:第三方索引列了六个内置 crate,包括一个 NFS 服务端和 FUSE 客户端,但树里只有四个内置目录;npm 包文档只列了四个受支持平台,而树里发的是六个平台包。

相关档案

全部档案 →