mcpField
F
feishu-cli-event

feishu-cli-event

github.com/riba2534開発1.4k154 回インストール3 週間前に更新
リポジトリ

feishu-cli-event について

feishu-cli-eventは、Feishu Open PlatformのイベントをWebSocketで購読するコマンドラインスキルです。イベントをリアルタイム処理するAIエージェント向けに、NDJSON出力と購読プロセスの管理機能を備えています。

主な機能

  1. 01WebSocket経由のリアルタイムイベント受信
  2. 02NDJSON形式でのイベント出力
  3. 03イベントキー一覧とペイロードスキーマの確認
  4. 04イベント数または時間による購読制限
  5. 05購読中プロセスの確認と停止

活用シーン

  1. 01Botが受信するユーザーやグループのメッセージ監視
  2. 02承認・カレンダー・ドライブイベントの処理
  3. 03イベントストリームのスクリプトやAIエージェントへの転送

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/riba2534/feishu-cli --skill feishu-cli-event

インストール後、Claude Code で/feishu-cli-eventを入力して読み込まれたか確認します。

詳細

飞书实时事件订阅技能(WebSocket)

通过 feishu-cli event 子命令族订阅飞书开放平台事件,使用 WebSocket 长连接接收事件并以 NDJSON 输出到 stdout,适合 AI Agent 做 bot 实时响应、群消息监听、审批回调消费等场景。

feishu-cli:如尚未安装,请前往 riba2534/feishu-cli 获取安装方式。

发消息? 请使用 feishu-cli-msg 技能。本技能专注于事件订阅(接收应用事件),不负责发送。

核心概念

进程模型 = 1 个 EventKey 1 个 consume 进程
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.lockflock 文件锁;bus.json 读写串行化,fd 关闭自动释放

每个 AppID 一个子目录,不同应用互不干扰。event status 查询会主动剔除已不存活的 PID 条目(kill -9 / 崩溃残留)。bus.json 用 tmp + rename 原子写,防半写。

输出协议(NDJSON + ready marker)
流内容
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 回环来确认链路通。

退出码与退出 reason
退出码含义
0正常退出(达到 --max-events / --timeout / SIGTERM / Ctrl-C / stdin EOF)
非 0startup 失败 / WebSocket 不可恢复错误 / 参数错误

stderr 末尾会输出 [event] exited — elapsed=<d> reason=<r>,reason 有 4 个:

  • limit — 达到 --max-events
  • timeout — 达到 --timeout
  • signal — 上下文取消(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
1. 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。

2. event schema:看 payload schema 与 scope
feishu-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 以飞书开放平台文档为准。

3. 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 N0(不限制)接收 N 条事件后退出,reason=limit
--timeout <duration>(示例 60s)0(不限制)运行 D 时长后退出,reason=timeout
--jq .event.xxx""极简点路径过滤,不支持完整 jq 语法(用 pipe 接外部 jq)
--output-dir ./events""每条事件额外 dump 为 <event_id>.json 落盘(不影响 stdout)
--quietfalse抑制 stderr 诊断;AI Agent 慎用——会一起抑制大部分 stderr,但 ready marker 仍走真实 os.Stderr 不受影响

--jq 限制:只识别 .a.b.c 形式的 map 取值(如 .event.message),不支持 select / 数组下标 / 管道。复杂过滤请用 feishu-cli event consume ... | jq '<expr>'。

--output-dir 限制:必须是安全相对路径;不做 ~ 展开,不接受绝对路径或 .. 路径段。

4. 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 / 崩溃残留的僵尸记录)。

5. 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 会自动清理。

EventKey クイックリファレンス(domain 別)

完全な一覧は feishu-cli event list で確認できます。よく使うもの:

DomainEventKey説明
imim.message.receive_v1メッセージを受信(ユーザー/グループチャットから Bot への送信)
imim.message.message_read_v1メッセージの既読レシート
imim.message.recalled_v1メッセージの取り消し
imim.message.reaction.created_v1 / deleted_v1メッセージへのリアクションの追加/削除
imim.chat.updated_v1グループチャット情報の更新
imim.chat.member.user.added_v1 / deleted_v1ユーザーのグループへの参加/退出
imim.chat.member.bot.added_v1 / deleted_v1Bot のグループへの追加/グループからの削除
imim.chat.disbanded_v1グループチャットの解散
contactcontact.user.created_v3 / updated_v3 / deleted_v3従業員の入社/変更/退職
calendarcalendar.calendar.event.changed_v4予定の変更(作成/更新/削除)
calendarcalendar.calendar.acl.created_v4カレンダー権限の変更
drivedrive.file.title_updated_v1ドキュメントタイトルの変更
drivedrive.file.permission_member_added_v1ドキュメントへの共同編集者の追加
approvalapproval_instance承認インスタンスの状態変更
approvalapproval_task承認タスクの変更
vcvc.meeting.meeting_started_v1 / meeting_ended_v1VC 会議の開始/終了

