把跑在你电脑上的 Claude Code 变成一个能用飞书私聊远程操控的 AI 智能体 —— 人在外面,手机一条消息就能精准呼叫某个会话干活、看进度、收报告。
Drive Claude Code remotely from Feishu / Lark IM — like OpenClaw or Hermes, but for Claude Code, powered by lark-cli.
Claude Code · Feishu · Lark · 飞书 · remote agent · mobile control · lark-cli · IM bot · slash command · multi-session routing · message reactions
一句话:Waga 让你用飞书私聊,从手机精准指挥电脑上的某一个 Claude Code 会话。
挂上 /waga-on 后,你的每个 Claude Code 会话都盯着同一个飞书机器人,只响应开头带自己名字的消息(这个开头的名字就叫「前缀」,比如 web: 里的 web)。于是人在外面也能:
- 用手机飞书发一句「
build 跑一下」,电脑上对应的 Claude Code 就开工; - 同时开几个会话(前端、后端、文档…),用
c:/web:精准点名其中一个,其余不抢答; - 隔着飞书看到进度:消息一被接走,气泡上自动冒出「处理中」表情,干完变绿勾;
- 甚至人在外面、电脑前没人,也能让 Claude 远程新起一个会话来干活(见下方「如何拉起新 session · 方式 B」,需提前做一次性设置)。
这是最该说清的一点。
单个会话:其实你光用 lark-cli 让一个 Claude Code 会话收发飞书消息就够了,不需要 Waga。
问题出在多窗口:当你同时开了三四个 Claude Code 窗口,飞书那头没法分辨该把消息交给哪一个——它们要么全抢答,要么你根本点不到指定的那个。
Waga 就是补这一层:用 /waga-on <名字> 给每个会话起个名,一个 bot 就能同时跟多个会话协作、各干各的,互不打架。外加状态/情绪气泡反馈,让远程操控顺手。
类比:把 Claude Code 当 OpenClaw / Hermes 那样的远程 IM 智能体来用——Waga 给
lark-cli套了一层多会话路由 + 状态反馈。
根本区别:lark-cli 是一次性命令(跑一次 = 一次 API 调用),Waga 把它变成常驻事件流 + 多会话编排。
| 能力 | 原生 lark-cli | Waga |
|---|---|---|
| 常驻消息泵 | ❌ 一次性命令,不持续监听 | ✅ Monitor 长轮询 + 去重(SEEN) + 命中就唤醒对应会话——把被动 CLI 变主动事件流 |
| 多会话路由 | ❌ 无会话概念 | ✅ 一个 bot 管多个 Claude Code 窗口,前缀精准点名互不抢答 |
| 粘性目标 | ❌ | ✅ 无前缀消息自动归当前会话,手机长聊不用每条加前缀 |
| 手机友好语法 | ❌ | ✅ 冒号统一切换/一次性,中英文全角冒号都认 |
| 在线探活 | ❌ | ✅ 心跳文件 + /who 报谁在线/哪个目录/多久没动静(文件锁防刷屏) |
| 状态气泡 | ⚠ 只有原始 reactions API | ✅ 自动 OnIt(处理中)→DONE(绿勾) 状态机 |
| 情绪呼应 | ❌ | ✅ 按你当下情绪贴表情(怒→致歉、喜→庆祝),实证调色板+情绪映射 |
| 会话生命周期 | ❌ | ✅ 关窗=Monitor 自动注销、同窗重跑=覆盖改名 |
| 回信纪律 | ❌ | ✅ helper 强制 [name] 前缀 + NO_PROXY + 「必须发飞书别只在 UI 写」 |
一句话:lark-cli 给的是『能力原料』,Waga 给的是『把多个 Claude Code 会话变成可远程精准调度的助手群』这套成品编排。
Waga(和 lark-cli)自己没法开终端、启动 Claude Code。它只能驱动已经开着的会话。所以:
- 出门前,先把当天要用的 Claude Code 窗口都开好,各自
/waga-on起好名。 - 多开就起
/waga-on 1、/waga-on 2,或/waga-on web、/waga-on api这种有意义的名。 - 不用了:像关任何窗口一样直接关掉,对应的后台 Monitor 自动失效,无残留。
- 想改名:在同一个窗口重跑
/waga-on <新名>即可(覆盖式,不会叠加)。
| 🎯 多会话精准路由 | 一个飞书 bot,多个 Claude Code 会话各认各的前缀,c: / web: 点名互不干扰 |
| 📱 手机友好语法 | 冒号一统「切换/一次性」,中英文冒号都认,全角 : 也行,单手可打 |
| 📌 粘性目标 | c: 单独发一条就把后续无前缀消息都粘到 c,长聊不用每条加前缀 |
| 💓 心跳 + /who | 每个会话写心跳文件,/who 一键报数(谁在线、哪个目录、多久没动静) |
| 🪧 流式 / 进度卡片 | 回复与干活进度刷在一张飞书交互卡片上实时更新(蓝运行/绿完成/红失败 + 工具调用),不再发一串刷屏文本(waga-card.py / waga-stream.py,借鉴 feishu-claude-code-bridge) |
| ↩️ 引用回复路由 | 在飞书里「引用」某个会话发的卡片回复,自动路由到那个会话并切粘性,连前缀都不用打 |
| 🤖 两层 reaction | 状态层 Typing→DONE(处理中/完成,远程可见)+ 情绪层(读完按你心情亲贴一组真实表情) |
| ❤️ 情绪呼应 | 情绪层每次按内容现挑、像人一样贴 2-4 个、绝不随机/复读:开心→庆祝、愤怒→致歉、沮丧→安慰 |
| 🏷️ 可换皮 | 一条命令把 Waga 整套改名成你自己的品牌(/ali-on / /bilu-on) |
| 🔒 零硬编码 | 所有账号信息走环境变量,仓库里不含任何私密标识 |
最省事的方式:clone 本仓库后,直接跟 Claude Code 说一句「帮我配 Waga」(或把 waga-setup.md 装成 /waga-setup 命令运行)。Claude 会按 waga-setup.md 的剧本:
- 检测 / 安装
lark-cli(飞书官方 CLIlarksuite/cli) - 跑
lark-cli config init --new—— 自带浏览器引导建应用,你只需在那一步给 bot 起个名、换个头像;不用去开放平台手动配权限或拿 App Secret - 跑
lark-cli auth login --domain im—— 把授权链接发给你,你点一下完成 - 自动抓你和 bot 的
chat_id/ 你的open_id,写好环境变量 - 装好
/waga-on命令
你全程只需要: 点一次浏览器链接(建 app + 授权)→ 给 bot 起名换头像 → 在飞书给 bot 发条消息建立单聊。其余 Claude 全包。
💡 lark-cli 原生支持 OpenClaw / Hermes 的 agent workspace(检测到会用
config bind绑定现有 app)。Waga 把这套能力对准了 Claude Code。
如果你想手动配、或了解底层依赖:
- lark-cli:飞书官方 CLI。装 +
lark-cli config init(配好 App ID/Secret)即可。Waga 全程走 bot 身份(--as bot),不需要lark-cli auth login(那是用户身份、访问个人资源才用)。 - Claude Code CLI:
claude,spawn worker / 流式卡片靠它的-p --output-format stream-json。 - Python 3(仅卡片功能
waga-card.py/waga-stream.py用):脚本一律用py启动器跑(Windows 上python常被 WindowsApps 桩占用)。卡片正文用<font color>上色,Windows 下 Python 调lark-cli.CMD时<>会被 cmd 当重定向符——脚本已自动改用node直跑 lark-cli 的 JS 绕过,无需你操心。 - 配置放在仓库目录下的
.env(已 gitignore,绝不上传)。所有脚本(reply/react/card/spawn/doctor)以及/waga-on都会自动source它,所以 shell profile 里只需 export 一个WAGA_DIR:
| 变量 | 放哪 | 含义(大白话) |
|---|---|---|
WAGA_CHAT_ID |
.env |
你和机器人那个对话框的编号(oc_ 开头)——消息从哪读 |
WAGA_USER_ID |
.env |
你这个人在飞书里的身份编号(open_id,ou_ 开头)——回信发给谁 |
WAGA_DIR |
.env + shell profile |
本仓库脚本所在目录;/waga-on 靠它找到 .env |
仓库目录下的 .env(waga-setup.md 会帮你写好):
export WAGA_CHAT_ID="oc_xxxxxxxxxxxx"
export WAGA_USER_ID="ou_xxxxxxxxxxxx"
export WAGA_DIR="$HOME/path/to/waga-feishu-skill"
export LARK_CLI_NO_PROXY=1 # lark-cli 走系统代理易被 reset,强制直连然后只把 WAGA_DIR 放进 shell profile(macOS = ~/.zshrc,Linux = ~/.bashrc,Windows PowerShell = $PROFILE),/waga-on 就能自动 source $WAGA_DIR/.env 拿到其余变量,不必把 ID 在两处重复维护:
echo 'export WAGA_DIR="$HOME/path/to/waga-feishu-skill"' >> ~/.zshrc
echo 'export LARK_CLI_NO_PROXY=1' >> ~/.zshrc手动拿 ID:先在飞书给 bot 发条消息建立单聊,再 lark-cli im +chat-list --as bot 取 chat_id、lark-cli im +chat-messages-list 取你的 open_id。
cp waga-on.md ~/.claude/commands/waga-on.md # /waga-on
cp waga-setup.md ~/.claude/commands/waga-setup.md # /waga-setup(可选)
chmod +x waga-reply.sh waga-react.sh在某个 Claude Code 会话里:
/waga-on # name = 当前目录名
/waga-on c # 自定义 name(手机上 1-2 字符最省事)
挂上后立刻往飞书发上线回执(name + cwd + 时间)。同一会话再 /waga-on <新名> 是改名(先停旧的再挂新的),不叠加。
先解释「粘性目标」:它就是当前默认接活的那个会话。你发的消息如果开头没带名字,就自动归给这个「粘性目标」处理——省得每条都打前缀。
冒号一统天下,靠冒号后有没有内容区分「切粘性」(换默认接活的人)和「一次性」(只这一条临时给某人)。中英文冒号都认。
| 用法 | 例子 | 含义 |
|---|---|---|
| 无前缀 | 你看看 build.bat |
发给当前粘性目标会话(默认 main) |
| 粘性切换 | c: / c:(单独一条) |
把粘性目标切到 c |
| 冒号一次性 | c: 跑下测试 |
只这一条给 c |
| 方括号一次性 | [c] 跑下测试 |
同上,PC 习惯 |
| 全员报数 | /who |
列出所有在线会话(含 cwd、心跳新鲜度) |
最常用:想找 c 长聊 → 发 c: → 之后随便说啥都到 c → 发 main: 切回去。
- 状态层:
Typing(处理中) → 回完换DONE(绿勾)。固定的,纯状态显示,远程可见「在处理/已处理」。 - 情绪层(核心):会话读完消息、判断你当下情绪后亲贴一组(常 2-4 个)真实表情——你开心它庆祝、你愤怒它致歉、你沮丧它安慰。绝不随机、绝不只贴一个、每次都不同(随机/复读=糊弄,不是「活」)。
bash "$WAGA_DIR/waga-react.sh" vibe <mid> "JOYFUL Fire CLAP" # 情绪层:按内容现挑一组
bash "$WAGA_DIR/waga-react.sh" done <mid> # 状态层:Typing 换 DONE⚠ 飞书
emoji_type大小写敏感、是 key 的一部分:Fire有效、FIRE报231001。连发太快也会 231001(helper 自带限速)。一条消息上限约 10 个。可用调色板见waga-react.sh头注释;负面/共情表情飞书放行得少(基本Sigh/Salute),方向对齐比数量重要。
bash "$WAGA_DIR/waga-reply.sh" <name> "<回复内容>" # 自动加 [name] 前缀、设 NO_PROXY先分清两种「session」:
- 交互式会话:一个你能看到、能在窗口里继续打字操作的 Claude Code(就是你平时用的那种)。
- headless worker:没有界面、在后台默默跑的 Claude。(headless = 无头 = 没有界面)。它自己收发飞书消息、自己干活,你看不到窗口,全靠飞书跟它沟通。
下面 4 种方式,方式 B 最重要——它是你人在外面、电脑前没人时,唯一能新起一个会话的办法。
| 方式 | 类型 | 在哪触发 | 适用 |
|---|---|---|---|
A. 开窗口 + /waga-on |
交互式 | 电脑前 | 最常规;出门前把当天要用的都开好 |
| B. 飞书一句话让 Claude 远程起 ⭐ | headless | 飞书(远程) | 人在外面、电脑前没人——唯一可行的远程起法 |
| C. 命令行起 worker | headless | 任意终端 | 在电脑前、不想占一个窗口 |
D. ! 前缀起 worker |
headless | Claude Code 输入框 | 已经在一个会话里,顺手起一个 |
在电脑上新开一个 Claude Code 窗口/标签(终端里再跑一个 claude,或 IDE 里开一个),然后:
/waga-on api # 起名 api
- 这是完整交互会话,你能看到界面、随时接管。
- ⚠ Waga 自己开不了窗口,所以这种方式必须你人在电脑前。出门前把当天要用的窗口都开好、各自
/waga-on起名。
人在外面、电脑前没人,也能新起一个会话干活。对任意一个已经挂着的 Waga 会话,在飞书说一句大白话,Claude 就会去跑 waga-spawn.sh 帮你起一个新的 headless worker:
waga: 起个新 session 叫 api,去 /path/to/proj 干「把测试跑一遍」
它起好后,这个叫 api 的 worker 就常驻后台,你再用 [api] xxx 给它派活(见下方「给 worker 派活」)。
为什么要加:headless worker 没有界面,弹不出「是否允许执行这条命令」的确认框,所以它得带一个开关 --dangerously-skip-permissions(大白话:让它干活时不用每次都问你同意,因为后台没界面没法问你)。而 Claude Code 出于安全,不允许 AI 自己给自己开这个开关,也不允许 AI 偷偷改配置来绕过——所以这条规则只能你本人手动加。
第 1 步:找到配置文件 settings.json。它在你家目录下的 .claude 文件夹里(~ 就是「你的家目录」的简写)。完整路径按系统:
| 系统 | settings.json 完整路径 |
|---|---|
| Windows | C:\Users\你的用户名\.claude\settings.json |
| macOS | /Users/你的用户名/.claude/settings.json |
| Linux | /home/你的用户名/.claude/settings.json |
把「你的用户名」换成你电脑的登录名。
.claude前面有个点,是隐藏文件夹。文件不存在就新建一个。
第 2 步:在里面的 permissions.allow 列表加一条规则。改完大概长这样(把路径换成你 clone 本仓库的真实位置):
⚠ 光写宽泛的
"Bash"不够——Claude Code 有一层「意图审查」会拦下「自动跳过权限的后台 agent」,必须是上面这条精确指向 waga-spawn.sh 的规则才放行。因为加规则得在电脑前,所以方式 B 是「桌前花一分钟设置好,之后随时在外面远程用」。
任意终端(Git Bash)里:
bash "$WAGA_DIR/waga-spawn.sh" <名字> "初始任务(可留空)" "/工作目录"
# 例:
bash "$WAGA_DIR/waga-spawn.sh" api "看下 api 目录有没有 lint 错误" "$HOME/proj"worker 后台常驻,监听 [名字] 的飞书消息,每条用 claude -p --resume <固定session-id> 处理(claude -p = 不开界面、跑一次就出结果的模式;--resume <号> = 接着同一个对话存档号聊,所以记得上下文,跟正常会话一样),结果发回飞书。
在 Claude Code 的输入框里直接敲(! 是输入框的本地执行前缀,敲了它会直接在本机跑这条命令):
! bash "$WAGA_DIR/waga-spawn.sh" api "初始任务" "/工作目录"
注意:
!只在你亲手在输入框敲时有效;把! ...通过飞书发给 Claude 只是一段文字,不会执行。
不管哪种方式起的 worker,都用同一套飞书语法派活:
[api] 把测试跑一遍 # 一次性给 api
api: 看下 lint # 同上
api: # 单独发一条,把粘性目标切到 api,之后无前缀都给它
api: /stop # 远程:worker 收到后优雅下线退出
本地关闭:touch /tmp/waga_stop_<名字>.txt,或杀进程 pkill -f "waga-spawn.sh <名字>"。关掉即注销,无残留。
交互式会话(方式 A)的关闭就是关掉那个窗口,对应 Monitor 自动失效。
不喜欢叫 Waga?一条命令全套改名(命令名、脚本名、事件标记、临时文件、环境变量):
bash rebrand.sh ali # /waga-on → /ali-on,WAGA_CHAT_ID → ALI_CHAT_ID …
bash rebrand.sh Bilu改完记得:① 重设 <新名大写>_CHAT_ID 等环境变量;② 装进 ~/.claude/commands/ 的那份也改名成 <新名>-on.md(命令名 = 文件名)。
- 每个会话跑一个独立后台 Monitor(常驻后台小程序,负责盯飞书有没有新消息),每 ~15s 拉一次飞书私聊历史(
lark-cli im +chat-messages-list)。 /tmp/waga_seen_<name>.txt记已处理的消息(防重复);/tmp/waga_sticky.txt存当前粘性目标;/tmp/waga_alive_<name>.txt每轮写个时间戳当「心跳」,/who靠它判断谁还活着。- 命中给本会话的消息 → 先贴状态 reaction → emit
[WAGA-MSG]事件唤醒会话。 - 会话关闭 = Monitor 死 = 自动注销,无残留。
详见 waga-on.md。
⚠ 最容易误解的一点:飞书 App ID / App Secret 和登录 token 不在本仓库里,也不会随同步盘(iCloud / Syncthing / Dropbox)走——它们存在 lark-cli 自己的、每台机器独立的配置目录(macOS: ~/.lark-cli/)。仓库里的 .env 只有 chat_id / open_id / WAGA_DIR 三样。
所以换一台新电脑(哪怕仓库已经同步过去了),lark-cli 这一层要重做:
- 装 lark-cli:
npx @larksuite/cli@latest install - 接回同一个已有应用(强烈推荐——旧的
chat_id/open_id继续有效,无需重抓):只有想新建 app 时才用# 零浏览器:用已有应用的 App ID + Secret 直接配(Secret 走 stdin,不进进程列表) printf '%s' '<你的 App Secret>' | lark-cli config init --app-id <你的 App ID> --app-secret-stdin --brand feishu
lark-cli config init --new(浏览器流程);但新 app 会让旧chat_id/open_id失配,得按waga-setup.mdStep 3 重抓。 - 验证 bot 通了:
lark-cli im +chat-messages-list --chat-id "$WAGA_CHAT_ID" --as bot --page-size 1(返回"ok": true即可)。 - 把
.env里的WAGA_DIR改成新机器上仓库的真实路径,并在 profile 里export WAGA_DIR=...。 - 装命令 + 加执行权限(见上方「安装命令」),跑
/waga-on测通。
💡 用 bot 身份收发消息只需要 App ID + Secret(
config init配好即可),不需要auth login。auth login(用户身份)只有访问你个人日历/云盘/邮箱才用到,Waga 用不上。
- 代理:
lark-cli走系统代理易被 reset,所有调用前设LARK_CLI_NO_PROXY=1(helper 已内置)。 - token 过期:约每 7 天,监听器喷
[WAGA-ERR],重跑lark-cli auth login --domain all。 - 一会话一 name:两个窗口挂同名会都响应(通过上线回执能立刻发现)。
- 隐私:
WAGA_CHAT_ID/WAGA_USER_ID是你私人的飞书标识,只进环境变量,别提交进仓库。
Q: 跟 OpenClaw / Hermes 有什么关系? A: 思路一样——把 AI agent 接进 IM 远程操控。Waga 专做 Claude Code + 飞书,更轻(无需部署服务),并加了多会话路由和情绪化反馈。
Q: 必须用 Claude Code 吗?
A: skill 形态是给 Claude Code 的。但 waga-on.md 里那段挂载脚本是普通 bash,可单独跑,只是少了「事件唤醒会话」那层。
Q: 支持飞书国际版 Lark 吗?
A: 支持,lark-cli 同时覆盖飞书与 Lark;建机器人和拿 ID 的流程一致。
Q: 人在外面,能让 Claude 自己新起一个会话干活吗? A: 能,就是上面的「方式 B」。需要你提前在电脑前加一条权限规则(一次性,做完永久有效)。之后在飞书说一句「起个新 session 叫 X 干 Y」即可。
Q: 让后台 worker 自动跳过权限确认,安全吗?
A: 它带 --dangerously-skip-permissions(自动放行工具),等于给这个无人值守的会话放了权——能力强但也意味着它会自动执行你飞书发去的指令。Claude Code 特意要求这一步由真人手动开就是这个原因。只在你自己的机器、给自己用的场景下用,别把 bot 暴露给别人。
Q: 会泄露我的聊天/账号吗? A: 不会。所有账号标识走环境变量,仓库零硬编码。
| 文件 | 作用 |
|---|---|
waga-setup.md |
一键 onboarding 剧本:让 Claude Code 帮你检测/装 lark-cli、引导授权、抓 ID、写配置(/waga-setup) |
waga-on.md |
skill 本体:/waga-on 说明 + 挂载用的 Monitor 脚本 |
waga-reply.sh |
回信 helper(走内联蓝字卡片,自动登记卡片 mid 供引用回复路由) |
waga-react.sh |
气泡表情 helper:add / done / clear / vibe |
waga-card.py |
卡片 helper:say(蓝字消息卡) / start+step+done(步进进度卡) / online(上线卡)。需 Python 3,用 py 启动 |
waga-stream.py |
流式卡片引擎:包 claude -p --output-format stream-json 跑,把过程实时刷到一张卡(spawn worker 用)。被 waga-card.py 复用渲染 |
waga-spawn.sh |
远程 spawn 一个 headless waga worker(无需开窗口的新 Claude 会话),输出走流式卡片 |
rebrand.sh |
一键换皮改名 |
{ "permissions": { "allow": [ "Edit", "Bash", "Bash(bash \"/你clone的路径/waga-feishu-skill/waga-spawn.sh\"*)" ] } }