claude-code-pilot 2.0.0 → 3.1.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 (514) hide show
  1. package/README.md +76 -97
  2. package/bin/install.js +267 -250
  3. package/manifest.json +5 -18
  4. package/package.json +5 -7
  5. package/src/agents/build-error-resolver.md +114 -0
  6. package/src/agents/ccp-advisor-researcher.md +104 -0
  7. package/src/agents/ccp-assumptions-analyzer.md +105 -0
  8. package/{gsd/agents/gsd-codebase-mapper.md → src/agents/ccp-codebase-mapper.md} +7 -7
  9. package/{gsd/agents/gsd-debugger.md → src/agents/ccp-debugger.md} +125 -8
  10. package/{gsd/agents/gsd-executor.md → src/agents/ccp-executor.md} +31 -20
  11. package/{gsd/agents/gsd-integration-checker.md → src/agents/ccp-integration-checker.md} +2 -2
  12. package/{gsd/agents/gsd-nyquist-auditor.md → src/agents/ccp-nyquist-auditor.md} +3 -3
  13. package/{gsd/agents/gsd-phase-researcher.md → src/agents/ccp-phase-researcher.md} +127 -13
  14. package/{gsd/agents/gsd-plan-checker.md → src/agents/ccp-plan-checker.md} +57 -21
  15. package/{gsd/agents/gsd-planner.md → src/agents/ccp-planner.md} +61 -23
  16. package/{gsd/agents/gsd-project-researcher.md → src/agents/ccp-project-researcher.md} +33 -6
  17. package/{gsd/agents/gsd-research-synthesizer.md → src/agents/ccp-research-synthesizer.md} +11 -11
  18. package/{gsd/agents/gsd-roadmapper.md → src/agents/ccp-roadmapper.md} +39 -10
  19. package/src/agents/ccp-ui-auditor.md +439 -0
  20. package/src/agents/ccp-ui-checker.md +300 -0
  21. package/src/agents/ccp-ui-researcher.md +357 -0
  22. package/{gsd/agents/gsd-verifier.md → src/agents/ccp-verifier.md} +81 -15
  23. package/src/agents/cpp-build-resolver.md +90 -0
  24. package/src/agents/cpp-reviewer.md +72 -0
  25. package/src/agents/database-reviewer.md +91 -0
  26. package/{ecc → src}/agents/doc-updater.md +1 -1
  27. package/src/agents/docs-lookup.md +68 -0
  28. package/src/agents/flutter-reviewer.md +243 -0
  29. package/src/agents/gan-evaluator.md +209 -0
  30. package/src/agents/gan-generator.md +131 -0
  31. package/src/agents/gan-planner.md +99 -0
  32. package/src/agents/go-build-resolver.md +94 -0
  33. package/src/agents/go-reviewer.md +76 -0
  34. package/src/agents/harness-optimizer.md +35 -0
  35. package/src/agents/java-build-resolver.md +153 -0
  36. package/src/agents/java-reviewer.md +92 -0
  37. package/src/agents/kotlin-build-resolver.md +118 -0
  38. package/src/agents/kotlin-reviewer.md +159 -0
  39. package/src/agents/loop-operator.md +36 -0
  40. package/src/agents/opensource-forker.md +198 -0
  41. package/src/agents/opensource-packager.md +249 -0
  42. package/src/agents/opensource-sanitizer.md +188 -0
  43. package/src/agents/performance-optimizer.md +446 -0
  44. package/src/agents/planner.md +212 -0
  45. package/src/agents/python-reviewer.md +98 -0
  46. package/src/agents/pytorch-build-resolver.md +120 -0
  47. package/src/agents/refactor-cleaner.md +85 -0
  48. package/src/agents/rust-build-resolver.md +148 -0
  49. package/src/agents/rust-reviewer.md +94 -0
  50. package/src/agents/typescript-reviewer.md +112 -0
  51. package/src/available-rules/README.md +80 -0
  52. package/src/available-rules/cpp/coding-style.md +44 -0
  53. package/src/available-rules/cpp/hooks.md +39 -0
  54. package/src/available-rules/cpp/patterns.md +51 -0
  55. package/src/available-rules/cpp/security.md +51 -0
  56. package/src/available-rules/cpp/testing.md +44 -0
  57. package/src/available-rules/csharp/coding-style.md +72 -0
  58. package/src/available-rules/csharp/hooks.md +25 -0
  59. package/src/available-rules/csharp/patterns.md +50 -0
  60. package/src/available-rules/csharp/security.md +58 -0
  61. package/src/available-rules/csharp/testing.md +46 -0
  62. package/src/available-rules/java/coding-style.md +114 -0
  63. package/src/available-rules/java/hooks.md +18 -0
  64. package/src/available-rules/java/patterns.md +146 -0
  65. package/src/available-rules/java/security.md +100 -0
  66. package/src/available-rules/java/testing.md +131 -0
  67. package/src/available-rules/kotlin/hooks.md +17 -0
  68. package/src/available-rules/rust/coding-style.md +151 -0
  69. package/src/available-rules/rust/hooks.md +16 -0
  70. package/src/available-rules/rust/patterns.md +168 -0
  71. package/src/available-rules/rust/security.md +141 -0
  72. package/src/available-rules/rust/testing.md +154 -0
  73. package/src/commands/ccp/add-backlog.md +76 -0
  74. package/{gsd/commands-gsd → src/commands/ccp}/add-phase.md +3 -3
  75. package/{gsd/commands-gsd → src/commands/ccp}/add-tests.md +5 -5
  76. package/{gsd/commands-gsd → src/commands/ccp}/add-todo.md +4 -4
  77. package/src/commands/ccp/aside.md +165 -0
  78. package/{gsd/commands-gsd → src/commands/ccp}/audit-milestone.md +3 -3
  79. package/src/commands/ccp/audit-uat.md +24 -0
  80. package/src/commands/ccp/autonomous.md +41 -0
  81. package/src/commands/ccp/build-fix.md +67 -0
  82. package/{gsd/commands-gsd → src/commands/ccp}/check-todos.md +3 -3
  83. package/{ecc/commands → src/commands/ccp}/checkpoint.md +12 -7
  84. package/{gsd/commands-gsd → src/commands/ccp}/cleanup.md +3 -3
  85. package/src/commands/ccp/code-review.md +45 -0
  86. package/{gsd/commands-gsd → src/commands/ccp}/complete-milestone.md +9 -9
  87. package/src/commands/ccp/context-budget.md +30 -0
  88. package/src/commands/ccp/cpp-build.md +174 -0
  89. package/src/commands/ccp/cpp-review.md +133 -0
  90. package/src/commands/ccp/cpp-test.md +252 -0
  91. package/{gsd/commands-gsd → src/commands/ccp}/debug.md +14 -9
  92. package/src/commands/ccp/discuss-phase.md +64 -0
  93. package/src/commands/ccp/do.md +30 -0
  94. package/src/commands/ccp/docs-update.md +48 -0
  95. package/src/commands/ccp/docs.md +32 -0
  96. package/src/commands/ccp/e2e.md +365 -0
  97. package/src/commands/ccp/eval.md +125 -0
  98. package/{ecc/commands → src/commands/ccp}/evolve.md +5 -5
  99. package/src/commands/ccp/execute-phase.md +59 -0
  100. package/src/commands/ccp/fast.md +30 -0
  101. package/src/commands/ccp/forensics.md +56 -0
  102. package/src/commands/ccp/go-build.md +184 -0
  103. package/src/commands/ccp/go-review.md +149 -0
  104. package/src/commands/ccp/go-test.md +269 -0
  105. package/src/commands/ccp/gradle-build.md +71 -0
  106. package/src/commands/ccp/harness-audit.md +76 -0
  107. package/{gsd/commands-gsd → src/commands/ccp}/health.md +3 -3
  108. package/{gsd/commands-gsd → src/commands/ccp}/help.md +5 -5
  109. package/{gsd/commands-gsd → src/commands/ccp}/insert-phase.md +3 -3
  110. package/src/commands/ccp/kotlin-build.md +175 -0
  111. package/src/commands/ccp/kotlin-review.md +141 -0
  112. package/src/commands/ccp/kotlin-test.md +313 -0
  113. package/{ecc/commands → src/commands/ccp}/learn.md +7 -2
  114. package/{gsd/commands-gsd → src/commands/ccp}/list-phase-assumptions.md +2 -2
  115. package/src/commands/ccp/manager.md +39 -0
  116. package/{gsd/commands-gsd → src/commands/ccp}/map-codebase.md +7 -7
  117. package/src/commands/ccp/milestone-summary.md +51 -0
  118. package/{ecc/commands → src/commands/ccp}/model-route.md +6 -1
  119. package/{gsd/commands-gsd → src/commands/ccp}/new-milestone.md +8 -8
  120. package/{gsd/commands-gsd → src/commands/ccp}/new-project.md +8 -8
  121. package/src/commands/ccp/next.md +24 -0
  122. package/src/commands/ccp/note.md +34 -0
  123. package/src/commands/ccp/orchestrate.md +232 -0
  124. package/{gsd/commands-gsd → src/commands/ccp}/pause-work.md +3 -3
  125. package/{gsd/commands-gsd → src/commands/ccp}/plan-milestone-gaps.md +5 -5
  126. package/{gsd/commands-gsd → src/commands/ccp}/plan-phase.md +9 -7
  127. package/src/commands/ccp/plan.md +115 -0
  128. package/src/commands/ccp/plant-seed.md +28 -0
  129. package/src/commands/ccp/pr-branch.md +25 -0
  130. package/src/commands/ccp/profile-user.md +46 -0
  131. package/{gsd/commands-gsd → src/commands/ccp}/progress.md +3 -3
  132. package/src/commands/ccp/prompt-optimize.md +39 -0
  133. package/src/commands/ccp/prune.md +25 -0
  134. package/src/commands/ccp/python-review.md +298 -0
  135. package/{ecc/commands → src/commands/ccp}/quality-gate.md +7 -2
  136. package/{gsd/commands-gsd → src/commands/ccp}/quick.md +10 -8
  137. package/src/commands/ccp/refactor-clean.md +85 -0
  138. package/{gsd/commands-gsd → src/commands/ccp}/remove-phase.md +3 -3
  139. package/{gsd/commands-gsd → src/commands/ccp}/research-phase.md +17 -12
  140. package/{ecc/commands → src/commands/ccp}/resume-session.md +9 -8
  141. package/{gsd/commands-gsd → src/commands/ccp}/resume-work.md +3 -3
  142. package/src/commands/ccp/review-backlog.md +61 -0
  143. package/src/commands/ccp/review.md +37 -0
  144. package/src/commands/ccp/rules-distill.md +12 -0
  145. package/src/commands/ccp/rust-build.md +188 -0
  146. package/src/commands/ccp/rust-review.md +143 -0
  147. package/src/commands/ccp/rust-test.md +309 -0
  148. package/{ecc/commands → src/commands/ccp}/save-session.md +2 -1
  149. package/src/commands/ccp/secure-phase.md +35 -0
  150. package/src/commands/ccp/session-report.md +19 -0
  151. package/{ecc/commands → src/commands/ccp}/sessions.md +39 -34
  152. package/src/commands/ccp/set-profile.md +12 -0
  153. package/{gsd/commands-gsd → src/commands/ccp}/settings.md +5 -5
  154. package/src/commands/ccp/setup-pm.md +81 -0
  155. package/{kit/commands → src/commands/ccp}/setup-refresh.md +4 -3
  156. package/{kit/commands → src/commands/ccp}/setup.md +67 -40
  157. package/src/commands/ccp/ship.md +23 -0
  158. package/src/commands/ccp/skill-create.md +172 -0
  159. package/src/commands/ccp/skill-health.md +51 -0
  160. package/src/commands/ccp/stats.md +18 -0
  161. package/src/commands/ccp/tdd.md +329 -0
  162. package/src/commands/ccp/test-coverage.md +74 -0
  163. package/src/commands/ccp/thread.md +127 -0
  164. package/{kit/commands → src/commands/ccp}/tool-guide.md +2 -1
  165. package/src/commands/ccp/ui-phase.md +34 -0
  166. package/src/commands/ccp/ui-review.md +32 -0
  167. package/src/commands/ccp/update-codemaps.md +77 -0
  168. package/src/commands/ccp/update-docs.md +89 -0
  169. package/{gsd/commands-gsd → src/commands/ccp}/update.md +5 -5
  170. package/{gsd/commands-gsd → src/commands/ccp}/validate-phase.md +3 -3
  171. package/{gsd/commands-gsd → src/commands/ccp}/verify-work.md +5 -5
  172. package/{ecc/commands → src/commands/ccp}/verify.md +5 -0
  173. package/src/commands/ccp/workstreams.md +68 -0
  174. package/{ecc → src}/examples/CLAUDE.md +4 -4
  175. package/{ecc → src}/examples/django-api-CLAUDE.md +5 -5
  176. package/{ecc → src}/examples/go-microservice-CLAUDE.md +6 -6
  177. package/{ecc → src}/examples/rust-api-CLAUDE.md +4 -4
  178. package/{ecc → src}/examples/saas-nextjs-CLAUDE.md +8 -8
  179. package/{gsd/hooks/gsd-context-monitor.js → src/hooks/ccp-context-monitor.js} +3 -3
  180. package/src/hooks/ccp-prompt-guard.js +96 -0
  181. package/{gsd/hooks/gsd-statusline.js → src/hooks/ccp-statusline.js} +7 -7
  182. package/src/hooks/ccp-workflow-guard.js +94 -0
  183. package/src/hooks/config-protection.js +141 -0
  184. package/{kit → src}/hooks/kit-check-update.js +7 -4
  185. package/src/hooks/mcp-health-check.js +620 -0
  186. package/{ecc/scripts → src}/hooks/run-with-flags-shell.sh +1 -1
  187. package/{ecc/scripts → src}/hooks/run-with-flags.js +74 -13
  188. package/src/hooks/session-end-marker.js +29 -0
  189. package/{ecc/scripts → src}/hooks/session-end.js +83 -40
  190. package/{ecc/scripts → src}/hooks/session-start.js +76 -10
  191. package/{ecc/scripts → src}/lib/hook-flags.js +8 -4
  192. package/{ecc/scripts → src}/lib/project-detect.js +2 -1
  193. package/{ecc/scripts → src}/lib/session-manager.d.ts +5 -1
  194. package/{ecc/scripts → src}/lib/session-manager.js +202 -92
  195. package/{ecc/scripts → src}/lib/utils.d.ts +23 -1
  196. package/{ecc/scripts → src}/lib/utils.js +91 -3
  197. package/{gsd/get-shit-done/bin/gsd-tools.cjs → src/pilot/bin/ccp-tools.cjs} +257 -86
  198. package/{gsd/get-shit-done → src/pilot}/bin/lib/commands.cjs +1 -1
  199. package/src/pilot/bin/lib/config.cjs +444 -0
  200. package/src/pilot/bin/lib/core.cjs +1190 -0
  201. package/src/pilot/bin/lib/init.cjs +1281 -0
  202. package/src/pilot/bin/lib/model-profiles.cjs +67 -0
  203. package/{gsd/get-shit-done → src/pilot}/bin/lib/phase.cjs +2 -2
  204. package/src/pilot/bin/lib/security.cjs +382 -0
  205. package/{gsd/get-shit-done → src/pilot}/bin/lib/state.cjs +1 -1
  206. package/src/pilot/bin/lib/uat.cjs +282 -0
  207. package/{gsd/get-shit-done → src/pilot}/bin/lib/verify.cjs +10 -10
  208. package/{gsd/get-shit-done → src/pilot}/references/continuation-format.md +16 -16
  209. package/{gsd/get-shit-done → src/pilot}/references/decimal-phase-calculation.md +5 -5
  210. package/{gsd/get-shit-done → src/pilot}/references/git-integration.md +5 -5
  211. package/{gsd/get-shit-done → src/pilot}/references/git-planning-commit.md +4 -4
  212. package/src/pilot/references/mcp-servers.json +153 -0
  213. package/{gsd/get-shit-done → src/pilot}/references/model-profile-resolution.md +2 -2
  214. package/{gsd/get-shit-done → src/pilot}/references/model-profiles.md +20 -20
  215. package/{gsd/get-shit-done → src/pilot}/references/phase-argument-parsing.md +4 -4
  216. package/{gsd/get-shit-done → src/pilot}/references/planning-config.md +15 -15
  217. package/{gsd/get-shit-done → src/pilot}/references/ui-brand.md +5 -5
  218. package/{gsd/get-shit-done → src/pilot}/references/verification-patterns.md +1 -1
  219. package/{gsd/get-shit-done → src/pilot}/templates/DEBUG.md +1 -1
  220. package/{gsd/get-shit-done → src/pilot}/templates/UAT.md +3 -3
  221. package/src/pilot/templates/UI-SPEC.md +100 -0
  222. package/{gsd/get-shit-done → src/pilot}/templates/VALIDATION.md +1 -1
  223. package/src/pilot/templates/claude-md.md +122 -0
  224. package/{gsd/get-shit-done → src/pilot}/templates/codebase/architecture.md +2 -2
  225. package/{gsd/get-shit-done → src/pilot}/templates/codebase/structure.md +13 -13
  226. package/{gsd/get-shit-done → src/pilot}/templates/context.md +4 -4
  227. package/src/pilot/templates/copilot-instructions.md +7 -0
  228. package/{gsd/get-shit-done → src/pilot}/templates/debug-subagent-prompt.md +4 -4
  229. package/src/pilot/templates/dev-preferences.md +21 -0
  230. package/{gsd/get-shit-done → src/pilot}/templates/discovery.md +2 -2
  231. package/src/pilot/templates/discussion-log.md +63 -0
  232. package/{gsd/get-shit-done → src/pilot}/templates/phase-prompt.md +12 -12
  233. package/{gsd/get-shit-done → src/pilot}/templates/planner-subagent-prompt.md +7 -7
  234. package/{gsd/get-shit-done → src/pilot}/templates/project.md +1 -1
  235. package/{gsd/get-shit-done → src/pilot}/templates/research.md +2 -2
  236. package/{gsd/get-shit-done → src/pilot}/templates/state.md +2 -2
  237. package/{gsd/get-shit-done → src/pilot}/templates/summary-complex.md +1 -1
  238. package/{gsd/get-shit-done → src/pilot}/workflows/add-phase.md +11 -11
  239. package/{gsd/get-shit-done → src/pilot}/workflows/add-tests.md +15 -15
  240. package/{gsd/get-shit-done → src/pilot}/workflows/add-todo.md +7 -7
  241. package/{gsd/get-shit-done → src/pilot}/workflows/audit-milestone.md +24 -16
  242. package/src/pilot/workflows/audit-uat.md +109 -0
  243. package/src/pilot/workflows/autonomous.md +891 -0
  244. package/{gsd/get-shit-done → src/pilot}/workflows/check-todos.md +10 -10
  245. package/{gsd/get-shit-done → src/pilot}/workflows/cleanup.md +3 -3
  246. package/{gsd/get-shit-done → src/pilot}/workflows/complete-milestone.md +19 -16
  247. package/{gsd/get-shit-done → src/pilot}/workflows/diagnose-issues.md +9 -4
  248. package/{gsd/get-shit-done → src/pilot}/workflows/discovery-phase.md +8 -8
  249. package/src/pilot/workflows/discuss-phase-assumptions.md +653 -0
  250. package/{gsd/get-shit-done → src/pilot}/workflows/discuss-phase.md +407 -49
  251. package/src/pilot/workflows/do.md +104 -0
  252. package/src/pilot/workflows/docs-update.md +1165 -0
  253. package/src/pilot/workflows/execute-phase.md +821 -0
  254. package/{gsd/get-shit-done → src/pilot}/workflows/execute-plan.md +79 -28
  255. package/src/pilot/workflows/fast.md +105 -0
  256. package/src/pilot/workflows/forensics.md +265 -0
  257. package/{gsd/get-shit-done → src/pilot}/workflows/health.md +34 -11
  258. package/src/pilot/workflows/help.md +767 -0
  259. package/{gsd/get-shit-done → src/pilot}/workflows/insert-phase.md +10 -10
  260. package/{gsd/get-shit-done → src/pilot}/workflows/list-phase-assumptions.md +4 -4
  261. package/src/pilot/workflows/manager.md +362 -0
  262. package/{gsd/get-shit-done → src/pilot}/workflows/map-codebase.md +27 -17
  263. package/src/pilot/workflows/milestone-summary.md +223 -0
  264. package/{gsd/get-shit-done → src/pilot}/workflows/new-milestone.md +135 -33
  265. package/{gsd/get-shit-done → src/pilot}/workflows/new-project.md +152 -79
  266. package/src/pilot/workflows/next.md +97 -0
  267. package/src/pilot/workflows/node-repair.md +92 -0
  268. package/src/pilot/workflows/note.md +156 -0
  269. package/src/pilot/workflows/pause-work.md +177 -0
  270. package/{gsd/get-shit-done → src/pilot}/workflows/plan-milestone-gaps.md +10 -11
  271. package/src/pilot/workflows/plan-phase.md +859 -0
  272. package/src/pilot/workflows/plant-seed.md +169 -0
  273. package/src/pilot/workflows/pr-branch.md +129 -0
  274. package/src/pilot/workflows/profile-user.md +452 -0
  275. package/{gsd/get-shit-done → src/pilot}/workflows/progress.md +95 -34
  276. package/{gsd/get-shit-done → src/pilot}/workflows/quick.md +33 -21
  277. package/{gsd/get-shit-done → src/pilot}/workflows/remove-phase.md +14 -14
  278. package/{gsd/get-shit-done → src/pilot}/workflows/research-phase.md +18 -10
  279. package/{gsd/get-shit-done → src/pilot}/workflows/resume-project.md +37 -18
  280. package/src/pilot/workflows/review.md +244 -0
  281. package/src/pilot/workflows/secure-phase.md +164 -0
  282. package/src/pilot/workflows/session-report.md +146 -0
  283. package/{gsd/get-shit-done → src/pilot}/workflows/set-profile.md +7 -7
  284. package/{gsd/get-shit-done → src/pilot}/workflows/settings.md +75 -22
  285. package/src/pilot/workflows/ship.md +228 -0
  286. package/src/pilot/workflows/stats.md +60 -0
  287. package/{gsd/get-shit-done → src/pilot}/workflows/transition.md +57 -17
  288. package/src/pilot/workflows/ui-phase.md +302 -0
  289. package/src/pilot/workflows/ui-review.md +165 -0
  290. package/{gsd/get-shit-done → src/pilot}/workflows/update.md +88 -58
  291. package/{gsd/get-shit-done → src/pilot}/workflows/validate-phase.md +24 -17
  292. package/{gsd/get-shit-done → src/pilot}/workflows/verify-phase.md +26 -15
  293. package/{gsd/get-shit-done → src/pilot}/workflows/verify-work.md +89 -37
  294. package/{ecc → src}/rules/common/agents.md +1 -0
  295. package/src/rules/common/code-review.md +124 -0
  296. package/{ecc → src}/rules/common/coding-style.md +21 -0
  297. package/src/rules/zh/README.md +108 -0
  298. package/src/rules/zh/agents.md +50 -0
  299. package/src/rules/zh/code-review.md +124 -0
  300. package/src/rules/zh/coding-style.md +48 -0
  301. package/src/rules/zh/development-workflow.md +44 -0
  302. package/src/rules/zh/git-workflow.md +24 -0
  303. package/src/rules/zh/hooks.md +30 -0
  304. package/src/rules/zh/patterns.md +31 -0
  305. package/src/rules/zh/performance.md +55 -0
  306. package/src/rules/zh/security.md +29 -0
  307. package/src/rules/zh/testing.md +29 -0
  308. package/src/skills/agentic-engineering/SKILL.md +63 -0
  309. package/src/skills/ai-first-engineering/SKILL.md +51 -0
  310. package/src/skills/ai-regression-testing/SKILL.md +385 -0
  311. package/src/skills/api-design/SKILL.md +523 -0
  312. package/src/skills/architecture-decision-records/SKILL.md +179 -0
  313. package/src/skills/autonomous-agent-harness/SKILL.md +267 -0
  314. package/src/skills/autonomous-loops/SKILL.md +610 -0
  315. package/src/skills/backend-patterns/SKILL.md +598 -0
  316. package/src/skills/benchmark/SKILL.md +87 -0
  317. package/src/skills/blueprint/SKILL.md +90 -0
  318. package/src/skills/browser-qa/SKILL.md +81 -0
  319. package/src/skills/bun-runtime/SKILL.md +84 -0
  320. package/src/skills/claude-api/SKILL.md +337 -0
  321. package/src/skills/codebase-onboarding/SKILL.md +233 -0
  322. package/src/skills/coding-standards/SKILL.md +530 -0
  323. package/src/skills/content-hash-cache-pattern/SKILL.md +161 -0
  324. package/src/skills/context-budget/SKILL.md +135 -0
  325. package/{ecc → src}/skills/continuous-learning-v2/SKILL.md +6 -6
  326. package/{ecc → src}/skills/continuous-learning-v2/agents/observer-loop.sh +1 -1
  327. package/{ecc → src}/skills/continuous-learning-v2/agents/observer.md +1 -1
  328. package/src/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
  329. package/src/skills/cpp-coding-standards/SKILL.md +723 -0
  330. package/src/skills/cpp-testing/SKILL.md +324 -0
  331. package/src/skills/database-migrations/SKILL.md +429 -0
  332. package/src/skills/deep-research/SKILL.md +155 -0
  333. package/src/skills/deployment-patterns/SKILL.md +427 -0
  334. package/src/skills/design-system/SKILL.md +82 -0
  335. package/src/skills/django-patterns/SKILL.md +734 -0
  336. package/src/skills/django-security/SKILL.md +593 -0
  337. package/src/skills/django-tdd/SKILL.md +729 -0
  338. package/src/skills/django-verification/SKILL.md +469 -0
  339. package/src/skills/docker-patterns/SKILL.md +364 -0
  340. package/src/skills/documentation-lookup/SKILL.md +90 -0
  341. package/src/skills/e2e-testing/SKILL.md +326 -0
  342. package/src/skills/eval-harness/SKILL.md +270 -0
  343. package/src/skills/exa-search/SKILL.md +103 -0
  344. package/src/skills/flutter-dart-code-review/SKILL.md +435 -0
  345. package/src/skills/frontend-patterns/SKILL.md +642 -0
  346. package/src/skills/gan-style-harness/SKILL.md +278 -0
  347. package/src/skills/git-workflow/SKILL.md +715 -0
  348. package/src/skills/golang-patterns/SKILL.md +674 -0
  349. package/src/skills/golang-testing/SKILL.md +720 -0
  350. package/src/skills/hexagonal-architecture/SKILL.md +276 -0
  351. package/src/skills/iterative-retrieval/SKILL.md +211 -0
  352. package/src/skills/java-coding-standards/SKILL.md +147 -0
  353. package/src/skills/jpa-patterns/SKILL.md +151 -0
  354. package/src/skills/kotlin-coroutines-flows/SKILL.md +284 -0
  355. package/src/skills/kotlin-exposed-patterns/SKILL.md +719 -0
  356. package/src/skills/kotlin-ktor-patterns/SKILL.md +689 -0
  357. package/src/skills/kotlin-patterns/SKILL.md +711 -0
  358. package/src/skills/kotlin-testing/SKILL.md +824 -0
  359. package/src/skills/laravel-patterns/SKILL.md +415 -0
  360. package/src/skills/laravel-plugin-discovery/SKILL.md +229 -0
  361. package/src/skills/laravel-security/SKILL.md +285 -0
  362. package/src/skills/laravel-tdd/SKILL.md +283 -0
  363. package/src/skills/laravel-verification/SKILL.md +179 -0
  364. package/src/skills/mcp-server-patterns/SKILL.md +67 -0
  365. package/src/skills/nextjs-turbopack/SKILL.md +44 -0
  366. package/src/skills/nuxt4-patterns/SKILL.md +100 -0
  367. package/src/skills/opensource-pipeline/SKILL.md +255 -0
  368. package/src/skills/perl-patterns/SKILL.md +504 -0
  369. package/src/skills/perl-security/SKILL.md +503 -0
  370. package/src/skills/perl-testing/SKILL.md +475 -0
  371. package/src/skills/postgres-patterns/SKILL.md +147 -0
  372. package/src/skills/project-flow-ops/SKILL.md +111 -0
  373. package/src/skills/project-guidelines-example/SKILL.md +349 -0
  374. package/src/skills/prompt-optimizer/SKILL.md +397 -0
  375. package/src/skills/python-patterns/SKILL.md +750 -0
  376. package/src/skills/python-testing/SKILL.md +816 -0
  377. package/src/skills/pytorch-patterns/SKILL.md +396 -0
  378. package/src/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
  379. package/src/skills/repo-scan/SKILL.md +78 -0
  380. package/src/skills/rules-distill/SKILL.md +264 -0
  381. package/src/skills/rules-distill/scripts/scan-rules.sh +58 -0
  382. package/src/skills/rules-distill/scripts/scan-skills.sh +129 -0
  383. package/src/skills/rust-patterns/SKILL.md +499 -0
  384. package/src/skills/rust-testing/SKILL.md +500 -0
  385. package/src/skills/safety-guard/SKILL.md +69 -0
  386. package/src/skills/search-first/SKILL.md +161 -0
  387. package/src/skills/security-review/SKILL.md +495 -0
  388. package/src/skills/security-review/cloud-infrastructure-security.md +361 -0
  389. package/src/skills/security-scan/SKILL.md +165 -0
  390. package/src/skills/springboot-patterns/SKILL.md +314 -0
  391. package/src/skills/springboot-security/SKILL.md +272 -0
  392. package/src/skills/springboot-tdd/SKILL.md +158 -0
  393. package/src/skills/springboot-verification/SKILL.md +231 -0
  394. package/src/skills/swift-concurrency-6-2/SKILL.md +216 -0
  395. package/src/skills/tdd-workflow/SKILL.md +410 -0
  396. package/src/skills/token-budget-advisor/SKILL.md +133 -0
  397. package/{ecc/skills/verification-loop-SKILL.md → src/skills/verification-loop/SKILL.md} +1 -1
  398. package/src/skills/workspace-surface-audit/SKILL.md +125 -0
  399. package/ecc/scripts/hooks/session-end-marker.js +0 -15
  400. package/gsd/LICENSE +0 -21
  401. package/gsd/commands-gsd/discuss-phase.md +0 -90
  402. package/gsd/commands-gsd/execute-phase.md +0 -41
  403. package/gsd/commands-gsd/join-discord.md +0 -18
  404. package/gsd/commands-gsd/reapply-patches.md +0 -123
  405. package/gsd/commands-gsd/set-profile.md +0 -34
  406. package/gsd/get-shit-done/bin/lib/config.cjs +0 -169
  407. package/gsd/get-shit-done/bin/lib/core.cjs +0 -492
  408. package/gsd/get-shit-done/bin/lib/init.cjs +0 -710
  409. package/gsd/get-shit-done/workflows/execute-phase.md +0 -459
  410. package/gsd/get-shit-done/workflows/help.md +0 -489
  411. package/gsd/get-shit-done/workflows/pause-work.md +0 -122
  412. package/gsd/get-shit-done/workflows/plan-phase.md +0 -560
  413. package/gsd/hooks/gsd-check-update.js +0 -81
  414. package/kit/CLAUDE.md +0 -43
  415. package/kit/commands/kit/update.md +0 -46
  416. package/kit/mcp.json +0 -10
  417. package/kit/rules/code-style.md +0 -24
  418. /package/{ecc → src}/agents/architect.md +0 -0
  419. /package/{ecc → src}/agents/code-reviewer.md +0 -0
  420. /package/{ecc → src}/agents/e2e-runner.md +0 -0
  421. /package/{ecc → src}/agents/security-reviewer.md +0 -0
  422. /package/{ecc → src}/agents/tdd-guide.md +0 -0
  423. /package/{ecc/rules → src/available-rules}/golang/coding-style.md +0 -0
  424. /package/{ecc/rules → src/available-rules}/golang/hooks.md +0 -0
  425. /package/{ecc/rules → src/available-rules}/golang/patterns.md +0 -0
  426. /package/{ecc/rules → src/available-rules}/golang/security.md +0 -0
  427. /package/{ecc/rules → src/available-rules}/golang/testing.md +0 -0
  428. /package/{ecc/rules → src/available-rules}/kotlin/coding-style.md +0 -0
  429. /package/{ecc/rules → src/available-rules}/kotlin/patterns.md +0 -0
  430. /package/{ecc/rules → src/available-rules}/kotlin/security.md +0 -0
  431. /package/{ecc/rules → src/available-rules}/kotlin/testing.md +0 -0
  432. /package/{ecc/rules → src/available-rules}/perl/coding-style.md +0 -0
  433. /package/{ecc/rules → src/available-rules}/perl/hooks.md +0 -0
  434. /package/{ecc/rules → src/available-rules}/perl/patterns.md +0 -0
  435. /package/{ecc/rules → src/available-rules}/perl/security.md +0 -0
  436. /package/{ecc/rules → src/available-rules}/perl/testing.md +0 -0
  437. /package/{ecc/rules → src/available-rules}/php/coding-style.md +0 -0
  438. /package/{ecc/rules → src/available-rules}/php/hooks.md +0 -0
  439. /package/{ecc/rules → src/available-rules}/php/patterns.md +0 -0
  440. /package/{ecc/rules → src/available-rules}/php/security.md +0 -0
  441. /package/{ecc/rules → src/available-rules}/php/testing.md +0 -0
  442. /package/{ecc/rules → src/available-rules}/python/coding-style.md +0 -0
  443. /package/{ecc/rules → src/available-rules}/python/hooks.md +0 -0
  444. /package/{ecc/rules → src/available-rules}/python/patterns.md +0 -0
  445. /package/{ecc/rules → src/available-rules}/python/security.md +0 -0
  446. /package/{ecc/rules → src/available-rules}/python/testing.md +0 -0
  447. /package/{ecc/rules → src/available-rules}/swift/coding-style.md +0 -0
  448. /package/{ecc/rules → src/available-rules}/swift/hooks.md +0 -0
  449. /package/{ecc/rules → src/available-rules}/swift/patterns.md +0 -0
  450. /package/{ecc/rules → src/available-rules}/swift/security.md +0 -0
  451. /package/{ecc/rules → src/available-rules}/swift/testing.md +0 -0
  452. /package/{ecc/rules → src/available-rules}/typescript/coding-style.md +0 -0
  453. /package/{ecc/rules → src/available-rules}/typescript/hooks.md +0 -0
  454. /package/{ecc/rules → src/available-rules}/typescript/patterns.md +0 -0
  455. /package/{ecc/rules → src/available-rules}/typescript/security.md +0 -0
  456. /package/{ecc/rules → src/available-rules}/typescript/testing.md +0 -0
  457. /package/{ecc → src}/contexts/dev.md +0 -0
  458. /package/{ecc → src}/contexts/research.md +0 -0
  459. /package/{ecc → src}/contexts/review.md +0 -0
  460. /package/{ecc → src}/examples/user-CLAUDE.md +0 -0
  461. /package/{ecc/scripts → src}/hooks/check-hook-enabled.js +0 -0
  462. /package/{ecc/scripts → src}/hooks/evaluate-session.js +0 -0
  463. /package/{ecc/scripts → src}/hooks/pre-compact.js +0 -0
  464. /package/{ecc/scripts → src}/hooks/suggest-compact.js +0 -0
  465. /package/{ecc/scripts → src}/lib/package-manager.d.ts +0 -0
  466. /package/{ecc/scripts → src}/lib/package-manager.js +0 -0
  467. /package/{ecc/scripts → src}/lib/resolve-formatter.js +0 -0
  468. /package/{ecc/scripts → src}/lib/session-aliases.d.ts +0 -0
  469. /package/{ecc/scripts → src}/lib/session-aliases.js +0 -0
  470. /package/{ecc/scripts → src}/lib/shell-split.js +0 -0
  471. /package/{gsd/get-shit-done → src/pilot}/bin/lib/frontmatter.cjs +0 -0
  472. /package/{gsd/get-shit-done → src/pilot}/bin/lib/milestone.cjs +0 -0
  473. /package/{gsd/get-shit-done → src/pilot}/bin/lib/roadmap.cjs +0 -0
  474. /package/{gsd/get-shit-done → src/pilot}/bin/lib/template.cjs +0 -0
  475. /package/{gsd/get-shit-done → src/pilot}/references/checkpoints.md +0 -0
  476. /package/{gsd/get-shit-done → src/pilot}/references/questioning.md +0 -0
  477. /package/{gsd/get-shit-done → src/pilot}/references/tdd.md +0 -0
  478. /package/{gsd/get-shit-done → src/pilot}/templates/codebase/concerns.md +0 -0
  479. /package/{gsd/get-shit-done → src/pilot}/templates/codebase/conventions.md +0 -0
  480. /package/{gsd/get-shit-done → src/pilot}/templates/codebase/integrations.md +0 -0
  481. /package/{gsd/get-shit-done → src/pilot}/templates/codebase/stack.md +0 -0
  482. /package/{gsd/get-shit-done → src/pilot}/templates/codebase/testing.md +0 -0
  483. /package/{gsd/get-shit-done → src/pilot}/templates/config.json +0 -0
  484. /package/{gsd/get-shit-done → src/pilot}/templates/continue-here.md +0 -0
  485. /package/{gsd/get-shit-done → src/pilot}/templates/milestone-archive.md +0 -0
  486. /package/{gsd/get-shit-done → src/pilot}/templates/milestone.md +0 -0
  487. /package/{gsd/get-shit-done → src/pilot}/templates/requirements.md +0 -0
  488. /package/{gsd/get-shit-done → src/pilot}/templates/research-project/ARCHITECTURE.md +0 -0
  489. /package/{gsd/get-shit-done → src/pilot}/templates/research-project/FEATURES.md +0 -0
  490. /package/{gsd/get-shit-done → src/pilot}/templates/research-project/PITFALLS.md +0 -0
  491. /package/{gsd/get-shit-done → src/pilot}/templates/research-project/STACK.md +0 -0
  492. /package/{gsd/get-shit-done → src/pilot}/templates/research-project/SUMMARY.md +0 -0
  493. /package/{gsd/get-shit-done → src/pilot}/templates/retrospective.md +0 -0
  494. /package/{gsd/get-shit-done → src/pilot}/templates/roadmap.md +0 -0
  495. /package/{gsd/get-shit-done → src/pilot}/templates/summary-minimal.md +0 -0
  496. /package/{gsd/get-shit-done → src/pilot}/templates/summary-standard.md +0 -0
  497. /package/{gsd/get-shit-done → src/pilot}/templates/summary.md +0 -0
  498. /package/{gsd/get-shit-done → src/pilot}/templates/user-setup.md +0 -0
  499. /package/{gsd/get-shit-done → src/pilot}/templates/verification-report.md +0 -0
  500. /package/{ecc → src}/rules/common/development-workflow.md +0 -0
  501. /package/{ecc → src}/rules/common/git-workflow.md +0 -0
  502. /package/{ecc → src}/rules/common/hooks.md +0 -0
  503. /package/{ecc → src}/rules/common/patterns.md +0 -0
  504. /package/{ecc → src}/rules/common/performance.md +0 -0
  505. /package/{ecc → src}/rules/common/security.md +0 -0
  506. /package/{ecc → src}/rules/common/testing.md +0 -0
  507. /package/{ecc → src}/skills/continuous-learning-v2/agents/start-observer.sh +0 -0
  508. /package/{ecc → src}/skills/continuous-learning-v2/config.json +0 -0
  509. /package/{ecc → src}/skills/continuous-learning-v2/hooks/observe.sh +0 -0
  510. /package/{ecc → src}/skills/continuous-learning-v2/scripts/detect-project.sh +0 -0
  511. /package/{ecc → src}/skills/continuous-learning-v2/scripts/instinct-cli.py +0 -0
  512. /package/{ecc → src}/skills/continuous-learning-v2/scripts/test_parse_instinct.py +0 -0
  513. /package/{ecc → src}/skills/strategic-compact/SKILL.md +0 -0
  514. /package/{ecc → src}/skills/strategic-compact/suggest-compact.sh +0 -0