EventKey と EventType は通常一致します。受信した payload の header.event_type は event_type フィールドと同じです。

権限とオープンプラットフォームの設定

デフォルトの App Token を使用するため、auth login は不要です

イベントの購読には App ID(app_id + app_secret)を使用するため、user token は必須ではありません。~/.feishu-cli/config.yaml を設定するか、環境変数 FEISHU_APP_ID / FEISHU_APP_SECRET を設定してください。

Feishu オープンプラットフォームでの 2 段階設定

open.feishu.cn のアプリコンソールで設定します。

  1. 「イベント購読 - 長時間接続でイベントを受信」で長時間接続モードを有効にします(feishu-cli は WebSocket を使用します。webhook URL モードではありません)
  2. **「イベントとコールバック - イベント購読」**で対象の EventType(event schema <key> の出力にある Event Type と同じ)を選択し、バージョンを公開します
  3. scope の有効化:各 EventKey に必要な scope は event schema <key> の Scopes フィールドで確認できます。「権限管理」ページで有効にします。event domain は --domain event --recommend の推奨リストに追加されているため、IM/contact/calendar/drive/approval/vc でよく使う scope の和集合をまとめて申請できます
よくあるエラー
現象原因解決方法
WS 接続に失敗し、stderr に ws error が表示される長時間接続モードが有効になっていないFeishu オープンプラットフォームで「イベント購読 - 長時間接続でイベントを受信」を有効にします
起動後に 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 または対応する設定が必要です

AI Agent のバックグラウンド購読におすすめの使い方

単一 EventKey のバックグラウンド購読(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)
子プロセスの stdin EOF プロトコル(非 TTY)

非 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 秒超时双保险

注意点と落とし穴

  • daemon プロセスは常駐します:event consume はシグナル/タイムアウト/EOF を受け取るまでブロッキング実行され、自動では終了しません。AI Agent のバックグラウンド実行では --max-events / --timeout を指定するか、明示的に event stop を実行してください。指定しないと長時間実行されるプロセスが残ります
  • flock によるプロセス間排他制御:bus.json の読み書きには flock を使用するため、複数の event consume を同時に起動して登録しても安全です。ただし、bus.json を手動で編集しないでください
  • pipe broken で自動終了:下流の jq / tee が stdout を閉じると(典型例:event consume ... | head -1)、SIGPIPE が発生し、consume は reason=signal で自発的に終了します。Ctrl-C を待ったまま停止しなくなることはありません
  • --quiet でも ready marker は出力されます:ready marker は実際の os.Stderr を使用し、--quiet によるリダイレクトを回避するため、AI Agent が --quiet を指定していても親プロセスは ready 行を待つことができます。ただし、[event] exited reason を含むその他の診断情報は表示されません
  • AutoReconnect は無限に再試行します:oapi-sdk-go v3 ws.Client はデフォルトで WithAutoReconnect(true) を使用し、切断後も無限に再試行します(間隔は 2 分、初回はジッターあり)。長時間の切断が想定される場合は、--timeout で明示的に終了させ、外部の監視プロセスから再起動する方法をおすすめします。内部で無限に retry するよりも制御しやすくなります
  • status はプロセスに対して能動的に ping しません:event status は signal(0) で生存確認を行います。PID が再利用された場合、理論上は誤判定する可能性があります(確率は極めて低いです)。event stop --pid N も syscall.Kill を使用するため、誤った PID に対しては ESRCH で失敗し、誤って別のプロセスを終了させることはありません
  • イベントごとに個別のファイルを作成します:--output-dir モードでは各イベントが <event_id>.json として保存されます。短時間にイベントが頻発すると、小さなファイルが大量に作成される可能性があります。ファイルへの保存は記録用であり、実際のイベント処理には stdout NDJSON の使用をおすすめします
  • --jq がサポートするのはドットパスのみです:--jq .event.message は各イベントをサブツリーに射影してから出力します。一致しないイベントはスキップされ(空行は出力されません)、複雑なフィルタリングには外部の jq を pipe で使用してください
  • --output-dir がサポートするのは安全な相対パスのみです:~/events、/tmp/events、../events を指定するとエラーになります。./events または events/today を使用してください

何时转其他 skill

任务路由
发消息 / 回复 / 卡片 / 通知feishu-cli-msg
构造 interactive 卡片 JSONfeishu-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

参考

安全 — event_id 文件名净化

--output-dir 启用时每条事件 dump 为 <event_id>.json。v1 PR 加 sanitizeEventID 防御:

  • 只保留 [A-Za-z0-9_-] 字符,长度截到 128
  • ..、/、空格、特殊符号都被丢弃
  • 净化后空串 → 跳过 dump(不写空文件名文件)

防御场景:服务端 payload 异常或恶意构造 header.event_id = "../etc/passwd" 类 payload 时,writeFile 不会逃出 --output-dir。

コメント