LarkFS
Mount Lark/Feishu as a local filesystem — FUSE & WebDAV
将飞书/Lark 的资源映射为本地可读写的文件目录。核心路径覆盖 Drive、Wiki、IM、Calendar、Tasks、Mail、Meetings,并通过控制节点补充 Approval、Base、Contact、Docs、Minutes、Sheets、VC、_system 等命令型能力。
Why
cat /mnt/lark/wiki/产品文档/PRD.md — 直接用终端 / 编辑器读写飞书文档
ls /mnt/lark/im/团队群/ — 浏览消息、发送文本
echo "明天 10:00 周会" > /mnt/lark/calendar/_create.md — 创建日历事件
- 在 Finder / Nautilus 中拖拽文件到飞书云空间
Features
| 能力 |
说明 |
| FUSE 挂载 |
POSIX 风格语义,像本地目录一样 ls / cat / vim / cp |
| WebDAV 模式 |
无需内核模块,Finder / 文件管理器直连 |
| macOS Desktop app(预览) |
SwiftUI 宿主 app,汇总认证/挂载/健康状态,并开始接入 File Provider 原生挂载 |
| 多类型文档 |
docx → Markdown, sheet → 目录/CSV, bitable → 目录/JSONL, file → 原样下载 |
| 多域映射 |
Drive · Wiki · IM · Calendar · Tasks · Mail · Meetings · Approval · Base · Contact · Docs · Minutes · Sheets · VC · _system |
| 同名冲突解决 |
自动 name~token 后缀,持久化映射保证路径稳定 |
| 三级缓存 |
in-memory → 磁盘 LRU ContentCache → 远程拉取,TTL 自动过期 |
| 重试 & 认证恢复 |
API 限流自动指数退避,token 过期自动刷新 |
| 清晰错误语义 |
FUSE/WebDAV 会区分只读、未找到、不支持等错误,避免客户端只看到泛化 I/O error |
| 守护进程 |
后台运行、PID 管理、优雅关闭、stale mount 自动清理 |
| 跨平台 |
macOS (macFUSE / Fuse-T) + Linux (FUSE3) |
| CI/CD |
GitHub Actions + GoReleaser 自动发布多平台二进制 |
Quick Start
Prerequisites
- lark-cli —
npm install -g @larksuite/cli
- FUSE (仅 FUSE 模式需要):
- macOS:
brew install macfuse 或 brew install macos-fuse-t/homebrew-cask/fuse-t
- Linux:
apt install fuse3
Install
# Go install
go install github.com/IchenDEV/larkfs/cmd/larkfs@latest
# 或从 Releases 下载预编译二进制
# https://github.com/IchenDEV/larkfs/releases
Setup
# 一键初始化:检测 lark-cli → 配置应用 → OAuth 登录
larkfs init
larkfs init 会自动引导完成以下步骤:
- 检查 lark-cli 是否安装
- 若未配置,运行
lark-cli config init --new 创建应用
- 若未登录,运行
lark-cli auth login --domain all 获取授权
Usage
# 检查环境(lark-cli 配置、认证、连通性、FUSE)
larkfs doctor
# WebDAV 模式(推荐,无需 FUSE)
larkfs serve --port 8080
# 挂载(前台)
larkfs mount ~/lark
# 挂载(后台守护进程)
larkfs mount ~/lark -d
# 只读模式
larkfs mount ~/lark --read-only
# 指定域
larkfs mount ~/lark --domains drive,wiki,calendar
# 查看状态
larkfs status
# 卸载
larkfs unmount ~/lark
# 卸载全部
larkfs unmount --all
Desktop App Preview
macOS 仓库内现在带了一个 SwiftUI 宿主 app,用来读取 larkfs 的 JSON 状态输出,并承接后续 File Provider 原生挂载方案:
./script/build_and_run.sh
仓库里也已经有 File Provider 的起步代码:larkfs native item/list/fetch 提供只读 bridge,apps/LarkFSDesktop/FileProviderExtension 提供可编译的 NSFileProviderReplicatedExtension。脚本会优先用 Xcode project 构建带 .appex 的 app;要让 Finder 接受插件,需要本机有 Apple Development / Developer ID 签名身份:
LARKFS_DEVELOPMENT_TEAM=<TEAM_ID> ./script/build_and_run.sh
更多设计说明见 docs/macos-native-mount.md。
Directory Layout
~/lark/
├── drive/ # 云空间
│ ├── 项目文档.md # docx → Markdown (读写)
│ ├── 数据表.sheet/ # spreadsheet → 目录
│ │ ├── _meta.json
│ │ └── Sheet1.csv # 每个 sheet → CSV (读写)
│ ├── 多维表格.base/ # bitable → 目录
│ │ ├── _meta.json
│ │ └── 表1.jsonl # 每张表 → JSONL (读写)
│ └── 设计稿.sketch # 普通文件 → 原样下载
├── wiki/ # 知识库
│ └── 产品空间/
│ ├── PRD.md # wiki node → docx → Markdown
│ └── 数据看板.sheet/
├── im/ # 即时消息
│ └── 产品群/
│ ├── latest.md # 最新消息 (只读)
│ ├── _send.md # 写入即发送
│ └── files/ # 群文件
├── calendar/ # 日历
│ ├── 周一站会.md # 事件详情 (只读)
│ └── _create.md # 写入即创建事件
├── tasks/ # 任务
│ ├── 完成设计评审.md # 任务详情
│ └── _create.md # 写入即创建任务
├── mail/ # 邮箱
│ ├── INBOX/
│ │ └── 2026-04-07_张三_会议通知.md
│ ├── _compose.md # 写入即发送
│ └── _send.md
└── meetings/ # 会议
└── 2026-04-07/
└── 产品评审/
├── _meta.json # 会议元数据
├── summary.md # AI 摘要
├── todos.md # 待办提取
├── transcript.md # 逐字稿
└── recording.mp4 # 录制文件
Architecture
┌─────────────┐ ┌─────────────┐
│ FUSE mount │ │ WebDAV srv │ ← mount layer (pkg/mount)
└──────┬──────┘ └──────┬──────┘
│ │
└────────┬────────┘
│
┌──────┴──────┐
│ VFS + Tree │ ← virtual fs (pkg/vfs)
└──────┬──────┘
│
┌───────────┼───────────┐
│ Domain Adapters │ ← adapters (pkg/adapter)
│ drive wiki im cal │
│ task mail meeting │
└───────────┬───────────┘
│
┌──────┴──────┐
│ DocType │ ← type handlers (pkg/doctype)
│ Registry │ docx/sheet/bitable/file/folder
└──────┬──────┘
│
┌──────┴──────┐
│ CLI Exec │ ← lark-cli wrapper (pkg/cli)
│ + Retry │ with middleware, retry, auth
└─────────────┘
Key packages:
| Package |
Responsibility |
cmd/larkfs |
CLI entry — mount, unmount, serve, status, doctor, init |
pkg/cli |
lark-cli subprocess wrapper, JSON param builder, error classification |
pkg/doctype |
Per-type read/write handlers: docx, sheet, bitable, file, folder, readonly |
pkg/adapter |
Domain adapters: drive, wiki, im, calendar, task, mail, meeting |
pkg/vfs |
Virtual tree + operations routing |
pkg/mount |
FUSE server (go-fuse/v2), WebDAV server (x/net/webdav) |
pkg/cache |
Metadata TTL cache + LRU disk content cache |
pkg/naming |
Name conflict resolution with ~token suffix + persistent mapping |
pkg/daemon |
PID file, fork, health check, stale mount cleanup |
pkg/errors |
Retry with exponential backoff, auth recovery, CLI error to errno helpers |
pkg/config |
Mount/Serve config structs, path resolution |
Filesystem Semantics
- FUSE 和 WebDAV 写入都会先按文件句柄缓冲,正确处理 editor-style 的 offset write、truncate、append,并在 flush/close 时提交到 VFS。
- 普通二进制文件支持下载,以及“新建后首次写入即上传”;普通路径上的再次覆盖写入仍会返回
unsupported,避免静默变成“删了再传一份”。
- 如果你明确要替换已有 Drive 普通文件,请写
/_ops/replace.request.json:指定 target_path,再提供 flags.file_path 或 data.content_base64 / data.content,结果里会返回新旧 token。
- 目录里也会为普通 Drive 文件生成就近入口,比如
blob.bin._replace.request.json;这条路径已经带好目标文件,直接写替换请求就行。
- CRUD 只会作用在真实资源节点上;
_meta/、_ops/、_queries/、_views/ 是控制面路径,不能被当成 Drive 文件夹误创建。
- FUSE 会把 VFS 错误映射成更可消费的 errno:read-only →
EROFS,not found → ENOENT,unsupported → ENOTSUP,未知错误才回退到 EIO。
- Rename 不会做本地假成功:如果没有明确映射到远端 CLI 命令,操作会返回 unsupported,而不是只改内存里的名字等待下次刷新回滚。
Development
# Build
make build
# Run tests
make test
# Unit coverage across production packages
make test-cover
# Lint
make lint
# Dev mount (foreground, debug log)
make dev-mount
# Dev unmount
make dev-unmount
# Clean
make clean
Tests live under each module's test/ subdirectory, so they do not sit flat beside implementation files. make test-cover runs the full suite and reports coverage for the pure unit-testable production packages; CLI subprocess and mount boundary behavior is still tested, but cmd/larkfs and pkg/mount are not included in the unit coverage denominator to avoid test-only hooks or same-package white-box tests.
Release
Releases are automated via GitHub Actions + GoReleaser on version tags:
git tag v0.1.0
git push origin v0.1.0
Produces multi-platform binaries (linux/darwin × amd64/arm64).
Configuration
All runtime state is stored in ~/.larkfs/:
~/.larkfs/
├── cache/ # LRU content cache (default 500MB)
├── mounts/ # PID files for active mounts
├── namemap.json # Persistent name → token mappings
└── larkfs.log # Log file
CLI Flags
| Flag |
Default |
Description |
--daemon, -d |
false |
Run as background daemon |
--cache-dir |
~/.larkfs/cache |
Cache directory |
--cache-size |
500MB |
Disk content cache size limit |
--metadata-ttl |
60 |
Metadata cache TTL (seconds) |
--read-only |
false |
Mount in read-only mode |
--domains |
all supported domains |
Comma-separated enabled domains |
--lark-cli |
auto-detect |
Path to lark-cli binary |
--log-level |
info |
Log level (debug/info/warn/error) |
License
MIT