feishu-doc-publish · git:20260826.fe03f66 · 2026-08-26 · sha256 63b0ad455b52bde0
feishu-doc-publish git:20260826.fe03f66A
Immutable. This exact content is served forever at /api/v1/blob/63b0ad455b52bde0.
---
name: feishu-doc-publish
description: 把本地 Markdown 一键发布为飞书云文档并拿回可分享链接(复用 pb-arena 仓库随附的 feishu-doc-sync CLI,即自建应用"飞书助理小桁")。当用户说「发布到飞书」「导出一份飞书文档」「让小桁发布」「同步到飞书」「给团队发个文档链接」「跟之前一样发飞书」,或任何「本地 md → 飞书云文档」的诉求时使用本 skill,即使没提到小桁、CLI 或 pb-arena。
---
# feishu-doc-publish — 发布 Markdown 到飞书云文档
把一篇本地 Markdown 变成飞书云文档(docx),**默认开启「互联网上获得链接的人可阅读」(只读)**,输出链接交付给用户。工具是 pb-arena 仓库随附的零依赖 Node CLI,API 走"飞书助理小桁"这个自建应用(租户域 `ncnnb044q88x.feishu.cn`)。
**交付标准**:给用户一条可直接粘到群里的 `https://ncnnb044q88x.feishu.cn/docx/...` 链接,且用户账号对文档有编辑权。
## 第 1 步:定位工具
CLI 在 pb-arena 仓库里:`<pb-arena>/tools/feishu-doc-sync/sync.mjs`(零 npm 依赖,Node ≥18 即可)。已知位置:
- 网吧机:`B:\临时\pb-arena`
- 主力机:E 盘工作区(用 Glob 找 `**/tools/feishu-doc-sync/sync.mjs`)
细节与故障速查见同目录 `README.md`,动手前值得扫一眼。
⚠️ 但该 README 有两处已过期:① 写着「默认组织内可阅读」——实际默认是互联网可阅读;
② 让配 `owner_mobile`——手机号路线 2026-07-14 已证伪,唯 `owner_open_id` 可靠。**以本文为准。**
## 第 2 步:环境检查(Node)
`node --version` 能出 ≥18 就跳过本步。网吧机没有全局 Node(winget 安装会崩 0xC0000005),用便携版:
1. 先找现成的:`Get-ChildItem "$env:LOCALAPPDATA\Temp\claude" -Recurse -Filter node.exe` —— 旧会话 scratchpad 里往往留着一份(node v22 便携版,验证过可直接用);
2. 找不到再准备新的:从 nodejs.org 下载 win-x64 便携 zip 解压到本会话 scratchpad(下载前按平台规则征得用户同意)。
后续命令统一用找到的 node.exe 全路径调用,不依赖 PATH。
## 第 3 步:凭证检查(最常缺的一环)
凭证按此顺序查找:环境变量 `FEISHU_APP_ID`/`FEISHU_APP_SECRET` → CLI 同目录 `feishu_config.json` → `~/.feishu/config.json`(推荐)。
**网吧机陷阱:C 盘每次还原都会清掉 `~/.feishu/config.json`,缺凭证是常态,不是异常。** 凭据本身永远不变——直接向用户要 App ID 和 App Secret(飞书开放平台 open.feishu.cn → 开发者后台 → 应用 → 凭证与基础信息),同时要 `owner_open_id`(用户本人 open_id,拿法见下方 ⚠️)。拿到后写入 `~/.feishu/config.json`:
```json
{
"app_id": "cli_...",
"app_secret": "...",
"tenant_domain": "ncnnb044q88x.feishu.cn",
"owner_open_id": "ou_..."
}
```
`owner_open_id` 不是可选项的原因:导入 API 生成的文档归应用所有,不授权的话**用户自己打开自己的文档只有只读权**。填了它,每次发布完会自动把用户账号加为协作者(full_access)。
> ⚠️ **别用 owner_mobile / owner_email(2026-07-14 证伪)**:本租户 `contact:user.id:readonly` 只给"用户身份",应用身份用手机号解析报 `99991672`(发版也没用);邮箱 `member_type=email` 报 `1063001`。**唯 open_id 可靠**。免通讯录权限拿 open_id:读该应用所在 wiki 空间成员表 `GET /wiki/v2/spaces/<space_id>/members`,用户那条 `member_id` 即 `ou_...`。完整复盘见 `04_方法论与洞察/06_协作运营与发布/飞书应用文档授用户编辑权_唯open_id可靠_v1.md`。
## 第 4 步:连通性测试
```powershell
<node> <pb-arena>\tools\feishu-doc-sync\sync.mjs --test
```
期望输出「连通性 OK + 凭据来源 + owner 解析 OK」。凭证错误在这一步暴露,别带着坏凭证进发布流程。
## 第 5 步:准备文档
- 文档须**独立成篇**:不含 Obsidian 双链 `[[...]]`、不依赖库内其他文档。若源文件来自知识库内核档,先按 08_对外分发体例改写;
- **本 CLI 不上传本地图片**——`` 这类引用导入后会失效。纯文字+表格的文档没问题;含本地图片的要么先把图删改成文字,要么改用 knowledge-base `06_代码/feishu_sync`(Python 版,支持嵌图);
- 标准 Markdown 表格、加粗、代码块都能正确转换;
- 标题约定 `<标题>_<YYYY-MM-DD>`,与历史文档保持一致。
## 第 6 步:发布
```powershell
<node> <pb-arena>\tools\feishu-doc-sync\sync.mjs "<md文件路径>" --title "<标题_YYYY-MM-DD>"
```
成功输出五步进度和最终链接。
⚠️ **分享档位(2026-08-26 核过代码,本文与 CLI README 此前都写反了)**:
`sync.mjs` 的默认是 **`anyone_readable`(互联网可阅读,只读)**,日志会打「4/5 开启互联网可阅读(只读)」。
加 `--org` 才退回 `tenant_readable`(仅组织内),加 `--no-share` 完全不设链接分享。
**放开到互联网属于扩大对外暴露,发布前要跟本人确认这份文档能不能对外**;
给组织外的人看(如朋友)走默认即可,组织内部资料记得加 `--org`。
配置里有 owner 时自动授权,日志会体现。
## 第 7 步:授权兜底
如果发布时配置里还没填 owner(比如 open_id 后补),单独补授权:
```powershell
<node> <pb-arena>\tools\feishu-doc-sync\sync.mjs --grant <doc_token>
```
`doc_token` 是链接里 `/docx/` 后面那串。补完把 `owner_open_id` 写回配置,下次自动带上。
## 故障速查
- `缺少飞书应用凭据` → 第 3 步,向用户要凭据重建配置;
- `获取 tenant_access_token 失败` → app_id/app_secret 抄错或应用被停用;
- `1061004 / forbidden` → 应用云文档权限问题(正常不会遇到,应用权限跟应用走、早已配好);
- 开分享失败但文档已生成 → 脚本只警告不中断,让用户在文档右上角手动开对应档位;
- 更多见 CLI 同目录 `README.md`。
## 交付
把链接给用户,一并说明:**实际开的是哪个档位**(默认=互联网可阅读,只读;带 `--org` =仅组织内)、账号已授权可编辑。若本次是在还原盘机器上重建过凭证,提醒一句「下次还原后需要再提供一次 App ID/Secret」。
## 延伸:发布后由 bot 直发群(CLI 不覆盖,裸调 API)
用户要求「发布并发到群里」时,文档发布完不必人肉粘贴:同一份凭据换 tenant token 后,`GET /im/v1/chats` 列 bot 所在群拿 chat_id,再 `POST /im/v1/messages?receive_id_type=chat_id` 发摘要+链接(content 是 JSON **字符串**,双重序列化)。前置:bot 已在目标群、应用有 IM 权限(本应用已具备,2026-07-17 真机验证)。完整链路与坑见 `04_方法论与洞察/06_协作运营与发布/飞书应用发群消息_免webhook直发_v1.md`。