把跑在你电脑上的 Cursor CLI(cursor-agent)变成一个能用飞书私聊远程操控的 AI 智能体 —— 人在外面,手机一条消息就能精准呼叫某个会话干活、看进度、收报告,还能自由切换 Gemini / GPT / Grok / Claude 等模型。
Drive Cursor CLI remotely from Feishu / Lark IM — like OpenClaw or Hermes, but for Cursor, powered by lark-cli.
Cursor · cursor-agent · Feishu · Lark · 飞书 · remote agent · mobile control · lark-cli · IM bot · slash command · multi-session routing · model switching · message reactions
💡 这是 Waga 的 Cursor CLI 版。原版面向 Claude Code,本仓库把同一套「多会话路由 + 状态反馈 + 流式卡片」适配到
cursor-agent,并新增 按会话切换模型 的能力。两套互不影响,可在同一台机上并存。
一句话:Waga 让你用飞书私聊,从手机精准指挥电脑上的某一个 Cursor 会话。
挂上 /waga-on 后,你的每个 Cursor 会话都盯着同一个飞书机器人,只响应开头带自己名字的消息(这个开头的名字就叫「前缀」,比如 web: 里的 web)。于是人在外面也能:
- 用手机飞书发一句「
build 跑一下」,电脑上对应的 Cursor 会话就开工; - 同时开几个会话(前端、后端、文档…),用
c:/web:精准点名其中一个,其余不抢答; - 隔着飞书看到进度:消息一被接走,气泡上自动冒出「处理中」表情,干完变绿勾;
- 甚至人在外面、电脑前没人,也能让 Cursor 远程新起一个 headless 会话来干活,并指定它用哪个模型(见「远程起 worker」)。
单个会话:你光用 lark-cli 让一个 cursor-agent -p 收发飞书消息就够了,不需要 Waga。
问题出在多窗口:当你同时开了三四个 Cursor 窗口,飞书那头没法分辨该把消息交给哪一个——它们要么全抢答,要么你根本点不到指定的那个。
Waga 就是补这一层:用 /waga-on <名字> 给每个会话起个名,一个 bot 就能同时跟多个会话协作、各干各的,互不打架。外加状态/情绪气泡反馈,让远程操控顺手。
根本区别:lark-cli 是一次性命令(跑一次 = 一次 API 调用),Waga 把它变成常驻事件流 + 多会话编排。
| 能力 | 原生 lark-cli | Waga for Cursor |
|---|---|---|
| 常驻消息泵 | ❌ 一次性命令 | ✅ Monitor 长轮询 + 去重 + 命中就唤醒对应会话 |
| 多会话路由 | ❌ 无会话概念 | ✅ 一个 bot 管多个 Cursor 窗口,前缀精准点名互不抢答 |
| 粘性目标 | ❌ | ✅ 无前缀消息自动归当前会话,手机长聊不用每条加前缀 |
| 手机友好语法 | ❌ | ✅ 冒号统一切换/一次性,中英文全角冒号都认 |
| 在线探活 | ❌ | ✅ 心跳文件 + /who 报谁在线/哪个目录/多久没动静 |
| 状态气泡 | ⚠ 只有原始 reactions API | ✅ 自动 OnIt(处理中)→DONE(绿勾) 状态机 |
| 情绪呼应 | ❌ | ✅ 按你当下情绪贴表情(怒→致歉、喜→庆祝) |
| 流式卡片 | ❌ | ✅ cursor-agent 输出实时刷到一张飞书卡片(蓝运行/绿完成/红失败 + 工具调用) |
| 🆕 模型切换 | ❌ | ✅ 起 worker 时指定 / 运行中 name: /model <model> 换 Gemini·GPT·Grok·Sonnet·Opus |
| 会话生命周期 | ❌ | ✅ 关窗=Monitor 自动注销、同窗重跑=覆盖改名 |
一句话:lark-cli 给的是『能力原料』,Waga 给的是『把多个 Cursor 会话变成可远程精准调度、可自由换模型的助手群』这套成品编排。
Waga(和 lark-cli)自己没法开终端、启动 cursor-agent。它只能驱动已经开着的会话(或后台 spawn 的 headless worker)。所以:
- 出门前,先把当天要用的 Cursor 窗口都开好,各自
/waga-on起好名。 - 多开就起
/waga-on 1、/waga-on web、/waga-on api这种有意义的名。 - 不用了:直接关掉窗口,对应的后台 Monitor 自动失效,无残留。
- 想改名:在同一个窗口重跑
/waga-on <新名>即可(覆盖式,不叠加)。
| 🎯 多会话精准路由 | 一个飞书 bot,多个 Cursor 会话各认各的前缀,c: / web: 点名互不干扰 |
| 🤖 按会话切模型 | 每个 worker 可独立指定 Gemini / GPT / Grok / Sonnet / Opus;运行中 name: /model X 热切 |
| 📱 手机友好语法 | 冒号一统「切换/一次性」,中英文冒号都认,全角 : 也行,单手可打 |
| 📌 粘性目标 | c: 单独发一条就把后续无前缀消息都粘到 c,长聊不用每条加前缀 |
| 💓 心跳 + /who | 每个会话写心跳文件,/who 一键报数(谁在线、哪个目录、多久没动静) |
| 🪧 流式 / 进度卡片 | 回复与干活进度刷在一张飞书交互卡片上实时更新(含工具调用名 + 参数) |
| ↩️ 引用回复路由 | 在飞书里「引用」某个会话发的卡片回复,自动路由到那个会话并切粘性 |
| 🤖 两层 reaction | 状态层 Typing→DONE + 情绪层(读完按你心情亲贴一组真实表情) |
| 🏷️ 引擎标签 | 卡片蓝名旁显示 · cursor · <模型>,与 Claude 拉起的卡一眼区分 |
| 🔒 零硬编码 | 所有账号信息走环境变量,仓库里不含任何私密标识 |
- Cursor CLI:
cursor-agent,已cursor-agent login(cursor-agent status显示 Logged in)。流式卡片靠它的-p --output-format stream-json。 - lark-cli:飞书官方 CLI(
larksuite/cli)。装 +lark-cli config init配好 bot 即可。Waga 全程走 bot 身份(--as bot),不需要lark-cli auth login。 - Python 3:卡片功能(
waga-card.py/waga-stream-cursor.py)用。
最省事:clone 本仓库后,直接跟 Cursor 说一句「帮我配 Waga」(或把 waga-setup.md 装成 /waga-setup 命令运行)。Cursor 会按剧本检测/装 lark-cli、引导授权、抓 chat_id/open_id、写好 .env。
export WAGA_CHAT_ID="oc_xxxxxxxxxxxx" # 你和 bot 的私聊 chat_id(消息从哪读)
export WAGA_USER_ID="ou_xxxxxxxxxxxx" # 你的 open_id(回信发给谁)
export WAGA_DIR="$HOME/path/to/waga-for-cursor" # 本仓库目录
export LARK_CLI_NO_PROXY=1 # lark-cli 强制直连,避免代理 reset
# 可选:worker 默认模型(不指定时用账号默认)
export WAGA_CURSOR_MODEL="gemini-3.1-pro"shell profile(macOS = ~/.zshrc)里只需 export WAGA_DIR 与 LARK_CLI_NO_PROXY,其余由各脚本自动 source $WAGA_DIR/.env:
echo 'export WAGA_DIR="$HOME/path/to/waga-for-cursor"' >> ~/.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。
把本仓库装成 Cursor 能识别的 skill,并把 /waga-on 装成命令:
# 方式 A:clone 进 Cursor skills 目录(仓库根的 SKILL.md 会被自动识别)
git clone https://github.com/XiaoChu-1208/waga-for-cursor.git ~/.cursor/skills-cursor/waga
export WAGA_DIR="$HOME/.cursor/skills-cursor/waga" # 让 WAGA_DIR 指向它
# 方式 B:仓库放别处,只把 SKILL.md 软链/复制进去
mkdir -p ~/.cursor/skills-cursor/waga
cp SKILL.md ~/.cursor/skills-cursor/waga/SKILL.md
# /waga-on 命令(Cursor 自定义命令)
mkdir -p ~/.cursor/commands
cat > ~/.cursor/commands/waga-on.md <<'EOF'
# /waga-on [name]
按 waga skill 的「挂监听(Cursor 适配版)」执行:起名 → 落盘 daemon 脚本 →
后台 Shell 跑它并设 notify_on_output 监听 [WAGA-MSG] → 确认上线卡片。
EOF
chmod +x "$WAGA_DIR"/*.shCursor 与 Claude Code 的差异:Claude 用
Monitor持久工具 +task-notification唤醒会话;Cursor 没有该工具,等价做法是后台Shell(is_background)+notify_on_output监听[WAGA-MSG]。详见SKILL.md。
在某个 Cursor 会话里:
/waga-on # name = 当前目录名
/waga-on c # 自定义 name(手机上 1-2 字符最省事)
挂上后立刻往飞书发上线回执卡片(name + cwd + 时间,蓝名旁标 · cursor)。同一会话再 /waga-on <新名> 是改名(先停旧的再挂新的),不叠加。
「粘性目标」= 当前默认接活的那个会话。消息开头没带名字,就自动归给它处理。
| 用法 | 例子 | 含义 |
|---|---|---|
| 无前缀 | 你看看 build.sh |
发给当前粘性目标会话(默认 main) |
| 粘性切换 | c: / c:(单独一条) |
把粘性目标切到 c |
| 冒号一次性 | c: 跑下测试 |
处理这条并把粘性切到 c |
| 方括号一次性 | [c] 跑下测试 |
只这一条给 c,不改粘性 |
| 全员报数 | /who |
列出所有在线会话(含 cwd、心跳新鲜度、引擎类型) |
- 状态层:
Typing(处理中) → 回完换DONE(绿勾)。纯状态显示,远程可见。 - 情绪层:会话读完消息、判断你当下情绪后亲贴一组(常 2-4 个)真实表情——你开心它庆祝、你愤怒它致歉、你沮丧它安慰。绝不随机、每次不同。
WAGA_ENGINE_LABEL=cursor bash "$WAGA_DIR/waga-reply.sh" <name> "<回复内容>"人在外面、电脑前没人,也能新起一个会话干活。对任意一个已经挂着的 Waga 会话,在飞书说一句大白话,Cursor 就会去跑 waga-spawn-cursor.sh 帮你起一个新的 headless worker:
waga: 起个新 session 叫 api,用 gemini,去 /path/to/proj 把测试跑一遍
它实际执行:
bash "$WAGA_DIR/waga-spawn-cursor.sh" api "把测试跑一遍" "/path/to/proj" gemini-3.1-proworker 后台常驻,监听 [api] 的飞书消息,每条用 cursor-agent -p --resume <session_id> 处理(保持上下文),过程实时刷到一张流式卡片。
# 起 worker 时(第 4 参)
bash "$WAGA_DIR/waga-spawn-cursor.sh" api "" "$HOME/proj" gpt-5.5-high- 默认模型:
.env里WAGA_CURSOR_MODEL,不传第 4 参时用它;都不设则用账号默认。 - 运行中热切:飞书发
api: /model grok-4.3(下一条消息生效)。 - 可用模型见
cursor-agent models(Gemini / GPT / Codex / Grok / Sonnet / Opus / Composer 等)。
卡片蓝名旁会显示 api · cursor · Gemini 3.1 Pro,一眼知道是哪个引擎、哪个模型。
headless worker 没有界面,弹不出确认框,所以带 --force(等价 Claude 的 --dangerously-skip-permissions,让它干活不用每次问你同意)。Cursor 出于安全不允许 AI 自己开这个口子——所以这条规则只能你本人手动加。
在 ~/.cursor/cli-config.json 的 permissions.allow 里加一条精确指向脚本的规则(把路径换成你 clone 本仓库的真实绝对路径):
因为加规则得在电脑前,所以「桌前花一分钟设置好,之后随时在外面远程用」。
[api] 把测试跑一遍 # 一次性给 api
api: 看下 lint # 切粘性 + 处理
api: /model gpt-5.5-high # 远程换模型
api: /cd /path/to/other # 切目录(新建 session)
api: /status # 看 cwd / 模型 / session
api: /stop # 优雅下线
本地关闭:touch /tmp/waga_stop_<名字>.txt,或 pkill -f "waga-spawn-cursor.sh <名字>"。
bash rebrand.sh ali # /waga-on → /ali-on,WAGA_CHAT_ID → ALI_CHAT_ID …- 每个会话跑一个独立后台 Monitor(Cursor 下 = 后台 Shell +
notify_on_output),每 ~15s 拉一次飞书私聊历史。 /tmp/waga_seen_<name>.txt记已处理消息(防重复);/tmp/waga_sticky.txt存粘性目标;/tmp/waga_alive_<name>.txt写心跳,/who据此判断谁在线。- 命中给本会话的消息 → 贴状态 reaction → emit
[WAGA-MSG]事件唤醒会话。 - worker 用
cursor-agent -p --output-format stream-json跑,waga-stream-cursor.py逐行解析事件(含tool_call工具名 + 参数,按call_id去重)刷到一张卡。 - 会话关闭 = Monitor 死 = 自动注销,无残留。
详见 SKILL.md 与 waga-on.md。
- 代理:
lark-cli走系统代理易被 reset,所有调用前设LARK_CLI_NO_PROXY=1(helper 已内置)。 - token 过期:约每 7 天,监听器喷
[WAGA-ERR],重跑lark-cli auth login --domain all。 - 会话存活才有唤醒:Cursor 的后台 shell + notify 仅在当前会话活着时起效(关窗即停)。
- 隐私:
WAGA_CHAT_ID/WAGA_USER_ID是你私人的飞书标识,只进.env(已 gitignore),别提交。
Q: 跟原版 Waga(Claude Code)什么关系?
A: 同一套编排,本仓库把底层 spawn 引擎从 claude 换成 cursor-agent(waga-spawn-cursor.sh / waga-stream-cursor.py),并加了模型切换。其余 helper(路由/卡片/表情/回信)完全复用。两套可在同一台机并存,互不干扰。
Q: 必须用 Cursor CLI 吗?
A: 是,本仓库面向 cursor-agent。要用 Claude Code 请看原版 Waga。
Q: 支持飞书国际版 Lark 吗?
A: 支持,lark-cli 同时覆盖飞书与 Lark。
Q: 让后台 worker 自动跳过权限确认,安全吗?
A: 它带 --force(自动放行工具),等于给这个无人值守会话放了权。Cursor 特意要求这一步由真人手动开。只在你自己的机器、给自己用的场景下用。
| 文件 | 作用 |
|---|---|
SKILL.md |
Cursor skill 本体:/waga-on 在 Cursor 下的挂载/收消息/起 worker 说明 |
waga-setup.md |
一键 onboarding 剧本:检测/装 lark-cli、引导授权、抓 ID、写配置 |
waga-on.md |
Monitor 监听循环源(飞书侧路由逻辑 + 挂载脚本,Cursor/Claude 共用) |
waga-spawn-cursor.sh |
🆕 远程 spawn 一个 headless cursor-agent worker(可指定模型) |
waga-stream-cursor.py |
🆕 cursor-agent 流式卡片引擎(解析 stream-json,工具名/参数实时刷卡) |
waga-spawn.sh / waga-stream.py |
Claude 版 spawn/流式引擎(共享渲染基座,被 waga-card.py 复用) |
waga-reply.sh |
回信 helper(走内联蓝字卡片,登记卡片 mid 供引用回复路由) |
waga-react.sh |
气泡表情 helper:add / done / clear / vibe |
waga-card.py |
卡片 helper:say / start+step+done / online / who |
waga-doctor.sh |
/doctor 自检:lark-cli 连通、粘性目标、各 worker 心跳/类型/日志 |
rebrand.sh |
一键换皮改名 |
{ "permissions": { "allow": [ "Shell(bash \"/绝对路径/waga-for-cursor/waga-spawn-cursor.sh\"*)" ] } }