Skip to main content
Glama
sevenyang129

flyu-design

by sevenyang129
README.md
# flyu

本地设计文件客户端:把 Sketch / Figma 设计文件解析为统一 DSL v3,通过内嵌 MCP(HTTP,随 app 启动)暴露给 Cursor / Claude,让 AI 直接看设计稿、写代码、改稿、导出切图。

## 演示

https://github.com/user-attachments/assets/51cc93c6-8413-4c3b-8bfd-7fd135e26a3c

许可:[MIT](./LICENSE)。第三方声明见 [NOTICE.md](./NOTICE.md)。安全披露见 [SECURITY.md](./SECURITY.md)。贡献见 [CONTRIBUTING.md](./CONTRIBUTING.md)。

Sketch / Figma 的文件格式与商标归其权利人所有。本项目在**用户本机**解析你导入的 `.sketch` / `.fig`,不附带厂商授权,也不声称与 Figma, Inc. 或 Sketch B.V. 有关联。请遵守其服务条款,只导入你有权使用的设计文件。`.fig` 解码实现见 `crates/fig-kiwi-rs`。

用户向文档见 `docs/user-guide.md`(安装 / 功能 / 话术 / 排查);MCP 工具细节见 `docs/write-tools-guide.md`。

## 开发

```bash
pnpm install        # 安装依赖(postinstall 会把 better-sqlite3 编到 Electron ABI)
pnpm dev            # 启动 Electron + HMR
pnpm typecheck      # 类型检查(main + renderer + mcp + tests)
pnpm lint           # ESLint
pnpm test           # 单元 + 契约测试(tsx --test)
pnpm test:visual    # 渲染像素回归(改 import/render 后必跑)
pnpm build          # 构建到 out/(含 main/preload/renderer/mcp)
pnpm dist           # 打本机未签名 mac 双架构(arm64 + x64).dmg → release/
```

### 打包(macOS 本机未签名)

```bash
pnpm dist           # build + electron-builder → release/flyu-*-mac-arm64.dmg + flyu-*-mac-x64.dmg
pnpm dist:dir       # 只打 arm64 .app 到 release/mac-arm64/(便于调试)
```

双架构:electron-builder 按目标架构分别打包;better-sqlite3 为每个架构各自重编(arm64 主机上交叉编 x64 已验证可用)。

产物为未签名包(`identity: null`),安装后应用名为「非鱼」。本机打开若被 Gatekeeper 拦截:右键 → 打开。勿与正在跑的 `pnpm dev` 同时启动(单例锁会让第二个进程立刻退出)。

## MCP Server

两种接入,同一份 tools/prompts(29 个 Tool + 4 个 Prompt):

- **HTTP(推荐)**:客户端内嵌 Streamable HTTP,随 app 启动。设置 → MCP 使用配置 → 复制(URL + Bearer token)。端口默认 32677 并持久化,被占用才顺延;token 持久化于 `userData/mcp-token`(0600),可重新生成。
- **stdio(备选,需本机 Node)**:`node out/mcp/server.js`。要求 DB 已存在(客户端至少跑过一次)。

### 构建 stdio 入口

```bash
pnpm mcp:build      # esbuild 打包到 out/mcp/server.js
pnpm mcp:dev        # tsx 直跑(调试用)
```

### 验证(JSON-RPC 手工测)

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | pnpm mcp:dev
```

应返回 `serverInfo: { name: "flyu-design", version: "1.0.0" }`。

### macOS 本地开发陷阱(双 ABI + 代码签名)

1. **ABI 切换**:better-sqlite3 同一时刻只能为一个 runtime 编译。
   - Electron 用:`pnpm rebuild`(走 `electron-rebuild`)
   - 直跑 Node(MCP 调试 / tsx 测试):`cd node_modules/.pnpm/better-sqlite3@*/node_modules/better-sqlite3 && ./node_modules/.bin/prebuild-install -r node`
   - 症状:跑错了 runtime 会报 `NODE_MODULE_VERSION 130 vs 127` 之类。
2. **代码签名**:从 npm 拉的 prebuilt `.node` 在 macOS 26+ 上会被 AMFI 以 `Invalid Page` 杀掉(SIGKILL,exit 137,stderr 空)。修法:
   ```bash
   codesign --remove-signature node_modules/.pnpm/better-sqlite3@*/node_modules/better-sqlite3/build/Release/better_sqlite3.node
   codesign --force --sign -       node_modules/.pnpm/better-sqlite3@*/node_modules/better-sqlite3/build/Release/better_sqlite3.node
   ```
   每次 `prebuild-install` 后都要重做。后续打包时用 electron-builder 的 afterSign 钩子自动化。

## 目录

```
src/
├── main/           Electron 主进程(DB / IPC / 渲染 / 导入导出)
│   ├── import/     双通道导入:sketch-*(.sketch)/ fig-*(.fig 本地,@open-pencil/core)
│   │               + html-to-dsl(HTML 生成)、collect-tokens(共享令牌统计)
│   ├── render/     渲染调度(fig 走 Skia 直渲;sketch 走 DSL→HTML→Chromium)
│   ├── export/     dsl-to-jsx / dsl-to-fig / vector-to-svg / code-snippets / cut-cache
│   ├── tokens/     设计令牌(L1 命名令牌 / L3 组件令牌 / tokenize)
│   ├── db/         SQLite(writers / write-ops / write-docs / restyle / migrations)
│   └── ipc/        渲染进程桥(files / folders / explorer / mcp-config / library)
├── preload/        contextBridge 桥
├── renderer/       React + AntD UI
├── mcp/            MCP Server:server.ts(stdio)+ tools.ts(聚合器)+ tools-*.ts(8 个域模块)
├── shared/         三端共享(DSL v3 类型 / IPC 通道 / 错误码 / 路径)
└── native/         fig-kiwi WASM(由 crates/ 编译)

crates/             Rust 原生(.fig Kiwi 解码)
resources/          打包图标 icon.png / icon.icns
docs/               用户教程 / 写能力设计与工具文档
scripts/            正式脚本(icons / wasm / 视觉回归)
tests/              单元与契约测试
```

本地运行时数据在用户目录(`~/Library/Application Support/flyu`)与可选的 `.tokensave/`(已 gitignore),构建产物在 `out/`。

## 当前状态

- [x] 双通道导入:.sketch / .fig 本地(@open-pencil/core)
- [x] 统一 DSL v3 + SQLite 落库 + 版本组
- [x] 渲染:fig Skia 直渲;sketch/ai DSL→HTML→Chromium;degraded 显式上报
- [x] MCP 29 Tool + 4 Prompt(导航/数据/视觉/代码/切图/写操作/语义修改)
- [x] 写能力:事务化 apply_operations / restyle_*(dryRun)/ create_from_html / fork_document / rollback
- [x] 导出:get_html(自包含单文件)/ get_code(JSX+Tailwind,vw/rem/tokenize)/ export_fig(.fig 非官方互通)/ download_assets(SVG/PNG/原图)
- [x] 设计令牌:L1 命名令牌(fig variables/sketch 样式,css/dtcg 导出)+ L3 组件令牌覆盖走查
- [ ] Windows / Linux 安装包(配置已有,未发布)