oh-my-claude-sisyphus 3.7.16 → 3.8.2

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 (52) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +8 -6
  4. package/agents/AGENTS.md +8 -8
  5. package/agents/architect.md +32 -0
  6. package/agents/build-fixer.md +35 -0
  7. package/agents/code-reviewer.md +51 -0
  8. package/agents/executor-high.md +49 -0
  9. package/agents/explore-high.md +39 -0
  10. package/agents/explore-medium.md +33 -0
  11. package/dist/__tests__/hooks/learner/bridge.test.js +13 -7
  12. package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -1
  13. package/dist/__tests__/hooks.test.js +306 -67
  14. package/dist/__tests__/hooks.test.js.map +1 -1
  15. package/dist/__tests__/installer.test.js +31 -15
  16. package/dist/__tests__/installer.test.js.map +1 -1
  17. package/dist/hooks/bridge.js +3 -3
  18. package/dist/hooks/bridge.js.map +1 -1
  19. package/dist/hooks/clear-suggestions/constants.d.ts +54 -0
  20. package/dist/hooks/clear-suggestions/constants.d.ts.map +1 -0
  21. package/dist/hooks/clear-suggestions/constants.js +102 -0
  22. package/dist/hooks/clear-suggestions/constants.js.map +1 -0
  23. package/dist/hooks/clear-suggestions/index.d.ts +61 -0
  24. package/dist/hooks/clear-suggestions/index.d.ts.map +1 -0
  25. package/dist/hooks/clear-suggestions/index.js +276 -0
  26. package/dist/hooks/clear-suggestions/index.js.map +1 -0
  27. package/dist/hooks/clear-suggestions/triggers.d.ts +65 -0
  28. package/dist/hooks/clear-suggestions/triggers.d.ts.map +1 -0
  29. package/dist/hooks/clear-suggestions/triggers.js +222 -0
  30. package/dist/hooks/clear-suggestions/triggers.js.map +1 -0
  31. package/dist/hooks/clear-suggestions/types.d.ts +92 -0
  32. package/dist/hooks/clear-suggestions/types.d.ts.map +1 -0
  33. package/dist/hooks/clear-suggestions/types.js +9 -0
  34. package/dist/hooks/clear-suggestions/types.js.map +1 -0
  35. package/dist/hooks/index.d.ts +1 -0
  36. package/dist/hooks/index.d.ts.map +1 -1
  37. package/dist/hooks/index.js +3 -0
  38. package/dist/hooks/index.js.map +1 -1
  39. package/dist/hooks/keyword-detector/__tests__/index.test.js +51 -51
  40. package/dist/hooks/keyword-detector/__tests__/index.test.js.map +1 -1
  41. package/dist/hooks/keyword-detector/index.d.ts +1 -1
  42. package/dist/hooks/keyword-detector/index.d.ts.map +1 -1
  43. package/dist/hooks/keyword-detector/index.js +18 -5
  44. package/dist/hooks/keyword-detector/index.js.map +1 -1
  45. package/docs/CLAUDE.md +104 -0
  46. package/package.json +1 -1
  47. package/scripts/keyword-detector.mjs +176 -84
  48. package/scripts/post-tool-verifier.mjs +42 -3
  49. package/scripts/pre-tool-enforcer.mjs +4 -1
  50. package/scripts/session-start.mjs +7 -1
  51. package/scripts/skill-injector.mjs +4 -1
  52. package/templates/hooks/keyword-detector.sh +197 -31
package/docs/CLAUDE.md CHANGED
@@ -36,8 +36,29 @@ RULE 1: ALWAYS delegate substantive work to specialized agents
36
36
  RULE 2: ALWAYS invoke appropriate skills for recognized patterns
37
37
  RULE 3: NEVER do code changes directly - delegate to executor
38
38
  RULE 4: NEVER complete without Architect verification
