lark-bridge-cli
v1.2.6
Published
Anti-overwrite guard for multi-agent editing of shared Feishu docs: transparent lark-cli PATH shim (fetch snapshot -> pre-write revision check -> conflict exit 42 -> self-heal).
Readme
lark-bridge
多 agent 并发编辑同一份飞书文档时的防覆盖层:透明 PATH shim 包装 lark-cli。
读取时自动存快照,写入前比对 revision,他人已改则命令失败(exit 42)并给出冲突证据与修复指引——agent 零学习成本,遇错自然走"重读-重生成-重提交"。
agent 侧无需任何改动:照官方 skill 原样调 lark-cli,不加参数、不设环境变量。
agent ──▶ lark-cli(shim) ──▶ 真 lark-cli ──▶ 飞书
│ docs +fetch → 存快照(revision + content)
│ docs +update → 写前自查:rev 不一致 = CONFLICT exit 42 + diff 证据
└ 其余命令原样透传设计全文见 DESIGN.md。
能力边界(必读)
这不是互斥锁,是防静默覆盖 + 冲突取证。 飞书服务端不提供条件写入(实测:带过期 --revision-id 提交照样成功,该参数语义是"读取基准"而非"期望版本"),所以最终一致性只能靠客户端收窄:
| 场景 | 行为 |
|---|---|
| 同机多 agent | fetch 存快照,update 前 check;check+write 由本机文件锁串行化 → 后手认知过期必被 42 拦 |
| 跨机多 agent | 各自快照独立,照样拦"你覆盖他"(rev 是服务端全局的);但两机毫秒级同刻提交无法互斥 |
| 对方没装桥 | 仍拦得住你覆盖他(你 check 时看到远端 rev 已变) |
| 认知来源 | 只有 docs +fetch 刷新基线。自己连写两次,第二次也会 42——重 fetch 即过 |
自愈动作(官方 skill 自带):紧贴提交前重新 docs +fetch → 按最新内容重生成 → 重提交。
避免并发用 --command overwrite。 实测(不经过桥)两个进程同时整文 overwrite,服务端非原子,结果是正文段落被复制一遍、新旧状态混杂,比单纯丢更新更难恢复。并发场景用 append / block_replace。
--doc 接 token 或分享链接都可以(?from=space、#anchor、结尾 / 会被剥掉),同一篇文档的各种写法命中同一份快照和同一把锁。
多 agent 隔离:LARK_BRIDGE_HOME 只隔离快照,锁始终在 ~/.lark-bridge/locks(要改用 LARK_BRIDGE_LOCK_DIR)—— 锁是本机全篇文档唯一的,跟着 HOME 走就等于没有锁。
docs +fetch 带 -q/--jq 时,调用方输出被过滤、不能当基线,桥会自己再取一次完整 JSON 存快照(多一次 API 往返,输出不受影响)。
安装(需已装真 lark-cli 与 python3)
一行安装(全平台首选):
npx -y lark-bridge-cli@latest install # macOS / Linux# Windows:用「以管理员身份运行」的 PowerShell,--machine 见下节(必须)
npx -y lark-bridge-cli@latest install --machine装完自跑 doctor 自检,看到 OK: bridge intercepts lark-cli 才算生效。Windows 上判定依据是注册表(新进程会拿到 Machine PATH + User PATH),所以必须新开一个 shell、并重启已在跑的 agent 才真正生效。
刚 npm publish 后注册表可见有几分钟延迟,@latest 可能还解析到旧版;要确定就钉版本号:npx -y [email protected] install。~/.lark-bridge 自包含,不依赖那个 npm 包留在机器上;升级就是再跑一次同一行。
npm install -g lark-bridge-cli && lark-bridge install --machine 也行,一样是一行。选 npx 的理由:① 运行期在 ~/.lark-bridge 自包含,全局包装完就没用了;② 全局包的 bin 目录通常排在 ~/.lark-bridge/bin 之前,留着旧全局包会让 lark-bridge 管理命令跑包内那份旧 bridge.py,与实际守卫分叉(doctor 会告警);③ allow-scripts 拦 postinstall 时 npx 那行不受影响,因为安装动作是显式子命令而不是生命周期钩子。
注意:提权安装要用同一个用户账户的管理员 shell(右键"以管理员身份运行")。若切换到别的管理员账户,文件会装进那个账户的 ~,你自己的账户仍无桥 —— doctor 会报 FAIL。
macOS / Linux(免 npm):
bash install.shWindows(PowerShell,非 WSL):
powershell -ExecutionPolicy Bypass -File install.ps1Windows 入口三件:lark-cli.cmd(cmd/PowerShell)、lark-cli(无扩展名,Git Bash/MSYS 用,因为 Git Bash 解析命令时不会自动补 .cmd)、两者都转 lark-cli.py(与 unix 同一份 python shim)。需 python(python3 / python / py)。装完重启终端/agent。WSL 用户直接用上面的 bash 版。
Windows: PATH 作用域(装完必看)
Windows 拼进程 PATH 的顺序是机器级在前、用户级在后,且无法翻转:微软 KB 100843 原文 "The user path is appended to the system path"。所以真 CLI 若装在机器级目录(Node 的默认全局 prefix C:\Program Files\nodejs 就是),我们往用户级 PATH 前置到第一位也排在它后面 —— 桥一次都拦不到,而且外观上毫无征兆。
装完先跑一次(退出码 0 才算真的生效):
lark-bridge doctor它按 PATH 顺序列出谁先命中 lark-cli 并判定,失败时直接打印修法。两种修法,都要一次管理员权限:
# A. 把桥前置到机器级 PATH(推荐:一条命令,对所有 shell 生效,可逆)
# 在「以管理员身份运行」的 PowerShell 里:
npx -y lark-bridge-cli@latest install --machine
# (从 git clone 装的用:powershell -ExecutionPolicy Bypass -File install.ps1 -Machine)
# B. 或把真 CLI 搬进用户作用域(影响面更大:所有 npm 全局包都要跟着搬)
npm uninstall -g @larksuite/cli # 这步需管理员
npm config set prefix %APPDATA%\npm
npm install -g @larksuite/cli # 普通权限为什么不提供免管理员的方案:agent 派生 shell 的两条主路径都绕过了 shell 启动钩子 —— Node 的 child_process 固定用 cmd.exe /d /s /c,/d 明确禁用 cmd 的 AutoRun 注册表钩子(官方 cmd 文档:"/d Disables execution of AutoRun commands");PowerShell 侧 -NoProfile 跳过 profile,且无任何用户级等价钩子。Git Bash 的 BASH_ENV 对 bash -c 有效,但只覆盖 Git Bash 一条路。所以免提权方案有确定性缺口,不如如实要求一次提权。
另注:unix 那套「往 ~/.bashrc 追加 export PATH」在 Windows 对 agent 完全无效 —— .bashrc 只在交互式 shell 读,bash -c 不读。
装完重启终端/agent 进程:环境变量是进程创建时的快照,已在运行的 agent 仍持有旧 PATH,改注册表也追不上。
卸载(秒级,零残留)
rm ~/.lark-bridge/bin/lark-cli # 即回原始 CLI
# 或从 PATH 移除 ~/.lark-bridge/bin;数据层回退用飞书原生 docs +history-revert命令
| 命令 | 作用 |
|---|---|
| lark-cli ... | 正常用,shim 自动拦截 fetch/update |
| lark-bridge log [-p] [--doc T] [-n N] | 事件索引 / 带 diff |
| lark-bridge show <id> | 单事件 + 冲突 diff |
| lark-bridge status --doc T | 快照 revision + 近期事件 |
| lark-bridge diff --doc T | 快照 vs 远端最新 |
| lark-bridge doctor | 自检:桥是否真的拦得住(PATH 顺序判定) |
| lark-bridge version | 实际部署的版本与文件时间(治"npm 升了、桥没升") |
| LARK_CLI_NO_BRIDGE=1 lark-cli ... | 单命令旁路 |
测试(离线,stub 模拟真 CLI,零网络)
bash tests/run_tests.sh # 59 项断言
bash tests/scenarios.sh # 真文档四场景(需网络+已登录真 CLI),16 项