# skills-manage 项目调研报告 > 调研对象:`skills-manage/` 目录,版本 0.10.0,Apache-2.0 > 项目定位:**跨平台 AI 编码 Agent 技能管理桌面应用**(Tauri v2 + React + Rust + SQLite) > 参考用途:为本项目的"技能(Skill)"管理能力提供桌面端借鉴(多平台分发、符号链接、市场导入、AI 解释) --- ## 一、项目概览 skills-manage 是一个**桌面端的 AI 技能中央管理器**。核心思想: - 把 `~/.agents/skills/` 作为**唯一中央目录(canonical source of truth)**,所有 SKILL.md 物理上只在这里存一份 - 各 AI 编码工具(Claude Code / Cursor / Gemini CLI / Codex / Hermes 等 27+ 个平台)通过**符号链接(symlink)**接入,达到"一份技能、多平台共享" - 提供"中央库 / 平台视图 / 项目发现 / 市场 / 集合"五种视角,把散落的技能统一收编、批量分发 它遵循 [Anthropic Agent Skills](https://github.com/anthropics/agent-skills) 开放模式,SKILL.md 用 YAML frontmatter 声明 `name` / `description`。 --- ## 二、技术栈 ### 总体架构 ``` React 前端 (src/) ↓ Tauri IPC(invoke() 调 #[tauri::command] 函数,50+ 个命令) Rust 后端 (src-tauri/src/) ↓ SQLx 异步驱动 SQLite 数据库(~/.skillsmanage/db.sqlite,WAL 模式) ``` ### 各层技术选型 | 层 | 技术 | 关键依赖 | |---|---|---| | 桌面框架 | **Tauri v2** | `tauri 2` + 4 个官方插件(sql/fs/dialog/shell) | | 前端框架 | React 18 + TypeScript 5.8 | `react`、`react-dom` | | UI 组件 | shadcn/ui(base-ui + Tailwind CSS 4) | `@base-ui/react`、`tailwindcss 4`、`class-variance-authority`、`tailwind-merge`、`lucide-react` | | 路由 | React Router v7 | `react-router-dom ^7.5.0` | | 状态管理 | Zustand 5 | `zustand ^5.0.3`(每业务域一个 store) | | 国际化 | i18next + react-i18next | 中英双语,`fallbackLng: "zh"` | | Markdown | react-markdown + remark-gfm | 前端展示;后端解析用 `serde_yaml` | | 主题 | Catppuccin 4 flavor × 14 accent | 自定义 `data-theme` / `data-accent` HTML 属性 | | 构建 | Vite 6 + tsc | dev 端口 24200 | | 后端语言 | **Rust 2021** | `serde`、`chrono`、`uuid` | | 数据库 | **SQLite via sqlx 0.8** | `sqlx { sqlite, runtime-tokio }` + WAL 模式 | | HTTP | reqwest 0.12 | `json`、`rustls-tls`、`stream`,用于 GitHub API + AI 解释 | | 压缩 | flate2 + tar | 解 GitHub tarball 到内存快照 | | YAML | serde_yaml 0.9 | 解析 SKILL.md frontmatter | | 测试 | Vitest 3 + jsdom + RTL(前端);cargo test + tempfile(后端) | 前端 370+ 用例,后端 214+ 用例 | ### 为什么选 Tauri 而非 Electron 从代码可推断(README 未明说): 1. Rust 原生提供跨平台文件系统与 symlink 能力(`std::os::unix::fs::symlink` vs `std::os::windows::fs::symlink_dir`) 2. SQLx 直连 SQLite,无需 Electron 常见的 `better-sqlite3` 等原生 Node 模块 3. 产物体积小、启动快;官方插件机制成熟(sql/fs/dialog/shell) ### 为什么用 SQLite WAL 模式 `db.rs:113` 显式 `PRAGMA journal_mode=WAL`——允许读(UI 查询)与写(扫描 upsert)并发,避免扫描大量项目期间 UI 卡顿;同时嵌入式零配置,跨平台单文件。 ### 为什么不用 `sqlx::query_as!` 宏 宏要求编译期 `DATABASE_URL` 连接真实库做类型校验,对 CI 和开发者机构成负担。全项目统一 `sqlx::query()` + `Row::get()` 手动映射。 --- ## 三、技能管理的具体逻辑 ### 3.1 核心概念与数据模型 | 概念 | 说明 | 存储 | |---|---|---| | **Skill** | 一个含 SKILL.md(YAML frontmatter)的目录 | `skills` 表 | | **Agent(平台)** | AI 编码工具(Claude Code / Cursor / Codex / Hermes / Copilot 等 27+ 内置) | `agents` 表 | | **中央目录** | `~/.agents/skills/`,技能的唯一权威位置 | 由特殊 agent id=`central` 标记 | | **安装(Installation)** | 中央 → 平台的符号链接/复制关系 | `skill_installations` 表(复合主键 skill_id+agent_id) | | **观测(Observation)** | 每次扫描平台目录时的技能快照,用于区分"平台原生/只读/本应用安装" | `agent_skill_observations` 表 | | **集合(Collection)** | 用户自定义的技能分组,可批量安装 | `collections` + `collection_skills`(多对多) | | **市场源(Registry)** | GitHub 仓库,作为远程技能目录 | `skill_registries` 表(带 etag/last-modified 缓存) | | **市场技能** | 远程同步下来的技能元数据 | `marketplace_skills` 表 | | **发现(Discover)** | 全盘扫描到的项目级技能 | `discovered_skills` 表 | | **AI 解释缓存** | 按 `(skill_id, lang)` 缓存的 AI 说明 | `skill_explanations` 表 | | **设置** | KV 存储(github_pat / ai_api_key / ai_model 等) | `settings` 表 | **支持的 27+ 平台**(节选):Claude Code、Codex CLI、Cursor、Gemini CLI、Trae、Factory Droid、Junie、Qwen、Windsurf、Qoder、Augment、OpenCode、KiloCode、OB1、Amp、Kiro、CodeBuddy、**Hermes**、Copilot、Aider;以及国内"龙虾系"(OpenClaw / QClaw / EasyClaw / AutoClaw / WorkBuddy)。特殊:`central` 即中央目录本身。 ### 3.2 技能识别:SKILL.md frontmatter 解析 `scanner.rs::parse_skill_md`(scanner.rs:120): 1. 平台/中央目录的**直接子目录**中是否含 `SKILL.md` 2. 文件首行必须是 `---`,截取至下一个 `\n---` 作为 frontmatter 3. 用 **serde_yaml 0.9** 解析(不引入完整 markdown 解析器) 4. `name` 必填(缺失静默跳过),`description` 可选 扫描时同步 upsert `skills` 表,并刷新 `agent_skill_observations` 记录观测。 ### 3.3 技能安装链路(重点) **入口**:前端 `centralSkillsStore.batchInstall` 或卡片图标单击 `togglePlatformLink` → `invoke("batch_install_to_agents" | "install_skill_to_agent", { skillId, agentIds, method })` **核心流程**(`linker.rs::install_skill_to_agent_impl`,:254): ``` 1. 禁止安装到 central 自身 2. 查 agent 与 central agent,确定 canonical_dir 3. 【关键】ensure_centralized: if canonical_dir/SKILL.md 不存在: 从 DB 取该技能当前实际 file_path 将其所在目录 copy_dir_all 到中央目录 回写 DB 的 canonical_path / is_central=true / file_path → "仅存在于某平台的技能被自动收养进中央目录",调用方对此透明 4. 支持"通用 ~/.agents/skills" 的平台(universal_available)直接返回成功 5. 目标已存在 symlink → 删除重建 目标已存在真实目录/文件 → 拒绝覆盖,报错(防误删用户手动放置的技能) 6. 计算相对路径 symlink_target_path(Windows 跨盘符时回退绝对路径) 7. 创建 symlink → upsert skill_installations (link_type="symlink") ``` **回退策略**(`install_skill_to_agent_auto_impl`,:338): - 仅 **Windows** 上当错误信息含 "Failed to create symlink"(典型为无开发者模式/权限不足)时,自动回退到 `install_skill_to_agent_copy_impl` 整目录复制 - Unix 上不回退,直接报错——保持行为可预期 **为什么用相对路径 symlink**:用户移动整个 home 目录或同步到另一台机器时链接不失效。 ### 3.4 卸载链路 `linker.rs::uninstall_skill_from_agent`:删除 symlink/copy 目录 → 删除 `skill_installations` 行。中央目录的物理目录**不动**,仅断开分发关系。 ### 3.5 Discover:全磁盘项目级技能发现 `discover.rs::start_project_scan`(:1387): - **扫描根**:默认 10 个候选(`~/projects`、`~/Documents`、`~/Developer`、`/Applications` 等),存在的自动启用;叠加用户在 settings 里加的自定义目录 - **递归策略**: - 最大深度 `MAX_SCAN_DEPTH = 8` - 黑名单 `SKIP_DIRS`:node_modules / target / .git / build / dist / .next / venv 等 16 个 - 深度 0 跳过 `.` 开头的隐藏目录,**深层放行**以命中 `.claude/skills`、`.agents/skills` 等模式 - 匹配模式来自各内置 agent 的 `project_skills_dir` - **进度流式推送**:通过 `app.emit("discover:progress" | "found" | "complete")`,前端 store 订阅 - **取消**:全局 `SCAN_CANCEL: AtomicBool` + thread-local 覆盖(测试隔离) - **`is_already_central` 实时重算**:每次从 DB 加载时检查 `~/.agents/skills/` 是否存在,不是静态快照 - **导入**:`import_discovered_skill_to_central` / `import_discovered_skill_to_platform`,**特意不删** discovered 记录,以支持连续导入到多个平台 ### 3.6 Marketplace:GitHub 远程技能市场 **抓取方式**(`github_import.rs::download_repository_archive`,:824): - 不用 Git Trees API,而是 `GET /repos/{owner}/{repo}/tarball/{branch}` 整包下载 - `flate2::GzDecoder` + `tar` 解压到内存快照 - `classify_skill_manifest_path` 识别三种布局: - 根 SKILL.md(单技能仓库) - 根级 `/SKILL.md`(多技能仓库,排除 `.github`) - `skills/**/SKILL.md`(含 `.curated`/`.system` 命名空间子目录) **认证与限流**: - `github_pat` 从 settings 表读取(`github_import.rs:649`) - 仅对直连 github.com 请求附带 token,**镜像请求不带**(避免泄漏) - `GITHUB_MIRROR_ENDPOINTS`:github 直连 + ghfast.top / ghproxy.net / mirror.ghproxy.com 三个国内镜像,403/429 时依次回退 - 读 `x-ratelimit-remaining/reset` 头构造结构化错误(含可操作建议的中文提示) **缓存策略**: - 同步结果 upsert `marketplace_skills`(`ON CONFLICT(id) DO UPDATE`) - 非 force 刷新 + 有缓存 → 直接返回缓存 - force 刷新失败 → 保留 last-good 缓存,只更新 `last_sync_status="error"` - 内置源(`is_builtin=true`)禁止删除;删除自定义源会先清掉其缓存技能 **安装**:`install_marketplace_skill` 直接 GET `download_url`(raw.githubusercontent.com 直链)→ 写 `~/.agents/skills//SKILL.md`。**注意**:仅下载单文件 SKILL.md,不带附属文件;完整仓库需走 `import_github_repo_skills`。 ### 3.7 AI 解释(Skill Explanation) `marketplace.rs::explain_skill_stream`(:1307): - **协议探测**:按 `ai_api_url` 路径后缀区分 Anthropic(`/v1/messages` + `x-api-key` + `anthropic-version`)与 OpenAI 兼容(`/v1/chat/completions` + `Authorization: Bearer`) - **Prompt 构造**:SKILL.md 内容截断 8000 字符;中英双语模板要求"一句话总结 + 适用场景 + 关键功能点,200 字以内" - **流式响应**:SSE 按行解析;Anthropic 取 `content_block_delta.delta.text`(跳过 `thinking_delta`),OpenAI 取 `choices[0].delta.content`;每块 `app.emit("skill:explanation:chunk")` 推前端 - **错误分类**:`classify_reqwest_error` 把 reqwest 错误分为 Proxy/Connect/Timeout/Dns/Tls/Auth/Response/Unknown,附中文可操作提示 - **区域端点回退**:MiniMax(minimaxi.com ↔ minimax.io)与 GLM(bigmodel.cn ↔ api.z.ai)在连接层失败时自动切换一次 - **缓存**:`skill_explanations` 表按 `(skill_id, lang)` 存;`INSERT OR REPLACE` 保留原 `created_at`;空文本视为缓存腐败会删除并重新生成 - **支持厂商**:Anthropic / GLM / MiniMax / Kimi / DeepSeek / OpenRouter(`src/data/aiProviders.ts` 7 个预设) ### 3.8 集合(Collection) `collections.rs`:分组管理 + `batch_install_collection`(对集合内每个技能 × 每个 agent 调 linker)+ JSON 导入/导出(`CollectionExport { version, name, description, skills[], created_at, exported_from }`)。 --- ## 四、IPC 命令清单(50+ 个) 按模块分组(`lib.rs:41-112` 注册): | 模块 | 主要命令 | 职责 | |---|---|---| | scanner | `scan_all_skills` | 全量扫描中央目录 + 所有启用平台 | | agents | `get_agents` / `detect_agents` / `add_custom_agent` / `update_custom_agent` / `remove_custom_agent` | 平台 CRUD;检测写回 is_detected | | linker | `install_skill_to_agent` / `uninstall_skill_from_agent` / `batch_install_to_agents` | symlink/copy 安装与卸载 | | skills | `get_skills_by_agent` / `get_central_skills` / `get_central_skill_bundles` / `get_skill_detail` / `read_skill_content` / `list_skill_directory` / `open_in_file_manager` / `preview_delete_central_skill_bundle` / `delete_central_skill*` | 技能查询/内容/删除 | | collections | `create/get/update/delete_collection` / `add/remove_skill_to_collection` / `batch_install_collection` / `export/import_collection` | 集合管理 | | settings | `get/set_scan_directories` / `set_scan_directory_active` / `get_setting` / `set_setting` | 扫描目录 + KV 设置 | | discover | `discover_scan_roots` / `get_scan_roots` / `set_scan_root_enabled` / `start/stop_project_scan` / `get_discovered_skills` / `import_discovered_skill_to_central/platform` / `clear_discovered_skills` / `get_obsidian_vaults/skills` | 项目级技能发现 | | github_import | `preview_github_repo_import` / `import_github_repo_skills` / `fetch_github_skill_markdown` | GitHub 仓库导入(带进度事件 + 冲突解决) | | marketplace | `list_registries` / `add/remove_registry` / `sync_registry(_with_options)` / `search_marketplace_skills` / `install_marketplace_skill` / `explain_skill(_stream)` / `get_skill_explanation` / `refresh_skill_explanation` | 市场源 + AI 解释 | --- ## 五、前端组织 ### 5.1 路由 | 路由 | 页面文件 | 布局模式 | |---|---|---| | `/` → 重定向 `/central` | — | — | | `/central` | `CentralSkillsView.tsx` | 技能卡片两列 | | `/platform/:agentId` | `PlatformView.tsx` | 技能卡片两列 | | `/skill/:skillId` | `SkillDetailPage.tsx` | **双栏**:左 SKILL.md 预览全高,右 metadata + 紧凑图标式安装状态 + collections | | `/collections` | `CollectionsListView.tsx` / `CollectionView.tsx` | 卡片横排选中 + 下方技能列表 | | `/marketplace` | `MarketplaceView.tsx` | 三 Tab:推荐 / 官方源目录 / 我的源 | | `/discover`, `/discover/:projectPath` | `DiscoverView.tsx` | 左面板项目列表 + 右面板技能详情 | | `/obsidian/:vaultId` | `ObsidianVaultView.tsx` | 独立视图 | | `/settings` | `SettingsView.tsx` | 卡片分区 | ### 5.2 Zustand Store(10 个) 约定:**组件不直接 `invoke()`,一律走 store**。 | Store | 职责 | |---|---| | `centralSkillsStore` | 中央库 + bundle + 平台链接切换 | | `platformStore` | 平台视图 + 全量扫描 | | `skillStore` | 单平台技能列表 | | `skillDetailStore` | 技能详情 + AI 解释流式订阅 | | `collectionStore` | 集合 CRUD/批量安装/导入导出 | | `discoverStore` | Discover 扫描与导入(监听 `discover:*` 事件) | | `marketplaceStore` | 市场三 Tab + GitHub 导入 + 解释 | | `obsidianStore` | Obsidian vault | | `settingsStore` | 扫描目录 + GitHub PAT + 自定义平台 | | `themeStore` | Catppuccin 主题(纯前端 localStorage,无 IPC) | ### 5.3 共享组件 **UnifiedSkillCard**(`src/components/skill/UnifiedSkillCard.tsx`):所有页面的技能卡片唯一实现,通过可选 props 自适应 5 种场景: | 场景 | 特征 props | |---|---| | central | `platformIcons{agents, linkedAgents, readOnlyAgents, onToggle}` 渲染 LOBSTER/CODING 两行图标即时切换 | | platform | `sourceType: "symlink"\|"copy"\|"native"` + `originKind` + `isReadOnly` | | discover | `checkbox{checked, onChange}` + `platformBadge` + `projectBadge` + `isCentral` | | marketplace | `isInstalled` + `tags[]` + `publisher` | | collection | 复用基础 + `onRemove` | 统一样式:`rounded-xl ring-1 ring-border bg-card shadow-sm`。**约定:不要为特定场景新建卡片组件**。 **InstallDialog**(`src/components/central/InstallDialog.tsx`): - 打开时**默认勾选"当前已链接(含只读)"的平台**,反映现状 - 确认时把勾选集合(剔除 read_only)+ 安装方式(symlink/copy 单选)传给 `onInstall` - 注意:该对话框只负责"安装到所选",取消勾选已链接平台**不会**触发卸载(卸载靠卡片图标 toggle 或平台视图) ### 5.4 i18n 与主题 - **语言**:仅 zh / en 两种语言包;`fallbackLng: "zh"`;检测顺序 localStorage(`i18nextLng`) → navigator - **主题**:Catppuccin 4 flavor(mocha / macchiato / frappe / latte)× 14 accent(rosewater … lavender) - 实现:`themeStore.applyFlavor/applyAccent` 在 `` 上写 `data-theme` / `data-accent`,持久化到 localStorage `catppuccin-flavor` / `catppuccin-accent`;`init()` 在渲染前调用防闪烁 --- ## 六、必需依赖 ### 6.1 开发期 | 类别 | 依赖 | 说明 | |---|---|---| | 运行时 | Node.js LTS + pnpm | `package.json` 中 `pnpm.onlyBuiltDependencies` 声明 pnpm 专用 | | Rust | stable toolchain(rustup) | 2021 edition | | 系统库 | Tauri v2 系统依赖 | Windows:WebView2 + MSVC;macOS:Xcode CLT;Linux:webkit2gtk 等(详见 ) | | Rust crate | tauri 2 + 4 插件 / sqlx 0.8 / serde_yaml 0.9 / reqwest 0.12 / flate2 / tar / chrono / uuid / futures-util | 见 `src-tauri/Cargo.toml:16-31` | | 前端依赖 | react 18 / react-router-dom 7 / zustand 5 / i18next / tailwindcss 4 / @base-ui/react / lucide-react / cmdk / sonner / react-markdown / gray-matter | 见 `package.json:17-44` | | 测试 | vitest 3 + jsdom + @testing-library/* / tokio(full) / tempfile | 前端 370+ 用例,后端 214+ 用例 | ### 6.2 最终用户运行时 **不需要 Node 也不需要 Rust**——`pnpm tauri build` 产出平台原生安装包。 - **Windows**:依赖系统 WebView2(Win10 1803+ 通常已内置;`tauri.conf.json` 配置 `webviewInstallMode: embedBootstrapper` 自动引导) - **macOS**:当前预编译包仅 Apple Silicon(`.dmg` / `.app.zip`),未 notarize,首次运行需 `xattr -dr com.apple.quarantine` - **Linux**:AppImage / deb / rpm 三形态 ### 6.3 数据存储位置 | 数据 | 位置 | |---|---| | 应用数据库 | `~/.skillsmanage/db.sqlite`(含 collections / settings / 市场缓存 / AI 解释缓存) | | 中央技能目录 | `~/.agents/skills/` | | 各平台技能目录 | `~/.claude/skills/` / `~/.cursor/skills/` / `~/.gemini/skills/` 等(由 agents 表 `global_skills_dir` 定义) | | 前端主题/语言偏好 | localStorage | ### 6.4 外网访问触发点(隐私说明) 应用本地优先,**仅以下功能联网**: | 功能 | 目标端点 | 是否带 token | |---|---|---| | Marketplace 源同步 / GitHub 仓库预览/导入 | `api.github.com` + `raw.githubusercontent.com`;镜像回退 ghfast.top / ghproxy.net / mirror.ghproxy.com | 直连 github.com 带 PAT;镜像不带 | | Marketplace 技能安装 | `raw.githubusercontent.com`(download_url 直链) | 不带 | | AI 技能解释 | 用户配置的 `ai_api_url`(Anthropic / GLM / MiniMax / Kimi / DeepSeek / OpenRouter) | 带用户配置的 api_key | **遥测**:无;**崩溃上报**:无;**凭证**:仅存本地 SQLite settings 表(明文)。 --- ## 七、关键技术决策(供本项目借鉴) | 决策 | 价值 | 对应代码 | |---|---|---| | `~/.agents/skills/` 作为唯一中央目录 + symlink 分发 | 一份技能多平台共享,避免散落与不一致 | `path_utils.rs:45-47`、`linker.rs:154` | | `ensure_centralized` 自动收养 | 仅存在于某平台的技能被自动拷贝进中央,调用方透明 | `linker.rs:154-195` | | 相对路径 symlink | 用户移动 home 目录链接不失效 | `linker.rs:89-100` | | 拒绝覆盖真实目录 | 防误删用户手动放置的技能 | `linker.rs:301-312` | | Windows symlink 失败自动回退 copy | 兼容无开发者模式的 Windows 环境 | `linker.rs:338-360` | | SQLite WAL + sqlx 手动映射 | 读写并发不卡 UI;避开 `query_as!` 宏对 DATABASE_URL 的依赖 | `db.rs:113`、全项目 | | GitHub tarball 整包解压到内存 | 规避 Trees API 限流;`flate2` + `tar` 流式 | `github_import.rs:824-870` | | 镜像回退 + 限流头解析 | 国内可用性;结构化错误提示可操作 | `github_import.rs:219-240`、`:1327-1341` | | AI 解释 `(skill_id, lang)` 缓存 + 空文本腐败检测 | 降本;防缓存损坏被永久复用 | `marketplace.rs:889-905` | | SSE 流式 + `app.emit` | 前端无感知渲染;错误分类可操作 | `marketplace.rs:1220-1251` | | `is_already_central` 实时重算 | 避免静态快照过期导致的状态错乱 | `discover.rs:1445` | | 前端组件不直接 invoke,统一走 store | 便于测试 mock + 集中错误处理 | `src/test/setup.ts:88-95` | | Vitest 通过 `window.__TAURI_INTERNALS__` mock IPC | 前端单测无需启动真实 Tauri | `src/test/setup.ts:88-95` | --- ## 八、对本项目的借鉴意义 1. **技能中央化 + 符号链接分发**:本项目的 Skill 管理目前是单平台(agent-management 自己的库),可借鉴"中央目录 + 多平台 symlink"模式,把技能共享到 Claude Code / Cursor 等其他工具。 2. **SKILL.md frontmatter 用 serde_yaml 解析**:与项目内已有的 Skill 解析逻辑可对照,避免重复造轮子。 3. **Discover 的扫描黑名单与深度限制**(`MAX_SCAN_DEPTH=8` + 16 个 `SKIP_DIRS`):项目内做本地知识库或代码库扫描时可参考。 4. **GitHub tarball 整包 + 镜像回退 + 限流头解析**:本项目已有从 GitHub 拉取 Skill 的需求时可复用此设计。 5. **AI 解释的协议探测 + 区域端点回退 + 缓存腐败检测**:与本项目的 LLM 调用层设计可互鉴。 6. **`is_already_central` 实时重算**:状态派生自文件系统而非数据库快照,避免缓存漂移——项目内做"技能是否已安装"判定可直接采用。 --- ## 附录:文件结构速查 ``` skills-manage/ ├── src/ # React 前端 │ ├── components/ # UI 组件(含 UnifiedSkillCard / InstallDialog) │ ├── data/ # officialSources.ts / aiProviders.ts 静态数据 │ ├── hooks/ # 通用 hooks │ ├── i18n/ # zh.json / en.json / index.ts │ ├── lib/ # 前端工具 │ ├── pages/ # 9 个路由页面 │ ├── stores/ # 10 个 Zustand store │ ├── test/ # Vitest + RTL(370+ 用例) │ ├── types/ # 共享 TS 类型 │ ├── App.tsx # 路由声明 │ ├── main.tsx # 入口(含 theme init) │ └── index.css # Catppuccin 4 flavor × 14 accent CSS 变量 ├── src-tauri/ │ ├── src/ │ │ ├── commands/ # 10 个 IPC 模块(scanner/agents/linker/skills/collections/settings/discover/github_import/marketplace) │ │ ├── db.rs # SQLite schema + 迁移 + 内置 seed(11 张表) │ │ ├── path_utils.rs # home 解析 + ~/.skillsmanage + ~/.agents/skills │ │ ├── lib.rs # Tauri Builder + invoke_handler 注册 │ │ └── main.rs # 桌面入口 │ └── Cargo.toml # Rust 依赖 ├── package.json # 前端依赖 ├── tauri.conf.json # Tauri 配置(bundle / window / plugins) └── docs/ # 项目内文档 ```