39
+ RULE 5: ALWAYS consult official documentation before implementing with SDKs/frameworks/APIs
39
40
  ```
40
41
 
42
+ ### Documentation-First Development (CRITICAL)
43
+
44
+ **NEVER make assumptions about SDK, framework, or API behavior.**
45
+
46
+ When implementing with any external tool (Claude Code hooks, React, database drivers, etc.):
47
+
48
+ 1. **BEFORE writing code**: Delegate to `researcher` agent to fetch official docs
49
+ 2. **Use Context7 MCP tools**: `resolve-library-id` → `query-docs` for up-to-date documentation
50
+ 3. **Verify API contracts**: Check actual schemas, return types, and field names
51
+ 4. **No guessing**: If docs are unclear, search for examples or ask the user
52
+
53
+ **Why this matters**: Assumptions about undocumented fields (like using `message` instead of `hookSpecificOutput.additionalContext`) lead to silent failures that are hard to debug.
54
+
55
+ | Situation | Action |
56
+ |-----------|--------|
57
+ | Using a new SDK/API | Delegate to `researcher` first |
58
+ | Implementing hooks/plugins | Verify output schema from official docs |
59
+ | Uncertain about field names | Query official documentation |
60
+ | Copying from old code | Verify pattern still valid |
61
+
41
62
  ### What You Do vs. Delegate
42
63
 
43
64
  | Action | YOU Do Directly | DELEGATE to Agent |
@@ -309,6 +330,89 @@ Always use `oh-my-claudecode:` prefix when calling via Task tool.
309
330
  | Data analysis/stats | `scientist` | sonnet |
310
331
  | Quick data inspection | `scientist-low` | haiku |
311
332
  | Complex ML/hypothesis | `scientist-high` | opus |
333
+ | Find symbol references | `explore-high` | opus |
334
+ | Get file/workspace symbol outline | `explore` | haiku |
335
+ | Structural code pattern search | `explore` | haiku |
336
+ | Structural code transformation | `executor-high` | opus |
337
+ | Project-wide type checking | `build-fixer` | sonnet |
338
+ | Check single file for errors | `executor-low` | haiku |
339
+ | Data analysis / computation | `scientist` | sonnet |
340
+
341
+ ### MCP Tools & Agent Capabilities
342
+
343
+ *Source of truth: `src/agents/definitions.ts`*
344
+
345
+ #### Tool Inventory
346
+
347
+ | Tool | Category | Purpose | Assigned to Agents? |
348
+ |------|----------|---------|---------------------|
349
+ | `lsp_hover` | LSP | Get type info and documentation at a code position | NO (orchestrator-direct) |
350
+ | `lsp_goto_definition` | LSP | Jump to where a symbol is defined | NO (orchestrator-direct) |
351
+ | `lsp_find_references` | LSP | Find all usages of a symbol across the codebase | YES (`explore-high` only) |
352
+ | `lsp_document_symbols` | LSP | Get outline of all symbols in a file | YES |
353
+ | `lsp_workspace_symbols` | LSP | Search for symbols by name across the workspace | YES |
354
+ | `lsp_diagnostics` | LSP | Get errors, warnings, and hints for a file | YES |
355
+ | `lsp_diagnostics_directory` | LSP | Project-level type checking (tsc --noEmit or LSP) | YES |
356
+ | `lsp_prepare_rename` | LSP | Check if a symbol can be renamed | NO (orchestrator-direct) |
357
+ | `lsp_rename` | LSP | Rename a symbol across the entire project | NO (orchestrator-direct) |
358
+ | `lsp_code_actions` | LSP | Get available refactorings and quick fixes | NO (orchestrator-direct) |
359
+ | `lsp_code_action_resolve` | LSP | Get full edit details for a code action | NO (orchestrator-direct) |
360
+ | `lsp_servers` | LSP | List available language servers and install status | NO (orchestrator-direct) |
361
+ | `ast_grep_search` | AST | Pattern-based structural code search using AST | YES |
362
+ | `ast_grep_replace` | AST | Pattern-based structural code transformation | YES (`executor-high` only) |
363
+ | `python_repl` | Data | Persistent Python REPL for data analysis and computation | YES |
364
+
365
+ #### Agent Tool Matrix (MCP Tools Only)
366
+
367
+ | Agent | LSP Diagnostics | LSP Dir Diagnostics | LSP Symbols | LSP References | AST Search | AST Replace | Python REPL |
368
+ |-------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
369
+ | `explore` | - | - | doc + workspace | - | yes | - | - |
370
+ | `explore-medium` | - | - | doc + workspace | - | yes | - | - |
371
+ | `explore-high` | - | - | doc + workspace | yes | yes | - | - |
372
+ | `architect-low` | yes | - | - | - | - | - | - |
373
+ | `architect-medium` | yes | yes | - | - | yes | - | - |
374
+ | `architect` | yes | yes | - | - | yes | - | - |
375
+ | `executor-low` | yes | - | - | - | - | - | - |
376
+ | `executor` | yes | yes | - | - | - | - | - |
377
+ | `executor-high` | yes | yes | - | - | yes | yes | - |
378
+ | `build-fixer` | yes | yes | - | - | - | - | - |
379
+ | `build-fixer-low` | yes | yes | - | - | - | - | - |
380
+ | `tdd-guide` | yes | - | - | - | - | - | - |
381
+ | `tdd-guide-low` | yes | - | - | - | - | - | - |
382
+ | `code-reviewer` | yes | - | - | - | yes | - | - |
383
+ | `code-reviewer-low` | yes | - | - | - | - | - | - |
384
+ | `qa-tester` | yes | - | - | - | - | - | - |
385
+ | `qa-tester-high` | yes | - | - | - | - | - | - |
386
+ | `scientist-low` | - | - | - | - | - | - | yes |
387
+ | `scientist` | - | - | - | - | - | - | yes |
388
+ | `scientist-high` | - | - | - | - | - | - | yes |
389
+
390
+ #### Unassigned Tools (Orchestrator-Direct)
391
+
392
+ The following 7 MCP tools are NOT assigned to any agent. Use directly when needed:
393
+
394
+ | Tool | When to Use Directly |
395
+ |------|---------------------|
396
+ | `lsp_hover` | Quick type lookups during conversation |
397
+ | `lsp_goto_definition` | Navigating to symbol definitions during analysis |
398
+ | `lsp_prepare_rename` | Checking rename feasibility before deciding on approach |
399
+ | `lsp_rename` | Safe rename operations (returns edit preview, does not auto-apply) |
400
+ | `lsp_code_actions` | Discovering available refactorings |
401
+ | `lsp_code_action_resolve` | Getting details of a specific code action |
402
+ | `lsp_servers` | Checking language server availability |
403
+
404
+ For complex rename or refactoring tasks requiring implementation, delegate to `executor-high` which can use `ast_grep_replace` for structural transformations.
405
+
406
+ #### Tool Selection Guidance
407
+
408
+ - **Need file symbol outline or workspace search?** Use `lsp_document_symbols`/`lsp_workspace_symbols` via `explore`, `explore-medium`, or `explore-high`
409
+ - **Need to find all usages of a symbol?** Use `lsp_find_references` via `explore-high` (only agent with it)
410
+ - **Need structural code patterns?** (e.g., "find all functions matching X shape") Use `ast_grep_search` via `explore` family, `architect`/`architect-medium`, or `code-reviewer`
411
+ - **Need to transform code structurally?** Use `ast_grep_replace` via `executor-high` (only agent with it)
412
+ - **Need project-wide type checking?** Use `lsp_diagnostics_directory` via `architect`/`architect-medium`, `executor`/`executor-high`, or `build-fixer` family
413
+ - **Need single-file error checking?** Use `lsp_diagnostics` via many agents (see matrix)
414
+ - **Need data analysis / computation?** Use `python_repl` via `scientist` agents (all tiers)
415
+ - **Need quick type info or definition lookup?** Use `lsp_hover`/`lsp_goto_definition` directly (orchestrator-direct tools)
312
416
 
313
417
  ---
314
418
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-claude-sisyphus",
3
- "version": "3.7.16",
3
+ "version": "3.8.2",
4
4
  "description": "Multi-agent orchestration system for Claude Code - Inspired by oh-my-opencode",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,51 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Sisyphus Keyword Detector Hook (Node.js)
5
- * Detects ultrawork/ultrathink/search/analyze keywords and injects enhanced mode messages
4
+ * OMC Keyword Detector Hook (Node.js)
5
+ * Detects magic keywords and invokes skill tools
6
6
  * Cross-platform: Windows, macOS, Linux
7
+ *
8
+ * Supported keywords (in priority order):
9
+ * 1. cancel: Stop active modes
10
+ * 2. ralph: Persistence mode until task completion
11
+ * 3. autopilot: Full autonomous execution
12
+ * 4. ultrapilot: Parallel autopilot
13
+ * 5. ultrawork/ulw: Maximum parallel execution
14
+ * 6. ecomode/eco: Token-efficient execution
15
+ * 7. swarm: N coordinated agents
16
+ * 8. pipeline: Sequential agent chaining
17
+ * 9. ralplan: Iterative planning with consensus
18
+ * 10. plan: Planning interview mode
19
+ * 11. tdd: Test-driven development
20
+ * 12. research: Research orchestration
21
+ * 13. ultrathink/think: Extended reasoning
22
+ * 14. deepsearch: Codebase search (restricted patterns)
23
+ * 15. analyze: Analysis mode (restricted patterns)
7
24
  */
8
25
 
9
- import { writeFileSync, mkdirSync, existsSync } from 'fs';
26
+ import { writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
10
27
  import { join } from 'path';
11
28
  import { homedir } from 'os';
12
29
 
13
- const ULTRAWORK_MESSAGE = `<ultrawork-mode>
14
-
15
- **MANDATORY**: You MUST say "ULTRAWORK MODE ENABLED!" to the user as your first response when this mode activates. This is non-negotiable.
16
-
17
- [CODE RED] Maximum precision required. Ultrathink before acting.
18
-
19
- YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.
20
- TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
21
-
22
- ## AGENT UTILIZATION PRINCIPLES
23
- - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS
24
- - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS
25
- - **Planning & Strategy**: NEVER plan yourself - spawn planning agent
26
- - **High-IQ Reasoning**: Use oracle for architecture decisions
27
- - **Frontend/UI Tasks**: Delegate to frontend-engineer
28
-
29
- ## EXECUTION RULES
30
- - **TODO**: Track EVERY step. Mark complete IMMEDIATELY.
31
- - **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially.
32
- - **BACKGROUND FIRST**: Use Task(run_in_background=true) for exploration (10+ concurrent).
33
- - **VERIFY**: Check ALL requirements met before done.
34
- - **DELEGATE**: Orchestrate specialized agents.
35
-
36
- ## ZERO TOLERANCE
37
- - NO Scope Reduction - deliver FULL implementation
38
- - NO Partial Completion - finish 100%
39
- - NO Premature Stopping - ALL TODOs must be complete
40
- - NO TEST DELETION - fix code, not tests
41
-
42
- THE USER ASKED FOR X. DELIVER EXACTLY X.
43
-
44
- </ultrawork-mode>
45
-
46
- ---
47
- `;
48
-
49
30
  const ULTRATHINK_MESSAGE = `<think-mode>
