Files
2026-08-16 02:42:22 +00:00

7.9 KiB
Raw Permalink Blame History

grok-glance

grok 终端会话加一个浏览器遥控台:镜像正在跑的 TUI,从网页里发 prompt、打断 turn、批准工具调用。终端不会交出控制权,两边同时可用。

一个 Go 二进制,前端编进去,一个端口,没有数据库。

你的机器                              任何能打开浏览器的地方
┌─────────────────────────┐           ┌──────────────────┐
│  grok TUInewgrok    │           │                  │
│         │               │           │                  │
│         └── /rc ══ WSS ═╪══▶ glance ══ WSS ══▶ 浏览器  │
└─────────────────────────┘           └──────────────────┘

grok 主动连出来。glance 可以跑在你能访问的地方,跑 grok 的那台机器不必开端口、不必做内网穿透。

必须搭配 newgrok

glance 自己不会跑 agent。/rc 桥在 iceBear67/newgrok 里:那是 xai-org/grok-build 的补丁工作流,远程控制是其中的 0003 / 0004 两个补丁。

这两边是同一个功能。 官方上游没有 /rc,单独用本仓库或单独用未打补丁的 grok 都连不上。线格式改一边,另一边也要改。

仓库 职责
iceBear67/newgrok 打过补丁的 grok TUI;在会话里敲 /rc,作为 ACP Agent 拨出
本仓库 自托管控制面:鉴权、会话列表、把 ACP 转成网页 UI

依赖

  • Go 1.24+
  • Node.js(构建嵌入的前端;make build 会跑 npm
  • 一台已经按 newgrok 的 README 编译好的 grokmake setup && make apply && make build

快速开始

1. 编译并启动 glance

make build
bin/glance serve --addr 127.0.0.1:7717 --insecure-cookie

首次启动会在 stderr 打出一条一次性 bootstrap URL(同时写到 ~/.grok/glance/bootstrap.token)。打开它,扫二维码,输入一个 TOTP 验证码。登记成功后这个 token 立刻作废。

--insecure-cookie 去掉 cookie 的 Secure,好让纯 HTTP 的 localhost 能登录。非回环地址会直接拒绝这个 flag。生产环境把 glance 放在终止 TLS 的反代后面,不要加这个 flag。

2. 给这台 grok 发一把 API key

另开一个终端:

bin/glance apikey add laptop

明文 glance_sk_… 只显示这一次,磁盘上只留 SHA-256。命令还会打出一段给 ~/.grok/config.toml 用的配置。

3. 在跑 grok 的机器上写配置

把上一步打印的内容写进 ~/.grok/config.toml

[remote_control]
url     = "ws://127.0.0.1:7717/api/acp/agent"
api_key = "glance_sk_…"

glance 不在本机时,把 url 换成它的地址(TLS 后面用 wss://…)。key 也可以不写进文件,改用环境变量:

配置项 环境变量 说明
url GROK_RC_URL glance 的 agent WebSocket
api_key GROK_RC_API_KEY glance apikey add 打出来的那把
auto_start GROK_RC_AUTO_START true 则会话一开始就连,不必敲 /rc
replay_buffer 重连时回放的帧数,默认 2048

环境变量优先于配置文件;空字符串当作没设置。

4. 在 grok 里打开遥控

按 newgrok 的方式启动 TUI(一般是仓库里的 make run),进入一个会话后:

/rc

也可以 /rc on/rc off/rc status。终端里应出现已连接的系统提示,TUI 本身继续能用——这是整件事情的前提。

然后打开 glance 的网页(默认 http://127.0.0.1:7717),用验证器里的 6 位码登录。会话列表里出现刚连上的 grok 即可遥控。

用的时候会怎样

  • 浏览器发的 prompt 会出现在终端里,两边一起流式输出。
  • 需要批准的工具调用、ask_user_question、退出 plan mode:终端和浏览器同时弹出。谁先答谁算数,另一边的卡片自己收起来。
  • 浏览器里的 Stop 是真正的 session/cancel,会话日志会记成 client:glance,不是模拟按 Esc。
  • glance 挂了、网络断了、进程被杀,终端不受影响。/rc 桥在自己的任务里退避重连;遥控不能把本地会话一起带走。

同一把 API key 重连会顶掉上一条连接。两台 grok 共用一把 key 会互相抢槽位,每台各发一把。

命令

glance serve [flags]            跑服务器
glance apikey add <name>        给一台 grok 签发 key
glance apikey list
glance apikey rm <id-or-name>
glance bootstrap                再打一次 setup token(仅未登记时)
glance version

serve 的 flag

Flag 默认 说明
--addr 127.0.0.1:7717 监听地址。默认只绑回环,对外暴露必须是有意识的
--dir ~/.grok/glance 状态目录
--insecure-cookie 纯 HTTP localhost 用;非回环地址禁止

状态与恢复

持久化的只有无法重算的东西,写在 ~/.grok/glance/state.json0600):TOTP 密钥、cookie 签名密钥、API key 的哈希。对话历史是每条 agent 内存里的环形缓冲(4096 帧),刷新页面会回放,重启服务器不会

验证器丢了:删掉 state.json,重新登记。没有别的找回方式。这会同时作废所有 API key 和已签发的 cookie。glance bootstrap 在已经登记过后会拒绝再发 token。

~/.grok/glance/ 里还有 secret.keyhook.secret,那是别的东西用的,不要动。

登录失败全局限流(5 分钟 8 次)。用过的 TOTP 步进会烧掉,同一个 30 秒窗口里登两次,第二次会失败——这是防重放,不是故障。

部署注意

glance 是带壳 agent 的遥控台。能通过鉴权的人可以批准任意工具调用。

  • 默认只听 127.0.0.1。要暴露出去,放在终止 TLS 的反代后面。
  • 自己不终止 TLS。公网上开 --insecure-cookie 等于把 session cookie 明文送出去。
  • 没有多用户、没有角色、没有审计日志、没有按 key 分权限。
  • Cookie 名是 __Host-glance:浏览器强制 Secure + Path=/ + 不许设 Domain。改其中任何一项,浏览器会静默丢掉 cookie,看起来像登录坏了。

开发

make build        # 前端,再编二进制 → bin/glance
make server       # 只编 Go,沿用上次的前端
make web          # 只编前端
make check        # go vet + go test + tsc --noEmit
make dev          # Go + Vite 热更新 → http://localhost:5173

//go:embed 在编译期解析,所以 go build 打进去的永远是上次 make web 的产物。改了 UI 却没出现在 bin/glance 里,就是这个原因。vite build 会清空 web/dist/,连 .gitkeep 一起删;make web / make clean 会补回来,裸跑 npm run build 不会。干净 clone 缺这个文件时,go build 会报一个难看的 embed 错误。

前端开发用 make devVite 把 /api 代理到 Go。__Host-glanceSameSite=Strict,跨源发不出去。拿 Vite UI 直接打 Go 的 7717 端口,会表现为莫名其妙的鉴权失败。

不编 Rust、只调 UI 时,用 cmd/fakeagent:它按真桥一样拨 agent socket,演一段带真实 session/request_permission 的回合。

bin/glance serve --insecure-cookie &
make fakeagent KEY=glance_sk_…

这证明不了真桥说的是同一种方言。动过桥、交互路径或线格式之后,按 ARCHITECTURE.md 的设计说明和仓库里的端到端清单,对着一台真的 newgrok 跑一遍。

设计上为什么是这个形状——grok 当拨出方、角色对终端是反的、浏览器不直接讲 ACP、交互两边抢答——见 ARCHITECTURE.md