@dianzhong/create-harness-app 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.
Files changed (95) hide show
  1. package/dist/index.mjs +412 -0
  2. package/package.json +29 -0
  3. package/templates/axios/.env.example +2 -0
  4. package/templates/axios/src/api/auth.ts +19 -0
  5. package/templates/axios/src/api/request.ts +61 -0
  6. package/templates/axios/src/types/api.ts +26 -0
  7. package/templates/axios/src/utils/auth.ts +5 -0
  8. package/templates/axios/src/utils/storage.ts +17 -0
  9. package/templates/harness/full/.agents/skills/find-skills/SKILL.md +143 -0
  10. package/templates/harness/full/.agents/skills/vue-best-practices/LICENSE.md +21 -0
  11. package/templates/harness/full/.agents/skills/vue-best-practices/SKILL.md +155 -0
  12. package/templates/harness/full/.agents/skills/vue-best-practices/SYNC.md +5 -0
  13. package/templates/harness/full/.agents/skills/vue-best-practices/references/animation-class-based-technique.md +258 -0
  14. package/templates/harness/full/.agents/skills/vue-best-practices/references/animation-state-driven-technique.md +287 -0
  15. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-async.md +99 -0
  16. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-data-flow.md +313 -0
  17. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-fallthrough-attrs.md +179 -0
  18. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-keep-alive.md +139 -0
  19. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-slots.md +226 -0
  20. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-suspense.md +231 -0
  21. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-teleport.md +110 -0
  22. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-transition-group.md +131 -0
  23. package/templates/harness/full/.agents/skills/vue-best-practices/references/component-transition.md +135 -0
  24. package/templates/harness/full/.agents/skills/vue-best-practices/references/composables.md +303 -0
  25. package/templates/harness/full/.agents/skills/vue-best-practices/references/directives.md +168 -0
  26. package/templates/harness/full/.agents/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +177 -0
  27. package/templates/harness/full/.agents/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +185 -0
  28. package/templates/harness/full/.agents/skills/vue-best-practices/references/perf-virtualize-large-lists.md +182 -0
  29. package/templates/harness/full/.agents/skills/vue-best-practices/references/plugins.md +178 -0
  30. package/templates/harness/full/.agents/skills/vue-best-practices/references/reactivity.md +371 -0
  31. package/templates/harness/full/.agents/skills/vue-best-practices/references/render-functions.md +227 -0
  32. package/templates/harness/full/.agents/skills/vue-best-practices/references/sfc.md +355 -0
  33. package/templates/harness/full/.agents/skills/vue-best-practices/references/state-management.md +138 -0
  34. package/templates/harness/full/.agents/skills/vue-best-practices/references/updated-hook-performance.md +193 -0
  35. package/templates/harness/full/.claude/agents/code-reviewer.md +109 -0
  36. package/templates/harness/full/.claude/agents/harness-reviewer.md +51 -0
  37. package/templates/harness/full/.claude/hooks/guard-tool.cjs +234 -0
  38. package/templates/harness/full/.claude/hooks/notify.cjs +168 -0
  39. package/templates/harness/full/.claude/hooks/quality-gate.cjs +135 -0
  40. package/templates/harness/full/.claude/rules/delivery.md +66 -0
  41. package/templates/harness/full/.claude/rules/formatting.md +7 -0
  42. package/templates/harness/full/.claude/rules/git.md +8 -0
  43. package/templates/harness/full/.claude/rules/skills-mcp.md +13 -0
  44. package/templates/harness/full/.claude/rules/vue.md +227 -0
  45. package/templates/harness/full/.claude/settings.json +123 -0
  46. package/templates/harness/full/.claude/skills/find-skills/SKILL.md +143 -0
  47. package/templates/harness/full/.claude/skills/vue-best-practices/LICENSE.md +21 -0
  48. package/templates/harness/full/.claude/skills/vue-best-practices/SKILL.md +155 -0
  49. package/templates/harness/full/.claude/skills/vue-best-practices/SYNC.md +5 -0
  50. package/templates/harness/full/.claude/skills/vue-best-practices/references/animation-class-based-technique.md +258 -0
  51. package/templates/harness/full/.claude/skills/vue-best-practices/references/animation-state-driven-technique.md +287 -0
  52. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-async.md +99 -0
  53. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-data-flow.md +313 -0
  54. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-fallthrough-attrs.md +179 -0
  55. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-keep-alive.md +139 -0
  56. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-slots.md +226 -0
  57. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-suspense.md +231 -0
  58. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-teleport.md +110 -0
  59. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-transition-group.md +131 -0
  60. package/templates/harness/full/.claude/skills/vue-best-practices/references/component-transition.md +135 -0
  61. package/templates/harness/full/.claude/skills/vue-best-practices/references/composables.md +303 -0
  62. package/templates/harness/full/.claude/skills/vue-best-practices/references/directives.md +168 -0
  63. package/templates/harness/full/.claude/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +177 -0
  64. package/templates/harness/full/.claude/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +185 -0
  65. package/templates/harness/full/.claude/skills/vue-best-practices/references/perf-virtualize-large-lists.md +182 -0
  66. package/templates/harness/full/.claude/skills/vue-best-practices/references/plugins.md +178 -0
  67. package/templates/harness/full/.claude/skills/vue-best-practices/references/reactivity.md +371 -0
  68. package/templates/harness/full/.claude/skills/vue-best-practices/references/render-functions.md +227 -0
  69. package/templates/harness/full/.claude/skills/vue-best-practices/references/sfc.md +355 -0
  70. package/templates/harness/full/.claude/skills/vue-best-practices/references/state-management.md +138 -0
  71. package/templates/harness/full/.claude/skills/vue-best-practices/references/updated-hook-performance.md +193 -0
  72. package/templates/harness/full/.editorconfig +8 -0
  73. package/templates/harness/full/.husky/commit-msg +1 -0
  74. package/templates/harness/full/.husky/pre-commit +1 -0
  75. package/templates/harness/full/.lintstagedrc.json +4 -0
  76. package/templates/harness/full/.nvmrc +1 -0
  77. package/templates/harness/full/.oxlintrc.json +11 -0
  78. package/templates/harness/full/.prettierrc.json +6 -0
  79. package/templates/harness/full/AGENTS.md +3 -0
  80. package/templates/harness/full/CLAUDE.md +28 -0
  81. package/templates/harness/full/GEMINI.md +3 -0
  82. package/templates/harness/full/commitlint.config.ts +3 -0
  83. package/templates/harness/full/docs/ai-harness.md +77 -0
  84. package/templates/harness/full/docs/delivery-template.md +66 -0
  85. package/templates/harness/full/docs/git.md +24 -0
  86. package/templates/harness/full/docs/harness-quick-reference.md +89 -0
  87. package/templates/harness/full/docs/review-checklist.md +49 -0
  88. package/templates/harness/full/scripts/harness-hooks.test.mjs +218 -0
  89. package/templates/harness/full/scripts/verify-skills.mjs +248 -0
  90. package/templates/harness/full/scripts/verify-skills.test.mjs +72 -0
  91. package/templates/harness/full/skills-lock.json +50 -0
  92. package/templates/harness/minimal/.claude/hooks/guard-tool.cjs +234 -0
  93. package/templates/harness/minimal/.claude/hooks/quality-gate.cjs +135 -0
  94. package/templates/harness/minimal/.claude/settings.json +27 -0
  95. package/templates/harness/minimal/CLAUDE.md +12 -0
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * PreToolUse 安全守护 hook
4
+ *
5
+ * 职责:在 Claude Code 执行任何工具之前拦截,阻断危险命令和敏感文件访问。
6
+ * 覆盖 Bash/Read/Write/Edit/Grep/Agent 等工具调用。
7
+ * 不改写任何文件,只返回 continue/deny 决策。
8
+ */
9
+
10
+ /* eslint-disable @typescript-eslint/no-require-imports */
11
+
12
+ const fs = require('node:fs')
13
+ const path = require('node:path')
14
+
15
+ // 从 stdin 读取 Claude Code 传入的 JSON hook payload
16
+ function readJsonStdin() {
17
+ const input = fs.readFileSync(0, 'utf8').trim()
18
+ if (!input) {
19
+ return {}
20
+ }
21
+
22
+ try {
23
+ return JSON.parse(input)
24
+ } catch {
25
+ return {}
26
+ }
27
+ }
28
+
29
+ // 构造拦截响应:阻止执行并附带原因
30
+ function deny(reason) {
31
+ process.stdout.write(
32
+ JSON.stringify({
33
+ continue: false,
34
+ stopReason: reason,
35
+ permissionDecision: 'deny',
36
+ permissionDecisionReason: reason,
37
+ }),
38
+ )
39
+ }
40
+
41
+ // 构造放行响应:允许执行,抑制输出
42
+ function allow() {
43
+ process.stdout.write(JSON.stringify({ continue: true, suppressOutput: true }))
44
+ }
45
+
46
+ // 统一路径格式:Windows 反斜线 → 正斜线,去除两端引号
47
+ function normalizePath(value) {
48
+ return String(value ?? '')
49
+ .replaceAll('\\', '/')
50
+ .replace(/^["']|["']$/g, '')
51
+ }
52
+
53
+ // 从嵌套的 toolInput 对象中递归收集所有含路径含义的字符串值
54
+ function collectPaths(value, results = []) {
55
+ if (!value) {
56
+ return results
57
+ }
58
+
59
+ if (typeof value === 'string') {
60
+ results.push(value)
61
+ return results
62
+ }
63
+
64
+ if (Array.isArray(value)) {
65
+ for (const item of value) {
66
+ collectPaths(item, results)
67
+ }
68
+ return results
69
+ }
70
+
71
+ if (typeof value === 'object') {
72
+ for (const [key, item] of Object.entries(value)) {
73
+ if (/path|file|filename/i.test(key) && typeof item === 'string') {
74
+ results.push(item)
75
+ } else {
76
+ collectPaths(item, results)
77
+ }
78
+ }
79
+ }
80
+
81
+ return results
82
+ }
83
+
84
+ // 判断文件路径是否为密钥/凭证等敏感文件(允许 .env.example)
85
+ function isSensitivePath(filePath) {
86
+ const normalized = normalizePath(filePath)
87
+ const base = path.posix.basename(normalized)
88
+
89
+ if (!normalized) {
90
+ return false
91
+ }
92
+
93
+ if (base === '.env.example') {
94
+ return false
95
+ }
96
+
97
+ return (
98
+ /^\.env($|\.)/.test(base) ||
99
+ /(^|\/)\.env($|\.)/.test(normalized) ||
100
+ /(^|\/)secrets?\//i.test(normalized) ||
101
+ /(^|\/)(id_rsa|id_ed25519|known_hosts)$/i.test(normalized) ||
102
+ /\.(pem|key|p12|pfx|crt|cer)$/i.test(base)
103
+ )
104
+ }
105
+
106
+ // 判断 glob pattern 是否匹配敏感文件模式
107
+ function isSensitiveGlob(glob) {
108
+ const normalized = String(glob ?? '').replaceAll('\\', '/')
109
+ return (
110
+ /^\.env($|\*)/.test(normalized) ||
111
+ /(^|\/)\.env($|\*)/.test(normalized) ||
112
+ /(^|\/)secrets?\//i.test(normalized) ||
113
+ /\.(pem|key|p12|pfx|crt|cer)$/i.test(normalized)
114
+ )
115
+ }
116
+
117
+ // 从 shell 命令文本中提取可能的路径片段。不能只按空白切分:
118
+ // cat<.env.production、node -e "readFileSync('.env')" 这类写法都不会产生独立空白 token。
119
+ function collectCommandPathCandidates(command) {
120
+ return String(command ?? '')
121
+ .replaceAll('\\', '/')
122
+ .split(/[\s"'`$;&|()<>,={}[\]]+/)
123
+ .map((token) => token.trim())
124
+ .filter(Boolean)
125
+ }
126
+
127
+ // 检测 Bash 命令是否包含危险操作(破坏性 Git、递归删除、低级磁盘写入等)
128
+ // commandStart 匹配命令起始位置:行首、管道/分号后,或环境变量赋值后
129
+ function dangerousCommandReason(command) {
130
+ const commandStart = String.raw`(?:^|[;&|()])\s*(?:\w+=(?:"[^"]*"|'[^']*'|[^\s;|()]+)\s+)*`
131
+ const checks = [
132
+ [new RegExp(`${commandStart}git\\s+reset\\s+--hard\\b`, 'i'), 'Blocked destructive git reset.'],
133
+ [
134
+ new RegExp(`${commandStart}git\\s+reset\\s+--mixed\\s+HEAD\\b`, 'i'),
135
+ 'Blocked destructive git reset.',
136
+ ],
137
+ [
138
+ new RegExp(`${commandStart}git\\s+push\\s+--force(?:-with-lease)?\\b`, 'i'),
139
+ 'Blocked force push.',
140
+ ],
141
+ [
142
+ new RegExp(`${commandStart}git\\s+push\\s+\\S+\\s+--delete\\b`, 'i'),
143
+ 'Blocked remote branch deletion.',
144
+ ],
145
+ [
146
+ new RegExp(`${commandStart}git\\s+push\\s+\\S+\\s+\\+\\S+\\b`, 'i'),
147
+ 'Blocked force push via refspec.',
148
+ ],
149
+ [new RegExp(`${commandStart}git\\s+branch\\s+-D\\b`, 'i'), 'Blocked local branch deletion.'],
150
+ [new RegExp(`${commandStart}git\\s+stash\\s+(drop|clear)\\b`, 'i'), 'Blocked stash deletion.'],
151
+ [
152
+ new RegExp(`${commandStart}git\\s+checkout\\s+(?:--\\s+|\\.)`, 'i'),
153
+ 'Blocked destructive git checkout.',
154
+ ],
155
+ [new RegExp(`${commandStart}git\\s+restore\\b`, 'i'), 'Blocked destructive git restore.'],
156
+ [
157
+ new RegExp(
158
+ `${commandStart}git\\s+clean\\s+(?=[^;&|\\n]*-[A-Za-z]*f)(?=[^;&|\\n]*-[A-Za-z]*d)`,
159
+ 'i',
160
+ ),
161
+ 'Blocked destructive git clean.',
162
+ ],
163
+ [
164
+ new RegExp(`${commandStart}rm\\s+(?=[^;&|\\n]*-[A-Za-z]*r)(?=[^;&|\\n]*-[A-Za-z]*f)`, 'i'),
165
+ 'Blocked recursive force delete.',
166
+ ],
167
+ [new RegExp(`${commandStart}del\\s+\\/[fsq]\\b`, 'i'), 'Blocked destructive Windows delete.'],
168
+ [new RegExp(`${commandStart}rmdir\\s+\\/s\\b`, 'i'), 'Blocked recursive directory delete.'],
169
+ [
170
+ new RegExp(`${commandStart}Remove-Item\\b.*\\s-Recurse\\b.*\\s-Force\\b`, 'i'),
171
+ 'Blocked recursive force delete.',
172
+ ],
173
+ [new RegExp(`${commandStart}dd\\s+\\b`, 'i'), 'Blocked low-level disk write command.'],
174
+ ]
175
+
176
+ for (const [pattern, reason] of checks) {
177
+ if (pattern.test(command)) {
178
+ return reason
179
+ }
180
+ }
181
+
182
+ return ''
183
+ }
184
+
185
+ // === 主逻辑 ===
186
+
187
+ // 1. Bash 命令检查:先检测危险命令,再扫描命令中的敏感路径
188
+ const payload = readJsonStdin()
189
+ const toolName = payload.tool_name || payload.toolName || payload.tool || ''
190
+ const toolInput = payload.tool_input || payload.toolInput || {}
191
+ const command = String(toolInput.command || '')
192
+
193
+ if (/bash/i.test(toolName) && command) {
194
+ const reason = dangerousCommandReason(command)
195
+
196
+ if (reason) {
197
+ deny(`${reason} Command: ${command.slice(0, 160)}`)
198
+ process.exit(0)
199
+ }
200
+
201
+ for (const token of collectCommandPathCandidates(command)) {
202
+ if (isSensitivePath(token)) {
203
+ deny(`Blocked command touching sensitive path: ${token}`)
204
+ process.exit(0)
205
+ }
206
+ }
207
+ }
208
+
209
+ // 2. 工具输入路径检查:递归收集所有路径参数,检测敏感文件
210
+ const paths = collectPaths(toolInput).map(normalizePath)
211
+ const sensitive = paths.find(isSensitivePath)
212
+
213
+ if (sensitive) {
214
+ deny(`Blocked access to sensitive path: ${sensitive}`)
215
+ process.exit(0)
216
+ }
217
+
218
+ // 3. Grep 工具专项检查:glob pattern 和搜索路径中的敏感文件
219
+ if (/grep/i.test(toolName)) {
220
+ const glob = String(toolInput.glob || '')
221
+ const grepPath = String(toolInput.path || '')
222
+
223
+ if (glob && isSensitiveGlob(glob)) {
224
+ deny(`Blocked Grep with sensitive glob pattern: ${glob}`)
225
+ process.exit(0)
226
+ }
227
+
228
+ if (grepPath && isSensitivePath(grepPath)) {
229
+ deny(`Blocked Grep in sensitive path: ${grepPath}`)
230
+ process.exit(0)
231
+ }
232
+ }
233
+
234
+ allow()
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Stop hook
4
+ *
5
+ * 职责:
6
+ * - git 有变更时先自动格式化,再运行 type-check / lint / harness:check。
7
+ * 失败时阻断 agent 停止,成功时放行并通知。
8
+ * 注意:不自动暂存(不 git add),由人工决定暂存与提交。
9
+ */
10
+
11
+ /* eslint-disable @typescript-eslint/no-require-imports */
12
+
13
+ const { spawnSync } = require('node:child_process')
14
+
15
+ const dryRun = process.argv.includes('--dry-run') || process.env.HARNESS_QUALITY_DRY_RUN === '1'
16
+
17
+ function writeJson(value) {
18
+ process.stdout.write(JSON.stringify(value))
19
+ }
20
+
21
+ // 跨平台 shell 参数转义:安全字符直接通过,POSIX 用单引号,Windows 用双引号
22
+ function shellQuote(value) {
23
+ const text = String(value)
24
+
25
+ if (!/[^\w@%+=:,./-]/.test(text)) {
26
+ return text
27
+ }
28
+
29
+ if (process.platform === 'win32') {
30
+ return `"${text.replaceAll('"', '\\"')}"`
31
+ }
32
+
33
+ return `'${text.replaceAll("'", "'\\''")}'`
34
+ }
35
+
36
+ // 跨平台执行 shell 命令:Windows 用 cmd.exe,POSIX 用 sh -lc
37
+ function runShell(commandLine, timeout = 180000) {
38
+ if (process.platform === 'win32') {
39
+ return spawnSync('cmd.exe', ['/d', '/s', '/c', commandLine], {
40
+ cwd: process.cwd(),
41
+ encoding: 'utf8',
42
+ shell: false,
43
+ timeout,
44
+ })
45
+ }
46
+
47
+ return spawnSync('sh', ['-lc', commandLine], {
48
+ cwd: process.cwd(),
49
+ encoding: 'utf8',
50
+ shell: false,
51
+ timeout,
52
+ })
53
+ }
54
+
55
+ // 封装命令执行,支持 --dry-run 模式跳过实际执行
56
+ function run(command, args) {
57
+ if (dryRun) {
58
+ return {
59
+ command: [command, ...args].join(' '),
60
+ status: 0,
61
+ stdout: '[dry-run] skipped command execution',
62
+ stderr: '',
63
+ error: '',
64
+ }
65
+ }
66
+
67
+ const commandLine = [command, ...args].map(shellQuote).join(' ')
68
+ const result = runShell(commandLine)
69
+
70
+ return {
71
+ command: [command, ...args].join(' '),
72
+ status: result.status ?? 1,
73
+ stdout: result.stdout || '',
74
+ stderr: result.stderr || '',
75
+ error: result.error ? result.error.message : '',
76
+ }
77
+ }
78
+
79
+ // 获取 git 变更文件列表(porcelain 格式)
80
+ function gitStatus() {
81
+ const result = runShell('git status --porcelain --untracked-files=all', 15000)
82
+
83
+ if (result.status !== 0) {
84
+ return null
85
+ }
86
+
87
+ return result.stdout
88
+ .split(/\r?\n/)
89
+ .map((line) => line.trim())
90
+ .filter(Boolean)
91
+ }
92
+
93
+ // Stop 模式:无变更时跳过门禁,否则运行完整的质量检查流水线
94
+ const changed = gitStatus()
95
+
96
+ if (changed && changed.length === 0) {
97
+ writeJson({
98
+ continue: true,
99
+ systemMessage: 'Harness 质量门禁跳过:git 未检测到变更文件。',
100
+ })
101
+ process.exit(0)
102
+ }
103
+
104
+ // Stop 收尾阶段允许自动格式化(本项目唯一允许自动格式化的 hook)
105
+ const formatResult = run('pnpm', ['format'])
106
+ const commands = [
107
+ ['pnpm', ['type-check']],
108
+ ['pnpm', ['lint']],
109
+ ['pnpm', ['harness:check']],
110
+ ]
111
+
112
+ const results = [formatResult, ...commands.map(([command, args]) => run(command, args))]
113
+ const failed = results.filter((result) => result.status !== 0)
114
+
115
+ if (failed.length > 0) {
116
+ const details = failed
117
+ .map((result) => {
118
+ const output = `${result.stdout}\n${result.stderr}\n${result.error}`.trim()
119
+ return `命令失败:${result.command}\n${output.slice(-2400)}`
120
+ })
121
+ .join('\n\n')
122
+
123
+ writeJson({
124
+ continue: false,
125
+ stopReason: `Harness 质量门禁未通过。请修复以下问题后再继续。\n\n${details}`,
126
+ })
127
+ process.exit(0)
128
+ }
129
+
130
+ writeJson({
131
+ continue: true,
132
+ systemMessage: `Harness 质量门禁通过。变更文件数:${
133
+ changed ? changed.length : 0
134
+ }。已通过的检查:pnpm format(自动修复)、pnpm type-check、pnpm lint、pnpm harness:check。`,
135
+ })
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
+ "permissions": {
4
+ "allow": [
5
+ "Read", "Glob", "Grep",
6
+ "Bash(git status*)", "Bash(git diff*)", "Bash(git log*)", "Bash(git show*)",
7
+ "Bash(pnpm *)", "Bash(node *)"
8
+ ],
9
+ "deny": [
10
+ "Read(.env*)", "Read(**/.env*)",
11
+ "Read(*.pem)", "Read(**/*.pem)", "Read(*.key)", "Read(**/*.key)",
12
+ "Bash(git reset --hard*)", "Bash(git push --force*)",
13
+ "Bash(rm -rf*)", "Bash(git commit*)"
14
+ ]
15
+ },
16
+ "hooks": {
17
+ "PreToolUse": [{
18
+ "matcher": "Bash|Read|Write|Edit|MultiEdit|Grep|Agent",
19
+ "hooks": [{ "type": "command", "command": "node .claude/hooks/guard-tool.cjs", "timeout": 10 }]
20
+ }],
21
+ "Stop": [{
22
+ "matcher": ".*",
23
+ "hooks": [{ "type": "command", "command": "node .claude/hooks/quality-gate.cjs stop", "timeout": 300 }]
24
+ }]
25
+ },
26
+ "disableBypassPermissionsMode": "disable"
27
+ }
@@ -0,0 +1,12 @@
1
+ # Claude Code 项目指南
2
+
3
+ 本项目使用最小 harness 配置:安全守护(guard-tool)+ 质量门禁(quality-gate)。
4
+
5
+ ## 项目事实
6
+ - 技术栈:Vue 3、TypeScript、Vite
7
+ - 包管理器:pnpm
8
+
9
+ ## 质量门禁
10
+ - 代码变更运行 `pnpm check`(type-check + lint + format:check)。
11
+ - 不读取、不写入密钥文件。
12
+ - 不自动提交。