| name | feishu-sticker-pack |
| description | 基于飞书/Lark 头像生成一套可直接添加到飞书表情面板的自定义表情包(透明底 PNG),并按使用频次挑选表情语义。工作流:读取目标用户近一个月在飞书里实际点过的表情回应(reaction)作为高频语义来源,不足时用飞书标准常用表情兜底,让用户从 6 种画风中选一种,生成透明底方形 PNG,逐张发送到用户与自己的飞书单聊,由用户右键「添加表情」完成落库。适用触发:用户要求做飞书表情包 / 自定义表情 / sticker / emoji 表情、把头像做成表情、生成飞书能用的表情、做一套团队成员表情包、按我常用表情做表情包。默认目标是当前用户本人,其头像可自动获取;指定他人时飞书 API 不返回他人头像,必须由用户主动提供头像图片,且需提醒取得对方同意。硬依赖飞书 CLI(@larksuite/cli),未安装时先引导安装并完成扫码授权。不负责企业专属表情包上架(需管理后台与旗舰版权限),也不负责飞书 sticker 消息图片的读取(API 不提供)。 |
飞书自定义表情包生成
把一张飞书头像变成一套「飞书里真的能用」的自定义表情。
能力边界(先读,避免许下做不到的承诺)
飞书没有写入自定义表情面板的开放 API。开放平台只允许发送机器人已收到的 sticker,file_key 无法凭空创建;企业专属表情包必须由管理员在管理后台上架,且要求认证旗舰版。
因此最后一步必须由用户手动完成。本 skill 的职责是把手动成本压到「右键点几下」:
- 能做:读取真实使用频次、生成透明底 PNG、逐张送达用户飞书会话、打包供批量导入
- 不能做:代替用户写入表情面板、读取历史 sticker 消息的图片内容(API 返回脱敏的
[Sticker])、上架企业表情包、获取他人头像(API 不提供,须用户主动提供图片)
向用户交代这条边界,不要让用户误以为表情会自动出现在面板里。
前置:飞书 CLI
本 skill 硬依赖飞书 CLI。命令名在不同环境可能是 lark-cli 或 lark,先探测:
command -v lark-cli || command -v lark || echo "feishu cli missing"
未安装或未授权时按 references/setup-feishu-cli.md 完成安装与登录,再继续。不要因为 CLI 缺失就改用搜索、网页或猜测数据绕过——本 skill 的价值全部建立在真实飞书数据上。
后文统一写作 lark-cli,实际执行时替换为探测到的命令名。
工作流总览
- 确定目标人物 → 本人头像自动取;他人头像请用户提供
- 采集近一个月的高频表情语义(reaction 频次),不足则用标准常用表情兜底
- 让用户从 6 种画风中选一种
- 生成核心角色定妆稿(锁定身份锚点)
- 基于定妆稿逐张生成表情,透明底
- 处理成飞书规格(PNG / 方形 / 100KB 内)
- 逐张发送到用户与自己的飞书单聊 + 打包 zip
- 告知用户右键「添加表情」
Step 1:目标人物与头像
默认目标是当前用户本人,这也是唯一能自动取到头像的情况:
lark-cli contact +get-user --as user --json
curl -sL -o avatar.jpg "<avatar_big>"
avatar_big 是 640×640 原图。这条命令在省略 --user-id 时走 authen/v1/user_info,只对当前认证用户有效。
指定他人时:头像必须由用户提供
飞书 API 不提供他人头像。 这不是权限配置问题,是接口设计——详见 references/setup-feishu-cli.md 的「他人头像为何取不到」。不要浪费轮次去试各种 contact / im 接口,七条路径都已验证过。
正确做法:
- 用
+search-user --query "姓名" --as user 解析 open_id,确认人找对了(命中多条时列候选让用户挑,不要擅自选第一条)
- 请用户提供该同事的头像图片——飞书里点开对方头像可保存原图,或直接截图
- 提醒用户取得对方同意。给同事做表情包涉及肖像使用,尤其是上级或客户,先确认对方知情
- 用户不提供图片时,如实说明缺口并停在这里,不要用相似的人脸或搜索结果凑
lark-cli contact +search-user --query "张三" --as user --json
看过头像再决定画风
必须实际看一眼头像:是真人照片还是已经卡通化、是否戴眼镜、有无标志性服装配色、分辨率是否够用。头像太小、严重遮挡或多人合影时,请用户换一张清晰正脸图。
多人批量
给团队多人各做一套时,逐人串行走完 Step 4–6(每人独立的 core-ip),产物按人分目录。
他人的 reaction 频次同样取不到(+chat-messages-list 只返回当前用户可见会话里的 reaction,覆盖不了对方的完整使用习惯),直接用标准常用表情骨架,不要谎称是那个人的真实习惯。
送达仍然发到当前用户自己的单聊,由用户自行转发给同事;不要直接发到同事会话去打扰对方。
Step 2:采集高频表情语义
时间窗固定为近一个月。更长的窗口不会提升准确度,只会拖慢采集并混入过期习惯。
运行采集脚本:
python3 scripts/collect_reactions.py --open-id <ou_xxx> --days 30 --cli lark-cli
脚本用线程池并发遍历用户可见会话,统计目标 open_id 作为 operator 的 reaction 频次。会话数常达 200+,实测并发 8 路约需 5–8 分钟。用后台任务运行并向用户说明在等什么,不要让前台命令超时掐断。
想先快速验证链路时用 --max-chats 40 跑个子集,约 1 分钟出结果。--workers 默认 8,调高可能触发限流。
频次数据的解读纪律
真实数据往往高度集中——竖拇指常占七成以上,其余表情各 1–2 次。不要把频次直接当成表情清单:
默认产出 9 个。用户明确要更多时,上限参考可迁移语义的实际数量:飞书内置约 185 个 emoji_type,但其中大量是物件与状态图标(炸弹、菜刀、月饼、出差、居家办公),没有人物可换;真正能做成人物表情的约三四十个。向用户说清这个上限,不要承诺 185 张。
把最终 9 个语义连同各自的频次呈现给用户确认,让用户看到「这套表情来自我的真实习惯」。
Step 3:画风选择
生成前让用户从 6 种画风里选一种。默认选项 1(沿用头像原本的质感,一致性最高、返工最少)。
选项清单与各自的 prompt 关键描述见 references/art-styles.md。用简短选择题提问,不要把 6 段完整描述糊给用户。
Step 4:核心角色定妆稿
这一步不能跳。 逐张独立生成会让人脸漂移,必须先固定一个身份锚点,后续每张都以它为参考图。
用图生图工具(image_edit 或宿主环境等价能力),以头像为参考图,生成一张:
- Q 版三头身比例,头部约占身高三分之一
- 正面居中、自然直立、双手垂放、轻松微笑
- 纯白背景,角色四周留均匀空白
- 画面无任何文字
prompt 必须逐项写出要保留的身份锚点:发型、眼镜款式、眼睛特征、五官气质、肤色、服装颜色与款式、领带、胸针等标志配饰。写"保持一致"是无效指令。
禁止项集中写在末尾:写实人体比例、原图背景、原图里的次要人物、多余人物、背景阴影、任何文字、水印、边框。
生成结果的 CDN URL 即为 core-ip,记录下来。后续所有表情都必须传入这个 URL,不许改用文生图重画。
Step 5:逐张生成表情
以 core-ip 为唯一参考图,为每个语义写一条独立 prompt。可批量并发调用,但每条 prompt 必须完整独立。
每条 prompt 的固定结构:
- 锚点复述:保持完全相同的三头身比例、脸部结构、眼镜、发型、服装配色、标志配饰、渲染质感
- 只改动作与表情:手部姿势写到手指级别(哪只手、抬到什么高度、哪几根手指、朝向);面部写到眼型嘴型(眼睛弯成什么形状、嘴巴张开什么轮廓、眉毛走向);头部与身体的倾斜方向
- 符号元素:需要时加立体小符号(爱心、碎纸片、动态弧线、泪滴),写清颜色、数量、排列轨迹、相对位置
- 背景约束:纯白背景、角色居中、四周均匀空白
- 文字约束:绝大多数表情写"画面不出现任何文字";只有语义本身是文字时(如 100 分)才允许,且必须用中文双引号逐字写出,并禁止其他文字
- 禁止项:改变脸型或服装、写实比例、背景色块、任何文字、水印、边框、额外人物
各语义的具体动作设计见 references/expression-designs.md。
构图一致性
带大符号的表情(数字、大图标)容易破坏整套的构图统一——角色被挤到一边、缩到 32px 后看不清。让符号做小角标、角色保持居中占主体。
写实质感撑不起夸张表情。「瞥」「无语」这类依赖夸张的语义,在 3D 写实风格下缩到小图会读不出情绪,需要刻意画得比直觉更夸张。
Step 6:处理成飞书规格
python3 scripts/make_stickers.py --src raw --dst out
脚本做四件事:从画布边缘 flood fill 抠白底(保护角色内部的白衬衫等白色区域)、按 alpha 裁到主体外框、等比缩放居中放入透明方形画布、控制在 100KB 以内。
飞书自定义表情要求 PNG 格式、不超过 100KB。脚本默认输出 320×320。
必须抽查处理结果:读 1–2 张输出图,确认边缘干净、脚下投影没残留、主体没被裁切。生成图脚下常有浅灰投影(RGB 约 224),默认容差 46 覆盖;若残留可用 --tol 调大,但过大会啃掉角色的浅色部分。
Step 7:送达
发到用户与自己的单聊——最不打扰他人、又能右键转存。直接用 --user-id 传目标 open_id,CLI 会自行解析 p2p 会话,不需要先查 +chat-list 找 chat_id:
必须先发说明文字,再发图。顺序不能颠倒——用户看到一串没有上下文的图片时无法判断这是什么、哪张对应什么语义。说明文字里要带上批次时间标记和本次的语义频次清单,因为重复运行会在同一会话里堆积多批图片,没有标记就分不清。
cd <产物目录>
lark-cli im +messages-send --as user --user-id <ou_xxx> \
--text "以下 N 张是基于你飞书头像生成的自定义表情包,<画风>,按你近一个月真实使用频次排序:<语义1 次数> / <语义2 次数> / ...。逐张右键「添加表情」即可加入表情面板。" --json
lark-cli im +messages-send --as user --user-id <ou_xxx> --image out/01_xxx.png --json
注意两点:
- 发图命令是
+messages-send --image,没有 +send-image 这个子命令
--image 只接受 cwd 相对路径,绝对路径和 .. 会被拒绝,先 cd 到产物目录
逐张串行发送并在每次之间留 1 秒间隔。用返回的 message_id 确认成功,不要靠 shell 管道里的解析结果判断——管道解析失败不代表发送失败,重发会造成重复。
送达后必须核对实际到达数量,不要凭印象向用户回报"已发送":
lark-cli im +chat-messages-list --as user --user-id <ou_xxx> --order desc --page-size 20 --no-reactions --json
核对时按 create_time 区分本次批次与历史遗留图片。若会话里已有前几轮的旧图,在说明文字里点明哪批是本次产物,避免用户误加旧版。
同时打包一份供批量导入:
zip -j -q feishu-stickers.zip out/*.png
Step 8:交代最后一步
告诉用户两条路径:
- 单张转存:会话里右键任意图片 → 「添加表情」,进入「添加的单个表情」面板
- 批量导入:表情面板 → 「添加的单个表情」→ 点
+ → 解压 zip 后多选
同时给出这套表情的语义与频次对照表,让用户知道每张对应自己哪个使用习惯。
跨 Agent 兼容
本 skill 面向多种 Agent 运行环境,工具名各处不同。按能力而非工具名执行:
| 需要的能力 | 常见形态 |
|---|
| 图生图(带参考图) | image_edit、gpt-image 编辑接口、宿主等价图像编辑能力 |
| 本地文件读写 | Read / Write / Bash,或等价文件工具 |
| 执行 Python | Bash / shell 工具;脚本只依赖 Pillow |
| 飞书操作 | 飞书 CLI(硬依赖,见前置章节) |
宿主环境缺少图生图能力时,明确告知用户能力缺口,不要用文生图硬凑——会丢失人物一致性。
脚本只依赖 Pillow。缺失时先 python3 -m pip install --user pillow。