@@ -2,7 +2,8 @@
2
2
  * Session Manager Library for Claude Code
3
3
  * Provides core session CRUD operations for listing, loading, and managing sessions
4
4
  *
5
- * Sessions are stored as markdown files in ~/.claude/sessions/ with format:
5
+ * Sessions are stored as markdown files in ~/.claude/session-data/ with
6
+ * legacy read compatibility for ~/.claude/sessions/:
6
7
  * - YYYY-MM-DD-session.tmp (old format)
7
8
  * - YYYY-MM-DD-<short-id>-session.tmp (new format)
8
9
  */
@@ -12,16 +13,18 @@ const path = require('path');
12
13
 
13
14
  const {
14
15
  getSessionsDir,
16
+ getSessionSearchDirs,
15
17
  readFile,
16
18
  log
17
19
  } = require('./utils');
18
20
 
19
21
  // Session filename pattern: YYYY-MM-DD-[session-id]-session.tmp
20
- // The session-id is optional (old format) and can include lowercase
21
- // alphanumeric characters and hyphens, with a minimum length of 8.
22
+ // The session-id is optional (old format) and can include letters, digits,
23
+ // underscores, and hyphens, but must not start with a hyphen.
22
24
  // Matches: "2026-02-01-session.tmp", "2026-02-01-a1b2c3d4-session.tmp",
