skills/feishu-cli-event/SKILL.md
飞书实时事件订阅(WebSocket)。event list 看支持的 EventKey;event schema 看事件 payload/scope; event consume 启动长连接订阅,事件流以 NDJSON 写到 stdout(阻塞,一个进程订阅一个 EventKey); event status 看本机活跃 consume 进程;event stop 按 PID / EventKey / --all 停止 consume。 支持 22+ EventKey(im 消息接收/已读/撤回/reaction、群成员变动、contact 员工变更、 日历变更、云盘标题/协作者、审批实例与任务、VC 会议起止)。 支持断线重连和多 EventKey 并行订阅。 当用户请求"监听飞书事件"、"实时接收消息事件"、"订阅审批回调"、"event 流"、 "WebSocket 长连接监听"、"event consume"、"event list / schema / status / stop"、 "AI Agent bot 实时响应"时使用。 注意:本技能只负责订阅;处理事件 webhook 业务逻辑(push 到飞书消息/写多维表格) 请配合 feishu-cli-msg / feishu-cli-bitable。
npx skillsauth add riba2534/feishu-cli feishu-cli-eventInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
通过 feishu-cli event 子命令族订阅飞书开放平台事件,使用 WebSocket 长连接接收事件并以 NDJSON 输出到 stdout,适合 AI Agent 做 bot 实时响应、群消息监听、审批回调消费等场景。
feishu-cli:如尚未安装,请前往 riba2534/feishu-cli 获取安装方式。
发消息? 请使用 feishu-cli-msg 技能。本技能专注于事件订阅(接收应用事件),不负责发送。
event consume <EventKey>
│
├─ 启动 WebSocket 长连接(飞书 SDK ws.Client + AutoReconnect)
├─ 注册到 bus.json(PID / EventKey / 启动时间 / max-events / timeout)
├─ stderr 输出 [event] ready event_key=<key>
├─ 接收事件 → 写 stdout(NDJSON,每条一行 JSON)
├─ 可选:dump 每条事件为 <event_id>.json 文件
├─ 退出条件:--max-events / --timeout / SIGTERM / Ctrl-C / stdin EOF / pipe broken
└─ 退出时自动 unregister bus.json
与 lark-cli event 的差异:lark-cli 用 Unix domain socket 跑独立 bus 守护进程做事件 fan-out;feishu-cli 简化为「每个 consume 直接连一条 WebSocket」,不做事件分发——足够覆盖 AI Agent 单 EventKey 订阅的主线场景。
| 路径 | 作用 |
|---|---|
| ~/.feishu-cli/events/<app_id>/bus.json | 活跃 consumer 列表(PID/EventKey/启动时间/参数) |
| ~/.feishu-cli/events/<app_id>/bus.lock | flock 文件锁;bus.json 读写串行化,fd 关闭自动释放 |
每个 AppID 一个子目录,不同应用互不干扰。event status 查询会主动剔除已不存活的 PID 条目(kill -9 / 崩溃残留)。bus.json 用 tmp + rename 原子写,防半写。
| 流 | 内容 |
|---|---|
| stdout | 每条事件一行 JSON(NDJSON),适合 jq / 脚本管道 |
| stderr | 诊断日志;启动时一行 [event] ready event_key=<key> (init complete; WS handshake in progress) |
AI Agent 推荐:父进程把 consume 跑后台(
run_in_background=true),先阻塞 stderr 等到[event] ready那一行再开始读 stdout。注意:ready marker 只表示进程初始化完成,WS 握手在后台异步执行;父进程见到 marker 后还需额外等 1-3s 让 WS 握手真正完成,生产环境建议父进程发自检事件 + 等 echo 回环来确认链路通。
| 退出码 | 含义 |
|---|---|
| 0 | 正常退出(达到 --max-events / --timeout / SIGTERM / Ctrl-C / stdin EOF) |
| 非 0 | startup 失败 / WebSocket 不可恢复错误 / 参数错误 |
stderr 末尾会输出 [event] exited — elapsed=<d> reason=<r>,reason 有 4 个:
limit — 达到 --max-eventstimeout — 达到 --timeoutsignal — 上下文取消(Ctrl-C / SIGTERM / stdin EOF / 下游 pipe broken)error — WebSocket 连接持续失败feishu-cli event list [--json] # 1. 列所有支持的 EventKey
feishu-cli event schema <event_key> [--json] # 2. 看某 key 的 EventType / scope / payload schema
feishu-cli event consume <event_key> [flags] # 3. 启动订阅(阻塞)
feishu-cli event status [--json] # 4. 看本机活跃 consume 进程
feishu-cli event stop {--pid N | --event-key K | --all} [--force] [--json] # 5. 停 consume
event list:列出支持的 EventKey按 domain 分组展示当前支持的 22+ EventKey(im / contact / calendar / drive / approval / vc)。
# 表格视图(默认)
feishu-cli event list
# JSON 输出,jq 提取 IM 域所有 EventKey
feishu-cli event list --json | jq -r '.[] | select(.domain=="im") | .key'
输出字段(JSON 模式):key / event_type / description / domain / scopes[] / payload_schema。
event schema:看 payload schema 与 scopefeishu-cli event schema im.message.receive_v1
feishu-cli event schema im.message.receive_v1 --json
输出 4 部分:Key / Event Type / Domain / Description / Scopes + 可选 Payload Schema (示例)。Payload schema 为手工 curated,订阅后实际 payload 以飞书开放平台文档为准。
event consume:启动 WebSocket 订阅(阻塞)# 基础订阅,Ctrl-C 退出
feishu-cli event consume im.message.receive_v1
# 调试:抓 5 条消息,最多跑 60s
feishu-cli event consume im.message.receive_v1 --max-events 5 --timeout 60s
# 落盘 + 静默
feishu-cli event consume im.message.receive_v1 --output-dir ./events --quiet
# 配合 jq 实时过滤群消息
feishu-cli event consume im.message.receive_v1 | jq 'select(.event.message.chat_type=="group")'
# 后台并发订阅多个 EventKey(每个 EventKey 一个进程)
feishu-cli event consume im.message.receive_v1 > receive.ndjson 2> receive.log &
feishu-cli event consume im.message.reaction.created_v1 > reaction.ndjson 2> reaction.log &
feishu-cli event status
关键 flag:
| Flag | 默认 | 说明 |
|---|---|---|
| --max-events N | 0(不限制) | 接收 N 条事件后退出,reason=limit |
| --timeout <duration>(示例 60s) | 0(不限制) | 运行 D 时长后退出,reason=timeout |
| --jq .event.xxx | "" | 极简点路径过滤,不支持完整 jq 语法(用 pipe 接外部 jq) |
| --output-dir ./events | "" | 每条事件额外 dump 为 <event_id>.json 落盘(不影响 stdout) |
| --quiet | false | 抑制 stderr 诊断;AI Agent 慎用——会一起抑制大部分 stderr,但 ready marker 仍走真实 os.Stderr 不受影响 |
--jq 限制:只识别 .a.b.c 形式的 map 取值(如 .event.message),不支持 select / 数组下标 / 管道。复杂过滤请用 feishu-cli event consume ... | jq '<expr>'。
--output-dir 限制:必须是安全相对路径;不做 ~ 展开,不接受绝对路径或 .. 路径段。
event status:看本机活跃 consume 进程feishu-cli event status
feishu-cli event status --json | jq '.consumers[] | .pid'
输出:App ID / State file 路径 / PID / EVENT_KEY / UPTIME / EXTRA(max-events / timeout / output-dir / jq)。
查询时会主动剔除已不存活的 PID 条目(清理 kill -9 / 崩溃残留的僵尸记录)。
event stop:停止 consume 进程feishu-cli event stop --pid 12345 # 按 PID
feishu-cli event stop --event-key im.message.receive_v1 # 按 EventKey(所有订阅该 key 的进程)
feishu-cli event stop --all # 当前 AppID 下全部 consume
feishu-cli event stop --all --force # SIGKILL(紧急情况)
默认 SIGTERM 优雅退出(consume 进程会自动 unregister bus.json),等最多 3s 验证进程已退出;--force 升级为 SIGKILL,会留下 bus.json 僵尸条目,下次 event status 会自动清理。
完整列表用 feishu-cli event list。常用:
| Domain | EventKey | 描述 |
|---|---|---|
| im | im.message.receive_v1 | 接收消息(用户/群聊发给 Bot) |
| im | im.message.message_read_v1 | 消息已读回执 |
| im | im.message.recalled_v1 | 消息被撤回 |
| im | im.message.reaction.created_v1 / deleted_v1 | 消息表情回复添加/删除 |
| im | im.chat.updated_v1 | 群聊信息更新 |
| im | im.chat.member.user.added_v1 / deleted_v1 | 用户进群/离群 |
| im | im.chat.member.bot.added_v1 / deleted_v1 | Bot 被拉入/移出群 |
| im | im.chat.disbanded_v1 | 群聊被解散 |
| contact | contact.user.created_v3 / updated_v3 / deleted_v3 | 员工入职/变更/离职 |
| calendar | calendar.calendar.event.changed_v4 | 日程变更(创建/更新/删除) |
| calendar | calendar.calendar.acl.created_v4 | 日历权限变更 |
| drive | drive.file.title_updated_v1 | 文档标题修改 |
| drive | drive.file.permission_member_added_v1 | 文档协作者添加 |
| approval | approval_instance | 审批实例状态变更 |
| approval | approval_task | 审批任务变更 |
| vc | vc.meeting.meeting_started_v1 / meeting_ended_v1 | VC 会议开始/结束 |
EventKey 与 EventType 通常一致;接收到的 payload 里
header.event_type等于event_type字段。
auth login事件订阅走 App 身份(app_id + app_secret),不强制 user token。配好 ~/.feishu-cli/config.yaml 或 FEISHU_APP_ID / FEISHU_APP_SECRET 环境变量即可。
在 open.feishu.cn 你的应用控制台:
event schema <key> 输出的 Event Type 一致)并发布版本event schema <key> 的 Scopes 字段;在「权限管理」页面开通。event 域已加入 --domain event --recommend 推荐列表,可一次性申请 IM/contact/calendar/drive/approval/vc 常用 scope 并集| 现象 | 原因 | 解决 |
|---|---|---|
| WS 连接失败,stderr 报 ws error | 长连接模式未开启 | 飞书开放平台开启「事件订阅 - 长连接接收事件」 |
| 启动后看到 ready,但收不到事件 | 目标 EventType 未在「事件订阅」勾选 / 未发版本 | 重新勾选 + 发版 |
| 收到事件但 payload 字段缺失 | App 缺对应 scope(如 im:message.p2p_msg:readonly) | event schema <key> 看 Scopes,去权限管理页开通后重新订阅 |
| event consume 立即退出 reason=error | App ID/Secret 错 / 网络不通 / 域名走 lark 但 BaseURL 用了 feishu | 检查 config.yaml;lark 国际版需 --base-url https://open.larksuite.com 或对应配置 |
run_in_background=true)# 1. 后台启动 consume,stderr/stdout 各 redirect
task = Bash(
command='feishu-cli event consume im.message.receive_v1 --output-dir ./events 2> consume.log',
run_in_background=True,
)
# 2. tail consume.log 阻塞等 "[event] ready event_key=im.message.receive_v1"
# 3. 额外 sleep 1-3s 让 WS 握手完成
# 4. 业务逻辑:tail stdout / 读 ./events/*.json 处理新事件
# 5. 退出:feishu-cli event stop --event-key im.message.receive_v1
# 或父进程 kill 后台 Bash task(SIGTERM 触发 graceful shutdown + unregister)
非 TTY 模式下,关闭 stdin 即触发优雅退出(reason=signal)。Python subprocess.Popen 用 stdin=subprocess.PIPE,处理完后 p.stdin.close() 比 SIGTERM 更稳——consume 会跑完当前事件再退出。
调试场景永远先用 --max-events N --timeout Ds,避免忘了 stop 留下后台进程吃 API quota:
feishu-cli event consume im.message.receive_v1 --max-events 1 --timeout 30s
# 抓 1 条事件 demo / 30 秒超时双保险
event consume 阻塞运行直到信号/超时/EOF;不会自己退出。AI Agent 后台跑必须配 --max-events / --timeout 或显式 event stop,否则会留下长跑进程event consume 同时启动注册是安全的;但不要手动编辑 bus.jsonevent consume ... | head -1)会触发 SIGPIPE,consume 主动 cancel 退出 reason=signal,不会卡死等 Ctrl-C--quiet 不影响 ready marker:ready marker 走真实 os.Stderr 绕过 --quiet 重定向,所以 AI Agent 即使开 --quiet 父进程仍能等到 ready 行;但其他诊断(包括 [event] exited reason)会被静默WithAutoReconnect(true),断线后无限重试(间隔 2 分钟 + 首次抖动)。长时间断线场景建议用 --timeout 主动退出,由外层守护进程拉起,比内层无限 retry 更可控event status 用 signal(0) 探活,对 PID 复用场景理论可能误判(极小概率)。event stop --pid N 也是 syscall.Kill,命中错 PID 会 ESRCH 失败,不会误杀--output-dir 模式下每条事件落盘 <event_id>.json,短时间高频事件可能创建大量小文件;落盘只为留痕,业务消费仍推荐用 stdout NDJSON--jq 只支持点路径:--jq .event.message 把每条事件投影到子树后再输出;不命中的事件会被 skip(不输出空行)。复杂过滤永远走 pipe 外部 jq--output-dir 只支持安全相对路径:传 ~/events、/tmp/events、../events 都会报错;用 ./events 或 events/today| 任务 | 路由 |
|---|---|
| 发消息 / 回复 / 卡片 / 通知 | feishu-cli-msg |
| 构造 interactive 卡片 JSON | feishu-cli-card |
| 处理收到的消息事件 → 写多维表格 | feishu-cli-bitable(解析 payload 后调 record 命令) |
| 处理收到的审批事件 → 查审批详情 | feishu-cli-toolkit(approval 子命令) |
| 收到群消息后查群信息/成员 | feishu-cli-chat |
| Webhook URL 模式(HTTP 回调,非长连接) | 不在本技能范围;走飞书开放平台的「请求网址配置」+ 自建 HTTP server |
| 历史消息批量拉取(非实时) | feishu-cli-chat 的 msg history / msg list |
CHANGELOG.md event 模块 段落cmd/event*.go + internal/event/{bus,keys,runtime}.go--output-dir 启用时每条事件 dump 为 <event_id>.json。v1 PR 加 sanitizeEventID 防御:
[A-Za-z0-9_-] 字符,长度截到 128..、/、空格、特殊符号都被丢弃防御场景:服务端 payload 异常或恶意构造 header.event_id = "../etc/passwd" 类 payload 时,writeFile 不会逃出 --output-dir。
tools
往飞书文档里插入/更新/读取/删除「妙笔BOX」HTML 小组件块——飞书文档里**唯一能跑动画和可交互内容**的载体。 把一整页 HTML(CSS/JS)塞进块,在 iframe 沙箱里真实执行:CSS @keyframes 动画、ECharts/Three.js 图表、 Canvas、可拖拽力导向图、Dashboard、打字机/进度条/状态机动画等都能动。 当用户请求"飞书文档里做动画/能动的图/可交互图表/数据大屏/Dashboard/真实地图/地理飞线/3D 图表(map3D、3D 曲面、Three.js)/在飞书文档里放 ECharts 可视化/批量做一套图表演示"、"妙笔BOX"、"HTML 小组件"、 "在飞书文档里跑 ECharts/CSS 动画/JavaScript"、"嵌入网页/HTML 到飞书文档"、"飞书文档里的图怎么动起来"时使用。 注意:要"动"必须用本技能(妙笔BOX);画板(feishu-cli-board)的 SVG 节点会被服务端栅格化成静态图,不会动。
tools
飞书 OpenAPI 裸调。api GET/POST/PUT/DELETE/PATCH <path> 直接调用任意飞书 OpenAPI 接口, 覆盖 feishu-cli 尚未封装的接口(对齐 lark-cli 的 api 能力)。支持 --params(query)/--data(body JSON)/--data-file(从文件读 body)/ --as auto|user|bot 身份/--dry-run 预览/-o 二进制下载/--format/--jq。 当用户请求"调用 X API"、"裸调飞书接口"、"feishu-cli 没封装的接口怎么调"、"raw api"、 "用 api 命令发请求"、"下载飞书媒体/文件 binary"时使用。 不适用:仅查 schema 不调用(用 feishu-cli schema);已有专用命令的高频场景(用对应 feishu-cli <模块>)。
tools
飞书电子表格高级能力(筛选视图 + 筛选条件 + 下拉单元格 + 浮动图片 + 批量样式)。 filter-view CRUD 管理筛选视图,filter-view condition CRUD 写筛选条件(V3 API); dropdown set/get/update/delete 管理单元格下拉框(V2 dataValidation); image get/update/media-upload/write-image 操作浮动图片与单元格写图; batch-set-style 批量设置多范围单元格样式。 基础读写(read/write/style/add-rows/add-sheet)仍在 feishu-cli 主命令 sheet/bitable, 本 skill 专注高级能力。 当用户请求"筛选视图"、"筛选条件"、"加下拉框"、"数据验证"、"列下拉"、"浮动图片"、"插入图片"、"批量样式"时使用。
tools
飞书 OpenAPI 方法本地浏览 + 通用 API 透传调用。schema `service.resource.method` 三段式查路径/参数/scope(无需联网); `feishu-cli api <method> <path>` 直接调任意端点(v1.29+,覆盖 2500+ 未封装 API)。 当用户请求"飞书有没有 XX API"、"X API 的参数是什么"、"X 方法需要什么 scope"、 "OpenAPI 方法浏览"、"看 SDK 怎么调用"、"调一个没封装的飞书 API"时使用。 不适用:查在线最新 schema(请用 OpenAPI Explorer,本地元数据可能落后于飞书开放平台)。