mustard-claude 3.0.2 → 3.0.3
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/package.json +1 -1
- package/templates/.claude/commands/guards.md +76 -0
- package/templates/.claude/commands/notes.md +22 -0
- package/templates/.claude/commands/patterns.md +173 -0
- package/templates/.claude/commands/recipes.md +91 -0
- package/templates/.claude/commands/stack.md +86 -0
- package/templates/.claude/skills/templates-command-authoring/SKILL.md +90 -0
- package/templates/.claude/skills/templates-command-authoring/references/examples.md +83 -0
- package/templates/.claude/skills/templates-hook-protocol/SKILL.md +73 -0
- package/templates/.claude/skills/templates-hook-protocol/references/examples.md +74 -0
- package/templates/.claude/skills/templates-settings-wiring/SKILL.md +75 -0
- package/templates/.claude/skills/templates-settings-wiring/references/examples.md +59 -0
- package/templates/.claude/skills/templates-skill-authoring/SKILL.md +97 -0
- package/templates/.claude/skills/templates-skill-authoring/references/examples.md +69 -0
- package/templates/.claude/skills/templates-sync-detect/SKILL.md +62 -0
- package/templates/.claude/skills/templates-sync-detect/references/examples.md +55 -0
- package/templates/CLAUDE.md +47 -0
- package/templates/settings.json +10 -10
package/package.json
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Guards: Templates
|
|
3
|
+
|
|
4
|
+
> DO/DON'T rules for the Mustard templates subproject.
|
|
5
|
+
|
|
6
|
+
## Hook Development
|
|
7
|
+
|
|
8
|
+
| Rule | Type |
|
|
9
|
+
|------|------|
|
|
10
|
+
| DO read all stdin before processing (`on('end', ...)`) | DO |
|
|
11
|
+
| DO fail-open: `catch → stderr + exit(0)` | DO |
|
|
12
|
+
| DO normalize Windows paths (`\` to `/`) before pattern matching | DO |
|
|
13
|
+
| DO use `process.exit(0)` for approve (silent exit) | DO |
|
|
14
|
+
| DO write JSON to stdout for block/deny/context responses | DO |
|
|
15
|
+
| DON'T use any npm dependencies — only Node.js built-ins | DON'T |
|
|
16
|
+
| DON'T throw unhandled exceptions — always wrap in try/catch | DON'T |
|
|
17
|
+
| DON'T block on parse errors — treat as approve | DON'T |
|
|
18
|
+
| DON'T use `console.log` for debugging — use `process.stderr.write` | DON'T |
|
|
19
|
+
|
|
20
|
+
## Hook Response Protocol
|
|
21
|
+
|
|
22
|
+
| Rule | Type |
|
|
23
|
+
|------|------|
|
|
24
|
+
| DO use `permissionDecision: 'block'` or `'deny'` for PreToolUse hooks | DO |
|
|
25
|
+
| DO use `decision: 'approve'` or `'block'` for PostToolUse hooks | DO |
|
|
26
|
+
| DO include `hookEventName` matching the hook's lifecycle event | DO |
|
|
27
|
+
| DON'T mix PreToolUse and PostToolUse response formats | DON'T |
|
|
28
|
+
|
|
29
|
+
## Settings & Wiring
|
|
30
|
+
|
|
31
|
+
| Rule | Type |
|
|
32
|
+
|------|------|
|
|
33
|
+
| DO register every new hook in `settings.json` under the correct lifecycle event | DO |
|
|
34
|
+
| DO set a `timeout` for every hook registration (3-15 seconds) | DO |
|
|
35
|
+
| DO use `$CLAUDE_PROJECT_DIR` in hook command paths | DO |
|
|
36
|
+
| DON'T add hooks without a `matcher` — every hook must declare what it matches | DON'T |
|
|
37
|
+
|
|
38
|
+
## Commands (SKILL.md)
|
|
39
|
+
|
|
40
|
+
| Rule | Type |
|
|
41
|
+
|------|------|
|
|
42
|
+
| DO end every command SKILL.md with `ULTRATHINK` | DO |
|
|
43
|
+
| DO include `## Trigger` with exact invocation syntax | DO |
|
|
44
|
+
| DO include `## Rules` section with explicit constraints | DO |
|
|
45
|
+
| DON'T create commands that implement code directly — delegate via Task | DON'T |
|
|
46
|
+
|
|
47
|
+
## Scripts
|
|
48
|
+
|
|
49
|
+
| Rule | Type |
|
|
50
|
+
|------|------|
|
|
51
|
+
| DO use `execSync` with `stdio: ['pipe','pipe','pipe']` and `windowsHide: true` | DO |
|
|
52
|
+
| DO set timeouts on all `execSync` calls | DO |
|
|
53
|
+
| DO handle missing files/dirs gracefully (try/catch around fs ops) | DO |
|
|
54
|
+
| DON'T import external packages — all scripts must be self-contained | DON'T |
|
|
55
|
+
|
|
56
|
+
## Skills (SKILL.md)
|
|
57
|
+
|
|
58
|
+
| Rule | Type |
|
|
59
|
+
|------|------|
|
|
60
|
+
| DO include YAML frontmatter with `name` and `description` | DO |
|
|
61
|
+
| DO write "pushy" descriptions with casual trigger phrases | DO |
|
|
62
|
+
| DO add `<!-- mustard:generated -->` after the closing `---` | DO |
|
|
63
|
+
| DO keep SKILL.md under 500 lines (ideally under 200) | DO |
|
|
64
|
+
| DON'T put `<!-- mustard:generated -->` before the opening `---` | DON'T |
|
|
65
|
+
| DON'T use generic descriptions — be specific about what and when | DON'T |
|
|
66
|
+
|
|
67
|
+
## Generated Files
|
|
68
|
+
|
|
69
|
+
| Rule | Type |
|
|
70
|
+
|------|------|
|
|
71
|
+
| DO start every generated file with `<!-- mustard:generated at:{ISO} role:{role} -->` | DO |
|
|
72
|
+
| DO include H1 title + blockquote description | DO |
|
|
73
|
+
| DO keep under 200 lines per file | DO |
|
|
74
|
+
| DO reference real files with `Ref: path/file.ext` | DO |
|
|
75
|
+
| DON'T include generic information — only data traced from real code | DON'T |
|
|
76
|
+
| DON'T overwrite files without `<!-- mustard:generated` header (manual files) | DON'T |
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Notes: Templates (General)
|
|
2
|
+
|
|
3
|
+
> Manual notes for the Mustard templates subproject. Never overwritten by /scan.
|
|
4
|
+
|
|
5
|
+
## Mandatory Patterns
|
|
6
|
+
|
|
7
|
+
- All hooks read JSON from stdin and write JSON to stdout
|
|
8
|
+
- All hooks fail-open (exit 0 on error) except when explicitly blocking
|
|
9
|
+
- All generated files start with `<!-- mustard:generated -->` header
|
|
10
|
+
- Skills use YAML frontmatter with `name` and `description` fields
|
|
11
|
+
|
|
12
|
+
## Known Pitfalls
|
|
13
|
+
|
|
14
|
+
- Hook stdin must be fully consumed before processing (`on('end', ...)`)
|
|
15
|
+
- Windows path separators must be normalized (`\` to `/`) in file-guard and guard-verify
|
|
16
|
+
- CLAUDE_PROJECT_DIR env var may not be set in all contexts — always fallback to cwd
|
|
17
|
+
|
|
18
|
+
## Observations
|
|
19
|
+
|
|
20
|
+
- Templates are copied verbatim to target projects by `mustard init`/`mustard update`
|
|
21
|
+
- The `settings.json` defines the full hook wiring — any new hook must be registered there
|
|
22
|
+
- Skills in `skills/` are foundation skills (stack-agnostic); subproject-specific skills go in `{sub}/.claude/skills/`
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Patterns: Templates
|
|
3
|
+
|
|
4
|
+
> Recurring code patterns across hooks, scripts, and commands.
|
|
5
|
+
|
|
6
|
+
## P1. Hook Stdin/Stdout Protocol
|
|
7
|
+
|
|
8
|
+
All hooks read JSON from stdin, process, and either exit silently (approve) or write JSON to stdout (block/deny/context).
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
let input = '';
|
|
12
|
+
process.stdin.setEncoding('utf8');
|
|
13
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
14
|
+
process.stdin.on('end', () => {
|
|
15
|
+
const data = JSON.parse(input);
|
|
16
|
+
// ... process
|
|
17
|
+
process.exit(0); // approve (silent)
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Ref: `hooks/bash-safety.js`, `hooks/file-guard.js`, `hooks/enforce-registry.js`
|
|
22
|
+
|
|
23
|
+
## P2. PreToolUse Block Response
|
|
24
|
+
|
|
25
|
+
Hooks that block return a specific JSON structure with `permissionDecision`:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
console.log(JSON.stringify({
|
|
29
|
+
hookSpecificOutput: {
|
|
30
|
+
hookEventName: 'PreToolUse',
|
|
31
|
+
permissionDecision: 'block', // or 'deny'
|
|
32
|
+
permissionDecisionReason: 'Reason message'
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Ref: `hooks/enforce-registry.js` (line 100-109), `hooks/bash-safety.js` (line 44-49)
|
|
38
|
+
|
|
39
|
+
## P3. PostToolUse Approve/Block Response
|
|
40
|
+
|
|
41
|
+
PostToolUse hooks use `decision` field (not `permissionDecision`):
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
process.stdout.write(JSON.stringify({ decision: 'approve' }));
|
|
45
|
+
// or
|
|
46
|
+
process.stdout.write(JSON.stringify({ decision: 'block', reason: '...' }));
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Ref: `hooks/guard-verify.js` (line 60-95)
|
|
50
|
+
|
|
51
|
+
## P4. Fail-Open Error Handling
|
|
52
|
+
|
|
53
|
+
Every hook wraps the main logic in try/catch and exits 0 on error — never blocking due to hook bugs:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
} catch (err) {
|
|
57
|
+
process.stderr.write(`[hook-name] Error: ${err.message}\n`);
|
|
58
|
+
process.exit(0); // fail-open
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Ref: `hooks/bash-safety.js` (line 56-59), `hooks/file-guard.js` (line 57-60)
|
|
63
|
+
|
|
64
|
+
## P5. Regex-Based Dangerous Command Detection
|
|
65
|
+
|
|
66
|
+
`bash-safety.js` uses an array of `{ re, msg }` objects tested sequentially against the command string:
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
const DANGEROUS = [
|
|
70
|
+
{ re: /\brm\s+(-\w*r\w*f|...)\b/i, msg: 'Recursive force delete blocked' },
|
|
71
|
+
// ...
|
|
72
|
+
];
|
|
73
|
+
for (const { re, msg } of DANGEROUS) {
|
|
74
|
+
if (re.test(cmd)) { /* deny */ }
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Ref: `hooks/bash-safety.js` (line 14-28)
|
|
79
|
+
|
|
80
|
+
## P6. File Pattern Blocking
|
|
81
|
+
|
|
82
|
+
`file-guard.js` blocks access to sensitive files using regex patterns tested against both full path and basename:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
const BLOCKED_PATTERNS = [/credentials/i, /\.pem$/i, /\.key$/i, ...];
|
|
86
|
+
for (const pattern of BLOCKED_PATTERNS) {
|
|
87
|
+
if (pattern.test(normalized) || pattern.test(basename)) { /* deny */ }
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Ref: `hooks/file-guard.js` (line 16-25)
|
|
92
|
+
|
|
93
|
+
## P7. Role Detection via Scoring
|
|
94
|
+
|
|
95
|
+
`sync-detect.js` assigns numeric weights (HIGH=10, MEDIUM=5, LOW=3) to file/dep signals, accumulating scores per role. Highest score wins:
|
|
96
|
+
|
|
97
|
+
| Weight | Signal Type | Example |
|
|
98
|
+
|--------|------------|---------|
|
|
99
|
+
| HIGH (10) | Config files | `.csproj` with Sdk.Web, `next.config.*` |
|
|
100
|
+
| MEDIUM (5) | Package deps | `react` in package.json, `express` |
|
|
101
|
+
| LOW (3) | Directories | `Controllers/`, `app/` + `components/` |
|
|
102
|
+
|
|
103
|
+
Ref: `scripts/sync-detect.js` (line 210-327)
|
|
104
|
+
|
|
105
|
+
## P8. SHA-256 Source Hashing for Incremental Scan
|
|
106
|
+
|
|
107
|
+
`sync-detect.js` computes deterministic hashes by sorting files and updating hash with both path and content:
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const hash = crypto.createHash('sha256');
|
|
111
|
+
for (const file of files.sort()) {
|
|
112
|
+
hash.update(file); // path (rename-sensitive)
|
|
113
|
+
hash.update(content); // content
|
|
114
|
+
}
|
|
115
|
+
return hash.digest('hex');
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Ref: `scripts/sync-detect.js` (line 643-659)
|
|
119
|
+
|
|
120
|
+
## P9. FIFO Queue with Type-Match Preference (Subagent Tracker)
|
|
121
|
+
|
|
122
|
+
Subagent tracker uses a queue to correlate Task tool calls with SubagentStart events. PreToolUse captures description; SubagentStart consumes by type-match first, FIFO fallback:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
const typeIdx = queue.findIndex(q => q.type === agentType);
|
|
126
|
+
if (typeIdx >= 0) { /* consume type-matched entry */ }
|
|
127
|
+
else { /* FIFO: consume first */ }
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Ref: `hooks/subagent-tracker.js` (line 80-95)
|
|
131
|
+
|
|
132
|
+
## P10. ANSI Statusline with Git Cache
|
|
133
|
+
|
|
134
|
+
`statusline.js` caches git status in a temp file with 5s TTL to avoid repeated `git` calls:
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
const GIT_CACHE_FILE = path.join(os.tmpdir(), 'claude-statusline-git.json');
|
|
138
|
+
const GIT_CACHE_TTL = 5000;
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Ref: `scripts/statusline.js` (line 17-18, 296-326)
|
|
142
|
+
|
|
143
|
+
## P11. Command SKILL.md Structure
|
|
144
|
+
|
|
145
|
+
All slash commands follow the same structure: H1 title, trigger section, description, procedure/action, rules, and `ULTRATHINK` footer:
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
# /command-name - Title
|
|
149
|
+
## Trigger
|
|
150
|
+
`/command-name <args>`
|
|
151
|
+
## Description / ## Procedure / ## Action
|
|
152
|
+
...
|
|
153
|
+
## Rules
|
|
154
|
+
...
|
|
155
|
+
ULTRATHINK
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Ref: `commands/mustard/feature/SKILL.md`, `commands/mustard/bugfix/SKILL.md`
|
|
159
|
+
|
|
160
|
+
## P12. Foundation Skill YAML Frontmatter
|
|
161
|
+
|
|
162
|
+
Foundation skills use YAML frontmatter with `name`, `description`, and optional `disable-model-invocation`:
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
---
|
|
166
|
+
name: skill-name
|
|
167
|
+
description: "What it does. When to use it."
|
|
168
|
+
disable-model-invocation: true
|
|
169
|
+
---
|
|
170
|
+
<!-- mustard:generated -->
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Ref: `skills/commit-workflow/SKILL.md`, `skills/pipeline-execution/SKILL.md`
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Recipes: Templates
|
|
3
|
+
|
|
4
|
+
> Implementation recipes for common tasks in the templates subproject.
|
|
5
|
+
|
|
6
|
+
## Recipe: New Hook
|
|
7
|
+
|
|
8
|
+
### Steps
|
|
9
|
+
1. Create `hooks/{hook-name}.js` following stdin/stdout protocol → `patterns.md` P1
|
|
10
|
+
2. Implement logic with fail-open error handling → `patterns.md` P4
|
|
11
|
+
3. Choose response format: PreToolUse (`permissionDecision`) or PostToolUse (`decision`) → `patterns.md` P2, P3
|
|
12
|
+
4. Register in `settings.json` under correct lifecycle event with matcher and timeout
|
|
13
|
+
5. Add test cases in `hooks/__tests__/hooks.test.js`
|
|
14
|
+
6. Run tests: `node --test hooks/__tests__/hooks.test.js`
|
|
15
|
+
|
|
16
|
+
### Reference module: bash-safety.js (PreToolUse) | guard-verify.js (PostToolUse)
|
|
17
|
+
### Reference files: `hooks/bash-safety.js`, `hooks/guard-verify.js`, `settings.json`, `hooks/__tests__/hooks.test.js`
|
|
18
|
+
|
|
19
|
+
### Task splits
|
|
20
|
+
- **HookImpl** (steps 1-3): Patterns: `patterns.md` P1-P4 | Depends on: none
|
|
21
|
+
- **HookWiring** (steps 4-6): Patterns: `guards.md` Settings | Depends on: HookImpl
|
|
22
|
+
|
|
23
|
+
### File hierarchy
|
|
24
|
+
| Level | Component | Depends on |
|
|
25
|
+
|-------|-----------|-----------|
|
|
26
|
+
| 1 | `hooks/{name}.js` | -- |
|
|
27
|
+
| 2 | `settings.json` (registration) | hooks/{name}.js |
|
|
28
|
+
| 3 | `hooks/__tests__/hooks.test.js` | hooks/{name}.js |
|
|
29
|
+
| 4 | test run | all |
|
|
30
|
+
|
|
31
|
+
## Recipe: New Slash Command
|
|
32
|
+
|
|
33
|
+
### Steps
|
|
34
|
+
1. Create `commands/mustard/{command-name}/SKILL.md` with trigger, description, procedure, rules → `patterns.md` P11
|
|
35
|
+
2. Include `ULTRATHINK` at the end
|
|
36
|
+
3. Verify command follows delegation pattern (no direct code implementation)
|
|
37
|
+
|
|
38
|
+
### Reference module: feature/SKILL.md (complex) | status/SKILL.md (simple)
|
|
39
|
+
### Reference files: `commands/mustard/feature/SKILL.md`, `commands/mustard/status/SKILL.md`
|
|
40
|
+
|
|
41
|
+
### Task splits
|
|
42
|
+
- **CommandDef** (steps 1-3): Patterns: `patterns.md` P11 | Depends on: none
|
|
43
|
+
|
|
44
|
+
### File hierarchy
|
|
45
|
+
| Level | Component | Depends on |
|
|
46
|
+
|-------|-----------|-----------|
|
|
47
|
+
| 1 | `commands/mustard/{name}/SKILL.md` | -- |
|
|
48
|
+
|
|
49
|
+
## Recipe: New Foundation Skill
|
|
50
|
+
|
|
51
|
+
### Steps
|
|
52
|
+
1. Create `skills/{skill-name}/SKILL.md` with YAML frontmatter → `patterns.md` P12
|
|
53
|
+
2. Write pushy description with casual trigger phrases → `guards.md` Skills
|
|
54
|
+
3. Add `<!-- mustard:generated -->` after closing `---`
|
|
55
|
+
4. Create `skills/{skill-name}/references/examples.md` with real code examples
|
|
56
|
+
5. Keep SKILL.md under 500 lines
|
|
57
|
+
|
|
58
|
+
### Reference module: commit-workflow (simple) | design-craft (with references)
|
|
59
|
+
### Reference files: `skills/commit-workflow/SKILL.md`, `skills/design-craft/SKILL.md`
|
|
60
|
+
|
|
61
|
+
### Task splits
|
|
62
|
+
- **SkillDef** (steps 1-5): Patterns: `patterns.md` P12, `guards.md` Skills | Depends on: none
|
|
63
|
+
|
|
64
|
+
### File hierarchy
|
|
65
|
+
| Level | Component | Depends on |
|
|
66
|
+
|-------|-----------|-----------|
|
|
67
|
+
| 1 | `skills/{name}/SKILL.md` | -- |
|
|
68
|
+
| 2 | `skills/{name}/references/examples.md` | SKILL.md |
|
|
69
|
+
|
|
70
|
+
## Recipe: New Sync Script
|
|
71
|
+
|
|
72
|
+
### Steps
|
|
73
|
+
1. Create `scripts/{script-name}.js` with shebang and JSDoc header
|
|
74
|
+
2. Use only Node.js built-ins (fs, path, child_process, crypto)
|
|
75
|
+
3. Read ROOT from `path.resolve(__dirname, '..', '..')` → `patterns.md` P8
|
|
76
|
+
4. Handle missing files/dirs gracefully with try/catch
|
|
77
|
+
5. Output JSON to stdout for consumption by other tools
|
|
78
|
+
6. Test manually: `node scripts/{script-name}.js`
|
|
79
|
+
|
|
80
|
+
### Reference module: sync-detect.js (complex) | sync-registry.js (medium)
|
|
81
|
+
### Reference files: `scripts/sync-detect.js`, `scripts/sync-registry.js`
|
|
82
|
+
|
|
83
|
+
### Task splits
|
|
84
|
+
- **ScriptImpl** (steps 1-5): Patterns: `patterns.md` P7, P8 | Depends on: none
|
|
85
|
+
- **ScriptTest** (step 6): Depends on: ScriptImpl
|
|
86
|
+
|
|
87
|
+
### File hierarchy
|
|
88
|
+
| Level | Component | Depends on |
|
|
89
|
+
|-------|-----------|-----------|
|
|
90
|
+
| 1 | `scripts/{name}.js` | -- |
|
|
91
|
+
| 2 | manual test | scripts/{name}.js |
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Stack: Templates
|
|
3
|
+
|
|
4
|
+
> Technology stack and tooling for the Mustard templates subproject.
|
|
5
|
+
|
|
6
|
+
## Runtime
|
|
7
|
+
|
|
8
|
+
| Component | Version | Notes |
|
|
9
|
+
|-----------|---------|-------|
|
|
10
|
+
| Node.js | >=18 | All hooks/scripts use CommonJS (`require`) |
|
|
11
|
+
| JavaScript | ES2020+ | Optional chaining, nullish coalescing, `Set`, `Map` |
|
|
12
|
+
|
|
13
|
+
## Dependencies
|
|
14
|
+
|
|
15
|
+
None. All template files are dependency-free — they use only Node.js built-in modules:
|
|
16
|
+
|
|
17
|
+
| Module | Used In |
|
|
18
|
+
|--------|---------|
|
|
19
|
+
| `fs` | All hooks, all scripts |
|
|
20
|
+
| `path` | All hooks, all scripts |
|
|
21
|
+
| `child_process` | `auto-format.js`, `pre-compact.js`, `statusline.js`, `sync-detect.js`, `sync-registry.js` |
|
|
22
|
+
| `crypto` | `sync-detect.js` (SHA-256 hashing) |
|
|
23
|
+
| `os` | `statusline.js`, `session-cleanup.js` |
|
|
24
|
+
|
|
25
|
+
## File Categories
|
|
26
|
+
|
|
27
|
+
| Category | Path | Count | Purpose |
|
|
28
|
+
|----------|------|-------|---------|
|
|
29
|
+
| Hooks | `hooks/*.js` | 8 | PreToolUse/PostToolUse/Session lifecycle guards |
|
|
30
|
+
| Scripts | `scripts/*.js` | 3 | Sync-detect, sync-registry, statusline |
|
|
31
|
+
| Commands | `commands/mustard/*/SKILL.md` | 14 | Slash command definitions |
|
|
32
|
+
| Skills | `skills/*/SKILL.md` | 6 | Foundation skills (design-craft, react-best-practices, etc.) |
|
|
33
|
+
| Config | `settings.json` | 1 | Hook wiring, permissions, statusline |
|
|
34
|
+
| Config | `pipeline-config.md` | 1 | Agent dispatch rules, wave system, model selection |
|
|
35
|
+
| Template | `CLAUDE.md` | 1 | Orchestrator rules template |
|
|
36
|
+
|
|
37
|
+
## Commands
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Run hook tests
|
|
41
|
+
node --test hooks/__tests__/hooks.test.js
|
|
42
|
+
|
|
43
|
+
# Run sync-detect (outputs JSON)
|
|
44
|
+
node scripts/sync-detect.js
|
|
45
|
+
node scripts/sync-detect.js --no-cache
|
|
46
|
+
|
|
47
|
+
# Run sync-registry
|
|
48
|
+
node scripts/sync-registry.js
|
|
49
|
+
node scripts/sync-registry.js --force
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Structure
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
templates/
|
|
56
|
+
├── CLAUDE.md # Orchestrator rules (copied to .claude/CLAUDE.md)
|
|
57
|
+
├── settings.json # Hook wiring + permissions
|
|
58
|
+
├── pipeline-config.md # Agent/wave/model config
|
|
59
|
+
├── commands/mustard/ # 14 slash commands
|
|
60
|
+
│ ├── feature/SKILL.md
|
|
61
|
+
│ ├── bugfix/SKILL.md
|
|
62
|
+
│ ├── scan/SKILL.md
|
|
63
|
+
│ ├── git/SKILL.md
|
|
64
|
+
│ └── ... (approve, complete, resume, status, task, etc.)
|
|
65
|
+
├── hooks/ # 8 lifecycle hooks
|
|
66
|
+
│ ├── bash-safety.js # PreToolUse — block dangerous commands
|
|
67
|
+
│ ├── file-guard.js # PreToolUse — block sensitive files
|
|
68
|
+
│ ├── enforce-registry.js # PreToolUse — require entity-registry
|
|
69
|
+
│ ├── auto-format.js # PostToolUse — prettier/dotnet format
|
|
70
|
+
│ ├── guard-verify.js # PostToolUse — architectural rules
|
|
71
|
+
│ ├── subagent-tracker.js # Pre/SubagentStart/Stop — agent state
|
|
72
|
+
│ ├── pre-compact.js # PreCompact — snapshot before compaction
|
|
73
|
+
│ ├── session-cleanup.js # SessionEnd — prune stale state
|
|
74
|
+
│ └── __tests__/hooks.test.js # Tests (node:test + node:assert)
|
|
75
|
+
├── scripts/
|
|
76
|
+
│ ├── sync-detect.js # Subproject discovery + role detection
|
|
77
|
+
│ ├── sync-registry.js # Entity registry generation
|
|
78
|
+
│ └── statusline.js # ANSI statusline renderer
|
|
79
|
+
└── skills/ # Foundation skills
|
|
80
|
+
├── commit-workflow/
|
|
81
|
+
├── design-craft/
|
|
82
|
+
├── pipeline-execution/
|
|
83
|
+
├── react-best-practices/
|
|
84
|
+
├── senior-architect/
|
|
85
|
+
└── skill-creator/
|
|
86
|
+
```
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: templates-command-authoring
|
|
3
|
+
description: "Pattern for writing slash command SKILL.md files with trigger, procedure,
|
|
4
|
+
rules, and ULTRATHINK. Use when creating a new mustard command, adding a pipeline
|
|
5
|
+
command, writing a /command, or the user says 'new command', 'add slash command',
|
|
6
|
+
'create /feature-like command', 'write command template'."
|
|
7
|
+
---
|
|
8
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
9
|
+
|
|
10
|
+
# Command Authoring Pattern
|
|
11
|
+
|
|
12
|
+
Slash commands are SKILL.md files in `commands/mustard/{command-name}/SKILL.md` that define orchestrator behavior.
|
|
13
|
+
|
|
14
|
+
## Pattern
|
|
15
|
+
|
|
16
|
+
### File Convention
|
|
17
|
+
- Location: `commands/mustard/{command-name}/SKILL.md`
|
|
18
|
+
- No YAML frontmatter (commands are not auto-loaded by description)
|
|
19
|
+
- End with `ULTRATHINK` keyword
|
|
20
|
+
|
|
21
|
+
### Structure
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
# /{command-name} - Title
|
|
25
|
+
|
|
26
|
+
> Advisory note (optional)
|
|
27
|
+
|
|
28
|
+
## Trigger
|
|
29
|
+
`/{command-name} <args>`
|
|
30
|
+
|
|
31
|
+
## Description
|
|
32
|
+
What the command does and when to use it.
|
|
33
|
+
|
|
34
|
+
## Procedure / ## Action
|
|
35
|
+
Step-by-step process. Use:
|
|
36
|
+
- Tables for signal → action mappings
|
|
37
|
+
- Numbered steps for sequential flow
|
|
38
|
+
- Code blocks for bash commands
|
|
39
|
+
- `### Phase` headers for multi-phase pipelines
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
- Explicit constraints (NEVER, ALWAYS, MUST)
|
|
43
|
+
- Budget limits (max reads, max API calls)
|
|
44
|
+
- Delegation requirements
|
|
45
|
+
|
|
46
|
+
ULTRATHINK
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Key Rules
|
|
50
|
+
- Commands NEVER implement code directly — they orchestrate via Task tool
|
|
51
|
+
- Pipeline commands create spec files and pipeline state JSON
|
|
52
|
+
- Git commands read `mustard.json` for branch flow configuration
|
|
53
|
+
- Zero-confirmation: most commands execute without asking user
|
|
54
|
+
|
|
55
|
+
### Command Categories
|
|
56
|
+
|
|
57
|
+
| Category | Examples | Characteristic |
|
|
58
|
+
|----------|----------|---------------|
|
|
59
|
+
| Pipeline | `/feature`, `/bugfix`, `/approve`, `/complete`, `/resume` | Multi-phase, creates spec, state tracking |
|
|
60
|
+
| Task | `/task-analyze`, `/task-review`, `/task-refactor` | Single delegation, no spec |
|
|
61
|
+
| Git | `/git sync`, `/git commit`, `/git push`, `/git merge` | Reads `mustard.json`, submodule-aware |
|
|
62
|
+
| Scan | `/scan`, `/scan-format` | Discovery + analysis + generation |
|
|
63
|
+
| Status | `/status`, `/validate` | Read-only, reporting |
|
|
64
|
+
|
|
65
|
+
## Example
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
# /my-command - Do Something
|
|
69
|
+
|
|
70
|
+
## Trigger
|
|
71
|
+
`/my-command <name>`
|
|
72
|
+
|
|
73
|
+
## Procedure
|
|
74
|
+
1. Read `pipeline-config.md` for agent config
|
|
75
|
+
2. Dispatch Task agent with context
|
|
76
|
+
3. Collect results and report
|
|
77
|
+
|
|
78
|
+
## Rules
|
|
79
|
+
- NEVER implement code directly
|
|
80
|
+
- ALWAYS delegate via Task tool
|
|
81
|
+
- Budget: max 5 API calls
|
|
82
|
+
|
|
83
|
+
ULTRATHINK
|
|
84
|
+
```
|
|
85
|
+
Ref: `commands/mustard/feature/SKILL.md`, `commands/mustard/status/SKILL.md`
|
|
86
|
+
|
|
87
|
+
## References
|
|
88
|
+
|
|
89
|
+
For full code examples with variants:
|
|
90
|
+
> Read `references/examples.md`
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Command Authoring Examples
|
|
3
|
+
|
|
4
|
+
## Example 1: Simple Status Command
|
|
5
|
+
|
|
6
|
+
```markdown
|
|
7
|
+
# /status - Consolidated Status
|
|
8
|
+
|
|
9
|
+
## Trigger
|
|
10
|
+
`/status`
|
|
11
|
+
|
|
12
|
+
## Description
|
|
13
|
+
Shows consolidated project status.
|
|
14
|
+
|
|
15
|
+
## Information
|
|
16
|
+
1. **Git Status** — branch, modified files, pending push
|
|
17
|
+
2. **Pipeline** — active pipeline, current phase
|
|
18
|
+
3. **Build** — last validation result
|
|
19
|
+
4. **Entity Registry** — entity count, last update
|
|
20
|
+
|
|
21
|
+
ULTRATHINK
|
|
22
|
+
```
|
|
23
|
+
Ref: `commands/mustard/status/SKILL.md`
|
|
24
|
+
|
|
25
|
+
## Example 2: Pipeline Command (Feature)
|
|
26
|
+
|
|
27
|
+
Key sections from the feature command:
|
|
28
|
+
|
|
29
|
+
```markdown
|
|
30
|
+
# /feature - Feature Pipeline
|
|
31
|
+
|
|
32
|
+
## Trigger
|
|
33
|
+
`/feature <feature-name>`
|
|
34
|
+
|
|
35
|
+
### ANALYZE Phase
|
|
36
|
+
1. Read `pipeline-config.md`
|
|
37
|
+
2. Read `entity-registry.json` via Grep
|
|
38
|
+
3. Determine layers from signals
|
|
39
|
+
|
|
40
|
+
#### Scope Detection
|
|
41
|
+
| Signal | Scope |
|
|
42
|
+
|--------|-------|
|
|
43
|
+
| 1-2 layers, ≤5 files | Light |
|
|
44
|
+
| 3+ layers, 5+ files | Full |
|
|
45
|
+
|
|
46
|
+
### PLAN Phase
|
|
47
|
+
Create `.claude/spec/active/{date}-{name}/spec.md`
|
|
48
|
+
|
|
49
|
+
## Rules
|
|
50
|
+
- NEVER implement code in Full scope
|
|
51
|
+
- ALWAYS create pipeline state at PLAN phase
|
|
52
|
+
- Light scope + user chose "implement now" → EXECUTE inline
|
|
53
|
+
|
|
54
|
+
ULTRATHINK
|
|
55
|
+
```
|
|
56
|
+
Ref: `commands/mustard/feature/SKILL.md`
|
|
57
|
+
|
|
58
|
+
## Example 3: Git Command with Action Dispatch
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
# /git - Git Operations
|
|
62
|
+
|
|
63
|
+
## Trigger
|
|
64
|
+
`/git <action>`
|
|
65
|
+
|
|
66
|
+
## Actions
|
|
67
|
+
| Action | Description |
|
|
68
|
+
|--------|-------------|
|
|
69
|
+
| `sync` | Pull parent into current |
|
|
70
|
+
| `commit` | Create commit (no push) |
|
|
71
|
+
| `push` | Sync + commit + push |
|
|
72
|
+
|
|
73
|
+
## Step 0 — Resolve Parent
|
|
74
|
+
cat mustard.json → match branch against flow patterns
|
|
75
|
+
|
|
76
|
+
## Behavior
|
|
77
|
+
- ZERO confirmations
|
|
78
|
+
- Minimize Bash calls — chain with &&
|
|
79
|
+
- Submodules BEFORE parent
|
|
80
|
+
|
|
81
|
+
ULTRATHINK
|
|
82
|
+
```
|
|
83
|
+
Ref: `commands/mustard/git/SKILL.md`
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: templates-hook-protocol
|
|
3
|
+
description: "Pattern for writing Claude Code JavaScript hooks with stdin/stdout JSON protocol,
|
|
4
|
+
fail-open error handling, and correct response formats. Use when creating a new hook,
|
|
5
|
+
adding a guard, writing a PreToolUse or PostToolUse handler, or the user says
|
|
6
|
+
'add hook', 'new guard', 'block command', 'validate file access'."
|
|
7
|
+
---
|
|
8
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
9
|
+
|
|
10
|
+
# Hook Protocol Pattern
|
|
11
|
+
|
|
12
|
+
All Claude Code hooks are Node.js scripts that read JSON from stdin and write JSON to stdout.
|
|
13
|
+
|
|
14
|
+
## Pattern
|
|
15
|
+
|
|
16
|
+
### File Convention
|
|
17
|
+
- Location: `hooks/{hook-name}.js`
|
|
18
|
+
- Shebang: `#!/usr/bin/env node`
|
|
19
|
+
- JSDoc: version, purpose, what it blocks/allows
|
|
20
|
+
- Module system: CommonJS (`require`)
|
|
21
|
+
- Dependencies: Node.js built-ins only (`fs`, `path`, `child_process`)
|
|
22
|
+
|
|
23
|
+
### Stdin/Stdout Contract
|
|
24
|
+
|
|
25
|
+
1. Read full stdin as UTF-8 string
|
|
26
|
+
2. Parse JSON — contains `tool_name`, `tool_input`, `hook_event_name`, `cwd`
|
|
27
|
+
3. Process: check tool name, extract relevant input, apply rules
|
|
28
|
+
4. Respond:
|
|
29
|
+
- **Approve**: `process.exit(0)` silently (no stdout)
|
|
30
|
+
- **PreToolUse block**: `console.log(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'block', permissionDecisionReason: '...' } }))`
|
|
31
|
+
- **PostToolUse block**: `process.stdout.write(JSON.stringify({ decision: 'block', reason: '...' }))`
|
|
32
|
+
5. **Always fail-open**: wrap in try/catch, exit 0 on error
|
|
33
|
+
|
|
34
|
+
### Key Rules
|
|
35
|
+
- PreToolUse uses `permissionDecision` (block/deny/allow)
|
|
36
|
+
- PostToolUse uses `decision` (approve/block)
|
|
37
|
+
- NEVER mix the two formats
|
|
38
|
+
- ALWAYS normalize Windows paths before matching (`replace(/\\/g, '/')`)
|
|
39
|
+
|
|
40
|
+
## Example
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
#!/usr/bin/env node
|
|
44
|
+
let input = '';
|
|
45
|
+
process.stdin.setEncoding('utf8');
|
|
46
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
47
|
+
process.stdin.on('end', () => {
|
|
48
|
+
try {
|
|
49
|
+
const data = JSON.parse(input);
|
|
50
|
+
if (data.tool_name !== 'Bash') { process.exit(0); }
|
|
51
|
+
const cmd = data.tool_input?.command || '';
|
|
52
|
+
if (/dangerous-pattern/.test(cmd)) {
|
|
53
|
+
console.log(JSON.stringify({
|
|
54
|
+
hookSpecificOutput: {
|
|
55
|
+
hookEventName: 'PreToolUse',
|
|
56
|
+
permissionDecision: 'deny',
|
|
57
|
+
permissionDecisionReason: '[hook-name] Blocked: reason'
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
process.exit(0);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
process.stderr.write(`[hook-name] Error: ${err.message}\n`);
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
Ref: `hooks/bash-safety.js`
|
|
69
|
+
|
|
70
|
+
## References
|
|
71
|
+
|
|
72
|
+
For full code examples with variants:
|
|
73
|
+
> Read `references/examples.md`
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Hook Protocol Examples
|
|
3
|
+
|
|
4
|
+
## Example 1: PreToolUse — Regex-Based Blocking (bash-safety.js)
|
|
5
|
+
|
|
6
|
+
Simple pattern: array of `{ re, msg }` tested against command string.
|
|
7
|
+
|
|
8
|
+
```js
|
|
9
|
+
const DANGEROUS = [
|
|
10
|
+
{ re: /\brm\s+(-\w*r\w*f|--no-preserve-root)\b/i, msg: 'Recursive delete blocked' },
|
|
11
|
+
{ re: /\bgit\s+push\s+(-\w*f|--force)\b/i, msg: 'Force push blocked' },
|
|
12
|
+
];
|
|
13
|
+
// ... stdin reading ...
|
|
14
|
+
for (const { re, msg } of DANGEROUS) {
|
|
15
|
+
if (re.test(cmd)) {
|
|
16
|
+
console.log(JSON.stringify({
|
|
17
|
+
hookSpecificOutput: {
|
|
18
|
+
hookEventName: 'PreToolUse',
|
|
19
|
+
permissionDecision: 'deny',
|
|
20
|
+
permissionDecisionReason: `[bash-safety] ${msg}.`
|
|
21
|
+
}
|
|
22
|
+
}));
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
Ref: `hooks/bash-safety.js`
|
|
28
|
+
|
|
29
|
+
## Example 2: PreToolUse — File Existence Check (enforce-registry.js)
|
|
30
|
+
|
|
31
|
+
Validates that a required file exists and has valid content before allowing a skill.
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const registryPath = path.join(process.cwd(), '.claude', 'entity-registry.json');
|
|
35
|
+
if (!fs.existsSync(registryPath)) {
|
|
36
|
+
console.log(JSON.stringify({
|
|
37
|
+
hookSpecificOutput: {
|
|
38
|
+
hookEventName: 'PreToolUse',
|
|
39
|
+
permissionDecision: 'block',
|
|
40
|
+
permissionDecisionReason: 'Entity registry not found. Run /sync-registry first.'
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
46
|
+
// validate version, entities, patterns...
|
|
47
|
+
```
|
|
48
|
+
Ref: `hooks/enforce-registry.js`
|
|
49
|
+
|
|
50
|
+
## Example 3: PostToolUse — Content Validation (guard-verify.js)
|
|
51
|
+
|
|
52
|
+
Checks the content being written against architectural rules.
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
const CRITICAL_RULES = [
|
|
56
|
+
{ pattern: /\bDbContext\b/i, scope: /Services?[/\\]/, msg: 'DbContext in Services' },
|
|
57
|
+
];
|
|
58
|
+
// ...
|
|
59
|
+
const violations = [];
|
|
60
|
+
for (const rule of CRITICAL_RULES) {
|
|
61
|
+
if (!rule.scope.test(relPath)) continue;
|
|
62
|
+
if (!rule.pattern.test(newContent)) continue;
|
|
63
|
+
violations.push(rule.msg);
|
|
64
|
+
}
|
|
65
|
+
if (violations.length > 0) {
|
|
66
|
+
process.stdout.write(JSON.stringify({
|
|
67
|
+
decision: 'block',
|
|
68
|
+
reason: violations.map(v => `CRITICAL: ${v}`).join('\n')
|
|
69
|
+
}));
|
|
70
|
+
} else {
|
|
71
|
+
process.stdout.write(JSON.stringify({ decision: 'approve' }));
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
Ref: `hooks/guard-verify.js`
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: templates-settings-wiring
|
|
3
|
+
description: "Pattern for wiring hooks, permissions, and statusline in settings.json.
|
|
4
|
+
Use when adding a new hook to settings, changing permissions, updating lifecycle
|
|
5
|
+
event matchers, configuring statusline, or the user says 'register hook',
|
|
6
|
+
'add permission', 'wire up', 'configure settings'."
|
|
7
|
+
---
|
|
8
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
9
|
+
|
|
10
|
+
# Settings.json Wiring Pattern
|
|
11
|
+
|
|
12
|
+
The `settings.json` file is the central configuration for Claude Code hook lifecycle, permissions, and statusline.
|
|
13
|
+
|
|
14
|
+
## Pattern
|
|
15
|
+
|
|
16
|
+
### Lifecycle Events
|
|
17
|
+
|
|
18
|
+
| Event | Matcher Examples | Purpose |
|
|
19
|
+
|-------|-----------------|---------|
|
|
20
|
+
| `PreToolUse` | `Bash`, `Read\|Write\|Edit`, `Skill`, `Task` | Guard before tool execution |
|
|
21
|
+
| `PostToolUse` | `Write\|Edit` | Validate/format after tool execution |
|
|
22
|
+
| `SessionStart` | `startup` | Clean stale state |
|
|
23
|
+
| `SessionEnd` | `prompt_input_exit\|clear\|other` | Prune state files |
|
|
24
|
+
| `PreCompact` | `auto\|manual` | Snapshot before compaction |
|
|
25
|
+
| `SubagentStart` | (no matcher) | Register agent |
|
|
26
|
+
| `SubagentStop` | (no matcher) | Deregister agent |
|
|
27
|
+
|
|
28
|
+
### Hook Registration Structure
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"matcher": "ToolName|OtherTool",
|
|
33
|
+
"hooks": [{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/{hook}.js",
|
|
36
|
+
"timeout": 5
|
|
37
|
+
}]
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Key Rules
|
|
42
|
+
- `$CLAUDE_PROJECT_DIR` resolves to the project root at runtime
|
|
43
|
+
- Always quote the path: `\"$CLAUDE_PROJECT_DIR\"`
|
|
44
|
+
- Timeout: 3-5s for simple checks, 10-15s for format/compile
|
|
45
|
+
- Multiple hooks under same matcher run sequentially
|
|
46
|
+
- Matcher uses `|` for OR: `"Write|Edit"`, `"Read|Write|Edit"`
|
|
47
|
+
|
|
48
|
+
### Permissions
|
|
49
|
+
|
|
50
|
+
- `allow`: array of tool patterns (`"Bash(git:*)"`, `"Read"`)
|
|
51
|
+
- `deny`: array of blocked patterns (`"Bash(rm -rf:*)"`)
|
|
52
|
+
- Deny overrides allow
|
|
53
|
+
|
|
54
|
+
## Example
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"hooks": {
|
|
59
|
+
"PreToolUse": [{
|
|
60
|
+
"matcher": "Bash",
|
|
61
|
+
"hooks": [{
|
|
62
|
+
"type": "command",
|
|
63
|
+
"command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/my-hook.js",
|
|
64
|
+
"timeout": 5
|
|
65
|
+
}]
|
|
66
|
+
}]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
Ref: `settings.json`
|
|
71
|
+
|
|
72
|
+
## References
|
|
73
|
+
|
|
74
|
+
For full code examples with variants:
|
|
75
|
+
> Read `references/examples.md`
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Settings Wiring Examples
|
|
3
|
+
|
|
4
|
+
## Example 1: PreToolUse with Multiple Matchers
|
|
5
|
+
|
|
6
|
+
```json
|
|
7
|
+
{
|
|
8
|
+
"PreToolUse": [
|
|
9
|
+
{
|
|
10
|
+
"matcher": "Bash",
|
|
11
|
+
"hooks": [{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/bash-safety.js", "timeout": 5 }]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"matcher": "Read|Write|Edit",
|
|
15
|
+
"hooks": [{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/file-guard.js", "timeout": 5 }]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"matcher": "Skill",
|
|
19
|
+
"hooks": [{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/enforce-registry.js", "timeout": 5 }]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
Ref: `settings.json` (lines 74-114)
|
|
25
|
+
|
|
26
|
+
## Example 2: PostToolUse with Sequential Hooks
|
|
27
|
+
|
|
28
|
+
Two hooks run sequentially on the same matcher — format first, then verify:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"PostToolUse": [{
|
|
33
|
+
"matcher": "Write|Edit",
|
|
34
|
+
"hooks": [
|
|
35
|
+
{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/auto-format.js", "timeout": 15 },
|
|
36
|
+
{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guard-verify.js", "timeout": 5 }
|
|
37
|
+
]
|
|
38
|
+
}]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
Ref: `settings.json` (lines 117-133)
|
|
42
|
+
|
|
43
|
+
## Example 3: Permission Configuration
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"permissions": {
|
|
48
|
+
"allow": [
|
|
49
|
+
"Read", "Edit", "Write", "Glob", "Grep", "Skill", "Task",
|
|
50
|
+
"Bash(git:*)", "Bash(node:*)", "Bash(npm:*)", "Bash(dotnet:*)"
|
|
51
|
+
],
|
|
52
|
+
"deny": [
|
|
53
|
+
"Bash(rm -rf:*)", "Bash(git push --force:*)", "Bash(git reset --hard:*)",
|
|
54
|
+
"Bash(shutdown:*)", "Bash(reboot:*)"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
Ref: `settings.json` (lines 8-70)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: templates-skill-authoring
|
|
3
|
+
description: "Pattern for writing foundation and subproject skills with YAML frontmatter,
|
|
4
|
+
pushy descriptions, and references. Use when creating a new skill, writing a
|
|
5
|
+
SKILL.md, adding skill references, or the user says 'new skill', 'create skill',
|
|
6
|
+
'add pattern skill', 'write foundation skill'."
|
|
7
|
+
---
|
|
8
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
9
|
+
|
|
10
|
+
# Skill Authoring Pattern
|
|
11
|
+
|
|
12
|
+
Skills are auto-loaded by Claude based on task description matching the skill's `description` field.
|
|
13
|
+
|
|
14
|
+
## Pattern
|
|
15
|
+
|
|
16
|
+
### File Convention
|
|
17
|
+
- Location: `skills/{skill-name}/SKILL.md` (foundation) or `{sub}/.claude/skills/{skill-name}/SKILL.md` (subproject)
|
|
18
|
+
- YAML frontmatter: `name`, `description`, optional `disable-model-invocation`
|
|
19
|
+
- `<!-- mustard:generated -->` goes AFTER closing `---` (never before opening `---`)
|
|
20
|
+
- Max 500 lines (ideally under 200)
|
|
21
|
+
|
|
22
|
+
### Description Writing (Critical)
|
|
23
|
+
|
|
24
|
+
Descriptions are the PRIMARY trigger mechanism. They must be "pushy":
|
|
25
|
+
|
|
26
|
+
**Good:**
|
|
27
|
+
```yaml
|
|
28
|
+
description: "Pattern for .NET Minimal API endpoints with validation and auth.
|
|
29
|
+
Use when creating new routes, adding HTTP verbs, wiring endpoints, or the user
|
|
30
|
+
says 'add endpoint', 'new route', 'expose via API'."
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Bad:**
|
|
34
|
+
```yaml
|
|
35
|
+
description: "API patterns"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### SKILL.md Structure
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
---
|
|
42
|
+
name: {skill-name}
|
|
43
|
+
description: "{What}. {When — be specific and pushy}."
|
|
44
|
+
---
|
|
45
|
+
<!-- mustard:generated at:{ISO} role:{role} -->
|
|
46
|
+
|
|
47
|
+
# {Skill Title}
|
|
48
|
+
|
|
49
|
+
{1-2 sentence summary.}
|
|
50
|
+
|
|
51
|
+
## Pattern
|
|
52
|
+
|
|
53
|
+
{Concise rules, file conventions, key constraints.}
|
|
54
|
+
|
|
55
|
+
## Example
|
|
56
|
+
|
|
57
|
+
{5-10 line code example — happy path only.}
|
|
58
|
+
Ref: `{path/to/real/file}`
|
|
59
|
+
|
|
60
|
+
## References
|
|
61
|
+
|
|
62
|
+
For full code examples with variants:
|
|
63
|
+
> Read `references/examples.md`
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### references/examples.md
|
|
67
|
+
|
|
68
|
+
- 2-3 real examples at different complexity levels
|
|
69
|
+
- Always include `Ref: path/to/file.ext`
|
|
70
|
+
- Max 15 lines per example
|
|
71
|
+
- Starts with `<!-- mustard:generated -->` header
|
|
72
|
+
|
|
73
|
+
## Example
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
---
|
|
77
|
+
name: commit-workflow
|
|
78
|
+
description: Git commit strategy, submodule-aware, budget <=15 API calls.
|
|
79
|
+
disable-model-invocation: true
|
|
80
|
+
---
|
|
81
|
+
<!-- mustard:generated -->
|
|
82
|
+
|
|
83
|
+
# Commit Workflow
|
|
84
|
+
|
|
85
|
+
> Git strategy for mono-repo with submodules.
|
|
86
|
+
|
|
87
|
+
## Strategy
|
|
88
|
+
1. `git status` — see all changes
|
|
89
|
+
2. Group changes by subproject
|
|
90
|
+
3. Per subproject: `git add` specific files -> `git commit`
|
|
91
|
+
```
|
|
92
|
+
Ref: `skills/commit-workflow/SKILL.md`
|
|
93
|
+
|
|
94
|
+
## References
|
|
95
|
+
|
|
96
|
+
For full code examples with variants:
|
|
97
|
+
> Read `references/examples.md`
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Skill Authoring Examples
|
|
3
|
+
|
|
4
|
+
## Example 1: Simple Foundation Skill (commit-workflow)
|
|
5
|
+
|
|
6
|
+
```yaml
|
|
7
|
+
---
|
|
8
|
+
name: commit-workflow
|
|
9
|
+
description: Git commit strategy, submodule-aware, budget ≤15 API calls.
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
<!-- mustard:generated -->
|
|
13
|
+
|
|
14
|
+
# Commit Workflow
|
|
15
|
+
|
|
16
|
+
> Git strategy for mono-repo with submodules. Budget ≤15 API calls.
|
|
17
|
+
|
|
18
|
+
## Strategy
|
|
19
|
+
1. `git status` — see all changes
|
|
20
|
+
2. `git diff --stat` — understand scope
|
|
21
|
+
3. Group changes by subproject
|
|
22
|
+
4. Per subproject: `git add` specific files → `git commit`
|
|
23
|
+
|
|
24
|
+
## Rules
|
|
25
|
+
- Budget: ≤15 API calls total
|
|
26
|
+
- NEVER use `git add .` — always specific files
|
|
27
|
+
```
|
|
28
|
+
Ref: `skills/commit-workflow/SKILL.md`
|
|
29
|
+
|
|
30
|
+
## Example 2: Complex Skill with References (pipeline-execution)
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
---
|
|
34
|
+
name: pipeline-execution
|
|
35
|
+
description: Pipeline phases, dispatch rules, wave system, validate, retry.
|
|
36
|
+
Load for /feature /resume /approve.
|
|
37
|
+
disable-model-invocation: true
|
|
38
|
+
---
|
|
39
|
+
<!-- mustard:generated -->
|
|
40
|
+
|
|
41
|
+
# Pipeline Execution Detail
|
|
42
|
+
|
|
43
|
+
> Phases, role rules, dispatch mechanics, validation, bugfix paths.
|
|
44
|
+
|
|
45
|
+
## Pipeline Feature
|
|
46
|
+
### ANALYZE Phase
|
|
47
|
+
1. AUTO-SYNC: `node .claude/scripts/sync-registry.js`
|
|
48
|
+
2. Read `entity-registry.json` → entity found? → infer layers
|
|
49
|
+
```
|
|
50
|
+
Ref: `skills/pipeline-execution/SKILL.md`
|
|
51
|
+
|
|
52
|
+
## Example 3: Skill with Rich References (design-craft)
|
|
53
|
+
|
|
54
|
+
Structure with multiple reference files:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
skills/design-craft/
|
|
58
|
+
├── SKILL.md
|
|
59
|
+
└── references/
|
|
60
|
+
├── critique.md
|
|
61
|
+
├── example.md
|
|
62
|
+
├── palettes-catalog.md
|
|
63
|
+
├── principles.md
|
|
64
|
+
├── styles-catalog.md
|
|
65
|
+
├── typography-catalog.md
|
|
66
|
+
├── ux-guidelines.md
|
|
67
|
+
└── validation.md
|
|
68
|
+
```
|
|
69
|
+
Ref: `skills/design-craft/SKILL.md`
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: templates-sync-detect
|
|
3
|
+
description: "Pattern for subproject discovery, role detection via scoring, and SHA-256
|
|
4
|
+
incremental hashing in sync-detect.js. Use when modifying detection logic,
|
|
5
|
+
adding a new role/stack, changing hash computation, adding new scoring signals,
|
|
6
|
+
or the user says 'add stack detection', 'new role', 'detect framework',
|
|
7
|
+
'fix detection', 'change scoring'."
|
|
8
|
+
---
|
|
9
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
10
|
+
|
|
11
|
+
# Sync-Detect Pattern
|
|
12
|
+
|
|
13
|
+
sync-detect.js discovers subprojects, detects their role via weighted scoring, and computes SHA-256 hashes for incremental scan.
|
|
14
|
+
|
|
15
|
+
## Pattern
|
|
16
|
+
|
|
17
|
+
### Discovery Order
|
|
18
|
+
1. `git submodule status` — prefer submodule paths
|
|
19
|
+
2. Fallback: scan root for dirs containing `CLAUDE.md`
|
|
20
|
+
|
|
21
|
+
### Role Scoring (weighted signals)
|
|
22
|
+
|
|
23
|
+
| Weight | Constant | Signal Type |
|
|
24
|
+
|--------|----------|-------------|
|
|
25
|
+
| 10 | `HIGH` | Config files: `.csproj` Sdk.Web, `next.config.*`, `drizzle.config.*`, `pubspec.yaml` |
|
|
26
|
+
| 5 | `MEDIUM` | Package deps: `react`, `express`, `drizzle-orm` in package.json |
|
|
27
|
+
| 3 | `LOW` | Directories: `Controllers/`, `app/`+`components/`, `migrations/` |
|
|
28
|
+
|
|
29
|
+
Roles: `api`, `ui`, `database`, `library`, `mobile`, `general` (fallback).
|
|
30
|
+
Role maps to agent: `api→backend`, `ui→frontend`, `database→database`, `library→backend`, `mobile→mobile`.
|
|
31
|
+
|
|
32
|
+
### Incremental Hashing
|
|
33
|
+
- Collect source files (`.cs`, `.ts`, `.tsx`, `.js`, `.jsx`, `.dart`)
|
|
34
|
+
- Exclude: `node_modules`, `.next`, `bin`, `obj`, `dist`, `migrations`, `_backup`, dotfiles
|
|
35
|
+
- Sort files → hash(path + content) per file → SHA-256 digest
|
|
36
|
+
- Module-level hashes for fine-grained incremental (backend: `Modules/v{N}/{Module}/`, frontend: `app/(dashboard)/*/`)
|
|
37
|
+
|
|
38
|
+
### Output
|
|
39
|
+
JSON to stdout: `{ subprojects, agents, detectedAgents, sourceHashes, moduleHashes }`
|
|
40
|
+
Writes `.claude/.detect-cache.json` (unless `--no-cache`).
|
|
41
|
+
|
|
42
|
+
## Example
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
function detectRole(absPath) {
|
|
46
|
+
const scores = { api: 0, ui: 0, database: 0, library: 0, mobile: 0 };
|
|
47
|
+
if (isCsprojWeb(absPath)) scores.api += 10;
|
|
48
|
+
if (fileExists(absPath, 'next.config.*')) scores.ui += 10;
|
|
49
|
+
// ... more signals ...
|
|
50
|
+
let maxScore = 0, role = 'general';
|
|
51
|
+
for (const [r, s] of Object.entries(scores)) {
|
|
52
|
+
if (s > maxScore) { maxScore = s; role = r; }
|
|
53
|
+
}
|
|
54
|
+
return { role, scores };
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
Ref: `scripts/sync-detect.js`
|
|
58
|
+
|
|
59
|
+
## References
|
|
60
|
+
|
|
61
|
+
For full code examples with variants:
|
|
62
|
+
> Read `references/examples.md`
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<!-- mustard:generated at:2026-03-25T00:00:00.000Z role:general -->
|
|
2
|
+
# Sync-Detect Examples
|
|
3
|
+
|
|
4
|
+
## Example 1: Adding a New Role Signal
|
|
5
|
+
|
|
6
|
+
To detect a new framework, add scoring in `detectRole()`:
|
|
7
|
+
|
|
8
|
+
```js
|
|
9
|
+
// In detectRole(absPath):
|
|
10
|
+
// Python FastAPI → api (HIGH)
|
|
11
|
+
if (fileExists(absPath, 'pyproject.toml')) {
|
|
12
|
+
if (pyprojectHas(absPath, ['fastapi', 'django', 'flask'])) {
|
|
13
|
+
scores.api += ROLE_WEIGHTS.HIGH;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
Ref: `scripts/sync-detect.js` (lines 271-276)
|
|
18
|
+
|
|
19
|
+
## Example 2: Adding Package.json Dep Detection
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
const deps = getPackageJsonDeps(absPath);
|
|
23
|
+
if (deps.length > 0) {
|
|
24
|
+
if (hasAnyDep(deps, ['express', 'fastify', 'hono', 'koa', 'nestjs'])) {
|
|
25
|
+
scores.api += ROLE_WEIGHTS.MEDIUM;
|
|
26
|
+
}
|
|
27
|
+
if (hasAnyDep(deps, ['react', 'next', 'vue', 'nuxt', 'svelte'])) {
|
|
28
|
+
scores.ui += ROLE_WEIGHTS.MEDIUM;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
Ref: `scripts/sync-detect.js` (lines 240-254)
|
|
33
|
+
|
|
34
|
+
## Example 3: Module-Level Hash Computation
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
function computeModuleHashes(subprojectPath, role) {
|
|
38
|
+
const modules = {};
|
|
39
|
+
if (role === 'api' || role === 'library') {
|
|
40
|
+
const allModuleDirs = findAllModulesDirs(absPath);
|
|
41
|
+
// ... collect files per module, compute SHA-256 per module
|
|
42
|
+
for (const [modName, files] of Object.entries(moduleFiles)) {
|
|
43
|
+
files.sort();
|
|
44
|
+
const hash = crypto.createHash('sha256');
|
|
45
|
+
for (const f of files) {
|
|
46
|
+
hash.update(f);
|
|
47
|
+
hash.update(fs.readFileSync(path.join(ROOT, f), 'utf-8'));
|
|
48
|
+
}
|
|
49
|
+
modules[modName] = { hash: hash.digest('hex'), files: files.length };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return modules;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
Ref: `scripts/sync-detect.js` (lines 665-784)
|
package/templates/CLAUDE.md
CHANGED
|
@@ -26,5 +26,52 @@ ANALYZE → PLAN → EXECUTE → CLOSE
|
|
|
26
26
|
Agents auto-load skills from `{subproject}/.claude/skills/` based on task description.
|
|
27
27
|
Guards always loaded via `{subproject}/CLAUDE.md`.
|
|
28
28
|
|
|
29
|
+
## Stack
|
|
30
|
+
|
|
31
|
+
Node.js (>=18), CommonJS, no external dependencies. 8 lifecycle hooks, 3 sync scripts, 14 slash commands, 6 foundation skills.
|
|
32
|
+
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Run hook tests
|
|
37
|
+
node --test hooks/__tests__/hooks.test.js
|
|
38
|
+
|
|
39
|
+
# Subproject discovery (outputs JSON)
|
|
40
|
+
node scripts/sync-detect.js
|
|
41
|
+
node scripts/sync-detect.js --no-cache
|
|
42
|
+
|
|
43
|
+
# Entity registry generation
|
|
44
|
+
node scripts/sync-registry.js
|
|
45
|
+
node scripts/sync-registry.js --force
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Guards
|
|
49
|
+
|
|
50
|
+
- All hooks fail-open (exit 0 on error) — never block due to hook bugs
|
|
51
|
+
- All hooks use only Node.js built-ins — no npm dependencies
|
|
52
|
+
- PreToolUse hooks use `permissionDecision` response format
|
|
53
|
+
- PostToolUse hooks use `decision` response format
|
|
54
|
+
- Every new hook must be registered in `settings.json` with a timeout
|
|
55
|
+
- Generated files must start with `<!-- mustard:generated -->` header
|
|
56
|
+
- Skills must have YAML frontmatter BEFORE the `<!-- mustard:generated -->` line
|
|
57
|
+
|
|
58
|
+
## Scan References
|
|
59
|
+
|
|
60
|
+
| File | Description |
|
|
61
|
+
|------|-------------|
|
|
62
|
+
| `.claude/commands/stack.md` | Technology stack, structure, tooling |
|
|
63
|
+
| `.claude/commands/patterns.md` | 12 recurring code patterns with refs |
|
|
64
|
+
| `.claude/commands/guards.md` | DO/DON'T rules for hooks, scripts, commands, skills |
|
|
65
|
+
| `.claude/commands/recipes.md` | Implementation recipes for new hooks, commands, skills, scripts |
|
|
66
|
+
| `.claude/commands/notes.md` | Manual notes (never overwritten) |
|
|
67
|
+
|
|
68
|
+
## Recommended Skills
|
|
69
|
+
|
|
70
|
+
- `templates-hook-protocol` — Hook stdin/stdout JSON protocol
|
|
71
|
+
- `templates-settings-wiring` — settings.json hook registration
|
|
72
|
+
- `templates-sync-detect` — Subproject discovery and role detection
|
|
73
|
+
- `templates-command-authoring` — Slash command SKILL.md structure
|
|
74
|
+
- `templates-skill-authoring` — Foundation/subproject skill creation
|
|
75
|
+
|
|
29
76
|
## Full Reference
|
|
30
77
|
Rules, pipeline, naming: `pipeline-config.md`
|
package/templates/settings.json
CHANGED
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
"permissions": {
|
|
9
9
|
"allow": [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"Bash
|
|
10
|
+
"Read",
|
|
11
|
+
"Edit",
|
|
12
|
+
"Write",
|
|
13
|
+
"Glob",
|
|
14
|
+
"Grep",
|
|
15
|
+
"Skill",
|
|
16
|
+
"Task",
|
|
17
|
+
"WebFetch",
|
|
18
|
+
"WebSearch",
|
|
19
|
+
"Bash"
|
|
20
20
|
],
|
|
21
21
|
"deny": [
|
|
22
22
|
"Bash(rm -rf:*)",
|