agentleFS
Practice019Practice019/agent-skills/feishu-cli/SKILL.md

feishu-cli

Skill0 starsChanged 2 months agoMITView on GitHub

用 lark-cli 命令行工具操作飞书:读写文档、编辑内容(含表格行列级块编辑)、搜索、上传下载文件、电子表格、多维表格、消息、日历、邮件等;含安装、应用配置、Device Flow 授权与权限排障。当用户需要查看/编辑/创建飞书文档、在表格中增删行、操作飞书云空间或调用飞书开放平台能力时使用。 Operate Feishu/Lark from the command line with lark-cli: read and write documents, edit content (including row/column-level table blocks), search, upload and download files, spreadsheets, bitables, messages, calendar, and mail. Covers install, app config, device-flow auth, and permission troubleshooting. Use when the user needs to view, edit, or create Feishu docs, add or remove table rows, manage Feishu cloud space, or call Feishu Open Platform APIs.

  • Installs packages

The file

Files
SKILL.md

lark-cli 飞书操作

用 lark-cli(官方 CLI)控制飞书:文档、云空间、电子表格、多维表格、消息、日历、邮件、任务、审批、OKR、妙记、视频会议等 18 大业务域。

前置检查(每次会话首次使用时执行一次)

1. 检查安装与版本

# 确认命令可用;没有则安装
Get-Command lark-cli -ErrorAction SilentlyContinue
# 未找到时(NODE_OPTIONS 会干扰全局安装,先清掉):
$env:NODE_OPTIONS=$null; npm install -g @larksuite/cli
# 装完仍找不到 -> 去 npm 全局目录里找实际路径
$npmPrefix = (npm prefix -g)
Get-ChildItem "$env:APPDATA\npm\lark-cli*", "$npmPrefix\lark-cli*" -ErrorAction SilentlyContinue

lark-cli --version
lark-cli doctor
  • doctor 输出各项检查。cli_update 为 warn 时建议先升级:lark-cli update
  • 若提示 "Check the installed lark-doc skill first; if it is not the v2 skill, run lark-cli update",先执行 lark-cli update(升级 CLI,同时更新配套 lark-doc 等 agent skills)

1b. 检查应用配置(与授权是两回事)

lark-cli config show

判据:输出里出现 appId 才算已配置——不要用退出码判断(配置缺失时它未必非零)。

  • 有 appId → 应用配置就绪,去看 §2 授权状态
  • 没有 appId → 需要初始化应用配置,但只能用非交互方式(见 §5 禁止命令)

⚠️ 应用配置完成 ≠ 用户已登录。config show 通过只说明应用凭证在,个人资源(用户文档、日历、邮件、任务、聊天记录)还需要 §3 的用户授权。两步要连着做完,不要停在申请配置这一步。

2. 检查授权状态

lark-cli auth status

auth status 关键字段的读法:

字段含义处理
identity当前默认身份(user / 无用户时才会回退 bot)要读个人资源必须是 user
tokenStatusvalid / needs_refresh / expiredneeds_refresh 会在下次调用时自动刷新,正常;expired 才要重新登录
expiresAt / refreshExpiresAtaccess token / refresh token 到期时间看 refreshExpiresAt 判断要不要重新走 Device Flow
scope已授权的 scope 列表权限报错时先来这儿对照缺哪个 scope
  • token expired → 重新登录(见下)
  • no token → 首次登录

3. 登录(Device Flow)

关键点:auth login 是阻塞式命令,必须用 --no-wait 先拿到授权 URL,再交给用户完成浏览器授权。

# 步骤 A:发起授权,立即返回
lark-cli auth login --no-wait --json --domain docs,drive,im,calendar

返回 JSON 中含 verification_uri、user_code。把这两个信息告诉用户:

请打开 {verification_uri},输入验证码 {user_code} 完成授权。

# 步骤 B:用户在浏览器完成授权后,用 device-code 完成登录
lark-cli auth login --device-code <DEVICE_CODE> --json

scope 选择(--domain 参数,可逗号分隔多个):

  • 只操作文档:docs,drive
  • 操作表格:sheets
  • 操作多维表格:base
  • 发消息:im
  • 日历:calendar
  • 邮件:mail
  • 任务:task
  • 全部:all(不推荐,scope 越多审批越慢)

