我做了一个 Codex 插件:离开 Mac 后,用飞书继续本地编程会话

14 阅读7分钟

最近做了一个很小的 Codex 插件,叫 Codex Lark Remote

它解决的是一个我自己反复遇到的问题:我在 Mac 上打开 Codex,让它做代码分析、迁移、修 bug 或跑测试。很多任务并不需要我一直盯着屏幕,但中途又经常需要补充指令、确认方向、看一下进度。

如果人已经离开电脑,只能等回到 Mac 前再继续。这件事有点浪费。

所以我做了一个插件:在当前 Codex 对话里启动后,把这个对话交给飞书/Lark 机器人接管。之后你可以在飞书里继续给同一个 Codex 线程发消息,Codex 的关键进度和最终回答也会回到飞书里。

项目地址:

github.com/GxFn/codex-…

Codex Marketplace:

www.codex-marketplace.com/plugins/cod…

它解决的是什么问题

我想要的不是“远程服务器上跑一个 agent”,也不是“把仓库同步到云端再执行”。

我想要的是:

  • 代码仍然在本机
  • Codex 仍然在本机执行
  • 当前 Codex 对话的上下文仍然保留
  • 我只是临时离开 Mac,用飞书继续和它对话

典型场景是:

  1. 在 Codex Desktop 里打开一个项目。
  2. 让 Codex 开始分析或修改代码。
  3. 任务跑起来之后离开电脑。
  4. 在飞书里补充一句:“先别改 UI,优先把测试跑通。”
  5. Codex 收到这条消息,继续同一个本地对话。
  6. 飞书里收到关键进度、权限提示和最终结果。

这个模式的关键点是:飞书只是远程输入输出通道,不接管代码执行环境。

使用体验

第一次配置飞书/Lark 应用后,正常使用流程是:

  1. 在想继续的 Codex 对话里说:
启动 codex-lark-remote
  1. Codex 会要求你明确同意接管。

因为这会在本地 bridge 里保存当前 Codex thread 的路由状态。已有聊天历史不会发送到飞书/Lark,但接管期间之后的飞书消息和 Codex 回复会通过机器人传递。

  1. 同意后,插件启动本地 bridge,并绑定当前 Codex 线程。

  2. 之后直接在飞书/Lark 机器人里发普通消息即可。

比如:

检查 Alembic 文件夹的当前主要功能

或:

先不要改代码,只做架构分析

对 Codex 来说,这些消息会被当成同一个对话里的下一条用户消息。

为什么强调“当前窗口绑定”

这个插件最容易出错的地方,是同一个工作目录下可能同时开着多个 Codex 对话。

如果只按 cwd 绑定,就可能出现 A 窗口启动了飞书接管,B 窗口的消息却串流到飞书里。

所以现在的实现会严格绑定当前 Codex 窗口:

  • 优先使用 Codex 工具调用里提供的精确 thread id
  • 或使用当前 session path
  • 如果拿不到按窗口区分的元数据,就直接阻止 handoff
  • 不再按工作目录猜测“最近的会话”

这让启动流程更保守,但能避免远程接管时最危险的串流问题。

技术结构

插件里主要有几层:

1. Codex Plugin

插件通过 .codex-plugin/plugin.json 暴露给 Codex,包含:

  • Skill:告诉 Codex 什么情况下应该使用这个插件
  • MCP server:提供配置、诊断、启动接管、状态查询等工具
  • 图标和插件元信息

2. MCP 工具

Codex 通过 MCP 工具执行本地操作,例如:

  • 配置飞书 appId/appSecret
  • 检查飞书鉴权
  • 启动本地 bridge
  • 将当前 Codex thread 交给 bridge
  • 查询状态
  • 停止接管

正常启动时,agent 不应该绕过 MCP 去跑本地脚本。这一点在 skill 里写得比较明确。

3. 本地 bridge

bridge 是一个本地 Node 进程,负责:

  • 连接飞书/Lark WebSocket
  • 接收机器人消息
  • 根据 handoff 状态找到当前 Codex thread
  • 调用 codex exec resume 继续同一个线程
  • 把 Codex 的关键进度和最终回答发回飞书

它不是云服务,只在本机运行。

4. 飞书/Lark WebSocket

插件优先使用飞书/Lark 长连接,不要求用户配置公网 URL 或 webhook callback。

配置时需要:

  • 创建企业自建应用/内部应用
  • 启用机器人能力
  • 拿到 App ID 和 App Secret
  • 在事件订阅里选择长连接/WebSocket
  • 订阅 im.message.receive_v1
  • 开通消息接收和回复权限

