@acmeacmeio/setup-sh 0.2.6
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 +212 -0
- package/package.json +39 -0
- package/src/cli.mjs +614 -0
- package/templates/.claude/agents/code-simplifier.md +52 -0
- package/templates/.claude/commands/auto.md +85 -0
- package/templates/.claude/commands/clean-copy.md +93 -0
- package/templates/.claude/commands/fix-issue.md +34 -0
- package/templates/.claude/commands/review.md +46 -0
- package/templates/.claude/router/classify.js +241 -0
- package/templates/.claude/router/registry.json +49 -0
- package/templates/.claude/settings.json +113 -0
- package/templates/.claude/skills/api-design/SKILL.md +77 -0
- package/templates/.claude/skills/security-review/SKILL.md +65 -0
- package/templates/.codex/config.toml +31 -0
- package/templates/.codex/skills/api-design/SKILL.md +77 -0
- package/templates/.codex/skills/security-review/SKILL.md +65 -0
- package/templates/.cursor/commands/auto.md +55 -0
- package/templates/.cursor/commands/clean-copy.md +80 -0
- package/templates/.cursor/commands/code-simplifier.md +28 -0
- package/templates/.cursor/commands/fix-issue.md +28 -0
- package/templates/.cursor/commands/review.md +41 -0
- package/templates/.cursor/hooks.json +11 -0
- package/templates/.cursor/rules/api-design.mdc +80 -0
- package/templates/.cursor/rules/git-workflow.mdc +73 -0
- package/templates/.cursor/rules/security.mdc +69 -0
- package/templates/.cursor/rules/tdd.mdc +35 -0
- package/templates/.cursor/rules/typescript.mdc +82 -0
- package/templates/.cursorignore.template +20 -0
- package/templates/.gitignore.template +10 -0
- package/templates/.mcp.json +16 -0
- package/templates/AGENTS.md +118 -0
- package/templates/CLAUDE.md +138 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Auto-detect and execute the best workflow for your request
|
|
3
|
+
argument-hint: <your request in natural language>
|
|
4
|
+
model: haiku
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Intent Router
|
|
8
|
+
|
|
9
|
+
Automatically classify user intent and route to the appropriate workflow.
|
|
10
|
+
|
|
11
|
+
## Available Commands
|
|
12
|
+
|
|
13
|
+
List of commands in `.claude/commands/`:
|
|
14
|
+
|
|
15
|
+
- `fix-issue` - Fix a GitHub issue following TDD workflow
|
|
16
|
+
- `tdd` - Activate strict TDD mode
|
|
17
|
+
- `review` - Run code review checklist
|
|
18
|
+
- `clean-copy` - Restructure commits into clean history
|
|
19
|
+
|
|
20
|
+
## Registry
|
|
21
|
+
|
|
22
|
+
Reference the registry at `.claude/router/registry.yaml` for trigger patterns and chains.
|
|
23
|
+
|
|
24
|
+
## Task
|
|
25
|
+
|
|
26
|
+
Classify this request: **$ARGUMENTS**
|
|
27
|
+
|
|
28
|
+
### Classification Process
|
|
29
|
+
|
|
30
|
+
1. **Extract key intent** from the natural language request
|
|
31
|
+
2. **Match against registry triggers** - find the best matching command or chain
|
|
32
|
+
3. **Extract arguments** - pull out issue numbers, branch names, or other parameters
|
|
33
|
+
4. **Determine confidence** - how well does this match?
|
|
34
|
+
|
|
35
|
+
### Output
|
|
36
|
+
|
|
37
|
+
Return a JSON object with your classification:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"intent": "description of what user wants",
|
|
42
|
+
"match": {
|
|
43
|
+
"type": "command" | "chain",
|
|
44
|
+
"name": "command or chain name",
|
|
45
|
+
"confidence": 0.0-1.0
|
|
46
|
+
},
|
|
47
|
+
"args": {
|
|
48
|
+
"issue_number": "123",
|
|
49
|
+
"branch_name": "feature-x"
|
|
50
|
+
},
|
|
51
|
+
"execute": "/command-name args"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Confidence Guidelines
|
|
56
|
+
|
|
57
|
+
- **0.9-1.0**: Exact trigger phrase match
|
|
58
|
+
- **0.7-0.9**: Clear intent, slightly different wording
|
|
59
|
+
- **0.5-0.7**: Probable match, some ambiguity
|
|
60
|
+
- **Below 0.5**: Ask user to clarify
|
|
61
|
+
|
|
62
|
+
### If Low Confidence
|
|
63
|
+
|
|
64
|
+
If confidence is below 0.7, present options to the user:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
I'm not sure which workflow you want. Did you mean:
|
|
68
|
+
|
|
69
|
+
1. `/fix-issue` - Fix a GitHub issue with TDD
|
|
70
|
+
2. `/tdd` - Start TDD mode
|
|
71
|
+
3. `/review` - Review code changes
|
|
72
|
+
|
|
73
|
+
Please choose or rephrase your request.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Examples
|
|
77
|
+
|
|
78
|
+
| Input | Match | Confidence |
|
|
79
|
+
| ----------------------- | ---------- | ---------- |
|
|
80
|
+
| "fix issue #123" | fix-issue | 0.95 |
|
|
81
|
+
| "I need to fix bug 456" | fix-issue | 0.85 |
|
|
82
|
+
| "review my changes" | review | 0.90 |
|
|
83
|
+
| "clean up my commits" | clean-copy | 0.85 |
|
|
84
|
+
| "do tdd" | tdd | 0.80 |
|
|
85
|
+
| "help me code" | - | 0.30 |
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Reimplement branch with clean, narrative-quality commit history
|
|
3
|
+
argument-hint: [new-branch-name]
|
|
4
|
+
allowed-tools: Bash(git:*), Bash(gh pr create:*)
|
|
5
|
+
model: opus
|
|
6
|
+
is_finisher: true
|
|
7
|
+
finishers: [review]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Clean Copy
|
|
11
|
+
|
|
12
|
+
Reimplement the current branch with clean, atomic commits suitable for reviewer comprehension.
|
|
13
|
+
|
|
14
|
+
## Context
|
|
15
|
+
|
|
16
|
+
Gather current state:
|
|
17
|
+
|
|
18
|
+
- **Source branch**: `git branch --show-current`
|
|
19
|
+
- **Git status**: `git status --short`
|
|
20
|
+
- **Commits since main**: `git log main..HEAD --oneline`
|
|
21
|
+
- **Diff stats**: `git diff main...HEAD --stat`
|
|
22
|
+
- **Full diff**: `git diff main...HEAD`
|
|
23
|
+
|
|
24
|
+
## Task
|
|
25
|
+
|
|
26
|
+
Create a new branch with restructured commits that tell a clear story.
|
|
27
|
+
|
|
28
|
+
**Branch name**: Use the argument if provided, otherwise `{source_branch}-clean`
|
|
29
|
+
|
|
30
|
+
### Steps
|
|
31
|
+
|
|
32
|
+
1. **Validate source branch**
|
|
33
|
+
- Ensure no uncommitted changes
|
|
34
|
+
- Ensure branch is up to date with main
|
|
35
|
+
|
|
36
|
+
2. **Analyze the full diff**
|
|
37
|
+
- Understand the complete intended final state
|
|
38
|
+
- Identify logical units of change
|
|
39
|
+
|
|
40
|
+
3. **Create clean branch from main**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git checkout main
|
|
44
|
+
git pull origin main
|
|
45
|
+
git checkout -b {new_branch_name}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
4. **Plan commit storyline**
|
|
49
|
+
- Break changes into self-contained logical steps
|
|
50
|
+
- Each commit should represent a single coherent idea
|
|
51
|
+
- Order commits so each builds on the previous (tutorial-style)
|
|
52
|
+
- Aim for 3-7 commits typically
|
|
53
|
+
|
|
54
|
+
5. **Reimplement step-by-step**
|
|
55
|
+
For each logical unit:
|
|
56
|
+
- Apply the relevant changes
|
|
57
|
+
- Write a clear commit message following conventional commits
|
|
58
|
+
- Use `git commit --no-verify` for intermediate commits (types/tests may not pass until complete)
|
|
59
|
+
|
|
60
|
+
6. **Verify final state matches source**
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git diff {source_branch}..HEAD
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This diff should be empty. If not, reconcile differences.
|
|
67
|
+
|
|
68
|
+
7. **Final commit verification**
|
|
69
|
+
- The final commit must NOT use `--no-verify`
|
|
70
|
+
- All checks (lint, types, tests) must pass
|
|
71
|
+
|
|
72
|
+
8. **Create PR**
|
|
73
|
+
- Follow project PR conventions
|
|
74
|
+
- Link to original branch or issue
|
|
75
|
+
- Use `gh pr create`
|
|
76
|
+
|
|
77
|
+
### Rules
|
|
78
|
+
|
|
79
|
+
- Never add "Co-Authored-By" or "Generated with Claude" lines
|
|
80
|
+
- End state must be byte-for-byte identical to source branch
|
|
81
|
+
- Each commit message should explain _why_, not just _what_
|
|
82
|
+
- If the source branch has a linked issue, reference it in the PR
|
|
83
|
+
|
|
84
|
+
### Example Commit Storyline
|
|
85
|
+
|
|
86
|
+
For a feature adding user authentication:
|
|
87
|
+
|
|
88
|
+
1. `feat: add User model and database migration`
|
|
89
|
+
2. `feat: implement password hashing utilities`
|
|
90
|
+
3. `feat: add login/logout API endpoints`
|
|
91
|
+
4. `feat: add session middleware`
|
|
92
|
+
5. `test: add authentication integration tests`
|
|
93
|
+
6. `docs: update API documentation with auth endpoints`
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Fix a GitHub issue following TDD workflow
|
|
3
|
+
argument-hint: <issue-number>
|
|
4
|
+
finishers: [clean-copy]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Fix Issue Workflow
|
|
8
|
+
|
|
9
|
+
When fixing a GitHub issue:
|
|
10
|
+
|
|
11
|
+
1. **Understand the issue**
|
|
12
|
+
- Read the issue description and comments
|
|
13
|
+
- Understand the expected vs actual behavior
|
|
14
|
+
- Identify affected files and components
|
|
15
|
+
|
|
16
|
+
2. **Write a failing test**
|
|
17
|
+
- Create a test that reproduces the issue
|
|
18
|
+
- Run it to confirm it fails
|
|
19
|
+
- The test should clearly demonstrate the bug
|
|
20
|
+
|
|
21
|
+
3. **Implement the fix**
|
|
22
|
+
- Write minimal code to fix the issue
|
|
23
|
+
- Keep changes focused on the bug
|
|
24
|
+
- Don't refactor unrelated code
|
|
25
|
+
|
|
26
|
+
4. **Verify the fix**
|
|
27
|
+
- Run the new test to confirm it passes
|
|
28
|
+
- Run all related tests to ensure no regressions
|
|
29
|
+
- Run lint and typecheck
|
|
30
|
+
|
|
31
|
+
5. **Create a PR**
|
|
32
|
+
- Use conventional commit: `fix: description`
|
|
33
|
+
- Reference the issue: `Fixes #123`
|
|
34
|
+
- Include before/after behavior in PR description
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run code review checklist
|
|
3
|
+
is_finisher: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code Review Checklist
|
|
7
|
+
|
|
8
|
+
Review the code against this checklist:
|
|
9
|
+
|
|
10
|
+
## Testing
|
|
11
|
+
|
|
12
|
+
- [ ] Tests cover the changes
|
|
13
|
+
- [ ] Edge cases are tested
|
|
14
|
+
- [ ] Tests are readable and maintainable
|
|
15
|
+
|
|
16
|
+
## Code Quality
|
|
17
|
+
|
|
18
|
+
- [ ] No console.log or debug code
|
|
19
|
+
- [ ] No commented-out code
|
|
20
|
+
- [ ] Types are explicit (no `any`)
|
|
21
|
+
- [ ] No hardcoded values that should be config
|
|
22
|
+
- [ ] Follows existing patterns in codebase
|
|
23
|
+
|
|
24
|
+
## Error Handling
|
|
25
|
+
|
|
26
|
+
- [ ] Errors are handled appropriately
|
|
27
|
+
- [ ] Error messages are helpful
|
|
28
|
+
- [ ] No silent failures
|
|
29
|
+
|
|
30
|
+
## Security
|
|
31
|
+
|
|
32
|
+
- [ ] No credentials or secrets in code
|
|
33
|
+
- [ ] User input is validated
|
|
34
|
+
- [ ] No SQL injection or XSS vulnerabilities
|
|
35
|
+
|
|
36
|
+
## Performance
|
|
37
|
+
|
|
38
|
+
- [ ] No obvious performance issues
|
|
39
|
+
- [ ] No unnecessary re-renders (React)
|
|
40
|
+
- [ ] Database queries are efficient
|
|
41
|
+
|
|
42
|
+
## Documentation
|
|
43
|
+
|
|
44
|
+
- [ ] Complex logic has comments
|
|
45
|
+
- [ ] Public APIs have documentation
|
|
46
|
+
- [ ] Breaking changes are documented
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Intent Classifier for Claude Code
|
|
5
|
+
*
|
|
6
|
+
* Runs on every UserPromptSubmit to classify intent and suggest workflows.
|
|
7
|
+
* Uses simple pattern matching for fast, local classification.
|
|
8
|
+
* Zero external dependencies - uses only Node.js built-ins.
|
|
9
|
+
*
|
|
10
|
+
* Usage: node classify.js "<user prompt>"
|
|
11
|
+
*
|
|
12
|
+
* Output: JSON metadata that Claude uses to route the request
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require("fs");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
|
|
18
|
+
// Load registry from JSON (no external dependencies)
|
|
19
|
+
function loadRegistry() {
|
|
20
|
+
const registryPath = path.join(__dirname, "registry.json");
|
|
21
|
+
try {
|
|
22
|
+
const content = fs.readFileSync(registryPath, "utf8");
|
|
23
|
+
return JSON.parse(content);
|
|
24
|
+
} catch {
|
|
25
|
+
return getDefaultRegistry();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Default registry fallback
|
|
30
|
+
function getDefaultRegistry() {
|
|
31
|
+
return {
|
|
32
|
+
commands: {
|
|
33
|
+
"fix-issue": {
|
|
34
|
+
triggers: ["fix issue", "fix bug", "resolve issue", "fix #"],
|
|
35
|
+
finishers: ["clean-copy"],
|
|
36
|
+
},
|
|
37
|
+
tdd: {
|
|
38
|
+
triggers: ["tdd mode", "test driven", "write tests first"],
|
|
39
|
+
},
|
|
40
|
+
review: {
|
|
41
|
+
triggers: ["review code", "code review", "check my code"],
|
|
42
|
+
is_finisher: true,
|
|
43
|
+
},
|
|
44
|
+
"clean-copy": {
|
|
45
|
+
triggers: ["clean commits", "clean history", "atomic commits"],
|
|
46
|
+
is_finisher: true,
|
|
47
|
+
finishers: ["review"],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
chains: {
|
|
51
|
+
"complete-fix": {
|
|
52
|
+
triggers: ["fix and review", "complete fix"],
|
|
53
|
+
sequence: ["fix-issue", "clean-copy", "review"],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
classification: {
|
|
57
|
+
confidence_threshold: 0.7,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Calculate match score between prompt and trigger
|
|
63
|
+
function matchScore(prompt, trigger) {
|
|
64
|
+
const normalizedPrompt = prompt.toLowerCase().trim();
|
|
65
|
+
const normalizedTrigger = trigger.toLowerCase().trim();
|
|
66
|
+
|
|
67
|
+
// Exact match
|
|
68
|
+
if (normalizedPrompt.includes(normalizedTrigger)) {
|
|
69
|
+
return 0.95;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Word-based matching
|
|
73
|
+
const promptWords = normalizedPrompt.split(/\s+/);
|
|
74
|
+
const triggerWords = normalizedTrigger.split(/\s+/);
|
|
75
|
+
|
|
76
|
+
let matchedWords = 0;
|
|
77
|
+
for (const tw of triggerWords) {
|
|
78
|
+
if (promptWords.some((pw) => pw.includes(tw) || tw.includes(pw))) {
|
|
79
|
+
matchedWords++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (matchedWords === triggerWords.length) {
|
|
84
|
+
return 0.85;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (matchedWords > 0) {
|
|
88
|
+
return 0.5 + (matchedWords / triggerWords.length) * 0.3;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Extract arguments from prompt
|
|
95
|
+
function extractArgs(prompt) {
|
|
96
|
+
const args = {};
|
|
97
|
+
|
|
98
|
+
// Extract issue numbers
|
|
99
|
+
const issueMatch = prompt.match(/#(\d+)/);
|
|
100
|
+
if (issueMatch) {
|
|
101
|
+
args.issue_number = issueMatch[1];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Extract branch names (common patterns)
|
|
105
|
+
const branchMatch = prompt.match(/branch[:\s]+([a-zA-Z0-9_\-/]+)/i);
|
|
106
|
+
if (branchMatch) {
|
|
107
|
+
args.branch_name = branchMatch[1];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return args;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Main classification function
|
|
114
|
+
function classify(prompt) {
|
|
115
|
+
const registry = loadRegistry();
|
|
116
|
+
const threshold = registry.classification?.confidence_threshold ?? 0.7;
|
|
117
|
+
|
|
118
|
+
let bestMatch = null;
|
|
119
|
+
let bestScore = 0;
|
|
120
|
+
|
|
121
|
+
// Check chains first (more specific)
|
|
122
|
+
for (const [chainName, chain] of Object.entries(registry.chains ?? {})) {
|
|
123
|
+
for (const trigger of chain.triggers ?? []) {
|
|
124
|
+
const score = matchScore(prompt, trigger);
|
|
125
|
+
if (score > bestScore) {
|
|
126
|
+
bestScore = score;
|
|
127
|
+
bestMatch = {
|
|
128
|
+
type: "chain",
|
|
129
|
+
name: chainName,
|
|
130
|
+
sequence: chain.sequence,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Check commands
|
|
137
|
+
for (const [cmdName, cmd] of Object.entries(registry.commands ?? {})) {
|
|
138
|
+
for (const trigger of cmd.triggers ?? []) {
|
|
139
|
+
const score = matchScore(prompt, trigger);
|
|
140
|
+
if (score > bestScore) {
|
|
141
|
+
bestScore = score;
|
|
142
|
+
bestMatch = {
|
|
143
|
+
type: "command",
|
|
144
|
+
name: cmdName,
|
|
145
|
+
finishers: cmd.finishers,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const args = extractArgs(prompt);
|
|
152
|
+
|
|
153
|
+
const result = {
|
|
154
|
+
prompt: prompt,
|
|
155
|
+
classification: {
|
|
156
|
+
match: bestMatch,
|
|
157
|
+
confidence: bestScore,
|
|
158
|
+
above_threshold: bestScore >= threshold,
|
|
159
|
+
args: args,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Add suggested execution if confidence is high enough
|
|
164
|
+
if (bestMatch && bestScore >= threshold) {
|
|
165
|
+
if (bestMatch.type === "chain") {
|
|
166
|
+
result.suggested_execution = {
|
|
167
|
+
workflow: bestMatch.name,
|
|
168
|
+
sequence: bestMatch.sequence,
|
|
169
|
+
first_command: `/${bestMatch.sequence[0]}${
|
|
170
|
+
args.issue_number ? " " + args.issue_number : ""
|
|
171
|
+
}`,
|
|
172
|
+
};
|
|
173
|
+
} else {
|
|
174
|
+
result.suggested_execution = {
|
|
175
|
+
command: `/${bestMatch.name}${
|
|
176
|
+
args.issue_number ? " " + args.issue_number : ""
|
|
177
|
+
}`,
|
|
178
|
+
finishers: bestMatch.finishers,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Read stdin as JSON (for hook input)
|
|
187
|
+
function readStdin() {
|
|
188
|
+
return new Promise((resolve) => {
|
|
189
|
+
let data = "";
|
|
190
|
+
process.stdin.setEncoding("utf8");
|
|
191
|
+
process.stdin.on("readable", () => {
|
|
192
|
+
let chunk;
|
|
193
|
+
while ((chunk = process.stdin.read()) !== null) {
|
|
194
|
+
data += chunk;
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
process.stdin.on("end", () => {
|
|
198
|
+
try {
|
|
199
|
+
resolve(JSON.parse(data));
|
|
200
|
+
} catch {
|
|
201
|
+
resolve(null);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// Timeout after 100ms if no stdin
|
|
205
|
+
setTimeout(() => resolve(null), 100);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// CLI entry point
|
|
210
|
+
if (require.main === module) {
|
|
211
|
+
// Check for command line argument first (manual testing)
|
|
212
|
+
const cliPrompt = process.argv[2];
|
|
213
|
+
|
|
214
|
+
if (cliPrompt) {
|
|
215
|
+
const result = classify(cliPrompt);
|
|
216
|
+
console.log(JSON.stringify(result, null, 2));
|
|
217
|
+
} else {
|
|
218
|
+
// Read from stdin (hook mode)
|
|
219
|
+
readStdin().then((input) => {
|
|
220
|
+
if (!input || !input.prompt) {
|
|
221
|
+
process.exit(0);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const result = classify(input.prompt);
|
|
225
|
+
|
|
226
|
+
// Output context for Claude if confidence is high
|
|
227
|
+
if (result.classification.above_threshold) {
|
|
228
|
+
const suggestion = result.suggested_execution;
|
|
229
|
+
if (suggestion) {
|
|
230
|
+
console.log(
|
|
231
|
+
`Intent detected: ${result.classification.match.name} (${Math.round(result.classification.confidence * 100)}% confidence). Suggested command: ${suggestion.command || suggestion.first_command}`,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
process.exit(0);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
module.exports = { classify, loadRegistry, matchScore };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"commands": {
|
|
3
|
+
"fix-issue": {
|
|
4
|
+
"description": "Fix a GitHub issue following TDD workflow",
|
|
5
|
+
"triggers": [
|
|
6
|
+
"fix issue",
|
|
7
|
+
"fix bug",
|
|
8
|
+
"resolve issue",
|
|
9
|
+
"close issue",
|
|
10
|
+
"fix #",
|
|
11
|
+
"resolve #"
|
|
12
|
+
],
|
|
13
|
+
"finishers": ["clean-copy"]
|
|
14
|
+
},
|
|
15
|
+
"review": {
|
|
16
|
+
"description": "Run code review checklist",
|
|
17
|
+
"triggers": [
|
|
18
|
+
"review code",
|
|
19
|
+
"code review",
|
|
20
|
+
"check my code",
|
|
21
|
+
"review changes",
|
|
22
|
+
"review pr"
|
|
23
|
+
],
|
|
24
|
+
"is_finisher": true
|
|
25
|
+
},
|
|
26
|
+
"clean-copy": {
|
|
27
|
+
"description": "Restructure commits into clean, reviewable history",
|
|
28
|
+
"triggers": [
|
|
29
|
+
"clean commits",
|
|
30
|
+
"clean history",
|
|
31
|
+
"atomic commits",
|
|
32
|
+
"clean copy",
|
|
33
|
+
"restructure commits"
|
|
34
|
+
],
|
|
35
|
+
"is_finisher": true,
|
|
36
|
+
"finishers": ["review"]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"chains": {
|
|
40
|
+
"complete-fix": {
|
|
41
|
+
"description": "Full issue fix workflow with clean commits and review",
|
|
42
|
+
"triggers": ["fix and review", "complete fix", "full fix"],
|
|
43
|
+
"sequence": ["fix-issue", "clean-copy", "review"]
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"classification": {
|
|
47
|
+
"confidence_threshold": 0.7
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npm run lint)",
|
|
5
|
+
"Bash(npm run test)",
|
|
6
|
+
"Bash(npm run typecheck)",
|
|
7
|
+
"Bash(pnpm lint)",
|
|
8
|
+
"Bash(pnpm test)",
|
|
9
|
+
"Bash(pnpm typecheck)",
|
|
10
|
+
"Bash(git status)",
|
|
11
|
+
"Bash(git diff*)",
|
|
12
|
+
"Bash(git log*)",
|
|
13
|
+
"Bash(git branch*)",
|
|
14
|
+
"Bash(git checkout*)",
|
|
15
|
+
"Bash(git commit*)",
|
|
16
|
+
"Bash(gh pr create*)",
|
|
17
|
+
"Command(clean-copy)",
|
|
18
|
+
"Command(review)"
|
|
19
|
+
],
|
|
20
|
+
"deny": ["Bash(git push --force*)", "Bash(rm -rf*)"]
|
|
21
|
+
},
|
|
22
|
+
"hooks": {
|
|
23
|
+
"UserPromptSubmit": [
|
|
24
|
+
{
|
|
25
|
+
"matcher": "",
|
|
26
|
+
"hooks": [
|
|
27
|
+
{
|
|
28
|
+
"type": "command",
|
|
29
|
+
"command": "node .claude/router/classify.js \"$CLAUDE_PROMPT\""
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"PreToolUse": [
|
|
35
|
+
{
|
|
36
|
+
"matcher": "Edit",
|
|
37
|
+
"hooks": [
|
|
38
|
+
{
|
|
39
|
+
"type": "command",
|
|
40
|
+
"command": "node -e \"if (process.argv[1]?.includes('.env')) { console.log('BLOCKED: Cannot edit .env files'); process.exit(1); }\" -- \"$CLAUDE_FILE_PATH\""
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"matcher": "Write",
|
|
46
|
+
"hooks": [
|
|
47
|
+
{
|
|
48
|
+
"type": "command",
|
|
49
|
+
"command": "node -e \"if (process.argv[1]?.includes('.env')) { console.log('BLOCKED: Cannot edit .env files'); process.exit(1); }\" -- \"$CLAUDE_FILE_PATH\""
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"PostToolUse": [
|
|
55
|
+
{
|
|
56
|
+
"matcher": "Edit",
|
|
57
|
+
"hooks": [
|
|
58
|
+
{
|
|
59
|
+
"type": "command",
|
|
60
|
+
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" && npx eslint --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"matcher": "Write",
|
|
66
|
+
"hooks": [
|
|
67
|
+
{
|
|
68
|
+
"type": "command",
|
|
69
|
+
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" && npx eslint --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
"extraKnownMarketplaces": {
|
|
76
|
+
"anthropics-skills": {
|
|
77
|
+
"source": {
|
|
78
|
+
"source": "github",
|
|
79
|
+
"repo": "anthropics/skills"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"anthropics-plugins": {
|
|
83
|
+
"source": {
|
|
84
|
+
"source": "github",
|
|
85
|
+
"repo": "anthropics/claude-code-plugins"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"vercel-labs": {
|
|
89
|
+
"source": {
|
|
90
|
+
"source": "github",
|
|
91
|
+
"repo": "vercel-labs/agent-skills"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"better-auth": {
|
|
95
|
+
"source": {
|
|
96
|
+
"source": "github",
|
|
97
|
+
"repo": "better-auth/skills"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"enabledPlugins": {
|
|
102
|
+
"frontend-design@anthropics-skills": true,
|
|
103
|
+
"commit-commands@anthropics-plugins": true,
|
|
104
|
+
"pr-review-toolkit@anthropics-plugins": true,
|
|
105
|
+
"code-simplifier@anthropics-plugins": true,
|
|
106
|
+
"create-auth-skill@better-auth": true,
|
|
107
|
+
"agent-browser@vercel-labs": true,
|
|
108
|
+
"github-cli@vercel-labs": true,
|
|
109
|
+
"skill-creator@vercel-labs": true,
|
|
110
|
+
"vercel-react-best-practices@vercel-labs": true,
|
|
111
|
+
"web-design-guidelines@vercel-labs": true
|
|
112
|
+
}
|
|
113
|
+
}
|