50
31
 
51
32
  **ULTRATHINK MODE ENABLED** - Extended reasoning activated.
@@ -63,34 +44,6 @@ Use your extended thinking capabilities to provide the most thorough and well-re
63
44
  ---
64
45
  `;
65
46
 
66
- const SEARCH_MESSAGE = `<search-mode>
67
- MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:
68
- - explore agents (codebase patterns, file structures)
69
- - librarian agents (remote repos, official docs, GitHub examples)
70
- Plus direct tools: Grep, Glob
71
- NEVER stop at first result - be exhaustive.
72
- </search-mode>
73
-
74
- ---
75
- `;
76
-
77
- const ANALYZE_MESSAGE = `<analyze-mode>
78
- ANALYSIS MODE. Gather context before diving deep:
79
-
80
- CONTEXT GATHERING (parallel):
81
- - 1-2 explore agents (codebase patterns, implementations)
82
- - 1-2 librarian agents (if external library involved)
83
- - Direct tools: Grep, Glob, LSP for targeted searches
84
-
85
- IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
86
- - Consult oracle agent for strategic guidance
87
-
88
- SYNTHESIZE findings before proceeding.
89
- </analyze-mode>
90
-
91
- ---
92
- `;
93
-
94
47
  // Read all stdin
95
48
  async function readStdin() {
96
49
  const chunks = [];
@@ -127,8 +80,8 @@ function removeCodeBlocks(text) {
127
80
  .replace(/`[^`]+`/g, '');
