claude-toolkit 0.1.9

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 (85) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +126 -0
  4. package/bin/cli.ts +112 -0
  5. package/core/agents/ct-code-reviewer.md +123 -0
  6. package/core/agents/ct-github-workflow.md +137 -0
  7. package/core/commands/ct/code-quality.md +59 -0
  8. package/core/commands/ct/onboard.md +84 -0
  9. package/core/commands/ct/pr-review.md +104 -0
  10. package/core/commands/ct/pr-summary.md +59 -0
  11. package/core/commands/ct/proto-check.md +74 -0
  12. package/core/commands/ct/ticket.md +71 -0
  13. package/core/hooks/skill-eval.js +381 -0
  14. package/core/hooks/skill-eval.sh +35 -0
  15. package/core/hooks/skill-rules.schema.json +112 -0
  16. package/core/skills/systematic-debugging/SKILL.md +44 -0
  17. package/core/skills/testing-patterns/SKILL.md +52 -0
  18. package/core/skills/typescript-conventions/SKILL.md +57 -0
  19. package/core/skills/verification-before-completion/SKILL.md +42 -0
  20. package/docs/README.md +49 -0
  21. package/docs/agents/code-reviewer.md +76 -0
  22. package/docs/agents/github-workflow.md +98 -0
  23. package/docs/best-practices/solidjs/README.md +43 -0
  24. package/docs/best-practices/solidjs/anti-patterns.md +166 -0
  25. package/docs/best-practices/solidjs/component-patterns.md +131 -0
  26. package/docs/best-practices/solidjs/context-and-global-state.md +131 -0
  27. package/docs/best-practices/solidjs/control-flow.md +124 -0
  28. package/docs/best-practices/solidjs/data-fetching.md +205 -0
  29. package/docs/best-practices/solidjs/effects-and-lifecycle.md +113 -0
  30. package/docs/best-practices/solidjs/performance.md +100 -0
  31. package/docs/best-practices/solidjs/props-patterns.md +100 -0
  32. package/docs/best-practices/solidjs/reactivity-model.md +104 -0
  33. package/docs/best-practices/solidjs/signals-and-state.md +78 -0
  34. package/docs/best-practices/solidjs/stores-and-nested-state.md +111 -0
  35. package/docs/best-practices/solidjs/typescript-integration.md +186 -0
  36. package/docs/best-practices/typescript/README.md +45 -0
  37. package/docs/best-practices/typescript/any-and-unknown.md +73 -0
  38. package/docs/best-practices/typescript/deriving-vs-decoupling.md +83 -0
  39. package/docs/best-practices/typescript/discriminated-unions.md +75 -0
  40. package/docs/best-practices/typescript/enums-alternatives.md +72 -0
  41. package/docs/best-practices/typescript/essential-patterns.md +119 -0
  42. package/docs/best-practices/typescript/generics-patterns.md +105 -0
  43. package/docs/best-practices/typescript/micro-opinions.md +87 -0
  44. package/docs/best-practices/typescript/runtime-validation.md +62 -0
  45. package/docs/best-practices/typescript/satisfies-operator.md +100 -0
  46. package/docs/best-practices/typescript/tsconfig-cheat-sheet.md +129 -0
  47. package/docs/best-practices/typescript/type-organization.md +64 -0
  48. package/docs/best-practices/typescript/type-vs-interface.md +80 -0
  49. package/docs/commands/code-quality.md +42 -0
  50. package/docs/commands/onboard.md +72 -0
  51. package/docs/commands/pr-review.md +102 -0
  52. package/docs/commands/pr-summary.md +50 -0
  53. package/docs/commands/proto-check.md +59 -0
  54. package/docs/commands/ticket.md +56 -0
  55. package/docs/skills/systematic-debugging.md +70 -0
  56. package/docs/skills/testing-patterns.md +89 -0
  57. package/docs/skills/typescript-conventions.md +137 -0
  58. package/docs/skills/verification-before-completion.md +91 -0
  59. package/docs/stacks/cloudflare-d1-kv.md +110 -0
  60. package/docs/stacks/i18n-typesafe.md +141 -0
  61. package/docs/stacks/protobuf-contracts.md +85 -0
  62. package/docs/stacks/rust-wasm-patterns.md +106 -0
  63. package/docs/stacks/solidjs-patterns.md +110 -0
  64. package/docs/stacks/vanilla-extract-patterns.md +115 -0
  65. package/package.json +58 -0
  66. package/src/generator.ts +317 -0
  67. package/src/index.ts +30 -0
  68. package/src/types.ts +85 -0
  69. package/src/utils.ts +53 -0
  70. package/stacks/cloudflare/skills/cloudflare-d1-kv/SKILL.md +84 -0
  71. package/stacks/cloudflare/stack.json +26 -0
  72. package/stacks/i18n-typesafe/skills/i18n-typesafe/SKILL.md +64 -0
  73. package/stacks/i18n-typesafe/stack.json +25 -0
  74. package/stacks/protobuf/skills/protobuf-contracts/SKILL.md +78 -0
  75. package/stacks/protobuf/stack.json +25 -0
  76. package/stacks/rust-wasm/skills/rust-wasm-patterns/SKILL.md +76 -0
  77. package/stacks/rust-wasm/stack.json +26 -0
  78. package/stacks/solidjs/skills/solidjs-patterns/SKILL.md +66 -0
  79. package/stacks/solidjs/stack.json +52 -0
  80. package/stacks/vanilla-extract/skills/vanilla-extract-patterns/SKILL.md +76 -0
  81. package/stacks/vanilla-extract/stack.json +40 -0
  82. package/templates/claude-toolkit.config.ts +34 -0
  83. package/templates/configs/biome.base.json +35 -0
  84. package/templates/configs/tsconfig.base.json +16 -0
  85. package/templates/skill-rules.base.json +98 -0
