lark-event

Lark/Feishu real-time event listening / subscribing / consuming: stream events as NDJSON via `lark-cli event consume ` (covers IM messages/reactions/chat changes, VC meeting ended, Minutes generated, etc.). Use for Lark bots, real-time message processing, long-running subscribers, streaming webhook/push handlers. Supports `--max-events` / `--timeout` bounded runs and a stderr ready-marker contract — designed for AI agents running as subprocesses.

npx skills add https://github.com/larksuite/cli --skill lark-event

Lark Events

Prerequisite: Read ../lark-shared/SKILL.md first for authentication, --as user/bot switching, Permission denied handling, and safety rules.

Core commands

CommandPurpose
lark-cli event list [--json]List all subscribable EventKeys
lark-cli event schema <EventKey> [--json]Show an EventKey's params and output schema
lark-cli event consume <EventKey> [flags]Blocking consume; events → stdout NDJSON
lark-cli event status [--json] [--fail-on-orphan]Inspect the local bus daemon status
lark-cli event stop [--all] [--force]Stop the bus daemon

Common flags

FlagDescription
--param key=value / -pBusiness params (repeatable; comma-separated for multi-value). Unknown keys fail with valid names listed inline
--jq <expr>jq expression to filter / transform each event; empty output skips the event
--max-events NExit after N events. Default 0 = unlimited
--timeout DExit after duration D (e.g. 30s, 2m). Default 0 = no timeout. Whichever of --max-events / --timeout fires first wins
--output-dir <dir>Write each event as a file (relative paths only; prevents traversal)
--quietSuppress stderr diagnostics. AI should not use this — it silences the ready marker
--as user|bot|autoIdentity for the session (see lark-shared)

Examples

# Default: stream every event for the key (no filter, no projection)
lark-cli event consume im.message.receive_v1 --as bot

# Grab one sample event to inspect payload shape
lark-cli event consume im.message.receive_v1 --max-events 1 --timeout 30s --as bot

# Run for 10 minutes then auto-exit
lark-cli event consume im.message.receive_v1 --timeout 10m --as bot

# Consume multiple EventKeys concurrently (one shape per process, no dispatcher)
lark-cli event consume im.message.receive_v1          --as bot > receive.ndjson &
lark-cli event consume im.message.reaction.created_v1 --as bot > reaction.ndjson &
wait

Call flow

  1. lark-cli event list --json → pick a legal key
  2. lark-cli event schema <key> --json → read resolved_output_schema + jq_root_path to determine field paths
  3. lark-cli event consume <key> [--jq '<expr>'] → consume

Subprocess contract

Ready marker

event consume's stderr emits a fixed line [event] ready event_key=<key>. Parent processes should block on stderr until this line appears, then start reading stdout. Do not fall back to sleep.

stdin EOF = graceful exit

event consume treats stdin close as a shutdown signal (wired for AI subprocess callers). Bounded runs are exempt: when --max-events or --timeout is set (> 0), stdin EOF is ignored and the run exits only via its own bound, timeout, or SIGTERM. For unbounded runs, < /dev/null / nohup / systemd's default StandardInput=null will cause an immediate graceful exit (stderr reason: signal). To keep an unbounded run alive:

  • Feed stdin a source that never EOFs: < <(tail -f /dev/null)
  • Or run bounded: --max-events N / --timeout D

Exit codes & reason

On exit, the last stderr line is [event] exited — received N event(s) in Xs (reason: ...).

exit codereasonTrigger
0reason: limit--max-events reached
0reason: timeout--timeout reached
0reason: signalCtrl+C / SIGTERM / stdin EOF (stdin EOF applies to unbounded runs only)
1JSON error envelope on stderrLark API business failure during pre-consume setup (for example subscription create/delete)
2JSON error envelope on stderr (no exited line)Validation failure (unknown EventKey, bad --param / --jq, another bus already connected)
3JSON error envelope on stderrAuth failure (missing token, missing scopes)
4 / 5JSON error envelope on stderrNetwork / internal failure (bus startup, handshake, file I/O)