128
81
  }
129
82
 
130
- // Create ultrawork state file
131
- function activateUltraworkState(directory, prompt) {
83
+ // Create state file for a mode
84
+ function activateState(directory, prompt, stateName) {
132
85
  const state = {
133
86
  active: true,
134
87
  started_at: new Date().toISOString(),
@@ -142,14 +95,57 @@ function activateUltraworkState(directory, prompt) {
142
95
  if (!existsSync(localDir)) {
143
96
  try { mkdirSync(localDir, { recursive: true }); } catch {}
144
97
  }
145
- try { writeFileSync(join(localDir, 'ultrawork-state.json'), JSON.stringify(state, null, 2)); } catch {}
98
+ try { writeFileSync(join(localDir, `${stateName}-state.json`), JSON.stringify(state, null, 2)); } catch {}
146
99
 
147
100
  // Write to global .omc/state directory
148
101
  const globalDir = join(homedir(), '.omc', 'state');
149
102
  if (!existsSync(globalDir)) {
150
103
  try { mkdirSync(globalDir, { recursive: true }); } catch {}
151
104
  }
152
- try { writeFileSync(join(globalDir, 'ultrawork-state.json'), JSON.stringify(state, null, 2)); } catch {}
105
+ try { writeFileSync(join(globalDir, `${stateName}-state.json`), JSON.stringify(state, null, 2)); } catch {}
106
+ }
107
+
108
+ /**
109
+ * Clear state files for cancel operation
110
+ */
111
+ function clearStateFiles(directory, modeNames) {
112
+ for (const name of modeNames) {
113
+ const localPath = join(directory, '.omc', 'state', `${name}-state.json`);
114
+ const globalPath = join(homedir(), '.omc', 'state', `${name}-state.json`);
115
+ try { if (existsSync(localPath)) unlinkSync(localPath); } catch {}
116
+ try { if (existsSync(globalPath)) unlinkSync(globalPath); } catch {}
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Create a skill invocation message that tells Claude to use the Skill tool
122
+ */
123
+ function createSkillInvocation(skillName, originalPrompt, args = '') {
124
+ const argsSection = args ? `\nArguments: ${args}` : '';
125
+ return `[MAGIC KEYWORD: ${skillName.toUpperCase()}]
126
+
127
+ You MUST invoke the skill using the Skill tool:
128
+
129
+ Skill: oh-my-claudecode:${skillName}${argsSection}
130
+
131
+ User request:
132
+ ${originalPrompt}
133
+
134
+ IMPORTANT: Invoke the skill IMMEDIATELY. Do not proceed without loading the skill instructions.`;
135
+ }
136
+
137
+ /**
138
+ * Create proper hook output with additionalContext (Claude Code hooks API)
139
+ * The 'message' field is NOT a valid hook output - use hookSpecificOutput.additionalContext
140
+ */
141
+ function createHookOutput(additionalContext) {
142
+ return {
143
+ continue: true,
144
+ hookSpecificOutput: {
145
+ hookEventName: 'UserPromptSubmit',
146
+ additionalContext
147
+ }
148
+ };
153
149
  }
154
150
 
155
151
  // Main
@@ -173,28 +169,124 @@ async function main() {
173
169
 
174
170
  const cleanPrompt = removeCodeBlocks(prompt).toLowerCase();
175
171
 
176
- // Check for ultrawork keywords (highest priority)
177
- if (/\b(ultrawork|ulw|uw)\b/.test(cleanPrompt)) {
178
- activateUltraworkState(directory, prompt);
179
- console.log(JSON.stringify({ continue: true, message: ULTRAWORK_MESSAGE }));
172
+ // Priority order: cancel > ralph > autopilot > ultrapilot > ultrawork > ecomode > swarm > pipeline > ralplan > plan > tdd > research > ultrathink > deepsearch > analyze
173
+
174
+ // Priority 1: Cancel (BEFORE other modes - clears states)
175
+ if (/\b(stop|cancel|abort)\b/i.test(cleanPrompt)) {
176
+ // Special: clear state files instead of creating them
177
+ clearStateFiles(directory, ['ralph', 'autopilot', 'ultrapilot', 'ultrawork', 'ecomode', 'swarm', 'pipeline']);
178
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('cancel', prompt))));
179
+ return;
180
+ }
181
+
182
+ // Priority 2: Ralph keywords
183
+ if (/\b(ralph|don't stop|must complete|until done)\b/i.test(cleanPrompt)) {
184
+ activateState(directory, prompt, 'ralph');
185
+ activateState(directory, prompt, 'ultrawork');
186
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('ralph', prompt))));
187
+ return;
188
+ }
189
+
190
+ // Priority 3: Autopilot keywords
191
+ if (/\b(autopilot|auto pilot|auto-pilot|autonomous|full auto|fullsend)\b/i.test(cleanPrompt) ||
192
+ /\bbuild\s+me\s+/i.test(cleanPrompt) ||
193
+ /\bcreate\s+me\s+/i.test(cleanPrompt) ||
194
+ /\bmake\s+me\s+/i.test(cleanPrompt) ||
195
+ /\bi\s+want\s+a\s+/i.test(cleanPrompt) ||
196
+ /\bi\s+want\s+an\s+/i.test(cleanPrompt) ||
197
+ /\bhandle\s+it\s+all\b/i.test(cleanPrompt) ||
198
+ /\bend\s+to\s+end\b/i.test(cleanPrompt) ||
199
+ /\be2e\s+this\b/i.test(cleanPrompt)) {
200
+ activateState(directory, prompt, 'autopilot');
201
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('autopilot', prompt))));
202
+ return;
203
+ }
204
+
205
+ // Priority 4: Ultrapilot
206
+ if (/\b(ultrapilot|ultra-pilot)\b/i.test(cleanPrompt) ||
207
+ /\bparallel\s+build\b/i.test(cleanPrompt) ||
208
+ /\bswarm\s+build\b/i.test(cleanPrompt)) {
209
+ activateState(directory, prompt, 'ultrapilot');
210
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('ultrapilot', prompt))));
211
+ return;
212
+ }
213
+
214
+ // Priority 5: Ultrawork keywords
215
+ if (/\b(ultrawork|ulw|uw)\b/i.test(cleanPrompt)) {
216
+ activateState(directory, prompt, 'ultrawork');
217
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('ultrawork', prompt))));
218
+ return;
219
+ }
220
+
221
+ // Priority 6: Ecomode keywords (includes "efficient")
222
+ if (/\b(eco|ecomode|eco-mode|efficient|save-tokens|budget)\b/i.test(cleanPrompt)) {
223
+ activateState(directory, prompt, 'ecomode');
224
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('ecomode', prompt))));
225
+ return;
226
+ }
227
+
228
+ // Priority 7: Swarm - parse N from "swarm N agents"
229
+ const swarmMatch = cleanPrompt.match(/\bswarm\s+(\d+)\s+agents?\b/i);
230
+ if (swarmMatch || /\bcoordinated\s+agents\b/i.test(cleanPrompt)) {
231
+ const agentCount = swarmMatch ? swarmMatch[1] : '3'; // default 3
232
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('swarm', prompt, agentCount))));
233
+ return;
234
+ }
235
+
236
+ // Priority 8: Pipeline
237
+ if (/\b(pipeline)\b/i.test(cleanPrompt) || /\bchain\s+agents\b/i.test(cleanPrompt)) {
238
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('pipeline', prompt))));
239
+ return;
240
+ }
241
+
242
+ // Priority 9: Ralplan keyword (before plan to avoid false match)
243
+ if (/\b(ralplan)\b/i.test(cleanPrompt)) {
244
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('ralplan', prompt))));
245
+ return;
246
+ }
247
+
248
+ // Priority 10: Plan keywords
249
+ if (/\b(plan this|plan the)\b/i.test(cleanPrompt)) {
250
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('plan', prompt))));
251
+ return;
252
+ }
253
+
254
+ // Priority 11: TDD
255
+ if (/\b(tdd)\b/i.test(cleanPrompt) ||
256
+ /\btest\s+first\b/i.test(cleanPrompt) ||
257
+ /\bred\s+green\b/i.test(cleanPrompt)) {
258
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('tdd', prompt))));
259
+ return;
260
+ }
261
+
262
+ // Priority 12: Research
263
+ // "research" alone OR "analyze data" OR "statistics" trigger research skill
264
+ if (/\b(research)\b/i.test(cleanPrompt) ||
265
+ /\banalyze\s+data\b/i.test(cleanPrompt) ||
266
+ /\bstatistics\b/i.test(cleanPrompt)) {
267
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('research', prompt))));
180
268
  return;