4. 常用授权管理命令

lark-cli auth status                 # 查看当前用户/token状态
lark-cli auth list                   # 列出所有已登录用户
lark-cli auth scopes                 # 查看应用已开通的 scopes
lark-cli auth check --scope docs:document:read   # 检查是否具备某 scope
lark-cli auth logout                 # 登出
lark-cli config show                 # 查看当前应用配置

5. 禁止执行的命令(会挂住会话)

以下命令任何情况下都不要跑——它们需要 TTY,非交互环境下会输出坏掉的二维码并一直阻塞:

禁止命令原因
lark-cli config init --new交互式,需 TTY
lark-cli config init同上(不带 --new 也会进交互)
lark-cli config set-default交互式选择,需 TTY

要初始化应用配置时,走非交互路径;不要用上面三条试探。

6. Device Flow 硬化规则(超时、重试、复用)

auth login --no-wait 拿到 device_code 后,轮询阶段有三条硬规则:

  1. authorization_pending 是正常状态,不是错误。它在 HTTP 层可能表现为 400,含义是「用户还没在浏览器点完授权」。继续等,不要重新发起。
  2. 轮询命令的存活时间必须长于 device code 有效期。device code 常见有效期为 10 分钟,所以轮询要跑 ≥11 分钟(工具超时给 700000 ms 以上),或干脆放到后台跑。
  3. 轮询被工具超时打断、但 device code 还没过期时,复用同一个 device_code 继续轮询,不要重新 --no-wait 生成新码。只有出现 expired_token、invalid_grant,或确认已过有效期,才重新发起一次登录。

同时:同一时刻只跑一个轮询。上一个轮询还在 authorization_pending 时,不要并行开新的 setup 或 login 流程。

7. 首次连接的用户提示语

首次使用需要两步连接时,先跟用户说清楚,避免他以为在重复授权:

第一次使用飞书套件需要完成两步连接:先初始化飞书 CLI 应用配置,再授权访问你有权限的飞书数据。两步完成后我会自动继续当前任务;这不是重复授权。

**补充授权(不是重连)**的话术——飞书权限按能力拆分,跑更具体的操作(文档搜索、云盘检索、导出等)时可能要追加 scope:

当前任务需要补充授权:飞书文档搜索权限 search:docs:read。授权后,后续搜索飞书文档不会再次要求这个权限。

补充授权时用显式 scope 登录,且 --scope 不能与 --domain、--recommend 同时使用(三者互斥)。除非有意收窄 token,否则不要用一小撮显式 scope 替换掉推荐范围登录。

常用命令速查

写法分两类:shortcut(+xxx,高层封装,优先用)与 原始 API(lark-cli <domain> <resource> <method>)。用原始 API 前先跑一次 lark-cli schema <domain>.<resource>.<method> 看准参数结构,别照记忆拼 --data。

域与 shortcut 速览(本机 lark-cli 1.0.31 实测)

域用途实测 shortcut
im消息、群、聊天记录、附件、话题、书签+messages-send、+messages-search、+messages-reply、+messages-resources-download、+chat-list、+chat-create、+chat-search、+chat-messages-list、+threads-messages-list、+flag-list
docs新版文档读写、搜索、媒体+fetch、+create、+update、+search、+media-insert、+media-download、+whiteboard-update
drive云空间文件、导入导出、权限、评论、目录镜像+upload、+download、+search、+export、+export-download、+import、+create-folder、+add-comment、+push、+pull、+status、+task_result
sheets电子表格读写、查找替换、行列增删、样式、浮动图片+read、+write、+append、+create、+find、+replace、+info、+insert-dimension、+delete-dimension、+export、+set-style
base多维表格记录/字段/视图/仪表盘/工作流/表单+base-create、+table-list、+field-list、+record-list、+record-search、+record-batch-create、+record-batch-update、+record-upsert、+record-upload-attachment、+data-query、+view-list、+workflow-list
calendar日程、空闲、会议时间建议、会议室+agenda、+create、+update、+freebusy、+suggestion、+rsvp、+room-find
task任务、清单、提醒、评论、附件+create、+get-my-tasks、+get-related-tasks、+search、+complete、+update、+comment、+reminder、+tasklist-create、+tasklist-search
mail收发、草稿、线程、全文检索+send、+draft-create、+reply、+reply-all、+forward、+message、+thread、+triage、+watch
wiki知识库节点、移动、空间删除+node-create、+move、+delete-space
vc会议记录、录制、纪要、bot 入会+search、+notes、+recording、+meeting-join、+meeting-events、+meeting-leave
contact用户搜索与资料(需 --as user)+search-user、+get-user
minutes妙记搜索、媒体下载、上传生成+search、+download、+upload
whiteboard画板查询 / 用 mermaid·plantuml·DSL 更新+query、+update

