@macpaw/cctk 1.0.0-beta.1

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 (415) hide show
  1. package/License +21 -0
  2. package/README.md +142 -0
  3. package/bin/index.js +5 -0
  4. package/dist/index.js +1 -0
  5. package/package.json +65 -0
  6. package/templates/claude/agents/brainstormer.md +113 -0
  7. package/templates/claude/agents/code-reviewer.md +157 -0
  8. package/templates/claude/agents/copywriter.md +110 -0
  9. package/templates/claude/agents/database-admin.md +92 -0
  10. package/templates/claude/agents/debugger.md +137 -0
  11. package/templates/claude/agents/docs-manager.md +208 -0
  12. package/templates/claude/agents/fullstack-developer.md +95 -0
  13. package/templates/claude/agents/git-manager.md +394 -0
  14. package/templates/claude/agents/journal-writer.md +113 -0
  15. package/templates/claude/agents/mcp-manager.md +89 -0
  16. package/templates/claude/agents/planner.md +108 -0
  17. package/templates/claude/agents/project-manager.md +125 -0
  18. package/templates/claude/agents/registry.json +304 -0
  19. package/templates/claude/agents/researcher.md +37 -0
  20. package/templates/claude/agents/scout-external.md +140 -0
  21. package/templates/claude/agents/scout.md +106 -0
  22. package/templates/claude/agents/tester.md +105 -0
  23. package/templates/claude/agents/ui-ux-designer.md +208 -0
  24. package/templates/claude/commands/ask.md +56 -0
  25. package/templates/claude/commands/bootstrap/auto/fast.md +106 -0
  26. package/templates/claude/commands/bootstrap/auto/parallel.md +64 -0
  27. package/templates/claude/commands/bootstrap/auto.md +110 -0
  28. package/templates/claude/commands/bootstrap.md +130 -0
  29. package/templates/claude/commands/brainstorm.md +75 -0
  30. package/templates/claude/commands/code/auto.md +198 -0
  31. package/templates/claude/commands/code/no-test.md +172 -0
  32. package/templates/claude/commands/code/parallel.md +100 -0
  33. package/templates/claude/commands/code.md +197 -0
  34. package/templates/claude/commands/coding-level.md +37 -0
  35. package/templates/claude/commands/content/cro.md +41 -0
  36. package/templates/claude/commands/content/enhance.md +12 -0
  37. package/templates/claude/commands/content/fast.md +11 -0
  38. package/templates/claude/commands/content/good.md +14 -0
  39. package/templates/claude/commands/cook/auto/fast.md +26 -0
  40. package/templates/claude/commands/cook/auto/parallel.md +49 -0
  41. package/templates/claude/commands/cook/auto.md +15 -0
  42. package/templates/claude/commands/cook.md +101 -0
  43. package/templates/claude/commands/debug.md +13 -0
  44. package/templates/claude/commands/docs/init.md +37 -0
  45. package/templates/claude/commands/docs/summarize.md +22 -0
  46. package/templates/claude/commands/docs/update.md +78 -0
  47. package/templates/claude/commands/fix/ci.md +17 -0
  48. package/templates/claude/commands/fix/fast.md +18 -0
  49. package/templates/claude/commands/fix/hard.md +35 -0
  50. package/templates/claude/commands/fix/logs.md +26 -0
  51. package/templates/claude/commands/fix/parallel.md +54 -0
  52. package/templates/claude/commands/fix/test.md +20 -0
  53. package/templates/claude/commands/fix/types.md +9 -0
  54. package/templates/claude/commands/fix/ui.md +33 -0
  55. package/templates/claude/commands/fix.md +43 -0
  56. package/templates/claude/commands/git/cm.md +5 -0
  57. package/templates/claude/commands/git/cp.md +4 -0
  58. package/templates/claude/commands/git/merge.md +40 -0
  59. package/templates/claude/commands/git/pr.md +50 -0
  60. package/templates/claude/commands/journal.md +7 -0
  61. package/templates/claude/commands/kanban.md +99 -0
  62. package/templates/claude/commands/plan/archive.md +57 -0
  63. package/templates/claude/commands/plan/ci.md +33 -0
  64. package/templates/claude/commands/plan/cro.md +67 -0
  65. package/templates/claude/commands/plan/fast.md +66 -0
  66. package/templates/claude/commands/plan/hard.md +92 -0
  67. package/templates/claude/commands/plan/parallel.md +129 -0
  68. package/templates/claude/commands/plan/two.md +45 -0
  69. package/templates/claude/commands/plan/validate.md +117 -0
  70. package/templates/claude/commands/plan.md +30 -0
  71. package/templates/claude/commands/preview.md +87 -0
  72. package/templates/claude/commands/registry.json +313 -0
  73. package/templates/claude/commands/review/codebase/parallel.md +122 -0
  74. package/templates/claude/commands/review/codebase.md +47 -0
  75. package/templates/claude/commands/scout/ext.md +35 -0
  76. package/templates/claude/commands/scout.md +28 -0
  77. package/templates/claude/commands/skill/add.md +36 -0
  78. package/templates/claude/commands/skill/create.md +29 -0
  79. package/templates/claude/commands/skill/fix-logs.md +22 -0
  80. package/templates/claude/commands/skill/optimize/auto.md +25 -0
  81. package/templates/claude/commands/skill/optimize.md +34 -0
  82. package/templates/claude/commands/skill/plan.md +45 -0
  83. package/templates/claude/commands/test/ui.md +91 -0
  84. package/templates/claude/commands/test.md +8 -0
  85. package/templates/claude/commands/use-mcp.md +34 -0
  86. package/templates/claude/commands/watzup.md +8 -0
  87. package/templates/claude/commands/worktree.md +126 -0
  88. package/templates/claude/hooks/dev-rules-reminder.cjs +258 -0
  89. package/templates/claude/hooks/docs/README.md +42 -0
  90. package/templates/claude/hooks/lib/cctk-config-utils.cjs +751 -0
  91. package/templates/claude/hooks/lib/cctk-paths.cjs +106 -0
  92. package/templates/claude/hooks/lib/context-tracker.cjs +346 -0
  93. package/templates/claude/hooks/privacy-block.cjs +289 -0
  94. package/templates/claude/hooks/registry.json +77 -0
  95. package/templates/claude/hooks/scout-block/broad-pattern-detector.cjs +293 -0
  96. package/templates/claude/hooks/scout-block/error-formatter.cjs +156 -0
  97. package/templates/claude/hooks/scout-block/path-extractor.cjs +359 -0
  98. package/templates/claude/hooks/scout-block/pattern-matcher.cjs +184 -0
  99. package/templates/claude/hooks/scout-block/vendor/ignore.js +626 -0
  100. package/templates/claude/hooks/scout-block.cjs +167 -0
  101. package/templates/claude/hooks/session-end.cjs +35 -0
  102. package/templates/claude/hooks/session-init.cjs +214 -0
  103. package/templates/claude/hooks/subagent-init.cjs +161 -0
  104. package/templates/claude/hooks/write-compact-marker.cjs +153 -0
  105. package/templates/claude/output-styles/coding-level-1.md +148 -0
  106. package/templates/claude/output-styles/coding-level-2.md +159 -0
  107. package/templates/claude/output-styles/coding-level-3.md +91 -0
  108. package/templates/claude/scripts/README.md +33 -0
  109. package/templates/claude/scripts/generate-catalogs.cjs +318 -0
  110. package/templates/claude/scripts/registry.json +48 -0
  111. package/templates/claude/scripts/set-active-plan.cjs +45 -0
  112. package/templates/claude/scripts/validate-docs.cjs +447 -0
  113. package/templates/claude/scripts/worktree.cjs +658 -0
  114. package/templates/claude/skills/README.md +112 -0
  115. package/templates/claude/skills/ai-artist/SKILL.md +75 -0
  116. package/templates/claude/skills/ai-artist/references/advanced-techniques.md +184 -0
  117. package/templates/claude/skills/ai-artist/references/domain-code.md +66 -0
  118. package/templates/claude/skills/ai-artist/references/domain-data.md +72 -0
  119. package/templates/claude/skills/ai-artist/references/domain-marketing.md +66 -0
  120. package/templates/claude/skills/ai-artist/references/domain-patterns.md +33 -0
  121. package/templates/claude/skills/ai-artist/references/domain-writing.md +68 -0
  122. package/templates/claude/skills/ai-artist/references/image-prompting.md +141 -0
  123. package/templates/claude/skills/ai-artist/references/llm-prompting.md +165 -0
  124. package/templates/claude/skills/ai-artist/references/nano-banana.md +59 -0
  125. package/templates/claude/skills/ai-artist/references/reasoning-techniques.md +201 -0
  126. package/templates/claude/skills/backend-development/SKILL.md +95 -0
  127. package/templates/claude/skills/backend-development/references/backend-api-design.md +495 -0
  128. package/templates/claude/skills/backend-development/references/backend-architecture.md +454 -0
  129. package/templates/claude/skills/backend-development/references/backend-authentication.md +338 -0
  130. package/templates/claude/skills/backend-development/references/backend-code-quality.md +659 -0
  131. package/templates/claude/skills/backend-development/references/backend-debugging.md +904 -0
  132. package/templates/claude/skills/backend-development/references/backend-devops.md +494 -0
  133. package/templates/claude/skills/backend-development/references/backend-mindset.md +387 -0
  134. package/templates/claude/skills/backend-development/references/backend-performance.md +397 -0
  135. package/templates/claude/skills/backend-development/references/backend-security.md +290 -0
  136. package/templates/claude/skills/backend-development/references/backend-technologies.md +256 -0
  137. package/templates/claude/skills/backend-development/references/backend-testing.md +429 -0
  138. package/templates/claude/skills/better-auth/SKILL.md +204 -0
  139. package/templates/claude/skills/better-auth/references/advanced-features.md +553 -0
  140. package/templates/claude/skills/better-auth/references/database-integration.md +577 -0
  141. package/templates/claude/skills/better-auth/references/email-password-auth.md +416 -0
  142. package/templates/claude/skills/better-auth/references/oauth-providers.md +430 -0
  143. package/templates/claude/skills/better-auth/scripts/better_auth_init.py +521 -0
  144. package/templates/claude/skills/chrome-devtools/SKILL.md +473 -0
  145. package/templates/claude/skills/chrome-devtools/references/cdp-domains.md +694 -0
  146. package/templates/claude/skills/chrome-devtools/references/performance-guide.md +940 -0
  147. package/templates/claude/skills/chrome-devtools/references/puppeteer-reference.md +953 -0
  148. package/templates/claude/skills/chrome-devtools/scripts/README.md +288 -0
  149. package/templates/claude/skills/chrome-devtools/scripts/aria-snapshot.js +368 -0
  150. package/templates/claude/skills/chrome-devtools/scripts/click.js +92 -0
  151. package/templates/claude/skills/chrome-devtools/scripts/console.js +85 -0
  152. package/templates/claude/skills/chrome-devtools/scripts/evaluate.js +59 -0
  153. package/templates/claude/skills/chrome-devtools/scripts/fill.js +84 -0
  154. package/templates/claude/skills/chrome-devtools/scripts/inject-auth.js +247 -0
  155. package/templates/claude/skills/chrome-devtools/scripts/install-deps.sh +11 -0
  156. package/templates/claude/skills/chrome-devtools/scripts/install.sh +36 -0
  157. package/templates/claude/skills/chrome-devtools/scripts/lib/browser.js +335 -0
  158. package/templates/claude/skills/chrome-devtools/scripts/lib/selector.js +183 -0
  159. package/templates/claude/skills/chrome-devtools/scripts/navigate.js +60 -0
  160. package/templates/claude/skills/chrome-devtools/scripts/network.js +113 -0
  161. package/templates/claude/skills/chrome-devtools/scripts/package.json +16 -0
  162. package/templates/claude/skills/chrome-devtools/scripts/performance.js +159 -0
  163. package/templates/claude/skills/chrome-devtools/scripts/screenshot.js +212 -0
  164. package/templates/claude/skills/chrome-devtools/scripts/select-ref.js +151 -0
  165. package/templates/claude/skills/chrome-devtools/scripts/snapshot.js +143 -0
  166. package/templates/claude/skills/chrome-devtools/scripts/ws-debug.js +47 -0
  167. package/templates/claude/skills/chrome-devtools/scripts/ws-full-debug.js +115 -0
  168. package/templates/claude/skills/claude-code/references/advanced-features.md +399 -0
  169. package/templates/claude/skills/claude-code/references/agent-skills.md +399 -0
  170. package/templates/claude/skills/claude-code/references/api-reference.md +498 -0
  171. package/templates/claude/skills/claude-code/references/best-practices.md +447 -0
  172. package/templates/claude/skills/claude-code/references/cicd-integration.md +428 -0
  173. package/templates/claude/skills/claude-code/references/common-workflows.md +107 -0
  174. package/templates/claude/skills/claude-code/references/configuration.md +480 -0
  175. package/templates/claude/skills/claude-code/references/enterprise-features.md +472 -0
  176. package/templates/claude/skills/claude-code/references/getting-started.md +244 -0
  177. package/templates/claude/skills/claude-code/references/hooks-and-plugins.md +444 -0
  178. package/templates/claude/skills/claude-code/references/hooks-comprehensive.md +622 -0
  179. package/templates/claude/skills/claude-code/references/ide-integration.md +316 -0
  180. package/templates/claude/skills/claude-code/references/mcp-integration.md +386 -0
  181. package/templates/claude/skills/claude-code/references/slash-commands.md +460 -0
  182. package/templates/claude/skills/claude-code/references/troubleshooting.md +455 -0
  183. package/templates/claude/skills/claude-code/skill.md +60 -0
  184. package/templates/claude/skills/code-review/SKILL.md +143 -0
  185. package/templates/claude/skills/code-review/references/code-review-reception.md +209 -0
  186. package/templates/claude/skills/code-review/references/requesting-code-review.md +105 -0
  187. package/templates/claude/skills/code-review/references/verification-before-completion.md +139 -0
  188. package/templates/claude/skills/context-engineering/SKILL.md +86 -0
  189. package/templates/claude/skills/context-engineering/references/context-compression.md +84 -0
  190. package/templates/claude/skills/context-engineering/references/context-degradation.md +93 -0
  191. package/templates/claude/skills/context-engineering/references/context-fundamentals.md +75 -0
  192. package/templates/claude/skills/context-engineering/references/context-optimization.md +82 -0
  193. package/templates/claude/skills/context-engineering/references/evaluation.md +89 -0
  194. package/templates/claude/skills/context-engineering/references/memory-systems.md +88 -0
  195. package/templates/claude/skills/context-engineering/references/multi-agent-patterns.md +90 -0
  196. package/templates/claude/skills/context-engineering/references/project-development.md +97 -0
  197. package/templates/claude/skills/context-engineering/references/tool-design.md +86 -0
  198. package/templates/claude/skills/context-engineering/scripts/compression_evaluator.py +329 -0
  199. package/templates/claude/skills/context-engineering/scripts/context_analyzer.py +294 -0
  200. package/templates/claude/skills/databases/SKILL.md +232 -0
  201. package/templates/claude/skills/databases/references/mongodb-aggregation.md +447 -0
  202. package/templates/claude/skills/databases/references/mongodb-atlas.md +465 -0
  203. package/templates/claude/skills/databases/references/mongodb-crud.md +408 -0
  204. package/templates/claude/skills/databases/references/mongodb-indexing.md +442 -0
  205. package/templates/claude/skills/databases/references/postgresql-administration.md +594 -0
  206. package/templates/claude/skills/databases/references/postgresql-performance.md +527 -0
  207. package/templates/claude/skills/databases/references/postgresql-psql-cli.md +467 -0
  208. package/templates/claude/skills/databases/references/postgresql-queries.md +475 -0
  209. package/templates/claude/skills/databases/scripts/db_backup.py +502 -0
  210. package/templates/claude/skills/databases/scripts/db_migrate.py +414 -0
  211. package/templates/claude/skills/databases/scripts/db_performance_check.py +445 -0
  212. package/templates/claude/skills/debugging/SKILL.md +84 -0
  213. package/templates/claude/skills/debugging/references/defense-in-depth.md +124 -0
  214. package/templates/claude/skills/debugging/references/root-cause-tracing.md +122 -0
  215. package/templates/claude/skills/debugging/references/systematic-debugging.md +102 -0
  216. package/templates/claude/skills/debugging/references/verification.md +123 -0
  217. package/templates/claude/skills/debugging/scripts/find-polluter.sh +63 -0
  218. package/templates/claude/skills/debugging/scripts/find-polluter.test.md +102 -0
  219. package/templates/claude/skills/devops/SKILL.md +293 -0
  220. package/templates/claude/skills/devops/references/browser-rendering.md +305 -0
  221. package/templates/claude/skills/devops/references/cloudflare-d1-kv.md +123 -0
  222. package/templates/claude/skills/devops/references/cloudflare-platform.md +271 -0
  223. package/templates/claude/skills/devops/references/cloudflare-r2-storage.md +280 -0
  224. package/templates/claude/skills/devops/references/cloudflare-workers-advanced.md +312 -0
  225. package/templates/claude/skills/devops/references/cloudflare-workers-apis.md +309 -0
  226. package/templates/claude/skills/devops/references/cloudflare-workers-basics.md +418 -0
  227. package/templates/claude/skills/devops/references/docker-basics.md +297 -0
  228. package/templates/claude/skills/devops/references/docker-compose.md +292 -0
  229. package/templates/claude/skills/devops/references/gcloud-platform.md +307 -0
  230. package/templates/claude/skills/devops/references/gcloud-services.md +304 -0
  231. package/templates/claude/skills/devops/scripts/cloudflare_deploy.py +269 -0
  232. package/templates/claude/skills/devops/scripts/docker_optimize.py +320 -0
  233. package/templates/claude/skills/docs-seeker/SKILL.md +95 -0
  234. package/templates/claude/skills/docs-seeker/package.json +24 -0
  235. package/templates/claude/skills/docs-seeker/references/advanced.md +78 -0
  236. package/templates/claude/skills/docs-seeker/references/context7-patterns.md +68 -0
  237. package/templates/claude/skills/docs-seeker/references/errors.md +68 -0
  238. package/templates/claude/skills/docs-seeker/scripts/analyze-llms-txt.js +245 -0
  239. package/templates/claude/skills/docs-seeker/scripts/detect-topic.js +172 -0
  240. package/templates/claude/skills/docs-seeker/scripts/fetch-docs.js +212 -0
  241. package/templates/claude/skills/docs-seeker/workflows/library-search.md +87 -0
  242. package/templates/claude/skills/docs-seeker/workflows/repo-analysis.md +91 -0
  243. package/templates/claude/skills/docs-seeker/workflows/topic-search.md +77 -0
  244. package/templates/claude/skills/frontend-design/SKILL.md +85 -0
  245. package/templates/claude/skills/frontend-design/references/analysis-best-practices.md +80 -0
  246. package/templates/claude/skills/frontend-design/references/analysis-prompts.md +141 -0
  247. package/templates/claude/skills/frontend-design/references/analysis-techniques.md +118 -0
  248. package/templates/claude/skills/frontend-design/references/animejs.md +396 -0
  249. package/templates/claude/skills/frontend-design/references/design-extraction-overview.md +71 -0
  250. package/templates/claude/skills/frontend-design/references/extraction-best-practices.md +141 -0
  251. package/templates/claude/skills/frontend-design/references/extraction-output-templates.md +162 -0
  252. package/templates/claude/skills/frontend-design/references/extraction-prompts.md +127 -0
  253. package/templates/claude/skills/frontend-design/references/technical-accessibility.md +119 -0
  254. package/templates/claude/skills/frontend-design/references/technical-best-practices.md +97 -0
  255. package/templates/claude/skills/frontend-design/references/technical-optimization.md +44 -0
  256. package/templates/claude/skills/frontend-design/references/technical-overview.md +90 -0
  257. package/templates/claude/skills/frontend-design/references/technical-workflows.md +150 -0
  258. package/templates/claude/skills/frontend-design/references/visual-analysis-overview.md +95 -0
  259. package/templates/claude/skills/frontend-development/SKILL.md +399 -0
  260. package/templates/claude/skills/frontend-development/resources/common-patterns.md +331 -0
  261. package/templates/claude/skills/frontend-development/resources/complete-examples.md +872 -0
  262. package/templates/claude/skills/frontend-development/resources/component-patterns.md +502 -0
  263. package/templates/claude/skills/frontend-development/resources/data-fetching.md +767 -0
  264. package/templates/claude/skills/frontend-development/resources/file-organization.md +502 -0
  265. package/templates/claude/skills/frontend-development/resources/loading-and-error-states.md +501 -0
  266. package/templates/claude/skills/frontend-development/resources/performance.md +406 -0
  267. package/templates/claude/skills/frontend-development/resources/routing-guide.md +364 -0
  268. package/templates/claude/skills/frontend-development/resources/styling-guide.md +428 -0
  269. package/templates/claude/skills/frontend-development/resources/typescript-standards.md +418 -0
  270. package/templates/claude/skills/markdown-novel-viewer/SKILL.md +272 -0
  271. package/templates/claude/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
  272. package/templates/claude/skills/markdown-novel-viewer/assets/favicon.png +0 -0
  273. package/templates/claude/skills/markdown-novel-viewer/assets/novel-theme.css +872 -0
  274. package/templates/claude/skills/markdown-novel-viewer/assets/reader.js +378 -0
  275. package/templates/claude/skills/markdown-novel-viewer/assets/template.html +85 -0
  276. package/templates/claude/skills/markdown-novel-viewer/package.json +15 -0
  277. package/templates/claude/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
  278. package/templates/claude/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +335 -0
  279. package/templates/claude/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
  280. package/templates/claude/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +49 -0
  281. package/templates/claude/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
  282. package/templates/claude/skills/markdown-novel-viewer/scripts/server.cjs +398 -0
  283. package/templates/claude/skills/mcp-builder/SKILL.md +328 -0
  284. package/templates/claude/skills/mcp-builder/reference/evaluation.md +602 -0
  285. package/templates/claude/skills/mcp-builder/reference/mcp_best_practices.md +915 -0
  286. package/templates/claude/skills/mcp-builder/reference/node_mcp_server.md +916 -0
  287. package/templates/claude/skills/mcp-builder/reference/python_mcp_server.md +752 -0
  288. package/templates/claude/skills/mcp-builder/scripts/connections.py +151 -0
  289. package/templates/claude/skills/mcp-builder/scripts/evaluation.py +381 -0
  290. package/templates/claude/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  291. package/templates/claude/skills/mcp-builder/scripts/requirements.txt +2 -0
  292. package/templates/claude/skills/mcp-management/README.md +219 -0
  293. package/templates/claude/skills/mcp-management/SKILL.md +209 -0
  294. package/templates/claude/skills/mcp-management/assets/tools.json +3146 -0
  295. package/templates/claude/skills/mcp-management/references/configuration.md +114 -0
  296. package/templates/claude/skills/mcp-management/references/gemini-cli-integration.md +209 -0
  297. package/templates/claude/skills/mcp-management/references/mcp-protocol.md +116 -0
  298. package/templates/claude/skills/mcp-management/scripts/.env.example +10 -0
  299. package/templates/claude/skills/mcp-management/scripts/cli.ts +202 -0
  300. package/templates/claude/skills/mcp-management/scripts/mcp-client.ts +247 -0
  301. package/templates/claude/skills/mcp-management/scripts/package.json +20 -0
  302. package/templates/claude/skills/mcp-management/scripts/tsconfig.json +15 -0
  303. package/templates/claude/skills/media-processing/SKILL.md +91 -0
  304. package/templates/claude/skills/media-processing/references/common-workflows.md +132 -0
  305. package/templates/claude/skills/media-processing/references/ffmpeg-encoding.md +358 -0
  306. package/templates/claude/skills/media-processing/references/ffmpeg-filters.md +503 -0
  307. package/templates/claude/skills/media-processing/references/ffmpeg-streaming.md +395 -0
  308. package/templates/claude/skills/media-processing/references/format-compatibility.md +375 -0
  309. package/templates/claude/skills/media-processing/references/imagemagick-batch.md +612 -0
  310. package/templates/claude/skills/media-processing/references/imagemagick-editing.md +623 -0
  311. package/templates/claude/skills/media-processing/references/rmbg-background-removal.md +66 -0
  312. package/templates/claude/skills/media-processing/references/troubleshooting.md +109 -0
  313. package/templates/claude/skills/media-processing/scripts/README.md +102 -0
  314. package/templates/claude/skills/media-processing/scripts/batch-remove-background.sh +124 -0
  315. package/templates/claude/skills/media-processing/scripts/batch_resize.py +342 -0
  316. package/templates/claude/skills/media-processing/scripts/media_convert.py +311 -0
  317. package/templates/claude/skills/media-processing/scripts/remove-background.sh +96 -0
  318. package/templates/claude/skills/media-processing/scripts/remove-bg-node.js +181 -0
  319. package/templates/claude/skills/mermaidjs-v11/SKILL.md +115 -0
  320. package/templates/claude/skills/mermaidjs-v11/references/cli-usage.md +228 -0
  321. package/templates/claude/skills/mermaidjs-v11/references/configuration.md +232 -0
  322. package/templates/claude/skills/mermaidjs-v11/references/diagram-types.md +315 -0
  323. package/templates/claude/skills/mermaidjs-v11/references/examples.md +344 -0
  324. package/templates/claude/skills/mermaidjs-v11/references/integration.md +310 -0
  325. package/templates/claude/skills/planning/SKILL.md +115 -0
  326. package/templates/claude/skills/planning/references/codebase-understanding.md +62 -0
  327. package/templates/claude/skills/planning/references/output-standards.md +127 -0
  328. package/templates/claude/skills/planning/references/plan-organization.md +150 -0
  329. package/templates/claude/skills/planning/references/research-phase.md +49 -0
  330. package/templates/claude/skills/planning/references/solution-design.md +63 -0
  331. package/templates/claude/skills/plans-kanban/SKILL.md +157 -0
  332. package/templates/claude/skills/plans-kanban/assets/dashboard-template.html +119 -0
  333. package/templates/claude/skills/plans-kanban/assets/dashboard.css +1594 -0
  334. package/templates/claude/skills/plans-kanban/assets/dashboard.js +659 -0
  335. package/templates/claude/skills/plans-kanban/assets/favicon.png +0 -0
  336. package/templates/claude/skills/plans-kanban/package.json +13 -0
  337. package/templates/claude/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +941 -0
  338. package/templates/claude/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
  339. package/templates/claude/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
  340. package/templates/claude/skills/plans-kanban/scripts/lib/plan-parser.cjs +194 -0
  341. package/templates/claude/skills/plans-kanban/scripts/lib/plan-scanner.cjs +277 -0
  342. package/templates/claude/skills/plans-kanban/scripts/lib/port-finder.cjs +49 -0
  343. package/templates/claude/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
  344. package/templates/claude/skills/plans-kanban/scripts/server.cjs +249 -0
  345. package/templates/claude/skills/problem-solving/SKILL.md +96 -0
  346. package/templates/claude/skills/problem-solving/references/attribution.md +69 -0
  347. package/templates/claude/skills/problem-solving/references/collision-zone-thinking.md +79 -0
  348. package/templates/claude/skills/problem-solving/references/inversion-exercise.md +91 -0
  349. package/templates/claude/skills/problem-solving/references/meta-pattern-recognition.md +87 -0
  350. package/templates/claude/skills/problem-solving/references/scale-game.md +95 -0
  351. package/templates/claude/skills/problem-solving/references/simplification-cascades.md +80 -0
  352. package/templates/claude/skills/problem-solving/references/when-stuck.md +72 -0
  353. package/templates/claude/skills/registry.json +258 -0
  354. package/templates/claude/skills/repomix/SKILL.md +247 -0
  355. package/templates/claude/skills/repomix/references/configuration.md +211 -0
  356. package/templates/claude/skills/repomix/references/usage-patterns.md +232 -0
  357. package/templates/claude/skills/repomix/scripts/README.md +179 -0
  358. package/templates/claude/skills/repomix/scripts/repomix_batch.py +455 -0
  359. package/templates/claude/skills/repomix/scripts/repos.example.json +15 -0
  360. package/templates/claude/skills/research/SKILL.md +168 -0
  361. package/templates/claude/skills/sequential-thinking/.env.example +8 -0
  362. package/templates/claude/skills/sequential-thinking/README.md +183 -0
  363. package/templates/claude/skills/sequential-thinking/SKILL.md +94 -0
  364. package/templates/claude/skills/sequential-thinking/package.json +31 -0
  365. package/templates/claude/skills/sequential-thinking/references/advanced-strategies.md +79 -0
  366. package/templates/claude/skills/sequential-thinking/references/advanced-techniques.md +76 -0
  367. package/templates/claude/skills/sequential-thinking/references/core-patterns.md +95 -0
  368. package/templates/claude/skills/sequential-thinking/references/examples-api.md +88 -0
  369. package/templates/claude/skills/sequential-thinking/references/examples-architecture.md +94 -0
  370. package/templates/claude/skills/sequential-thinking/references/examples-debug.md +90 -0
  371. package/templates/claude/skills/sequential-thinking/scripts/format-thought.js +182 -0
  372. package/templates/claude/skills/sequential-thinking/scripts/process-thought.js +252 -0
  373. package/templates/claude/skills/skill-creator/LICENSE.txt +202 -0
  374. package/templates/claude/skills/skill-creator/SKILL.md +266 -0
  375. package/templates/claude/skills/skill-creator/references/agent-skills-spec.md +51 -0
  376. package/templates/claude/skills/skill-creator/scripts/encoding_utils.py +21 -0
  377. package/templates/claude/skills/skill-creator/scripts/init_skill.py +304 -0
  378. package/templates/claude/skills/skill-creator/scripts/package_skill.py +110 -0
  379. package/templates/claude/skills/skill-creator/scripts/quick_validate.py +66 -0
  380. package/templates/claude/skills/template-skill/SKILL.md +6 -0
  381. package/templates/claude/skills/vitest/SKILL.md +595 -0
  382. package/templates/claude/skills/vitest/references/async-patterns.md +82 -0
  383. package/templates/claude/skills/vitest/references/mock-patterns.md +78 -0
  384. package/templates/claude/skills/vitest/references/monorepo-setup.md +185 -0
  385. package/templates/claude/skills/vitest/references/turborepo-setup.md +332 -0
  386. package/templates/claude/skills/web-frameworks/SKILL.md +324 -0
  387. package/templates/claude/skills/web-frameworks/references/nextjs-app-router.md +465 -0
  388. package/templates/claude/skills/web-frameworks/references/nextjs-data-fetching.md +459 -0
  389. package/templates/claude/skills/web-frameworks/references/nextjs-optimization.md +511 -0
  390. package/templates/claude/skills/web-frameworks/references/nextjs-server-components.md +495 -0
  391. package/templates/claude/skills/web-frameworks/references/remix-icon-integration.md +603 -0
  392. package/templates/claude/skills/web-frameworks/references/turborepo-caching.md +551 -0
  393. package/templates/claude/skills/web-frameworks/references/turborepo-pipelines.md +517 -0
  394. package/templates/claude/skills/web-frameworks/references/turborepo-setup.md +542 -0
  395. package/templates/claude/skills/web-frameworks/scripts/nextjs_init.py +547 -0
  396. package/templates/claude/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
  397. package/templates/claude/workflows/development-rules.md +40 -0
  398. package/templates/claude/workflows/documentation-management.md +121 -0
  399. package/templates/claude/workflows/orchestration-protocol.md +16 -0
  400. package/templates/claude/workflows/primary-workflow.md +45 -0
  401. package/templates/claude/workflows/registry.json +37 -0
  402. package/templates/common/.cct.json +41 -0
  403. package/templates/common/.cctkignore +22 -0
  404. package/templates/common/.env.example +39 -0
  405. package/templates/common/.mcp.json.example +16 -0
  406. package/templates/common/metadata.json +15 -0
  407. package/templates/common/settings.json +79 -0
  408. package/templates/common/statusline.cjs +271 -0
  409. package/templates/config/.repomixignore +22 -0
  410. package/templates/config/AGENTS.md +55 -0
  411. package/templates/config/CLAUDE.md +87 -0
  412. package/templates/plans/bug-fix-template.md +69 -0
  413. package/templates/plans/feature-implementation-template.md +84 -0
  414. package/templates/plans/refactor-template.md +82 -0
  415. package/templates/plans/template-usage-guide.md +58 -0
