飞书控制 Claude Code 工作 —— lark-channel-bridge 完整配置指南
用飞书/Lark 直接指挥你电脑上的 Claude Code(或 Codex CLI)干活:发消息、发图、传文件、切项目、跑代码,人在外面用手机就能让本机 agent 改代码。本文从零开始,覆盖安装、扫码绑定、后台常驻、访问控制、身份授权,以及一路上会踩的坑和解决办法。
0. 一句话说明
lark-channel-bridge 是一个轻量 bot,把飞书消息和本机 Claude Code / Codex CLI 打通:你在飞书私聊发一句话,bridge 转发给本机 agent 执行,结果流式回显到飞书。核心命令一条:
npm i -g lark-channel-bridge && lark-channel-bridge run
扫个码绑定飞书应用,就能用了。本文剩余部分讲清楚每一步的细节和坑。
1. 能做什么
- 飞书私聊直接发消息,或在群里
@bot,把任务转给本机 Claude Code / Codex CLI。 - 流式卡片:文本回复和工具调用实时更新在同一张卡片上。
- 会话延续:每个聊天 / 话题 / 文档评论各自独立,互不串。
- 排队与合并:短时间连续消息合并处理;任务运行中收到的消息排队到下一轮。
/new、/cd、/ws use、/stop可中断当前任务。 - 多工作空间:
/cd切项目,/ws保存复用常用目录。 - 图片 / 文件:直接发给 bot,bridge 下载到本地交给 agent 处理。
- 卡片按钮:
/help、/ws list、/status返回可点击交互卡片。
2. 前置条件
| 依赖 | 要求 |
|---|---|
| Node.js | >= 20.12.0 |
| 本机 agent CLI | claude(Claude Code)或 codex(Codex CLI),已安装并登录 |
| 飞书 / Lark 应用 | 一个 PersonalAgent 应用(首次扫码向导可帮你创建并绑定) |
agent CLI 的"登录"很关键:bridge 拉起的子进程要能用对应 CLI 正常干活,否则 bot 会出现"没反应"。详见第 9 节坑 1。
3. 安装
npm i -g lark-channel-bridge
# 或
pnpm add -g lark-channel-bridge
⚠️ 服务层命令(
start/stop/status/restart/unregister)必须先全局安装,不能用npx。原因见第 9 节坑 10。
4. 首次启动与扫码绑定(bot 应用身份)
lark-channel-bridge run
第一次运行进入扫码向导:
- 终端渲染二维码。
- 用飞书 App 扫码。
- 选择或创建 PersonalAgent 应用。
- 若终端提示,选择本次要初始化的 agent(claude / codex)。
- 成功后配置写入
~/.lark-channel/config.json。
没有指定项目目录也能启动:bridge 会创建一个 profile 托管的默认工作目录,之后在飞书里发 /cd <path> 切到实际项目即可。
已有 PersonalAgent 应用,可传 --app-id 跳过创建流程,命令会提示输入 App Secret:
lark-channel-bridge run --app-id cli_xxx
# 或直接初始化并启动后台服务
lark-channel-bridge start --app-id cli_xxx
Lark 国际版应用加 --tenant lark。
5. 后台常驻(让 bot 一直在线)
run 适合首次配置和前台调试。确认能正常收发消息后,Ctrl-C 停掉,再用系统服务常驻:
lark-channel-bridge start
lark-channel-bridge status
lark-channel-bridge stop
平台映射:
| 平台 | 服务方式 |
|---|---|
| macOS | launchd 用户代理 ai.lark-channel-bridge.bot.<profile> |
| Linux | systemd 用户单元 lark-channel-bridge.bot.<profile>.service |
| Windows | 任务计划 LarkChannelBridge.Bot.<profile>(launcher 为 .cmd) |
daemon 日志:~/.lark-channel/profiles/<profile>/logs/daemon/
多 profile(分别跑 Claude / Codex)
默认用当前激活的 profile,profile use <name> 切换。每个 profile 独立维护应用凭据、会话、工作目录和日志。只有需要同时连多个 PersonalAgent 应用,或分别跑 Claude 和 Codex 时才需要多 profile:
lark-channel-bridge start --profile claude --agent claude
lark-channel-bridge start --profile codex --agent codex
lark-channel-bridge restart --profile codex
lark-channel-bridge status --profile codex
profile 管理命令:
lark-channel-bridge profile create claude --agent claude
lark-channel-bridge profile list
lark-channel-bridge profile use <name>
lark-channel-bridge profile remove <name> # 归档(默认)
lark-channel-bridge profile remove <name> --purge --yes # 永久删除
lark-channel-bridge profile export <name> --output ./profile.json
6. 飞书内斜杠命令速查
| 命令 | 作用 |
|---|---|
/new, /reset |
清空当前会话 |
/cd <path> |
切换工作目录并重置会话 |
/ws list |
列出命名工作空间 |
/ws save <name> |
保存当前目录为命名工作空间 |
/ws use <name> |
切换到命名工作空间 |
/ws remove <name> |
删除命名工作空间 |
/resume |
恢复历史会话 |
/status |
查看 profile / agent / 目录 / 会话 / lark-cli 身份状态 |
/config |
调整展示偏好、访问控制、lark-cli 身份策略 |
/invite user @某人 |
允许该用户私聊使用 |
/invite admin @某人 |
添加管理员 |
/invite group |
允许当前群使用 |
/invite all group |
允许 bot 所在的所有群使用 |
/remove ... |
移除对应访问控制条目 |
/stop |
停止当前 run |
/timeout [N\|off\|default] |
设置/清除当前会话 idle watchdog |
/ps |
列出本机 bridge 进程 |
/exit <id\|#> |
停止指定 bridge 进程 |
/reconnect |
强制 WebSocket 重连 |
/doctor [描述] |
执行低敏诊断 |
/help |
帮助卡片 |
私聊不需要 @;群和话题群默认必须 @bot,@all 被忽略。
7. 访问控制(谁能用)
默认私有:开箱即用,只有"你"(应用创建者/owner)能在私聊和群聊里用 bot。其他人消息被静默忽略(不回"你没权限",避免暴露存在)。
想让别人也能用,加进三类名单:
| 名单 | 控制谁 | 加入 | 移除 |
|---|---|---|---|
| 允许私聊的用户 | 谁能私聊 bot | /invite user @某人 |
/remove user @某人 |
| 响应的群 | bot 在哪些群对群内所有人响应 | /invite group / /invite all group |
/remove group |
| 管理员 | 谁能改设置、任意群用 bot | /invite admin @某人 |
/remove admin @某人 |
常见配置:
- 只给自己用 → 什么都不用做。
- 让同事能私聊 →
/invite user @他 - 让某个群全员可用 → 在那个群发
/invite group - 首次一次性开放所有群 →
/invite all group,再/remove group删不想要的。 - 拉人一起当管理员 →
/invite admin @他
改完下一条消息即生效,不用重启。群默认要
@bot才回,这是另一个开关(/config→"群里需要 @ bot")。
8. 可选:绑定个人身份授权(lark-cli auth login)
上面扫码绑定的是应用/bot 身份。如果还想让 agent 访问你的个人资源(日历、邮箱、云盘等),需要额外的用户身份授权(OAuth 设备流)。
两阶段授权流程(关键,务必前台阻塞)
# 阶段 1:秒返回,拿 verification_url 和 device_code
lark-cli auth login --no-wait --json [--recommend | --domain ... | --scope ...]
stdout 里有 verification_url 和 device_code。把 verification_url 原样发给用户(用代码块,不要 Markdown 链接化)。
# 阶段 2:前台阻塞,等用户点完(或 10 分钟超时)
lark-cli auth login --device-code <code>
用户点完后,继续在当前 profile 环境执行:
lark-cli config strict-mode off
lark-cli config default-as auto
这会让当前 profile 同时可用应用身份和已授权用户身份。
⚠️ 为什么不能后台跑、为什么必须私聊——见第 9 节坑 2、坑 3。授权期间你发的新消息会自动排队,不会打断阻塞。
9. 踩坑与解决(重点)
下面是实际部署过程中验证过的问题和完整解决办法。
坑 1:systemd 后台运行时 claude 子进程报 "Not logged in"
- 现象:前台
run一切正常;start装成 systemd 服务后,bot 不回复,日志显示 claude 子进程Not logged in。 - 原因:systemd 服务默认不继承你 shell 里的环境变量。你平时在终端里配好的
ANTHROPIC_*(登录态 / 自定义端点)不在 service 环境里,bridge 拉起的 claude 子进程继承到的是空环境。 - 解决:给 service 加一个 drop-in 环境文件补齐变量:
mkdir -p ~/.config/systemd/user/lark-channel-bridge.bot.<profile>.service.d
cat > ~/.config/systemd/user/lark-channel-bridge.bot.<profile>.service.d/env.conf <<'EOF'
[Service]
Environment="ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic"
Environment="ANTHROPIC_AUTH_TOKEN=sk-xxxxxxxxxxxxxxxx"
Environment="ANTHROPIC_MODEL=deepseek-v4-pro"
Environment="CLAUDE_CODE_SUBAGENT_MODEL=deepseek-v4-pro"
Environment="CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000"
EOF
chmod 600 ~/.config/systemd/user/lark-channel-bridge.bot.<profile>.service.d/env.conf
systemctl --user daemon-reload
lark-channel-bridge restart --profile <profile>
(示例是 DeepSeek 的 Anthropic 兼容端点;用官方 Claude 就填官方 ANTHROPIC_BASE_URL 或直接不设,用你自己的 key。)
- 安全注意:token 是明文存在这个文件里的,务必
chmod 600收紧权限。
坑 2:OAuth 授权必须前台阻塞,不能丢到后台
- 现象:把
lark-cli auth login用后台方式跑,用户还没点完授权,进程就被回收,授权永远失败。 - 原因:bridge 在 run 结束后会回收 agent 子进程,你 spawn 的任何后台 bash 也跟着一起死。
- 解决:用第 8 节的两阶段流——先
--no-wait --json秒返回拿链接,再把--device-code <code>前台阻塞等用户点完。
坑 3:群里发起设备流授权,token 会被抢
- 现象:device flow 的
verification_url发到群里,谁先点谁拿走 token,可能绑到错的身份。 - 解决:只在私聊(p2p)发起授权。群聊里用户要求授权时,回复"授权要在私聊里做,请单独私信我"。
坑 4:授权成功后还要收敛身份策略
- 现象:
lark-cli auth login已成功,但--as user仍被 strict-mode / default-as 拒绝。 - 解决:授权完成后顺序执行
lark-cli config strict-mode off和lark-cli config default-as auto。不要重新 bind,不要绕回本机普通配置。
坑 5:不要 unset bridge 注入的环境变量
bridge 会给子进程注入 LARK_CHANNEL、LARK_CHANNEL_HOME、LARK_CHANNEL_PROFILE、LARK_CHANNEL_CONFIG、LARKSUITE_CLI_CONFIG_DIR 等变量,指向当前 profile。不要 unset、不要 env -u LARK_CHANNEL 绕回本机普通配置,否则会读写错 profile。
坑 6:提示 "lark-channel context detected but not bound"
- 现象:
lark-cli报lark-channel context detected but lark-cli is not bound to it。 - 解决:停止当前操作,请用户重启 bridge 或运行 bridge doctor / preflight。不要改用普通 profile、不要自行 bind、不要直接读
config.json里的账号密钥。
坑 7:bot 只有被真实 @ 才能收到群消息
飞书机制:bot 只有被结构化 @ 才能收到群消息。纯文本写 "@名字"、或不带 @ 的普通回复,其他 bot 一律收不到。需要某个 bot 接着处理时,必须真实 @ 它(open_id 优先从 bridge_context.mentions 取)。默认不要 @ 其他 bot,互相 @ 会死循环。
坑 8:交互卡片回调按钮需要签名 token
想发可点击的回调卡片,按钮 value 对象必须同时含 __bridge_cb: true 和 bridge_token: "<signed token>":
{
"tag": "button",
"text": { "tag": "plain_text", "content": "方案 A" },
"behaviors": [{
"type": "callback",
"value": {
"__bridge_cb": true,
"bridge_token": "SIGNED_TOKEN_FROM_LARK_CLI",
"choice": "a"
}
}]
}
bridge_token必须由 bridge-aware 的 lark-cli 回调签名能力生成,不要猜测、伪造、复用或手写。- 如果当前 lark-cli 不能生成
bridge_token,不要发回调按钮,改成普通展示卡,让用户用文字回复选择。 - 用户点击后,bridge 校验 token,把 payload(去掉
__bridge_cb和bridge_token)作为[card-click] {...}发回给你,session 自动续上。
坑 9:interactive card 的 schema 2.0 vs v1 降级
飞书 v2 CardKit(schema 2.0)会双发:elements 是 v1 兼容降级("请升级至最新版本客户端"),user_dsl 才是真卡内容。解析卡结构时认 user_dsl,别被 elements 的降级文案误导。零文字 v1 卡(纯按钮/图片/装饰)SDK 抓不到字时,bridge 会把整段 raw JSON 灌进来。
坑 10:服务层命令必须全局安装
start / stop / status 等 daemon 命令不能用 npx。daemon 的 systemd unit / launchd plist / Windows 任务会记录 bridge CLI 的路径;如果这个路径来自 npm 临时缓存,缓存清掉后 daemon 就起不来。先 npm i -g lark-channel-bridge。run 用 npx 单次启动没问题。
10. 数据目录与配置参考
| 路径 | 内容 |
|---|---|
~/.lark-channel/config.json |
root config(profiles + active profile) |
~/.lark-channel/active-profile |
最近选择的 profile |
~/.lark-channel/profiles/<profile>/sessions.json |
会话状态 |
~/.lark-channel/profiles/<profile>/secrets.enc |
profile 本地加密 secret |
~/.lark-channel/profiles/<profile>/lark-cli/ |
当前 profile 的 lark-cli 目录 |
~/.lark-channel/profiles/<profile>/media/ |
附件缓存 |
~/.lark-channel/profiles/<profile>/logs/ |
结构化运行日志 |
~/.lark-channel/registry/processes.json |
本机进程注册表 |
~/.lark-channel/registry/locks/ |
profile lock 和 app lock |
设置 LARK_CHANNEL_HOME=/path/to/state 可迁移整棵本地状态目录;LARK_CHANNEL_LOG_DAYS 调整日志保留天数。
权限模式(permissions.defaultAccess / maxAccess)
新 profile 默认都是 full(保证 bridge 本地工具、授权流程、文件写入完整可用)。收紧可改 workspace 或 read-only:
| Bridge access | Claude 权限模式 | Codex 模式 |
|---|---|---|
full |
bypassPermissions |
danger-full-access |
workspace |
acceptEdits |
workspace-write |
read-only |
plan |
read-only |
lark-cli 身份策略
每个 profile 用独立 lark-cli 目录 ~/.lark-channel/profiles/<profile>/lark-cli。默认 bot-only(只访问应用/bot 身份);完成用户授权后可切 user-default(保留应用身份 + 允许已授权用户身份)。owner/admin 用 /config 切换,/status 显示 lark-cli: app 或 lark-cli: user-ready。
11. 常见问题 FAQ
bot 没反应 / agent 不回复 → 通常是本机 claude/codex 没登录,或当前会话指向不存在的目录。发 /status 看状态,/new 重开会话。(后台运行时还可能是坑 1 的环境变量问题。)
卡片停在最后一帧不动(假死) → idle 探活:/config 设全局值,或 /timeout 10 只对当前会话;/timeout off 关闭,/timeout default 回退全局。
图片发过去 agent 说看不到 → 升级到最新版(0.1.0 之前有文件名去重 bug)。
12. 参考
- 官方中文 README(本文的权威来源):npm 包内
node_modules/lark-channel-bridge/README.zh.md - 飞书效果文档:https://larkcommunity.feishu.cn/docx/OaRIdFIRFoLM3xxTmKwcetHqn5e
- Claude Code 安装:https://docs.anthropic.com/en/docs/claude-code/quickstart
- Codex CLI 安装:https://developers.openai.com/codex/cli
- 许可:MIT