Startup and runtime failures emit a structured JSON envelope on stderr: {"ok":false,"error":{"type","subtype","param","message","hint",...}} (the envelope may also carry top-level identity / _notice siblings). Parse error.type / error.subtype to branch (e.g. missing_scope carries a missing_scopes list), error.param to find the offending flag, and error.hint for the recovery action — do not regex-match message text.

Orchestrators should treat reason: limit/timeout/signal (all exit 0) as "business completion" and non-zero as "failure".

Never kill -9

Avoid kill -9 on consume processes: for EventKeys with a PreConsume hook (those that register server-side subscriptions via OAPI), kill -9 skips the OAPI unsubscribe and leaks server-side subscriptions (symptoms: "subscription already exists" on restart, duplicate event delivery). Prefer SIGTERM or closing stdin.

One consume, one EventKey (multi-key = multi-shell)

The command takes exactly one positional argument; k1,k2 and wildcards are unsupported. Listening to N keys means N subprocesses — this is intentional:

  • One shape per process stdout; no dispatcher logic required in the AI
  • Fault isolation (one key failing doesn't affect others)
  • Independent --as / --jq / --max-events / --timeout per key

All N consumers share a single bus daemon (UDS local IPC), so the overhead is small

Writing jq via schema

event schema <key> --json is the source of truth for writing --jq. Four things to look at:

(1) Where fields start — see jq_root_path

  • Value "." → fields are at the top level, write .chat_id
  • Value ".event" → fields are inside a V2 envelope, write .event.chat_id

(2) Field list and types — see resolved_output_schema.properties.<name>

Each field carries type / description, and some also have format. Snippet (from event schema im.message.receive_v1 --json):

{
  "chat_id":     {"type":"string", "format":"chat_id",      "description":"Chat ID, prefixed with oc_"},
  "sender_id":   {"type":"string", "format":"open_id",      "description":"Sender open_id, prefixed with ou_"},
  "create_time": {"type":"string", "format":"timestamp_ms", "description":"Send time as ms-epoch string"}
}

(3) Field semantics — see the format tag

Lark-defined semantic tags (not JSON Schema's standard format). Common values: open_id / chat_id / message_id / timestamp_ms / email. Purpose: distinguish "same string type, different meanings" fields so you can reverse-lookup via API or convert formats.

(4) Decoded state — read the field's description

event consume runs Process hooks that may pre-decode some payload fields (flattening V2 envelopes, rendering .content to plain text, etc.) — behavior differs from raw OAPI. Always read the field's description before writing jq, especially for generic field names like content / data / body / payload.

Why it matters: blindly applying fromjson to an already-decoded text field makes jq error on every event and silently drop it — the consumer looks alive but emits nothing, with only a single WARN line buried on stderr. (This is the general behavior: any jq runtime error skips the event with a one-line WARN; the loop does not abort.)

Don't shortcut the schema: when projecting event schema --json with jq, do not strip .description from properties — that's the field that tells you whether a field is already decoded. Dump the full property objects, not just keys.


Aside: --param's valid parameters also live in the schema — the params section lists name / type / required / enum / default / description; section missing = this key accepts no --param.

Topic index

TopicReferenceCoverage
IMreferences/lark-event-im.mdCatalog of 11 IM EventKeys + shape notes (flat vs V2 envelope) + im.message.receive_v1 field gotchas (sender_id is open_id only; .content is plain text except for interactive cards) + common jq recipes (filter by chat_type / message_type / sender)
VCreferences/lark-event-vc.mdCatalog of 2 VC EventKeys (vc.meeting.participant_meeting_ended_v1, vc.note.generated_v1) + field reference + source type semantics (meeting only)
Minutesreferences/lark-event-minutes.mdCatalog of 1 Minutes EventKey (minutes.minute.generated_v1) + field reference + source type semantics (meeting only)
Whiteboardreferences/lark-event-whiteboard.mdCatalog of 1 Board EventKey (board.whiteboard.updated_v1) + per-whiteboard subscription model (requires -p whiteboard_id=<token>) + payload field reference (whiteboard_id / operator_ids triple-id)

More skills from larksuite

lark-doc
larksuite
飞书云文档 / Docx / 知识库 Wiki 文档(v2):创建、打开、读取、获取、查看、总结、整理、改写、翻译、审阅和编辑飞书文档内容。当用户给出飞书文档 URL/token,或说查看/读取/打开某个文档、提取文档内容、总结文档、生成/创建文档、追加/替换/删除/移动内容、调整排版、插入或下载文档图片/附件/素材/画板缩略图时使用。文档内容中出现嵌入电子表格、多维表格、需要将重要信息可视化为画板(含 SVG 画板)、引用或同步块时,也先用本 skill 读取和提取 token,再切到对应 skill 下钻。使用本 skill 时,docs +create、docs +fetch、docs +update 必须携带 --api-version v2;默认使用 DocxXML,也支持 Markdown。
documentapiproductivity
lark-im
larksuite
飞书即时通讯:收发消息和管理群聊。发送和回复消息、搜索聊天记录、管理群聊成员、上传下载图片和文件(支持大文件分片下载)、管理表情回复。当用户需要发消息、查看或搜索聊天记录、下载聊天中的文件、查看群成员、搜索群、创建群聊或话题群、管理标记数据时使用。
communicationproductivityapi
lark-shared
larksuite
Use when first setting up lark-cli, running auth login, switching user/bot identity (--as), handling permission denied or scope errors, needing to update lark-cli, or seeing _notice in JSON output.
developmentapicommunication
lark-base
larksuite
当需要用 lark-cli 操作飞书多维表格(Base)时调用:搜索 Base、建表、字段管理、记录读写、记录分享链接、视图配置、历史查询,以及角色/表单/仪表盘管理/工作流;也适用于把旧的 +table / +field / +record 写法改成当前命令写法。涉及字段设计、公式字段、查找引用、跨表计算、行级派生指标、数据分析需求时也必须使用本 skill。
databasedata-analysisapi
lark-drive
larksuite
飞书云空间:管理云空间中的文件和文件夹。上传和下载文件、创建文件夹、复制/移动/删除文件、查看文件元数据、管理文档评论、管理文档权限、订阅用户评论变更事件、修改文件标题(docx、sheet、bitable、file、folder、wiki);也负责把本地 Word/Markdown/Excel/CSV 以及 Base 快照(.base)导入为飞书在线云文档(docx、sheet、bitable)。当用户需要上传或下载文件、整理云空间目录、查看文件详情、管理评论、管理文档权限、修改文件标题、订阅用户评论变更事件,或要把本地文件导入成新版文档、电子表格、多维表格/Base 时使用。
documentproductivityapi
lark-whiteboard
larksuite
飞书画板:查询和编辑飞书云文档中的画板。支持导出画板为预览图片、导出原始节点结构、使用多种格式更新画板内容。 当用户需要查看画板内容、导出画板图片、编辑画板时使用此 skill。不负责:飞书云文档内容编辑(lark-doc)、文档内嵌电子表格/Base(lark-sheets / lark-base)。
documentcreativeproductivity
lark-mail
larksuite
飞书邮箱 — draft, compose, send, reply, forward, read, and search emails; manage drafts, folders, labels, contacts, attachments, and mail rules. Use when user mentions 起草邮件, 写一封邮件, 拟邮件, 草稿, 发通知邮件, 发送邮件, 发邮件, 回复邮件, 转发邮件, 查看邮件, 看邮件, 读邮件, 搜索邮件, 查邮件, 收件箱, 邮件会话, 编辑草稿, 管理草稿, 下载附件, 邮件文件夹, 邮件标签, 邮件联系人, 监听新邮件, 收信规则, 邮件规则, draft, compose, send email, reply, forward, inbox, mail thread, mail rules.
communicationproductivityapi
lark-workflow-meeting-summary
larksuite
会议纪要整理工作流:汇总指定时间范围内的会议纪要并生成结构化报告。当用户需要整理会议纪要、生成会议周报、回顾一段时间内的会议内容时使用。
productivitydocumentcommunication