23
- // and "2026-02-01-frontend-worktree-1-session.tmp"
24
- const SESSION_FILENAME_REGEX = /^(\d{4}-\d{2}-\d{2})(?:-([a-z0-9-]{8,}))?-session\.tmp$/;
25
+ // "2026-02-01-frontend-worktree-1-session.tmp", and
26
+ // "2026-02-01-ChezMoi_2-session.tmp"
27
+ const SESSION_FILENAME_REGEX = /^(\d{4}-\d{2}-\d{2})(?:-([a-zA-Z0-9_][a-zA-Z0-9_-]*))?-session\.tmp$/;
25
28
 
26
29
  /**
27
30
  * Parse session filename to extract metadata
@@ -29,6 +32,7 @@ const SESSION_FILENAME_REGEX = /^(\d{4}-\d{2}-\d{2})(?:-([a-z0-9-]{8,}))?-sessio
29
32
  * @returns {object|null} Parsed metadata or null if invalid
30
33
  */
31
34
  function parseSessionFilename(filename) {
35
+ if (!filename || typeof filename !== 'string') return null;
32
36
  const match = filename.match(SESSION_FILENAME_REGEX);
33
37
  if (!match) return null;
34
38
 
@@ -74,6 +78,166 @@ function getSessionContent(sessionPath) {
74
78
  return readFile(sessionPath);
75
79
  }
76
80
 
81
+ /**
82
+ * Gather session candidates from all search directories, deduplicated by filename.
83
+ * session-data/ entries take priority over sessions/ entries.
84
+ * @param {object} options - Filter options { date, search }
85
+ * @returns {object[]} Deduplicated, sorted session candidates
86
+ */
87
+ function getSessionCandidates(options = {}) {
88
+ const {
89
+ date = null,
90
+ search = null
91
+ } = options;
92
+
93
+ const candidates = [];
94
+
95
+ for (const sessionsDir of getSessionSearchDirs()) {
96
+ if (!fs.existsSync(sessionsDir)) {
97
+ continue;
98
+ }
99
+
100
+ let entries;
101
+ try {
102
+ entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
103
+ } catch (error) {
104
+ log(`[SessionManager] Error reading sessions directory ${sessionsDir}: ${error.message}`);
105
+ continue;
106
+ }
107
+
108
+ for (const entry of entries) {
109
+ if (!entry.isFile() || !entry.name.endsWith('.tmp')) continue;
110
+
111
+ const filename = entry.name;
112
+ const metadata = parseSessionFilename(filename);
113
+
114
+ if (!metadata) continue;
115
+ if (date && metadata.date !== date) continue;
116
+ if (search && !metadata.shortId.includes(search)) continue;
117
+
118
+ const sessionPath = path.join(sessionsDir, filename);
119
+
120
+ let stats;
121
+ try {
122
+ stats = fs.statSync(sessionPath);
123
+ } catch {
124
+ continue;
125
+ }
126
+
127
+ candidates.push({
128
+ ...metadata,
129
+ sessionPath,
130
+ hasContent: stats.size > 0,
131
+ size: stats.size,
132
+ modifiedTime: stats.mtime,
133
+ createdTime: stats.birthtime || stats.ctime
134
+ });
135
+ }
136
+ }
137
+
138
+ const deduped = [];
139
+ const seenFilenames = new Set();
140
+
141
+ for (const session of candidates) {
142
+ if (seenFilenames.has(session.filename)) {
143
+ continue;
144
+ }
145
+ seenFilenames.add(session.filename);
146
+ deduped.push(session);
147
+ }
148
+
149
+ deduped.sort((a, b) => b.modifiedTime - a.modifiedTime);
150
+ return deduped;
151
+ }
152
+
153
+ /**
154
+ * Build a session record from a path and metadata
155
+ * @param {string} sessionPath - Full path to session file
156
+ * @param {object} metadata - Parsed filename metadata
157
+ * @returns {object|null} Session record or null if stat fails
158
+ */
159
+ function buildSessionRecord(sessionPath, metadata) {
160
+ let stats;
161
+ try {
162
+ stats = fs.statSync(sessionPath);
163
+ } catch {
164
+ return null;
165
+ }
166
+
167
+ return {
168
+ ...metadata,
169
+ sessionPath,
170
+ hasContent: stats.size > 0,
171
+ size: stats.size,
172
+ modifiedTime: stats.mtime,
173
+ createdTime: stats.birthtime || stats.ctime
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Check if a session's metadata matches a given session ID
179
+ * @param {object} metadata - Parsed filename metadata
180
+ * @param {string} normalizedSessionId - Trimmed session ID to match against
181
+ * @returns {boolean} True if the session matches
182
+ */
183
+ function sessionMatchesId(metadata, normalizedSessionId) {
184
+ const filename = metadata.filename;
185
+ const shortIdMatch = metadata.shortId !== 'no-id' && metadata.shortId.startsWith(normalizedSessionId);
186
+ const filenameMatch = filename === normalizedSessionId || filename === `${normalizedSessionId}.tmp`;
187
+ const noIdMatch = metadata.shortId === 'no-id' && filename === `${normalizedSessionId}-session.tmp`;
188
+
189
+ return shortIdMatch || filenameMatch || noIdMatch;
190
+ }
191
+
192
+ /**
193
+ * Find matching session candidates across all search directories
194
+ * @param {string} normalizedSessionId - Trimmed session ID to match
195
+ * @returns {object[]} Matching session records, sorted by modification time
196
+ */
197
+ function getMatchingSessionCandidates(normalizedSessionId) {
198
+ const matches = [];
199
+ const seenFilenames = new Set();
200
+
201
+ for (const sessionsDir of getSessionSearchDirs()) {
202
+ if (!fs.existsSync(sessionsDir)) {
203
+ continue;
204
+ }
205
+
206
+ let entries;
207
+ try {
208
+ entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
209
+ } catch (error) {
210
+ log(`[SessionManager] Error reading sessions directory ${sessionsDir}: ${error.message}`);
211
+ continue;
212
+ }
213
+
214
+ for (const entry of entries) {
215
+ if (!entry.isFile() || !entry.name.endsWith('.tmp')) continue;
216
+
217
+ const metadata = parseSessionFilename(entry.name);
218
+ if (!metadata || !sessionMatchesId(metadata, normalizedSessionId)) {
219
+ continue;
220
+ }
221
+
222
+ if (seenFilenames.has(metadata.filename)) {
223
+ continue;
224
+ }
225
+
226
+ const sessionPath = path.join(sessionsDir, metadata.filename);
227
+ const sessionRecord = buildSessionRecord(sessionPath, metadata);
228
+ if (!sessionRecord) {
229
+ continue;
230
+ }
231
+
232
+ seenFilenames.add(metadata.filename);
233
+ matches.push(sessionRecord);
234
+ }
235
+ }
236
+
237
+ matches.sort((a, b) => b.modifiedTime - a.modifiedTime);
238
+ return matches;
239
+ }
240
+
77
241
  /**
78
242
  * Parse session metadata from markdown content
79
243
  * @param {string} content - Session markdown content
@@ -85,6 +249,9 @@ function parseSessionMetadata(content) {
85
249
  date: null,
86
250
  started: null,
87
251
  lastUpdated: null,
252
+ project: null,
253
+ branch: null,
254
+ worktree: null,
88
255
  completed: [],
89
256
  inProgress: [],
90
257
  notes: '',
@@ -117,6 +284,22 @@ function parseSessionMetadata(content) {
117
284
  metadata.lastUpdated = updatedMatch[1];
118
285
  }
119
286
 
287
+ // Extract control-plane metadata
288
+ const projectMatch = content.match(/\*\*Project:\*\*\s*(.+)$/m);
289
+ if (projectMatch) {
290
+ metadata.project = projectMatch[1].trim();
291
+ }
292
+
293
+ const branchMatch = content.match(/\*\*Branch:\*\*\s*(.+)$/m);
294
+ if (branchMatch) {
295
+ metadata.branch = branchMatch[1].trim();
296
+ }
297
+
298
+ const worktreeMatch = content.match(/\*\*Worktree:\*\*\s*(.+)$/m);
299
+ if (worktreeMatch) {
300
+ metadata.worktree = worktreeMatch[1].trim();
301
+ }
302
+
120
303
  // Extract completed items
121
304
  const completedSection = content.match(/### Completed\s*\n([\s\S]*?)(?=###|\n\n|$)/);
122
305
  if (completedSection) {
@@ -208,58 +391,12 @@ function getAllSessions(options = {}) {
208
391
  const limitNum = Number(rawLimit);
209
392
  const limit = Number.isNaN(limitNum) ? 50 : Math.max(1, Math.floor(limitNum));
210
393
 
211
- const sessionsDir = getSessionsDir();
394
+ const sessions = getSessionCandidates({ date, search });
212
395
 
213
- if (!fs.existsSync(sessionsDir)) {
396
+ if (sessions.length === 0) {
214
397
  return { sessions: [], total: 0, offset, limit, hasMore: false };
215
398
  }
216
399
 
217
- const entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
218
- const sessions = [];
219
-
220
- for (const entry of entries) {
221
- // Skip non-files (only process .tmp files)
222
- if (!entry.isFile() || !entry.name.endsWith('.tmp')) continue;
223
-
224
- const filename = entry.name;
225
- const metadata = parseSessionFilename(filename);
226
-
227
- if (!metadata) continue;
228
-
229
- // Apply date filter
230
- if (date && metadata.date !== date) {
231
- continue;
232
- }
233
-
234
- // Apply search filter (search in short ID)
235
- if (search && !metadata.shortId.includes(search)) {
236
- continue;
237
- }
238
-
239
- const sessionPath = path.join(sessionsDir, filename);
240
-
241
- // Get file stats (wrapped in try-catch to handle TOCTOU race where
242
- // file is deleted between readdirSync and statSync)
243
- let stats;
244
- try {
245
- stats = fs.statSync(sessionPath);
246
- } catch {
247
- continue; // File was deleted between readdir and stat
248
- }
249
-
250
- sessions.push({
251
- ...metadata,
252
- sessionPath,
253
- hasContent: stats.size > 0,
254
- size: stats.size,
255
- modifiedTime: stats.mtime,
256
- createdTime: stats.birthtime || stats.ctime
257
- });
258
- }
259
-
260
- // Sort by modified time (newest first)
261
- sessions.sort((a, b) => b.modifiedTime - a.modifiedTime);
262
-
263
400
  // Apply pagination
264
401
  const paginatedSessions = sessions.slice(offset, offset + limit);
265
402
 
@@ -279,55 +416,28 @@ function getAllSessions(options = {}) {
279
416
  * @returns {object|null} Session object or null if not found
280
417
  */
281
418
  function getSessionById(sessionId, includeContent = false) {
282
- const sessionsDir = getSessionsDir();
283
-
284
- if (!fs.existsSync(sessionsDir)) {
419
+ if (typeof sessionId !== 'string') {
285
420
  return null;
286
421
  }
287
422
 
288
- const entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
289
-
290
- for (const entry of entries) {
291
- if (!entry.isFile() || !entry.name.endsWith('.tmp')) continue;
292
-
293
- const filename = entry.name;
294
- const metadata = parseSessionFilename(filename);
295
-
296
- if (!metadata) continue;
297
-
298
- // Check if session ID matches (short ID or full filename without .tmp)
299
- const shortIdMatch = sessionId.length > 0 && metadata.shortId !== 'no-id' && metadata.shortId.startsWith(sessionId);
300
- const filenameMatch = filename === sessionId || filename === `${sessionId}.tmp`;
301
- const noIdMatch = metadata.shortId === 'no-id' && filename === `${sessionId}-session.tmp`;
302
-
303
- if (!shortIdMatch && !filenameMatch && !noIdMatch) {
304
- continue;
305
- }
423
+ const normalizedSessionId = sessionId.trim();
424
+ if (!normalizedSessionId) {
425
+ return null;
426
+ }
306
427
 
307
- const sessionPath = path.join(sessionsDir, filename);
308
- let stats;
309
- try {
310
- stats = fs.statSync(sessionPath);
311
- } catch {
312
- return null; // File was deleted between readdir and stat
313
- }
428
+ const sessions = getMatchingSessionCandidates(normalizedSessionId);
314
429
 
315
- const session = {
316
- ...metadata,
317
- sessionPath,
318
- size: stats.size,
319
- modifiedTime: stats.mtime,
320
- createdTime: stats.birthtime || stats.ctime
321
- };
430
+ for (const session of sessions) {
431
+ const sessionRecord = { ...session };
322
432
 
323
433
  if (includeContent) {
324
- session.content = getSessionContent(sessionPath);
325
- session.metadata = parseSessionMetadata(session.content);
434
+ sessionRecord.content = getSessionContent(sessionRecord.sessionPath);
435
+ sessionRecord.metadata = parseSessionMetadata(sessionRecord.content);
326
436
  // Pass pre-read content to avoid a redundant disk read
327
- session.stats = getSessionStats(session.content || '');
437
+ sessionRecord.stats = getSessionStats(sessionRecord.content || '');
328
438
  }
329
439
 
330
- return session;
440
+ return sessionRecord;
331
441
  }
332
442
 
333
443
  return null;
@@ -18,9 +18,15 @@ export function getHomeDir(): string;
18
18
  /** Get the Claude config directory (~/.claude) */
19
19
  export function getClaudeDir(): string;
20
20
 
21
- /** Get the sessions directory (~/.claude/sessions) */
21
+ /** Get the sessions directory (~/.claude/session-data) */
22
22
  export function getSessionsDir(): string;
23
23
 
24
+ /** Get the legacy sessions directory (~/.claude/sessions) used by older installs */
25
+ export function getLegacySessionsDir(): string;
26
+
27
+ /** Get all session directories to search, in canonical-first order */
28
+ export function getSessionSearchDirs(): string[];
29
+
24
30
  /** Get the learned skills directory (~/.claude/skills/learned) */
25
31
  export function getLearnedSkillsDir(): string;
26
32
 
@@ -47,6 +53,14 @@ export function getDateTimeString(): string;
47
53
 
48
54
  // --- Session/Project ---
49
55
 
56
+ /**
57
+ * Sanitize a string for use as a session filename segment.
58
+ * Replaces invalid characters, handles non-ASCII via hashing,
59
+ * and guards against Windows reserved names.
60
+ * @returns Sanitized string, or null if input is empty/meaningless
61
+ */
62
+ export function sanitizeSessionId(raw: string): string | null;
63
+
50
64
  /**
51
65
  * Get short session ID from CLAUDE_SESSION_ID environment variable.
52
66
  * Returns last 8 characters, falls back to project name then the provided fallback.
@@ -123,6 +137,14 @@ export interface GrepMatch {
123
137
  /** Search for a pattern in a file and return matching lines with line numbers */
124
138
  export function grepFile(filePath: string, pattern: string | RegExp): GrepMatch[];
125
139
 
140
+ // --- String sanitisation ---
141
+
142
+ /**
143
+ * Strip all ANSI escape sequences from a string.
144
+ * Handles CSI, OSC, charset selection, and bare ESC sequences.
145
+ */
146
+ export function stripAnsi(str: string): string;
147
+
126
148
  // --- Hook I/O ---
127
149
 
128
150
  export interface ReadStdinJsonOptions {
@@ -6,12 +6,20 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const os = require('os');
9
+ const crypto = require('crypto');
9
10
  const { execSync, spawnSync } = require('child_process');
10
11
 
11
12
  // Platform detection
12
13
  const isWindows = process.platform === 'win32';
13
14
  const isMacOS = process.platform === 'darwin';
14
15
  const isLinux = process.platform === 'linux';
16
+ const SESSION_DATA_DIR_NAME = 'session-data';
17
+ const LEGACY_SESSIONS_DIR_NAME = 'sessions';
18
+ const WINDOWS_RESERVED_SESSION_IDS = new Set([
19
+ 'CON', 'PRN', 'AUX', 'NUL',
20
+ 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
21
+ 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'
22
+ ]);
15
23
 
16
24
  /**
17
25
  * Get the user's home directory (cross-platform)
@@ -21,17 +29,38 @@ function getHomeDir() {
21
29
  }
22
30
 
23
31
  /**
24
- * Get the Claude config directory
32
+ * Get the Claude config directory.
33
+ * Self-detects local CCP installs by checking for .claude/pilot/VERSION
34
+ * in the current working directory. Falls back to CLAUDE_CONFIG_DIR env
35
+ * var or the global ~/.claude/ directory.
25
36
  */
26
37
  function getClaudeDir() {
27
- return path.join(getHomeDir(), '.claude');
38
+ const localDir = path.join(process.cwd(), '.claude');
39
+ if (fs.existsSync(path.join(localDir, 'pilot', 'VERSION'))) {
40
+ return localDir;
41
+ }
42
+ return process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
28
43
  }
29
44
 
30
45
  /**
31
46
  * Get the sessions directory
32
47
  */
33
48
  function getSessionsDir() {
34
- return path.join(getClaudeDir(), 'sessions');
49
+ return path.join(getClaudeDir(), SESSION_DATA_DIR_NAME);
50
+ }
51
+
52
+ /**
53
+ * Get the legacy sessions directory used by older ECC installs
54
+ */
55
+ function getLegacySessionsDir() {
56
+ return path.join(getClaudeDir(), LEGACY_SESSIONS_DIR_NAME);
57
+ }
58
+
59
+ /**
60
+ * Get all session directories to search, in canonical-first order
61
+ */
62
+ function getSessionSearchDirs() {
63
+ return Array.from(new Set([getSessionsDir(), getLegacySessionsDir()]));
35
64
  }
36
65
 
37
66
  /**
@@ -107,6 +136,41 @@ function getProjectName() {
107
136
  return path.basename(process.cwd()) || null;
108
137
  }
109
138
 
139
+ /**
140
+ * Sanitize a string for use as a session filename segment.
141
+ * Replaces invalid characters with hyphens, collapses runs, strips
142
+ * leading/trailing hyphens, and removes leading dots so hidden-dir names
143
+ * like ".claude" map cleanly to "claude".
144
+ *
145
+ * Pure non-ASCII inputs get a stable 8-char hash so distinct names do not
146
+ * collapse to the same fallback session id. Mixed-script inputs retain their
147
+ * ASCII part and gain a short hash suffix for disambiguation.
148
+ */
149
+ function sanitizeSessionId(raw) {
150
+ if (!raw || typeof raw !== 'string') return null;
151
+
152
+ const hasNonAscii = Array.from(raw).some(char => char.codePointAt(0) > 0x7f);
153
+ const normalized = raw.replace(/^\.+/, '');
154
+ const sanitized = normalized
155
+ .replace(/[^a-zA-Z0-9_-]/g, '-')
156
+ .replace(/-{2,}/g, '-')
157
+ .replace(/^-+|-+$/g, '');
158
+
159
+ if (sanitized.length > 0) {
160
+ const suffix = crypto.createHash('sha256').update(normalized).digest('hex').slice(0, 6);
161
+ if (WINDOWS_RESERVED_SESSION_IDS.has(sanitized.toUpperCase())) {
162
+ return `${sanitized}-${suffix}`;
163
+ }
164
+ if (!hasNonAscii) return sanitized;
165
+ return `${sanitized}-${suffix}`;
166
+ }
167
+
168
+ const meaningful = normalized.replace(/[\s\p{P}]/gu, '');
169
+ if (meaningful.length === 0) return null;
170
+
171
+ return crypto.createHash('sha256').update(normalized).digest('hex').slice(0, 8);
172
+ }
173
+
110
174
  /**
111
175
  * Get short session ID from CLAUDE_SESSION_ID environment variable
112
176
  * Returns last 8 characters, falls back to project name then 'default'
@@ -464,6 +528,24 @@ function countInFile(filePath, pattern) {
464
528
  return matches ? matches.length : 0;
465
529
  }
466
530
 
531
+ /**
532
+ * Strip all ANSI escape sequences from a string.
533
+ *
534
+ * Handles:
535
+ * - CSI sequences: \x1b[ ... <letter> (colors, cursor movement, erase, etc.)
536
+ * - OSC sequences: \x1b] ... BEL/ST (window titles, hyperlinks)
537
+ * - Charset selection: \x1b(B
538
+ * - Bare ESC + single letter: \x1b <letter> (e.g. \x1bM for reverse index)
539
+ *
540
+ * @param {string} str - Input string possibly containing ANSI codes
541
+ * @returns {string} Cleaned string with all escape sequences removed
542
+ */
543
+ function stripAnsi(str) {
544
+ if (typeof str !== 'string') return '';
545
+ // eslint-disable-next-line no-control-regex
546
+ return str.replace(/\x1b(?:\[[0-9;?]*[A-Za-z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|\([A-Z]|[A-Z])/g, '');
547
+ }
548
+
467
549
  /**
468
550
  * Search for pattern in file and return matching lines with line numbers
469
551
  */
@@ -507,6 +589,8 @@ module.exports = {
507
589
  getHomeDir,
508
590
  getClaudeDir,
509
591
  getSessionsDir,
592
+ getLegacySessionsDir,
593
+ getSessionSearchDirs,
510
594
  getLearnedSkillsDir,
511
595
  getTempDir,
512
596
  ensureDir,
@@ -517,6 +601,7 @@ module.exports = {
517
601
  getDateTimeString,
518
602
 
519
603
  // Session/Project
604
+ sanitizeSessionId,
520
605
  getSessionIdShort,
521
606
  getGitRepoName,
522
607
  getProjectName,
@@ -530,6 +615,9 @@ module.exports = {
530
615
  countInFile,
531
616
  grepFile,
532
617
 
618
+ // String sanitisation
619
+ stripAnsi,
620
+
533
621
  // Hook I/O
534
622
  readStdinJson,
535
623
  log,