English | 简体中文
Feishu ↔ Markdown two-way sync toolkit. Download Feishu docx/wiki as markdown (with metadata-based incremental cache). Upload markdown to Feishu (auto-detects LaTeX formulas and renders them correctly). Upload CSV/MD-table/TSV directly as Feishu Sheets.
For anyone using Feishu: developers, technical writers, knowledge management teams, AI agent users. Portable, self-installing dependencies, actionable errors, no hardcoded business identifiers.
Three ways to use it (pick any):
- As a Claude Code skill — after
bash install.sh, trigger via natural language in Claude Code conversations - As a standalone bash CLI — run
bash bin/download.sh <url>/bash bin/upload.sh <md>directly, no agent framework required - As a tool in any AI agent framework — integrate as a tool in Multica / LangChain / your own runtime; the agent self-clones and self-installs
- Two-way: download (docx / wiki spaces, with metadata cache) + upload (with formula rendering)
- Thin orchestration + 3-layer fallback: don't reinvent wheels — just route decisions and assemble dependencies; falls back to stdlib if any external dep is missing
- Download prefers feishu-docx (high-fidelity); falls back to built-in
bin/download-lite.py(pure stdlib raw_content) if missing - Upload with formulas uses feishu-markdown-uploader (LaTeX → real equation block, not inline-degraded); falls back to feishu-docx if missing
- Upload without formulas uses feishu-docx; falls back to uploader if missing
- Download prefers feishu-docx (high-fidelity); falls back to built-in
- Dedicated table channel: CSV/MD-table/TSV → Feishu Sheets (Excel-like standalone page), pure stdlib, zero extra dependencies
- Agent-friendly: self-installs deps on first call; failures come with explicit error codes and fix recipes
- Portable: zero hardcoded business identifiers, one set of scripts works for any Feishu/Lark tenant
- Open knowledge: permission model / error code manual / auth modes — all distilled from real testing
feishu-sync is complementary, not a replacement, to projects like riba2534/feishu-cli:
| feishu-cli | feishu-sync | |
|---|---|---|
| Positioning | Full-stack Feishu CLI (Swiss Army knife) | Knowledge sync + table import (specialized chisel) |
| Command count | 200+ across docs/sheet/wiki/msg/calendar/task/meeting | 3 focused: download / upload / upload-sheet |
| LaTeX formulas | Inline-degraded (per its README) | Real equation block via feishu-markdown-uploader |
| Metadata-based incremental cache | Not supported | ✅ --cache-mode auto/force/skip, compares revision_id |
| CSV/TSV → standalone Feishu Sheet | Not supported | ✅ 13 flags incl. styling, --literal, --update |
| Three-layer fallback (stdlib safety net) | Not supported | ✅ download-lite.py keeps base capability alive when feishu-docx is missing |
Use both together: install feishu-cli for full-stack Feishu coverage, and feishu-sync whenever you specifically need incremental wiki sync, CSV→Sheet imports, or true LaTeX equation rendering. The scopes don't overlap.
- Individual developers / technical writers — publish local markdown (papers, technical notes, blog drafts) to Feishu spaces, including LaTeX formulas
- Knowledge management teams — batch sync Feishu wiki/docx to local files for AI analysis, review, full-text search
- Claude Code users — after install, just say "upload this md to Feishu" or "pull this wiki for analysis" in Claude conversations
- AI agent developers — integrate as a tool in any agent framework (Multica, LangChain, AutoGen, custom runtime)
- CI / automation scripts — schedule pulls of Feishu cloud documents (with metadata cache, saving bandwidth), or auto-publish weekly reports / data tables
- Data analysts — one-shot upload CSV/TSV as Feishu Sheets (with styling), team can collaborate online with filtering
- Feishu self-built app: create at https://open.feishu.cn/app, get
APP_ID+APP_SECRET - App identity scopes (your app admin enables and publishes on the open platform):
- Read:
wiki:wiki:readonly+docx:document:readonly - Write docx:
docx:document+drive:drive - Write spreadsheet:
sheets:spreadsheet(includes create + read/write); using--folderalso requiresdrive:drive
- Read:
- Runtime: bash + python3 (>=3.6) + git (macOS / Linux) required. Full features additionally need Python 3.8+/feishu-docx + Node 18+/uploader (high-fidelity download + LaTeX rendering). Minimum: bash + python3 alone works —
download.shauto-degrades to stdlib raw_content,upload-sheet.shis pure stdlib with zero external deps.
Via vercel-labs/skills (16k stars, cross-agent standard tool, supports 45+ agents including Claude Code / Cursor / Codex / OpenCode):
# Install globally (recommended)
npx skills add 0xE1337/feishu-sync -g
# Then run dependency setup once (optional — minimum mode doesn't need it)
cd ~/.claude/skills/feishu-sync && bash bin/setup.shSkipping
setup.shworks too —download.shauto-falls back to stdlib,upload-sheet.shis pure stdlib.setup.shexists to install feishu-docx (high-fidelity download) + uploader (LaTeX rendering); only needed for full features.
In a Claude Code conversation:
/plugin marketplace add 0xE1337/feishu-sync
/plugin install feishu-sync@feishu-sync
git clone https://github.com/0xE1337/feishu-sync ~/code/feishu-sync
cd ~/code/feishu-sync
bash install.sh # symlink to ~/.claude/skills/feishu-sync + install deps
bash install.sh --no-deps # install skill only, skip deps
bash install.sh --copy # copy instead of symlink (offline / Windows)install.sh does two things: ① symlink to ~/.claude/skills/feishu-sync ② run bin/setup.sh to install deps.
cp .env.example .env
# Edit .env, fill in real FEISHU_APP_ID / FEISHU_APP_SECRET
source .envbash bin/probe.sh # creds + token
bash bin/probe.sh --wiki "https://xxx.feishu.cn/wiki/YYY" # also verify wiki readableAll three steps green = ready.
bash bin/download.sh "https://xxx.feishu.cn/docx/<token>" -o ./out/bash bin/download.sh "https://xxx.feishu.cn/wiki/<root_token>" -o ./out/ --recursivedownload.sh defaults to metadata comparison: if remote revision_id / obj_edit_time matches local, skip the download.
# auto (default): compare metadata, skip download on hit
bash bin/download.sh "https://xxx.feishu.cn/docx/<token>" -o ./out/
# force: re-download, overwrite local (including .meta)
bash bin/download.sh "https://xxx.feishu.cn/docx/<token>" -o ./out/ --cache-mode force
# skip: use local copy only, no network (single docx URL only; errors if no copy exists)
bash bin/download.sh "https://xxx.feishu.cn/docx/<token>" -o ./out/ --cache-mode skip
# Or via env var (CLI flag takes precedence)
CACHE_MODE=force bash bin/download.sh <URL> -o ./out/Cache metadata lives in <out>/.meta/<obj_token>.json. Constraint: full wiki recursion (--recursive) + the feishu-docx path doesn't yet support per-node cache and behaves like force, re-downloading the whole space. For per-node caching, use the lite path (uninstall feishu-docx to trigger auto-fallback, or call python3 bin/download-lite.py <wiki_url> --recursive --cache-mode auto directly).
# No formulas → uses feishu-docx create
bash bin/upload.sh ./note.md --title "My note"
# Has $...$ or $$...$$ → auto-routes to uploader
bash bin/upload.sh ./paper.md --title "Paper"
# Force uploader path (even if no formulas detected)
bash bin/upload.sh ./x.md --force-latex
# Specify Feishu folder_token
bash bin/upload.sh ./x.md --folder fldcn_xxxxupload.sh falls back both ways: when feishu-docx is unavailable it uses uploader; when uploader is unavailable it uses feishu-docx — only fails if neither is installed.
Difference:
upload.shabove treats markdown as a whole docx document, where tables become markdown table blocks;upload-sheet.shbelow uploads a single table as a standalone spreadsheet, producing an Excel-like Feishu page with online filter/sort/formula editing.
# CSV → standalone Feishu spreadsheet
# Default styling: bold header + light-blue background (#E8F0FE) + center align / freeze first row / autosize columns
bash bin/upload-sheet.sh ./data.csv --title "Q1 Sales"
# Pull the first GFM table from a markdown file (other paragraphs/headings ignored)
bash bin/upload-sheet.sh ./report.md --title "Demo"
# TSV / explicit format
bash bin/upload-sheet.sh ./data.tsv --title "Raw logs"
bash bin/upload-sheet.sh ./data.txt --format csv --title "No extension"
# Specify Feishu folder
bash bin/upload-sheet.sh ./data.csv --title "Q1 Sales" --folder fldcn_xxxx
# Dry-run: parse + print request skeleton, no actual API call
bash bin/upload-sheet.sh ./data.csv --dry-run
# Disable all styling, write data only
bash bin/upload-sheet.sh ./data.csv --plain
# Granular style toggles (combine freely)
bash bin/upload-sheet.sh ./data.csv --no-freeze # don't freeze first row
bash bin/upload-sheet.sh ./data.csv --no-autosize # don't autosize columns
bash bin/upload-sheet.sh ./data.csv --no-header-style # don't bold header
# Customize header background color (default light blue #E8F0FE)
bash bin/upload-sheet.sh ./data.csv --header-bg "#FFE5E5"
# RAW mode: preserve leading zeros, don't recognize scientific notation, treat = as plain text
bash bin/upload-sheet.sh ./flight-numbers.csv --literal
# Refresh existing spreadsheet content (no new sheet; pass URL or raw token)
bash bin/upload-sheet.sh ./weekly.csv --update "https://my.feishu.cn/sheets/XYZ"On success prints [DONE] https://xxx.feishu.cn/sheets/<token>.
Data fidelity (verified against real Feishu API):
- Default
USER_ENTEREDmode: pure numbers parsed as int/float (including scientific notation1.23e10), booleans auto-detected by Feishu, leading-zero values like007preserved as strings, formula-like strings such as=SUM(...)get a leading'to prevent injection --literalRAWmode: everything as string — use for code snippets, IDs, or to preserve specific data formats
Constraints (Feishu side): max 5000 rows × 100 columns per write; cell ≤ 40000 chars. Exceeding fails fast before the call.
After install.sh, the skill feishu-sync is immediately usable. Trigger it via natural language in Claude Code conversations — the skill guides you through choosing download/upload and the relevant parameters.
Skill entry point: SKILL.md
This repo is designed as a general AI agent toolkit for Feishu — any agent runtime that can git clone + run bash can integrate it. The agent self-clones and self-installs at startup, then uses tenant_access_token to read/write Feishu directly with no human intervention.
Known integrations:
- Multica — detailed integration guide at docs/multica-integration.md (custom_env config + self-install instructions + task protocol)
- Other agent frameworks (LangChain Tools, AutoGen Skills, custom runtimes, etc.) — adapt by analogy with the Multica example. Three things matter: ① inject
FEISHU_APP_ID/SECRETinto the runtime env ② runbash install.shin the agent startup script ③ exposebin/*.shas agent-callable commands
If you've integrated a new agent framework, PRs adding an adapter doc under docs/ are welcome.
feishu-sync/
├── README.md / README_zh.md (English / 简体中文)
├── LICENSE (MIT)
├── SKILL.md (Claude Code skill entry; placed at root → npx skills add picks it up)
├── install.sh / uninstall.sh
├── .env.example
│
├── .claude-plugin/ (Claude Code native /plugin install support)
│ ├── plugin.json - plugin manifest (name/version/author/keywords)
│ └── marketplace.json - single-plugin marketplace (this repo IS its own marketplace)
│
├── bin/ (executable scripts)
│ ├── setup.sh - idempotent dependency installer
│ ├── probe.sh - self-check
│ ├── token.sh - fetch tenant_access_token
│ ├── download.sh - download router (feishu-docx → stdlib fallback, with --cache-mode)
│ ├── download-lite.py - pure stdlib download impl (fallback + cache probe/save-meta subcommands)
│ ├── upload.sh - upload router (with LaTeX detection + bidirectional fallback)
│ ├── upload-sheet.sh - single table → Feishu spreadsheet (thin wrapper)
│ ├── upload-sheet.py - upload-sheet implementation (pure stdlib, CSV/TSV/MD-table parsing + styling + Sheets API)
│ └── test-upload-sheet.py - upload-sheet mock integration tests (76 assertions)
│
├── docs/ (knowledge distilled from real testing)
│ ├── permission-model.md - Feishu's 3-layer permission model
│ ├── error-codes.md - actionable error code manual
│ ├── auth-modes.md - auth mode selection (CDP / OAuth / Tenant)
│ └── multica-integration.md - AI agent integration example (Multica; analogize for other runtimes)
│
└── examples/ (runnable examples)
├── download-wiki-space.sh
├── upload-with-latex.sh
├── upload-sheet.sh - end-to-end: CSV → Feishu spreadsheet
└── upload-sheet-literal.sh - default vs --literal mode comparison
- Thin orchestration > heavy implementation: if an existing tool does it, don't write your own
- Let the caller pass links/parameters: zero hardcoded values in scripts; switching tenants/projects requires no code change
- Self-diagnostic:
setup.sh+probe.shlet agents diagnose their environment independently - Actionable errors: every failure point maps to a specific fix recipe in
docs/error-codes.md— no staring at a wall - Graceful degradation: when external dependencies (feishu-docx / uploader) are missing, fall back to stdlib or to each other; when LaTeX detection fails, retry via feishu-docx — base capability never breaks
When something breaks, run bash bin/probe.sh first to see which step fails. Common error code cheat sheet:
| Code | Meaning | Quick fix |
|---|---|---|
99991672 |
Insufficient app identity scope | Add scope on open platform + publish a new version |
131006 |
Not a member, or wiki not public | Read: add app as wiki member; Write: add edit role |
20027 |
Insufficient OAuth scope | Use OAuth2Authenticator(scopes=[...]) to request only the minimum set |
20029 |
redirect_uri mismatch | Add http://127.0.0.1:9527/ (with trailing slash) under open platform → security settings |
Full manual at docs/error-codes.md.
This project stands on the shoulders of these tools:
- feishu-docx — Python SDK + CLI, the core of the download path
- feishu-markdown-uploader — Node uploader, exclusive LaTeX equation rendering
- feishu-markdown — the underlying markdown → Feishu blocks library that uploader depends on
What we add is decision routing and knowledge distillation — not reinventing wheels.
PRs welcome. When opening one, please:
- Don't commit real
FEISHU_APP_ID/FEISHU_APP_SECRET(.gitignorealready filters.env) - Don't put concrete business wiki links or tokens in
examples/ordocs/ - New error code handling → update docs/error-codes.md
- New auth path → update docs/auth-modes.md