Create Feishu cloud documents from local Markdown files, or append-import Markdown into an existing document.Supports conversion of Mermaid/PlantUML diagrams to Feishu whiteboards, intelligent handling of large tables (rows > 9 appended via single-block API; columns > 9 split while retaining the first column)。
Owner Rules: After creating a new document, if it needs to be delivered to a user, first parse
FEISHU_OWNER_EMAILor the config fileowner_email. Only grantfull_accesswhen an owner is resolved; only transfer ownership whentransfer_ownership=true. Do not treat the example email as a real recipient.
Core Features
- Three-stage concurrent pipeline: sequential block creation → concurrent processing of diagrams/tables → failure fallback
- Mermaid/PlantUML → Feishu Whiteboard:
mermaid/plantuml/pumlcode blocks are automatically converted to Feishu whiteboards - Diagram fault tolerance: syntax errors automatically degrade to code block display, server errors automatically retry (default up to 10 times, adjustable via
--diagram-retries) - Intelligent handling of large tables: when rows > 9, create an initial 9-row table +
insert_table_rowAPI appends to the same block (visually continuous, about 1 API round trip per row; in verbose mode, progress is printed for ≥ 5 rows); when columns > 9, split by column groups while retaining the first column as an identifier.Cell content filling now usesbatch_updatebatch acceleration (v1.29+, #159): stage two preheatscellMapthen writes in batches at once (single-group cells ≤ 30 per batch), falling back to per-cell on failure; a typical 4×6×8 table goes from ~70s to ~3s (25-30x) - Table column widths: by default based on content heuristics (Chinese 14px / English 8px, minimum 80px, maximum 400px). Can be globally overridden via a comment immediately above the table
<!-- feishu-colwidth: 80,200,*,30% -->(units px / percentage /*uses auto) or the CLI flag--table-column-width=auto|fixed|N1,N2,...; comments take precedence over the flag - Automatic API rate-limit retry: automatically retries on HTTP 429 during whiteboard creation and diagram import, reads the server's
x-ogw-ratelimit-resetresponse header to precisely calculate backoff time, uses an exponential backoff strategy, and retries up to 10 times by default - Concurrency control: diagrams and tables each use independent worker pools (default 5 concurrent for diagrams, 3 for tables)
- True embedding of table cell images (#164): local/network images inside Markdown table cells are truly embedded as Image sub-blocks within the cell after table filling is complete (stage 2.5), rather than being lost or degraded to text. Details: pure image cells do not concatenate the image caption (alt) into extra title text; images that fail to embed or cells that are misaligned are counted in the statistics
cell_image_failedand printed, not silently discarded; empty image blocks that fail to upload are cleaned up and placeholder text is added. Onlydoc importuses true embedding,doc add/content-updateand other non-import scenarios degrade cell images to[图片: 说明]placeholder text. JSON output addscell_image_total/success/failed
Core Concepts
Markdown as an intermediate state: conversion between local documents and Feishu cloud documents is performed via the Markdown format.
Boundary clarification: This skill only supports importing Markdown source text. To import binary formats such as Word/Excel, use the
feishu-cli doc import-fileorfeishu-cli-driveskill'sdrive import。
If the user's goal is to "turn tables in Markdown into Feishu spreadsheets", do not use doc import, instead use:
feishu-cli sheet import-md report.md --title "报表"
Prerequisites
- feishu-cli: If not yet installed, go to riba2534/feishu-cli to get installation instructions
- App Token configured (
FEISHU_APP_ID+FEISHU_APP_SECRET), no need forauth login - Markdown files use UTF-8 encoding (the CLI will use
utf8.Validto reject invalid UTF-8 byte sequences; theU+FFFDreplacement character contained in valid UTF-8 will not be blocked, so it is recommended to search for it in the editor first)
Usage
# 创建新文档
feishu-cli doc import ./document.md --title "文档标题"
# 追加导入到已有文档(不会原地替换)
feishu-cli doc import ./document.md --document-id <existing_doc_id>
# 上传本地图片
feishu-cli doc import ./document.md --title "带图文档" --upload-images
Execution Flow
Create a New Document
-
Validate File
- Check whether the Markdown file exists
- Preview file content
- Encoding validation: CLI built-in
utf8.Validvalidation, directly rejects import when encountering invalid UTF-8 bytes; theU+FFFDreplacement character remaining in valid UTF-8 will not be blocked, so it is recommended to search globally for�
-
Execute Import
feishu-cli doc import <file.md> --title "<title>" [--upload-images] -
Add Permissions(only when owner is configured)
feishu-cli perm add <document_id> --doc-type docx --member-type email --member-id <owner_email> --perm full_access --notification -
Transfer Document Ownership(only when
transfer_ownership=true)feishu-cli perm transfer-owner <document_id> --doc-type docx --member-type email --member-id <owner_email> --notification -
Send Notification Send a Feishu message to notify the user that the document has been created
Append Import to an Existing Document
--document-id will not replace existing content, it will only append the blocks converted from Markdown to the end of the document. To modify/overwrite existing content, use feishu-cli doc content-update(see feishu-cli-write skill)。
-
Execute Append Import
feishu-cli doc import <file.md> --document-id <doc_id> [--upload-images] -
Notify User
Parameter Description
| Parameter | Description | Default Value |
|---|---|---|
| markdown_file | Markdown file path | Required |
| --title | New document title | File name |
| --document-id | Append import to an existing document | Create a new document |
| --upload-images | Upload local and network images to Feishu | Yes (enabled by default) |
| --image-workers | Number of concurrent image uploads | 2 (API limit 5 QPS) |
| --folder, -f | Target folder Token for the new document | Root directory |
| --diagram-workers | Number of concurrent diagram (Mermaid/PlantUML) imports | 5 |
| --table-workers | Number of concurrent table fills | 3 |
| --table-column-width | Column width strategy:auto / fixed / N1,N2,...(pixel list,* uses auto) |
auto |
| --diagram-retries | Maximum number of diagram retries | 10 |
| --verbose | Show detailed progress information | No |
Supported Markdown Syntax
- Headings (# ~ ######)
- Paragraph text
- Unordered/ordered lists (supports unlimited nesting depth and mixed nesting)
- Task lists (- [ ] / - [x])
- Code blocks (with language identifier)
- Mermaid/PlantUML diagrams → automatically converted to Feishu whiteboards
- Blockquotes(supports nested quotes, automatically converted to QuoteContainer)
- Callout highlight blocks(
> [!NOTE]、> [!WARNING]and 6 other types) - Horizontal rule
- Images(by default, automatically uploads local and network images via
--upload-images; without this parameter, creates placeholder blocks.Images inside table cells are actually embedded as in-cell images, see core feature #164; inline images mixed with text are uniformly converted to[图片: 说明]placeholders, http(s) are clickable links) - Tables(rows > 9 are appended via the
insert_table_rowAPI to keep a single block; columns > 9 are split by column group while preserving the first column;images can be placed inside cells and are truly embedded after import) - Bold, italic, strikethrough, inline code,underline(
<u>文本</u>) - Links
- Inline formulas(
$E = mc^2$, supports multiple formulas in one paragraph) - Block-level formulas(
$$formula$$or standalone line$formula$)
Diagram examples (Mermaid recommended)
```mermaid
flowchart TD
A[开始] --> B{判断}
B -->|是| C[处理]
B -->|否| D[结束]
```
```plantuml
@startuml
Alice -> Bob: Hello
Bob --> Alice: Hi
@enduml
```
Supported Mermaid diagram types (all verified):
- ✅ flowchart (flowchart, supports nested subgraph)
- ✅ sequenceDiagram (sequence diagram)
- ✅ classDiagram (class diagram)
- ✅ stateDiagram-v2 (state diagram)
- ✅ erDiagram (ER diagram)
- ✅ gantt (Gantt chart)
- ✅ pie (pie chart)
- ✅ mindmap (mind map)
Callout highlight block examples
> [!NOTE]
> 这是一个提示信息。
> [!WARNING]
> 这是一个警告信息。
> [!TIP]
> 这是一个技巧提示。
> [!CAUTION]
> 这是一个警示。
> [!IMPORTANT]
> 这是一个重要信息。
> [!SUCCESS]
> 这是一个成功信息。
Callouts support child blocks internally (paragraphs, lists, etc.), automatically created as child blocks of the Callout.
Background color mapping:
| Type | Background color |
|---|---|
| NOTE/INFO | Blue (6) |
| WARNING | Red (2) |
| TIP | Yellow (4) |
| CAUTION | Orange (3) |
| IMPORTANT | Purple (7) |
| SUCCESS | Green (5) |
Formula examples
行内公式:爱因斯坦质能方程 $E = mc^2$ 是最著名的公式。
块级公式(独立行):
$\int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}$
- Inline formulas support multiple
$...$formulas within one paragraph - Block-level formulas are created in Feishu as Equation elements within a Text block
- Formula content preserves the original LaTeX
Underline examples
这段文本包含 <u>下划线</u> 样式。
Output format
已导入文档!
文档 ID: <document_id>
文档链接: https://feishu.cn/docx/<document_id>
导入块数: 25
Examples
# 创建新文档
feishu-cli doc import ./meeting-notes.md --title "会议纪要"
# 追加导入到现有文档
feishu-cli doc import ./updated-spec.md --document-id <document_id>
# 带图片导入(自动上传本地和网络图片)
feishu-cli doc import ./blog-post.md --title "博客文章" --upload-images
# 批量导入(一次循环多个 Markdown)
for f in *.md; do feishu-cli doc import "$f" --title "${f%.md}" --upload-images; done
Verified features
All syntax listed in the above "Supported Markdown syntax" has been tested and verified, and all works properly. For specific handling details of tables/images/videos, see the "Core Features" and "Supported Markdown Syntax" sections above; below only large-scale test results are listed.
Large-scale test results
Large documents verified to import successfully:
- 10,000+ lines of Markdown ✓
- 127 Mermaid diagrams → all successfully converted to Feishu boards ✓
- 170+ tables(including 17 rows × 5 columns single-block continuous appending, column splitting for more than 9 columns, automatic column width calculation) → all successful ✓
- 8 diagram types → flowchart/sequenceDiagram/classDiagram/stateDiagram/erDiagram/gantt/pie/mindmap all successful ✓
- 88 Mermaid diagrams tested one by one → 82/88 successful, 6 failed (3 server-side transient errors + 2 curly-brace syntax + 1 extraction exception)
Three-stage concurrent pipeline architecture
- Stage one (sequential): create all document blocks, collect diagram (Mermaid/PlantUML) and table tasks
- Stage two (concurrent):Use a worker pool to concurrently process diagram import and table filling. For table cell filling, first warm up
cellMap,then go through thebatch_updateAPI for batch writes (single-group cells ≤ 30 per batch), falling back to per-cell only when the batch fails; for rows > 9,insert_table_rowappends are still serial row by row (throttled by the single-document 3 QPS limit) - Phase 3 (reverse order):Handle failed diagrams → delete the empty board block, insert a code block as a fallback display
Mermaid known limitations
| Limitation | Description | Handling method |
|---|---|---|
{} curly braces |
The Mermaid parser treats {text} as a diamond node |
Automatically fall back to a code block |
par...and...end |
The Feishu parser does not support par parallel syntax at all | Use Note over X: 并行执行 instead |
| Combined rendering complexity exceeds the limit | A single factor will not trigger it, but when 10+ participants + 2+ alt blocks + 30+ long message labels are combined, the server returns 500 | Fall back to a code block after retrying |
| Transient server error | Occasional HTTP 500 (caused by concurrency pressure) | Automatic retry (default up to 10 times, exponential backoff) |
| Parse error is not retried | Syntax errors fall back directly | Automatically fall back to a code block |
Rendering complexity safety threshold(measured by binary search):
- participant ≤8 or alt ≤1 or short message labels → safe
- 10 participants + 2 alt + 30 long message labels → exceeds the limit
- Recommendation: keep sequenceDiagram participant ≤8, alt ≤1, and message labels short
Technical notes
Diagrams are imported via the Feishu Board API:
- API endpoint:
/open-apis/board/v1/whiteboards/{id}/nodes/plantuml syntax_type=1indicates PlantUML syntax,syntax_type=2indicates Mermaid syntaxdiagram_typeuses an integer (0=auto, 6=flowchart, etc.)- Retry strategy: exponential backoff + read the
x-ogw-ratelimit-resetresponse header for precise backoff, default up to 10 times; Parse error and Invalid request parameter are not retried - Failure fallback: delete the empty board block and insert a code block in the original position
- Supported code block identifiers:
```mermaid、```plantuml、```puml
HTML tag extension syntax
In addition to standard Markdown syntax, the following extension syntax in the form of HTML tags is also recognized during import. These tags are automatically generated by the export side and support roundtrip (export→import without losing information).
| Tag | Description | Example |
|---|---|---|
<mention-user id="ou_xxx"/> |
@user | Create a MentionUser element |
<mention-doc token="xxx" type="docx">标题</mention-doc> |
@document | Create a MentionDoc element |
<grid cols="2"><column>...</column><column>...</column></grid> |
Column layout | Create a Grid Block + GridColumn child block |
<callout type="NOTE">内容</callout> |
Highlight block (HTML tag form) | Equivalent to > [!NOTE] equivalent |
<whiteboard type="blank"/> |
Blank board | Create a Board Block |
<sheet rows="5" cols="5"/> |
Spreadsheet | Create a Sheet Block |
<bitable view="table"/> |
Bitable | Create a Bitable Block |
<image token="xxx" width="800" align="center" caption="说明"/> |
Image with attributes | Create an Image Block, preserving size/alignment |
<file token="xxx" name="report.pdf" view-type="1"/> |
File Block | Create File Block |
<video src="./demo.mp4" data-name="demo.mp4" data-view-type="1"></video> |
Video Block (v1.22+) | Create File Block (type=23), recognizing extensions such as mp4/mov/avi/mkv as videos;src is a local path or an uploaded token; single file ≤ 20MB direct upload |
These tags are mainly used in roundtrip scenarios (export then re-import), and can also be written manually for precise control of Feishu block types.
Video import concurrency: shares the worker pool with images (default 2 concurrent, limited by API 5 QPS), import statistics include video_total/success/failed/skipped. Verbose mode prints the upload progress of each video.
FAQ
| Symptom | Cause | Solution |
|---|---|---|
| Authentication failed / Token expired | Not logged in or Token has expired | Run feishu-cli auth login to re-authenticate (Device Flow, automatically injects offline_access) |
| Diagram downgraded to code block | Mermaid/PlantUML syntax incompatible with Feishu rendering engine | Refer to references/doc-guide.md to adjust syntax (no curly braces, no par, etc.) |
| Importing very long tables takes significantly longer | Cell content filling already uses batch_update batch acceleration (v1.29+, ~25-30x); the main time cost comes from, when rows > 9, insert_table_row API appending row by row seriallyto the same block (throttled by the single-document 3 QPS limit, about 1 API round trip per row) |
This is normal behavior; verbose mode prints progress every 5 rows. When the number of rows is extremely large (200+), it is recommended to use a spreadsheet (Sheet) instead |
| Table split into multiple blocks | When columns > 9, the CLI splits by column groups (each group ≤ 9 columns), with the first column retained as an identifier in all groups | This is normal behavior, preventing rows from being unrecognizable after splitting |
| Image upload failed | Network unreachable or image URL inaccessible | Check network connectivity; failed images will automatically create placeholder blocks and will not affect the overall import |
| Document created successfully but cannot be edited | Permissions not added according to owner configuration | Set FEISHU_OWNER_EMAIL then run perm add; only when transfer_ownership=true then run perm transfer-owner |