@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.
Files changed (32) hide show
  1. package/README.md +212 -0
  2. package/package.json +39 -0
  3. package/src/cli.mjs +614 -0
  4. package/templates/.claude/agents/code-simplifier.md +52 -0
  5. package/templates/.claude/commands/auto.md +85 -0
  6. package/templates/.claude/commands/clean-copy.md +93 -0
  7. package/templates/.claude/commands/fix-issue.md +34 -0
  8. package/templates/.claude/commands/review.md +46 -0
  9. package/templates/.claude/router/classify.js +241 -0
  10. package/templates/.claude/router/registry.json +49 -0
  11. package/templates/.claude/settings.json +113 -0
  12. package/templates/.claude/skills/api-design/SKILL.md +77 -0
  13. package/templates/.claude/skills/security-review/SKILL.md +65 -0
  14. package/templates/.codex/config.toml +31 -0
  15. package/templates/.codex/skills/api-design/SKILL.md +77 -0
  16. package/templates/.codex/skills/security-review/SKILL.md +65 -0
  17. package/templates/.cursor/commands/auto.md +55 -0
  18. package/templates/.cursor/commands/clean-copy.md +80 -0
  19. package/templates/.cursor/commands/code-simplifier.md +28 -0
  20. package/templates/.cursor/commands/fix-issue.md +28 -0
  21. package/templates/.cursor/commands/review.md +41 -0
  22. package/templates/.cursor/hooks.json +11 -0
  23. package/templates/.cursor/rules/api-design.mdc +80 -0
  24. package/templates/.cursor/rules/git-workflow.mdc +73 -0
  25. package/templates/.cursor/rules/security.mdc +69 -0
  26. package/templates/.cursor/rules/tdd.mdc +35 -0
  27. package/templates/.cursor/rules/typescript.mdc +82 -0
  28. package/templates/.cursorignore.template +20 -0
  29. package/templates/.gitignore.template +10 -0
  30. package/templates/.mcp.json +16 -0
  31. package/templates/AGENTS.md +118 -0
  32. 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
+ }