huhaa-myskills 0.2.13 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -375
- package/bin/huhaa-myskills.mjs +194 -12
- package/{scripts → build}/verify.mjs +3 -1
- package/docs/Frontend-Spec.md +1149 -0
- package/docs/assets/layout-wireframe.png +0 -0
- package/docs/assets/theme-reference.png +0 -0
- package/docs/scan_rules.md +172 -0
- package/package.json +33 -9
- package/packages/scanner/src/adapters/directory-skill.mjs +239 -0
- package/packages/scanner/src/adapters/skill-adapter.mjs +345 -0
- package/packages/scanner/src/icon/brand-map.mjs +84 -0
- package/packages/scanner/src/icon/icon-extractor.mjs +246 -0
- package/packages/scanner/src/index.mjs +107 -82
- package/packages/scanner/src/types.d.ts +18 -0
- package/packages/scanner/test/icon.test.mjs +61 -0
- package/packages/scanner/test/scanner.test.mjs +37 -41
- package/packages/scanner/test/skill-adapter.test.mjs +70 -0
- package/packages/scanner/tests/directory-skill.test.mjs +93 -0
- package/packages/scanner/tests/scanner-integration.test.mjs +139 -0
- package/packages/server/src/index.mjs +164 -12
- package/packages/server/src/labels.mjs +62 -0
- package/packages/server/test/server.test.mjs +1 -1
- package/packages/web/README.md +33 -2
- package/packages/web/dist/assets/index-BCY2cRaO.js +175 -0
- package/packages/web/dist/assets/index-DALKjJPi.css +1 -0
- package/packages/web/dist/favicon-16x16.png +0 -0
- package/packages/web/dist/favicon-192x192.png +0 -0
- package/packages/web/dist/favicon-32x32.png +0 -0
- package/packages/web/dist/favicon-512x512.png +0 -0
- package/packages/web/dist/favicon-source.svg +5 -0
- package/packages/web/dist/index.html +23 -9
- package/packages/web/index.html +22 -8
- package/packages/web/package-lock.json +2989 -0
- package/packages/web/package.json +21 -8
- package/packages/web/postcss.config.js +6 -0
- package/packages/web/public/favicon-16x16.png +0 -0
- package/packages/web/public/favicon-192x192.png +0 -0
- package/packages/web/public/favicon-32x32.png +0 -0
- package/packages/web/public/favicon-512x512.png +0 -0
- package/packages/web/public/favicon-source.svg +5 -0
- package/packages/web/src/App.test.ts +40 -0
- package/packages/web/src/App.tsx +177 -0
- package/packages/web/src/components/ComingSoon.tsx +14 -0
- package/packages/web/src/components/layout/Sidebar.test.tsx +74 -0
- package/packages/web/src/components/layout/Sidebar.tsx +114 -0
- package/packages/web/src/components/layout/Topbar.tsx +74 -0
- package/packages/web/src/components/ui/ActionButton.tsx +48 -0
- package/packages/web/src/components/ui/button.tsx +48 -0
- package/packages/web/src/components/ui/card.tsx +45 -0
- package/packages/web/src/components/views/DashboardView.tsx +122 -0
- package/packages/web/src/components/views/OtherSkillsView.test.tsx +126 -0
- package/packages/web/src/components/views/OtherSkillsView.tsx +306 -0
- package/packages/web/src/components/views/SettingsView.tsx +95 -0
- package/packages/web/src/components/views/SkillDetail.test.tsx +57 -0
- package/packages/web/src/components/views/SkillDetail.tsx +81 -0
- package/packages/web/src/components/views/SkillsView.test.ts +28 -0
- package/packages/web/src/components/views/SkillsView.tsx +226 -0
- package/packages/web/src/hooks/QUICK_REFERENCE.md +165 -0
- package/packages/web/src/hooks/README.md +378 -0
- package/packages/web/src/hooks/__tests__/useOtherSkills.test.ts +422 -0
- package/packages/web/src/hooks/__tests__/useSkillIcons.test.ts +272 -0
- package/packages/web/src/hooks/useLiveReload.ts +20 -0
- package/packages/web/src/hooks/useOtherSkills.ts +387 -0
- package/packages/web/src/hooks/useSkillIcons.ts +248 -0
- package/packages/web/src/hooks/useTheme.ts +36 -0
- package/packages/web/src/index.css +161 -0
- package/packages/web/src/lib/api.test.ts +47 -0
- package/packages/web/src/lib/api.ts +77 -0
- package/packages/web/src/lib/cn.ts +7 -0
- package/packages/web/src/lib/editors.test.ts +30 -0
- package/packages/web/src/lib/editors.ts +70 -0
- package/packages/web/src/lib/markdown.test.ts +27 -0
- package/packages/web/src/lib/markdown.ts +14 -0
- package/packages/web/src/main.tsx +13 -0
- package/packages/web/src/types/index.ts +62 -0
- package/packages/web/src/types/other-skill.ts +88 -0
- package/packages/web/src/types/skill.ts +136 -0
- package/packages/web/src/types.ts +47 -0
- package/packages/web/src/vite-env.d.ts +1 -0
- package/packages/web/tailwind.config.ts +66 -0
- package/packages/web/tsconfig.json +28 -0
- package/packages/web/vite.config.ts +36 -0
- package/packages/web/vitest.config.ts +21 -0
- package/packages/web/vitest.setup.ts +1 -0
- package/scripts/activate-data-sources.sh +223 -0
- package/scripts/brand-completion.py +586 -0
- package/scripts/init-nextjs-project.sh +421 -0
- package/scripts/install-and-sync.sh +209 -0
- package/scripts/start-dev.sh +72 -0
- package/docs/GUIDE.md +0 -190
- package/docs/PLAN.md +0 -359
- package/docs/RULES.md +0 -329
- package/docs/RUNBOOK-myskills.md +0 -258
- package/docs/SYNC-SKILLS.md +0 -259
- package/docs/releases/README.md +0 -47
- package/docs/releases/v0.1.0.md +0 -256
- package/docs/releases/v0.1.1.md +0 -297
- package/docs/releases/v0.1.2.md +0 -207
- package/docs/releases/v0.1.3.md +0 -269
- package/docs/todo/v0.1.2.md +0 -98
- package/docs/todo/v0.1.3.md +0 -40
- package/docs/todo/v0.1.4.md +0 -36
- package/docs/todo/v0.1.5.md +0 -41
- package/docs/todo/v0.1.6.md +0 -43
- package/docs/todo/v0.1.7.md +0 -38
- package/docs/todo/v0.1.8.md +0 -36
- package/docs/todo/v0.1.9.md +0 -54
- package/packages/web/dist/assets/index-BPepSb3q.js +0 -36
- package/packages/web/dist/assets/index-CIGkgT5w.css +0 -1
- package/packages/web/src/App.vue +0 -483
- package/packages/web/src/components/AppTree.vue +0 -230
- package/packages/web/src/components/DirectoryTree.vue +0 -263
- package/packages/web/src/components/SkillTree.vue +0 -208
- package/packages/web/src/lib/api.js +0 -43
- package/packages/web/src/main.js +0 -6
- package/packages/web/src/stores/i18n.js +0 -161
- package/packages/web/src/stores/skills.js +0 -287
- package/packages/web/src/styles.css +0 -365
- package/packages/web/vite.config.js +0 -17
- /package/{scripts → build}/build-web.mjs +0 -0
- /package/{scripts → build}/prepare-publish.mjs +0 -0
package/docs/GUIDE.md
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# HuHaa-MySkills 快速启动指南
|
|
2
|
-
|
|
3
|
-
> 5 分钟内将 HuHaa-MySkills 部署到你的本地环境
|
|
4
|
-
|
|
5
|
-
## 前置条件
|
|
6
|
-
|
|
7
|
-
- **Node.js 20+** - 检查:`node --version`
|
|
8
|
-
- **npm** - 检查:`npm --version`
|
|
9
|
-
- **macOS/Linux/Windows** - 支持所有平台
|
|
10
|
-
|
|
11
|
-
## 安装方式
|
|
12
|
-
|
|
13
|
-
### 选项 A:快速启动(推荐)
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
# 1. 克隆到 Project 目录
|
|
17
|
-
cd ~/Project
|
|
18
|
-
git clone https://github.com/aquarkgn/HuHaa-MySkills.git
|
|
19
|
-
cd HuHaa-MySkills
|
|
20
|
-
|
|
21
|
-
# 2. 安装依赖
|
|
22
|
-
npm install
|
|
23
|
-
|
|
24
|
-
# 3. 启动(自动打开浏览器)
|
|
25
|
-
npm start
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
✓ 完成。浏览器会自动打开 `http://localhost:11520`
|
|
29
|
-
|
|
30
|
-
### 选项 B:全局 CLI
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
# 一次安装,到处使用
|
|
34
|
-
npm install -g github:aquarkgn/HuHaa-MySkills
|
|
35
|
-
|
|
36
|
-
# 任何目录启动
|
|
37
|
-
huhaa-myskills start
|
|
38
|
-
huhaa-myskills scan
|
|
39
|
-
huhaa-myskills stats
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 选项 C:从 Hermes 技能启动
|
|
43
|
-
|
|
44
|
-
在 Hermes 或 Claude Code 中调用技能 `huhaa-myskills-manager`:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
"启动 huhaa" 或 "打开技能中心"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
自动判断状态并启动。
|
|
51
|
-
|
|
52
|
-
## 首次配置
|
|
53
|
-
|
|
54
|
-
### 1. 自动生成配置文件
|
|
55
|
-
|
|
56
|
-
首次启动时,HuHaa 会在用户数据目录创建 `sources.yaml`:
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
# macOS / Linux
|
|
60
|
-
~/.config/huhaa-myskills/sources.yaml
|
|
61
|
-
|
|
62
|
-
# 或指定自定义路径
|
|
63
|
-
export HUHAA_HOME=/path/to/config
|
|
64
|
-
npm start
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 2. 默认扫描源
|
|
68
|
-
|
|
69
|
-
| 源 | 路径 | 说明 |
|
|
70
|
-
|----|------|------|
|
|
71
|
-
| **hermes** | `~/.hermes/skills/` | Hermes 技能库 |
|
|
72
|
-
| **claude-code** | `~/.claude/skills/` | Claude Code 技能 |
|
|
73
|
-
| **mcp-config** | 各配置文件 | MCP 服务器定义 |
|
|
74
|
-
| **cursor-rules** | `.cursorrules` 等 | Cursor 规则 |
|
|
75
|
-
| **project-runbook** | `docs/RUNBOOK-*.md` | 项目文档 |
|
|
76
|
-
|
|
77
|
-
### 3. 自定义扫描源
|
|
78
|
-
|
|
79
|
-
编辑 `sources.yaml` 添加新源:
|
|
80
|
-
|
|
81
|
-
```yaml
|
|
82
|
-
sources:
|
|
83
|
-
hermes:
|
|
84
|
-
enabled: true
|
|
85
|
-
roots:
|
|
86
|
-
- ~/.hermes/skills
|
|
87
|
-
|
|
88
|
-
my-project-skills:
|
|
89
|
-
enabled: true
|
|
90
|
-
roots:
|
|
91
|
-
- ~/Project/MyProject/skills
|
|
92
|
-
glob: "**/*.md"
|
|
93
|
-
|
|
94
|
-
limits:
|
|
95
|
-
maxFiles: 5000
|
|
96
|
-
maxFileBytes: 1048576
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## 核心命令
|
|
100
|
-
|
|
101
|
-
| 命令 | 说明 |
|
|
102
|
-
|------|------|
|
|
103
|
-
| `npm start` | 启动并打开浏览器 |
|
|
104
|
-
| `npm run scan` | 仅扫描,输出 JSON |
|
|
105
|
-
| `npm run stats` | 统计信息 |
|
|
106
|
-
| `npm run dev` | 开发模式(热重载) |
|
|
107
|
-
| `npm run verify` | 完整性检查 |
|
|
108
|
-
| `npm test` | 运行测试 |
|
|
109
|
-
|
|
110
|
-
## 使用场景
|
|
111
|
-
|
|
112
|
-
### 场景 1:查找技能
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
|
-
# 浏览器打开 localhost:11520
|
|
116
|
-
# ↓
|
|
117
|
-
# 搜索框输入关键词(支持中文)
|
|
118
|
-
# ↓
|
|
119
|
-
# 找到目标技能
|
|
120
|
-
# ↓
|
|
121
|
-
# 点击"复制原文" 或 "复制路径"
|
|
122
|
-
# ↓
|
|
123
|
-
# 粘贴到 Cursor 上下文使用
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 场景 2:浏览所有 MCP
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
# 主页左侧分组切换为 "source"
|
|
130
|
-
# ↓
|
|
131
|
-
# 选择 "mcp-config"
|
|
132
|
-
# ↓
|
|
133
|
-
# 查看所有已配置的 MCP 服务器和工具
|
|
134
|
-
# ↓
|
|
135
|
-
# 在详情页复制工具定义
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### 场景 3:开发新技能
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
# 1. 在编辑器中创建 ~/.hermes/skills/my-skill/SKILL.md
|
|
142
|
-
# 2. HuHaa 会在 1 秒内自动检测并显示
|
|
143
|
-
# 3. 实时查看、测试、调试
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## 故障排查
|
|
147
|
-
|
|
148
|
-
### 端口被占用
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
PORT=11521 npm start
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### 依赖安装失败
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
rm -rf node_modules package-lock.json
|
|
158
|
-
npm install
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### 某个源为 unavailable
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
# 检查源配置
|
|
165
|
-
cat ~/.config/huhaa-myskills/sources.yaml
|
|
166
|
-
|
|
167
|
-
# 或诊断
|
|
168
|
-
huhaa-myskills doctor # v0.1.8+ 支持
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### 搜索性能慢
|
|
172
|
-
|
|
173
|
-
```bash
|
|
174
|
-
# 编辑 sources.yaml,添加 exclude 规则
|
|
175
|
-
exclude:
|
|
176
|
-
- "**/node_modules"
|
|
177
|
-
- "**/.git"
|
|
178
|
-
- "**/dist"
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## 下一步
|
|
182
|
-
|
|
183
|
-
- 📖 [完整文档](../README.md)
|
|
184
|
-
- 🏗️ [架构设计](./PLAN.md)
|
|
185
|
-
- 📋 [版本计划](./todo/)
|
|
186
|
-
- 🚀 [Runbook](./RUNBOOK-myskills.md)
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
**需要帮助?** → [GitHub Issues](https://github.com/aquarkgn/HuHaa-MySkills/issues)
|
package/docs/PLAN.md
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
# HuHaa-MySkills — 本地 Skill / Plugin / MCP 聚合中枢
|
|
2
|
-
|
|
3
|
-
按 gstack/plan-eng-review 评审骨架编写(架构 / 代码质量 / 测试 / 性能 / NOT-in-scope / 必填输出),用于实施前锁定方案。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 0. 项目定位(一句话)
|
|
8
|
-
|
|
9
|
-
一个本地纯 Node.js 项目,`npm install && npm start` 起 `http://localhost:11520`,把散落在 Hermes / Claude Code / Codex / Cursor / Obsidian / 各项目根目录的「skill / plugin / MCP / 部署 RUNBOOK」**聚合成一个浏览器目录**,按 工具 → 项目 → 目录 → 产品/品牌 四级浏览,详情页提供描述、参数、用法示例、**一键复制路径 / 复制原文 / 在编辑器中打开**,让"想用某技能 → 切回 Cursor 粘贴上下文"这条路从「翻 5 个目录 + grep」收敛成「11520 搜一下点复制」。
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## 1. 架构评审(Architecture)
|
|
14
|
-
|
|
15
|
-
### 1.1 顶层组件
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
HuHaa-MySkills/
|
|
19
|
-
├── packages/
|
|
20
|
-
│ ├── scanner/ # 扫描器:多源 → 统一 IR
|
|
21
|
-
│ ├── server/ # Fastify HTTP + SSE 热更新
|
|
22
|
-
│ └── web/ # Vite + Vue3 SPA
|
|
23
|
-
├── config/
|
|
24
|
-
│ └── sources.yaml # 用户声明的扫描源
|
|
25
|
-
├── data/
|
|
26
|
-
│ └── cache.json # IR 缓存(gitignore)
|
|
27
|
-
└── package.json # workspaces 单仓
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
不拆 monorepo 的多包发布,只拿 npm workspaces 做内部代码隔离 —— 用户口径"最简能跑",单仓单 `npm start`。
|
|
31
|
-
|
|
32
|
-
### 1.2 数据流
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
sources.yaml ──┐
|
|
36
|
-
├─→ Scanner ──→ Adapters ──→ 统一 IR (JSON) ──┐
|
|
37
|
-
fs walkers ────┘ (per-type) │ ├─→ cache.json
|
|
38
|
-
▼ │
|
|
39
|
-
chokidar watch ────── SSE ────→ Browser SPA
|
|
40
|
-
└─→ /api/skills
|
|
41
|
-
/api/copy
|
|
42
|
-
/api/open
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
关键设计:**所有源都被适配器规范化成同一份 IR**,前端只认 IR,不关心源是 Hermes 还是 Cursor。
|
|
46
|
-
|
|
47
|
-
### 1.3 统一 IR(Intermediate Representation)
|
|
48
|
-
|
|
49
|
-
```ts
|
|
50
|
-
type SkillItem = {
|
|
51
|
-
id: string; // sha1(absPath),稳定
|
|
52
|
-
kind: 'skill' | 'plugin' | 'mcp' | 'runbook' | 'agent-rule';
|
|
53
|
-
source: 'hermes' | 'claude-code' | 'codex' | 'cursor' | 'obsidian' | 'project' | 'mcp-config';
|
|
54
|
-
name: string; // frontmatter.name 或 文件名
|
|
55
|
-
title?: string; // 人类可读
|
|
56
|
-
description?: string;
|
|
57
|
-
category?: string; // 例:devops, mlops/inference
|
|
58
|
-
brand?: string; // 例:OpenAI, Anthropic, Google, Cloudflare(从 description / 路径推断)
|
|
59
|
-
product?: string; // 例:new-api, frp, vLLM
|
|
60
|
-
triggers?: string[]; // when_to_use / triggers / aliases
|
|
61
|
-
params?: ParamSpec[]; // MCP tools 才有;skill 一般为空
|
|
62
|
-
tags?: string[];
|
|
63
|
-
paths: {
|
|
64
|
-
abs: string; // 绝对路径(复制按钮用)
|
|
65
|
-
rel?: string; // 相对项目根
|
|
66
|
-
rootKind: 'home' | 'project' | 'icloud';
|
|
67
|
-
};
|
|
68
|
-
preview: string; // 截前 N 行 markdown body
|
|
69
|
-
raw: string; // 完整文件原文(详情页 lazy load)
|
|
70
|
-
links?: { label: string; url: string }[];
|
|
71
|
-
updatedAt: string; // ISO
|
|
72
|
-
};
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### 1.4 适配器矩阵(决定能聚合到什么)
|
|
76
|
-
|
|
77
|
-
| Adapter | 扫描路径 | 解析 | kind |
|
|
78
|
-
|----------------|--------------------------------------------------------------------------|-----------------------------------------------|---------------------|
|
|
79
|
-
| hermes | `~/.hermes/skills/**/SKILL.md`,`~/.hermes/profiles/*/skills/**` | YAML frontmatter + body | skill |
|
|
80
|
-
| claude-code | `~/.claude/skills/**/SKILL.md` | YAML frontmatter + body | skill |
|
|
81
|
-
| codex-agents | 工程根 `AGENTS.md`,`~/.codex/AGENTS.md` | 纯 markdown,h1/h2 切段 | agent-rule |
|
|
82
|
-
| cursor-rules | 工程根 `.cursorrules`,`.cursor/rules/*.mdc` | mdc frontmatter + body | agent-rule |
|
|
83
|
-
| claude-md | 工程根 `CLAUDE.md` | 纯 markdown | agent-rule |
|
|
84
|
-
| mcp-config | `~/.cursor/mcp.json`,`~/.codex/config.toml [mcp_servers]`,`~/Library/Application Support/Claude/claude_desktop_config.json`,`~/.hermes/config.yaml mcp:` | JSON / TOML / YAML 解析出 servers + tools | mcp |
|
|
85
|
-
| hermes-plugin | `~/.hermes/plugins/**/manifest.*` | manifest.json/yaml | plugin |
|
|
86
|
-
| project-runbook| `**/docs/RUNBOOK-*.md`(按 sources.yaml 声明的项目根) | 纯 markdown | runbook |
|
|
87
|
-
| obsidian | 用户声明 vault 路径下打了 `#skill` 标签的 note | frontmatter + tags | skill |
|
|
88
|
-
|
|
89
|
-
`sources.yaml` 默认开 hermes / claude-code / mcp-config,其他要用户白名单具体项目根(避免误扫整个磁盘)。
|
|
90
|
-
|
|
91
|
-
### 1.5 单一职责边界
|
|
92
|
-
|
|
93
|
-
- **Scanner** 只产 IR,不碰 HTTP。
|
|
94
|
-
- **Server** 只读 IR + 提供 API + 静态文件 + SSE,不解析任何源文件。
|
|
95
|
-
- **Web** 只渲染 IR + 调三个 endpoint:`/api/skills`、`/api/copy`、`/api/open`。
|
|
96
|
-
- 复制路径走 `/api/copy?path=...` → 后端 `pbcopy`(macOS)/ `clip`(win)/ `xclip`(linux),**不**靠浏览器 `navigator.clipboard`(HTTP 在非 localhost 域会卡权限,且复制原文时绕过 N KB 上限更稳)。
|
|
97
|
-
- "在编辑器中打开"走 `/api/open?path=...&editor=cursor` → 后端 `open -a 'Cursor' <path>` 或 `cursor <path>` / `code <path>`。
|
|
98
|
-
|
|
99
|
-
### 1.6 关键失败场景与对策
|
|
100
|
-
|
|
101
|
-
| 场景 | 后果 | 对策 |
|
|
102
|
-
|-------------------------------------------------|-------------------|-------------------------------------------------------------------|
|
|
103
|
-
| 用户声明的项目根不存在(机器搬迁) | 扫描器抛错 | 单源 try/catch,UI 上单源标 `unavailable`,其他源照常 |
|
|
104
|
-
| YAML frontmatter 损坏(手改坏的) | 整文件丢失 | parse 失败时降级:name=文件名、preview=前 30 行、`parseError` 字段 |
|
|
105
|
-
| 11520 端口被占 | 起不来 | 启动检测,`PORT` env 覆盖;CLI 输出 fallback 端口 |
|
|
106
|
-
| 文件数量爆炸(vault 含 10k notes) | 扫描卡 CPU | sources.yaml 强制 `include`/`exclude` glob,`maxFiles: 5000` 硬限 |
|
|
107
|
-
| 浏览器在远端(SSH 转发)打开页面,复制按钮失效 | 复制不动 | `/api/copy` 在远端跑 pbcopy 也无意义 —— UI 同时给"原文+点击全选" |
|
|
108
|
-
| chokidar 在 macOS 全盘监听耗 fd | 系统卡 | 只 watch sources.yaml 列出的具体子树,`usePolling: false` |
|
|
109
|
-
|
|
110
|
-
### 1.7 安全 / 数据边界
|
|
111
|
-
|
|
112
|
-
- 全程 **localhost only**:server bind `127.0.0.1`,**不**支持 `0.0.0.0`。
|
|
113
|
-
- `/api/open` 路径白名单:必须在 sources.yaml 已声明的根之下,否则 403 —— 防 `?path=/etc/passwd` 这类。
|
|
114
|
-
- `/api/copy` 同样白名单 —— 防当文件读取代理。
|
|
115
|
-
- 不上传不联网,不写 telemetry。
|
|
116
|
-
- `data/cache.json` 进 `.gitignore`,但 `.env` / `sources.yaml` 用户决定(按你的 git 习惯:`.env` 入库)。
|
|
117
|
-
|
|
118
|
-
### 1.8 分发架构
|
|
119
|
-
|
|
120
|
-
- **不发 npm**。私仓 git clone + `npm install && npm start`。
|
|
121
|
-
- `package.json` 暴露三条 script:
|
|
122
|
-
- `npm start` — 一键:扫一次 → 起 server → 自动 `open http://localhost:11520`
|
|
123
|
-
- `npm run scan` — 只扫描,dump IR 到 stdout(debug 用)
|
|
124
|
-
- `npm run dev` — Vite dev server + nodemon server,前后端热重载
|
|
125
|
-
- 后续要给别的机器用,直接 `git clone + npm i + npm start`。
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## 2. 代码质量评审(Code Quality)
|
|
130
|
-
|
|
131
|
-
### 2.1 技术选型(决策已锁)
|
|
132
|
-
|
|
133
|
-
| 维度 | 选型 | 理由 |
|
|
134
|
-
|---------------|-------------------------------|---------------------------------------------------------------------|
|
|
135
|
-
| Runtime | Node 20+ | LTS、Fastify v5 要求、原生 `fs.glob` |
|
|
136
|
-
| 包管理 | npm workspaces | 你机器装的是 npm,pnpm 不强制 |
|
|
137
|
-
| HTTP 框架 | **Fastify 5** | Express 已死气;Fastify 内置 schema validation + 更快 |
|
|
138
|
-
| YAML | `yaml` (eemeli/yaml) | 比 js-yaml 更宽容损坏 frontmatter |
|
|
139
|
-
| TOML | `@iarna/toml` | Codex config.toml 必须 |
|
|
140
|
-
| 文件 watch | `chokidar` v3 | 跨平台、稳定 |
|
|
141
|
-
| Frontend | **Vite 5 + Vue 3 + TS** | 单 SPA、轻、官方 Devtools、UI 用 [Vuetify](https://vuetifyjs.com) |
|
|
142
|
-
| 状态 | Pinia | Vue 官方,简单 |
|
|
143
|
-
| 搜索 | Fuse.js | 全在前端,无需后端 ES |
|
|
144
|
-
| 编辑器跳转 | `child_process.spawn` | 直接 `cursor` / `code` / `open -a` |
|
|
145
|
-
| 剪贴板 | `clipboardy` 或自写 pbcopy | clipboardy 4.x ESM-only 注意 |
|
|
146
|
-
|
|
147
|
-
> 不要 React —— 单人小工具用 Vue 心智更轻;不要 Next/Nuxt —— 没 SSR 需求,纯 SPA 够。
|
|
148
|
-
> 不要 TypeScript on backend 也无所谓,但**前端必须 TS**(IR 类型定义会救命)。
|
|
149
|
-
|
|
150
|
-
### 2.2 模块边界(强约束 — 防滑坡)
|
|
151
|
-
|
|
152
|
-
- 适配器 **不允许**互相 import,全部产同一份 `SkillItem[]`。新增源 = 新文件 + 注册表登记一行。
|
|
153
|
-
- Server 的 route handler **不允许**做扫描,启动期 + watch 事件触发 scanner,handler 只读内存 IR。
|
|
154
|
-
- 前端 **不允许**直接读文件 fetch,全部走 `/api/*`。
|
|
155
|
-
- DRY:所有适配器共享 `parseFrontmatter(text)` / `inferBrand(item)` / `normalizePath(p)` 三个 util,禁止各自实现。
|
|
156
|
-
|
|
157
|
-
### 2.3 配置文件 schema(sources.yaml 草案)
|
|
158
|
-
|
|
159
|
-
```yaml
|
|
160
|
-
sources:
|
|
161
|
-
hermes:
|
|
162
|
-
enabled: true
|
|
163
|
-
roots:
|
|
164
|
-
- ~/.hermes/skills
|
|
165
|
-
- ~/.hermes/profiles/*/skills
|
|
166
|
-
claude-code:
|
|
167
|
-
enabled: true
|
|
168
|
-
roots:
|
|
169
|
-
- ~/.claude/skills
|
|
170
|
-
mcp-config:
|
|
171
|
-
enabled: true
|
|
172
|
-
files:
|
|
173
|
-
- ~/.cursor/mcp.json
|
|
174
|
-
- ~/.codex/config.toml
|
|
175
|
-
- ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
176
|
-
- ~/.hermes/config.yaml
|
|
177
|
-
project-runbook:
|
|
178
|
-
enabled: true
|
|
179
|
-
roots:
|
|
180
|
-
- ~/Project/HuHaa-AI-Platform
|
|
181
|
-
- ~/Project/HuHaa-Open-Guide
|
|
182
|
-
- ~/Project/HuHaa-Quark-Bridge
|
|
183
|
-
- ~/Library/Mobile Documents/com~apple~CloudDocs/notes
|
|
184
|
-
glob: 'docs/RUNBOOK-*.md'
|
|
185
|
-
ui:
|
|
186
|
-
port: 11520
|
|
187
|
-
autoOpen: true
|
|
188
|
-
defaultEditor: cursor # cursor | code | open
|
|
189
|
-
groupBy: [source, category, brand]
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### 2.4 你已经踩过坑、要预先避免的反模式
|
|
193
|
-
|
|
194
|
-
- **不**新建 `xxxProxy.ts` / `xxxAdapter` 层去包装 Fastify —— 直接路由 + handler。
|
|
195
|
-
- **不**在 server 里做"先看 cache 再决定扫"的乐观快路径 —— 启动一定全扫一次,避免缓存陈旧(首扫 < 1s,没必要省)。
|
|
196
|
-
- **不**做 SSR、登录、用户系统、多租户。这是单机工具。
|
|
197
|
-
- **不**把扫描和 HTTP 混进同一个文件 —— 两件事。
|
|
198
|
-
|
|
199
|
-
### 2.5 错误处理
|
|
200
|
-
|
|
201
|
-
- 适配器解析失败 → IR 里 `parseError: string` 字段,UI 红角标显示。
|
|
202
|
-
- HTTP handler 全部用 Fastify schema 校验入参。
|
|
203
|
-
- `/api/open` 失败(编辑器没装)→ 200 返回 `{ ok:false, hint:"未检测到 cursor,请安装 Cursor 命令行" }`,UI 弹 toast。
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## 3. 测试评审(Test)
|
|
208
|
-
|
|
209
|
-
### 3.1 测试栈
|
|
210
|
-
|
|
211
|
-
- **Vitest**(前后端通吃)+ `supertest` 打 Fastify。
|
|
212
|
-
- E2E 不做(单人工具,过度工程)。
|
|
213
|
-
|
|
214
|
-
### 3.2 必测覆盖(按代码路径 + 用户路径)
|
|
215
|
-
|
|
216
|
-
```
|
|
217
|
-
适配器层(每个 adapter 独立 fixture 目录)
|
|
218
|
-
├─ hermes.adapter.test.ts
|
|
219
|
-
│ ├── ★★★ 正常 SKILL.md → 完整 IR
|
|
220
|
-
│ ├── ★★★ frontmatter 损坏 → 降级 + parseError
|
|
221
|
-
│ ├── ★★ 目录不存在 → 单源 unavailable,不 throw
|
|
222
|
-
│ └── ★★ description 含 brand 关键字 → brand 推断正确
|
|
223
|
-
├─ mcp-config.adapter.test.ts
|
|
224
|
-
│ ├── ★★★ 解析 cursor mcp.json
|
|
225
|
-
│ ├── ★★★ 解析 codex config.toml [mcp_servers]
|
|
226
|
-
│ └── ★★ 字段缺失(command 没写)→ parseError
|
|
227
|
-
├─ cursor-rules.adapter.test.ts ── ★★ mdc frontmatter
|
|
228
|
-
└─ project-runbook.adapter.test.ts ── ★★ glob 命中
|
|
229
|
-
|
|
230
|
-
Server 层
|
|
231
|
-
├─ GET /api/skills ★★★ 返回全量 IR
|
|
232
|
-
├─ GET /api/skills/:id ★★★ 返回 raw + 详情
|
|
233
|
-
├─ POST /api/copy { path } ★★★ 白名单内 → pbcopy;白名单外 → 403
|
|
234
|
-
├─ POST /api/open { path, editor } ★★★ 白名单内 → spawn;编辑器没装 → 友好失败
|
|
235
|
-
├─ GET /sse ★★ watch 触发 → 推 'reload' 事件
|
|
236
|
-
└─ Port 11520 已占 ★★ fallback 提示
|
|
237
|
-
|
|
238
|
-
前端
|
|
239
|
-
└─ 不写单测;靠手测 + Pinia DevTools 即可(单人小工具,不值得)
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
覆盖率目标:**适配器与 server 90% 行覆盖**,前端 0%。
|
|
243
|
-
|
|
244
|
-
### 3.3 关键回归用例(必须打住的退化)
|
|
245
|
-
|
|
246
|
-
- 任何对 frontmatter 解析的修改 → 回归一遍"损坏 YAML 不 crash 整次扫描"。
|
|
247
|
-
- 任何对路径白名单的修改 → 回归"路径穿越 `../../etc/passwd` 必 403"。
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## 4. 性能评审(Performance)
|
|
252
|
-
|
|
253
|
-
### 4.1 扫描期
|
|
254
|
-
|
|
255
|
-
- 你机器上初步统计:Hermes 116 + gstack 545 + 项目 RUNBOOK 数十 ≈ **800 文件量级**。读 + parse YAML ≈ 100-300 ms(M 系列),完全不需要 worker pool。
|
|
256
|
-
- 上限保护:`maxFiles: 5000` + `maxFileBytes: 1MB`,超过跳过 + warn。
|
|
257
|
-
|
|
258
|
-
### 4.2 运行期
|
|
259
|
-
|
|
260
|
-
- IR 全量内存(800 条 × 平均 2KB raw ≈ 2MB),单进程吃得下。
|
|
261
|
-
- `/api/skills` 只返回 IR 元信息(不带 raw),约 200KB gzip 后 < 30KB。
|
|
262
|
-
- raw 走 `/api/skills/:id`,懒加载,详情页打开才取。
|
|
263
|
-
- 前端 Fuse.js 索引在加载后构建一次,800 条搜索延迟 < 5ms。
|
|
264
|
-
|
|
265
|
-
### 4.3 watch 风暴
|
|
266
|
-
|
|
267
|
-
- chokidar 在 SKILL.md 改动 → debounce 500ms → 单源重扫(不全量)→ SSE broadcast `{type:'reload', source:'hermes'}`。
|
|
268
|
-
- 前端收到后只重拉对应 source 的 IR,不全量刷新。
|
|
269
|
-
|
|
270
|
-
### 4.4 不优化的事
|
|
271
|
-
|
|
272
|
-
- 不做 lazy 适配器(首扫 < 1s 没必要)。
|
|
273
|
-
- 不做 IndexedDB 前端缓存(每次刷新重拉 200KB 没影响)。
|
|
274
|
-
- 不做 SSR / 预渲染。
|
|
275
|
-
|
|
276
|
-
---
|
|
277
|
-
|
|
278
|
-
## 5. NOT in scope(已考虑但显式不做,每条带理由)
|
|
279
|
-
|
|
280
|
-
- **写 / 编辑技能**:本工具是只读浏览器,编辑请回到 Cursor / Hermes CLI。原因:避免变成第二个编辑器,scope 爆炸。
|
|
281
|
-
- **跨机同步**:每台机器自己跑,sources.yaml 自己写。原因:你已有 iCloud / git 同步习惯,重复造轮子。
|
|
282
|
-
- **AI 推荐 / 智能调用**:不在页面里调 LLM 帮你选技能。原因:你有 Hermes / Claude Code,那是它们的事。
|
|
283
|
-
- **打包成 Electron 桌面 app**:只是浏览器 SPA。原因:单人工具,浏览器够用,省 200MB。
|
|
284
|
-
- **多用户 / 鉴权**:localhost only。原因:单机工具。
|
|
285
|
-
- **写入 MCP 服务器配置**:只读展示。原因:写配置是一次性的事,不值得做 UI。
|
|
286
|
-
- **远程 SSH skill 聚合**:只扫本机。原因:你机器之间通常 git 同步项目,跨机扫盘没必要。
|
|
287
|
-
- **Windows / Linux 一等公民**:开发以 macOS 为准;其他平台尽量兼容但不专门测。原因:你是 Mac 用户。
|
|
288
|
-
- **OAuth / 私有 Git 拉技能**:源限文件系统。原因:scope。
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## 6. 必填输出
|
|
293
|
-
|
|
294
|
-
### 6.1 验收标准(Done definition)
|
|
295
|
-
|
|
296
|
-
- [ ] `git clone && npm install && npm start` → 浏览器自动打开 `localhost:11520`,主页可见至少 hermes / claude-code / mcp-config 三个 source 的合计技能数。
|
|
297
|
-
- [ ] 左侧树支持四种分组切换:source / category / brand / product。
|
|
298
|
-
- [ ] 详情页有:description、triggers、参数表(仅 MCP)、preview、原文、**复制路径按钮**、**复制原文按钮**、**在 Cursor 中打开按钮**。
|
|
299
|
-
- [ ] 修改 `~/.hermes/skills/devops/new-api-deployment/SKILL.md` 后,浏览器在 1s 内自动刷新该条目。
|
|
300
|
-
- [ ] 关掉 Cursor,点"在 Cursor 中打开" → toast "未检测到 cursor 命令",不崩。
|
|
301
|
-
- [ ] `curl 'http://localhost:11520/api/copy?path=/etc/passwd'` → 403。
|
|
302
|
-
- [ ] 任何一个源的根目录不存在 → 该源标 `unavailable`,其他源照常列出。
|
|
303
|
-
|
|
304
|
-
### 6.2 实施阶段(按你 30s 协议,每阶段一个可验产物)
|
|
305
|
-
|
|
306
|
-
| 阶段 | 交付 | 验证 | 估时 |
|
|
307
|
-
|------|----------------------------------------------------------|-------------------------------------------------|--------|
|
|
308
|
-
| P0 | 仓骨架 + workspaces + sources.yaml + IR 类型 | `npm install` 通过 | 30 min |
|
|
309
|
-
| P1 | hermes + claude-code 适配器 + `npm run scan` 出全量 IR | stdout 看到 660+ 条 | 60 min |
|
|
310
|
-
| P2 | Fastify server + `/api/skills` + `/api/skills/:id` | curl 返回 JSON | 45 min |
|
|
311
|
-
| P3 | Vue SPA 主页 + 列表 + 详情 + 复制路径 | 浏览器能浏览 + 复制 | 90 min |
|
|
312
|
-
| P4 | mcp-config + cursor-rules + project-runbook 适配器 | 主页见到 MCP servers + RUNBOOK | 60 min |
|
|
313
|
-
| P5 | chokidar + SSE 热更新 | 改 SKILL.md → 页面 1s 内刷新 | 45 min |
|
|
314
|
-
| P6 | brand/product 推断 + 四种分组 | 切分组下拉 → UI 重排 | 30 min |
|
|
315
|
-
| P7 | `/api/open` + Vitest 测试 | 点按钮跳 Cursor + `npm test` 全绿 | 45 min |
|
|
316
|
-
|
|
317
|
-
合计约 7-8 小时净工作量,分两到三天。
|
|
318
|
-
|
|
319
|
-
### 6.3 风险登记(Risks)
|
|
320
|
-
|
|
321
|
-
| ID | 风险 | 影响 | 缓解 |
|
|
322
|
-
|----|--------------------------------------------|----------|-------------------------------------------------------|
|
|
323
|
-
| R1 | 适配器对每种格式假设错误(实际 frontmatter 字段名不一致) | 数据错乱 | P1 出 IR 后人工抽 20 条对照原文 |
|
|
324
|
-
| R2 | macOS pbcopy 在 Cursor terminal session 复制不到系统剪贴板 | 复制按钮无效 | 提供"双轨":后端 pbcopy + 前端 navigator.clipboard fallback |
|
|
325
|
-
| R3 | 11520 已被你某个服务占 | 起不来 | 启动期 try-listen,占用就 +1 试到 11530,最终值打到日志 |
|
|
326
|
-
| R4 | iCloud 路径含空格 + `~/Library/Mobile Documents/com~apple~CloudDocs` 这种波浪号 | 路径解析炸 | 统一用 `os.homedir() + path.join`,不字符串拼 |
|
|
327
|
-
|
|
328
|
-
### 6.4 Cross-model tension(自我反诘)
|
|
329
|
-
|
|
330
|
-
- **是否该用 Tauri 而非纯 Web SPA?** 我倾向**否**。Tauri 给本地剪贴板/打开文件更原生,但带来 Rust 工具链 + 打包复杂度,单人工具划不来;浏览器 + `/api/copy` `/api/open` 已覆盖核心诉求。
|
|
331
|
-
- **是否该把 Hermes 自己做的 skill 浏览器(如果有)直接借用?** Hermes 的 `hermes skills` 是 CLI、且只看 Hermes 自己的目录。本项目核心价值是**跨工具聚合**,不可替代。
|
|
332
|
-
|
|
333
|
-
---
|
|
334
|
-
|
|
335
|
-
## 7. Open questions(开干前需要你确认)
|
|
336
|
-
|
|
337
|
-
仅 4 条 —— 其他默认按上面写法。
|
|
338
|
-
|
|
339
|
-
Q1. **sources.yaml 默认要不要包含 `~/.codex/`、Cursor 项目 `.cursorrules`?**
|
|
340
|
-
A) 默认全开(hermes + claude-code + cursor + codex + mcp-config + 你列的 4 个项目根的 RUNBOOK)
|
|
341
|
-
B) 只默认开 hermes + claude-code + mcp-config,剩余手动加(更保守)
|
|
342
|
-
我建议 A,理由:你机器上这些路径都真实存在,默认聚合才有"中枢"感。
|
|
343
|
-
|
|
344
|
-
Q2. **前端 UI 风格?**
|
|
345
|
-
A) Vuetify Material Design(最快,组件全)
|
|
346
|
-
B) 自己写 Tailwind + 极简(你 HuHaa 系产品的 brand 一致)
|
|
347
|
-
我建议 A 第一版上,P7 之后看心情换 B。
|
|
348
|
-
|
|
349
|
-
Q3. **"复制原文"按钮要不要带 frontmatter?**
|
|
350
|
-
A) 带(粘到 Cursor 里 LLM 能看到 triggers / when_to_use,更聪明)
|
|
351
|
-
B) 只复制 body
|
|
352
|
-
我建议 A。
|
|
353
|
-
|
|
354
|
-
Q4. **要不要顺便加一个 `/api/exec-skill?id=...` —— 直接调起对应的 Hermes / Claude Code 命令?**
|
|
355
|
-
A) 加(一键执行)
|
|
356
|
-
B) **本期不加**,只复制路径 → 你回 Cursor 自己说 "用这个 skill"
|
|
357
|
-
我建议 B —— 原始诉求是"复制按钮回到编辑器使用",多搞执行通道 = scope 爆炸 + 安全面变大。
|
|
358
|
-
|
|
359
|
-
回我 `Q1=A Q2=A Q3=A Q4=B`(或任意改动)我就进入 P0。
|