skills/feishu-cli-msg/SKILL.md
飞书消息发送。发送消息(text/post/interactive 卡片等 10 种类型:text/post/image/file/audio/media/sticker/interactive/share_chat/share_user;system 分割线 CLI 暂未直接支持,需用 `feishu-cli api` 透传)、回复消息、 转发/合并转发、消息加急、消息书签(flag 收藏/list/cancel)、下载消息资源(图片/文件)。 发送/回复/转发/加急默认 App Token(Bot 身份);msg flag 收藏/书签必需 User Token(`im:feed.flag:read/write`); msg resource-download 已登录时优先 User Token,未登录回落 App Token。 当用户明确请求通过飞书即时消息/Bot 消息发送、回复、转发、合并转发、加急、消息收藏/书签、 下载消息图片或文件时使用。邮件走 feishu-cli-mail;文档评论/共享权限走对应 skill。 注意:Reaction/Pin/获取消息详情/批量获取消息/话题回复/消息历史/搜索群聊/群聊管理, 以及消息删除(默认 App Token 用于 Bot 自撤回,可选 User Token 让管理员撤回他人) 请使用 feishu-cli-chat 技能。 发送 interactive 卡片时,先用 feishu-cli-card 构造 v2 JSON, 再回到本技能用 --msg-type interactive --content-file 发送。
npx skillsauth add riba2534/feishu-cli feishu-cli-msgInstall 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 发送飞书消息、回复、转发、合并转发、加急和下载消息资源。
feishu-cli:如尚未安装,请前往 riba2534/feishu-cli 获取安装方式。
重要:CLI 路径 ≠ SKILL 归属。
feishu-cli msg下的子命令同时被两个 SKILL 分管,按动作类型划分,不按 CLI 路径划分。| 动作类型 | 子命令 | 归属 SKILL | | --- | --- | --- | | 发送类(本 SKILL 覆盖) |
send/reply/forward/merge-forward/urgent/flag/resource-download| feishu-cli-msg | | 读取类(请用 chat SKILL) |history/list/get/mget/thread-messages/search-chats/read-users/pins| feishu-cli-chat | | 互动类(请用 chat SKILL) |reaction/pin/unpin/delete| feishu-cli-chat |端到端拉一段时间窗的群消息(含话题展开、名字反解、卡片解析)直接跑:
python3 skills/feishu-cli-chat/scripts/fetch_chat_history.py oc_xxx --since 24h
飞书消息 API 的 content 字段是一个 JSON 字符串(不是 JSON 对象)。CLI 提供三种输入方式:
| 输入方式 | 参数 | 适用场景 |
|---------|------|---------|
| 快捷文本 | --text "内容" | 纯文本消息,最简单 |
| 发送文件 | --file <路径> 或 -f | 本地文件自动上传并发送(限 30MB) |
| 发送图片 | --image <路径> | 本地图片自动上传并发送(限 10MB) |
| 内联 JSON | --content '{"key":"val"}' 或 -c | 简单 JSON,一行搞定 |
| JSON 文件 | --content-file file.json | 复杂消息(卡片、富文本等) |
互斥:以上 5 种输入方式只能指定一个,同时指定会报错。
| --receive-id-type | 说明 | 示例 | |-------------------|------|------| | email | 邮箱地址 | [email protected] | | open_id | Open ID | ou_xxx | | user_id | User ID | xxx | | union_id | Union ID | on_xxx | | chat_id | 群聊 ID | oc_xxx |
默认优先使用 interactive(卡片消息),样式美观、内容丰富、支持颜色/多列/按钮等。
用户需求
├─ 【默认】通知/报告/告警/任何有信息量的消息 → interactive(卡片)
├─ 发送已上传的图片/文件/音视频 → image/file/audio/media
├─ 分享群聊或用户名片 → share_chat/share_user
└─ 仅以下场景才用 text/post:
├─ 用户明确要求发纯文本 → text
└─ 用户明确要求发富文本 → post
为什么优先卡片:text 不支持任何格式渲染,post 样式有限,卡片支持彩色 header、多列 fields、按钮、分割线、备注等,视觉效果远优于其他类型。
| 类型 | 说明 | content 格式 | 大小限制 |
|------|------|-------------|---------|
| text | 纯文本 | {"text":"内容"} | 150 KB |
| post | 富文本 | {"zh_cn":{"title":"","content":[[...]]}} | 150 KB |
| image | 图片 | {"image_key":"img_xxx"} | — |
| file | 文件 | {"file_key":"file_v2_xxx"} | — |
| audio | 语音 | {"file_key":"file_v2_xxx"} | — |
| media | 视频 | {"file_key":"...","image_key":"..."} | — |
| sticker | 表情包 | {"file_key":"file_v2_xxx"} | 仅转发 |
| interactive | 卡片 | Card JSON / template_id / card_id | 30 KB |
| share_chat | 群名片 | {"chat_id":"oc_xxx"} | — |
| share_user | 个人名片 | {"user_id":"ou_xxx"} | — |
system系统分割线(仅 p2p)CLI--msg-type白名单暂未收录(见cmd/send_message.go:261-266),需要时用feishu-cli api POST /open-apis/im/v1/messages直接透传。
本技能以发送类命令为主,默认使用 App Token(Bot 身份),无需登录。
msg flag 收藏/书签子命令(im:feed.flag:read/write),见末尾"消息书签"章节。msg resource-download 已登录时自动用 User Token 下载(要求你能看到该消息),未登录则尝试 App Token(要求 Bot 能看到该消息)。其他子命令(reaction/pin/delete/history/list/get/mget/thread-messages/search-chats)的 Token 策略见 feishu-cli-chat 技能。
feishu-cli msg send \
--receive-id-type <type> \
--receive-id <id> \
[--msg-type <msg_type>] \
[--text "<text>" | --file <path> | --image <path> | --content '<json>' | --content-file <file.json>]
# 直接发送本地文件(自动上传,限 30MB)
feishu-cli msg send \
--receive-id-type email \
--receive-id [email protected] \
--file /path/to/report.pdf
自动推断文件 MIME 类型(opus/mp4/pdf/doc/xls/ppt),未知类型使用 stream。超过 30MB 的文件请先用 file upload 上传到云空间,再用 --msg-type file --content '{"file_key":"..."}' 发送。
# 直接发送本地图片(自动上传,限 10MB)
feishu-cli msg send \
--receive-id-type chat_id \
--receive-id oc_xxx \
--image /path/to/screenshot.png
支持 JPEG、PNG、BMP、GIF、TIFF、WebP 格式。
# 最简形式(默认 msg-type 为 text)
feishu-cli msg send \
--receive-id-type email \
--receive-id [email protected] \
--text "你好,这是一条测试消息"
text 类型支持的内联 @ 语法:
@ 用户:<at user_id="ou_xxx">Tom</at> —— ou_xxx 必须是真实 open_id@ 所有人:<at user_id="all"></at>@ 机器人:与 @ 用户语法相同,把 ou_xxx 换成机器人 open_id 即可只能用 open_id:<at email="..."> 在 text 消息里不会触发 @ entity(飞书 IM 客户端会把邮箱字符串自动渲染成超链接,看起来像 @ 但没有通知、不是真的提及)。需要 @ 邮箱用户,先查 open_id:
# 第一步:查 open_id
feishu-cli user search --email [email protected] -o json
# 第二步:用真实 open_id @ 人
feishu-cli msg send --receive-id-type chat_id --receive-id oc_xxx \
--text '<at user_id="ou_xxx">Alice</at> 你好'
容错(仅 --text 模式):msg send / msg reply 在 --text 模式下会自动修正 AI 易写错的 @ 标签格式,下列写法都会被规范化为标准 <at user_id="...">:
<at id=ou_xxx>(缺引号 / 用 id 而非 user_id)<at open_id="ou_xxx"/>(自闭合 / 用 open_id)<at user_id=ou_xxx/>(自闭合无引号)--content / --content-file 模式不做隐式 normalize(用户自己写的 JSON 自己负责,避免破坏结构)。
注意:text 类型不支持富文本样式(加粗、斜体、下划线、删除线、超链接等均不会渲染)。如需格式排版,请使用 post 类型。
推荐使用 md 标签承载 Markdown,一个 md 标签独占一个段落:
cat > /tmp/msg.json << 'EOF'
{
"zh_cn": {
"title": "项目进展通知",
"content": [
[{"tag": "md", "text": "**本周进展**\n- 完成功能 A 开发\n- 修复 3 个 Bug\n- [查看详情](https://example.com)"}],
[{"tag": "md", "text": "**下周计划**\n1. 功能 B 开发\n2. 性能优化"}]
]
}
}
EOF
feishu-cli msg send \
--receive-id-type email \
--receive-id [email protected] \
--msg-type post \
--content-file /tmp/msg.json
post 支持的 tag 类型:
| tag | 说明 | 主要属性 | |-----|------|---------| | text | 文本 | text, style(bold/italic/underline/lineThrough) | | a | 超链接 | text, href | | at | @用户 | user_id, user_name | | img | 图片 | image_key, width, height | | media | 视频 | file_key, image_key | | emotion | 表情 | emoji_type | | hr | 分割线 | — | | code_block | 代码块 | language, text | | md | Markdown | text(独占段落,推荐使用) |
msg send 支持 --upload-images,扫描 post / interactive 消息中的 Markdown 图片语法 ,把 path 指向的本地图片自动上传到飞书 IM 图床、替换为 image_key,再发送。
| 维度 | 行为 |
| --- | --- |
| 触发条件 | 仅当 --msg-type post 或 --msg-type interactive 时生效(其他类型即使传也忽略,见 cmd/send_message.go:212) |
| 适用语法 | 内容里的  标记;URL(http/https)和已有 image_key 不会被改写 |
| 路径解析 | 相对路径:以 --content-file 所在目录为 basePath;用 --content 内联 JSON 时以当前工作目录为 basePath(见 cmd/send_message.go:213-220) |
| 失败回落 | 上传失败直接报错退出,不会继续发送残缺消息(避免 image_key 缺失被服务端拒绝) |
| 进度提示 | 上传 > 0 张时 stderr 打印 已自动上传 N 张本地图片 |
# post 内嵌本地图:自动上传相对路径 ./diagrams/foo.png
feishu-cli msg send --receive-id-type email --receive-id [email protected] \
--msg-type post --content-file /path/to/post.json --upload-images
# interactive 卡片内嵌本地图同理
feishu-cli msg send --receive-id-type chat_id --receive-id oc_xxx \
--msg-type interactive --content-file /tmp/card.json --upload-images
不需要预先调
feishu-cli media upload:本标志已包装了"上传 + 替换 + 发送"的全流程。需要把图片当作独立image消息发送,请直接用--image <path>快捷方式。
卡片消息有三种发送方式:
方式一:完整 Card JSON(仅发送;复杂卡片先用 feishu-cli-card 生成)
cat > /tmp/card.json << 'EOF'
{
"schema": "2.0",
"header": {
"template": "blue",
"title": {"tag": "plain_text", "content": "任务完成通知"}
},
"body": {
"direction": "vertical",
"elements": [
{"tag": "markdown", "content": "**项目**: feishu-cli\n**状态**: 已完成\n**负责人**: <at id=all></at>"}
]
}
}
EOF
feishu-cli msg send \
--receive-id-type email \
--receive-id [email protected] \
--msg-type interactive \
--content-file /tmp/card.json
方式二:template_id
cat > /tmp/card.json << 'EOF'
{
"type": "template",
"data": {
"template_id": "AAqk1xxxxxx",
"template_variable": {"name": "张三", "status": "已完成"}
}
}
EOF
feishu-cli msg send \
--receive-id-type email \
--receive-id [email protected] \
--msg-type interactive \
--content-file /tmp/card.json
方式三:card_id
feishu-cli msg send \
--receive-id-type email \
--receive-id [email protected] \
--msg-type interactive \
--content '{"type":"card","data":{"card_id":"7371713483664506900"}}'
本技能只负责发送 interactive 消息,不负责设计卡片 JSON。
[email protected](email),或从上下文获取feishu-cli-card 构造 JSON,再用 interactive 发送text / post--text;卡片 JSON 使用 --content-file;文件/图片使用 --file / --image| 权限 | 说明 |
|------|------|
| im:message | 消息读写(发送/回复/转发) |
| im:message:send_as_bot | 以机器人身份发送消息 |
| 限制 | 说明 |
|------|------|
| text 大小限制 | 单条最大 150 KB |
| 卡片/富文本大小限制 | 单条最大 30 KB |
| system 消息 | CLI --msg-type 暂不支持,仅 p2p 会话有效;需用 feishu-cli api 透传 |
| sticker 消息 | 仅支持转发收到的表情包,不支持自行上传 |
| 卡片按钮回调 | 按钮的交互回调需应用服务端支持,CLI 发送的按钮仅 url 跳转有效 |
| API 频率限制 | 请求过快返回 429,等待几秒后重试 |
| 删除消息 | 仅能删除机器人发送的消息 |
| 错误 | 原因 | 解决 |
|------|------|------|
| content format of a post type is incorrect | post 类型 JSON 格式错误 | 确保格式为 {"zh_cn":{"title":"","content":[[...]]}} |
| invalid receive_id | 接收者 ID 无效 | 检查 --receive-id-type 和 --receive-id 是否匹配 |
| bot has no permission | 机器人无权限 | 确认应用有 im:message:send_as_bot 权限 |
| rate limit exceeded | API 限流 | 等待几秒后重试 |
| user not found | 用户不存在 | 检查邮箱或 ID 是否正确 |
| card content too large | 卡片 JSON 超过 30 KB | 精简卡片内容或拆分为多条消息 |
| Bot/User can NOT be out of the chat | Bot 不在目标群内 | 添加 --user-access-token 切换为 User 身份重试 |
读消息详情和批量获取消息请使用 feishu-cli-chat 技能。
msg get/list/history/mget默认请求user_card_content并额外提取card_texts,该行为和排错说明维护在 chat skill 中,避免发送与读取职责混在一起。
下载消息中的图片或文件附件。
# 下载消息中的图片
feishu-cli msg resource-download <message_id> <file_key> --type image -o /tmp/photo.png
# 下载消息中的文件
feishu-cli msg resource-download <message_id> <file_key> --type file -o /tmp/attachment.pdf
# Bot 不可见但当前用户可见的历史消息资源,可显式用 User Token
feishu-cli msg resource-download <message_id> <file_key> --type file --user-access-token u-xxx -o /tmp/attachment.pdf
# 下载大文件时指定超时时间
feishu-cli msg resource-download <message_id> <file_key> --type file --user-access-token u-xxx -o /tmp/large.bin --timeout 30m
| 参数 | 说明 | 默认值 |
|------|------|--------|
| <message_id> | 消息 ID | 必填 |
| <file_key> | 资源的 file_key | 必填 |
| --type | 资源类型 image/file | 必填 |
| -o, --output | 输出文件路径 | — |
| --user-access-token | 使用用户身份下载用户可见、但 Bot 不可见的历史消息资源 | — |
| --timeout | 下载超时时间(Go duration 格式,如 10m、30m、1h) | 5m |
file_key 来源:通过
msg get <message_id>获取消息详情,从 content 中提取image_key或file_key。 使用用户身份直连下载时,如遇到飞书大文件限制,会自动使用 HTTP Range 分片下载并合并。
msg send 支持 --thread-id(等价于 --receive-id-type thread_id --receive-id <thread_id>):
# 在已有话题内追加一条消息
feishu-cli msg send --thread-id omt_xxx --text "话题内继续聊"
# 卡片消息也支持
feishu-cli msg send --thread-id omt_xxx \
--msg-type interactive \
--content "$(cat card.json)"
--thread-id与--receive-id-type/--receive-id互斥,只能指定一组。
msg reply 支持 --reply-in-thread(reply_in_thread=true):
# 在非话题群聊中,以话题形式回复某条消息(会开启一个新话题)
feishu-cli msg reply om_xxx --text "这里开个话题" --reply-in-thread
# 若群聊已是话题模式,--reply-in-thread 会自动回复到消息所在话题
获取话题回复属于读取消息,请使用 feishu-cli-chat 技能。发送话题内消息仍使用本技能的 msg send --thread-id。
references/message_content.md:各消息类型的 content JSON 结构详解references/card_schema.md:interactive 发送格式与历史卡片排障;新增卡片构造优先用 feishu-cli-card服务端称 message flag,用于把消息加 Feed 标记,把消息推上用户 Feed/书签。
对应 HTTP API POST/GET/PATCH /open-apis/im/v1/flags。需 User Access Token:list 需要 im:feed.flag:read,create/cancel 需要 im:feed.flag:write。
feishu-cli msg flag create <message_id> — 创建消息层书签(默认 --item-type default --flag-type message)feishu-cli msg flag create <message_id> --flag-type feed — feed 层书签,自动读取 chat_mode 判断 thread / msg_threadfeishu-cli msg flag create <message_id> --item-type msg_thread --flag-type feed — feed 层书签(显式指定普通群线程)feishu-cli msg flag list [--page-size 50] [--page-token xxx] — 列当前用户的书签feishu-cli msg flag cancel <message_id> [--item-type ... --flag-type ...] — 默认尽量取消消息层 + feed 层;显式传 item/flag 时只取消指定层CLI flag 用字符串,底层映射到 OpenAPI 整数枚举:
| 字段 | CLI 字符串 | OpenAPI 整数 | 含义 | | --- | --- | --- | --- | | --item-type | default | 0 | 普通消息 | | --item-type | thread | 4 | topic-style 话题群 | | --item-type | msg_thread | 11 | 普通群消息线程 | | --flag-type | message | 2 | 消息层书签(默认) | | --flag-type | feed | 1 | feed 层(侧边栏书签) |
⚠️ 反向陷阱:网上某些第三方教程(含部分 lark-cli 旧版示例)把
flag_type: 1=message / 2=feed写反了。本项目以飞书 OpenAPI 官方真值为准(1=feed / 2=message,见上表)。list命令输出里也是这套真值,写代码处理 JSON 时认上面这张表。
list命令不接受--flag-type/--item-type作为入参(list 是全量返回),只能在输出flag_items[*].flag_type字段上过滤。要看自己有哪些书签直接feishu-cli msg flag list -o json。
支持的组合(其余服务端拒绝):
default + message:消息层书签,最常见thread + feed:topic-style 话题群 feed 层msg_thread + feed:普通群消息线程 feed 层源码引用:internal/client/flag.go:23-28(本仓库权威,对齐 lark-cli shortcuts/im 的 ItemType/FlagType 定义)。
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,本地元数据可能落后于飞书开放平台)。