claudecode-omc 5.5.2 → 5.6.0

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 (433) hide show
  1. package/README.md +63 -0
  2. package/bundled/manifest.json +3 -2
  3. package/bundled/upstream/ecc/.omc-source/bundle.json +23 -0
  4. package/bundled/upstream/ecc/.omc-source/last-plan-apply.json +439 -0
  5. package/bundled/upstream/ecc/.omc-source/manifests/.claude-plugin/marketplace.json +47 -0
  6. package/bundled/upstream/ecc/agents/a11y-architect.md +141 -0
  7. package/bundled/upstream/ecc/agents/architect.md +211 -0
  8. package/bundled/upstream/ecc/agents/build-error-resolver.md +114 -0
  9. package/bundled/upstream/ecc/agents/chief-of-staff.md +151 -0
  10. package/bundled/upstream/ecc/agents/code-architect.md +71 -0
  11. package/bundled/upstream/ecc/agents/code-explorer.md +69 -0
  12. package/bundled/upstream/ecc/agents/code-reviewer.md +237 -0
  13. package/bundled/upstream/ecc/agents/code-simplifier.md +47 -0
  14. package/bundled/upstream/ecc/agents/comment-analyzer.md +45 -0
  15. package/bundled/upstream/ecc/agents/conversation-analyzer.md +52 -0
  16. package/bundled/upstream/ecc/agents/cpp-build-resolver.md +90 -0
  17. package/bundled/upstream/ecc/agents/cpp-reviewer.md +72 -0
  18. package/bundled/upstream/ecc/agents/csharp-reviewer.md +101 -0
  19. package/bundled/upstream/ecc/agents/dart-build-resolver.md +201 -0
  20. package/bundled/upstream/ecc/agents/database-reviewer.md +91 -0
  21. package/bundled/upstream/ecc/agents/doc-updater.md +107 -0
  22. package/bundled/upstream/ecc/agents/docs-lookup.md +68 -0
  23. package/bundled/upstream/ecc/agents/e2e-runner.md +107 -0
  24. package/bundled/upstream/ecc/agents/flutter-reviewer.md +243 -0
  25. package/bundled/upstream/ecc/agents/gan-evaluator.md +209 -0
  26. package/bundled/upstream/ecc/agents/gan-generator.md +131 -0
  27. package/bundled/upstream/ecc/agents/gan-planner.md +99 -0
  28. package/bundled/upstream/ecc/agents/go-build-resolver.md +94 -0
  29. package/bundled/upstream/ecc/agents/go-reviewer.md +76 -0
  30. package/bundled/upstream/ecc/agents/harness-optimizer.md +35 -0
  31. package/bundled/upstream/ecc/agents/healthcare-reviewer.md +83 -0
  32. package/bundled/upstream/ecc/agents/java-build-resolver.md +153 -0
  33. package/bundled/upstream/ecc/agents/java-reviewer.md +92 -0
  34. package/bundled/upstream/ecc/agents/kotlin-build-resolver.md +118 -0
  35. package/bundled/upstream/ecc/agents/kotlin-reviewer.md +159 -0
  36. package/bundled/upstream/ecc/agents/loop-operator.md +36 -0
  37. package/bundled/upstream/ecc/agents/opensource-forker.md +198 -0
  38. package/bundled/upstream/ecc/agents/opensource-packager.md +249 -0
  39. package/bundled/upstream/ecc/agents/opensource-sanitizer.md +188 -0
  40. package/bundled/upstream/ecc/agents/performance-optimizer.md +446 -0
  41. package/bundled/upstream/ecc/agents/planner.md +212 -0
  42. package/bundled/upstream/ecc/agents/pr-test-analyzer.md +45 -0
  43. package/bundled/upstream/ecc/agents/python-reviewer.md +98 -0
  44. package/bundled/upstream/ecc/agents/pytorch-build-resolver.md +120 -0
  45. package/bundled/upstream/ecc/agents/refactor-cleaner.md +85 -0
  46. package/bundled/upstream/ecc/agents/rust-build-resolver.md +148 -0
  47. package/bundled/upstream/ecc/agents/rust-reviewer.md +94 -0
  48. package/bundled/upstream/ecc/agents/security-reviewer.md +108 -0
  49. package/bundled/upstream/ecc/agents/seo-specialist.md +62 -0
  50. package/bundled/upstream/ecc/agents/silent-failure-hunter.md +50 -0
  51. package/bundled/upstream/ecc/agents/tdd-guide.md +91 -0
  52. package/bundled/upstream/ecc/agents/type-design-analyzer.md +41 -0
  53. package/bundled/upstream/ecc/agents/typescript-reviewer.md +112 -0
  54. package/bundled/upstream/ecc/commands/agent-sort.md +23 -0
  55. package/bundled/upstream/ecc/commands/aside.md +164 -0
  56. package/bundled/upstream/ecc/commands/build-fix.md +62 -0
  57. package/bundled/upstream/ecc/commands/checkpoint.md +74 -0
  58. package/bundled/upstream/ecc/commands/claw.md +23 -0
  59. package/bundled/upstream/ecc/commands/code-review.md +289 -0
  60. package/bundled/upstream/ecc/commands/context-budget.md +23 -0
  61. package/bundled/upstream/ecc/commands/cpp-build.md +173 -0
  62. package/bundled/upstream/ecc/commands/cpp-review.md +132 -0
  63. package/bundled/upstream/ecc/commands/cpp-test.md +251 -0
  64. package/bundled/upstream/ecc/commands/devfleet.md +23 -0
  65. package/bundled/upstream/ecc/commands/docs.md +23 -0
  66. package/bundled/upstream/ecc/commands/e2e.md +268 -0
  67. package/bundled/upstream/ecc/commands/eval.md +23 -0
  68. package/bundled/upstream/ecc/commands/evolve.md +178 -0
  69. package/bundled/upstream/ecc/commands/feature-dev.md +49 -0
  70. package/bundled/upstream/ecc/commands/flutter-build.md +164 -0
  71. package/bundled/upstream/ecc/commands/flutter-review.md +116 -0
  72. package/bundled/upstream/ecc/commands/flutter-test.md +144 -0
  73. package/bundled/upstream/ecc/commands/gan-build.md +99 -0
  74. package/bundled/upstream/ecc/commands/gan-design.md +35 -0
  75. package/bundled/upstream/ecc/commands/go-build.md +183 -0
  76. package/bundled/upstream/ecc/commands/go-review.md +148 -0
  77. package/bundled/upstream/ecc/commands/go-test.md +268 -0
  78. package/bundled/upstream/ecc/commands/gradle-build.md +70 -0
  79. package/bundled/upstream/ecc/commands/harness-audit.md +73 -0
  80. package/bundled/upstream/ecc/commands/hookify-configure.md +14 -0
  81. package/bundled/upstream/ecc/commands/hookify-help.md +46 -0
  82. package/bundled/upstream/ecc/commands/hookify-list.md +21 -0
  83. package/bundled/upstream/ecc/commands/hookify.md +50 -0
  84. package/bundled/upstream/ecc/commands/instinct-export.md +66 -0
  85. package/bundled/upstream/ecc/commands/instinct-import.md +114 -0
  86. package/bundled/upstream/ecc/commands/instinct-status.md +59 -0
  87. package/bundled/upstream/ecc/commands/jira.md +106 -0
  88. package/bundled/upstream/ecc/commands/kotlin-build.md +174 -0
  89. package/bundled/upstream/ecc/commands/kotlin-review.md +140 -0
  90. package/bundled/upstream/ecc/commands/kotlin-test.md +312 -0
  91. package/bundled/upstream/ecc/commands/learn-eval.md +116 -0
  92. package/bundled/upstream/ecc/commands/learn.md +70 -0
  93. package/bundled/upstream/ecc/commands/loop-start.md +32 -0
  94. package/bundled/upstream/ecc/commands/loop-status.md +24 -0
  95. package/bundled/upstream/ecc/commands/model-route.md +26 -0
  96. package/bundled/upstream/ecc/commands/multi-backend.md +158 -0
  97. package/bundled/upstream/ecc/commands/multi-execute.md +315 -0
  98. package/bundled/upstream/ecc/commands/multi-frontend.md +158 -0
  99. package/bundled/upstream/ecc/commands/multi-plan.md +268 -0
  100. package/bundled/upstream/ecc/commands/multi-workflow.md +191 -0
  101. package/bundled/upstream/ecc/commands/orchestrate.md +135 -0
  102. package/bundled/upstream/ecc/commands/plan.md +117 -0
  103. package/bundled/upstream/ecc/commands/pm2.md +272 -0
  104. package/bundled/upstream/ecc/commands/projects.md +39 -0
  105. package/bundled/upstream/ecc/commands/promote.md +41 -0
  106. package/bundled/upstream/ecc/commands/prompt-optimize.md +23 -0
  107. package/bundled/upstream/ecc/commands/prp-commit.md +112 -0
  108. package/bundled/upstream/ecc/commands/prp-implement.md +385 -0
  109. package/bundled/upstream/ecc/commands/prp-plan.md +502 -0
  110. package/bundled/upstream/ecc/commands/prp-pr.md +184 -0
  111. package/bundled/upstream/ecc/commands/prp-prd.md +447 -0
  112. package/bundled/upstream/ecc/commands/prune.md +31 -0
  113. package/bundled/upstream/ecc/commands/python-review.md +297 -0
  114. package/bundled/upstream/ecc/commands/quality-gate.md +29 -0
  115. package/bundled/upstream/ecc/commands/refactor-clean.md +80 -0
  116. package/bundled/upstream/ecc/commands/resume-session.md +156 -0
  117. package/bundled/upstream/ecc/commands/review-pr.md +37 -0
  118. package/bundled/upstream/ecc/commands/rules-distill.md +20 -0
  119. package/bundled/upstream/ecc/commands/rust-build.md +187 -0
  120. package/bundled/upstream/ecc/commands/rust-review.md +142 -0
  121. package/bundled/upstream/ecc/commands/rust-test.md +308 -0
  122. package/bundled/upstream/ecc/commands/santa-loop.md +175 -0
  123. package/bundled/upstream/ecc/commands/save-session.md +275 -0
  124. package/bundled/upstream/ecc/commands/sessions.md +339 -0
  125. package/bundled/upstream/ecc/commands/setup-pm.md +80 -0
  126. package/bundled/upstream/ecc/commands/skill-create.md +174 -0
  127. package/bundled/upstream/ecc/commands/skill-health.md +54 -0
  128. package/bundled/upstream/ecc/commands/tdd.md +231 -0
  129. package/bundled/upstream/ecc/commands/test-coverage.md +69 -0
  130. package/bundled/upstream/ecc/commands/update-codemaps.md +72 -0
  131. package/bundled/upstream/ecc/commands/update-docs.md +84 -0
  132. package/bundled/upstream/ecc/commands/verify.md +23 -0
  133. package/bundled/upstream/ecc/hooks/README.md +237 -0
  134. package/bundled/upstream/ecc/hooks/hooks.json +330 -0
  135. package/bundled/upstream/ecc/skills/accessibility/SKILL.md +146 -0
  136. package/bundled/upstream/ecc/skills/agent-eval/SKILL.md +145 -0
  137. package/bundled/upstream/ecc/skills/agent-harness-construction/SKILL.md +73 -0
  138. package/bundled/upstream/ecc/skills/agent-introspection-debugging/SKILL.md +153 -0
  139. package/bundled/upstream/ecc/skills/agent-payment-x402/SKILL.md +178 -0
  140. package/bundled/upstream/ecc/skills/agent-sort/SKILL.md +215 -0
  141. package/bundled/upstream/ecc/skills/agentic-engineering/SKILL.md +63 -0
  142. package/bundled/upstream/ecc/skills/ai-first-engineering/SKILL.md +51 -0
  143. package/bundled/upstream/ecc/skills/ai-regression-testing/SKILL.md +385 -0
  144. package/bundled/upstream/ecc/skills/android-clean-architecture/SKILL.md +339 -0
  145. package/bundled/upstream/ecc/skills/api-connector-builder/SKILL.md +120 -0
  146. package/bundled/upstream/ecc/skills/api-design/SKILL.md +523 -0
  147. package/bundled/upstream/ecc/skills/architecture-decision-records/SKILL.md +179 -0
  148. package/bundled/upstream/ecc/skills/article-writing/SKILL.md +79 -0
  149. package/bundled/upstream/ecc/skills/automation-audit-ops/SKILL.md +142 -0
  150. package/bundled/upstream/ecc/skills/autonomous-agent-harness/SKILL.md +267 -0
  151. package/bundled/upstream/ecc/skills/autonomous-loops/SKILL.md +610 -0
  152. package/bundled/upstream/ecc/skills/backend-patterns/SKILL.md +598 -0
  153. package/bundled/upstream/ecc/skills/benchmark/SKILL.md +93 -0
  154. package/bundled/upstream/ecc/skills/blueprint/SKILL.md +105 -0
  155. package/bundled/upstream/ecc/skills/brand-voice/SKILL.md +97 -0
  156. package/bundled/upstream/ecc/skills/brand-voice/references/voice-profile-schema.md +55 -0
  157. package/bundled/upstream/ecc/skills/browser-qa/SKILL.md +87 -0
  158. package/bundled/upstream/ecc/skills/bun-runtime/SKILL.md +84 -0
  159. package/bundled/upstream/ecc/skills/canary-watch/SKILL.md +99 -0
  160. package/bundled/upstream/ecc/skills/carrier-relationship-management/SKILL.md +212 -0
  161. package/bundled/upstream/ecc/skills/ck/SKILL.md +147 -0
  162. package/bundled/upstream/ecc/skills/ck/commands/forget.mjs +44 -0
  163. package/bundled/upstream/ecc/skills/ck/commands/info.mjs +24 -0
  164. package/bundled/upstream/ecc/skills/ck/commands/init.mjs +143 -0
  165. package/bundled/upstream/ecc/skills/ck/commands/list.mjs +40 -0
  166. package/bundled/upstream/ecc/skills/ck/commands/migrate.mjs +202 -0
  167. package/bundled/upstream/ecc/skills/ck/commands/resume.mjs +36 -0
  168. package/bundled/upstream/ecc/skills/ck/commands/save.mjs +210 -0
  169. package/bundled/upstream/ecc/skills/ck/commands/shared.mjs +387 -0
  170. package/bundled/upstream/ecc/skills/ck/hooks/session-start.mjs +224 -0
  171. package/bundled/upstream/ecc/skills/claude-api/SKILL.md +337 -0
  172. package/bundled/upstream/ecc/skills/claude-devfleet/SKILL.md +103 -0
  173. package/bundled/upstream/ecc/skills/click-path-audit/SKILL.md +244 -0
  174. package/bundled/upstream/ecc/skills/clickhouse-io/SKILL.md +439 -0
  175. package/bundled/upstream/ecc/skills/code-tour/SKILL.md +236 -0
  176. package/bundled/upstream/ecc/skills/codebase-onboarding/SKILL.md +233 -0
  177. package/bundled/upstream/ecc/skills/coding-standards/SKILL.md +549 -0
  178. package/bundled/upstream/ecc/skills/compose-multiplatform-patterns/SKILL.md +299 -0
  179. package/bundled/upstream/ecc/skills/configure-ecc/SKILL.md +367 -0
  180. package/bundled/upstream/ecc/skills/connections-optimizer/SKILL.md +189 -0
  181. package/bundled/upstream/ecc/skills/content-engine/SKILL.md +131 -0
  182. package/bundled/upstream/ecc/skills/content-hash-cache-pattern/SKILL.md +161 -0
  183. package/bundled/upstream/ecc/skills/context-budget/SKILL.md +135 -0
  184. package/bundled/upstream/ecc/skills/continuous-agent-loop/SKILL.md +45 -0
  185. package/bundled/upstream/ecc/skills/continuous-learning/SKILL.md +123 -0
  186. package/bundled/upstream/ecc/skills/continuous-learning/config.json +18 -0
  187. package/bundled/upstream/ecc/skills/continuous-learning/evaluate-session.sh +69 -0
  188. package/bundled/upstream/ecc/skills/continuous-learning-v2/SKILL.md +346 -0
  189. package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/observer-loop.sh +282 -0
  190. package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/observer.md +198 -0
  191. package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
  192. package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/start-observer.sh +244 -0
  193. package/bundled/upstream/ecc/skills/continuous-learning-v2/config.json +8 -0
  194. package/bundled/upstream/ecc/skills/continuous-learning-v2/hooks/observe.sh +460 -0
  195. package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/detect-project.sh +243 -0
  196. package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/instinct-cli.py +1426 -0
  197. package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/test_parse_instinct.py +984 -0
  198. package/bundled/upstream/ecc/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
  199. package/bundled/upstream/ecc/skills/council/SKILL.md +203 -0
  200. package/bundled/upstream/ecc/skills/cpp-coding-standards/SKILL.md +723 -0
  201. package/bundled/upstream/ecc/skills/cpp-testing/SKILL.md +324 -0
  202. package/bundled/upstream/ecc/skills/crosspost/SKILL.md +111 -0
  203. package/bundled/upstream/ecc/skills/csharp-testing/SKILL.md +321 -0
  204. package/bundled/upstream/ecc/skills/customer-billing-ops/SKILL.md +140 -0
  205. package/bundled/upstream/ecc/skills/customs-trade-compliance/SKILL.md +263 -0
  206. package/bundled/upstream/ecc/skills/dart-flutter-patterns/SKILL.md +563 -0
  207. package/bundled/upstream/ecc/skills/dashboard-builder/SKILL.md +108 -0
  208. package/bundled/upstream/ecc/skills/data-scraper-agent/SKILL.md +764 -0
  209. package/bundled/upstream/ecc/skills/database-migrations/SKILL.md +429 -0
  210. package/bundled/upstream/ecc/skills/deep-research/SKILL.md +155 -0
  211. package/bundled/upstream/ecc/skills/defi-amm-security/SKILL.md +160 -0
  212. package/bundled/upstream/ecc/skills/deployment-patterns/SKILL.md +427 -0
  213. package/bundled/upstream/ecc/skills/design-system/SKILL.md +82 -0
  214. package/bundled/upstream/ecc/skills/django-patterns/SKILL.md +734 -0
  215. package/bundled/upstream/ecc/skills/django-security/SKILL.md +593 -0
  216. package/bundled/upstream/ecc/skills/django-tdd/SKILL.md +729 -0
  217. package/bundled/upstream/ecc/skills/django-verification/SKILL.md +469 -0
  218. package/bundled/upstream/ecc/skills/dmux-workflows/SKILL.md +191 -0
  219. package/bundled/upstream/ecc/skills/docker-patterns/SKILL.md +364 -0
  220. package/bundled/upstream/ecc/skills/documentation-lookup/SKILL.md +90 -0
  221. package/bundled/upstream/ecc/skills/dotnet-patterns/SKILL.md +321 -0
  222. package/bundled/upstream/ecc/skills/e2e-testing/SKILL.md +326 -0
  223. package/bundled/upstream/ecc/skills/ecc-tools-cost-audit/SKILL.md +160 -0
  224. package/bundled/upstream/ecc/skills/email-ops/SKILL.md +121 -0
  225. package/bundled/upstream/ecc/skills/energy-procurement/SKILL.md +228 -0
  226. package/bundled/upstream/ecc/skills/enterprise-agent-ops/SKILL.md +50 -0
  227. package/bundled/upstream/ecc/skills/eval-harness/SKILL.md +270 -0
  228. package/bundled/upstream/ecc/skills/evm-token-decimals/SKILL.md +130 -0
  229. package/bundled/upstream/ecc/skills/exa-search/SKILL.md +103 -0
  230. package/bundled/upstream/ecc/skills/fal-ai-media/SKILL.md +284 -0
  231. package/bundled/upstream/ecc/skills/finance-billing-ops/SKILL.md +127 -0
  232. package/bundled/upstream/ecc/skills/flutter-dart-code-review/SKILL.md +435 -0
  233. package/bundled/upstream/ecc/skills/foundation-models-on-device/SKILL.md +243 -0
  234. package/bundled/upstream/ecc/skills/frontend-design/SKILL.md +145 -0
  235. package/bundled/upstream/ecc/skills/frontend-patterns/SKILL.md +642 -0
  236. package/bundled/upstream/ecc/skills/frontend-slides/SKILL.md +184 -0
  237. package/bundled/upstream/ecc/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  238. package/bundled/upstream/ecc/skills/gan-style-harness/SKILL.md +278 -0
  239. package/bundled/upstream/ecc/skills/gateguard/SKILL.md +121 -0
  240. package/bundled/upstream/ecc/skills/git-workflow/SKILL.md +715 -0
  241. package/bundled/upstream/ecc/skills/github-ops/SKILL.md +144 -0
  242. package/bundled/upstream/ecc/skills/golang-patterns/SKILL.md +674 -0
  243. package/bundled/upstream/ecc/skills/golang-testing/SKILL.md +720 -0
  244. package/bundled/upstream/ecc/skills/google-workspace-ops/SKILL.md +95 -0
  245. package/bundled/upstream/ecc/skills/healthcare-cdss-patterns/SKILL.md +245 -0
  246. package/bundled/upstream/ecc/skills/healthcare-emr-patterns/SKILL.md +159 -0
  247. package/bundled/upstream/ecc/skills/healthcare-eval-harness/SKILL.md +207 -0
  248. package/bundled/upstream/ecc/skills/healthcare-phi-compliance/SKILL.md +145 -0
  249. package/bundled/upstream/ecc/skills/hexagonal-architecture/SKILL.md +276 -0
  250. package/bundled/upstream/ecc/skills/hipaa-compliance/SKILL.md +78 -0
  251. package/bundled/upstream/ecc/skills/hookify-rules/SKILL.md +128 -0
  252. package/bundled/upstream/ecc/skills/inventory-demand-planning/SKILL.md +247 -0
  253. package/bundled/upstream/ecc/skills/investor-materials/SKILL.md +96 -0
  254. package/bundled/upstream/ecc/skills/investor-outreach/SKILL.md +91 -0
  255. package/bundled/upstream/ecc/skills/iterative-retrieval/SKILL.md +211 -0
  256. package/bundled/upstream/ecc/skills/java-coding-standards/SKILL.md +147 -0
  257. package/bundled/upstream/ecc/skills/jira-integration/SKILL.md +293 -0
  258. package/bundled/upstream/ecc/skills/jpa-patterns/SKILL.md +151 -0
  259. package/bundled/upstream/ecc/skills/knowledge-ops/SKILL.md +154 -0
  260. package/bundled/upstream/ecc/skills/kotlin-coroutines-flows/SKILL.md +284 -0
  261. package/bundled/upstream/ecc/skills/kotlin-exposed-patterns/SKILL.md +719 -0
  262. package/bundled/upstream/ecc/skills/kotlin-ktor-patterns/SKILL.md +689 -0
  263. package/bundled/upstream/ecc/skills/kotlin-patterns/SKILL.md +711 -0
  264. package/bundled/upstream/ecc/skills/kotlin-testing/SKILL.md +824 -0
  265. package/bundled/upstream/ecc/skills/laravel-patterns/SKILL.md +415 -0
  266. package/bundled/upstream/ecc/skills/laravel-plugin-discovery/SKILL.md +229 -0
  267. package/bundled/upstream/ecc/skills/laravel-security/SKILL.md +285 -0
  268. package/bundled/upstream/ecc/skills/laravel-tdd/SKILL.md +283 -0
  269. package/bundled/upstream/ecc/skills/laravel-verification/SKILL.md +179 -0
  270. package/bundled/upstream/ecc/skills/lead-intelligence/SKILL.md +321 -0
  271. package/bundled/upstream/ecc/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
  272. package/bundled/upstream/ecc/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
  273. package/bundled/upstream/ecc/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
  274. package/bundled/upstream/ecc/skills/lead-intelligence/agents/signal-scorer.md +60 -0
  275. package/bundled/upstream/ecc/skills/liquid-glass-design/SKILL.md +279 -0
  276. package/bundled/upstream/ecc/skills/llm-trading-agent-security/SKILL.md +146 -0
  277. package/bundled/upstream/ecc/skills/logistics-exception-management/SKILL.md +222 -0
  278. package/bundled/upstream/ecc/skills/manim-video/SKILL.md +89 -0
  279. package/bundled/upstream/ecc/skills/manim-video/assets/network_graph_scene.py +52 -0
  280. package/bundled/upstream/ecc/skills/market-research/SKILL.md +75 -0
  281. package/bundled/upstream/ecc/skills/mcp-server-patterns/SKILL.md +69 -0
  282. package/bundled/upstream/ecc/skills/messages-ops/SKILL.md +104 -0
  283. package/bundled/upstream/ecc/skills/nanoclaw-repl/SKILL.md +33 -0
  284. package/bundled/upstream/ecc/skills/nestjs-patterns/SKILL.md +230 -0
  285. package/bundled/upstream/ecc/skills/nextjs-turbopack/SKILL.md +44 -0
  286. package/bundled/upstream/ecc/skills/nodejs-keccak256/SKILL.md +102 -0
  287. package/bundled/upstream/ecc/skills/nutrient-document-processing/SKILL.md +167 -0
  288. package/bundled/upstream/ecc/skills/nuxt4-patterns/SKILL.md +100 -0
  289. package/bundled/upstream/ecc/skills/openclaw-persona-forge/SKILL.md +296 -0
  290. package/bundled/upstream/ecc/skills/openclaw-persona-forge/gacha.py +224 -0
  291. package/bundled/upstream/ecc/skills/openclaw-persona-forge/gacha.sh +5 -0
  292. package/bundled/upstream/ecc/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
  293. package/bundled/upstream/ecc/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
  294. package/bundled/upstream/ecc/skills/openclaw-persona-forge/references/error-handling.md +53 -0
  295. package/bundled/upstream/ecc/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
  296. package/bundled/upstream/ecc/skills/openclaw-persona-forge/references/naming-system.md +39 -0
  297. package/bundled/upstream/ecc/skills/openclaw-persona-forge/references/output-template.md +166 -0
  298. package/bundled/upstream/ecc/skills/opensource-pipeline/SKILL.md +255 -0
  299. package/bundled/upstream/ecc/skills/perl-patterns/SKILL.md +504 -0
  300. package/bundled/upstream/ecc/skills/perl-security/SKILL.md +503 -0
  301. package/bundled/upstream/ecc/skills/perl-testing/SKILL.md +475 -0
  302. package/bundled/upstream/ecc/skills/plankton-code-quality/SKILL.md +236 -0
  303. package/bundled/upstream/ecc/skills/postgres-patterns/SKILL.md +147 -0
  304. package/bundled/upstream/ecc/skills/product-capability/SKILL.md +141 -0
  305. package/bundled/upstream/ecc/skills/product-lens/SKILL.md +92 -0
  306. package/bundled/upstream/ecc/skills/production-scheduling/SKILL.md +238 -0
  307. package/bundled/upstream/ecc/skills/project-flow-ops/SKILL.md +111 -0
  308. package/bundled/upstream/ecc/skills/prompt-optimizer/SKILL.md +397 -0
  309. package/bundled/upstream/ecc/skills/python-patterns/SKILL.md +750 -0
  310. package/bundled/upstream/ecc/skills/python-testing/SKILL.md +816 -0
  311. package/bundled/upstream/ecc/skills/pytorch-patterns/SKILL.md +396 -0
  312. package/bundled/upstream/ecc/skills/quality-nonconformance/SKILL.md +260 -0
  313. package/bundled/upstream/ecc/skills/ralphinho-rfc-pipeline/SKILL.md +67 -0
  314. package/bundled/upstream/ecc/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
  315. package/bundled/upstream/ecc/skills/remotion-video-creation/SKILL.md +43 -0
  316. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/3d.md +86 -0
  317. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/animations.md +29 -0
  318. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
  319. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
  320. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
  321. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/assets.md +78 -0
  322. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/audio.md +172 -0
  323. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
  324. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/can-decode.md +75 -0
  325. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/charts.md +58 -0
  326. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/compositions.md +146 -0
  327. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/display-captions.md +126 -0
  328. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/extract-frames.md +229 -0
  329. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/fonts.md +152 -0
  330. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
  331. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
  332. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
  333. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/gifs.md +138 -0
  334. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/images.md +130 -0
  335. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
  336. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/lottie.md +67 -0
  337. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
  338. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/measuring-text.md +143 -0
  339. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/sequencing.md +106 -0
  340. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/tailwind.md +11 -0
  341. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/text-animations.md +20 -0
  342. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/timing.md +179 -0
  343. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
  344. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/transitions.md +122 -0
  345. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/trimming.md +52 -0
  346. package/bundled/upstream/ecc/skills/remotion-video-creation/rules/videos.md +171 -0
  347. package/bundled/upstream/ecc/skills/repo-scan/SKILL.md +78 -0
  348. package/bundled/upstream/ecc/skills/research-ops/SKILL.md +112 -0
  349. package/bundled/upstream/ecc/skills/returns-reverse-logistics/SKILL.md +240 -0
  350. package/bundled/upstream/ecc/skills/rules-distill/SKILL.md +264 -0
  351. package/bundled/upstream/ecc/skills/rules-distill/scripts/scan-rules.sh +58 -0
  352. package/bundled/upstream/ecc/skills/rules-distill/scripts/scan-skills.sh +129 -0
  353. package/bundled/upstream/ecc/skills/rust-patterns/SKILL.md +499 -0
  354. package/bundled/upstream/ecc/skills/rust-testing/SKILL.md +500 -0
  355. package/bundled/upstream/ecc/skills/safety-guard/SKILL.md +75 -0
  356. package/bundled/upstream/ecc/skills/santa-method/SKILL.md +306 -0
  357. package/bundled/upstream/ecc/skills/search-first/SKILL.md +161 -0
  358. package/bundled/upstream/ecc/skills/security-bounty-hunter/SKILL.md +99 -0
  359. package/bundled/upstream/ecc/skills/security-review/SKILL.md +495 -0
  360. package/bundled/upstream/ecc/skills/security-review/cloud-infrastructure-security.md +361 -0
  361. package/bundled/upstream/ecc/skills/security-scan/SKILL.md +165 -0
  362. package/bundled/upstream/ecc/skills/seo/SKILL.md +154 -0
  363. package/bundled/upstream/ecc/skills/skill-comply/SKILL.md +58 -0
  364. package/bundled/upstream/ecc/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
  365. package/bundled/upstream/ecc/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
  366. package/bundled/upstream/ecc/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
  367. package/bundled/upstream/ecc/skills/skill-comply/prompts/classifier.md +24 -0
  368. package/bundled/upstream/ecc/skills/skill-comply/prompts/scenario_generator.md +62 -0
  369. package/bundled/upstream/ecc/skills/skill-comply/prompts/spec_generator.md +42 -0
  370. package/bundled/upstream/ecc/skills/skill-comply/pyproject.toml +15 -0
  371. package/bundled/upstream/ecc/skills/skill-comply/scripts/__init__.py +0 -0
  372. package/bundled/upstream/ecc/skills/skill-comply/scripts/classifier.py +85 -0
  373. package/bundled/upstream/ecc/skills/skill-comply/scripts/grader.py +124 -0
  374. package/bundled/upstream/ecc/skills/skill-comply/scripts/parser.py +107 -0
  375. package/bundled/upstream/ecc/skills/skill-comply/scripts/report.py +170 -0
  376. package/bundled/upstream/ecc/skills/skill-comply/scripts/run.py +127 -0
  377. package/bundled/upstream/ecc/skills/skill-comply/scripts/runner.py +161 -0
  378. package/bundled/upstream/ecc/skills/skill-comply/scripts/scenario_generator.py +70 -0
  379. package/bundled/upstream/ecc/skills/skill-comply/scripts/spec_generator.py +72 -0
  380. package/bundled/upstream/ecc/skills/skill-comply/scripts/utils.py +13 -0
  381. package/bundled/upstream/ecc/skills/skill-comply/tests/test_grader.py +197 -0
  382. package/bundled/upstream/ecc/skills/skill-comply/tests/test_parser.py +90 -0
  383. package/bundled/upstream/ecc/skills/skill-stocktake/SKILL.md +193 -0
  384. package/bundled/upstream/ecc/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
  385. package/bundled/upstream/ecc/skills/skill-stocktake/scripts/save-results.sh +56 -0
  386. package/bundled/upstream/ecc/skills/skill-stocktake/scripts/scan.sh +170 -0
  387. package/bundled/upstream/ecc/skills/social-graph-ranker/SKILL.md +154 -0
  388. package/bundled/upstream/ecc/skills/springboot-patterns/SKILL.md +314 -0
  389. package/bundled/upstream/ecc/skills/springboot-security/SKILL.md +272 -0
  390. package/bundled/upstream/ecc/skills/springboot-tdd/SKILL.md +158 -0
  391. package/bundled/upstream/ecc/skills/springboot-verification/SKILL.md +231 -0
  392. package/bundled/upstream/ecc/skills/strategic-compact/SKILL.md +131 -0
  393. package/bundled/upstream/ecc/skills/strategic-compact/suggest-compact.sh +54 -0
  394. package/bundled/upstream/ecc/skills/swift-actor-persistence/SKILL.md +143 -0
  395. package/bundled/upstream/ecc/skills/swift-concurrency-6-2/SKILL.md +216 -0
  396. package/bundled/upstream/ecc/skills/swift-protocol-di-testing/SKILL.md +190 -0
  397. package/bundled/upstream/ecc/skills/swiftui-patterns/SKILL.md +259 -0
  398. package/bundled/upstream/ecc/skills/tdd-workflow/SKILL.md +463 -0
  399. package/bundled/upstream/ecc/skills/team-builder/SKILL.md +168 -0
  400. package/bundled/upstream/ecc/skills/terminal-ops/SKILL.md +109 -0
  401. package/bundled/upstream/ecc/skills/token-budget-advisor/SKILL.md +133 -0
  402. package/bundled/upstream/ecc/skills/ui-demo/SKILL.md +465 -0
  403. package/bundled/upstream/ecc/skills/unified-notifications-ops/SKILL.md +187 -0
  404. package/bundled/upstream/ecc/skills/verification-loop/SKILL.md +126 -0
  405. package/bundled/upstream/ecc/skills/video-editing/SKILL.md +310 -0
  406. package/bundled/upstream/ecc/skills/videodb/SKILL.md +374 -0
  407. package/bundled/upstream/ecc/skills/videodb/reference/api-reference.md +550 -0
  408. package/bundled/upstream/ecc/skills/videodb/reference/capture-reference.md +407 -0
  409. package/bundled/upstream/ecc/skills/videodb/reference/capture.md +101 -0
  410. package/bundled/upstream/ecc/skills/videodb/reference/editor.md +443 -0
  411. package/bundled/upstream/ecc/skills/videodb/reference/generative.md +331 -0
  412. package/bundled/upstream/ecc/skills/videodb/reference/rtstream-reference.md +564 -0
  413. package/bundled/upstream/ecc/skills/videodb/reference/rtstream.md +65 -0
  414. package/bundled/upstream/ecc/skills/videodb/reference/search.md +230 -0
  415. package/bundled/upstream/ecc/skills/videodb/reference/streaming.md +406 -0
  416. package/bundled/upstream/ecc/skills/videodb/reference/use-cases.md +118 -0
  417. package/bundled/upstream/ecc/skills/videodb/scripts/ws_listener.py +282 -0
  418. package/bundled/upstream/ecc/skills/visa-doc-translate/README.md +86 -0
  419. package/bundled/upstream/ecc/skills/visa-doc-translate/SKILL.md +117 -0
  420. package/bundled/upstream/ecc/skills/workspace-surface-audit/SKILL.md +125 -0
  421. package/bundled/upstream/ecc/skills/x-api/SKILL.md +230 -0
  422. package/bundled/upstream/superpowers/.omc-source/last-plan-apply.json +22 -0
  423. package/package.json +3 -1
  424. package/src/catalog/source-catalog.js +391 -0
  425. package/src/cli/artifact.js +3 -2
  426. package/src/cli/doctor.js +25 -4
  427. package/src/cli/index.js +19 -0
  428. package/src/cli/plan.js +220 -0
  429. package/src/cli/setup.js +209 -12
  430. package/src/cli/source.js +110 -3
  431. package/src/config/paths.js +31 -0
  432. package/src/config/sources.js +103 -10
  433. package/src/merge/hook-merger.js +1 -0