⚠️ shortcut 名随版本变化:网上某些移植文档写的是 +calendars-list、+events-list、+spreadsheets-read、+tables-records-list、+documents-create 这类名字,在本机 1.0.31 上不存在(calendar 实际是 +agenda / +freebusy 等,sheets 是 +read,base 是 +record-list)。一律以 lark-cli <domain> --help 的实际输出为准,不要照抄外部文档。

常用实体 ID

实体ID 形态
用户open_id(ou_xxx)/ user_id / email
群聊chat_id(oc_xxx)
消息message_id(om_xxx)
话题thread_id
文档document_id(docx token)
文件file_key / file_id
多维表格base_id(app_xxx)+ table_id(tbl_xxx)
日程event_id

文档(docs)

操作命令
读取文档lark-cli docs +fetch --api-version v2 --doc "<URL或token>"
创建文档lark-cli docs +create --api-version v2 --title "标题" --markdown "<内容或@file>"
追加内容lark-cli docs +update --api-version v2 --doc "<token>" --mode append --markdown "<内容>"
覆盖全文lark-cli docs +update --api-version v2 --doc "<token>" --mode overwrite --markdown "<内容>"
替换某段lark-cli docs +update --api-version v2 --doc "<token>" --mode replace_range --selection-by-title "## 小节" --markdown "<新内容>"
更新标题lark-cli docs +update --api-version v2 --doc "<token>" --new-title "新标题"
删除范围lark-cli docs +update --api-version v2 --doc "<token>" --mode delete_range --selection-by-title "## 小节"
搜索文档lark-cli docs +search --query "关键词"
插入图片lark-cli docs +media-insert --doc "<token>" --file "D:\path\img.png"

文档 token 提取:URL https://xxx.feishu.cn/docx/I005dwk5poSRtExG0RpcRG5Knrf 中的 I005dwk5poSRtExG0RpcRG5Knrf 就是 doc token,可直接传给 --doc。

