agentsclimarketplace

Feishu

Skill AceDataCloud/Skills/skills/feishu

Read and write Feishu (飞书) docs, sheets, Base (bitable), Drive files, calendar events, tasks, wiki, and IM messages via the Feishu Open Platform REST API. Use when the user mentions 飞书 / Feishu / Lark, a Feishu document or sheet link, their Feishu calendar, or wants to send a Feishu message.From its SKILL.md

Install
npx -y skills add AceDataCloud/Skills --skill feishu

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 13 stars13 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its file declares

Copied from the file, not written here

The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

8.8 KB, ~2.6k tokens by cl100k_base, as published. Nobody here has run it

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).

Response shape & error handling

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:

codemeaningwhat to do
99991663 / 99991668access token invalid / expiredtell the user to reconnect Feishu in 连接 settings
99991661no permission (scope not granted)the connect-time scope is missing — reconnect and grant it
1254xxxresource not found / no accessthe user can't see that doc / sheet / app — double-check the token/id

Recipes

Verify auth (always run first)

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'

Docs (docx)

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'

Spreadsheets (sheets v2)

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'

Base / 多维表格 (bitable v1)

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'

Drive files

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'

Calendar (v4)

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'

Tasks (v2)

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'

Wiki

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 an IM message

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'

Notes

  • Confirm destructive or outward-facing actions (sending a message, creating a calendar invite, posting to a shared doc) with the user before running them.
  • Pagination: list endpoints return data.page_token / data.has_more; pass page_token=… to fetch the next page.
  • When the user pastes a Feishu link, extract the token/id from the URL path rather than asking them for it.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,790. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.