181
269
  }
182
270
 
183
- // Check for ultrathink/think keywords
184
- if (/\b(ultrathink|think)\b/.test(cleanPrompt)) {
185
- console.log(JSON.stringify({ continue: true, message: ULTRATHINK_MESSAGE }));
271
+ // Priority 13: Ultrathink/think keywords (keep inline message)
272
+ if (/\b(ultrathink|think hard|think deeply)\b/i.test(cleanPrompt)) {
273
+ console.log(JSON.stringify(createHookOutput(ULTRATHINK_MESSAGE)));
186
274
  return;
187
275
  }
188
276
 
189
- // Check for search keywords
190
- if (/\b(search|find|locate|lookup|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\b|where\s+is|show\s+me|list\s+all/.test(cleanPrompt)) {
191
- console.log(JSON.stringify({ continue: true, message: SEARCH_MESSAGE }));
277
+ // Priority 14: Deepsearch (RESTRICTED patterns)
278
+ if (/\b(deepsearch)\b/i.test(cleanPrompt) ||
279
+ /\bsearch\s+(the\s+)?(codebase|code|files?|project)\b/i.test(cleanPrompt) ||
280
+ /\bfind\s+(in\s+)?(codebase|code|all\s+files?)\b/i.test(cleanPrompt)) {
281
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('deepsearch', prompt))));
192
282
  return;
193
283
  }