@@ -0,0 +1,104 @@
1
+ ---
2
+ description: "Review a pull request using project standards"
3
+ allowed-tools:
4
+ - Bash
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ ---
9
+
10
+ # Pull Request Review
11
+
12
+ Perform a checklist-based code review on the current PR or a specified PR number. Evaluate against project standards and common quality criteria.
13
+
14
+ ## Workflow
15
+
16
+ 1. **Get PR context.** If a PR number is provided, fetch it with `gh pr view {number} --json title,body,files,commits`. Otherwise, diff the current branch against the base branch (`main` or `master`).
17
+
18
+ 2. **Read all changed files** in full to understand the complete context of the change. Do not review diffs in isolation — understand what the surrounding code does.
19
+
20
+ 3. **Run the review checklist** against every changed file.
21
+
22
+ 4. **Compile findings** into a structured review.
23
+
24
+ ## Review Checklist
25
+
26
+ ### Logic Correctness
27
+ - Are conditionals and branches correct? Any off-by-one errors?
28
+ - Are edge cases handled (empty inputs, null values, boundary conditions)?
29
+ - Does the control flow match the intended behavior?
30
+ - Are there any unreachable code paths?
31
+
32
+ ### Type Safety
33
+ - Are types precise (no `any`, no unsafe casts, no overly broad unions)?
34
+ - Is type narrowing used correctly before accessing properties?
35
+ - Are generic constraints appropriate?
36
+ - Are return types explicit where they should be?
37
+
38
+ ### Error Handling
39
+ - Are errors caught and handled meaningfully (not swallowed)?
40
+ - Do error messages provide enough context for debugging?
41
+ - Are error boundaries or fallbacks in place where needed?
42
+ - Is cleanup logic (finally blocks, defer, etc.) correct?
43
+
44
+ ### Test Coverage
45
+ - Are new behaviors covered by tests?
46
+ - Do tests focus on behavior, not implementation details?
47
+ - Are edge cases and error paths tested?
48
+ - Are test descriptions clear and descriptive?
49
+
50
+ ### Performance
51
+ - Any unnecessary re-renders, recomputations, or allocations?
52
+ - Any N+1 query patterns or missing pagination?
53
+ - Any missing memoization for expensive operations?
54
+ - Any potential memory leaks (unclosed resources, dangling listeners)?
55
+
56
+ ### Security
57
+ - Any injection vulnerabilities (SQL, XSS, command injection)?
58
+ - Are user inputs validated and sanitized?
59
+ - Are auth checks present on protected operations?
60
+ - Are secrets or sensitive data properly handled (not logged, not exposed)?
61
+
62
+ ### Code Style
63
+ - Does naming follow project conventions?
64
+ - Is the code readable without excessive comments?
65
+ - Are abstractions at the right level (not over- or under-engineered)?
66
+ - Is there unnecessary duplication?
67
+
68
+ ## Output Format
69
+
70
+ ```markdown
71
+ ## PR Review: {title}
72
+
73
+ **Branch:** {branch} -> {base}
74
+ **Files changed:** {count}
75
+ **Verdict:** {APPROVE | REQUEST_CHANGES | COMMENT}
76
+
77
+ ### Critical Issues
78
+ > Must be fixed before merge.
79
+
80
+ - **[CRITICAL]** {file}:{line} - {description}
81
+
82
+ ### Warnings
83
+ > Should be addressed, but not blocking.
84
+
85
+ - **[WARNING]** {file}:{line} - {description}
86
+
87
+ ### Suggestions
88
+ > Nice-to-have improvements.
89
+
90
+ - **[SUGGESTION]** {file}:{line} - {description}
91
+
92
+ ### Positive Notes
93
+ - {things done well}
94
+
95
+ ### Summary
96
+ {1-3 sentence overall assessment}
97
+ ```
98
+
99
+ ## Notes
100
+
101
+ - Be specific. Reference file names and line numbers.
102
+ - Distinguish between opinion and objective issues.
103
+ - Acknowledge good patterns, not just problems.
104
+ - If the PR is too large to review effectively, say so and suggest splitting it.
@@ -0,0 +1,59 @@
1
+ ---
2
+ description: "Generate a PR summary from the current branch"
3
+ allowed-tools:
4
+ - Bash
5
+ - Read
6
+ ---
7
+
8
+ # PR Summary Generator
9
+
10
+ Generate a structured pull request summary by analyzing the diff and commit history of the current branch against its base.
11
+
12
+ ## Workflow
13
+
14
+ 1. **Identify the base branch.** Check for `main` or `master`. Use `git merge-base` to find the common ancestor.
15
+
16
+ 2. **Gather the diff.** Run `git diff {base}...HEAD --stat` for an overview and `git diff {base}...HEAD` for full changes.
17
+
18
+ 3. **Gather commit history.** Run `git log {base}...HEAD --oneline --no-merges` to understand the progression of changes.
19
+
20
+ 4. **Analyze changes** by reading modified files to understand the "why" behind each change. Group related changes together.
21
+
22
+ 5. **Generate the summary.**
23
+
24
+ ## Output Format
25
+
26
+ ```markdown
27
+ ## Summary
28
+
29
+ {1-3 bullet points describing the high-level purpose of this PR}
30
+
31
+ ## What Changed
32
+
33
+ ### {Category 1} (e.g., "Authentication", "Database", "UI")
34
+ - `{file}` - {what changed and why}
35
+ - `{file}` - {what changed and why}
36
+
37
+ ### {Category 2}
38
+ - ...
39
+
40
+ ## Impact Assessment
41
+
42
+ - **Risk level:** {low | medium | high}
43
+ - **Affected areas:** {list of features or systems impacted}
44
+ - **Breaking changes:** {none, or describe}
45
+ - **Migration needed:** {none, or describe}
46
+
47
+ ## Testing Notes
48
+
49
+ - {How to test this change}
50
+ - {Key scenarios to verify}
51
+ - {Any manual testing required}
52
+ ```
53
+
54
+ ## Notes
55
+
56
+ - Infer the "why" from commit messages, code comments, and the nature of changes. Do not just list file names.
57
+ - Group related file changes under meaningful categories, not one-file-per-bullet.
58
+ - Be honest about risk level. If you see potential issues, flag them in Testing Notes.
59
+ - Keep it concise. The summary should be scannable in under 60 seconds.
@@ -0,0 +1,74 @@
1
+ ---
2
+ description: "Validate protobuf definitions and check for breaking changes"
3
+ allowed-tools:
4
+ - Bash
5
+ - Read
6
+ - Glob
7
+ - Grep
8
+ ---
9
+
10
+ # Protobuf Validation
11
+
12
+ Validate protobuf definitions for correctness, lint compliance, and backward compatibility. Regenerate types and verify the generated code compiles.
13
+
14
+ ## Workflow
15
+
16
+ 1. **Find proto files.** Locate all `.proto` files in the project. Identify the buf configuration (`buf.yaml`, `buf.gen.yaml`) or other protobuf tooling in use.
17
+
18
+ 2. **Run lint checks.** Execute `buf lint` (or the project-configured linter) against proto definitions. Report any style or correctness violations.
19
+
20
+ 3. **Check for breaking changes.** Run `buf breaking --against .git#branch=main` (or equivalent) to detect backward-incompatible changes. Common breaking changes include:
21
+ - Removing or renaming fields
22
+ - Changing field numbers
23
+ - Changing field types
24
+ - Removing services or RPCs
25
+ - Changing RPC signatures
26
+
27
+ 4. **Regenerate types.** Run `buf generate` (or the project-configured generation command) to regenerate code from proto definitions.
28
+
29
+ 5. **Verify generated code compiles.** Run the project's typecheck or build command to ensure the regenerated code is valid and integrates correctly with the rest of the codebase.
30
+
31
+ 6. **Report results.**
32
+
33
+ ## Output Format
34
+
35
+ ```markdown
36
+ ## Protobuf Validation Report
37
+
38
+ **Proto files found:** {count}
39
+ **Buf config:** {path or "not found"}
40
+
41
+ ### Lint Results
42
+ - **Status:** {pass | fail}
43
+ - **Issues:** {count}
44
+
45
+ | File | Line | Rule | Message |
46
+ |------|------|------|---------|
47
+ | ... | ... | ... | ... |
48
+
49
+ ### Breaking Change Check
50
+ - **Status:** {pass | fail}
51
+ - **Against:** {branch or reference}
52
+ - **Breaking changes found:** {count}
53
+
54
+ | File | Change | Description |
55
+ |------|--------|-------------|
56
+ | ... | ... | ... |
57
+
58
+ ### Code Generation
59
+ - **Status:** {success | failure}
60
+ - **Files generated:** {count}
61
+
62
+ ### Compilation Check
63
+ - **Status:** {pass | fail}
64
+ - **Errors:** {if any}
65
+
66
+ ### Summary
67
+ {Overall status and recommended actions}
68
+ ```
69
+
70
+ ## Notes
71
+
72
+ - If `buf` is not installed, check for alternative protobuf tooling (`protoc`, `grpc_tools`, etc.) before reporting failure.
73
+ - If no proto files are found, report that clearly rather than failing silently.
74
+ - Breaking changes are not always wrong — they just need to be intentional. Flag them for human review rather than treating them as errors.
@@ -0,0 +1,71 @@
1
+ ---
2
+ description: "Work end-to-end on a ticket or issue"
3
+ allowed-tools:
4
+ - Bash
5
+ - Read
6
+ - Write
7
+ - Edit
8
+ - Glob
9
+ - Grep
10
+ ---
11
+
12
+ # Ticket Workflow
13
+
14
+ Work on a ticket or issue end-to-end: understand it, explore the codebase, plan the implementation, build it, test it, and prepare a PR.
15
+
16
+ ## Workflow
17
+
18
+ ### Phase 1: Understand
19
+
20
+ 1. **Read the ticket.** If a GitHub issue number is provided, fetch it with `gh issue view {number}`. Otherwise, use the description provided by the user.
21
+
22
+ 2. **Clarify requirements.** Identify acceptance criteria, edge cases, and constraints. If anything is ambiguous, ask before proceeding.
23
+
24
+ 3. **Identify scope.** What needs to change? What should NOT change? Are there related tickets or dependencies?
25
+
26
+ ### Phase 2: Explore
27
+
28
+ 4. **Find relevant code.** Search for files, functions, and patterns related to the ticket. Read them fully to understand the current behavior.
29
+
30
+ 5. **Understand the test landscape.** Find existing tests for the affected area. Note the testing framework, patterns, and coverage.
31
+
32
+ 6. **Check for related changes.** Look at recent commits or PRs in the affected area for context.
33
+
34
+ ### Phase 3: Plan
35
+
36
+ 7. **Draft an implementation plan.** List the specific changes needed, in order:
37
+ - Files to create or modify
38
+ - Functions to add or change
39
+ - Tests to write
40
+ - Migrations or config changes needed
41
+
42
+ 8. **Share the plan with the user** and get confirmation before proceeding. If the change is small and obvious, proceed directly.
43
+
44
+ ### Phase 4: Implement
45
+
46
+ 9. **Create a feature branch** following project conventions (e.g., `feat/description`, `fix/description`).
47
+
48
+ 10. **Write tests first** when applicable (TDD). Write failing tests that describe the desired behavior, then implement to make them pass.
49
+
50
+ 11. **Implement the changes.** Follow project conventions for code style, error handling, and naming. Make focused, atomic changes.
51
+
52
+ 12. **Run quality checks.** Run lint, typecheck, and tests. Fix any issues introduced by the changes.
53
+
54
+ ### Phase 5: Deliver
55
+
56
+ 13. **Commit with conventional commit messages.** Group related changes into logical commits.
57
+
58
+ 14. **Create a PR** with a clear title and description. Include:
59
+ - Summary of what changed and why
60
+ - How to test
61
+ - Any follow-up work needed
62
+
63
+ 15. **Report back** with the PR link and a summary of what was done.
64
+
65
+ ## Notes
66
+
67
+ - Always ask before making architectural decisions (new tables, new services, changing frameworks).
68
+ - Do not gold-plate. Implement what the ticket asks for, nothing more.
69
+ - If the ticket is too large for a single PR, propose splitting it and implement the first piece.
70
+ - If you discover bugs or issues outside the ticket scope, note them but do not fix them unless they block the ticket.
71
+ - Prefer small, reviewable PRs over large monolithic ones.
@@ -0,0 +1,381 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Skill Evaluation Engine v2.0
4
+ *
5
+ * Intelligent skill activation based on:
6
+ * - Keywords and patterns in prompts
7
+ * - File paths mentioned or being edited
8
+ * - Directory mappings
9
+ * - Intent detection
10
+ * - Content pattern matching
11
+ *
12
+ * Outputs a structured reminder with matched skills and reasons.
13
+ */
14
+
15
+ const fs = require("node:fs");
16
+ const path = require("node:path");
17
+
18
+ // Configuration
19
+ const RULES_PATH = path.join(__dirname, "skill-rules.json");
20
+
21
+ /**
22
+ * @typedef {Object} SkillMatch
23
+ * @property {string} name - Skill name
24
+ * @property {number} score - Confidence score
25
+ * @property {string[]} reasons - Why this skill was matched
26
+ * @property {number} priority - Skill priority
27
+ */
28
+
29
+ /**
30
+ * Load skill rules from JSON file
31
+ * @returns {Object} Parsed skill rules
32
+ */
33
+ function loadRules() {
34
+ try {
35
+ const content = fs.readFileSync(RULES_PATH, "utf-8");
36
+ return JSON.parse(content);
37
+ } catch (error) {
38
+ console.error(`Failed to load skill rules: ${error.message}`);
39
+ process.exit(0);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Extract file paths mentioned in the prompt
45
+ * @param {string} prompt - User's prompt text
46
+ * @returns {string[]} Array of detected file paths
47
+ */
48
+ function extractFilePaths(prompt) {
49
+ const paths = new Set();
50
+
51
+ // Match explicit paths with extensions
52
+ const extensionPattern =
53
+ /(?:^|\s|["'`])([\w\-./]+\.(?:[tj]sx?|json|gql|ya?ml|md|sh|rs|proto|toml|css\.ts|wasm))\b/gi;
54
+ for (const match of prompt.matchAll(extensionPattern)) {
55
+ paths.add(match[1]);
56
+ }
57
+
58
+ // Match paths starting with common directories
59
+ const dirPattern =
60
+ /(?:^|\s|["'`])((?:src|app|components|worker|workers|proto|hooks|utils|services|styles|locales|tests|\.claude|\.github)\/[\w\-./]+)/gi;
61
+ for (const match of prompt.matchAll(dirPattern)) {
62
+ paths.add(match[1]);
63
+ }
64
+
65
+ // Match quoted paths
66
+ const quotedPattern = /["'`]([\w\-./]+\/[\w\-./]+)["'`]/g;
67
+ for (const match of prompt.matchAll(quotedPattern)) {
68
+ paths.add(match[1]);
69
+ }
70
+
71
+ return Array.from(paths);
72
+ }
73
+
74
+ /**
75
+ * Check if a pattern matches the text
76
+ * @param {string} text - Text to search in
77
+ * @param {string} pattern - Regex pattern
78
+ * @param {string} flags - Regex flags
79
+ * @returns {boolean}
80
+ */
81
+ function matchesPattern(text, pattern, flags = "i") {
82
+ try {
83
+ const regex = new RegExp(pattern, flags);
84
+ return regex.test(text);
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Check if a glob pattern matches a file path
92
+ * @param {string} filePath - File path to check
93
+ * @param {string} globPattern - Glob pattern (simplified)
94
+ * @returns {boolean}
95
+ */
96
+ function matchesGlob(filePath, globPattern) {
97
+ const regexPattern = globPattern
98
+ .replace(/\./g, "\\.")
99
+ .replace(/\*\*\//g, "<<<DOUBLESTARSLASH>>>")
100
+ .replace(/\*\*/g, "<<<DOUBLESTAR>>>")
101
+ .replace(/\*/g, "[^/]*")
102
+ .replace(/<<<DOUBLESTARSLASH>>>/g, "(.*\\/)?")
103
+ .replace(/<<<DOUBLESTAR>>>/g, ".*")
104
+ .replace(/\?/g, ".");
105
+
106
+ try {
107
+ const regex = new RegExp(`^${regexPattern}$`, "i");
108
+ return regex.test(filePath);
109
+ } catch {
110
+ return false;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Check if file path matches any directory mapping
116
+ * @param {string} filePath - File path to check
117
+ * @param {Object} mappings - Directory to skill mappings
118
+ * @returns {string|null} Matched skill name or null
119
+ */
120
+ function matchDirectoryMapping(filePath, mappings) {
121
+ for (const [dir, skillName] of Object.entries(mappings)) {
122
+ if (filePath === dir || filePath.startsWith(`${dir}/`)) {
123
+ return skillName;
124
+ }
125
+ }
126
+ return null;
127
+ }
128
+
129
+ /**
130
+ * Evaluate a single skill against the prompt and context
131
+ */
132
+ function evaluateSkill(
133
+ skillName,
134
+ skill,
135
+ prompt,
136
+ promptLower,
137
+ filePaths,
138
+ rules,
139
+ ) {
140
+ const { triggers = {}, excludePatterns = [], priority = 5 } = skill;
141
+ const scoring = rules.scoring;
142
+
143
+ let score = 0;
144
+ const reasons = [];
145
+
146
+ // Check exclude patterns first
147
+ for (const excludePattern of excludePatterns) {
148
+ if (matchesPattern(promptLower, excludePattern)) {
149
+ return null;
150
+ }
151
+ }
152
+
153
+ // 1. Check keywords
154
+ if (triggers.keywords) {
155
+ for (const keyword of triggers.keywords) {
156
+ if (promptLower.includes(keyword.toLowerCase())) {
157
+ score += scoring.keyword;
158
+ reasons.push(`keyword "${keyword}"`);
159
+ }
160
+ }
161
+ }
162
+
163
+ // 2. Check keyword patterns (regex)
164
+ if (triggers.keywordPatterns) {
165
+ for (const pattern of triggers.keywordPatterns) {
166
+ if (matchesPattern(promptLower, pattern)) {
167
+ score += scoring.keywordPattern;
168
+ reasons.push(`pattern /${pattern}/`);
169
+ }
170
+ }
171
+ }
172
+
173
+ // 3. Check intent patterns
174
+ if (triggers.intentPatterns) {
175
+ for (const pattern of triggers.intentPatterns) {
176
+ if (matchesPattern(promptLower, pattern)) {
177
+ score += scoring.intentPattern;
178
+ reasons.push(`intent detected`);
179
+ break;
180
+ }
181
+ }
182
+ }
183
+
184
+ // 4. Check context patterns
185
+ if (triggers.contextPatterns) {
186
+ for (const pattern of triggers.contextPatterns) {
187
+ if (promptLower.includes(pattern.toLowerCase())) {
188
+ score += scoring.contextPattern;
189
+ reasons.push(`context "${pattern}"`);
190
+ }
191
+ }
192
+ }
193
+
194
+ // 5. Check file paths against path patterns
195
+ if (triggers.pathPatterns && filePaths.length > 0) {
196
+ for (const filePath of filePaths) {
197
+ for (const pattern of triggers.pathPatterns) {
198
+ if (matchesGlob(filePath, pattern)) {
199
+ score += scoring.pathPattern;
200
+ reasons.push(`path "${filePath}"`);
201
+ break;
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ // 6. Check directory mappings
208
+ if (rules.directoryMappings && filePaths.length > 0) {
209
+ for (const filePath of filePaths) {
210
+ const mappedSkill = matchDirectoryMapping(
211
+ filePath,
212
+ rules.directoryMappings,
213
+ );
214
+ if (mappedSkill === skillName) {
215
+ score += scoring.directoryMatch;
216
+ reasons.push(`directory mapping`);
217
+ break;
218
+ }
219
+ }
220
+ }
221
+
222
+ // 7. Check content patterns in prompt (for code snippets)
223
+ if (triggers.contentPatterns) {
224
+ for (const pattern of triggers.contentPatterns) {
225
+ if (matchesPattern(prompt, pattern)) {
226
+ score += scoring.contentPattern;
227
+ reasons.push(`code pattern detected`);
228
+ break;
229
+ }
230
+ }
231
+ }
232
+
233
+ if (score > 0) {
234
+ return { name: skillName, score, reasons: [...new Set(reasons)], priority };
235
+ }
236
+
237
+ return null;
238
+ }
239
+
240
+ /**
241
+ * Get related skills that should also be suggested
242
+ */
243
+ function getRelatedSkills(matches, skills) {
244
+ const matchedNames = new Set(matches.map((m) => m.name));
245
+ const related = new Set();
246
+
247
+ for (const match of matches) {
248
+ const skill = skills[match.name];
249
+ if (skill?.relatedSkills) {
250
+ for (const relatedName of skill.relatedSkills) {
251
+ if (!matchedNames.has(relatedName)) {
252
+ related.add(relatedName);
253
+ }
254
+ }
255
+ }
256
+ }
257
+
258
+ return Array.from(related);
259
+ }
260
+
261
+ /**
262
+ * Format confidence level based on score
263
+ */
264
+ function formatConfidence(score, minScore) {
265
+ if (score >= minScore * 3) return "HIGH";
266
+ if (score >= minScore * 2) return "MEDIUM";
267
+ return "LOW";
268
+ }
269
+
270
+ /**
271
+ * Main evaluation function
272
+ */
273
+ function evaluate(prompt) {
274
+ const rules = loadRules();
275
+ const { config, skills } = rules;
276
+
277
+ const promptLower = prompt.toLowerCase();
278
+ const filePaths = extractFilePaths(prompt);
279
+
280
+ const matches = [];
281
+ for (const [name, skill] of Object.entries(skills)) {
282
+ const match = evaluateSkill(
283
+ name,
284
+ skill,
285
+ prompt,
286
+ promptLower,
287
+ filePaths,
288
+ rules,
289
+ );
290
+ if (match && match.score >= config.minConfidenceScore) {
291
+ matches.push(match);
292
+ }
293
+ }
294
+
295
+ if (matches.length === 0) {
296
+ return "";
297
+ }
298
+
299
+ matches.sort((a, b) => {
300
+ if (b.score !== a.score) return b.score - a.score;
301
+ return b.priority - a.priority;
302
+ });
303
+
304
+ const topMatches = matches.slice(0, config.maxSkillsToShow);
305
+ const relatedSkills = getRelatedSkills(topMatches, skills);
306
+
307
+ let output = "<user-prompt-submit-hook>\n";
308
+ output += "SKILL ACTIVATION REQUIRED\n\n";
309
+
310
+ if (filePaths.length > 0) {
311
+ output += `Detected file paths: ${filePaths.join(", ")}\n\n`;
312
+ }
313
+
314
+ output += "Matched skills (ranked by relevance):\n";
315
+
316
+ for (let i = 0; i < topMatches.length; i++) {
317
+ const match = topMatches[i];
318
+ const confidence = formatConfidence(match.score, config.minConfidenceScore);
319
+ output += `${i + 1}. ${match.name} (${confidence} confidence)\n`;
320
+ if (config.showMatchReasons && match.reasons.length > 0) {
321
+ output += ` Matched: ${match.reasons.slice(0, 3).join(", ")}\n`;
322
+ }
323
+ }
324
+
325
+ if (relatedSkills.length > 0) {
326
+ output += `\nRelated skills to consider: ${relatedSkills.join(", ")}\n`;
327
+ }
328
+
329
+ output += "\nBefore implementing, you MUST:\n";
330
+ output += "1. EVALUATE: State YES/NO for each skill with brief reasoning\n";
331
+ output += "2. ACTIVATE: Invoke the Skill tool for each YES skill\n";
332
+ output += "3. IMPLEMENT: Only proceed after skill activation\n";
333
+ output += "\nExample evaluation:\n";
334
+ output += `- ${topMatches[0].name}: YES - [your reasoning]\n`;
335
+ if (topMatches.length > 1) {
336
+ output += `- ${topMatches[1].name}: NO - [your reasoning]\n`;
337
+ }
338
+ output += "\nDO NOT skip this step. Invoke relevant skills NOW.\n";
339
+ output += "</user-prompt-submit-hook>";
340
+
341
+ return output;
342
+ }
343
+
344
+ // Main execution
345
+ function main() {
346
+ let input = "";
347
+
348
+ process.stdin.setEncoding("utf8");
349
+
350
+ process.stdin.on("data", (chunk) => {
351
+ input += chunk;
352
+ });
353
+
354
+ process.stdin.on("end", () => {
355
+ let prompt = "";
356
+
357
+ try {
358
+ const data = JSON.parse(input);
359
+ prompt = data.prompt || "";
360
+ } catch {
361
+ prompt = input;
362
+ }
363
+
364
+ if (!prompt.trim()) {
365
+ process.exit(0);
366
+ }
367
+
368
+ try {
369
+ const output = evaluate(prompt);
370
+ if (output) {
371
+ console.log(output);
372
+ }
373
+ } catch (error) {
374
+ console.error(`Skill evaluation failed: ${error.message}`);
375
+ }
376
+
377
+ process.exit(0);
378
+ });
379
+ }
380
+
381
+ main();