# AI Skill Manager Windows 设计规格 ## 背景 本项目是一个基于 Wails 的 Windows 桌面应用,用于从 Gitea 组织仓库中发现、下载、更新和安装 AI skill。首版面向 Codex 和 Claude 两个目标应用,后续可以扩展到其他应用。 项目约束: - 不使用 git worktree。 - 一个 Gitea 仓库对应一个 skill。 - 只有仓库根目录存在 `SKILL.md` 时,才认为该仓库是有效 skill。 - 本地只保留一份 skill 仓库,安装到目标应用时使用 Windows 目录 Junction,不复制完整目录。 ## 首版范围 首版包含三类页面: 1. 配置页 2. 远程市场页 3. 本地管理页 首版支持: - 配置 Gitea `baseURL`、认证方式、账号密码或 Token、组织名。 - 默认使用账号密码认证,同时支持 Token 认证。 - 从指定 Gitea 组织读取仓库列表。 - 只展示根目录存在 `SKILL.md` 的仓库。 - 将 skill 仓库 clone 到本地应用数据目录。 - 对已下载仓库执行手动更新和自动更新。 - 将本地 skill 通过 Junction 安装到 Codex 和 Claude。 - 从 Codex 和 Claude 卸载本软件创建的 Junction。 - 删除本地 skill 仓库。 - 使用 VS Code 打开 skill 目录。 - 使用资源管理器打开 skill 目录。 首版不包含: - 多 Gitea 实例或多组织同时管理。 - GitHub、GitLab 或其他代码托管源。 - skill 版本选择、回滚和发布管理。 - 自动解决本地未提交改动。 - 批量安装、批量卸载和批量删除。 ## 路径约定 应用数据目录: ```text %APPDATA%\sgg-ai-skill-manager ``` 配置文件: ```text %APPDATA%\sgg-ai-skill-manager\config.json ``` 状态文件: ```text %APPDATA%\sgg-ai-skill-manager\state.json ``` 本地仓库目录: ```text %APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo} ``` Codex skill 目录: ```text C:\Users\{user}\.codex\skills ``` Claude skill 目录: ```text C:\Users\{user}\.claude\skills ``` ## 认证设计 配置页提供两种认证方式: - 账号密码认证,作为默认方式。 - Token 认证,作为可选方式。 敏感信息不明文写入 `config.json`。配置文件只保存认证方式和凭据引用标识,真实密码或 Token 优先保存到 Windows Credential Manager。 如果 Windows Credential Manager 写入失败,保存配置失败并提示用户,不降级为明文保存。 Gitea API 调用规则: - 账号密码模式使用 Basic Auth。 - Token 模式使用 `Authorization: token `。 Git clone 和 pull 的认证规则: - 首版优先调用系统 `git`。 - 账号密码或 Token 仅在执行 git 命令时从 Credential Manager 读取到内存中使用,不写入 `config.json`、`state.json` 或仓库 remote URL。 - clone 后仓库 remote URL 保存为不含密码和 Token 的普通 HTTPS URL。 - 如果认证失败,错误显示在对应仓库状态上,不阻塞整个应用。 ## Gitea 仓库发现 远程市场页通过 Gitea API 读取组织仓库: ```http GET /api/v1/orgs/{org}/repos ``` 列表需要分页加载。每个仓库再检查根目录是否存在 `SKILL.md`。只有检查通过的仓库出现在远程市场页。 远程市场页展示字段: - 仓库名 - 描述 - 默认分支 - 最近更新时间 - 本地状态:未下载、已下载、可更新、检查失败 搜索行为: - 首版在已加载的远程仓库结果中按名称和描述进行本地过滤。 - 后续可以扩展为服务端搜索。 ## 页面设计 ### 配置页 配置项: - Gitea baseURL - 认证方式:账号密码或 Token - 用户名 - 密码 - Token - 组织名 - 自动更新开关,默认开启 - 启动时检查更新开关,默认开启 - 定时检查间隔,默认 60 分钟 操作: - 保存配置 - 测试连接 测试连接需要验证: - baseURL 可访问 - 凭据有效 - 当前账号能访问指定组织 ### 远程市场页 远程市场页用于发现和下载 skill。 主要控件: - 搜索框 - 刷新按钮 - 仓库列表 仓库操作: - 下载:本地不存在时执行 `git clone` - 更新:本地存在时执行更新检查和 `git pull` - 打开本地:本地存在时打开目录 下载目标: ```text %APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo} ``` ### 本地管理页 本地管理页用于管理已下载 skill 和目标应用安装状态。 建议使用表格布局,字段包括: - 名称 - 本地路径 - 当前 commit - 更新状态 - Codex 安装状态 - Claude 安装状态 - 操作 操作包括: - 手动更新 - 安装到 Codex - 卸载 Codex - 安装到 Claude - 卸载 Claude - VS Code 打开 - 文件夹打开 - 删除本地 VS Code 打开使用: ```powershell code . -n ``` 命令执行目录为对应 skill 本地仓库目录。 文件夹打开使用 Windows 资源管理器打开对应目录。 ## Junction 安装语义 安装到 Codex 或 Claude 时,不复制 skill 文件,而是在目标 skills 目录创建同名 Junction。 示例: ```text C:\Users\{user}\.codex\skills\{repo} -> %APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo} C:\Users\{user}\.claude\skills\{repo} -> %APPDATA%\sgg-ai-skill-manager\repos\{org}\{repo} ``` 安装规则: - 如果目标 skills 目录不存在,安装时创建该目录。 - 如果目标路径不存在,创建 Junction。 - 如果目标路径是本软件记录的 Junction,且指向当前 skill 本地路径,可以重建或保持不变。 - 如果目标路径是普通目录、文件、或指向其他位置的 Junction,标记为冲突,不自动删除。 - 安装成功后写入 `state.json`。 卸载规则: - 只卸载本软件记录的目标。 - 删除前再次确认目标是 Junction,且指向当前 skill 本地路径。 - 确认通过后,只删除 Junction 本身,不删除本地 skill 仓库。 - 如果目标不是预期 Junction,卸载失败并提示冲突。 删除本地 skill 规则: - 如果 skill 已安装到 Codex 或 Claude,先卸载对应 Junction。 - 如果任一 Junction 无法安全卸载,则阻止删除本地仓库。 - Junction 清理完成后,再删除本地仓库目录。 ## 后端模块 ### config 职责: - 读取和保存 `config.json`。 - 管理自动更新设置。 - 管理 Credential Manager 中的密码或 Token 引用。 ### gitea 职责: - 测试连接。 - 读取组织仓库。 - 检查仓库根目录 `SKILL.md`。 - 获取仓库默认分支和远程最新 commit。 ### gitops 职责: - 检查系统 `git` 是否可用。 - 执行 clone。 - 执行 fetch 和 pull。 - 获取当前 commit。 - 获取远程 commit。 - 检测工作区是否存在未提交改动。 ### skillstore 职责: - 管理本地仓库目录。 - 读取和保存 `state.json`。 - 记录本地 skill 元数据。 - 根据本地路径扫描已下载 skill。 ### targets 职责: - 管理 Codex 和 Claude 两个目标应用。 - 检测目标 skills 目录是否存在。 - 创建 Junction。 - 识别 Junction 目标。 - 卸载 Junction。 - 识别安装冲突。 ### updater 职责: - 启动后执行更新检查。 - 按配置间隔执行定时检查。 - 对无本地改动的已下载 skill 自动 pull。 - 记录更新失败原因。 ## 状态文件设计 `config.json` 示例: ```json { "gitea": { "baseURL": "https://gitea.example.com", "org": "ai-skills", "authType": "password", "username": "user", "credentialKey": "sgg-ai-skill-manager:gitea" }, "update": { "autoUpdate": true, "checkOnStartup": true, "intervalMinutes": 60 } } ``` `state.json` 示例: ```json { "skills": [ { "org": "ai-skills", "repo": "lark-base", "localPath": "C:\\Users\\wdh\\AppData\\Roaming\\sgg-ai-skill-manager\\repos\\ai-skills\\lark-base", "remoteURL": "https://gitea.example.com/ai-skills/lark-base.git", "defaultBranch": "main", "currentCommit": "abc123", "lastCheckedAt": "2026-05-13T14:00:00+08:00", "lastError": "", "installedTargets": { "codex": { "path": "C:\\Users\\wdh\\.codex\\skills\\lark-base", "linkType": "junction", "targetPath": "C:\\Users\\wdh\\AppData\\Roaming\\sgg-ai-skill-manager\\repos\\ai-skills\\lark-base" }, "claude": { "path": "C:\\Users\\wdh\\.claude\\skills\\lark-base", "linkType": "junction", "targetPath": "C:\\Users\\wdh\\AppData\\Roaming\\sgg-ai-skill-manager\\repos\\ai-skills\\lark-base" } } } ] } ``` ## 自动更新策略 默认开启自动更新。 启动时: 1. 读取 `state.json`。 2. 对已下载 skill 执行更新检查。 3. 如果远程 commit 比本地新,且本地没有未提交改动,执行 `git pull`。 4. 如果 skill 已安装到 Codex 或 Claude,因为目标应用读取的是 Junction,pull 完成本身即完成同步。 5. 如果更新失败,记录错误并在本地管理页显示。 定时检查: - 按配置的分钟间隔执行。 - 同一时刻只允许一个更新任务运行。 - 用户手动更新时,如果后台正在更新同一个 skill,需要返回“正在更新”状态。 本地改动处理: - 如果发现本地仓库有未提交改动,不执行自动更新。 - 状态显示为“本地有改动”。 - 首版允许用户打开目录或 VS Code 手动处理。 - 首版不自动 stash、reset 或覆盖本地改动。 ## 错误处理 错误状态应落到具体对象上,避免一个仓库失败影响其他仓库。 常见错误: - Gitea baseURL 不可访问。 - 凭据无效。 - 当前账号无组织访问权限。 - 仓库没有 `SKILL.md`。 - 系统未安装 `git` 或 `git` 不在 PATH。 - clone 或 pull 认证失败。 - 本地仓库存在未提交改动。 - 目标 skills 目录不存在。 - 目标路径存在同名普通目录。 - 目标路径存在未知 Junction。 - Junction 删除前校验失败。 用户可见错误需要包含: - 失败对象,例如仓库名或目标应用名。 - 简短原因。 - 可执行建议,例如“检查配置”“打开本地目录处理改动”“手动处理同名目录”。 ## 安全规则 - 不自动删除用户已有普通目录。 - 不自动删除未知 Junction。 - 不自动覆盖本地仓库未提交改动。 - 不明文保存 Gitea 密码或 Token。 - 删除本地 skill 前必须先安全清理本软件创建的 Junction。 - 所有路径操作使用绝对路径。 - 删除操作限定在应用管理目录或记录中的目标 Junction 路径内。 ## 验收标准 配置: - 能保存 Gitea baseURL、认证方式、账号密码或 Token、组织名。 - 能测试连接并识别组织访问权限。 - 敏感信息不出现在 `config.json` 明文中。 远程市场: - 能读取组织仓库列表。 - 只展示根目录存在 `SKILL.md` 的仓库。 - 能按名称和描述搜索。 - 能下载未下载 skill。 - 能更新已下载 skill。 本地管理: - 能展示已下载 skill 的路径、commit 和安装状态。 - 能安装到 Codex。 - 能安装到 Claude。 - 安装结果是 Junction,不是目录复制。 - 能卸载 Codex 和 Claude 的 Junction。 - 卸载不会删除本地仓库。 - 能删除本地 skill,并先清理本软件创建的 Junction。 - 遇到同名普通目录或未知 Junction 时不会自动覆盖。 - 能用 VS Code 打开 skill 目录。 - 能用资源管理器打开 skill 目录。 自动更新: - 启动时能检查已下载 skill 是否有更新。 - 无本地改动时能自动 pull。 - 已安装 skill 更新后,Codex 和 Claude 通过 Junction 能读取最新内容。 - 有本地未提交改动时不会自动覆盖。 ## 后续扩展方向 首版采用轻量 MVP,但保留模块边界,后续可以扩展: - 更多目标应用。 - 多个 Gitea 组织。 - 多个代码托管源。 - 批量操作。 - 更新日志和版本回滚。 - skill 元数据解析和分类。