飞书里的输出怎么控制

一开始我把 Codex 的命令和输出都发到飞书,结果很快发现会刷屏。尤其是 catnlsedrg 这类源码查看命令,内容对手机阅读意义不大。

现在默认策略是:

  • 最终回答正常发送
  • 关键进度发送
  • 普通 shell 命令默认不展示
  • Output: 默认不展示
  • 风险命令仍然显示,并带 Warning:
  • 如果用户主动发送 /codex commands on,才展示命令
  • 即使命令展示打开,Output 也只保留一行摘要
  • 长消息会自动拆成多条飞书消息,而不是截断

这样飞书里看到的是“Codex 做到哪了、结论是什么、需要我做什么”,而不是整屏终端日志。

执行中的补充消息

还有一个场景:Codex 正在执行时,我又从飞书发了一条新消息。

当前实现不会尝试把文本热注入已经运行中的 Codex 进程。这样做不稳定,也容易让状态变乱。

它会把这条消息保存为“补充引导”,在飞书里回复已收到,并在当前轮结束后作为下一轮继续执行。

这更像正常的对话节奏,也更可控。

权限边界

这个插件有一个非常重要的限制:飞书不能点击 Codex Desktop 的原生权限弹窗。

比如:

  • MCP 工具审批
  • 沙箱提权
  • 联网权限
  • 安装依赖
  • 写出工作区外的文件
  • Codex Desktop 里的安全确认弹窗

这些不能被飞书自动处理。

所以插件做的是:要求 agent 遇到这类边界时,不要沉默等待,而是发回一条清晰的飞书提示,说明需要什么权限,以及用户是必须回到 Mac 上点确认,还是可以在飞书里用文字明确授权。

换句话说,飞书接管的是“对话流”,不是“桌面 UI 控制权”。

Mac 状态要求

因为 Codex 仍然在本机运行,所以 Mac 必须在线,不能睡眠。

插件在 macOS 上默认会在 handoff 期间启动:

caffeinate -dimsu

这表示屏幕可以熄灭,但系统不要睡眠。关闭 handoff 或 bridge 停止时,这个保活进程会一起停止。

如果你想自己管理睡眠,也可以在配置里关闭:

{
  "handoff": {
    "keepAwake": false
  }
}

安装方式

最简单的安装方式:

npx codex-marketplace add GxFn/codex-lark-remote/plugins/codex-lark-remote --plugin --global

如果想固定到当前审核版本:

npx codex-marketplace add https://github.com/GxFn/codex-lark-remote/tree/v0.1.23/plugins/codex-lark-remote --plugin --global

插件页面:

www.codex-marketplace.com/plugins/cod…

GitHub:

github.com/GxFn/codex-…

配置飞书/Lark

创建飞书/Lark 应用后,把 appId、appSecret 和允许使用者配置给插件:

请配置 codex-lark-remote。

飞书应用:
- appId: cli_xxx
- appSecret: xxx

允许使用者:
- allowedUsers: ["ou_xxx"]

请用这些值调用 codex_lark_configure,然后运行 codex_lark_check_auth。

如果不知道自己的 sender id,可以先允许空列表启动,然后在飞书里发送:

/codex whoami

再把返回的 senderId 加入 allowedUsers

私密配置默认写在:

~/.codex-lark-remote/config.json

不要把这个文件提交到仓库。

常用命令

/codex whoami
/codex status
/codex observe
/codex observe <number|thread-prefix>
/codex observe off
/codex commands on
/codex commands off
/codex handoff off

另外,“断开连接”“停止接管”“关闭观察”“打开命令显示”这类口语也会被识别。

适合谁

我觉得它适合这些场景:

  • 你经常在本地用 Codex 跑长任务
  • 你希望代码仍然留在自己的 Mac 上
  • 你不想搭一套远程开发服务器
  • 你已经在团队里使用飞书/Lark
  • 你希望从手机上补充指令、看进度、接收最终结果

不适合的场景也很明确:

  • 希望 Mac 关机后继续执行
  • 希望自动处理所有权限弹窗
  • 希望多人同时控制同一个 Codex 线程
  • 希望把它当成完整的云端 coding agent

后续可能做什么

目前它还是一个很小的插件,后续我比较想继续打磨:

  • 更自然的中文口语指令
  • 更好的权限提示格式
  • 更清晰的进度摘要
  • 更完善的观察模式
  • 更稳定的首次安装和诊断体验

如果你也在用 Codex 和飞书/Lark,欢迎试一下,也欢迎提 issue。