feishu
Skill9 starsChanged 4 days agoMITView on GitHub
This skill should be used when the user asks to read, create, or edit Feishu/Lark documents, search docs in their Feishu workspace, or fetch content from a Feishu wiki or docx URL.
We split this skill into the rules it gives an agent
24 rules. 0 are common, 13 are distinctive, and 11 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
13
Distinctive
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 9
Read, create, and edit documents in the Feishu workspace using the Feishu Open API with a user access token.
- Very specific: line 88
When docs_types contains "doc", search returns an empty result.
- Distinctive: line 90
Treat an empty result as inconclusive.
- Distinctive: line 91
Verify an absence claim with another search surface or a known document link.
- Very specific: line 93
After a recorded meeting, Feishu stores AI notes and the transcript in the meeting owner's space.
- Distinctive: line 95
Search returns only notes the user owns or the owner shared with the user.
- Distinctive: line 96
When the notes of a meeting that another person owns are not visible, ask the user for the notes link.
- Distinctive: line 100
Use this to inspect or update the public-sharing policy for a docx document:
- Very specific: line 112
Use the doc token / document_id as {token}.
- Distinctive: line 120
Default policy for Linear-linked docs:
- Very specific: line 122
Do not widen to tenant_editable unless the user explicitly asks
- Distinctive: line 123
Do not enable external public access by default
- Very specific: line 272
All writes still require explicit user approval first.
- Very specific: line 273
When creating a Feishu document for a Linear issue, immediately call PATCH …
- Very specific: line 274
Do NOT widen sharing to tenant_editable unless the user explicitly asks for edit access.
- Distinctive: line 275
Do NOT enable external public access by default.
- Distinctive: line 276
Before any permission write, show the exact change and get explicit user approval first.
- Very specific: line 282
If the refresh itself fails, the command exits 1 and leaves credentials.yaml unchanged.
- Distinctive: line 288
When the refresh token expires or new scopes are needed, the user must re-authorize:
- Distinctive: line 307
If the user provides a URL, parse the token from the URL path
- Very specific: line 316
If the document is created for a Linear issue and the user approved the permission write, immediately set its public permission to …
- Very specific: line 318
Do not widen the document to tenant_editable unless the user explicitly asks
- Distinctive: line 323
When a doc exists, each Linear issue maps to at most one Feishu doc — subsequent updates append to the same doc, never a new one
- Very specific: line 324
After creating the doc and getting explicit user approval for the permission write, set its public permission with PATCH …
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Feishu Docs
Read, create, and edit documents in the Feishu workspace using the Feishu Open API with a user access token.
IMPORTANT: User approval required for all writes. Feishu does not support online review/diff. Before creating or editing any document, you MUST show the user the planned content and get explicit approval first.
Configuration
- Credentials location:
$CHARLIEBOT_HOME/credentials.yaml - Keys (section
feishu):app_id,app_secret,user_access_token,refresh_token - Auth method: OAuth2 user access token (acts as the user's own account)
- Requests: send every Feishu Open API request through
charliebot feishu request. The command reads the token fromcredentials.yamlinside its own process, so no token appears in a command, an output or a run record.
API Reference
Send every request through charliebot feishu request <METHOD> <URL>:
charliebot feishu request GET 'https://open.feishu.cn/open-apis/docx/v1/documents/{doc_token}/raw_content'
charliebot feishu request POST 'https://open.feishu.cn/open-apis/suite/docs-api/search/object' \
--json '{"search_key":"query","count":10,"docs_types":["docx","wiki"]}'The command adds the bearer header itself and prints the 2xx response body. Pass a request body from a file with --data-file <path>, and add any other header with --header 'NAME:VALUE'.
| Exit code | Meaning |
| 0 | A 2xx response whose code is absent or 0. |
| 1 | Another status, a nonzero code, or a network failure. |
| 2 | Invalid arguments. |
| 3 | credentials.yaml is unreadable or a required feishu key is missing. |
Pipe the response body to jq when you need one field.
Read a Wiki Page
Wiki URLs look like: https://xxx.feishu.cn/wiki/{node_token}
Step 1 — Resolve the wiki node to get the actual document token:
GET https://open.feishu.cn/open-apis/wiki/v2/spaces/get_node?token={node_token}The response contains data.node.obj_token (the document ID) and data.node.obj_type (usually docx).
Step 2 — Fetch document content:
GET https://open.feishu.cn/open-apis/docx/v1/documents/{obj_token}/raw_contentReturns plain text in data.content.
Read a Docx Page
Docx URLs look like: https://xxx.feishu.cn/docx/{doc_token}
GET https://open.feishu.cn/open-apis/docx/v1/documents/{doc_token}/raw_contentGet Document Blocks (Structured)
For richer content with block types (headings, code, tables, etc.):
GET https://open.feishu.cn/open-apis/docx/v1/documents/{doc_token}/blocks?page_size=500Returns block tree in data.items. Use page_token from response for pagination.
Search Documents
POST https://open.feishu.cn/open-apis/suite/docs-api/search/object
Content-Type: application/json
{
"search_key": "your query",
"count": 10,
"docs_types": ["docx", "wiki"]
}Requires the search:docs:read user scope. Results are returned in data.docs_entities[], each with docs_token, docs_type, and title.
When docs_types contains "doc", search returns an empty result. Search has poor recall for every document type.
- Treat an empty result as inconclusive.
- Verify an absence claim with another search surface or a known document link.
After a recorded meeting, Feishu stores AI notes and the transcript in the meeting owner's space. Search can match these title prefixes: notes titled 智能纪要:<title> or AI notes: <title>, and transcripts titled 文字记录:<title> or Meeting transcript: <title>.
- Search returns only notes the user owns or the owner shared with the user.
- When the notes of a meeting that another person owns are not visible, ask the user for the notes link.
Public Permission
Use this to inspect or update the public-sharing policy for a docx document:
GET https://open.feishu.cn/open-apis/drive/v1/permissions/{token}/public?type=docx
PATCH https://open.feishu.cn/open-apis/drive/v1/permissions/{token}/public?type=docx
Content-Type: application/json
{
"link_share_entity": "tenant_readable"
}Use the doc token / document_id as {token}.
Required user scopes:
docs:permission.setting:readdocs:permission.setting:write_only
PATCH is a write and still requires explicit user approval before execution.
Default policy for Linear-linked docs:
link_share_entity: tenant_readableso the document is readable within the configured tenant- Do not widen to
tenant_editableunless the user explicitly asks - Do not enable external public access by default
List Wiki Space Nodes
To browse a wiki space:
GET https://open.feishu.cn/open-apis/wiki/v2/spaces/{space_id}/nodes?page_size=50Create a Document
POST https://open.feishu.cn/open-apis/docx/v1/documents
Content-Type: application/json
{
"title": "Document Title",
"folder_token": "optional_folder_token"
}Returns data.document.document_id.
To create in a specific folder, provide folder_token. Omit it to create in the user's root folder.
Add Content Blocks to a Document
POST https://open.feishu.cn/open-apis/docx/v1/documents/{document_id}/blocks/{block_id}/children
Content-Type: application/json
{
"children": [
{
"block_type": 2,
"text": {
"elements": [
{
"text_run": {
"content": "Your text here",
"text_element_style": {}
}
}
]
}
}
]
}Common block types:
2— Text paragraph3— Heading 14— Heading 25— Heading 312— Bullet (unordered list)13— Ordered list14— Code block31— Table (use two-step process below)32— Table cell (auto-created, do not insert manually)
For the top-level document block, block_id equals document_id.
Insert a Table
Tables require a two-step process: create the table block, then fill each cell.
Step 1 — Create the table (block_type 31):
POST https://open.feishu.cn/open-apis/docx/v1/documents/{document_id}/blocks/{block_id}/children
{
"children": [
{
"block_type": 31,
"table": {
"property": {
"row_size": 3,
"column_size": 2
}
}
}
]
}The response contains data.children[0].table.cells — a flat array of cell block IDs in row-major order (row0col0, row0col1, row1col0, row1col1, ...).
Step 2 — Fill each cell by adding a text block as its child:
POST https://open.feishu.cn/open-apis/docx/v1/documents/{document_id}/blocks/{cell_block_id}/children
{
"children": [
{
"block_type": 2,
"text": {
"elements": [
{
"text_run": {
"content": "Cell content",
"text_element_style": {}
}
}
]
}
}
]
}Important notes:
- Max 5 table blocks per request
- Rate limit: 3 edits/sec per document — add ~0.4s delay between cell writes
- Cell block IDs are auto-generated; do NOT create block_type 32 manually
- Header row styling is cosmetic in Feishu — first row has no special API treatment
Update a Block
PATCH https://open.feishu.cn/open-apis/docx/v1/documents/{document_id}/blocks/{block_id}
Content-Type: application/json
{
"update_text_elements": {
"elements": [
{
"text_run": {
"content": "Updated text"
}
}
]
}
}Delete Blocks
DELETE https://open.feishu.cn/open-apis/docx/v1/documents/{document_id}/blocks/{block_id}/children/batch_delete
Content-Type: application/json
{
"start_index": 0,
"end_index": 1
}Workflow Rules
- All writes still require explicit user approval first. This includes document creation, document edits, and permission changes, including the default
tenant_readablepermission update for a new Linear-linked doc. - When creating a Feishu document for a Linear issue, immediately call
PATCH https://open.feishu.cn/open-apis/drive/v1/permissions/{document_id}/public?type=docxwith{"link_share_entity":"tenant_readable"}after document creation so the doc is tenant-internal readable by default. - Do NOT widen sharing to
tenant_editableunless the user explicitly asks for edit access. - Do NOT enable external public access by default.
- Before any permission write, show the exact change and get explicit user approval first.
Token Refresh
The user access token expires every 2 hours. charliebot feishu request handles this itself: when Feishu answers 401 or an expired-token code (99991663 or 20005), the command gets an app access token from app_id and app_secret, exchanges the stored refresh_token, writes the new user_access_token and refresh_token to credentials.yaml, and retries the request once. Never mint, print or store a token by hand.
If the refresh itself fails, the command exits 1 and leaves credentials.yaml unchanged.
The refresh token lasts 30 days. If it expires, ask the user to re-authorize via OAuth.
OAuth2 Re-authorization
When the refresh token expires or new scopes are needed, the user must re-authorize:
- Print the authorize URL and open it in a browser:
charliebot feishu consent-url --scope <scope>…(repeat--scopeor list several scopes after one flag). The URL carries the app id and redirects tohttp://localhost:9999/callback. - User authorizes and gets redirected to
http://localhost:9999/callback?code=XXX. - Exchange the code:
charliebot feishu exchange-code XXX. The command gets an app access token fromapp_idandapp_secretand stores the newuser_access_tokenandrefresh_tokenin thefeishusection ofcredentials.yaml. It prints no token. - Confirm with a request, for example
charliebot feishu request GET https://open.feishu.cn/open-apis/authen/v1/user_info.
Current scopes depend on what your app has been granted; check your token's actual granted scopes.
URL Parsing
Extract tokens from Feishu URLs:
https://<tenant>.feishu.cn/wiki/WIKINODETOKENEXAMPLE0123→ node_token =WIKINODETOKENEXAMPLE0123(wiki, needs 2-step)https://<tenant>.feishu.cn/docx/DOCTOKENEXAMPLE0123→ doc_token =DOCTOKENEXAMPLE0123(direct read)
Workflow
Reading
- Send each request through
charliebot feishu request - If the user provides a URL, parse the token from the URL path
- For wiki URLs, resolve node → doc token first
- Fetch content via
raw_contentendpoint - An expired token refreshes and retries inside the command
- Present the document content to the user
Creating / Editing
- Draft the content and show it to the user for approval — do NOT write to Feishu without explicit confirmation
- Once approved, create the document and add content blocks
- If the document is created for a Linear issue and the user approved the permission write, immediately set its public permission to tenant-internal readable by calling
PATCH https://open.feishu.cn/open-apis/drive/v1/permissions/{document_id}/public?type=docxwith{"link_share_entity":"tenant_readable"} - Return the document URL to the user:
https://<tenant>.feishu.cn/docx/{document_id} - Do not widen the document to
tenant_editableunless the user explicitly asks - Do not enable external public access by default
Linking with Linear
- Title format:
{identifier} {title}— e.g.ABC-123 Example Linear issue title - When a doc exists, each Linear issue maps to at most one Feishu doc — subsequent updates append to the same doc, never a new one
- After creating the doc and getting explicit user approval for the permission write, set its public permission with
PATCH https://open.feishu.cn/open-apis/drive/v1/permissions/{document_id}/public?type=docxand{"link_share_entity":"tenant_readable"}, then update the Linear issue description to include the Feishu doc URL - Organize by date: Feishu docs linked from Linear issues are living documents with ongoing updates. Structure content with H1 date headers (e.g.
# 2026-03-26) as top-level sections. Each day's work goes under its date. New updates append a new date section — never overwrite previous dates. - Use Pacific Time (PT) for dates — all date headers use
America/Los_Angelestimezone, not UTC. RunTZ=America/Los_Angeles date +%Y-%m-%dto get the correct date.
Content conventions
For docs linked to a Linear issue, the division of content between the issue and
the doc is defined in the linear skill (Content conventions).
Other versions9 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 9
- shiwenwen/hope-agent★ 1.9ksame name
- AceDataCloud/Skills★ 17same name
- csrhandsome/my_skills★ 4same name
- tinqiao-oss/clawtouch-skills★ 4same name
- zhenzoo/link16-agent-infra★ 4same name
- xiangu152/my_claude_skills★ 2same name
- JakkuSakura/skills★ 1same name
- jinsi-ai/agent-skills★ 0same name
- nearthink/agent-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Used alongsideProjects with it also use agent-browser and skill-creator.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
VercelSkillagent-browser
Automates browser interactions for web testing, form filling, screenshots, and data extraction. Use when the user needs to navigate websites, interact with web pages, fill forms, take screenshots, test web applications, or extract information from web pages.
Also in 3 projects that use this
SentrySkillskill-creator
Create new agent skills following the Agent Skills specification. Use when asked to "create a skill", "add a new skill", "write a skill", "make a skill", "build a skill", or scaffold a new skill with SKILL.md. Guides through requirements, writing, registration, and verification.
Also in 3 projects that use this
In this repository21 other files it gives its agents.
- AGENTS.mdAGENTS.md
- charliebotSkill
- claude-versionSkill
- cli-tool-trapsSkill
- file-serverSkill
- gmailSkill
- google-docsSkill
- google-oauthSkill
- google-sheetsSkill
- improve-goalSkill
- improve-workerSkill
- language-portSkill
- linearSkill
- llm-context-guidelineSkill
- perfettoSkill
- plan-approvalSkill
- pytorch-gpu-trainingSkill
- skill-managementSkill
- slackSkill
- voice-notesSkill
- writing-styleSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
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.