194
284
 
195
- // Check for analyze keywords
196
- if (/\b(analyze|analyse|investigate|examine|research|study|deep.?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\b|why\s+is|how\s+does|how\s+to/.test(cleanPrompt)) {
197
- console.log(JSON.stringify({ continue: true, message: ANALYZE_MESSAGE }));
285
+ // Priority 15: Analyze (RESTRICTED patterns)
286
+ if (/\b(deep\s*analyze)\b/i.test(cleanPrompt) ||
287
+ /\binvestigate\s+(the|this|why)\b/i.test(cleanPrompt) ||
288
+ /\bdebug\s+(the|this|why)\b/i.test(cleanPrompt)) {
289
+ console.log(JSON.stringify(createHookOutput(createSkillInvocation('analyze', prompt))));
198
290
  return;
199
291
  }
200
292
 
@@ -15,6 +15,7 @@ import { fileURLToPath } from 'url';
15
15
  const __filename = fileURLToPath(import.meta.url);
16
16
  const __dirname = dirname(__filename);
17
17
  const distDir = join(__dirname, '..', 'dist', 'hooks', 'notepad');
18
+ const clearSuggestionsDistDir = join(__dirname, '..', 'dist', 'hooks', 'clear-suggestions');
18
19
 
19
20
  // Try to import notepad functions (may fail if not built)
20
21
  let setPriorityContext = null;
@@ -27,6 +28,15 @@ try {
27
28
  // Notepad module not available - remember tags will be silently ignored
28
29
  }
29
30
 
31
+ // Try to import clear suggestions functions (may fail if not built)
32
+ let checkClearSuggestion = null;
33
+ try {
34
+ const clearSuggestionsModule = await import(join(clearSuggestionsDistDir, 'index.js'));
35
+ checkClearSuggestion = clearSuggestionsModule.checkClearSuggestion;
36
+ } catch {
37
+ // Clear suggestions module not available - will be silently skipped
38
+ }
39
+
30
40
  // State file for session tracking
31
41
  const STATE_FILE = join(homedir(), '.claude', '.session-stats.json');
32
42
 
@@ -262,10 +272,39 @@ async function main() {
262
272
  // Generate contextual message
263
273
  const message = generateMessage(toolName, toolOutput, sessionId, toolCount);
264
274
 
265
- // Build response
275
+ // Check for clear suggestions (complements /compact suggestions)
276
+ let clearSuggestionMessage = null;
277
+ if (checkClearSuggestion) {
278
+ try {
279
+ const stats = loadStats();
280
+ const session = stats.sessions[sessionId];
281
+ // Estimate context usage from total tool calls (rough heuristic)
282
+ const estimatedContextRatio = session ? Math.min(session.total_calls / 200, 1.0) : 0;
283
+
284
+ const clearResult = checkClearSuggestion({
285
+ sessionId,
286
+ directory,
287
+ toolName,
288
+ toolOutput,
289
+ contextUsageRatio: estimatedContextRatio,
290
+ });
291
+
292
+ if (clearResult.shouldSuggest && clearResult.message) {
293
+ clearSuggestionMessage = clearResult.message;
294
+ }
295
+ } catch {
296
+ // Clear suggestion check failed - continue without it
297
+ }
298
+ }
299
+
300
+ // Build response - use hookSpecificOutput.additionalContext for PostToolUse
266
301
  const response = { continue: true };
267
- if (message) {
268
- response.message = message;
302
+ const contextMessage = clearSuggestionMessage || message;
303
+ if (contextMessage) {
304
+ response.hookSpecificOutput = {
305
+ hookEventName: 'PostToolUse',
306
+ additionalContext: contextMessage
307
+ };
269
308
  }
270
309
 
271
310
  console.log(JSON.stringify(response, null, 2));
@@ -115,7 +115,10 @@ async function main() {
115
115
 
116
116
  console.log(JSON.stringify({
117
117
  continue: true,
118
- message: message
118
+ hookSpecificOutput: {
119
+ hookEventName: 'PreToolUse',
120
+ additionalContext: message
121
+ }
119
122
  }, null, 2));
120
123
  } catch (error) {
121
124
  // On error, always continue
@@ -171,7 +171,13 @@ ${cleanContent}
171
171
  }
172
172
 
173
173
  if (messages.length > 0) {
174
- console.log(JSON.stringify({ continue: true, message: messages.join('\n') }));
174
+ console.log(JSON.stringify({
175
+ continue: true,
176
+ hookSpecificOutput: {
177
+ hookEventName: 'SessionStart',
178
+ additionalContext: messages.join('\n')
179
+ }
180
+ }));
175
181
  } else {
176
182
  console.log(JSON.stringify({ continue: true }));
177
183
  }
@@ -268,7 +268,10 @@ async function main() {
268
268
  if (matchingSkills.length > 0) {
269
269
  console.log(JSON.stringify({
270
270
  continue: true,
271
- message: formatSkillsMessage(matchingSkills)
271
+ hookSpecificOutput: {
272
+ hookEventName: 'UserPromptSubmit',
273
+ additionalContext: formatSkillsMessage(matchingSkills)
274
+ }
272
275
  }));
273
276
  } else {
274
277
  console.log(JSON.stringify({ continue: true }));