内容格式:

  • --markdown 支持 Lark-flavored Markdown,也支持 @文件路径(读取本地文件)或 -(stdin)
  • 也可用 --doc-format xml 使用 XML 格式获得更强的结构控制(表格/画板/图表等)
  • ⚠️ 已知问题:v2 +create --title T --content @file.md 可能静默丢弃 title 和 content(GitHub issue #827),返回 ok 但文档是空的。建议创建时用 --markdown 而非 --content,创建后立即 +fetch 验证非空。
  • 版本差异(实测 lark-cli 1.0.31):docs +update --api-version v2 的实际 flag 是 --command append|overwrite|replace_range|...、--content、--doc-format xml|markdown,没有 --mode / --markdown(上表是新版 CLI 写法;用前先 lark-cli docs +update --api-version v2 --help 确认)。+update 不支持 --format。表格行列级编辑请直接用下方块级 API。

云空间(drive)

操作命令
上传文件lark-cli drive +upload --file "D:\path\file.pdf" --folder-token <token>
下载文件lark-cli drive +download --token <file_token> --output "D:\path\save.pdf"
搜索文件lark-cli drive +search --query "关键词"
创建文件夹lark-cli drive +create-folder --name "新文件夹" --folder-token <父token>
移动文件lark-cli drive +move --token <file_token> --folder-token <目标token>
删除文件lark-cli drive +delete --token <file_token>
导出文档lark-cli drive +export --token <doc_token> --type docx
添加评论lark-cli drive +add-comment --token <doc_token> --content "评论内容"

电子表格(sheets)

操作命令
创建表格lark-cli sheets +create --title "表名" --header "A,B,C"
读取数据lark-cli sheets +read --spreadsheet-token <token> --range "Sheet1!A1:C10"
写入数据lark-cli sheets +write --spreadsheet-token <token> --range "Sheet1!A1" --values "[[1,2,3]]"
追加数据lark-cli sheets +append --spreadsheet-token <token> --values "[[1,2,3]]"
查找替换lark-cli sheets +find --spreadsheet-token <token> --find "关键词"
查看信息lark-cli sheets +info --spreadsheet-token <token>

多维表格(base)

操作命令
创建lark-cli base +base-create --name "表名"
查看字段lark-cli base +field-list --app-token <token> --table-id <table_id>
读取记录lark-cli base +record-list --app-token <token> --table-id <table_id>
搜索记录lark-cli base +record-search --app-token <token> --table-id <table_id> --query "关键词"

消息(im)

操作命令
发消息lark-cli im +message-send --receive-id <open_id> --receive-id-type open_id --msg-type text --content "内容"
搜索消息lark-cli im +message-search --query "关键词"
列出群聊lark-cli im +chat-list

通用 API(兜底,透传飞书开放平台 OpenAPI)

# GET(无查询参数)
lark-cli api GET /open-apis/docx/v1/documents/<doc>/raw_content

# GET(带查询参数)—— PowerShell 会吃掉 --params 里的双引号,必须"单引号 + 反斜杠转义":
lark-cli api GET "/open-apis/docx/v1/documents/<doc>/blocks" --params '{\"page_size\":500}'

# PATCH/POST(带请求体)—— 复杂 JSON 先写 body.json(UTF-8 无 BOM),再 --data @file:
[IO.File]::WriteAllText("$PWD\body.json", $json, (New-Object System.Text.UTF8Encoding($false)))
lark-cli api PATCH "/open-apis/docx/v1/documents/<doc>/blocks/<block_id>" --data "@body.json"

实测三个坑:

  • HTTP 动词必须严格照官方文档:docx「更新块」是 PATCH;用 PUT/POST 调它得到的是 HTTP 404: 404 page not found(不是 405),容易误判成接口不存在
  • --params 报 invalid format, expected JSON object = 双引号被 PowerShell 剥掉了,改用 '{\"k\":v}' 写法
  • schema 子命令只覆盖 approval/calendar/drive/im/mail/sheets/wiki 等,不含 docx(报 Unknown service: docx),docx 参数直接查官方文档(链接见下节)

官方块级 API(docx v1:表格行列级、块级精细编辑)

docs +update 只能整段 Markdown 追加/覆盖,表格加行、单格改字、删行列这类结构级编辑它做不到,要直接调官方块级 OpenAPI(lark-cli api 透传)。官方文档入口:

接口方法与 URL官方文档
获取所有块GET /open-apis/docx/v1/documents/<doc>/blocks?page_size=500文档概述(块级接口总览)
获取单块GET .../blocks/<block_id>同上
更新块PATCH .../blocks/<block_id>更新块
批量更新块PATCH .../blocks/batch_update批量更新块
创建块POST .../blocks/<parent_id>/children,body {"children":[...],"index":n}文档概述
创建嵌套块(一次建出表格+单元格)POST .../blocks/<parent_id>/descendant文档概述
删除块DELETE .../blocks/<block_id>/children/batch_delete,body {"start_index":0,"end_index":2}文档概述

权限:创建及编辑新版文档 或 编辑新版文档(scope 里有 docx:document:write_only 即可)。

块模型(GET blocks 实测确认的 block_type)

block_type含义识别特征
1页面(根块,page 的 block_id = document_id)children 是文档顶层块序列
2文本段落text.elements[].text_run
3–11标题 1–9 级heading1 / heading2 …
14代码块code.elements,style.language
31表格table.property.{row_size,column_size,header_row};table.cells 为 cell 的 block_id 按行主序排列(每行 column_size 个)
32单元格table_cell,children 通常是一个 block_type 2 的段落

更新块(PATCH /blocks/<block_id>)请求体键

一次 PATCH 只做一个操作,请求体取以下键之一(标 ✋ 的仅 Table 块可用):

键用途
update_text_elements重写段落文本。elements 数组支持 text_run / mention_user / mention_doc / equation;样式放 text_element_style(bold/italic/underline/strikethrough/inline_code/background_color/text_color/link)
update_text_style只改段落样式(align/folded),不动内容
update_table_property ✋表格属性(列宽 column_width 等)
insert_table_row ✋{"row_index":n}:n=-1 插在最前,n=row_size 追加末尾;响应直接返回新行各 cell 的 block_id
insert_table_column ✋{"column_index":n}
delete_table_rows / delete_table_columns ✋批量删行/列(行/列索引数组)
merge_table_cells / unmerge_table_cells ✋合并/取消合并(row/column_start_index、row/column_end_index)

批量更新块(PATCH /blocks/batch_update)

请求体 requests 为数组,每项 = block_id + 上面任意一个操作键。一次调用改多个段落:

{ "requests": [
  { "block_id": "<段落block1>", "update_text_elements": { "elements": [
      { "text_run": { "content": "加粗文字", "text_element_style": { "bold": true } } } ] } },
  { "block_id": "<段落block2>", "update_text_elements": { "elements": [
      { "text_run": { "content": "https://example.com",
        "text_element_style": { "link": { "url": "https%3A%2F%2Fexample.com" } } } } ] } }
] }

⚠️ link.url 必须 percent-encode(https:// → https%3A%2F%2F),写原始 URL 会得到坏链接。响应带 document_revision_id;可传 client_token 幂等。

表格追加一行:完整调用序列(实测 5 步)

  1. GET .../blocks → 找 block_type:31 的 table 块,记 block_id 与 property.row_size
  2. PATCH .../blocks/<table_block_id> + {"insert_table_row":{"row_index":<row_size>}} → 末尾加空行,响应返回新行 3 个 cell 的 block_id
  3. 再 GET .../blocks → 用 cell id 反查各 cell 的 children,拿到新行的文本段落 block id(insert 响应里只有 cell id,没有段落 id)
  4. PATCH .../blocks/batch_update → 对三个段落 block 分别 update_text_elements 填入各列内容(名称 bold、纯文本、link 三件套)
  5. docs +fetch 回读 → 确认行数 +1、新行内容与样式正确

工作流程

场景 A:读取飞书文档

  1. 用户给 URL → 提取 token(/docx/<token> 或 /wiki/<token>)
  2. lark-cli docs +fetch --api-version v2 --doc "<token>" --format json
  3. 输出是 JSON,含 markdown 格式正文;如需落盘:
    lark-cli docs +fetch --api-version v2 --doc "<token>" | Out-File -Encoding utf8 doc.md
  4. wiki 文档可能需要先通过 lark-cli wiki 解析 node → 实际 obj_token,再 fetch

场景 B:编辑飞书文档

  1. 先 +fetch 读取现状(拿到 markdown + block 结构)
  2. 确认要改动的位置:追加到末尾用 --mode append;整篇替换用 --mode overwrite;只改某一节用 --mode replace_range --selection-by-title "## 章节"
  3. 写入临时 md 文件,用 --markdown @temp.md 传入,避免命令行转义问题
  4. 执行 +update,检查返回 JSON 的 code 字段是否为 0
  5. 再次 +fetch 验证修改生效

场景 C:创建飞书文档

  1. 准备 markdown 内容(写入本地临时文件最稳妥)
  2. lark-cli docs +create --api-version v2 --title "标题" --markdown @temp.md
  3. 检查返回 JSON 中的 url / document_id
  4. 立即 fetch 回读验证内容非空(见上文 issue #827 的坑)

场景 D:批量文档处理

  1. lark-cli docs +search --query "关键词" --page-size 20 拿到一批文档
  2. 逐个提取 token,循环执行 fetch / update
  3. 有失败要单独记录,不要让单条失败中断整批

输出处理技巧

# 用 --jq 过滤 JSON 字段
lark-cli docs +fetch --api-version v2 --doc <token> -q '.data.content'
lark-cli docs +search --query "周报" -q '.data.items[].url'

# 输出格式选择
--format json      # 默认,结构化
--format pretty    # 人类可读
--format table     # 表格
--format ndjson    # 每行一个JSON,便于逐行处理

# 分页
--page-all         # 自动翻页拿全量
--page-size 50     # 每页条数

常见错误与排查

错误原因处理
token expired登录过期重新 auth login --no-wait --domain ...
permission denied / forbidden缺少 scope 或文档未授权给当前用户检查 auth scopes;请文档所有者在飞书客户端里把文档分享给当前登录用户
InvalidParam参数格式错误检查 token 是否取对、JSON 是否合法
not existtoken 错误或文档被删确认 URL 是否最新
Rate limit触发限流加 Start-Sleep -Milliseconds 500 重试
输出中文乱码PowerShell 编码问题命令前先执行 [Console]::OutputEncoding=[Text.Encoding]::UTF8
v2 create 内容为空issue #827用 --markdown 而非 --content,创建后 fetch 验证
api 透传返回 404 page not foundHTTP 动词不对(docx 更新块是 PATCH,用 PUT/POST 就 404)或路径拼错(如 /all-blocks 不存在)逐字对照官方文档的方法+URL
--params invalid format, expected JSON objectPowerShell 剥掉了内层双引号写成 --params '{\"page_size\":500}'
--file/--content must be a relative path@file 只接受当前目录内的相对路径临时文件写进工作区,用 @./file.json
Unknown service: docx(schema 命令)schema 不覆盖 docxdocx 参数查官方文档(「官方块级 API」一节有链接)
表格要加行/改单元格,+update 做不到CLI 只有整段 Markdown 粒度走官方块级 PATCH/batch_update(见「官方块级 API」一节)
need_user_authorization / No user logged in / failed to get access token用户未登录或 token 过期停止重试业务接口,走 device flow 登录并复用同一 device_code 轮询,再 auth status 确认
forbidden(配 --as bot)bot/应用不是该资源协作者停止用 bot 重试;改用 --as user,或请用户把应用加为文档/资源协作者
App scope not enabled / required scope ...应用没在开放平台开通该 scope,用户授权也补不上停止重试;告知用户/管理员需在开发者后台开通的具体 scope 名,开通后重授权再重试一次
authorization_pending用户还没在浏览器点完授权保持当前轮询,不要开新流程
expired_token / invalid_grantdevice code 过期重新发起一次登录,把新 URL 给用户

熔断规则(fail-fast):业务接口报授权/权限错误后,只允许诊断一次,然后切到对应的授权步骤。不要反复换 --as user / --as bot / --format 等无关变体重试同一接口。

注意事项

  1. 身份选择:
    • 默认 --as auto:有登录用户就用用户身份,否则回退到应用(bot)身份。
    • 个人资源(用户能打开的文档、日历、邮件、任务、聊天记录)在 auth status 有效时优先显式 --as user。
    • --as bot 只用于应用自身操作,或 bot 明确是成员/协作者的资源;不是协作者时给它 --as bot 只会拿到 forbidden。
    • 文档归属:用户要的文档/表格默认用 --as user 创建,这样归属用户本人;只有用户明确要应用归属内容时才用 --as bot。
    • bot 建的文档要分享给用户,需要 docs:permission.member:create;该 scope 未开通时停下来找管理员开通,不要绕路。
  2. Risk 标记:+fetch/+search 是 read;+create/+update/+delete 是 write。写操作前确认目标正确。
  3. dry-run:加 --dry-run 只打印请求不执行,可用来验证参数。
  4. 大文件/长内容:优先走 @file 方式传内容,避免命令行长度限制和转义坑。
  5. Windows 路径:@D:\path\to\file.md 反斜杠在 PowerShell 里没问题,但如果内容含中文建议文件存 UTF-8(无 BOM 更稳)。
  6. 不要把 token/app-secret 写进 skill 或脚本:凭证由 lark-cli config / auth 管理,OS keychain 存储。
  7. CLI 升级:lark-cli update --json;升级后 agent skills(lark-doc 等)会同步更新到 v2。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.