Reads and writes Feishu (飞书) docs, sheets, Base records, Drive files, calendar events, tasks, wiki, and IM messages via the Feishu Open Platform REST API using curl and jq.
How this skill is triggered — by the user, by Claude, or both
Slash command
/acedatacloud-ai-media:feishuWhen to use
Trigger when the user wants to read or write something in Feishu (飞书) — summarize / create / edit a doc, read or append to a spreadsheet, query or add Base (bitable) records, browse Drive files, look at or create calendar events, manage tasks, read wiki nodes, or send an IM message.
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
We drive the [Feishu Open Platform API](https://open.feishu.cn/document)
We drive the Feishu Open Platform API
with curl + jq. The user's OAuth user_access_token is in
$FEISHU_TOKEN; every call sends it as Authorization: Bearer $FEISHU_TOKEN. All endpoints live under https://open.feishu.cn/open-apis.
Calls run in the user's context (their docs, calendar, messages) — only data the user can access and only the scopes they granted at connect time (docs / sheets / base / drive / calendar / IM / wiki / task / contacts).
Every Feishu response is {"code": 0, "msg": "success", "data": {…}}.
code == 0 means success; any non-zero code is an error — surface
msg to the user. Always check it:
resp=$(curl -sS … )
echo "$resp" | jq 'if .code == 0 then .data else error("Feishu \(.code): \(.msg)") end'
Common error codes:
| code | meaning | what to do |
|---|---|---|
99991663 / 99991668 | access token invalid / expired | tell the user to reconnect Feishu in 连接 settings |
99991661 | no permission (scope not granted) | the connect-time scope is missing — reconnect and grant it |
1254xxx | resource not found / no access | the user can't see that doc / sheet / app — double-check the token/id |
curl -sS https://open.feishu.cn/open-apis/authen/v1/user_info \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then {name: .data.name, open_id: .data.open_id, email: .data.email} else . end'
A Feishu doc URL looks like https://…feishu.cn/docx/<document_id>. The
document_id is the last path segment.
Read a document's plain text:
curl -sS "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/raw_content" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq -r 'if .code == 0 then .data.content else "ERR \(.code): \(.msg)" end'
List a document's blocks (structured content):
curl -sS "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/blocks?page_size=500" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {block_id, block_type}] else . end'
Create a new empty document (optionally inside a folder):
curl -sS -X POST "https://open.feishu.cn/open-apis/docx/v1/documents" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg title "会议纪要 2026-07-01" '{title: $title}')" \
| jq 'if .code == 0 then {document_id: .data.document.document_id} else . end'
Append a text block to a document (insert at the end of the document body —
DOCUMENT_ID is also the root block id):
curl -sS -X POST "https://open.feishu.cn/open-apis/docx/v1/documents/DOCUMENT_ID/blocks/DOCUMENT_ID/children" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg text "由助手追加的一段内容。" '
{children: [{block_type: 2, text: {elements: [{text_run: {content: $text}}]}}]}')" \
| jq 'if .code == 0 then "appended" else . end'
A sheet URL looks like https://…feishu.cn/sheets/<spreadsheet_token>.
A range is <sheetId>!<A1:range>, e.g. abc123!A1:D10. List sheet ids via
the metainfo endpoint first if you don't have one.
Read a range:
curl -sS "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/SPREADSHEET_TOKEN/values/RANGE" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then .data.valueRange.values else . end'
Append rows after the last non-empty row:
curl -sS -X POST "https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/SPREADSHEET_TOKEN/values_append" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{valueRange: {range: "SHEET_ID!A1:B1", values: [["张三", 100], ["李四", 200]]}}')" \
| jq 'if .code == 0 then .data.updates else . end'
A Base URL looks like https://…feishu.cn/base/<app_token>. Get table_id
from …/bitable/v1/apps/APP_TOKEN/tables.
List records:
curl -sS "https://open.feishu.cn/open-apis/bitable/v1/apps/APP_TOKEN/tables/TABLE_ID/records?page_size=100" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {record_id, fields}] else . end'
Create a record:
curl -sS -X POST "https://open.feishu.cn/open-apis/bitable/v1/apps/APP_TOKEN/tables/TABLE_ID/records" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{fields: {"标题": "新任务", "状态": "待办"}}')" \
| jq 'if .code == 0 then {record_id: .data.record.record_id} else . end'
List files in a folder (omit folder_token for the root):
curl -sS "https://open.feishu.cn/open-apis/drive/v1/files?folder_token=FOLDER_TOKEN&page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.files[] | {name, type, token, url}] else . end'
List the user's calendars (the primary one has type: "primary"):
curl -sS "https://open.feishu.cn/open-apis/calendar/v4/calendars?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.calendar_list[] | {calendar_id, summary, type}] else . end'
List events in a time window (epoch-seconds strings):
curl -sS "https://open.feishu.cn/open-apis/calendar/v4/calendars/CALENDAR_ID/events?start_time=1751299200&end_time=1751385600&page_size=100" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {summary, start: .start_time, end: .end_time, event_id}] else . end'
Create an event (times are epoch-seconds strings):
curl -sS -X POST "https://open.feishu.cn/open-apis/calendar/v4/calendars/CALENDAR_ID/events" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{summary: "项目评审", start_time: {timestamp: "1751302800"}, end_time: {timestamp: "1751306400"}}')" \
| jq 'if .code == 0 then {event_id: .data.event.event_id} else . end'
List the user's tasks:
curl -sS "https://open.feishu.cn/open-apis/task/v2/tasks?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {summary, completed_at, task_guid: .guid}] else . end'
Create a task:
curl -sS -X POST "https://open.feishu.cn/open-apis/task/v2/tasks" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc '{summary: "准备周会材料"}')" \
| jq 'if .code == 0 then {task_guid: .data.task.guid} else . end'
List wiki spaces, then nodes within a space:
curl -sS "https://open.feishu.cn/open-apis/wiki/v2/spaces?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {space_id, name}] else . end'
curl -sS "https://open.feishu.cn/open-apis/wiki/v2/spaces/SPACE_ID/nodes?page_size=50" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
| jq 'if .code == 0 then [.data.items[] | {title, node_token, obj_type}] else . end'
Send to a user by open_id (use receive_id_type=chat_id for a group
chat). content must be a JSON string, so it's double-encoded:
curl -sS -X POST "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id" \
-H "Authorization: Bearer $FEISHU_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg rid "ou_xxx" --arg text "你好,这是助手发送的消息。" '
{receive_id: $rid, msg_type: "text", content: ({text: $text} | tostring)}')" \
| jq 'if .code == 0 then {message_id: .data.message_id} else . end'
data.page_token / data.has_more;
pass page_token=… to fetch the next page.npx claudepluginhub acedatacloud/skills --plugin acedatacloud-ai-mediaAutomates Feishu (Lark) operations: Bitable, messaging, documents, groups, wiki, calendar, tasks via lark-mcp. Syncs data, sends notifications, automates workflows.
Extracts Feishu/Lark docs, wiki pages, collections, spreadsheets, and Minutes transcripts into faithful local Markdown via lark-cli API, with browser-DOM and .docx fallback paths.
Read WeCom contacts, send app/group messages, manage WeDoc smart sheets, schedules, and meetings via the WeCom server-side API as a self-built app. Triggered when users mention 企业微信 or WeCom operations.