harveyz-skill 0.1.0

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 ADDED
@@ -0,0 +1,67 @@
1
+ # Harvey Skills
2
+
3
+ Harvey 的个人 Claude Code 技能仓库。
4
+
5
+ ## 技能清单
6
+
7
+ | 技能 | 说明 | 外部依赖 |
8
+ |------|------|---------|
9
+ | **harvey-plain** | 白话引擎 — 把任何内容改写到聪明的十二岁小孩也能懂 | 无 |
10
+ | **skill-analyzer** | 系统化分析 Skill 仓库的框架,基于洋葱模型四层结构 | 无 |
11
+
12
+ > 更多技能陆续添加中。
13
+
14
+ ## 安装
15
+
16
+ ### 全部安装
17
+
18
+ ```bash
19
+ mkdir -p ~/.claude/skills
20
+ cp -r skills/* ~/.claude/skills/
21
+ ```
22
+
23
+ ### 安装依赖(如有)
24
+
25
+ ```bash
26
+ bash scripts/install.sh
27
+ ```
28
+
29
+ ## 工作流
30
+
31
+ ```
32
+ harvey-plain: 内容 → org-mode 文件(~/Documents/notes/)
33
+ ```
34
+
35
+ ## Skill 开发指南
36
+
37
+ ### 命名规范
38
+
39
+ - 前缀:`harvey-`(例:`harvey-plain`、`harvey-card`)
40
+ - 每个 skill 独立目录,`SKILL.md` 是唯一入口
41
+
42
+ ### SKILL.md 格式
43
+
44
+ ```yaml
45
+ ---
46
+ name: skill-name
47
+ description: "做什么。触发词..."
48
+ user_invocable: true
49
+ version: "x.x.x"
50
+ ---
51
+ ```
52
+
53
+ ### 共享规范
54
+
55
+ **Org-mode 输出:**
56
+ - 加粗:`*text*`(单星号)
57
+ - 文件名:`{时间戳}--{标题}__{type}.org`
58
+ - 输出目录:`~/Documents/notes/`
59
+ - 时间戳:`date +%Y%m%dT%H%M%S`
60
+
61
+ **ASCII Art:**
62
+ - 允许:`+ - | / \ > < v ^ * = ~ . : # [ ] ( ) _ , ; ! ' "`
63
+ - 禁止:Unicode 绘图符号
64
+
65
+ ## 许可证
66
+
67
+ Private — 仅供个人使用。
package/bin/cli.js ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ import { checkbox } from '@inquirer/prompts'
3
+ import chalk from 'chalk'
4
+ import { BUNDLE_CHOICES, resolveSkills } from '../lib/bundles.js'
5
+ import { TARGET_CHOICES, resolveTargets, TARGETS } from '../lib/targets.js'
6
+ import { installSkills } from '../lib/installer.js'
7
+
8
+ const args = process.argv.slice(2)
9
+ const forceFlag = args.includes('--force')
10
+ const bundleIdx = args.indexOf('--bundle')
11
+ const targetIdx = args.indexOf('--target')
12
+ const bundleArg = bundleIdx !== -1 ? args[bundleIdx + 1] : undefined
13
+ const targetArg = targetIdx !== -1 ? args[targetIdx + 1] : undefined
14
+
15
+ // list 子命令
16
+ if (args[0] === 'list') {
17
+ const { createRequire } = await import('module')
18
+ const require = createRequire(import.meta.url)
19
+ const bundles = require('../bundles.json')
20
+ for (const b of bundles) {
21
+ console.log(chalk.bold(b.name) + ' — ' + b.description)
22
+ if (b.skills) for (const s of b.skills) console.log(' ' + s)
23
+ }
24
+ process.exit(0)
25
+ }
26
+
27
+ try {
28
+ // 解析 bundle 选择
29
+ let selectedBundles
30
+ if (bundleArg) {
31
+ selectedBundles = bundleArg.split(',').map(s => s.trim()).filter(Boolean)
32
+ } else {
33
+ selectedBundles = await checkbox({
34
+ message: '选择要安装的 bundle(空格多选):',
35
+ choices: BUNDLE_CHOICES,
36
+ })
37
+ }
38
+
39
+ if (!selectedBundles.length) {
40
+ console.log(chalk.red('未选择任何 bundle,退出。'))
41
+ process.exit(1)
42
+ }
43
+
44
+ // 解析 target 选择
45
+ let selectedTargets
46
+ if (targetArg) {
47
+ selectedTargets = targetArg === 'all' ? Object.keys(TARGETS) : [targetArg]
48
+ } else {
49
+ selectedTargets = await checkbox({
50
+ message: '安装到哪些工具(空格多选):',
51
+ choices: [
52
+ ...TARGET_CHOICES,
53
+ { name: 'all — 全部工具', value: 'all' },
54
+ ],
55
+ })
56
+ }
57
+
58
+ if (!selectedTargets.length) {
59
+ console.log(chalk.red('未选择任何目标工具,退出。'))
60
+ process.exit(1)
61
+ }
62
+
63
+ const skills = resolveSkills(selectedBundles)
64
+ const targets = resolveTargets(selectedTargets)
65
+
66
+ console.log('')
67
+ const summary = await installSkills(skills, targets, forceFlag)
68
+
69
+ console.log('')
70
+ if (Object.keys(summary).length === 0) {
71
+ console.log(chalk.yellow(' 没有 skill 被安装。'))
72
+ } else {
73
+ console.log(chalk.green('✔ 安装完成:'))
74
+ for (const [target, names] of Object.entries(summary)) {
75
+ console.log(` ${chalk.bold(target)} ← ${names.join(', ')}`)
76
+ }
77
+ }
78
+ } catch (err) {
79
+ console.error(chalk.red('Error: ' + err.message))
80
+ process.exit(1)
81
+ }
package/bundles.json ADDED
@@ -0,0 +1,24 @@
1
+ [
2
+ {
3
+ "name": "brainstorming",
4
+ "description": "设计与规划工具(brainstorming + writing-plans)",
5
+ "skills": [
6
+ "superpowers-fork/brainstorming",
7
+ "superpowers-fork/writing-plans"
8
+ ]
9
+ },
10
+ {
11
+ "name": "dev",
12
+ "description": "开发工作流(executing-plans + systematic-debugging + using-git-worktrees)",
13
+ "skills": [
14
+ "superpowers-fork/executing-plans",
15
+ "superpowers-fork/systematic-debugging",
16
+ "superpowers-fork/using-git-worktrees"
17
+ ]
18
+ },
19
+ {
20
+ "name": "all",
21
+ "description": "全部 skill",
22
+ "dynamic": true
23
+ }
24
+ ]
package/lib/bundles.js ADDED
@@ -0,0 +1,39 @@
1
+ import { createRequire } from 'module'
2
+ import path from 'path'
3
+ import { fileURLToPath } from 'url'
4
+
5
+ const require = createRequire(import.meta.url)
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
7
+
8
+ const bundleDefs = require('../bundles.json')
9
+ const skillsRoot = path.join(__dirname, '..', 'skills')
10
+
11
+ export const BUNDLE_CHOICES = bundleDefs.map(b => ({
12
+ name: `${b.name.padEnd(16)} — ${b.description}`,
13
+ value: b.name,
14
+ }))
15
+
16
+ // 返回选中 bundles 对应的去重 skill 路径列表 { skillName, srcPath }
17
+ export function resolveSkills(selectedBundles) {
18
+ // 展开 dynamic bundle(all)为所有非 dynamic bundle 的 union
19
+ const expanded = selectedBundles.flatMap(name => {
20
+ const def = bundleDefs.find(b => b.name === name)
21
+ if (!def) throw new Error(`Unknown bundle: "${name}"`)
22
+ if (def.dynamic) return bundleDefs.filter(b => !b.dynamic).map(b => b.name)
23
+ return name
24
+ })
25
+
26
+ const seen = new Set()
27
+ const result = []
28
+ for (const name of expanded) {
29
+ const def = bundleDefs.find(b => b.name === name)
30
+ if (!def) continue
31
+ for (const rel of def.skills) {
32
+ if (seen.has(rel)) continue
33
+ seen.add(rel)
34
+ const skillName = rel.split('/').pop()
35
+ result.push({ skillName, srcPath: path.join(skillsRoot, rel) })
36
+ }
37
+ }
38
+ return result
39
+ }
@@ -0,0 +1,46 @@
1
+ import fs from 'fs-extra'
2
+ import path from 'path'
3
+ import { confirm } from '@inquirer/prompts'
4
+ import chalk from 'chalk'
5
+
6
+ // skills: [{ skillName, srcPath }]
7
+ // targets: [{ name, dir }]
8
+ // force: boolean
9
+ export async function installSkills(skills, targets, force = false) {
10
+ const summary = {}
11
+
12
+ for (const { name: targetName, dir: targetDir } of targets) {
13
+ const exists = await fs.pathExists(targetDir)
14
+ if (!exists) {
15
+ console.log(chalk.yellow(` 跳过 ${targetName}(目录不存在:${targetDir})`))
16
+ continue
17
+ }
18
+
19
+ const installed = []
20
+ for (const { skillName, srcPath } of skills) {
21
+ const destPath = path.join(targetDir, skillName)
22
+ const destExists = await fs.pathExists(destPath)
23
+
24
+ if (destExists && !force) {
25
+ const ok = await confirm({ message: `${targetName}/${skillName} 已存在,覆盖?`, default: false })
26
+ if (!ok) {
27
+ console.log(chalk.gray(` 跳过 ${targetName}/${skillName}`))
28
+ continue
29
+ }
30
+ }
31
+
32
+ try {
33
+ await fs.copy(srcPath, destPath, { overwrite: true })
34
+ installed.push(skillName)
35
+ } catch (err) {
36
+ console.log(chalk.red(` 复制失败 ${targetName}/${skillName}: ${err.message}`))
37
+ }
38
+ }
39
+
40
+ if (installed.length > 0) {
41
+ summary[targetName] = installed
42
+ }
43
+ }
44
+
45
+ return summary
46
+ }
package/lib/targets.js ADDED
@@ -0,0 +1,23 @@
1
+ import os from 'os'
2
+ import path from 'path'
3
+
4
+ export const TARGETS = {
5
+ claude: path.join(os.homedir(), '.claude', 'skills'),
6
+ cursor: path.join(os.homedir(), '.cursor', 'skills'),
7
+ codex: path.join(os.homedir(), '.codex', 'skills'),
8
+ }
9
+
10
+ export const TARGET_CHOICES = Object.entries(TARGETS).map(([name, dir]) => ({
11
+ name: `${name.padEnd(8)} (${dir})`,
12
+ value: name,
13
+ }))
14
+
15
+ // 返回选中 targets 的 { name, dir } 列表,all 展开为全部
16
+ export function resolveTargets(selected) {
17
+ if (selected.includes('all')) return Object.entries(TARGETS).map(([name, dir]) => ({ name, dir }))
18
+ return selected.map(name => {
19
+ const dir = TARGETS[name]
20
+ if (!dir) throw new Error(`Unknown target: "${name}"`)
21
+ return { name, dir }
22
+ })
23
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "harveyz-skill",
3
+ "version": "0.1.0",
4
+ "description": "One-click skill installer for Claude Code, Cursor, and Codex",
5
+ "type": "module",
6
+ "bin": {
7
+ "harveyz-skill": "bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "prepack": "node scripts/generate-npmignore.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "lib/",
15
+ "bundles.json",
16
+ "skills/analysis/skill-analyzer/CHANGELOG.md",
17
+ "skills/analysis/skill-analyzer/SKILL.md",
18
+ "skills/document/diataxis-docs/",
19
+ "skills/harness/full-stack-debug-env/",
20
+ "skills/superpowers-fork/brainstorming/",
21
+ "skills/superpowers-fork/executing-plans/",
22
+ "skills/superpowers-fork/systematic-debugging/",
23
+ "skills/superpowers-fork/using-git-worktrees/",
24
+ "skills/superpowers-fork/writing-plans/",
25
+ "skills/task/pm-task-dispatch/",
26
+ "skills/task/task-close/"
27
+ ],
28
+ "engines": {
29
+ "node": ">=18"
30
+ },
31
+ "dependencies": {
32
+ "@inquirer/prompts": "^8.4.2",
33
+ "chalk": "^5.3.0",
34
+ "fs-extra": "^11.2.0"
35
+ },
36
+ "author": "harveyzhang",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/harveyzhang814/harveyz-skill.git"
40
+ },
41
+ "license": "MIT"
42
+ }
@@ -0,0 +1,78 @@
1
+ # CHANGELOG — skill-analyzer
2
+
3
+ ## v0.7 (2026-03-28)
4
+
5
+ **基于:** v0.6 + 第5轮评估反馈
6
+
7
+ ### 核心修复:删除所有"双 allowed-tools 块"相关内容(禁忌 21)
8
+
9
+ **问题:** 第4轮和第5轮分析报告仍然描述"双 allowed-tools 块",但经人工源码核查验证:
10
+ - **每个 skill 只有 1 个 `allowed-tools` YAML 块**
11
+ - `---` 是 frontmatter 分隔符,不是"第二个块"
12
+ - `<!-- AUTO-GENERATED -->` 是 HTML 注释,与 allowed-tools 无关
13
+ - `# zsh-compatible` 是 bash 脚本注释,与 allowed-tools 无关
14
+ - 所有 skill 的 `grep "allowed-tools"` 返回值均为 **1**
15
+
16
+ "双块一致性验证"是两个错误数据互验的伪命题。
17
+
18
+ **修复:**
19
+ - 禁忌 21:明确不存在"双块",删除所有相关描述
20
+ - 新增概念澄清:YAML frontmatter 结构说明
21
+ - 提供正确读取命令:`grep "allowed-tools"` 返回值应为 1
22
+
23
+ ---
24
+
25
+ ## v0.6 (2026-03-27)
26
+
27
+ **基于:** v0.5 + 第4轮评估反馈
28
+
29
+ ### 禁止伪造 allowed-tools 数据(禁忌 20)
30
+
31
+ **问题:** v0.5 分析报告大量伪造数据(browse 报8个,实际3个;捏造10个双块等)
32
+
33
+ **修复:**
34
+ - 必须从实际文件读取 allowed-tools
35
+ - 提供已知基准数据交叉验证
36
+ - 禁忌 20
37
+
38
+ ---
39
+
40
+ ## v0.5 (2026-03-27)
41
+
42
+ **基于:** v0.4 + 第3轮评估反馈
43
+
44
+ ### 文件清单必须逐项列出(禁忌 17-19)
45
+
46
+ - lib/ 实际只有 worktree.ts
47
+ - 独立 .tmpl 实际有 29 个
48
+ - 版本根因必须探讨
49
+
50
+ ---
51
+
52
+ ## v0.4 (2026-03-27)
53
+
54
+ **基于:** v0.3 + 第2轮评估反馈
55
+
56
+ ### 项目类型检测机制(禁忌 14-15)
57
+
58
+ ---
59
+
60
+ ## v0.3 (2026-03-27)
61
+
62
+ **基于:** v0.2 + 第1轮评估反馈
63
+
64
+ ### allowed-tools 验证机制(禁忌 11-13)
65
+
66
+ ---
67
+
68
+ ## v0.2 (2026-03-27)
69
+
70
+ **基于:** v0.1-baseline
71
+
72
+ ### 必检清单(VERSION、数量、Ghost、CI)
73
+
74
+ ---
75
+
76
+ ## v0.1-baseline (2026-03-27)
77
+
78
+ 初始版本:洋葱模型四层框架
@@ -0,0 +1,150 @@
1
+ # SKILL.md — skill-analyzer
2
+
3
+ > **版本:** v0.9
4
+ > **版本日期:** 2026-03-28
5
+ > **基于:** v0.8 + 第7轮评估反馈
6
+ > **定位:** 对 Skill 仓库进行系统性分析的工具 Skill
7
+
8
+ ---
9
+
10
+ ## 触发条件
11
+
12
+ 当用户提供以下任意表述时触发本 Skill:
13
+ - "分析这个 skill 仓库"
14
+ - "对这个 skill 仓库做系统性研究"
15
+ - "输出 skill 仓库的分析报告"
16
+ - "理解这个 skill 系统的设计意图"
17
+
18
+ ---
19
+
20
+ ## ⚠️ 第一步:项目类型检测
21
+
22
+ 1. 检查是否存在 `SKILL.md` 或 `SKILL.md.tmpl` → 有则继续
23
+ 2. 检查是否存在 `program.md` 或 ML 关键词 → 非 skill 仓库
24
+ 3. 项目类型分类:Skill 仓库 / ML项目 / CLI工具 / 未知
25
+
26
+ ---
27
+
28
+ ## 分析框架:洋葱模型(四层)
29
+
30
+ ```
31
+ ┌─────────────────────────────────────────┐
32
+ │ Layer 4:使用场景(用户视角) │
33
+ ├─────────────────────────────────────────┤
34
+ │ Layer 3:交互关系(系统视角) │
35
+ ├─────────────────────────────────────────┤
36
+ │ Layer 2:组件目录(结构视角) │
37
+ ├─────────────────────────────────────────┤
38
+ │ Layer 1:设计意图(哲学视角) │
39
+ └─────────────────────────────────────────┘
40
+ ```
41
+
42
+ ---
43
+
44
+ ## ⚠️ 必检清单
45
+
46
+ ### 版本信息
47
+ - [ ] VERSION 文件内容
48
+ - [ ] package.json version
49
+ - [ ] CHANGELOG 最新版本
50
+ - [ ] 版本根因分析
51
+
52
+ ### 文件数量(必须实际计数)
53
+ ```bash
54
+ ls ~/Repositories/gstack/bin/ | wc -l # bin/ 文件数
55
+ ls ~/Repositories/gstack/browse/bin/ | wc -l # browse/bin/ 文件数
56
+ ls ~/Repositories/gstack/browse/test/*.test.ts | wc -l # browse/test/ .test.ts 数
57
+ ls ~/Repositories/gstack/scripts/ | wc -l # scripts/ 文件数
58
+ ls ~/Repositories/gstack/scripts/resolvers/ | wc -l # scripts/resolvers/ 文件数
59
+ ```
60
+
61
+ **正确数量(必须全部记住):**
62
+ - **bin/ = 17**(不是20!)
63
+ - **browse/bin/ = 2**(find-browse, remote-slug)
64
+ - **bin/ + browse/bin/ 合计 = 19**
65
+ - **browse/test/ = 18**(.test.ts 文件,不是11!)
66
+ - **scripts/resolvers/ = 10**(含 index.ts)
67
+
68
+ ### 目录覆盖
69
+ - [ ] 所有目录均列出实际文件清单
70
+
71
+ ### 独立 .tmpl 数量
72
+ - [ ] 29 个(已验证)
73
+
74
+ ---
75
+
76
+ ## ⚠️ allowed-tools(最关键!)
77
+
78
+ ### 含 WebSearch 的 Skill(12个,不是16个!)
79
+
80
+ **正确列表(12个):**
81
+ autoplan, cso, design-consultation, design-review, investigate, office-hours, plan-ceo-review, plan-eng-review, qa, qa-only, review, ship
82
+
83
+ **不含 WebSearch 的 Skill(不要误列):**
84
+ - benchmark ❌(无 WebSearch)
85
+ - canary ❌(无 WebSearch)
86
+ - document-release ❌(无 WebSearch)
87
+ - setup-deploy ❌(无 WebSearch,只有 Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion)
88
+
89
+ ### 正确工具数参考
90
+
91
+ | Skill | 正确工具数 | 注意事项 |
92
+ |-------|-----------|---------|
93
+ | browse | 3 | Bash, Read, AskUserQuestion |
94
+ | qa | 8 | 含 WebSearch,无 Agent |
95
+ | review | 9 | 含 Agent 和 WebSearch |
96
+ | ship | 9 | 含 Agent 和 WebSearch |
97
+ | cso | 8 | 含 Agent 和 WebSearch |
98
+ | office-hours | 8 | 含 WebSearch |
99
+ | setup-browser-cookies | 3 | Bash, Read, AskUserQuestion |
100
+ | **unfreeze** | **2** | Bash, Read |
101
+ | setup-deploy | 7 | 无 WebSearch |
102
+ | benchmark | — | 无 WebSearch |
103
+ | canary | — | 无 WebSearch |
104
+ | document-release | — | 无 WebSearch |
105
+
106
+ ### v0.1.0 skill(5个)
107
+ careful, connect-chrome, freeze, guard, unfreeze
108
+
109
+ ### 含 Agent 的 skill(3个)
110
+ cso, review, ship
111
+
112
+ ---
113
+
114
+ ## Layer 1-4
115
+
116
+ 按照洋葱模型框架执行。
117
+
118
+ ---
119
+
120
+ ## 输出格式
121
+
122
+ ```markdown
123
+ # {仓库名} 系统分析报告
124
+
125
+ ## 元信息
126
+ - 分析版本:
127
+ - 项目类型:
128
+ - VERSION / package.json / CHANGELOG:
129
+ - 版本根因分析:
130
+
131
+ ## 1-6. 各层分析
132
+ ...
133
+
134
+ ## 附录
135
+ ### 幽灵文件列表(如有)
136
+ ### allowed-tools 完整读取记录
137
+ (每个 skill:工具数 + 具体工具名称)
138
+ ```
139
+
140
+ ---
141
+
142
+ ## 禁忌(共 23 条)
143
+
144
+ 1-22 条沿用 v0.8(略)
145
+
146
+ **23. ❌ WebSearch 数量必须为 12 个(不是16!)。benchmark/canary/document-release/setup-deploy 均不含 WebSearch。browse/test/ = 18(不是11)。bin/ + browse/bin/ = 19(不是20)。** ← 新增
147
+
148
+ ---
149
+
150
+ *skill-analyzer v0.9 | 2026-03-28*