@@ -0,0 +1,237 @@
1
+ # Hooks
2
+
3
+ Hooks are event-driven automations that fire before or after Claude Code tool executions. They enforce code quality, catch mistakes early, and automate repetitive checks.
4
+
5
+ ## How Hooks Work
6
+
7
+ ```
8
+ User request → Claude picks a tool → PreToolUse hook runs → Tool executes → PostToolUse hook runs
9
+ ```
10
+
11
+ - **PreToolUse** hooks run before the tool executes. They can **block** (exit code 2) or **warn** (stderr without blocking).
12
+ - **PostToolUse** hooks run after the tool completes. They can analyze output but cannot block.
13
+ - **Stop** hooks run after each Claude response.
14
+ - **SessionStart/SessionEnd** hooks run at session lifecycle boundaries.
15
+ - **PreCompact** hooks run before context compaction, useful for saving state.
16
+
17
+ ## Hooks in This Plugin
18
+
19
+ ## Installing These Hooks Manually
20
+
21
+ For Claude Code manual installs, do not paste the raw repo `hooks.json` into `~/.claude/settings.json` or copy it directly into `~/.claude/hooks/hooks.json`. The checked-in file is plugin/repo-oriented and is meant to be installed through the ECC installer or loaded as a plugin.
22
+
23
+ Use the installer instead so hook commands are rewritten against your actual Claude root:
24
+
25
+ ```bash
26
+ bash ./install.sh --target claude --modules hooks-runtime
27
+ ```
28
+
29
+ ```powershell
30
+ pwsh -File .\install.ps1 --target claude --modules hooks-runtime
31
+ ```
32
+
33
+ That installs resolved hooks to `~/.claude/hooks/hooks.json`. On Windows, the Claude config root is `%USERPROFILE%\\.claude`.
34
+
35
+ ### PreToolUse Hooks
36
+
37
+ | Hook | Matcher | Behavior | Exit Code |
38
+ |------|---------|----------|-----------|
39
+ | **Dev server blocker** | `Bash` | Blocks `npm run dev` etc. outside tmux — ensures log access | 2 (blocks) |
40
+ | **Tmux reminder** | `Bash` | Suggests tmux for long-running commands (npm test, cargo build, docker) | 0 (warns) |
41
+ | **Git push reminder** | `Bash` | Reminds to review changes before `git push` | 0 (warns) |
42
+ | **Pre-commit quality check** | `Bash` | Runs quality checks before `git commit`: lints staged files, validates commit message format when provided via `-m/--message`, detects console.log/debugger/secrets | 2 (blocks critical) / 0 (warns) |
43
+ | **Doc file warning** | `Write` | Warns about non-standard `.md`/`.txt` files (allows README, CLAUDE, CONTRIBUTING, CHANGELOG, LICENSE, SKILL, docs/, skills/); cross-platform path handling | 0 (warns) |
44
+ | **Strategic compact** | `Edit\|Write` | Suggests manual `/compact` at logical intervals (every ~50 tool calls) | 0 (warns) |
45
+
46
+ ### PostToolUse Hooks
47
+
48
+ | Hook | Matcher | What It Does |
49
+ |------|---------|-------------|
50
+ | **PR logger** | `Bash` | Logs PR URL and review command after `gh pr create` |
51
+ | **Build analysis** | `Bash` | Background analysis after build commands (async, non-blocking) |
52
+ | **Quality gate** | `Edit\|Write\|MultiEdit` | Runs fast quality checks after edits |
53
+ | **Design quality check** | `Edit\|Write\|MultiEdit` | Warns when frontend edits drift toward generic template-looking UI |
54
+ | **Prettier format** | `Edit` | Auto-formats JS/TS files with Prettier after edits |
55
+ | **TypeScript check** | `Edit` | Runs `tsc --noEmit` after editing `.ts`/`.tsx` files |
56
+ | **console.log warning** | `Edit` | Warns about `console.log` statements in edited files |
57
+
58
+ ### Lifecycle Hooks
59
+
60
+ | Hook | Event | What It Does |
61
+ |------|-------|-------------|
62
+ | **Session start** | `SessionStart` | Loads previous context and detects package manager |
63
+ | **Pre-compact** | `PreCompact` | Saves state before context compaction |
64
+ | **Console.log audit** | `Stop` | Checks all modified files for `console.log` after each response |
65
+ | **Session summary** | `Stop` | Persists session state when transcript path is available |
66
+ | **Pattern extraction** | `Stop` | Evaluates session for extractable patterns (continuous learning) |
67
+ | **Cost tracker** | `Stop` | Emits lightweight run-cost telemetry markers |
68
+ | **Desktop notify** | `Stop` | Sends macOS desktop notification with task summary (standard+) |
69
+ | **Session end marker** | `SessionEnd` | Lifecycle marker and cleanup log |
70
+
71
+ ## Customizing Hooks
72
+
73
+ ### Disabling a Hook
74
+
75
+ Remove or comment out the hook entry in `hooks.json`. If installed as a plugin, override in your `~/.claude/settings.json`:
76
+
77
+ ```json
78
+ {
79
+ "hooks": {
80
+ "PreToolUse": [
81
+ {
82
+ "matcher": "Write",
83
+ "hooks": [],
84
+ "description": "Override: allow all .md file creation"
85
+ }
86
+ ]
87
+ }
88
+ }
89
+ ```
90
+
91
+ ### Runtime Hook Controls (Recommended)
92
+
93
+ Use environment variables to control hook behavior without editing `hooks.json`:
94
+
95
+ ```bash
96
+ # minimal | standard | strict (default: standard)
97
+ export ECC_HOOK_PROFILE=standard
98
+
99
+ # Disable specific hook IDs (comma-separated)
100
+ export ECC_DISABLED_HOOKS="pre:bash:tmux-reminder,post:edit:typecheck"
101
+ ```
102
+
103
+ Profiles:
104
+ - `minimal` — keep essential lifecycle and safety hooks only.
105
+ - `standard` — default; balanced quality + safety checks.
106
+ - `strict` — enables additional reminders and stricter guardrails.
107
+
108
+ ### Writing Your Own Hook
109
+
110
+ Hooks are shell commands that receive tool input as JSON on stdin and must output JSON on stdout.
111
+
112
+ **Basic structure:**
113
+
114
+ ```javascript
115
+ // my-hook.js
116
+ let data = '';
117
+ process.stdin.on('data', chunk => data += chunk);
118
+ process.stdin.on('end', () => {
119
+ const input = JSON.parse(data);
120
+
121
+ // Access tool info
122
+ const toolName = input.tool_name; // "Edit", "Bash", "Write", etc.
123
+ const toolInput = input.tool_input; // Tool-specific parameters
124
+ const toolOutput = input.tool_output; // Only available in PostToolUse
125
+
126
+ // Warn (non-blocking): write to stderr
127
+ console.error('[Hook] Warning message shown to Claude');
128
+
129
+ // Block (PreToolUse only): exit with code 2
130
+ // process.exit(2);
131
+
132
+ // Always output the original data to stdout
133
+ console.log(data);
134
+ });
135
+ ```
136
+
137
+ **Exit codes:**
138
+ - `0` — Success (continue execution)
139
+ - `2` — Block the tool call (PreToolUse only)
140
+ - Other non-zero — Error (logged but does not block)
141
+
142
+ ### Hook Input Schema
143
+
144
+ ```typescript
145
+ interface HookInput {
146
+ tool_name: string; // "Bash", "Edit", "Write", "Read", etc.
147
+ tool_input: {
148
+ command?: string; // Bash: the command being run
149
+ file_path?: string; // Edit/Write/Read: target file
150
+ old_string?: string; // Edit: text being replaced
151
+ new_string?: string; // Edit: replacement text
152
+ content?: string; // Write: file content
153
+ };
154
+ tool_output?: { // PostToolUse only
155
+ output?: string; // Command/tool output
156
+ };
157
+ }
158
+ ```
159
+
160
+ ### Async Hooks
161
+
162
+ For hooks that should not block the main flow (e.g., background analysis):
163
+
164
+ ```json
165
+ {
166
+ "type": "command",
167
+ "command": "node my-slow-hook.js",
168
+ "async": true,
169
+ "timeout": 30
170
+ }
171
+ ```
172
+
173
+ Async hooks run in the background. They cannot block tool execution.
174
+
175
+ ## Common Hook Recipes
176
+
177
+ ### Warn about TODO comments
178
+
179
+ ```json
180
+ {
181
+ "matcher": "Edit",
182
+ "hooks": [{
183
+ "type": "command",
184
+ "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const ns=i.tool_input?.new_string||'';if(/TODO|FIXME|HACK/.test(ns)){console.error('[Hook] New TODO/FIXME added - consider creating an issue')}console.log(d)})\""
185
+ }],
186
+ "description": "Warn when adding TODO/FIXME comments"
187
+ }
188
+ ```
189
+
190
+ ### Block large file creation
191
+
192
+ ```json
193
+ {
194
+ "matcher": "Write",
195
+ "hooks": [{
196
+ "type": "command",
197
+ "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const c=i.tool_input?.content||'';const lines=c.split('\\n').length;if(lines>800){console.error('[Hook] BLOCKED: File exceeds 800 lines ('+lines+' lines)');console.error('[Hook] Split into smaller, focused modules');process.exit(2)}console.log(d)})\""
198
+ }],
199
+ "description": "Block creation of files larger than 800 lines"
200
+ }
201
+ ```
202
+
203
+ ### Auto-format Python files with ruff
204
+
205
+ ```json
206
+ {
207
+ "matcher": "Edit",
208
+ "hooks": [{
209
+ "type": "command",
210
+ "command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path||'';if(/\\.py$/.test(p)){const{execFileSync}=require('child_process');try{execFileSync('ruff',['format',p],{stdio:'pipe'})}catch(e){}}console.log(d)})\""
211
+ }],
212
+ "description": "Auto-format Python files with ruff after edits"
213
+ }
214
+ ```
215
+
216
+ ### Require test files alongside new source files
217
+
218
+ ```json
219
+ {
220
+ "matcher": "Write",
221
+ "hooks": [{
222
+ "type": "command",
223
+ "command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path||'';if(/src\\/.*\\.(ts|js)$/.test(p)&&!/\\.test\\.|\\.spec\\./.test(p)){const testPath=p.replace(/\\.(ts|js)$/,'.test.$1');if(!fs.existsSync(testPath)){console.error('[Hook] No test file found for: '+p);console.error('[Hook] Expected: '+testPath);console.error('[Hook] Consider writing tests first (/tdd)')}}console.log(d)})\""
224
+ }],
225
+ "description": "Remind to create tests when adding new source files"
226
+ }
227
+ ```
228
+
229
+ ## Cross-Platform Notes
230
+
231
+ Hook logic is implemented in Node.js scripts for cross-platform behavior on Windows, macOS, and Linux. A small number of shell wrappers are retained for continuous-learning observer hooks; those wrappers are profile-gated and have Windows-safe fallback behavior.
232
+
233
+ ## Related
234
+
235
+ - [rules/common/hooks.md](../rules/common/hooks.md) — Hook architecture guidelines
236
+ - [skills/strategic-compact/](../skills/strategic-compact/) — Strategic compaction skill
237
+ - [scripts/hooks/](../scripts/hooks/) — Hook script implementations
@@ -0,0 +1,330 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
+ "hooks": {
4
+ "PreToolUse": [
5
+ {
6
+ "matcher": "Bash",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/pre-bash-dispatcher.js"
11
+ }
12
+ ],
13
+ "description": "Consolidated Bash preflight dispatcher for quality, tmux, push, and GateGuard checks",
14
+ "id": "pre:bash:dispatcher"
15
+ },
16
+ {
17
+ "matcher": "Write",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:write:doc-file-warning scripts/hooks/doc-file-warning.js standard,strict"
22
+ }
23
+ ],
24
+ "description": "Doc file warning: warn about non-standard documentation files (exit code 0; warns only)",
25
+ "id": "pre:write:doc-file-warning"
26
+ },
27
+ {
28
+ "matcher": "Edit|Write",
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:edit-write:suggest-compact scripts/hooks/suggest-compact.js standard,strict"
33
+ }
34
+ ],
35
+ "description": "Suggest manual compaction at logical intervals",
36
+ "id": "pre:edit-write:suggest-compact"
37
+ },
38
+ {
39
+ "matcher": "*",
40
+ "hooks": [
41
+ {
42
+ "type": "command",
43
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" shell scripts/hooks/run-with-flags-shell.sh pre:observe skills/continuous-learning-v2/hooks/observe.sh standard,strict",
44
+ "async": true,
45
+ "timeout": 10
46
+ }
47
+ ],
48
+ "description": "Capture tool use observations for continuous learning",
49
+ "id": "pre:observe:continuous-learning"
50
+ },
51
+ {
52
+ "matcher": "Bash|Write|Edit|MultiEdit",
53
+ "hooks": [
54
+ {
55
+ "type": "command",
56
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:governance-capture scripts/hooks/governance-capture.js standard,strict",
57
+ "timeout": 10
58
+ }
59
+ ],
60
+ "description": "Capture governance events (secrets, policy violations, approval requests). Enable with ECC_GOVERNANCE_CAPTURE=1",
61
+ "id": "pre:governance-capture"
62
+ },
63
+ {
64
+ "matcher": "Write|Edit|MultiEdit",
65
+ "hooks": [
66
+ {
67
+ "type": "command",
68
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:config-protection scripts/hooks/config-protection.js standard,strict",
69
+ "timeout": 5
70
+ }
71
+ ],
72
+ "description": "Block modifications to linter/formatter config files. Steers agent to fix code instead of weakening configs.",
73
+ "id": "pre:config-protection"
74
+ },
75
+ {
76
+ "matcher": "*",
77
+ "hooks": [
78
+ {
79
+ "type": "command",
80
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:mcp-health-check scripts/hooks/mcp-health-check.js standard,strict"
81
+ }
82
+ ],
83
+ "description": "Check MCP server health before MCP tool execution and block unhealthy MCP calls",
84
+ "id": "pre:mcp-health-check"
85
+ },
86
+ {
87
+ "matcher": "Edit|Write|MultiEdit",
88
+ "hooks": [
89
+ {
90
+ "type": "command",
91
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:edit-write:gateguard-fact-force scripts/hooks/gateguard-fact-force.js standard,strict",
92
+ "timeout": 5
93
+ }
94
+ ],
95
+ "description": "Fact-forcing gate: block first Edit/Write/MultiEdit per file and demand investigation (importers, data schemas, user instruction) before allowing",
96
+ "id": "pre:edit-write:gateguard-fact-force"
97
+ }
98
+ ],
99
+ "PreCompact": [
100
+ {
101
+ "matcher": "*",
102
+ "hooks": [
103
+ {
104
+ "type": "command",
105
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js pre:compact scripts/hooks/pre-compact.js standard,strict"
106
+ }
107
+ ],
108
+ "description": "Save state before context compaction",
109
+ "id": "pre:compact"
110
+ }
111
+ ],
112
+ "SessionStart": [
113
+ {
114
+ "matcher": "*",
115
+ "hooks": [
116
+ {
117
+ "type": "command",
118
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/session-start-bootstrap.js"
119
+ }
120
+ ],
121
+ "description": "Load previous context and detect package manager on new session",
122
+ "id": "session:start"
123
+ }
124
+ ],
125
+ "PostToolUse": [
126
+ {
127
+ "matcher": "Bash",
128
+ "hooks": [
129
+ {
130
+ "type": "command",
131
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/post-bash-dispatcher.js",
132
+ "async": true,
133
+ "timeout": 30
134
+ }
135
+ ],
136
+ "description": "Consolidated Bash postflight dispatcher for logging, PR, and build notifications",
137
+ "id": "post:bash:dispatcher"
138
+ },
139
+ {
140
+ "matcher": "Edit|Write|MultiEdit",
141
+ "hooks": [
142
+ {
143
+ "type": "command",
144
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:quality-gate scripts/hooks/quality-gate.js standard,strict",
145
+ "async": true,
146
+ "timeout": 30
147
+ }
148
+ ],
149
+ "description": "Run quality gate checks after file edits",
150
+ "id": "post:quality-gate"
151
+ },
152
+ {
153
+ "matcher": "Edit|Write|MultiEdit",
154
+ "hooks": [
155
+ {
156
+ "type": "command",
157
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:edit:design-quality-check scripts/hooks/design-quality-check.js standard,strict",
158
+ "timeout": 10
159
+ }
160
+ ],
161
+ "description": "Warn when frontend edits drift toward generic template-looking UI",
162
+ "id": "post:edit:design-quality-check"
163
+ },
164
+ {
165
+ "matcher": "Edit|Write|MultiEdit",
166
+ "hooks": [
167
+ {
168
+ "type": "command",
169
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:edit:accumulate scripts/hooks/post-edit-accumulator.js standard,strict"
170
+ }
171
+ ],
172
+ "description": "Record edited JS/TS file paths for batch format+typecheck at Stop time",
173
+ "id": "post:edit:accumulator"
174
+ },
175
+ {
176
+ "matcher": "Edit",
177
+ "hooks": [
178
+ {
179
+ "type": "command",
180
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:edit:console-warn scripts/hooks/post-edit-console-warn.js standard,strict"
181
+ }
182
+ ],
183
+ "description": "Warn about console.log statements after edits",
184
+ "id": "post:edit:console-warn"
185
+ },
186
+ {
187
+ "matcher": "Bash|Write|Edit|MultiEdit",
188
+ "hooks": [
189
+ {
190
+ "type": "command",
191
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:governance-capture scripts/hooks/governance-capture.js standard,strict",
192
+ "timeout": 10
193
+ }
194
+ ],
195
+ "description": "Capture governance events from tool outputs. Enable with ECC_GOVERNANCE_CAPTURE=1",
196
+ "id": "post:governance-capture"
197
+ },
198
+ {
199
+ "matcher": "*",
200
+ "hooks": [
201
+ {
202
+ "type": "command",
203
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:session-activity-tracker scripts/hooks/session-activity-tracker.js standard,strict",
204
+ "timeout": 10
205
+ }
206
+ ],
207
+ "description": "Track per-session tool calls and file activity for ECC2 metrics",
208
+ "id": "post:session-activity-tracker"
209
+ },
210
+ {
211
+ "matcher": "*",
212
+ "hooks": [
213
+ {
214
+ "type": "command",
215
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" shell scripts/hooks/run-with-flags-shell.sh post:observe skills/continuous-learning-v2/hooks/observe.sh standard,strict",
216
+ "async": true,
217
+ "timeout": 10
218
+ }
219
+ ],
220
+ "description": "Capture tool use results for continuous learning",
221
+ "id": "post:observe:continuous-learning"
222
+ }
223
+ ],
224
+ "PostToolUseFailure": [
225
+ {
226
+ "matcher": "*",
227
+ "hooks": [
228
+ {
229
+ "type": "command",
230
+ "command": "node -e \"const p=require('path');const r=(()=>{var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var p=require('path'),f=require('fs'),h=require('os').homedir(),d=p.join(h,'.claude'),q=p.join('scripts','lib','utils.js');if(f.existsSync(p.join(d,q)))return d;for(var s of [[\\\"ecc\\\"],[\\\"ecc@ecc\\\"],[\\\"marketplace\\\",\\\"ecc\\\"],[\\\"everything-claude-code\\\"],[\\\"everything-claude-code@everything-claude-code\\\"],[\\\"marketplace\\\",\\\"everything-claude-code\\\"]]){var l=p.join(d,'plugins',...s);if(f.existsSync(p.join(l,q)))return l}try{for(var g of [\\\"ecc\\\",\\\"everything-claude-code\\\"]){var b=p.join(d,'plugins','cache',g);for(var o of f.readdirSync(b,{withFileTypes:true})){if(!o.isDirectory())continue;for(var v of f.readdirSync(p.join(b,o.name),{withFileTypes:true})){if(!v.isDirectory())continue;var c=p.join(b,o.name,v.name);if(f.existsSync(p.join(c,q)))return c}}}}catch(x){}return d})();const s=p.join(r,'scripts/hooks/plugin-hook-bootstrap.js');process.env.CLAUDE_PLUGIN_ROOT=r;process.argv.splice(1,0,s);require(s)\" node scripts/hooks/run-with-flags.js post:mcp-health-check scripts/hooks/mcp-health-check.js standard,strict"
231
+ }
232
+ ],
233
+ "description": "Track failed MCP tool calls, mark unhealthy servers, and attempt reconnect",
234
+ "id": "post:mcp-health-check"
235
+ }
236
+ ],
237
+ "Stop": [
238
+ {
239
+ "matcher": "*",
240
+ "hooks": [
241
+ {
242
+ "type": "command",
243
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:format-typecheck','scripts/hooks/stop-format-typecheck.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:300000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
244
+ "timeout": 300
245
+ }
246
+ ],
247
+ "description": "Batch format (Biome/Prettier) and typecheck (tsc) all JS/TS files edited this response — runs once at Stop instead of after every Edit",
248
+ "id": "stop:format-typecheck"
249
+ },
250
+ {
251
+ "matcher": "*",
252
+ "hooks": [
253
+ {
254
+ "type": "command",
255
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:check-console-log','scripts/hooks/check-console-log.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\""
256
+ }
257
+ ],
258
+ "description": "Check for console.log in modified files after each response",
259
+ "id": "stop:check-console-log"
260
+ },
261
+ {
262
+ "matcher": "*",
263
+ "hooks": [
264
+ {
265
+ "type": "command",
266
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:session-end','scripts/hooks/session-end.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
267
+ "async": true,
268
+ "timeout": 10
269
+ }
270
+ ],
271
+ "description": "Persist session state after each response (Stop carries transcript_path)",
272
+ "id": "stop:session-end"
273
+ },
274
+ {
275
+ "matcher": "*",
276
+ "hooks": [
277
+ {
278
+ "type": "command",
279
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:evaluate-session','scripts/hooks/evaluate-session.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
280
+ "async": true,
281
+ "timeout": 10
282
+ }
283
+ ],
284
+ "description": "Evaluate session for extractable patterns",
285
+ "id": "stop:evaluate-session"
286
+ },
287
+ {
288
+ "matcher": "*",
289
+ "hooks": [
290
+ {
291
+ "type": "command",
292
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:cost-tracker','scripts/hooks/cost-tracker.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
293
+ "async": true,
294
+ "timeout": 10
295
+ }
296
+ ],
297
+ "description": "Track token and cost metrics per session",
298
+ "id": "stop:cost-tracker"
299
+ },
300
+ {
301
+ "matcher": "*",
302
+ "hooks": [
303
+ {
304
+ "type": "command",
305
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'stop:desktop-notify','scripts/hooks/desktop-notify.js','standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[Stop] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[Stop] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
306
+ "async": true,
307
+ "timeout": 10
308
+ }
309
+ ],
310
+ "description": "Send desktop notification (macOS/WSL) with task summary when Claude responds",
311
+ "id": "stop:desktop-notify"
312
+ }
313
+ ],
314
+ "SessionEnd": [
315
+ {
316
+ "matcher": "*",
317
+ "hooks": [
318
+ {
319
+ "type": "command",
320
+ "command": "node -e \"const fs=require('fs');const path=require('path');const {spawnSync}=require('child_process');const raw=fs.readFileSync(0,'utf8');const rel=path.join('scripts','hooks','run-with-flags.js');const hasRunnerRoot=candidate=>{const value=typeof candidate==='string'?candidate.trim():'';return value.length>0&&fs.existsSync(path.join(path.resolve(value),rel));};const root=(()=>{const envRoot=process.env.CLAUDE_PLUGIN_ROOT||'';if(hasRunnerRoot(envRoot))return path.resolve(envRoot.trim());const home=require('os').homedir();const claudeDir=path.join(home,'.claude');if(hasRunnerRoot(claudeDir))return claudeDir;for(const candidate of [path.join(claudeDir,'plugins','ecc'),path.join(claudeDir,'plugins','ecc@ecc'),path.join(claudeDir,'plugins','marketplace','ecc'),path.join(claudeDir,'plugins','everything-claude-code'),path.join(claudeDir,'plugins','everything-claude-code@everything-claude-code'),path.join(claudeDir,'plugins','marketplace','everything-claude-code')]){if(hasRunnerRoot(candidate))return candidate;}try{for(const slug of ['ecc','everything-claude-code']){const cacheBase=path.join(claudeDir,'plugins','cache',slug);for(const org of fs.readdirSync(cacheBase,{withFileTypes:true})){if(!org.isDirectory())continue;for(const version of fs.readdirSync(path.join(cacheBase,org.name),{withFileTypes:true})){if(!version.isDirectory())continue;const candidate=path.join(cacheBase,org.name,version.name);if(hasRunnerRoot(candidate))return candidate;}}}}catch{}return claudeDir;})();const script=path.join(root,rel);if(fs.existsSync(script)){const result=spawnSync(process.execPath,[script,'session:end:marker','scripts/hooks/session-end-marker.js','minimal,standard,strict'],{input:raw,encoding:'utf8',env:process.env,cwd:process.cwd(),timeout:30000});const stdout=typeof result.stdout==='string'?result.stdout:'';if(stdout)process.stdout.write(stdout);else process.stdout.write(raw);if(result.stderr)process.stderr.write(result.stderr);if(result.error||result.status===null||result.signal){const reason=result.error?result.error.message:(result.signal?'signal '+result.signal:'missing exit status');process.stderr.write('[SessionEnd] ERROR: hook runner failed: '+reason+String.fromCharCode(10));process.exit(1);}process.exit(Number.isInteger(result.status)?result.status:0);}process.stderr.write('[SessionEnd] WARNING: could not resolve ECC plugin root; skipping hook'+String.fromCharCode(10));process.stdout.write(raw);\"",
321
+ "async": true,
322
+ "timeout": 10
323
+ }
324
+ ],
325
+ "description": "Session end lifecycle marker (non-blocking)",
326
+ "id": "session:end:marker"
327
+ }
328
+ ]
329
+ }
330
+ }