@@ -0,0 +1,751 @@
1
+ /**
2
+ * Shared utilities for Claude Code Toolkit hooks
3
+ *
4
+ * Contains config loading, path sanitization, and common constants
5
+ * used by session-init.cjs and dev-rules-reminder.cjs
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const os = require('os');
11
+
12
+ const LOCAL_CONFIG_PATH = '.claude/.cctk.json';
13
+ const GLOBAL_CONFIG_PATH = path.join(os.homedir(), '.claude', '.cctk.json');
14
+
15
+ // Legacy export for backward compatibility
16
+ const CONFIG_PATH = LOCAL_CONFIG_PATH;
17
+
18
+ const DEFAULT_CONFIG = {
19
+ plan: {
20
+ namingFormat: '{date}-{issue}-{slug}',
21
+ dateFormat: 'YYMMDD-HHmm',
22
+ issuePrefix: null,
23
+ reportsDir: 'reports',
24
+ resolution: {
25
+ order: ['session', 'branch'],
26
+ branchPattern: '(?:feat|fix|chore|refactor|docs)/(?:[^/]+/)?(.+)'
27
+ },
28
+ validation: {
29
+ mode: 'prompt', // 'auto' | 'prompt' | 'off'
30
+ minQuestions: 3,
31
+ maxQuestions: 8,
32
+ focusAreas: ['assumptions', 'risks', 'tradeoffs', 'architecture']
33
+ }
34
+ },
35
+ paths: {
36
+ docs: 'docs',
37
+ plans: 'plans'
38
+ },
39
+ docs: {
40
+ maxLoc: 800 // Maximum lines of code per doc file before warning
41
+ },
42
+ locale: {
43
+ thinkingLanguage: null, // Language for reasoning (e.g., "en" for precision)
44
+ responseLanguage: null // Language for user-facing output (e.g., "vi")
45
+ },
46
+ trust: {
47
+ passphrase: null,
48
+ enabled: false
49
+ },
50
+ project: {
51
+ type: 'auto',
52
+ packageManager: 'auto',
53
+ framework: 'auto'
54
+ },
55
+ assertions: []
56
+ };
57
+
58
+ /**
59
+ * Deep merge objects (source values override target, nested objects merged recursively)
60
+ * Arrays are replaced entirely (not concatenated) to avoid duplicate entries
61
+ * @param {Object} target - Base object
62
+ * @param {Object} source - Object to merge (takes precedence)
63
+ * @returns {Object} Merged object
64
+ */
65
+ function deepMerge(target, source) {
66
+ if (!source || typeof source !== 'object') return target;
67
+ if (!target || typeof target !== 'object') return source;
68
+
69
+ const result = { ...target };
70
+ for (const key of Object.keys(source)) {
71
+ const sourceVal = source[key];
72
+ const targetVal = target[key];
73
+
74
+ // Arrays: replace entirely (don't concatenate)
75
+ if (Array.isArray(sourceVal)) {
76
+ result[key] = [...sourceVal];
77
+ }
78
+ // Objects: recurse (but not null)
79
+ else if (sourceVal !== null && typeof sourceVal === 'object' && !Array.isArray(sourceVal)) {
80
+ result[key] = deepMerge(targetVal || {}, sourceVal);
81
+ }
82
+ // Primitives: source wins
83
+ else {
84
+ result[key] = sourceVal;
85
+ }
86
+ }
87
+ return result;
88
+ }
89
+
90
+ /**
91
+ * Load config from a specific file path
92
+ * @param {string} configPath - Path to config file
93
+ * @returns {Object|null} Parsed config or null if not found/invalid
94
+ */
95
+ function loadConfigFromPath(configPath) {
96
+ try {
97
+ if (!fs.existsSync(configPath)) return null;
98
+ return JSON.parse(fs.readFileSync(configPath, 'utf8'));
99
+ } catch (e) {
100
+ return null;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Get session temp file path
106
+ * @param {string} sessionId - Session identifier
107
+ * @returns {string} Path to session temp file
108
+ */
109
+ function getSessionTempPath(sessionId) {
110
+ return path.join(os.tmpdir(), `cctk-session-${sessionId}.json`);
111
+ }
112
+
113
+ /**
114
+ * Read session state from temp file
115
+ * @param {string} sessionId - Session identifier
116
+ * @returns {Object|null} Session state or null
117
+ */
118
+ function readSessionState(sessionId) {
119
+ if (!sessionId) return null;
120
+ const tempPath = getSessionTempPath(sessionId);
121
+ try {
122
+ if (!fs.existsSync(tempPath)) return null;
123
+ return JSON.parse(fs.readFileSync(tempPath, 'utf8'));
124
+ } catch (e) {
125
+ return null;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Write session state atomically to temp file
131
+ * @param {string} sessionId - Session identifier
132
+ * @param {Object} state - State object to persist
133
+ * @returns {boolean} Success status
134
+ */
135
+ function writeSessionState(sessionId, state) {
136
+ if (!sessionId) return false;
137
+ const tempPath = getSessionTempPath(sessionId);
138
+ const tmpFile = tempPath + '.' + Math.random().toString(36).slice(2);
139
+ try {
140
+ fs.writeFileSync(tmpFile, JSON.stringify(state, null, 2));
141
+ fs.renameSync(tmpFile, tempPath);
142
+ return true;
143
+ } catch (e) {
144
+ try { fs.unlinkSync(tmpFile); } catch (_) { /* ignore */ }
145
+ return false;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Characters invalid in filenames across macOS, Linux
151
+ * macOS/Linux: / and null byte
152
+ * Also includes control characters and other problematic chars
153
+ */
154
+ const INVALID_FILENAME_CHARS = /[<>:"/\\|?*\x00-\x1f\x7f]/g;
155
+
156
+ /**
157
+ * Sanitize slug for safe filesystem usage
158
+ * - Removes invalid filename characters
159
+ * - Replaces non-alphanumeric (except hyphen) with hyphen
160
+ * - Collapses multiple hyphens
161
+ * - Removes leading/trailing hyphens
162
+ * - Limits length to prevent filesystem issues
163
+ *
164
+ * @param {string} slug - Slug to sanitize
165
+ * @returns {string} Sanitized slug (empty string if nothing valid remains)
166
+ */
167
+ function sanitizeSlug(slug) {
168
+ if (!slug || typeof slug !== 'string') return '';
169
+
170
+ let sanitized = slug
171
+ // Remove invalid filename chars first
172
+ .replace(INVALID_FILENAME_CHARS, '')
173
+ // Replace any non-alphanumeric (except hyphen) with hyphen
174
+ .replace(/[^a-z0-9-]/gi, '-')
175
+ // Collapse multiple consecutive hyphens
176
+ .replace(/-+/g, '-')
177
+ // Remove leading/trailing hyphens
178
+ .replace(/^-+|-+$/g, '')
179
+ // Limit length (most filesystems support 255, but keep reasonable)
180
+ .slice(0, 100);
181
+
182
+ return sanitized;
183
+ }
184
+
185
+ /**
186
+ * Extract feature slug from git branch name
187
+ * Pattern: (?:feat|fix|chore|refactor|docs)/(?:[^/]+/)?(.+)
188
+ * @param {string} branch - Git branch name
189
+ * @param {string} pattern - Regex pattern (optional)
190
+ * @returns {string|null} Extracted slug or null
191
+ */
192
+ function extractSlugFromBranch(branch, pattern) {
193
+ if (!branch) return null;
194
+ const defaultPattern = /(?:feat|fix|chore|refactor|docs)\/(?:[^\/]+\/)?(.+)/;
195
+ const regex = pattern ? new RegExp(pattern) : defaultPattern;
196
+ const match = branch.match(regex);
197
+ return match ? sanitizeSlug(match[1]) : null;
198
+ }
199
+
200
+ /**
201
+ * Find most recent plan folder by timestamp prefix
202
+ * @param {string} plansDir - Plans directory path
203
+ * @returns {string|null} Most recent plan path or null
204
+ */
205
+ function findMostRecentPlan(plansDir) {
206
+ try {
207
+ if (!fs.existsSync(plansDir)) return null;
208
+ const entries = fs.readdirSync(plansDir, { withFileTypes: true });
209
+ const planDirs = entries
210
+ .filter(e => e.isDirectory() && /^\d{6}/.test(e.name))
211
+ .map(e => e.name)
212
+ .sort()
213
+ .reverse();
214
+ return planDirs.length > 0 ? path.join(plansDir, planDirs[0]) : null;
215
+ } catch (e) {
216
+ return null;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Default timeout for git commands (5 seconds)
222
+ * Prevents indefinite hangs on network mounts or corrupted repos
223
+ */
224
+ const DEFAULT_EXEC_TIMEOUT_MS = 5000;
225
+
226
+ /**
227
+ * Safely execute shell command (internal helper)
228
+ * SECURITY: Only accepts whitelisted git read commands
229
+ * @param {string} cmd - Command to execute
230
+ * @param {Object} options - Execution options
231
+ * @param {string} options.cwd - Working directory (optional)
232
+ * @param {number} options.timeout - Timeout in ms (default: 5000)
233
+ * @returns {string|null} Command output or null
234
+ */
235
+ function execSafe(cmd, options = {}) {
236
+ // Whitelist of safe read-only commands
237
+ const allowedCommands = [
238
+ 'git branch --show-current',
239
+ 'git rev-parse --abbrev-ref HEAD',
240
+ 'git rev-parse --show-toplevel'
241
+ ];
242
+ if (!allowedCommands.includes(cmd)) {
243
+ return null;
244
+ }
245
+
246
+ const { cwd = undefined, timeout = DEFAULT_EXEC_TIMEOUT_MS } = options;
247
+
248
+ try {
249
+ return require('child_process')
250
+ .execSync(cmd, {
251
+ encoding: 'utf8',
252
+ timeout,
253
+ cwd,
254
+ stdio: ['pipe', 'pipe', 'pipe']
255
+ })
256
+ .trim();
257
+ } catch (e) {
258
+ return null;
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Resolve active plan path using cascading resolution with tracking
264
+ *
265
+ * Resolution semantics:
266
+ * - 'session': Explicitly set via set-active-plan.cjs → ACTIVE (directive)
267
+ * - 'branch': Matched from git branch name → SUGGESTED (hint only)
268
+ * - 'mostRecent': REMOVED - was causing stale plan pollution
269
+ *
270
+ * @param {string} sessionId - Session identifier (optional)
271
+ * @param {Object} config - Claude Code Toolkit config
272
+ * @returns {{ path: string|null, resolvedBy: 'session'|'branch'|null }} Resolution result with tracking
273
+ */
274
+ function resolvePlanPath(sessionId, config) {
275
+ const plansDir = config?.paths?.plans || 'plans';
276
+ const resolution = config?.plan?.resolution || {};
277
+ const order = resolution.order || ['session', 'branch'];
278
+ const branchPattern = resolution.branchPattern;
279
+
280
+ for (const method of order) {
281
+ switch (method) {
282
+ case 'session': {
283
+ const state = readSessionState(sessionId);
284
+ if (state?.activePlan) {
285
+ // Only use session state if CWD matches session origin (monorepo support)
286
+ if (state.sessionOrigin && state.sessionOrigin !== process.cwd()) {
287
+ break; // Fall through to branch
288
+ }
289
+ return { path: state.activePlan, resolvedBy: 'session' };
290
+ }
291
+ break;
292
+ }
293
+ case 'branch': {
294
+ try {
295
+ const branch = execSafe('git branch --show-current');
296
+ const slug = extractSlugFromBranch(branch, branchPattern);
297
+ if (slug && fs.existsSync(plansDir)) {
298
+ const entries = fs.readdirSync(plansDir, { withFileTypes: true })
299
+ .filter(e => e.isDirectory() && e.name.includes(slug));
300
+ if (entries.length > 0) {
301
+ return {
302
+ path: path.join(plansDir, entries[entries.length - 1].name),
303
+ resolvedBy: 'branch'
304
+ };
305
+ }
306
+ }
307
+ } catch (e) {
308
+ // Ignore errors reading plans dir
309
+ }
310
+ break;
311
+ }
312
+ // NOTE: 'mostRecent' case intentionally removed - was causing stale plan pollution
313
+ }
314
+ }
315
+ return { path: null, resolvedBy: null };
316
+ }
317
+
318
+ /**
319
+ * Normalize path value (trim, remove trailing slashes, handle empty)
320
+ * @param {string} pathValue - Path to normalize
321
+ * @returns {string|null} Normalized path or null if invalid
322
+ */
323
+ function normalizePath(pathValue) {
324
+ if (!pathValue || typeof pathValue !== 'string') return null;
325
+
326
+ // Trim whitespace
327
+ let normalized = pathValue.trim();
328
+
329
+ // Empty after trim = invalid
330
+ if (!normalized) return null;
331
+
332
+ // Remove trailing slashes (but keep root "/" or "C:\")
333
+ normalized = normalized.replace(/[/\\]+$/, '');
334
+
335
+ // If it became empty (was just slashes), return null
336
+ if (!normalized) return null;
337
+
338
+ return normalized;
339
+ }
340
+
341
+ /**
342
+ * Check if path is absolute
343
+ * @param {string} pathValue - Path to check
344
+ * @returns {boolean} True if absolute path
345
+ */
346
+ function isAbsolutePath(pathValue) {
347
+ if (!pathValue) return false;
348
+
349
+ return path.isAbsolute(pathValue);
350
+ }
351
+
352
+ /**
353
+ * Sanitize path values
354
+ * - Normalizes path (trim, remove trailing slashes)
355
+ * - Allows absolute paths (for consolidated plans use case)
356
+ * - Prevents obvious security issues (null bytes, etc.)
357
+ *
358
+ * @param {string} pathValue - Path to sanitize
359
+ * @param {string} projectRoot - Project root for relative path resolution
360
+ * @returns {string|null} Sanitized path or null if invalid
361
+ */
362
+ function sanitizePath(pathValue, projectRoot) {
363
+ // Normalize first
364
+ const normalized = normalizePath(pathValue);
365
+ if (!normalized) return null;
366
+
367
+ // Block null bytes and other dangerous chars
368
+ if (/[\x00]/.test(normalized)) return null;
369
+
370
+ // Allow absolute paths (user explicitly wants consolidated plans elsewhere)
371
+ if (isAbsolutePath(normalized)) {
372
+ return normalized;
373
+ }
374
+
375
+ // For relative paths, resolve and validate
376
+ const resolved = path.resolve(projectRoot, normalized);
377
+
378
+ // Prevent path traversal outside project (../ attacks)
379
+ // But allow if user explicitly set absolute path
380
+ if (!resolved.startsWith(projectRoot + path.sep) && resolved !== projectRoot) {
381
+ // This is a relative path trying to escape - block it
382
+ return null;
383
+ }
384
+
385
+ return normalized;
386
+ }
387
+
388
+ /**
389
+ * Validate and sanitize config paths
390
+ */
391
+ function sanitizeConfig(config, projectRoot) {
392
+ const result = { ...config };
393
+
394
+ if (result.plan) {
395
+ result.plan = { ...result.plan };
396
+ if (!sanitizePath(result.plan.reportsDir, projectRoot)) {
397
+ result.plan.reportsDir = DEFAULT_CONFIG.plan.reportsDir;
398
+ }
399
+ // Merge resolution defaults
400
+ result.plan.resolution = {
401
+ ...DEFAULT_CONFIG.plan.resolution,
402
+ ...result.plan.resolution
403
+ };
404
+ // Merge validation defaults
405
+ result.plan.validation = {
406
+ ...DEFAULT_CONFIG.plan.validation,
407
+ ...result.plan.validation
408
+ };
409
+ }
410
+
411
+ if (result.paths) {
412
+ result.paths = { ...result.paths };
413
+ if (!sanitizePath(result.paths.docs, projectRoot)) {
414
+ result.paths.docs = DEFAULT_CONFIG.paths.docs;
415
+ }
416
+ if (!sanitizePath(result.paths.plans, projectRoot)) {
417
+ result.paths.plans = DEFAULT_CONFIG.paths.plans;
418
+ }
419
+ }
420
+
421
+ if (result.locale) {
422
+ result.locale = { ...result.locale };
423
+ }
424
+
425
+ return result;
426
+ }
427
+
428
+ /**
429
+ * Load config with cascading resolution: DEFAULT → global → local
430
+ *
431
+ * Resolution order (each layer overrides the previous):
432
+ * 1. DEFAULT_CONFIG (hardcoded defaults)
433
+ * 2. Global config (~/.claude/.cctk.json) - user preferences
434
+ * 3. Local config (./.claude/.cctk.json) - project-specific overrides
435
+ *
436
+ * @param {Object} options - Options for config loading
437
+ * @param {boolean} options.includeProject - Include project section (default: true)
438
+ * @param {boolean} options.includeAssertions - Include assertions (default: true)
439
+ * @param {boolean} options.includeLocale - Include locale section (default: true)
440
+ */
441
+ function loadConfig(options = {}) {
442
+ const { includeProject = true, includeAssertions = true, includeLocale = true } = options;
443
+ const projectRoot = process.cwd();
444
+
445
+ // Load configs from both locations
446
+ const globalConfig = loadConfigFromPath(GLOBAL_CONFIG_PATH);
447
+ const localConfig = loadConfigFromPath(LOCAL_CONFIG_PATH);
448
+
449
+ // No config files found - use defaults
450
+ if (!globalConfig && !localConfig) {
451
+ return getDefaultConfig(includeProject, includeAssertions, includeLocale);
452
+ }
453
+
454
+ try {
455
+ // Deep merge: DEFAULT → global → local (local wins)
456
+ let merged = deepMerge({}, DEFAULT_CONFIG);
457
+ if (globalConfig) merged = deepMerge(merged, globalConfig);
458
+ if (localConfig) merged = deepMerge(merged, localConfig);
459
+
460
+ // Build result with optional sections
461
+ const result = {
462
+ plan: merged.plan || DEFAULT_CONFIG.plan,
463
+ paths: merged.paths || DEFAULT_CONFIG.paths,
464
+ docs: merged.docs || DEFAULT_CONFIG.docs
465
+ };
466
+
467
+ if (includeLocale) {
468
+ result.locale = merged.locale || DEFAULT_CONFIG.locale;
469
+ }
470
+ // Always include trust config for verification
471
+ result.trust = merged.trust || DEFAULT_CONFIG.trust;
472
+ if (includeProject) {
473
+ result.project = merged.project || DEFAULT_CONFIG.project;
474
+ }
475
+ if (includeAssertions) {
476
+ result.assertions = merged.assertions || [];
477
+ }
478
+ // Coding level guidelines (true/false, default: false = disabled)
479
+ // When enabled, injects expert-level communication guidelines
480
+ result.codingLevel = merged.codingLevel ?? false;
481
+
482
+ return sanitizeConfig(result, projectRoot);
483
+ } catch (e) {
484
+ return getDefaultConfig(includeProject, includeAssertions, includeLocale);
485
+ }
486
+ }
487
+
488
+ /**
489
+ * Get default config with optional sections
490
+ */
491
+ function getDefaultConfig(includeProject = true, includeAssertions = true, includeLocale = true) {
492
+ const result = {
493
+ plan: { ...DEFAULT_CONFIG.plan },
494
+ paths: { ...DEFAULT_CONFIG.paths },
495
+ docs: { ...DEFAULT_CONFIG.docs },
496
+ codingLevel: false // Default: disabled (no injection, saves tokens)
497
+ };
498
+ if (includeLocale) {
499
+ result.locale = { ...DEFAULT_CONFIG.locale };
500
+ }
501
+ if (includeProject) {
502
+ result.project = { ...DEFAULT_CONFIG.project };
503
+ }
504
+ if (includeAssertions) {
505
+ result.assertions = [];
506
+ }
507
+ return result;
508
+ }
509
+
510
+ /**
511
+ * Escape shell special characters for env file values
512
+ * Handles: backslash, double quote, dollar sign, backtick
513
+ */
514
+ function escapeShellValue(str) {
515
+ if (typeof str !== 'string') return str;
516
+ return str
517
+ .replace(/\\/g, '\\\\') // Backslash first
518
+ .replace(/"/g, '\\"') // Double quotes
519
+ .replace(/\$/g, '\\$') // Dollar sign
520
+ .replace(/`/g, '\\`'); // Backticks (command substitution)
521
+ }
522
+
523
+ /**
524
+ * Write environment variable to CLAUDE_ENV_FILE (with escaping)
525
+ */
526
+ function writeEnv(envFile, key, value) {
527
+ if (envFile && value !== null && value !== undefined) {
528
+ const escaped = escapeShellValue(String(value));
529
+ fs.appendFileSync(envFile, `export ${key}="${escaped}"\n`);
530
+ }
531
+ }
532
+
533
+ /**
534
+ * Get reports path based on plan resolution
535
+ * Only uses plan-specific path for 'session' resolved plans (explicitly active)
536
+ * Branch-matched (suggested) plans use default path to avoid pollution
537
+ *
538
+ * @param {string|null} planPath - The plan path
539
+ * @param {string|null} resolvedBy - How plan was resolved ('session'|'branch'|null)
540
+ * @param {Object} planConfig - Plan configuration
541
+ * @param {Object} pathsConfig - Paths configuration
542
+ * @param {string|null} baseDir - Optional base directory for absolute path resolution
543
+ * @returns {string} Reports path (absolute if baseDir provided, relative otherwise)
544
+ */
545
+ function getReportsPath(planPath, resolvedBy, planConfig, pathsConfig, baseDir = null) {
546
+ const reportsDir = normalizePath(planConfig?.reportsDir) || 'reports';
547
+ const plansDir = normalizePath(pathsConfig?.plans) || 'plans';
548
+
549
+ let reportPath;
550
+ // Only use plan-specific reports path if explicitly active (session state)
551
+ if (planPath && resolvedBy === 'session') {
552
+ const normalizedPlanPath = normalizePath(planPath) || planPath;
553
+ reportPath = `${normalizedPlanPath}/${reportsDir}`;
554
+ } else {
555
+ // Default path for no plan or suggested (branch-matched) plans
556
+ reportPath = `${plansDir}/${reportsDir}`;
557
+ }
558
+
559
+ // Return absolute path if baseDir provided
560
+ if (baseDir) {
561
+ return path.join(baseDir, reportPath);
562
+ }
563
+ return reportPath + '/';
564
+ }
565
+
566
+ /**
567
+ * Format issue ID with prefix
568
+ */
569
+ function formatIssueId(issueId, planConfig) {
570
+ if (!issueId) return null;
571
+ return planConfig.issuePrefix ? `${planConfig.issuePrefix}${issueId}` : `#${issueId}`;
572
+ }
573
+
574
+ /**
575
+ * Extract issue ID from branch name
576
+ */
577
+ function extractIssueFromBranch(branch) {
578
+ if (!branch) return null;
579
+ const patterns = [
580
+ /(?:issue|gh|fix|feat|bug)[/-]?(\d+)/i,
581
+ /[/-](\d+)[/-]/,
582
+ /#(\d+)/
583
+ ];
584
+ for (const pattern of patterns) {
585
+ const match = branch.match(pattern);
586
+ if (match) return match[1];
587
+ }
588
+ return null;
589
+ }
590
+
591
+ /**
592
+ * Format date according to dateFormat config
593
+ * Supports: YYMMDD, YYMMDD-HHmm, YYYYMMDD, etc.
594
+ * @param {string} format - Date format string
595
+ * @returns {string} Formatted date
596
+ */
597
+ function formatDate(format) {
598
+ const now = new Date();
599
+ const pad = (n, len = 2) => String(n).padStart(len, '0');
600
+
601
+ const tokens = {
602
+ 'YYYY': now.getFullYear(),
603
+ 'YY': String(now.getFullYear()).slice(-2),
604
+ 'MM': pad(now.getMonth() + 1),
605
+ 'DD': pad(now.getDate()),
606
+ 'HH': pad(now.getHours()),
607
+ 'mm': pad(now.getMinutes()),
608
+ 'ss': pad(now.getSeconds())
609
+ };
610
+
611
+ let result = format;
612
+ for (const [token, value] of Object.entries(tokens)) {
613
+ result = result.replace(token, value);
614
+ }
615
+ return result;
616
+ }
617
+
618
+ /**
619
+ * Validate naming pattern result
620
+ * Ensures pattern resolves to a usable directory name
621
+ *
622
+ * @param {string} pattern - Resolved naming pattern
623
+ * @returns {{ valid: boolean, error?: string }} Validation result
624
+ */
625
+ function validateNamingPattern(pattern) {
626
+ if (!pattern || typeof pattern !== 'string') {
627
+ return { valid: false, error: 'Pattern is empty or not a string' };
628
+ }
629
+
630
+ // After removing {slug} placeholder, should still have content
631
+ const withoutSlug = pattern.replace(/\{slug\}/g, '').replace(/-+/g, '-').replace(/^-|-$/g, '');
632
+ if (!withoutSlug) {
633
+ return { valid: false, error: 'Pattern resolves to empty after removing {slug}' };
634
+ }
635
+
636
+ // Check for remaining unresolved placeholders (besides {slug})
637
+ const unresolvedMatch = withoutSlug.match(/\{[^}]+\}/);
638
+ if (unresolvedMatch) {
639
+ return { valid: false, error: `Unresolved placeholder: ${unresolvedMatch[0]}` };
640
+ }
641
+
642
+ // Pattern must contain {slug} for agents to substitute
643
+ if (!pattern.includes('{slug}')) {
644
+ return { valid: false, error: 'Pattern must contain {slug} placeholder' };
645
+ }
646
+
647
+ return { valid: true };
648
+ }
649
+
650
+ /**
651
+ * Resolve naming pattern with date and optional issue prefix
652
+ * Keeps {slug} as placeholder for agents to substitute
653
+ *
654
+ * Example: namingFormat="{date}-{issue}-{slug}", dateFormat="YYMMDD-HHmm", issue="GH-88"
655
+ * Returns: "251212-1830-GH-88-{slug}" (if issue exists)
656
+ * Returns: "251212-1830-{slug}" (if no issue)
657
+ *
658
+ * @param {Object} planConfig - Plan configuration
659
+ * @param {string|null} gitBranch - Current git branch (for issue extraction)
660
+ * @returns {string} Resolved naming pattern with {slug} placeholder
661
+ */
662
+ function resolveNamingPattern(planConfig, gitBranch) {
663
+ const { namingFormat, dateFormat, issuePrefix } = planConfig;
664
+ const formattedDate = formatDate(dateFormat);
665
+
666
+ // Try to extract issue ID from branch name
667
+ const issueId = extractIssueFromBranch(gitBranch);
668
+ const fullIssue = issueId && issuePrefix ? `${issuePrefix}${issueId}` : null;
669
+
670
+ // Build pattern by substituting {date} and {issue}, keep {slug}
671
+ let pattern = namingFormat;
672
+ pattern = pattern.replace('{date}', formattedDate);
673
+
674
+ if (fullIssue) {
675
+ pattern = pattern.replace('{issue}', fullIssue);
676
+ } else {
677
+ // Remove {issue} and any trailing/leading dash
678
+ pattern = pattern.replace(/-?\{issue\}-?/, '-').replace(/--+/g, '-');
679
+ }
680
+
681
+ // Clean up the result:
682
+ // - Remove leading/trailing hyphens
683
+ // - Collapse multiple hyphens (except around {slug})
684
+ pattern = pattern
685
+ .replace(/^-+/, '') // Remove leading hyphens
686
+ .replace(/-+$/, '') // Remove trailing hyphens
687
+ .replace(/-+(\{slug\})/g, '-$1') // Single hyphen before {slug}
688
+ .replace(/(\{slug\})-+/g, '$1-') // Single hyphen after {slug}
689
+ .replace(/--+/g, '-'); // Collapse other multiple hyphens
690
+
691
+ // Validate the resulting pattern
692
+ const validation = validateNamingPattern(pattern);
693
+ if (!validation.valid) {
694
+ // Log warning but return pattern anyway (fail-safe)
695
+ if (process.env.CCTK_DEBUG) {
696
+ console.error(`[cctk-config] Warning: ${validation.error}`);
697
+ }
698
+ }
699
+
700
+ return pattern;
701
+ }
702
+
703
+ /**
704
+ * Get current git branch (safe execution)
705
+ * @param {string|null} cwd - Working directory to run git command from (optional)
706
+ * @returns {string|null} Current branch name or null
707
+ */
708
+ function getGitBranch(cwd = null) {
709
+ return execSafe('git branch --show-current', { cwd: cwd || undefined });
710
+ }
711
+
712
+ /**
713
+ * Get git repository root directory
714
+ * @param {string|null} cwd - Working directory to run git command from (optional)
715
+ * @returns {string|null} Git root absolute path or null if not in git repo
716
+ */
717
+ function getGitRoot(cwd = null) {
718
+ return execSafe('git rev-parse --show-toplevel', { cwd: cwd || undefined });
719
+ }
720
+
721
+ module.exports = {
722
+ CONFIG_PATH,
723
+ LOCAL_CONFIG_PATH,
724
+ GLOBAL_CONFIG_PATH,
725
+ DEFAULT_CONFIG,
726
+ INVALID_FILENAME_CHARS,
727
+ deepMerge,
728
+ loadConfigFromPath,
729
+ loadConfig,
730
+ normalizePath,
731
+ isAbsolutePath,
732
+ sanitizePath,
733
+ sanitizeSlug,
734
+ sanitizeConfig,
735
+ escapeShellValue,
736
+ writeEnv,
737
+ getSessionTempPath,
738
+ readSessionState,
739
+ writeSessionState,
740
+ resolvePlanPath,
741
+ extractSlugFromBranch,
742
+ findMostRecentPlan,
743
+ getReportsPath,
744
+ formatIssueId,
745
+ extractIssueFromBranch,
746
+ formatDate,
747
+ validateNamingPattern,
748
+ resolveNamingPattern,
749
+ getGitBranch,
750
+ getGitRoot
751
+ };