claude-code-workflow 6.2.5 → 6.2.7

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 (965) hide show
  1. package/.claude/CLAUDE.md +10 -0
  2. package/.claude/agents/action-planning-agent.md +857 -0
  3. package/.claude/agents/cli-execution-agent.md +267 -0
  4. package/.claude/agents/cli-explore-agent.md +182 -0
  5. package/.claude/agents/cli-lite-planning-agent.md +446 -0
  6. package/.claude/agents/cli-planning-agent.md +558 -0
  7. package/.claude/agents/code-developer.md +311 -0
  8. package/.claude/agents/conceptual-planning-agent.md +308 -0
  9. package/.claude/agents/context-search-agent.md +581 -0
  10. package/.claude/agents/doc-generator.md +330 -0
  11. package/.claude/agents/memory-bridge.md +94 -0
  12. package/.claude/agents/test-context-search-agent.md +400 -0
  13. package/.claude/agents/test-fix-agent.md +344 -0
  14. package/.claude/agents/ui-design-agent.md +593 -0
  15. package/.claude/agents/universal-executor.md +131 -0
  16. package/.claude/commands/clean.md +516 -0
  17. package/.claude/commands/cli/cli-init.md +440 -0
  18. package/.claude/commands/enhance-prompt.md +93 -0
  19. package/.claude/commands/memory/code-map-memory.md +687 -0
  20. package/.claude/commands/memory/compact.md +383 -0
  21. package/.claude/commands/memory/docs-full-cli.md +471 -0
  22. package/.claude/commands/memory/docs-related-cli.md +386 -0
  23. package/.claude/commands/memory/docs.md +615 -0
  24. package/.claude/commands/memory/load-skill-memory.md +182 -0
  25. package/.claude/commands/memory/load.md +240 -0
  26. package/.claude/commands/memory/skill-memory.md +525 -0
  27. package/.claude/commands/memory/style-skill-memory.md +396 -0
  28. package/.claude/commands/memory/tech-research-rules.md +310 -0
  29. package/.claude/commands/memory/update-full.md +332 -0
  30. package/.claude/commands/memory/update-related.md +332 -0
  31. package/.claude/commands/memory/workflow-skill-memory.md +517 -0
  32. package/.claude/commands/task/breakdown.md +204 -0
  33. package/.claude/commands/task/create.md +152 -0
  34. package/.claude/commands/task/execute.md +270 -0
  35. package/.claude/commands/task/replan.md +437 -0
  36. package/.claude/commands/version.md +254 -0
  37. package/.claude/commands/workflow/action-plan-verify.md +447 -0
  38. package/.claude/commands/workflow/brainstorm/api-designer.md +587 -0
  39. package/.claude/commands/workflow/brainstorm/artifacts.md +453 -0
  40. package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -0
  41. package/.claude/commands/workflow/brainstorm/data-architect.md +220 -0
  42. package/.claude/commands/workflow/brainstorm/product-manager.md +200 -0
  43. package/.claude/commands/workflow/brainstorm/product-owner.md +200 -0
  44. package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -0
  45. package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -0
  46. package/.claude/commands/workflow/brainstorm/synthesis.md +398 -0
  47. package/.claude/commands/workflow/brainstorm/system-architect.md +389 -0
  48. package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -0
  49. package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -0
  50. package/.claude/commands/workflow/debug.md +321 -0
  51. package/.claude/commands/workflow/execute.md +475 -0
  52. package/.claude/commands/workflow/init.md +165 -0
  53. package/.claude/commands/workflow/lite-execute.md +792 -0
  54. package/.claude/commands/workflow/lite-fix.md +623 -0
  55. package/.claude/commands/workflow/lite-plan.md +610 -0
  56. package/.claude/commands/workflow/plan.md +551 -0
  57. package/.claude/commands/workflow/replan.md +515 -0
  58. package/.claude/commands/workflow/review-fix.md +606 -0
  59. package/.claude/commands/workflow/review-module-cycle.md +767 -0
  60. package/.claude/commands/workflow/review-session-cycle.md +778 -0
  61. package/.claude/commands/workflow/review.md +297 -0
  62. package/.claude/commands/workflow/session/complete.md +153 -0
  63. package/.claude/commands/workflow/session/list.md +96 -0
  64. package/.claude/commands/workflow/session/resume.md +61 -0
  65. package/.claude/commands/workflow/session/start.md +200 -0
  66. package/.claude/commands/workflow/tdd-plan.md +460 -0
  67. package/.claude/commands/workflow/tdd-verify.md +400 -0
  68. package/.claude/commands/workflow/test-cycle-execute.md +500 -0
  69. package/.claude/commands/workflow/test-fix-gen.md +699 -0
  70. package/.claude/commands/workflow/test-gen.md +529 -0
  71. package/.claude/commands/workflow/tools/conflict-resolution.md +766 -0
  72. package/.claude/commands/workflow/tools/context-gather.md +436 -0
  73. package/.claude/commands/workflow/tools/task-generate-agent.md +490 -0
  74. package/.claude/commands/workflow/tools/task-generate-tdd.md +526 -0
  75. package/.claude/commands/workflow/tools/tdd-coverage-analysis.md +309 -0
  76. package/.claude/commands/workflow/tools/test-concept-enhanced.md +164 -0
  77. package/.claude/commands/workflow/tools/test-context-gather.md +236 -0
  78. package/.claude/commands/workflow/tools/test-task-generate.md +257 -0
  79. package/.claude/commands/workflow/ui-design/animation-extract.md +1150 -0
  80. package/.claude/commands/workflow/ui-design/codify-style.md +652 -0
  81. package/.claude/commands/workflow/ui-design/design-sync.md +454 -0
  82. package/.claude/commands/workflow/ui-design/explore-auto.md +678 -0
  83. package/.claude/commands/workflow/ui-design/generate.md +504 -0
  84. package/.claude/commands/workflow/ui-design/imitate-auto.md +745 -0
  85. package/.claude/commands/workflow/ui-design/import-from-code.md +540 -0
  86. package/.claude/commands/workflow/ui-design/layout-extract.md +788 -0
  87. package/.claude/commands/workflow/ui-design/reference-page-generator.md +356 -0
  88. package/.claude/commands/workflow/ui-design/style-extract.md +773 -0
  89. package/.claude/skills/command-guide/SKILL.md +388 -0
  90. package/.claude/skills/command-guide/UPDATE-GUIDELINE.md +592 -0
  91. package/.claude/skills/command-guide/guides/cli-tools-guide.md +410 -0
  92. package/.claude/skills/command-guide/guides/examples.md +537 -0
  93. package/.claude/skills/command-guide/guides/getting-started.md +242 -0
  94. package/.claude/skills/command-guide/guides/implementation-details.md +1010 -0
  95. package/.claude/skills/command-guide/guides/index-structure.md +326 -0
  96. package/.claude/skills/command-guide/guides/troubleshooting.md +92 -0
  97. package/.claude/skills/command-guide/guides/ui-design-workflow-guide.md +316 -0
  98. package/.claude/skills/command-guide/guides/workflow-patterns.md +662 -0
  99. package/.claude/skills/command-guide/index/all-commands.json +772 -0
  100. package/.claude/skills/command-guide/index/by-category.json +800 -0
  101. package/.claude/skills/command-guide/index/by-use-case.json +786 -0
  102. package/.claude/skills/command-guide/index/command-relationships.json +307 -0
  103. package/.claude/skills/command-guide/index/essential-commands.json +112 -0
  104. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -0
  105. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +267 -0
  106. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +182 -0
  107. package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +446 -0
  108. package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +558 -0
  109. package/.claude/skills/command-guide/reference/agents/code-developer.md +311 -0
  110. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +308 -0
  111. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +581 -0
  112. package/.claude/skills/command-guide/reference/agents/doc-generator.md +330 -0
  113. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +94 -0
  114. package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +400 -0
  115. package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +344 -0
  116. package/.claude/skills/command-guide/reference/agents/ui-design-agent.md +593 -0
  117. package/.claude/skills/command-guide/reference/agents/universal-executor.md +131 -0
  118. package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +440 -0
  119. package/.claude/skills/command-guide/reference/commands/enhance-prompt.md +93 -0
  120. package/.claude/skills/command-guide/reference/commands/memory/code-map-memory.md +687 -0
  121. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -0
  122. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -0
  123. package/.claude/skills/command-guide/reference/commands/memory/docs.md +616 -0
  124. package/.claude/skills/command-guide/reference/commands/memory/load-skill-memory.md +182 -0
  125. package/.claude/skills/command-guide/reference/commands/memory/load.md +240 -0
  126. package/.claude/skills/command-guide/reference/commands/memory/skill-memory.md +525 -0
  127. package/.claude/skills/command-guide/reference/commands/memory/style-skill-memory.md +396 -0
  128. package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +314 -0
  129. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -0
  130. package/.claude/skills/command-guide/reference/commands/memory/update-related.md +332 -0
  131. package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +517 -0
  132. package/.claude/skills/command-guide/reference/commands/task/breakdown.md +204 -0
  133. package/.claude/skills/command-guide/reference/commands/task/create.md +152 -0
  134. package/.claude/skills/command-guide/reference/commands/task/execute.md +270 -0
  135. package/.claude/skills/command-guide/reference/commands/task/replan.md +437 -0
  136. package/.claude/skills/command-guide/reference/commands/version.md +254 -0
  137. package/.claude/skills/command-guide/reference/commands/workflow/action-plan-verify.md +447 -0
  138. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -0
  139. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +452 -0
  140. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -0
  141. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -0
  142. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -0
  143. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -0
  144. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -0
  145. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -0
  146. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +398 -0
  147. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -0
  148. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -0
  149. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -0
  150. package/.claude/skills/command-guide/reference/commands/workflow/execute.md +465 -0
  151. package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -0
  152. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -0
  153. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -0
  154. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -0
  155. package/.claude/skills/command-guide/reference/commands/workflow/plan.md +551 -0
  156. package/.claude/skills/command-guide/reference/commands/workflow/replan.md +515 -0
  157. package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +606 -0
  158. package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +765 -0
  159. package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +776 -0
  160. package/.claude/skills/command-guide/reference/commands/workflow/review.md +298 -0
  161. package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -0
  162. package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +114 -0
  163. package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +77 -0
  164. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +257 -0
  165. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +460 -0
  166. package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +400 -0
  167. package/.claude/skills/command-guide/reference/commands/workflow/test-cycle-execute.md +498 -0
  168. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -0
  169. package/.claude/skills/command-guide/reference/commands/workflow/test-gen.md +529 -0
  170. package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +766 -0
  171. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -0
  172. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -0
  173. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +525 -0
  174. package/.claude/skills/command-guide/reference/commands/workflow/tools/tdd-coverage-analysis.md +309 -0
  175. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +163 -0
  176. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +235 -0
  177. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +256 -0
  178. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/animation-extract.md +1150 -0
  179. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/codify-style.md +652 -0
  180. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/design-sync.md +454 -0
  181. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/explore-auto.md +678 -0
  182. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +504 -0
  183. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/imitate-auto.md +745 -0
  184. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +537 -0
  185. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/layout-extract.md +788 -0
  186. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/reference-page-generator.md +356 -0
  187. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/style-extract.md +773 -0
  188. package/.claude/skills/command-guide/scripts/analyze_commands.py +502 -0
  189. package/.claude/skills/command-guide/scripts/update-index.sh +130 -0
  190. package/.claude/skills/command-guide/templates/issue-bug.md +104 -0
  191. package/.claude/skills/command-guide/templates/issue-diagnosis.md +275 -0
  192. package/.claude/skills/command-guide/templates/issue-feature.md +97 -0
  193. package/.claude/skills/command-guide/templates/issue-question.md +141 -0
  194. package/.claude/skills/prompt-enhancer/SKILL.md +124 -0
  195. package/.claude/workflows/_template-compare-matrix.html +692 -0
  196. package/.claude/workflows/chinese-response.md +38 -0
  197. package/.claude/workflows/cli-templates/fix-plan-template.json +75 -0
  198. package/.claude/workflows/cli-templates/fix-progress-template.json +48 -0
  199. package/.claude/workflows/cli-templates/memory/style-skill-memory/skill-md-template.md +299 -0
  200. package/.claude/workflows/cli-templates/planning-roles/data-architect.md +120 -0
  201. package/.claude/workflows/cli-templates/planning-roles/product-manager.md +119 -0
  202. package/.claude/workflows/cli-templates/planning-roles/product-owner.md +261 -0
  203. package/.claude/workflows/cli-templates/planning-roles/scrum-master.md +186 -0
  204. package/.claude/workflows/cli-templates/planning-roles/subject-matter-expert.md +281 -0
  205. package/.claude/workflows/cli-templates/planning-roles/synthesis-role.md +414 -0
  206. package/.claude/workflows/cli-templates/planning-roles/system-architect.md +106 -0
  207. package/.claude/workflows/cli-templates/planning-roles/test-strategist.md +124 -0
  208. package/.claude/workflows/cli-templates/planning-roles/ui-designer.md +379 -0
  209. package/.claude/workflows/cli-templates/planning-roles/ux-expert.md +240 -0
  210. package/.claude/workflows/cli-templates/prompts/analysis/01-diagnose-bug-root-cause.txt +127 -0
  211. package/.claude/workflows/cli-templates/prompts/analysis/01-trace-code-execution.txt +115 -0
  212. package/.claude/workflows/cli-templates/prompts/analysis/02-analyze-code-patterns.txt +37 -0
  213. package/.claude/workflows/cli-templates/prompts/analysis/02-analyze-technical-document.txt +33 -0
  214. package/.claude/workflows/cli-templates/prompts/analysis/02-review-architecture.txt +29 -0
  215. package/.claude/workflows/cli-templates/prompts/analysis/02-review-code-quality.txt +28 -0
  216. package/.claude/workflows/cli-templates/prompts/analysis/03-analyze-performance.txt +29 -0
  217. package/.claude/workflows/cli-templates/prompts/analysis/03-assess-security-risks.txt +29 -0
  218. package/.claude/workflows/cli-templates/prompts/analysis/03-review-quality-standards.txt +29 -0
  219. package/.claude/workflows/cli-templates/prompts/development/02-generate-tests.txt +70 -0
  220. package/.claude/workflows/cli-templates/prompts/development/02-implement-component-ui.txt +55 -0
  221. package/.claude/workflows/cli-templates/prompts/development/02-implement-feature.txt +58 -0
  222. package/.claude/workflows/cli-templates/prompts/development/02-refactor-codebase.txt +55 -0
  223. package/.claude/workflows/cli-templates/prompts/development/03-debug-runtime-issues.txt +55 -0
  224. package/.claude/workflows/cli-templates/prompts/documentation/api.txt +15 -0
  225. package/.claude/workflows/cli-templates/prompts/documentation/folder-navigation.txt +27 -0
  226. package/.claude/workflows/cli-templates/prompts/documentation/module-readme.txt +49 -0
  227. package/.claude/workflows/cli-templates/prompts/documentation/project-architecture.txt +41 -0
  228. package/.claude/workflows/cli-templates/prompts/documentation/project-examples.txt +35 -0
  229. package/.claude/workflows/cli-templates/prompts/documentation/project-readme.txt +35 -0
  230. package/.claude/workflows/cli-templates/prompts/memory/02-document-module-structure.txt +165 -0
  231. package/.claude/workflows/cli-templates/prompts/planning/01-plan-architecture-design.txt +109 -0
  232. package/.claude/workflows/cli-templates/prompts/planning/02-breakdown-task-steps.txt +30 -0
  233. package/.claude/workflows/cli-templates/prompts/planning/02-design-component-spec.txt +28 -0
  234. package/.claude/workflows/cli-templates/prompts/planning/03-evaluate-concept-feasibility.txt +127 -0
  235. package/.claude/workflows/cli-templates/prompts/planning/03-plan-migration-strategy.txt +30 -0
  236. package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
  237. package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
  238. package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
  239. package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
  240. package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
  241. package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
  242. package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
  243. package/.claude/workflows/cli-templates/prompts/tech/tech-module-format.txt +359 -0
  244. package/.claude/workflows/cli-templates/prompts/tech/tech-skill-index.txt +185 -0
  245. package/.claude/workflows/cli-templates/prompts/test/test-concept-analysis.txt +179 -0
  246. package/.claude/workflows/cli-templates/prompts/universal/00-universal-creative-style.txt +95 -0
  247. package/.claude/workflows/cli-templates/prompts/universal/00-universal-rigorous-style.txt +92 -0
  248. package/.claude/workflows/cli-templates/prompts/verification/codex-technical.txt +28 -0
  249. package/.claude/workflows/cli-templates/prompts/verification/cross-validation.txt +28 -0
  250. package/.claude/workflows/cli-templates/prompts/verification/gemini-strategic.txt +27 -0
  251. package/.claude/workflows/cli-templates/prompts/workflow/analysis-results-structure.txt +224 -0
  252. package/.claude/workflows/cli-templates/prompts/workflow/codex-feasibility-validation.txt +176 -0
  253. package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -0
  254. package/.claude/workflows/cli-templates/prompts/workflow/impl-plan-template.txt +286 -0
  255. package/.claude/workflows/cli-templates/prompts/workflow/skill-aggregation.txt +172 -0
  256. package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +94 -0
  257. package/.claude/workflows/cli-templates/prompts/workflow/skill-index.txt +224 -0
  258. package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +94 -0
  259. package/.claude/workflows/cli-templates/prompts/workflow/skill-sessions-timeline.txt +53 -0
  260. package/.claude/workflows/cli-templates/prompts/workflow/task-json-agent-mode.txt +123 -0
  261. package/.claude/workflows/cli-templates/prompts/workflow/task-json-cli-mode.txt +182 -0
  262. package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
  263. package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
  264. package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
  265. package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
  266. package/.claude/workflows/cli-templates/schemas/diagnosis-json-schema.json +234 -0
  267. package/.claude/workflows/cli-templates/schemas/explore-json-schema.json +124 -0
  268. package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +298 -0
  269. package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +244 -0
  270. package/.claude/workflows/cli-templates/schemas/project-json-schema.json +221 -0
  271. package/.claude/workflows/cli-templates/schemas/review-deep-dive-results-schema.json +82 -0
  272. package/.claude/workflows/cli-templates/schemas/review-dimension-results-schema.json +51 -0
  273. package/.claude/workflows/cli-templates/tech-stacks/go-dev.md +91 -0
  274. package/.claude/workflows/cli-templates/tech-stacks/java-dev.md +107 -0
  275. package/.claude/workflows/cli-templates/tech-stacks/javascript-dev.md +58 -0
  276. package/.claude/workflows/cli-templates/tech-stacks/python-dev.md +79 -0
  277. package/.claude/workflows/cli-templates/tech-stacks/react-dev.md +103 -0
  278. package/.claude/workflows/cli-templates/tech-stacks/typescript-dev.md +83 -0
  279. package/.claude/workflows/cli-templates/ui-design/systems/animation-tokens.json +247 -0
  280. package/.claude/workflows/cli-templates/ui-design/systems/design-tokens.json +342 -0
  281. package/.claude/workflows/cli-templates/ui-design/systems/layout-templates.json +145 -0
  282. package/.claude/workflows/cli-tools-usage.md +526 -0
  283. package/.claude/workflows/coding-philosophy.md +70 -0
  284. package/.claude/workflows/context-tools.md +84 -0
  285. package/.claude/workflows/file-modification.md +64 -0
  286. package/.claude/workflows/review-directory-specification.md +336 -0
  287. package/.claude/workflows/task-core.md +214 -0
  288. package/.claude/workflows/tool-strategy.md +216 -0
  289. package/.claude/workflows/windows-platform.md +16 -0
  290. package/.claude/workflows/workflow-architecture.md +942 -0
  291. package/.codex/AGENTS.md +63 -0
  292. package/.codex/prompts/debug.md +318 -0
  293. package/.codex/prompts/execute.md +273 -0
  294. package/.codex/prompts/lite-execute.md +164 -0
  295. package/.codex/prompts/lite-plan.md +469 -0
  296. package/.codex/prompts.zip +0 -0
  297. package/.gemini/GEMINI.md +25 -0
  298. package/.qwen/QWEN.md +25 -0
  299. package/LICENSE +21 -0
  300. package/README.md +294 -145
  301. package/ccw/README.md +145 -0
  302. package/ccw/dist/core/lite-scanner-complete.d.ts.map +1 -0
  303. package/ccw/dist/core/lite-scanner-complete.js +371 -0
  304. package/ccw/dist/core/lite-scanner-complete.js.map +1 -0
  305. package/ccw/dist/core/lite-scanner.d.ts.map +1 -0
  306. package/ccw/dist/core/lite-scanner.js +371 -0
  307. package/ccw/dist/core/lite-scanner.js.map +1 -0
  308. package/ccw/dist/core/routes/claude-routes.d.ts.map +1 -0
  309. package/ccw/dist/core/routes/claude-routes.js +1015 -0
  310. package/ccw/dist/core/routes/claude-routes.js.map +1 -0
  311. package/ccw/dist/core/routes/cli-routes.d.ts.map +1 -0
  312. package/ccw/dist/core/routes/cli-routes.js +469 -0
  313. package/ccw/dist/core/routes/cli-routes.js.map +1 -0
  314. package/ccw/dist/core/routes/rules-routes.d.ts.map +1 -0
  315. package/ccw/dist/core/routes/rules-routes.js +443 -0
  316. package/ccw/dist/core/routes/rules-routes.js.map +1 -0
  317. package/ccw/dist/core/routes/skills-routes.d.ts.map +1 -0
  318. package/ccw/dist/core/routes/skills-routes.js +651 -0
  319. package/ccw/dist/core/routes/skills-routes.js.map +1 -0
  320. package/ccw/dist/tools/cli-executor.d.ts +376 -0
  321. package/ccw/dist/tools/cli-executor.d.ts.map +1 -0
  322. package/ccw/dist/tools/cli-executor.js +1677 -0
  323. package/ccw/dist/tools/cli-executor.js.map +1 -0
  324. package/ccw/package.json +65 -0
  325. package/ccw/src/core/lite-scanner-complete.ts +473 -0
  326. package/ccw/src/core/lite-scanner.ts +473 -0
  327. package/ccw/src/core/routes/claude-routes.ts +1181 -0
  328. package/ccw/src/core/routes/cli-routes.ts +562 -0
  329. package/ccw/src/core/routes/rules-routes.ts +527 -0
  330. package/ccw/src/core/routes/skills-routes.ts +737 -0
  331. package/ccw/src/templates/dashboard-js/components/cli-status.js +1011 -0
  332. package/ccw/src/templates/dashboard-js/i18n.js +2969 -0
  333. package/ccw/src/templates/dashboard-js/views/claude-manager.js +926 -0
  334. package/ccw/src/templates/dashboard-js/views/cli-manager.js +2313 -0
  335. package/ccw/src/templates/dashboard-js/views/rules-manager.js +857 -0
  336. package/ccw/src/templates/dashboard-js/views/skills-manager.js +1183 -0
  337. package/ccw/src/tools/cli-executor.ts +2082 -0
  338. package/codex-lens/pyproject.toml +66 -0
  339. package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
  340. package/codex-lens/src/codexlens/__init__.py +28 -0
  341. package/codex-lens/src/codexlens/__main__.py +14 -0
  342. package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
  343. package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
  344. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  345. package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
  346. package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
  347. package/codex-lens/src/codexlens/cli/__init__.py +27 -0
  348. package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
  349. package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
  350. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  351. package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
  352. package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
  353. package/codex-lens/src/codexlens/cli/commands.py +1940 -0
  354. package/codex-lens/src/codexlens/cli/embedding_manager.py +635 -0
  355. package/codex-lens/src/codexlens/cli/model_manager.py +337 -0
  356. package/codex-lens/src/codexlens/cli/output.py +124 -0
  357. package/codex-lens/src/codexlens/config.py +201 -0
  358. package/codex-lens/src/codexlens/entities.py +121 -0
  359. package/codex-lens/src/codexlens/errors.py +55 -0
  360. package/codex-lens/src/codexlens/indexing/README.md +77 -0
  361. package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
  362. package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
  363. package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
  364. package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
  365. package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
  366. package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
  367. package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
  368. package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
  369. package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
  370. package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
  371. package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
  372. package/codex-lens/src/codexlens/parsers/factory.py +256 -0
  373. package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
  374. package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
  375. package/codex-lens/src/codexlens/search/__init__.py +15 -0
  376. package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
  377. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  378. package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
  379. package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
  380. package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
  381. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  382. package/codex-lens/src/codexlens/search/chain_search.py +660 -0
  383. package/codex-lens/src/codexlens/search/enrichment.py +150 -0
  384. package/codex-lens/src/codexlens/search/hybrid_search.py +326 -0
  385. package/codex-lens/src/codexlens/search/query_parser.py +242 -0
  386. package/codex-lens/src/codexlens/search/ranking.py +274 -0
  387. package/codex-lens/src/codexlens/semantic/__init__.py +76 -0
  388. package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
  389. package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
  390. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  391. package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
  392. package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
  393. package/codex-lens/src/codexlens/semantic/__pycache__/gpu_support.cpython-313.pyc +0 -0
  394. package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
  395. package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
  396. package/codex-lens/src/codexlens/semantic/__pycache__/ollama_backend.cpython-313.pyc +0 -0
  397. package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
  398. package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
  399. package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
  400. package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
  401. package/codex-lens/src/codexlens/semantic/embedder.py +244 -0
  402. package/codex-lens/src/codexlens/semantic/gpu_support.py +192 -0
  403. package/codex-lens/src/codexlens/semantic/vector_store.py +1052 -0
  404. package/codex-lens/src/codexlens/storage/__init__.py +29 -0
  405. package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
  406. package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
  407. package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
  408. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  409. package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
  410. package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
  411. package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
  412. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
  413. package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
  414. package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
  415. package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
  416. package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
  417. package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
  418. package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
  419. package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  420. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
  421. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
  422. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
  423. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
  424. package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
  425. package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
  426. package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
  427. package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
  428. package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
  429. package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
  430. package/codex-lens/src/codexlens/storage/registry.py +670 -0
  431. package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
  432. package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
  433. package/package.json +36 -28
  434. package/dist/core/lite-scanner-complete.d.ts.map +0 -1
  435. package/dist/core/lite-scanner-complete.js +0 -368
  436. package/dist/core/lite-scanner-complete.js.map +0 -1
  437. package/dist/core/lite-scanner.d.ts.map +0 -1
  438. package/dist/core/lite-scanner.js +0 -368
  439. package/dist/core/lite-scanner.js.map +0 -1
  440. package/dist/core/routes/claude-routes.d.ts.map +0 -1
  441. package/dist/core/routes/claude-routes.js +0 -1017
  442. package/dist/core/routes/claude-routes.js.map +0 -1
  443. package/dist/core/routes/cli-routes.d.ts.map +0 -1
  444. package/dist/core/routes/cli-routes.js +0 -468
  445. package/dist/core/routes/cli-routes.js.map +0 -1
  446. package/dist/core/routes/rules-routes.d.ts.map +0 -1
  447. package/dist/core/routes/rules-routes.js +0 -442
  448. package/dist/core/routes/rules-routes.js.map +0 -1
  449. package/dist/core/routes/skills-routes.d.ts.map +0 -1
  450. package/dist/core/routes/skills-routes.js +0 -533
  451. package/dist/core/routes/skills-routes.js.map +0 -1
  452. package/dist/tools/cli-executor.d.ts +0 -373
  453. package/dist/tools/cli-executor.d.ts.map +0 -1
  454. package/dist/tools/cli-executor.js +0 -1625
  455. package/dist/tools/cli-executor.js.map +0 -1
  456. package/src/core/lite-scanner-complete.ts +0 -469
  457. package/src/core/lite-scanner.ts +0 -469
  458. package/src/core/routes/claude-routes.ts +0 -1183
  459. package/src/core/routes/cli-routes.ts +0 -561
  460. package/src/core/routes/rules-routes.ts +0 -526
  461. package/src/core/routes/skills-routes.ts +0 -599
  462. package/src/templates/dashboard-js/components/cli-status.js +0 -978
  463. package/src/templates/dashboard-js/i18n.js +0 -2963
  464. package/src/templates/dashboard-js/views/claude-manager.js +0 -912
  465. package/src/templates/dashboard-js/views/cli-manager.js +0 -2272
  466. package/src/templates/dashboard-js/views/rules-manager.js +0 -828
  467. package/src/templates/dashboard-js/views/skills-manager.js +0 -819
  468. package/src/tools/cli-executor.ts +0 -2014
  469. /package/{bin → ccw/bin}/ccw-mcp.js +0 -0
  470. /package/{bin → ccw/bin}/ccw.js +0 -0
  471. /package/{dist → ccw/dist}/cli.d.ts +0 -0
  472. /package/{dist → ccw/dist}/cli.d.ts.map +0 -0
  473. /package/{dist → ccw/dist}/cli.js +0 -0
  474. /package/{dist → ccw/dist}/cli.js.map +0 -0
  475. /package/{dist → ccw/dist}/commands/cli.d.ts +0 -0
  476. /package/{dist → ccw/dist}/commands/cli.d.ts.map +0 -0
  477. /package/{dist → ccw/dist}/commands/cli.js +0 -0
  478. /package/{dist → ccw/dist}/commands/cli.js.map +0 -0
  479. /package/{dist → ccw/dist}/commands/core-memory.d.ts +0 -0
  480. /package/{dist → ccw/dist}/commands/core-memory.d.ts.map +0 -0
  481. /package/{dist → ccw/dist}/commands/core-memory.js +0 -0
  482. /package/{dist → ccw/dist}/commands/core-memory.js.map +0 -0
  483. /package/{dist → ccw/dist}/commands/hook.d.ts +0 -0
  484. /package/{dist → ccw/dist}/commands/hook.d.ts.map +0 -0
  485. /package/{dist → ccw/dist}/commands/hook.js +0 -0
  486. /package/{dist → ccw/dist}/commands/hook.js.map +0 -0
  487. /package/{dist → ccw/dist}/commands/install.d.ts +0 -0
  488. /package/{dist → ccw/dist}/commands/install.d.ts.map +0 -0
  489. /package/{dist → ccw/dist}/commands/install.js +0 -0
  490. /package/{dist → ccw/dist}/commands/install.js.map +0 -0
  491. /package/{dist → ccw/dist}/commands/list.d.ts +0 -0
  492. /package/{dist → ccw/dist}/commands/list.d.ts.map +0 -0
  493. /package/{dist → ccw/dist}/commands/list.js +0 -0
  494. /package/{dist → ccw/dist}/commands/list.js.map +0 -0
  495. /package/{dist → ccw/dist}/commands/memory.d.ts +0 -0
  496. /package/{dist → ccw/dist}/commands/memory.d.ts.map +0 -0
  497. /package/{dist → ccw/dist}/commands/memory.js +0 -0
  498. /package/{dist → ccw/dist}/commands/memory.js.map +0 -0
  499. /package/{dist → ccw/dist}/commands/serve.d.ts +0 -0
  500. /package/{dist → ccw/dist}/commands/serve.d.ts.map +0 -0
  501. /package/{dist → ccw/dist}/commands/serve.js +0 -0
  502. /package/{dist → ccw/dist}/commands/serve.js.map +0 -0
  503. /package/{dist → ccw/dist}/commands/session-path-resolver.d.ts +0 -0
  504. /package/{dist → ccw/dist}/commands/session-path-resolver.d.ts.map +0 -0
  505. /package/{dist → ccw/dist}/commands/session-path-resolver.js +0 -0
  506. /package/{dist → ccw/dist}/commands/session-path-resolver.js.map +0 -0
  507. /package/{dist → ccw/dist}/commands/session.d.ts +0 -0
  508. /package/{dist → ccw/dist}/commands/session.d.ts.map +0 -0
  509. /package/{dist → ccw/dist}/commands/session.js +0 -0
  510. /package/{dist → ccw/dist}/commands/session.js.map +0 -0
  511. /package/{dist → ccw/dist}/commands/stop.d.ts +0 -0
  512. /package/{dist → ccw/dist}/commands/stop.d.ts.map +0 -0
  513. /package/{dist → ccw/dist}/commands/stop.js +0 -0
  514. /package/{dist → ccw/dist}/commands/stop.js.map +0 -0
  515. /package/{dist → ccw/dist}/commands/tool.d.ts +0 -0
  516. /package/{dist → ccw/dist}/commands/tool.d.ts.map +0 -0
  517. /package/{dist → ccw/dist}/commands/tool.js +0 -0
  518. /package/{dist → ccw/dist}/commands/tool.js.map +0 -0
  519. /package/{dist → ccw/dist}/commands/uninstall.d.ts +0 -0
  520. /package/{dist → ccw/dist}/commands/uninstall.d.ts.map +0 -0
  521. /package/{dist → ccw/dist}/commands/uninstall.js +0 -0
  522. /package/{dist → ccw/dist}/commands/uninstall.js.map +0 -0
  523. /package/{dist → ccw/dist}/commands/upgrade.d.ts +0 -0
  524. /package/{dist → ccw/dist}/commands/upgrade.d.ts.map +0 -0
  525. /package/{dist → ccw/dist}/commands/upgrade.js +0 -0
  526. /package/{dist → ccw/dist}/commands/upgrade.js.map +0 -0
  527. /package/{dist → ccw/dist}/commands/view.d.ts +0 -0
  528. /package/{dist → ccw/dist}/commands/view.d.ts.map +0 -0
  529. /package/{dist → ccw/dist}/commands/view.js +0 -0
  530. /package/{dist → ccw/dist}/commands/view.js.map +0 -0
  531. /package/{dist → ccw/dist}/config/storage-paths.d.ts +0 -0
  532. /package/{dist → ccw/dist}/config/storage-paths.d.ts.map +0 -0
  533. /package/{dist → ccw/dist}/config/storage-paths.js +0 -0
  534. /package/{dist → ccw/dist}/config/storage-paths.js.map +0 -0
  535. /package/{dist → ccw/dist}/core/cache-manager.d.ts +0 -0
  536. /package/{dist → ccw/dist}/core/cache-manager.d.ts.map +0 -0
  537. /package/{dist → ccw/dist}/core/cache-manager.js +0 -0
  538. /package/{dist → ccw/dist}/core/cache-manager.js.map +0 -0
  539. /package/{dist → ccw/dist}/core/claude-freshness.d.ts +0 -0
  540. /package/{dist → ccw/dist}/core/claude-freshness.d.ts.map +0 -0
  541. /package/{dist → ccw/dist}/core/claude-freshness.js +0 -0
  542. /package/{dist → ccw/dist}/core/claude-freshness.js.map +0 -0
  543. /package/{dist → ccw/dist}/core/core-memory-store.d.ts +0 -0
  544. /package/{dist → ccw/dist}/core/core-memory-store.d.ts.map +0 -0
  545. /package/{dist → ccw/dist}/core/core-memory-store.js +0 -0
  546. /package/{dist → ccw/dist}/core/core-memory-store.js.map +0 -0
  547. /package/{dist → ccw/dist}/core/dashboard-generator-patch.d.ts +0 -0
  548. /package/{dist → ccw/dist}/core/dashboard-generator-patch.d.ts.map +0 -0
  549. /package/{dist → ccw/dist}/core/dashboard-generator-patch.js +0 -0
  550. /package/{dist → ccw/dist}/core/dashboard-generator-patch.js.map +0 -0
  551. /package/{dist → ccw/dist}/core/dashboard-generator.d.ts +0 -0
  552. /package/{dist → ccw/dist}/core/dashboard-generator.d.ts.map +0 -0
  553. /package/{dist → ccw/dist}/core/dashboard-generator.js +0 -0
  554. /package/{dist → ccw/dist}/core/dashboard-generator.js.map +0 -0
  555. /package/{dist → ccw/dist}/core/data-aggregator.d.ts +0 -0
  556. /package/{dist → ccw/dist}/core/data-aggregator.d.ts.map +0 -0
  557. /package/{dist → ccw/dist}/core/data-aggregator.js +0 -0
  558. /package/{dist → ccw/dist}/core/data-aggregator.js.map +0 -0
  559. /package/{dist → ccw/dist}/core/history-importer.d.ts +0 -0
  560. /package/{dist → ccw/dist}/core/history-importer.d.ts.map +0 -0
  561. /package/{dist → ccw/dist}/core/history-importer.js +0 -0
  562. /package/{dist → ccw/dist}/core/history-importer.js.map +0 -0
  563. /package/{dist → ccw/dist}/core/lite-scanner-complete.d.ts +0 -0
  564. /package/{dist → ccw/dist}/core/lite-scanner.d.ts +0 -0
  565. /package/{dist → ccw/dist}/core/manifest.d.ts +0 -0
  566. /package/{dist → ccw/dist}/core/manifest.d.ts.map +0 -0
  567. /package/{dist → ccw/dist}/core/manifest.js +0 -0
  568. /package/{dist → ccw/dist}/core/manifest.js.map +0 -0
  569. /package/{dist → ccw/dist}/core/memory-embedder-bridge.d.ts +0 -0
  570. /package/{dist → ccw/dist}/core/memory-embedder-bridge.d.ts.map +0 -0
  571. /package/{dist → ccw/dist}/core/memory-embedder-bridge.js +0 -0
  572. /package/{dist → ccw/dist}/core/memory-embedder-bridge.js.map +0 -0
  573. /package/{dist → ccw/dist}/core/memory-store.d.ts +0 -0
  574. /package/{dist → ccw/dist}/core/memory-store.d.ts.map +0 -0
  575. /package/{dist → ccw/dist}/core/memory-store.js +0 -0
  576. /package/{dist → ccw/dist}/core/memory-store.js.map +0 -0
  577. /package/{dist → ccw/dist}/core/routes/ccw-routes.d.ts +0 -0
  578. /package/{dist → ccw/dist}/core/routes/ccw-routes.d.ts.map +0 -0
  579. /package/{dist → ccw/dist}/core/routes/ccw-routes.js +0 -0
  580. /package/{dist → ccw/dist}/core/routes/ccw-routes.js.map +0 -0
  581. /package/{dist → ccw/dist}/core/routes/claude-routes.d.ts +0 -0
  582. /package/{dist → ccw/dist}/core/routes/cli-routes.d.ts +0 -0
  583. /package/{dist → ccw/dist}/core/routes/codexlens-routes.d.ts +0 -0
  584. /package/{dist → ccw/dist}/core/routes/codexlens-routes.d.ts.map +0 -0
  585. /package/{dist → ccw/dist}/core/routes/codexlens-routes.js +0 -0
  586. /package/{dist → ccw/dist}/core/routes/codexlens-routes.js.map +0 -0
  587. /package/{dist → ccw/dist}/core/routes/core-memory-routes.d.ts +0 -0
  588. /package/{dist → ccw/dist}/core/routes/core-memory-routes.d.ts.map +0 -0
  589. /package/{dist → ccw/dist}/core/routes/core-memory-routes.js +0 -0
  590. /package/{dist → ccw/dist}/core/routes/core-memory-routes.js.map +0 -0
  591. /package/{dist → ccw/dist}/core/routes/files-routes.d.ts +0 -0
  592. /package/{dist → ccw/dist}/core/routes/files-routes.d.ts.map +0 -0
  593. /package/{dist → ccw/dist}/core/routes/files-routes.js +0 -0
  594. /package/{dist → ccw/dist}/core/routes/files-routes.js.map +0 -0
  595. /package/{dist → ccw/dist}/core/routes/graph-routes.d.ts +0 -0
  596. /package/{dist → ccw/dist}/core/routes/graph-routes.d.ts.map +0 -0
  597. /package/{dist → ccw/dist}/core/routes/graph-routes.js +0 -0
  598. /package/{dist → ccw/dist}/core/routes/graph-routes.js.map +0 -0
  599. /package/{dist → ccw/dist}/core/routes/help-routes.d.ts +0 -0
  600. /package/{dist → ccw/dist}/core/routes/help-routes.d.ts.map +0 -0
  601. /package/{dist → ccw/dist}/core/routes/help-routes.js +0 -0
  602. /package/{dist → ccw/dist}/core/routes/help-routes.js.map +0 -0
  603. /package/{dist → ccw/dist}/core/routes/hooks-routes.d.ts +0 -0
  604. /package/{dist → ccw/dist}/core/routes/hooks-routes.d.ts.map +0 -0
  605. /package/{dist → ccw/dist}/core/routes/hooks-routes.js +0 -0
  606. /package/{dist → ccw/dist}/core/routes/hooks-routes.js.map +0 -0
  607. /package/{dist → ccw/dist}/core/routes/mcp-routes.d.ts +0 -0
  608. /package/{dist → ccw/dist}/core/routes/mcp-routes.d.ts.map +0 -0
  609. /package/{dist → ccw/dist}/core/routes/mcp-routes.js +0 -0
  610. /package/{dist → ccw/dist}/core/routes/mcp-routes.js.map +0 -0
  611. /package/{dist → ccw/dist}/core/routes/mcp-templates-db.d.ts +0 -0
  612. /package/{dist → ccw/dist}/core/routes/mcp-templates-db.d.ts.map +0 -0
  613. /package/{dist → ccw/dist}/core/routes/mcp-templates-db.js +0 -0
  614. /package/{dist → ccw/dist}/core/routes/mcp-templates-db.js.map +0 -0
  615. /package/{dist → ccw/dist}/core/routes/memory-routes.d.ts +0 -0
  616. /package/{dist → ccw/dist}/core/routes/memory-routes.d.ts.map +0 -0
  617. /package/{dist → ccw/dist}/core/routes/memory-routes.js +0 -0
  618. /package/{dist → ccw/dist}/core/routes/memory-routes.js.map +0 -0
  619. /package/{dist → ccw/dist}/core/routes/rules-routes.d.ts +0 -0
  620. /package/{dist → ccw/dist}/core/routes/session-routes.d.ts +0 -0
  621. /package/{dist → ccw/dist}/core/routes/session-routes.d.ts.map +0 -0
  622. /package/{dist → ccw/dist}/core/routes/session-routes.js +0 -0
  623. /package/{dist → ccw/dist}/core/routes/session-routes.js.map +0 -0
  624. /package/{dist → ccw/dist}/core/routes/skills-routes.d.ts +0 -0
  625. /package/{dist → ccw/dist}/core/routes/status-routes.d.ts +0 -0
  626. /package/{dist → ccw/dist}/core/routes/status-routes.d.ts.map +0 -0
  627. /package/{dist → ccw/dist}/core/routes/status-routes.js +0 -0
  628. /package/{dist → ccw/dist}/core/routes/status-routes.js.map +0 -0
  629. /package/{dist → ccw/dist}/core/routes/system-routes.d.ts +0 -0
  630. /package/{dist → ccw/dist}/core/routes/system-routes.d.ts.map +0 -0
  631. /package/{dist → ccw/dist}/core/routes/system-routes.js +0 -0
  632. /package/{dist → ccw/dist}/core/routes/system-routes.js.map +0 -0
  633. /package/{dist → ccw/dist}/core/server.d.ts +0 -0
  634. /package/{dist → ccw/dist}/core/server.d.ts.map +0 -0
  635. /package/{dist → ccw/dist}/core/server.js +0 -0
  636. /package/{dist → ccw/dist}/core/server.js.map +0 -0
  637. /package/{dist → ccw/dist}/core/session-clustering-service.d.ts +0 -0
  638. /package/{dist → ccw/dist}/core/session-clustering-service.d.ts.map +0 -0
  639. /package/{dist → ccw/dist}/core/session-clustering-service.js +0 -0
  640. /package/{dist → ccw/dist}/core/session-clustering-service.js.map +0 -0
  641. /package/{dist → ccw/dist}/core/session-scanner.d.ts +0 -0
  642. /package/{dist → ccw/dist}/core/session-scanner.d.ts.map +0 -0
  643. /package/{dist → ccw/dist}/core/session-scanner.js +0 -0
  644. /package/{dist → ccw/dist}/core/session-scanner.js.map +0 -0
  645. /package/{dist → ccw/dist}/core/websocket.d.ts +0 -0
  646. /package/{dist → ccw/dist}/core/websocket.d.ts.map +0 -0
  647. /package/{dist → ccw/dist}/core/websocket.js +0 -0
  648. /package/{dist → ccw/dist}/core/websocket.js.map +0 -0
  649. /package/{dist → ccw/dist}/index.d.ts +0 -0
  650. /package/{dist → ccw/dist}/index.d.ts.map +0 -0
  651. /package/{dist → ccw/dist}/index.js +0 -0
  652. /package/{dist → ccw/dist}/index.js.map +0 -0
  653. /package/{dist → ccw/dist}/mcp-server/index.d.ts +0 -0
  654. /package/{dist → ccw/dist}/mcp-server/index.d.ts.map +0 -0
  655. /package/{dist → ccw/dist}/mcp-server/index.js +0 -0
  656. /package/{dist → ccw/dist}/mcp-server/index.js.map +0 -0
  657. /package/{dist → ccw/dist}/tools/classify-folders.d.ts +0 -0
  658. /package/{dist → ccw/dist}/tools/classify-folders.d.ts.map +0 -0
  659. /package/{dist → ccw/dist}/tools/classify-folders.js +0 -0
  660. /package/{dist → ccw/dist}/tools/classify-folders.js.map +0 -0
  661. /package/{dist → ccw/dist}/tools/cli-config-manager.d.ts +0 -0
  662. /package/{dist → ccw/dist}/tools/cli-config-manager.d.ts.map +0 -0
  663. /package/{dist → ccw/dist}/tools/cli-config-manager.js +0 -0
  664. /package/{dist → ccw/dist}/tools/cli-config-manager.js.map +0 -0
  665. /package/{dist → ccw/dist}/tools/cli-history-store.d.ts +0 -0
  666. /package/{dist → ccw/dist}/tools/cli-history-store.d.ts.map +0 -0
  667. /package/{dist → ccw/dist}/tools/cli-history-store.js +0 -0
  668. /package/{dist → ccw/dist}/tools/cli-history-store.js.map +0 -0
  669. /package/{dist → ccw/dist}/tools/codex-lens.d.ts +0 -0
  670. /package/{dist → ccw/dist}/tools/codex-lens.d.ts.map +0 -0
  671. /package/{dist → ccw/dist}/tools/codex-lens.js +0 -0
  672. /package/{dist → ccw/dist}/tools/codex-lens.js.map +0 -0
  673. /package/{dist → ccw/dist}/tools/convert-tokens-to-css.d.ts +0 -0
  674. /package/{dist → ccw/dist}/tools/convert-tokens-to-css.d.ts.map +0 -0
  675. /package/{dist → ccw/dist}/tools/convert-tokens-to-css.js +0 -0
  676. /package/{dist → ccw/dist}/tools/convert-tokens-to-css.js.map +0 -0
  677. /package/{dist → ccw/dist}/tools/core-memory.d.ts +0 -0
  678. /package/{dist → ccw/dist}/tools/core-memory.d.ts.map +0 -0
  679. /package/{dist → ccw/dist}/tools/core-memory.js +0 -0
  680. /package/{dist → ccw/dist}/tools/core-memory.js.map +0 -0
  681. /package/{dist → ccw/dist}/tools/detect-changed-modules.d.ts +0 -0
  682. /package/{dist → ccw/dist}/tools/detect-changed-modules.d.ts.map +0 -0
  683. /package/{dist → ccw/dist}/tools/detect-changed-modules.js +0 -0
  684. /package/{dist → ccw/dist}/tools/detect-changed-modules.js.map +0 -0
  685. /package/{dist → ccw/dist}/tools/discover-design-files.d.ts +0 -0
  686. /package/{dist → ccw/dist}/tools/discover-design-files.d.ts.map +0 -0
  687. /package/{dist → ccw/dist}/tools/discover-design-files.js +0 -0
  688. /package/{dist → ccw/dist}/tools/discover-design-files.js.map +0 -0
  689. /package/{dist → ccw/dist}/tools/edit-file.d.ts +0 -0
  690. /package/{dist → ccw/dist}/tools/edit-file.d.ts.map +0 -0
  691. /package/{dist → ccw/dist}/tools/edit-file.js +0 -0
  692. /package/{dist → ccw/dist}/tools/edit-file.js.map +0 -0
  693. /package/{dist → ccw/dist}/tools/generate-module-docs.d.ts +0 -0
  694. /package/{dist → ccw/dist}/tools/generate-module-docs.d.ts.map +0 -0
  695. /package/{dist → ccw/dist}/tools/generate-module-docs.js +0 -0
  696. /package/{dist → ccw/dist}/tools/generate-module-docs.js.map +0 -0
  697. /package/{dist → ccw/dist}/tools/get-modules-by-depth.d.ts +0 -0
  698. /package/{dist → ccw/dist}/tools/get-modules-by-depth.d.ts.map +0 -0
  699. /package/{dist → ccw/dist}/tools/get-modules-by-depth.js +0 -0
  700. /package/{dist → ccw/dist}/tools/get-modules-by-depth.js.map +0 -0
  701. /package/{dist → ccw/dist}/tools/index.d.ts +0 -0
  702. /package/{dist → ccw/dist}/tools/index.d.ts.map +0 -0
  703. /package/{dist → ccw/dist}/tools/index.js +0 -0
  704. /package/{dist → ccw/dist}/tools/index.js.map +0 -0
  705. /package/{dist → ccw/dist}/tools/native-session-discovery.d.ts +0 -0
  706. /package/{dist → ccw/dist}/tools/native-session-discovery.d.ts.map +0 -0
  707. /package/{dist → ccw/dist}/tools/native-session-discovery.js +0 -0
  708. /package/{dist → ccw/dist}/tools/native-session-discovery.js.map +0 -0
  709. /package/{dist → ccw/dist}/tools/notifier.d.ts +0 -0
  710. /package/{dist → ccw/dist}/tools/notifier.d.ts.map +0 -0
  711. /package/{dist → ccw/dist}/tools/notifier.js +0 -0
  712. /package/{dist → ccw/dist}/tools/notifier.js.map +0 -0
  713. /package/{dist → ccw/dist}/tools/read-file.d.ts +0 -0
  714. /package/{dist → ccw/dist}/tools/read-file.d.ts.map +0 -0
  715. /package/{dist → ccw/dist}/tools/read-file.js +0 -0
  716. /package/{dist → ccw/dist}/tools/read-file.js.map +0 -0
  717. /package/{dist → ccw/dist}/tools/resume-strategy.d.ts +0 -0
  718. /package/{dist → ccw/dist}/tools/resume-strategy.d.ts.map +0 -0
  719. /package/{dist → ccw/dist}/tools/resume-strategy.js +0 -0
  720. /package/{dist → ccw/dist}/tools/resume-strategy.js.map +0 -0
  721. /package/{dist → ccw/dist}/tools/session-content-parser.d.ts +0 -0
  722. /package/{dist → ccw/dist}/tools/session-content-parser.d.ts.map +0 -0
  723. /package/{dist → ccw/dist}/tools/session-content-parser.js +0 -0
  724. /package/{dist → ccw/dist}/tools/session-content-parser.js.map +0 -0
  725. /package/{dist → ccw/dist}/tools/session-manager.d.ts +0 -0
  726. /package/{dist → ccw/dist}/tools/session-manager.d.ts.map +0 -0
  727. /package/{dist → ccw/dist}/tools/session-manager.js +0 -0
  728. /package/{dist → ccw/dist}/tools/session-manager.js.map +0 -0
  729. /package/{dist → ccw/dist}/tools/smart-context.d.ts +0 -0
  730. /package/{dist → ccw/dist}/tools/smart-context.d.ts.map +0 -0
  731. /package/{dist → ccw/dist}/tools/smart-context.js +0 -0
  732. /package/{dist → ccw/dist}/tools/smart-context.js.map +0 -0
  733. /package/{dist → ccw/dist}/tools/smart-search.d.ts +0 -0
  734. /package/{dist → ccw/dist}/tools/smart-search.d.ts.map +0 -0
  735. /package/{dist → ccw/dist}/tools/smart-search.js +0 -0
  736. /package/{dist → ccw/dist}/tools/smart-search.js.map +0 -0
  737. /package/{dist → ccw/dist}/tools/storage-manager.d.ts +0 -0
  738. /package/{dist → ccw/dist}/tools/storage-manager.d.ts.map +0 -0
  739. /package/{dist → ccw/dist}/tools/storage-manager.js +0 -0
  740. /package/{dist → ccw/dist}/tools/storage-manager.js.map +0 -0
  741. /package/{dist → ccw/dist}/tools/ui-generate-preview.d.ts +0 -0
  742. /package/{dist → ccw/dist}/tools/ui-generate-preview.d.ts.map +0 -0
  743. /package/{dist → ccw/dist}/tools/ui-generate-preview.js +0 -0
  744. /package/{dist → ccw/dist}/tools/ui-generate-preview.js.map +0 -0
  745. /package/{dist → ccw/dist}/tools/ui-instantiate-prototypes.d.ts +0 -0
  746. /package/{dist → ccw/dist}/tools/ui-instantiate-prototypes.d.ts.map +0 -0
  747. /package/{dist → ccw/dist}/tools/ui-instantiate-prototypes.js +0 -0
  748. /package/{dist → ccw/dist}/tools/ui-instantiate-prototypes.js.map +0 -0
  749. /package/{dist → ccw/dist}/tools/update-module-claude.d.ts +0 -0
  750. /package/{dist → ccw/dist}/tools/update-module-claude.d.ts.map +0 -0
  751. /package/{dist → ccw/dist}/tools/update-module-claude.js +0 -0
  752. /package/{dist → ccw/dist}/tools/update-module-claude.js.map +0 -0
  753. /package/{dist → ccw/dist}/tools/write-file.d.ts +0 -0
  754. /package/{dist → ccw/dist}/tools/write-file.d.ts.map +0 -0
  755. /package/{dist → ccw/dist}/tools/write-file.js +0 -0
  756. /package/{dist → ccw/dist}/tools/write-file.js.map +0 -0
  757. /package/{dist → ccw/dist}/types/config.d.ts +0 -0
  758. /package/{dist → ccw/dist}/types/config.d.ts.map +0 -0
  759. /package/{dist → ccw/dist}/types/config.js +0 -0
  760. /package/{dist → ccw/dist}/types/config.js.map +0 -0
  761. /package/{dist → ccw/dist}/types/index.d.ts +0 -0
  762. /package/{dist → ccw/dist}/types/index.d.ts.map +0 -0
  763. /package/{dist → ccw/dist}/types/index.js +0 -0
  764. /package/{dist → ccw/dist}/types/index.js.map +0 -0
  765. /package/{dist → ccw/dist}/types/session.d.ts +0 -0
  766. /package/{dist → ccw/dist}/types/session.d.ts.map +0 -0
  767. /package/{dist → ccw/dist}/types/session.js +0 -0
  768. /package/{dist → ccw/dist}/types/session.js.map +0 -0
  769. /package/{dist → ccw/dist}/types/tool.d.ts +0 -0
  770. /package/{dist → ccw/dist}/types/tool.d.ts.map +0 -0
  771. /package/{dist → ccw/dist}/types/tool.js +0 -0
  772. /package/{dist → ccw/dist}/types/tool.js.map +0 -0
  773. /package/{dist → ccw/dist}/utils/browser-launcher.d.ts +0 -0
  774. /package/{dist → ccw/dist}/utils/browser-launcher.d.ts.map +0 -0
  775. /package/{dist → ccw/dist}/utils/browser-launcher.js +0 -0
  776. /package/{dist → ccw/dist}/utils/browser-launcher.js.map +0 -0
  777. /package/{dist → ccw/dist}/utils/file-utils.d.ts +0 -0
  778. /package/{dist → ccw/dist}/utils/file-utils.d.ts.map +0 -0
  779. /package/{dist → ccw/dist}/utils/file-utils.js +0 -0
  780. /package/{dist → ccw/dist}/utils/file-utils.js.map +0 -0
  781. /package/{dist → ccw/dist}/utils/path-resolver.d.ts +0 -0
  782. /package/{dist → ccw/dist}/utils/path-resolver.d.ts.map +0 -0
  783. /package/{dist → ccw/dist}/utils/path-resolver.js +0 -0
  784. /package/{dist → ccw/dist}/utils/path-resolver.js.map +0 -0
  785. /package/{dist → ccw/dist}/utils/path-validator.d.ts +0 -0
  786. /package/{dist → ccw/dist}/utils/path-validator.d.ts.map +0 -0
  787. /package/{dist → ccw/dist}/utils/path-validator.js +0 -0
  788. /package/{dist → ccw/dist}/utils/path-validator.js.map +0 -0
  789. /package/{dist → ccw/dist}/utils/ui.d.ts +0 -0
  790. /package/{dist → ccw/dist}/utils/ui.d.ts.map +0 -0
  791. /package/{dist → ccw/dist}/utils/ui.js +0 -0
  792. /package/{dist → ccw/dist}/utils/ui.js.map +0 -0
  793. /package/{src → ccw/src}/.workflow/.cli-history/history.db +0 -0
  794. /package/{src → ccw/src}/.workflow/.cli-history/history.db-shm +0 -0
  795. /package/{src → ccw/src}/.workflow/.cli-history/history.db-wal +0 -0
  796. /package/{src → ccw/src}/cli.ts +0 -0
  797. /package/{src → ccw/src}/commands/cli.ts +0 -0
  798. /package/{src → ccw/src}/commands/core-memory.ts +0 -0
  799. /package/{src → ccw/src}/commands/hook.ts +0 -0
  800. /package/{src → ccw/src}/commands/install.ts +0 -0
  801. /package/{src → ccw/src}/commands/list.ts +0 -0
  802. /package/{src → ccw/src}/commands/memory.ts +0 -0
  803. /package/{src → ccw/src}/commands/serve.ts +0 -0
  804. /package/{src → ccw/src}/commands/session-path-resolver.ts +0 -0
  805. /package/{src → ccw/src}/commands/session.ts +0 -0
  806. /package/{src → ccw/src}/commands/stop.ts +0 -0
  807. /package/{src → ccw/src}/commands/tool.ts +0 -0
  808. /package/{src → ccw/src}/commands/uninstall.ts +0 -0
  809. /package/{src → ccw/src}/commands/upgrade.ts +0 -0
  810. /package/{src → ccw/src}/commands/view.ts +0 -0
  811. /package/{src → ccw/src}/config/storage-paths.ts +0 -0
  812. /package/{src → ccw/src}/core/cache-manager.ts +0 -0
  813. /package/{src → ccw/src}/core/claude-freshness.ts +0 -0
  814. /package/{src → ccw/src}/core/core-memory-store.ts +0 -0
  815. /package/{src → ccw/src}/core/dashboard-generator-patch.ts +0 -0
  816. /package/{src → ccw/src}/core/dashboard-generator.ts +0 -0
  817. /package/{src → ccw/src}/core/data-aggregator.ts +0 -0
  818. /package/{src → ccw/src}/core/history-importer.ts +0 -0
  819. /package/{src → ccw/src}/core/manifest.ts +0 -0
  820. /package/{src → ccw/src}/core/memory-embedder-bridge.ts +0 -0
  821. /package/{src → ccw/src}/core/memory-store.ts +0 -0
  822. /package/{src → ccw/src}/core/routes/ccw-routes.ts +0 -0
  823. /package/{src → ccw/src}/core/routes/codexlens-routes.ts +0 -0
  824. /package/{src → ccw/src}/core/routes/core-memory-routes.ts +0 -0
  825. /package/{src → ccw/src}/core/routes/files-routes.ts +0 -0
  826. /package/{src → ccw/src}/core/routes/graph-routes.md +0 -0
  827. /package/{src → ccw/src}/core/routes/graph-routes.ts +0 -0
  828. /package/{src → ccw/src}/core/routes/help-routes.ts +0 -0
  829. /package/{src → ccw/src}/core/routes/hooks-routes.ts +0 -0
  830. /package/{src → ccw/src}/core/routes/mcp-routes.ts +0 -0
  831. /package/{src → ccw/src}/core/routes/mcp-routes.ts.backup +0 -0
  832. /package/{src → ccw/src}/core/routes/mcp-templates-db.ts +0 -0
  833. /package/{src → ccw/src}/core/routes/memory-routes.ts +0 -0
  834. /package/{src → ccw/src}/core/routes/session-routes.ts +0 -0
  835. /package/{src → ccw/src}/core/routes/status-routes.ts +0 -0
  836. /package/{src → ccw/src}/core/routes/system-routes.ts +0 -0
  837. /package/{src → ccw/src}/core/server.ts +0 -0
  838. /package/{src → ccw/src}/core/session-clustering-service.ts +0 -0
  839. /package/{src → ccw/src}/core/session-scanner.ts +0 -0
  840. /package/{src → ccw/src}/core/websocket.ts +0 -0
  841. /package/{src → ccw/src}/index.ts +0 -0
  842. /package/{src → ccw/src}/mcp-server/index.ts +0 -0
  843. /package/{src → ccw/src}/templates/assets/css/github-dark.min.css +0 -0
  844. /package/{src → ccw/src}/templates/assets/css/github.min.css +0 -0
  845. /package/{src → ccw/src}/templates/assets/js/cytoscape.min.js +0 -0
  846. /package/{src → ccw/src}/templates/assets/js/d3.min.js +0 -0
  847. /package/{src → ccw/src}/templates/assets/js/highlight.min.js +0 -0
  848. /package/{src → ccw/src}/templates/assets/js/lucide.min.js +0 -0
  849. /package/{src → ccw/src}/templates/assets/js/marked.min.js +0 -0
  850. /package/{src → ccw/src}/templates/assets/js/tailwind.js +0 -0
  851. /package/{src → ccw/src}/templates/dashboard-css/01-base.css +0 -0
  852. /package/{src → ccw/src}/templates/dashboard-css/02-session.css +0 -0
  853. /package/{src → ccw/src}/templates/dashboard-css/03-tasks.css +0 -0
  854. /package/{src → ccw/src}/templates/dashboard-css/04-lite-tasks.css +0 -0
  855. /package/{src → ccw/src}/templates/dashboard-css/05-context.css +0 -0
  856. /package/{src → ccw/src}/templates/dashboard-css/06-cards.css +0 -0
  857. /package/{src → ccw/src}/templates/dashboard-css/07-managers.css +0 -0
  858. /package/{src → ccw/src}/templates/dashboard-css/08-review.css +0 -0
  859. /package/{src → ccw/src}/templates/dashboard-css/09-explorer.css +0 -0
  860. /package/{src → ccw/src}/templates/dashboard-css/10-cli-status.css +0 -0
  861. /package/{src → ccw/src}/templates/dashboard-css/11-cli-history.css +0 -0
  862. /package/{src → ccw/src}/templates/dashboard-css/12-cli-legacy.css +0 -0
  863. /package/{src → ccw/src}/templates/dashboard-css/13-cli-ccw.css +0 -0
  864. /package/{src → ccw/src}/templates/dashboard-css/14-cli-modals.css +0 -0
  865. /package/{src → ccw/src}/templates/dashboard-css/15-cli-endpoints.css +0 -0
  866. /package/{src → ccw/src}/templates/dashboard-css/16-cli-session.css +0 -0
  867. /package/{src → ccw/src}/templates/dashboard-css/17-cli-conversation.css +0 -0
  868. /package/{src → ccw/src}/templates/dashboard-css/18-cli-settings.css +0 -0
  869. /package/{src → ccw/src}/templates/dashboard-css/19-cli-native-session.css +0 -0
  870. /package/{src → ccw/src}/templates/dashboard-css/20-cli-taskqueue.css +0 -0
  871. /package/{src → ccw/src}/templates/dashboard-css/21-cli-toolmgmt.css +0 -0
  872. /package/{src → ccw/src}/templates/dashboard-css/22-cli-semantic.css +0 -0
  873. /package/{src → ccw/src}/templates/dashboard-css/23-memory.css +0 -0
  874. /package/{src → ccw/src}/templates/dashboard-css/24-prompt-history.css +0 -0
  875. /package/{src → ccw/src}/templates/dashboard-css/25-skills-rules.css +0 -0
  876. /package/{src → ccw/src}/templates/dashboard-css/26-claude-manager.css +0 -0
  877. /package/{src → ccw/src}/templates/dashboard-css/27-graph-explorer.css +0 -0
  878. /package/{src → ccw/src}/templates/dashboard-css/28-mcp-manager.css +0 -0
  879. /package/{src → ccw/src}/templates/dashboard-css/29-help.css +0 -0
  880. /package/{src → ccw/src}/templates/dashboard-css/30-core-memory.css +0 -0
  881. /package/{src → ccw/src}/templates/dashboard-js/api.js +0 -0
  882. /package/{src → ccw/src}/templates/dashboard-js/components/_conflict_tab.js +0 -0
  883. /package/{src → ccw/src}/templates/dashboard-js/components/_exp_helpers.js +0 -0
  884. /package/{src → ccw/src}/templates/dashboard-js/components/_review_tab.js +0 -0
  885. /package/{src → ccw/src}/templates/dashboard-js/components/carousel.js +0 -0
  886. /package/{src → ccw/src}/templates/dashboard-js/components/cli-history.js +0 -0
  887. /package/{src → ccw/src}/templates/dashboard-js/components/flowchart.js +0 -0
  888. /package/{src → ccw/src}/templates/dashboard-js/components/global-notifications.js +0 -0
  889. /package/{src → ccw/src}/templates/dashboard-js/components/hook-manager.js +0 -0
  890. /package/{src → ccw/src}/templates/dashboard-js/components/index-manager.js +0 -0
  891. /package/{src → ccw/src}/templates/dashboard-js/components/mcp-manager.js +0 -0
  892. /package/{src → ccw/src}/templates/dashboard-js/components/modals.js +0 -0
  893. /package/{src → ccw/src}/templates/dashboard-js/components/navigation.js +0 -0
  894. /package/{src → ccw/src}/templates/dashboard-js/components/notifications.js +0 -0
  895. /package/{src → ccw/src}/templates/dashboard-js/components/sidebar.js +0 -0
  896. /package/{src → ccw/src}/templates/dashboard-js/components/storage-manager.js +0 -0
  897. /package/{src → ccw/src}/templates/dashboard-js/components/tabs-context.js +0 -0
  898. /package/{src → ccw/src}/templates/dashboard-js/components/tabs-other.js +0 -0
  899. /package/{src → ccw/src}/templates/dashboard-js/components/task-drawer-core.js +0 -0
  900. /package/{src → ccw/src}/templates/dashboard-js/components/task-drawer-renderers.js +0 -0
  901. /package/{src → ccw/src}/templates/dashboard-js/components/task-queue-sidebar.js +0 -0
  902. /package/{src → ccw/src}/templates/dashboard-js/components/theme.js +0 -0
  903. /package/{src → ccw/src}/templates/dashboard-js/components/version-check.js +0 -0
  904. /package/{src → ccw/src}/templates/dashboard-js/help-i18n.js +0 -0
  905. /package/{src → ccw/src}/templates/dashboard-js/main.js +0 -0
  906. /package/{src → ccw/src}/templates/dashboard-js/state.js +0 -0
  907. /package/{src → ccw/src}/templates/dashboard-js/utils.js +0 -0
  908. /package/{src → ccw/src}/templates/dashboard-js/views/codexlens-manager.js +0 -0
  909. /package/{src → ccw/src}/templates/dashboard-js/views/core-memory-clusters.js +0 -0
  910. /package/{src → ccw/src}/templates/dashboard-js/views/core-memory.js +0 -0
  911. /package/{src → ccw/src}/templates/dashboard-js/views/explorer.js +0 -0
  912. /package/{src → ccw/src}/templates/dashboard-js/views/fix-session.js +0 -0
  913. /package/{src → ccw/src}/templates/dashboard-js/views/graph-explorer.js +0 -0
  914. /package/{src → ccw/src}/templates/dashboard-js/views/help.js +0 -0
  915. /package/{src → ccw/src}/templates/dashboard-js/views/history.js +0 -0
  916. /package/{src → ccw/src}/templates/dashboard-js/views/home.js +0 -0
  917. /package/{src → ccw/src}/templates/dashboard-js/views/hook-manager.js +0 -0
  918. /package/{src → ccw/src}/templates/dashboard-js/views/lite-tasks.js +0 -0
  919. /package/{src → ccw/src}/templates/dashboard-js/views/mcp-manager.js +0 -0
  920. /package/{src → ccw/src}/templates/dashboard-js/views/mcp-manager.js.backup +0 -0
  921. /package/{src → ccw/src}/templates/dashboard-js/views/mcp-manager.js.new +0 -0
  922. /package/{src → ccw/src}/templates/dashboard-js/views/memory.js +0 -0
  923. /package/{src → ccw/src}/templates/dashboard-js/views/project-overview.js +0 -0
  924. /package/{src → ccw/src}/templates/dashboard-js/views/prompt-history.js +0 -0
  925. /package/{src → ccw/src}/templates/dashboard-js/views/review-session.js +0 -0
  926. /package/{src → ccw/src}/templates/dashboard-js/views/session-detail.js +0 -0
  927. /package/{src → ccw/src}/templates/dashboard.html +0 -0
  928. /package/{src → ccw/src}/templates/hooks-config-example.json +0 -0
  929. /package/{src → ccw/src}/templates/review-cycle-dashboard.html +0 -0
  930. /package/{src → ccw/src}/templates/workflow-dashboard.html +0 -0
  931. /package/{src → ccw/src}/tools/classify-folders.ts +0 -0
  932. /package/{src → ccw/src}/tools/cli-config-manager.ts +0 -0
  933. /package/{src → ccw/src}/tools/cli-history-store.ts +0 -0
  934. /package/{src → ccw/src}/tools/codex-lens.ts +0 -0
  935. /package/{src → ccw/src}/tools/convert-tokens-to-css.ts +0 -0
  936. /package/{src → ccw/src}/tools/core-memory.ts +0 -0
  937. /package/{src → ccw/src}/tools/detect-changed-modules.ts +0 -0
  938. /package/{src → ccw/src}/tools/discover-design-files.ts +0 -0
  939. /package/{src → ccw/src}/tools/edit-file.ts +0 -0
  940. /package/{src → ccw/src}/tools/generate-module-docs.ts +0 -0
  941. /package/{src → ccw/src}/tools/get-modules-by-depth.ts +0 -0
  942. /package/{src → ccw/src}/tools/index.ts +0 -0
  943. /package/{src → ccw/src}/tools/native-session-discovery.ts +0 -0
  944. /package/{src → ccw/src}/tools/notifier.ts +0 -0
  945. /package/{src → ccw/src}/tools/read-file.ts +0 -0
  946. /package/{src → ccw/src}/tools/resume-strategy.ts +0 -0
  947. /package/{src → ccw/src}/tools/session-content-parser.ts +0 -0
  948. /package/{src → ccw/src}/tools/session-manager.ts +0 -0
  949. /package/{src → ccw/src}/tools/smart-context.ts +0 -0
  950. /package/{src → ccw/src}/tools/smart-search.ts +0 -0
  951. /package/{src → ccw/src}/tools/smart-search.ts.backup +0 -0
  952. /package/{src → ccw/src}/tools/storage-manager.ts +0 -0
  953. /package/{src → ccw/src}/tools/ui-generate-preview.js +0 -0
  954. /package/{src → ccw/src}/tools/ui-instantiate-prototypes.js +0 -0
  955. /package/{src → ccw/src}/tools/update-module-claude.js +0 -0
  956. /package/{src → ccw/src}/tools/write-file.ts +0 -0
  957. /package/{src → ccw/src}/types/config.ts +0 -0
  958. /package/{src → ccw/src}/types/index.ts +0 -0
  959. /package/{src → ccw/src}/types/session.ts +0 -0
  960. /package/{src → ccw/src}/types/tool.ts +0 -0
  961. /package/{src → ccw/src}/utils/browser-launcher.ts +0 -0
  962. /package/{src → ccw/src}/utils/file-utils.ts +0 -0
  963. /package/{src → ccw/src}/utils/path-resolver.ts +0 -0
  964. /package/{src → ccw/src}/utils/path-validator.ts +0 -0
  965. /package/{src → ccw/src}/utils/ui.ts +0 -0
@@ -0,0 +1,1940 @@
1
+ """Typer commands for CodexLens."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ import os
8
+ import shutil
9
+ from pathlib import Path
10
+ from typing import Any, Dict, Iterable, List, Optional
11
+
12
+ import typer
13
+ from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
14
+ from rich.table import Table
15
+
16
+ from codexlens.config import Config
17
+ from codexlens.entities import IndexedFile, SearchResult, Symbol
18
+ from codexlens.errors import CodexLensError, ConfigError, ParseError, StorageError, SearchError
19
+ from codexlens.parsers.factory import ParserFactory
20
+ from codexlens.storage.path_mapper import PathMapper
21
+ from codexlens.storage.registry import RegistryStore, ProjectInfo
22
+ from codexlens.storage.index_tree import IndexTreeBuilder
23
+ from codexlens.storage.dir_index import DirIndexStore
24
+ from codexlens.search.chain_search import ChainSearchEngine, SearchOptions
25
+
26
+ from .output import (
27
+ console,
28
+ print_json,
29
+ render_file_inspect,
30
+ render_search_results,
31
+ render_status,
32
+ render_symbols,
33
+ )
34
+
35
+ app = typer.Typer(help="CodexLens CLI — local code indexing and search.")
36
+
37
+
38
+ def _configure_logging(verbose: bool, json_mode: bool = False) -> None:
39
+ """Configure logging level.
40
+
41
+ In JSON mode, suppress INFO logs to keep stderr clean for error parsing.
42
+ Only WARNING and above are shown to avoid mixing logs with JSON output.
43
+ """
44
+ if json_mode and not verbose:
45
+ # In JSON mode, suppress INFO logs to keep stderr clean
46
+ level = logging.WARNING
47
+ else:
48
+ level = logging.DEBUG if verbose else logging.INFO
49
+ logging.basicConfig(level=level, format="%(levelname)s %(message)s")
50
+
51
+
52
+ def _parse_languages(raw: Optional[List[str]]) -> Optional[List[str]]:
53
+ if not raw:
54
+ return None
55
+ langs: List[str] = []
56
+ for item in raw:
57
+ for part in item.split(","):
58
+ part = part.strip()
59
+ if part:
60
+ langs.append(part)
61
+ return langs or None
62
+
63
+
64
+ def _get_index_root() -> Path:
65
+ """Get the index root directory from config or default."""
66
+ env_override = os.getenv("CODEXLENS_INDEX_DIR")
67
+ if env_override:
68
+ return Path(env_override).expanduser().resolve()
69
+ return Path.home() / ".codexlens" / "indexes"
70
+
71
+
72
+ def _get_registry_path() -> Path:
73
+ """Get the registry database path."""
74
+ env_override = os.getenv("CODEXLENS_DATA_DIR")
75
+ if env_override:
76
+ return Path(env_override).expanduser().resolve() / "registry.db"
77
+ return Path.home() / ".codexlens" / "registry.db"
78
+
79
+
80
+ @app.command()
81
+ def init(
82
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True, help="Project root to index."),
83
+ language: Optional[List[str]] = typer.Option(
84
+ None,
85
+ "--language",
86
+ "-l",
87
+ help="Limit indexing to specific languages (repeat or comma-separated).",
88
+ ),
89
+ workers: Optional[int] = typer.Option(None, "--workers", "-w", min=1, max=16, help="Parallel worker processes (default: auto-detect based on CPU count, max 16)."),
90
+ force: bool = typer.Option(False, "--force", "-f", help="Force full reindex (skip incremental mode)."),
91
+ no_embeddings: bool = typer.Option(False, "--no-embeddings", help="Skip automatic embedding generation (if semantic deps installed)."),
92
+ embedding_model: str = typer.Option("code", "--embedding-model", help="Embedding model profile: fast, code, multilingual, balanced."),
93
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
94
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
95
+ ) -> None:
96
+ """Initialize or rebuild the index for a directory.
97
+
98
+ Indexes are stored in ~/.codexlens/indexes/ with mirrored directory structure.
99
+ Set CODEXLENS_INDEX_DIR to customize the index location.
100
+
101
+ By default, uses incremental indexing (skip unchanged files).
102
+ Use --force to rebuild all files regardless of modification time.
103
+
104
+ If semantic search dependencies are installed, automatically generates embeddings
105
+ after indexing completes. Use --no-embeddings to skip this step.
106
+ """
107
+ _configure_logging(verbose, json_mode)
108
+ config = Config()
109
+ languages = _parse_languages(language)
110
+ base_path = path.expanduser().resolve()
111
+
112
+ registry: RegistryStore | None = None
113
+ try:
114
+ registry = RegistryStore()
115
+ registry.initialize()
116
+ mapper = PathMapper()
117
+
118
+ builder = IndexTreeBuilder(registry, mapper, config, incremental=not force)
119
+
120
+ if force:
121
+ console.print(f"[bold]Building index for:[/bold] {base_path} [yellow](FULL reindex)[/yellow]")
122
+ else:
123
+ console.print(f"[bold]Building index for:[/bold] {base_path} [dim](incremental)[/dim]")
124
+
125
+ build_result = builder.build(
126
+ source_root=base_path,
127
+ languages=languages,
128
+ workers=workers,
129
+ force_full=force,
130
+ )
131
+
132
+ result = {
133
+ "path": str(base_path),
134
+ "files_indexed": build_result.total_files,
135
+ "dirs_indexed": build_result.total_dirs,
136
+ "index_root": str(build_result.index_root),
137
+ "project_id": build_result.project_id,
138
+ "languages": languages or sorted(config.supported_languages.keys()),
139
+ "errors": len(build_result.errors),
140
+ }
141
+
142
+ if json_mode:
143
+ print_json(success=True, result=result)
144
+ else:
145
+ console.print(f"[green]OK[/green] Indexed [bold]{build_result.total_files}[/bold] files in [bold]{build_result.total_dirs}[/bold] directories")
146
+ console.print(f" Index root: {build_result.index_root}")
147
+ if build_result.errors:
148
+ console.print(f" [yellow]Warnings:[/yellow] {len(build_result.errors)} errors")
149
+
150
+ # Auto-generate embeddings if semantic search is available
151
+ if not no_embeddings:
152
+ try:
153
+ from codexlens.semantic import SEMANTIC_AVAILABLE
154
+ from codexlens.cli.embedding_manager import generate_embeddings_recursive, get_embeddings_status
155
+
156
+ if SEMANTIC_AVAILABLE:
157
+ # Use the index root directory (not the _index.db file)
158
+ index_root = Path(build_result.index_root)
159
+
160
+ if not json_mode:
161
+ console.print("\n[bold]Generating embeddings...[/bold]")
162
+ console.print(f"Model: [cyan]{embedding_model}[/cyan]")
163
+ else:
164
+ # Output progress message for JSON mode (parsed by Node.js)
165
+ print("Generating embeddings...", flush=True)
166
+
167
+ # Progress callback - outputs progress for both json and non-json modes
168
+ # Node.js parseProgressLine() expects formats like:
169
+ # - "Batch X: N files, M chunks"
170
+ # - "Processing N files"
171
+ # - "Finalizing index"
172
+ def progress_update(msg: str):
173
+ if json_mode:
174
+ # Output without prefix so Node.js can parse it
175
+ # Strip leading spaces that embedding_manager adds
176
+ print(msg.strip(), flush=True)
177
+ elif verbose:
178
+ console.print(f" {msg}")
179
+
180
+ embed_result = generate_embeddings_recursive(
181
+ index_root,
182
+ model_profile=embedding_model,
183
+ force=False, # Don't force regenerate during init
184
+ chunk_size=2000,
185
+ progress_callback=progress_update, # Always use callback
186
+ )
187
+
188
+ if embed_result["success"]:
189
+ embed_data = embed_result["result"]
190
+
191
+ # Output completion message for Node.js to parse
192
+ if json_mode:
193
+ print(f"Embeddings complete: {embed_data['total_chunks_created']} chunks", flush=True)
194
+
195
+ # Get comprehensive coverage statistics
196
+ status_result = get_embeddings_status(index_root)
197
+ if status_result["success"]:
198
+ coverage = status_result["result"]
199
+ result["embeddings"] = {
200
+ "generated": True,
201
+ "total_indexes": coverage["total_indexes"],
202
+ "total_files": coverage["total_files"],
203
+ "files_with_embeddings": coverage["files_with_embeddings"],
204
+ "coverage_percent": coverage["coverage_percent"],
205
+ "total_chunks": coverage["total_chunks"],
206
+ }
207
+ else:
208
+ result["embeddings"] = {
209
+ "generated": True,
210
+ "total_chunks": embed_data["total_chunks_created"],
211
+ "files_processed": embed_data["total_files_processed"],
212
+ }
213
+
214
+ if not json_mode:
215
+ console.print(f"[green]✓[/green] Generated embeddings for [bold]{embed_data['total_files_processed']}[/bold] files")
216
+ console.print(f" Total chunks: [bold]{embed_data['total_chunks_created']}[/bold]")
217
+ console.print(f" Indexes processed: [bold]{embed_data['indexes_successful']}/{embed_data['indexes_processed']}[/bold]")
218
+ else:
219
+ if not json_mode:
220
+ console.print(f"[yellow]Warning:[/yellow] Embedding generation failed: {embed_result.get('error', 'Unknown error')}")
221
+ result["embeddings"] = {
222
+ "generated": False,
223
+ "error": embed_result.get("error"),
224
+ }
225
+ else:
226
+ if not json_mode and verbose:
227
+ console.print("[dim]Semantic search not available. Skipping embeddings.[/dim]")
228
+ result["embeddings"] = {
229
+ "generated": False,
230
+ "error": "Semantic dependencies not installed",
231
+ }
232
+ except Exception as e:
233
+ if not json_mode and verbose:
234
+ console.print(f"[yellow]Warning:[/yellow] Could not generate embeddings: {e}")
235
+ result["embeddings"] = {
236
+ "generated": False,
237
+ "error": str(e),
238
+ }
239
+ else:
240
+ result["embeddings"] = {
241
+ "generated": False,
242
+ "error": "Skipped (--no-embeddings)",
243
+ }
244
+
245
+ except StorageError as exc:
246
+ if json_mode:
247
+ print_json(success=False, error=f"Storage error: {exc}")
248
+ else:
249
+ console.print(f"[red]Init failed (storage):[/red] {exc}")
250
+ raise typer.Exit(code=1)
251
+ except ConfigError as exc:
252
+ if json_mode:
253
+ print_json(success=False, error=f"Configuration error: {exc}")
254
+ else:
255
+ console.print(f"[red]Init failed (config):[/red] {exc}")
256
+ raise typer.Exit(code=1)
257
+ except ParseError as exc:
258
+ if json_mode:
259
+ print_json(success=False, error=f"Parse error: {exc}")
260
+ else:
261
+ console.print(f"[red]Init failed (parse):[/red] {exc}")
262
+ raise typer.Exit(code=1)
263
+ except PermissionError as exc:
264
+ if json_mode:
265
+ print_json(success=False, error=f"Permission denied: {exc}")
266
+ else:
267
+ console.print(f"[red]Init failed (permission denied):[/red] {exc}")
268
+ raise typer.Exit(code=1)
269
+ except CodexLensError as exc:
270
+ if json_mode:
271
+ print_json(success=False, error=str(exc))
272
+ else:
273
+ console.print(f"[red]Init failed:[/red] {exc}")
274
+ raise typer.Exit(code=1)
275
+ finally:
276
+ if registry is not None:
277
+ registry.close()
278
+
279
+
280
+ @app.command()
281
+ def search(
282
+ query: str = typer.Argument(..., help="FTS query to run."),
283
+ path: Path = typer.Option(Path("."), "--path", "-p", help="Directory to search from."),
284
+ limit: int = typer.Option(20, "--limit", "-n", min=1, max=500, help="Max results."),
285
+ depth: int = typer.Option(-1, "--depth", "-d", help="Search depth (-1 = unlimited, 0 = current only)."),
286
+ files_only: bool = typer.Option(False, "--files-only", "-f", help="Return only file paths without content snippets."),
287
+ mode: str = typer.Option("auto", "--mode", "-m", help="Search mode: auto, exact, fuzzy, hybrid, vector, pure-vector."),
288
+ weights: Optional[str] = typer.Option(None, "--weights", help="Custom RRF weights as 'exact,fuzzy,vector' (e.g., '0.5,0.3,0.2')."),
289
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
290
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
291
+ ) -> None:
292
+ """Search indexed file contents using SQLite FTS5 or semantic vectors.
293
+
294
+ Uses chain search across directory indexes.
295
+ Use --depth to limit search recursion (0 = current dir only).
296
+
297
+ Search Modes:
298
+ - auto: Auto-detect (hybrid if embeddings exist, exact otherwise) [default]
299
+ - exact: Exact FTS using unicode61 tokenizer - for code identifiers
300
+ - fuzzy: Fuzzy FTS using trigram tokenizer - for typo-tolerant search
301
+ - hybrid: RRF fusion of exact + fuzzy + vector (recommended) - best recall
302
+ - vector: Vector search with exact FTS fallback - semantic + keyword
303
+ - pure-vector: Pure semantic vector search only - natural language queries
304
+
305
+ Vector Search Requirements:
306
+ Vector search modes require pre-generated embeddings.
307
+ Use 'codexlens embeddings-generate' to create embeddings first.
308
+
309
+ Hybrid Mode:
310
+ Default weights: exact=0.4, fuzzy=0.3, vector=0.3
311
+ Use --weights to customize (e.g., --weights 0.5,0.3,0.2)
312
+
313
+ Examples:
314
+ # Auto-detect mode (uses hybrid if embeddings available)
315
+ codexlens search "authentication"
316
+
317
+ # Explicit exact code search
318
+ codexlens search "authenticate_user" --mode exact
319
+
320
+ # Semantic search (requires embeddings)
321
+ codexlens search "how to verify user credentials" --mode pure-vector
322
+
323
+ # Force hybrid mode
324
+ codexlens search "authentication" --mode hybrid
325
+ """
326
+ _configure_logging(verbose, json_mode)
327
+ search_path = path.expanduser().resolve()
328
+
329
+ # Validate mode
330
+ valid_modes = ["auto", "exact", "fuzzy", "hybrid", "vector", "pure-vector"]
331
+ if mode not in valid_modes:
332
+ if json_mode:
333
+ print_json(success=False, error=f"Invalid mode: {mode}. Must be one of: {', '.join(valid_modes)}")
334
+ else:
335
+ console.print(f"[red]Invalid mode:[/red] {mode}")
336
+ console.print(f"[dim]Valid modes: {', '.join(valid_modes)}[/dim]")
337
+ raise typer.Exit(code=1)
338
+
339
+ # Parse custom weights if provided
340
+ hybrid_weights = None
341
+ if weights:
342
+ try:
343
+ weight_parts = [float(w.strip()) for w in weights.split(",")]
344
+ if len(weight_parts) == 3:
345
+ weight_sum = sum(weight_parts)
346
+ if abs(weight_sum - 1.0) > 0.01:
347
+ console.print(f"[yellow]Warning: Weights sum to {weight_sum:.2f}, should sum to 1.0. Normalizing...[/yellow]")
348
+ # Normalize weights
349
+ weight_parts = [w / weight_sum for w in weight_parts]
350
+ hybrid_weights = {
351
+ "exact": weight_parts[0],
352
+ "fuzzy": weight_parts[1],
353
+ "vector": weight_parts[2],
354
+ }
355
+ else:
356
+ console.print("[yellow]Warning: Invalid weights format (need 3 values). Using defaults.[/yellow]")
357
+ except ValueError:
358
+ console.print("[yellow]Warning: Invalid weights format. Using defaults.[/yellow]")
359
+
360
+ registry: RegistryStore | None = None
361
+ try:
362
+ registry = RegistryStore()
363
+ registry.initialize()
364
+ mapper = PathMapper()
365
+
366
+ engine = ChainSearchEngine(registry, mapper)
367
+
368
+ # Auto-detect mode if set to "auto"
369
+ actual_mode = mode
370
+ if mode == "auto":
371
+ # Check if embeddings are available by looking for project in registry
372
+ project_record = registry.find_by_source_path(str(search_path))
373
+ has_embeddings = False
374
+
375
+ if project_record:
376
+ # Check if index has embeddings
377
+ index_path = Path(project_record["index_root"]) / "_index.db"
378
+ try:
379
+ from codexlens.cli.embedding_manager import check_embeddings_status
380
+ embed_status = check_embeddings_status(index_path)
381
+ if embed_status["success"]:
382
+ embed_data = embed_status["result"]
383
+ has_embeddings = embed_data["has_embeddings"] and embed_data["chunks_count"] > 0
384
+ except Exception:
385
+ pass
386
+
387
+ # Choose mode based on embedding availability
388
+ if has_embeddings:
389
+ actual_mode = "hybrid"
390
+ if not json_mode and verbose:
391
+ console.print("[dim]Auto-detected mode: hybrid (embeddings available)[/dim]")
392
+ else:
393
+ actual_mode = "exact"
394
+ if not json_mode and verbose:
395
+ console.print("[dim]Auto-detected mode: exact (no embeddings)[/dim]")
396
+
397
+ # Map mode to options
398
+ if actual_mode == "exact":
399
+ hybrid_mode, enable_fuzzy, enable_vector, pure_vector = False, False, False, False
400
+ elif actual_mode == "fuzzy":
401
+ hybrid_mode, enable_fuzzy, enable_vector, pure_vector = False, True, False, False
402
+ elif actual_mode == "vector":
403
+ hybrid_mode, enable_fuzzy, enable_vector, pure_vector = True, False, True, False # Vector + exact fallback
404
+ elif actual_mode == "pure-vector":
405
+ hybrid_mode, enable_fuzzy, enable_vector, pure_vector = True, False, True, True # Pure vector only
406
+ elif actual_mode == "hybrid":
407
+ hybrid_mode, enable_fuzzy, enable_vector, pure_vector = True, True, True, False
408
+ else:
409
+ raise ValueError(f"Invalid mode: {actual_mode}")
410
+
411
+ options = SearchOptions(
412
+ depth=depth,
413
+ total_limit=limit,
414
+ files_only=files_only,
415
+ hybrid_mode=hybrid_mode,
416
+ enable_fuzzy=enable_fuzzy,
417
+ enable_vector=enable_vector,
418
+ pure_vector=pure_vector,
419
+ hybrid_weights=hybrid_weights,
420
+ )
421
+
422
+ if files_only:
423
+ file_paths = engine.search_files_only(query, search_path, options)
424
+ payload = {"query": query, "count": len(file_paths), "files": file_paths}
425
+ if json_mode:
426
+ print_json(success=True, result=payload)
427
+ else:
428
+ for fp in file_paths:
429
+ console.print(fp)
430
+ else:
431
+ result = engine.search(query, search_path, options)
432
+ results_list = [
433
+ {
434
+ "path": r.path,
435
+ "score": r.score,
436
+ "excerpt": r.excerpt,
437
+ "source": getattr(r, "search_source", None),
438
+ "symbol": getattr(r, "symbol", None),
439
+ }
440
+ for r in result.results
441
+ ]
442
+
443
+ payload = {
444
+ "query": query,
445
+ "mode": actual_mode,
446
+ "count": len(results_list),
447
+ "results": results_list,
448
+ "stats": {
449
+ "dirs_searched": result.stats.dirs_searched,
450
+ "files_matched": result.stats.files_matched,
451
+ "time_ms": result.stats.time_ms,
452
+ },
453
+ }
454
+ if json_mode:
455
+ print_json(success=True, result=payload)
456
+ else:
457
+ render_search_results(result.results, verbose=verbose)
458
+ console.print(f"[dim]Mode: {actual_mode} | Searched {result.stats.dirs_searched} directories in {result.stats.time_ms:.1f}ms[/dim]")
459
+
460
+ except SearchError as exc:
461
+ if json_mode:
462
+ print_json(success=False, error=f"Search error: {exc}")
463
+ else:
464
+ console.print(f"[red]Search failed (query):[/red] {exc}")
465
+ raise typer.Exit(code=1)
466
+ except StorageError as exc:
467
+ if json_mode:
468
+ print_json(success=False, error=f"Storage error: {exc}")
469
+ else:
470
+ console.print(f"[red]Search failed (storage):[/red] {exc}")
471
+ raise typer.Exit(code=1)
472
+ except CodexLensError as exc:
473
+ if json_mode:
474
+ print_json(success=False, error=str(exc))
475
+ else:
476
+ console.print(f"[red]Search failed:[/red] {exc}")
477
+ raise typer.Exit(code=1)
478
+ finally:
479
+ if registry is not None:
480
+ registry.close()
481
+
482
+
483
+ @app.command()
484
+ def symbol(
485
+ name: str = typer.Argument(..., help="Symbol name to look up."),
486
+ path: Path = typer.Option(Path("."), "--path", "-p", help="Directory to search from."),
487
+ kind: Optional[str] = typer.Option(
488
+ None,
489
+ "--kind",
490
+ "-k",
491
+ help="Filter by kind (function|class|method).",
492
+ ),
493
+ limit: int = typer.Option(50, "--limit", "-n", min=1, max=500, help="Max symbols."),
494
+ depth: int = typer.Option(-1, "--depth", "-d", help="Search depth (-1 = unlimited)."),
495
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
496
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
497
+ ) -> None:
498
+ """Look up symbols by name and optional kind."""
499
+ _configure_logging(verbose, json_mode)
500
+ search_path = path.expanduser().resolve()
501
+
502
+ registry: RegistryStore | None = None
503
+ try:
504
+ registry = RegistryStore()
505
+ registry.initialize()
506
+ mapper = PathMapper()
507
+
508
+ engine = ChainSearchEngine(registry, mapper)
509
+ options = SearchOptions(depth=depth, total_limit=limit)
510
+
511
+ syms = engine.search_symbols(name, search_path, kind=kind, options=options)
512
+
513
+ payload = {"name": name, "kind": kind, "count": len(syms), "symbols": syms}
514
+ if json_mode:
515
+ print_json(success=True, result=payload)
516
+ else:
517
+ render_symbols(syms)
518
+
519
+ except SearchError as exc:
520
+ if json_mode:
521
+ print_json(success=False, error=f"Search error: {exc}")
522
+ else:
523
+ console.print(f"[red]Symbol lookup failed (search):[/red] {exc}")
524
+ raise typer.Exit(code=1)
525
+ except StorageError as exc:
526
+ if json_mode:
527
+ print_json(success=False, error=f"Storage error: {exc}")
528
+ else:
529
+ console.print(f"[red]Symbol lookup failed (storage):[/red] {exc}")
530
+ raise typer.Exit(code=1)
531
+ except CodexLensError as exc:
532
+ if json_mode:
533
+ print_json(success=False, error=str(exc))
534
+ else:
535
+ console.print(f"[red]Symbol lookup failed:[/red] {exc}")
536
+ raise typer.Exit(code=1)
537
+ finally:
538
+ if registry is not None:
539
+ registry.close()
540
+
541
+
542
+ @app.command()
543
+ def inspect(
544
+ file: Path = typer.Argument(..., exists=True, dir_okay=False, help="File to analyze."),
545
+ symbols: bool = typer.Option(True, "--symbols/--no-symbols", help="Show discovered symbols."),
546
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
547
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
548
+ ) -> None:
549
+ """Analyze a single file and display symbols."""
550
+ _configure_logging(verbose, json_mode)
551
+ config = Config()
552
+ factory = ParserFactory(config)
553
+
554
+ file_path = file.expanduser().resolve()
555
+ try:
556
+ text = file_path.read_text(encoding="utf-8", errors="ignore")
557
+ language_id = config.language_for_path(file_path) or "unknown"
558
+ parser = factory.get_parser(language_id)
559
+ indexed = parser.parse(text, file_path)
560
+ payload = {"file": indexed, "content_lines": len(text.splitlines())}
561
+ if json_mode:
562
+ print_json(success=True, result=payload)
563
+ else:
564
+ if symbols:
565
+ render_file_inspect(indexed.path, indexed.language, indexed.symbols)
566
+ else:
567
+ render_status({"file": indexed.path, "language": indexed.language})
568
+ except ParseError as exc:
569
+ if json_mode:
570
+ print_json(success=False, error=f"Parse error: {exc}")
571
+ else:
572
+ console.print(f"[red]Inspect failed (parse):[/red] {exc}")
573
+ raise typer.Exit(code=1)
574
+ except FileNotFoundError as exc:
575
+ if json_mode:
576
+ print_json(success=False, error=f"File not found: {exc}")
577
+ else:
578
+ console.print(f"[red]Inspect failed (file not found):[/red] {exc}")
579
+ raise typer.Exit(code=1)
580
+ except PermissionError as exc:
581
+ if json_mode:
582
+ print_json(success=False, error=f"Permission denied: {exc}")
583
+ else:
584
+ console.print(f"[red]Inspect failed (permission denied):[/red] {exc}")
585
+ raise typer.Exit(code=1)
586
+ except CodexLensError as exc:
587
+ if json_mode:
588
+ print_json(success=False, error=str(exc))
589
+ else:
590
+ console.print(f"[red]Inspect failed:[/red] {exc}")
591
+ raise typer.Exit(code=1)
592
+
593
+
594
+ @app.command()
595
+ def status(
596
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
597
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
598
+ ) -> None:
599
+ """Show index status and configuration."""
600
+ _configure_logging(verbose, json_mode)
601
+
602
+ registry: RegistryStore | None = None
603
+ try:
604
+ registry = RegistryStore()
605
+ registry.initialize()
606
+ mapper = PathMapper()
607
+
608
+ # Get all projects
609
+ projects = registry.list_projects()
610
+
611
+ # Calculate total stats
612
+ total_files = sum(p.total_files for p in projects)
613
+ total_dirs = sum(p.total_dirs for p in projects)
614
+
615
+ # Get index root size
616
+ index_root = mapper.index_root
617
+ index_size = 0
618
+ if index_root.exists():
619
+ for f in index_root.rglob("*"):
620
+ if f.is_file():
621
+ index_size += f.stat().st_size
622
+
623
+ # Check schema version and enabled features
624
+ schema_version = None
625
+ has_dual_fts = False
626
+ if projects and index_root.exists():
627
+ # Check first index database for features
628
+ index_files = list(index_root.rglob("_index.db"))
629
+ if index_files:
630
+ try:
631
+ with DirIndexStore(index_files[0]) as store:
632
+ with store._lock:
633
+ conn = store._get_connection()
634
+ schema_version = store._get_schema_version(conn)
635
+ # Check if dual FTS tables exist
636
+ cursor = conn.execute(
637
+ "SELECT name FROM sqlite_master WHERE type='table' AND name IN ('search_fts_exact', 'search_fts_fuzzy')"
638
+ )
639
+ fts_tables = [row[0] for row in cursor.fetchall()]
640
+ has_dual_fts = len(fts_tables) == 2
641
+ except Exception:
642
+ pass
643
+
644
+ # Check embeddings coverage
645
+ embeddings_info = None
646
+ has_vector_search = False
647
+ try:
648
+ from codexlens.cli.embedding_manager import get_embeddings_status
649
+
650
+ if index_root.exists():
651
+ embed_status = get_embeddings_status(index_root)
652
+ if embed_status["success"]:
653
+ embeddings_info = embed_status["result"]
654
+ # Enable vector search if coverage >= 50%
655
+ has_vector_search = embeddings_info["coverage_percent"] >= 50.0
656
+ except ImportError:
657
+ # Embedding manager not available
658
+ pass
659
+ except Exception as e:
660
+ logging.debug(f"Failed to get embeddings status: {e}")
661
+
662
+ stats = {
663
+ "index_root": str(index_root),
664
+ "registry_path": str(_get_registry_path()),
665
+ "projects_count": len(projects),
666
+ "total_files": total_files,
667
+ "total_dirs": total_dirs,
668
+ "index_size_bytes": index_size,
669
+ "index_size_mb": round(index_size / (1024 * 1024), 2),
670
+ "schema_version": schema_version,
671
+ "features": {
672
+ "exact_fts": True, # Always available
673
+ "fuzzy_fts": has_dual_fts,
674
+ "hybrid_search": has_dual_fts,
675
+ "vector_search": has_vector_search,
676
+ },
677
+ }
678
+
679
+ # Add embeddings info if available
680
+ if embeddings_info:
681
+ stats["embeddings"] = embeddings_info
682
+
683
+ if json_mode:
684
+ print_json(success=True, result=stats)
685
+ else:
686
+ console.print("[bold]CodexLens Status[/bold]")
687
+ console.print(f" Index Root: {stats['index_root']}")
688
+ console.print(f" Registry: {stats['registry_path']}")
689
+ console.print(f" Projects: {stats['projects_count']}")
690
+ console.print(f" Total Files: {stats['total_files']}")
691
+ console.print(f" Total Directories: {stats['total_dirs']}")
692
+ console.print(f" Index Size: {stats['index_size_mb']} MB")
693
+ if schema_version:
694
+ console.print(f" Schema Version: {schema_version}")
695
+ console.print("\n[bold]Search Backends:[/bold]")
696
+ console.print(f" Exact FTS: ✓ (unicode61)")
697
+ if has_dual_fts:
698
+ console.print(f" Fuzzy FTS: ✓ (trigram)")
699
+ console.print(f" Hybrid Search: ✓ (RRF fusion)")
700
+ else:
701
+ console.print(f" Fuzzy FTS: ✗ (run 'migrate' to enable)")
702
+ console.print(f" Hybrid Search: ✗ (run 'migrate' to enable)")
703
+
704
+ if has_vector_search:
705
+ console.print(f" Vector Search: ✓ (embeddings available)")
706
+ else:
707
+ console.print(f" Vector Search: ✗ (no embeddings or coverage < 50%)")
708
+
709
+ # Display embeddings statistics if available
710
+ if embeddings_info:
711
+ console.print("\n[bold]Embeddings Coverage:[/bold]")
712
+ console.print(f" Total Indexes: {embeddings_info['total_indexes']}")
713
+ console.print(f" Total Files: {embeddings_info['total_files']}")
714
+ console.print(f" Files with Embeddings: {embeddings_info['files_with_embeddings']}")
715
+ console.print(f" Coverage: {embeddings_info['coverage_percent']:.1f}%")
716
+ console.print(f" Total Chunks: {embeddings_info['total_chunks']}")
717
+
718
+ except StorageError as exc:
719
+ if json_mode:
720
+ print_json(success=False, error=f"Storage error: {exc}")
721
+ else:
722
+ console.print(f"[red]Status failed (storage):[/red] {exc}")
723
+ raise typer.Exit(code=1)
724
+ except CodexLensError as exc:
725
+ if json_mode:
726
+ print_json(success=False, error=str(exc))
727
+ else:
728
+ console.print(f"[red]Status failed:[/red] {exc}")
729
+ raise typer.Exit(code=1)
730
+ finally:
731
+ if registry is not None:
732
+ registry.close()
733
+
734
+
735
+ @app.command()
736
+ def projects(
737
+ action: str = typer.Argument("list", help="Action: list, show, remove"),
738
+ project_path: Optional[Path] = typer.Argument(None, help="Project path (for show/remove)."),
739
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
740
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
741
+ ) -> None:
742
+ """Manage registered projects in the global registry.
743
+
744
+ Actions:
745
+ - list: Show all registered projects
746
+ - show <path>: Show details for a specific project
747
+ - remove <path>: Remove a project from the registry
748
+ """
749
+ _configure_logging(verbose, json_mode)
750
+
751
+ registry: RegistryStore | None = None
752
+ try:
753
+ registry = RegistryStore()
754
+ registry.initialize()
755
+
756
+ if action == "list":
757
+ project_list = registry.list_projects()
758
+ if json_mode:
759
+ result = [
760
+ {
761
+ "id": p.id,
762
+ "source_root": str(p.source_root),
763
+ "index_root": str(p.index_root),
764
+ "total_files": p.total_files,
765
+ "total_dirs": p.total_dirs,
766
+ "status": p.status,
767
+ }
768
+ for p in project_list
769
+ ]
770
+ print_json(success=True, result=result)
771
+ else:
772
+ if not project_list:
773
+ console.print("[yellow]No projects registered.[/yellow]")
774
+ else:
775
+ table = Table(title="Registered Projects")
776
+ table.add_column("ID", style="dim")
777
+ table.add_column("Source Root")
778
+ table.add_column("Files", justify="right")
779
+ table.add_column("Dirs", justify="right")
780
+ table.add_column("Status")
781
+
782
+ for p in project_list:
783
+ table.add_row(
784
+ str(p.id),
785
+ str(p.source_root),
786
+ str(p.total_files),
787
+ str(p.total_dirs),
788
+ p.status,
789
+ )
790
+ console.print(table)
791
+
792
+ elif action == "show":
793
+ if not project_path:
794
+ raise typer.BadParameter("Project path required for 'show' action")
795
+
796
+ project_path = project_path.expanduser().resolve()
797
+ project_info = registry.get_project(project_path)
798
+
799
+ if not project_info:
800
+ if json_mode:
801
+ print_json(success=False, error=f"Project not found: {project_path}")
802
+ else:
803
+ console.print(f"[red]Project not found:[/red] {project_path}")
804
+ raise typer.Exit(code=1)
805
+
806
+ if json_mode:
807
+ result = {
808
+ "id": project_info.id,
809
+ "source_root": str(project_info.source_root),
810
+ "index_root": str(project_info.index_root),
811
+ "total_files": project_info.total_files,
812
+ "total_dirs": project_info.total_dirs,
813
+ "status": project_info.status,
814
+ "created_at": project_info.created_at,
815
+ "last_indexed": project_info.last_indexed,
816
+ }
817
+ print_json(success=True, result=result)
818
+ else:
819
+ console.print(f"[bold]Project:[/bold] {project_info.source_root}")
820
+ console.print(f" ID: {project_info.id}")
821
+ console.print(f" Index Root: {project_info.index_root}")
822
+ console.print(f" Files: {project_info.total_files}")
823
+ console.print(f" Directories: {project_info.total_dirs}")
824
+ console.print(f" Status: {project_info.status}")
825
+
826
+ # Show directory breakdown
827
+ dirs = registry.get_project_dirs(project_info.id)
828
+ if dirs:
829
+ console.print(f"\n [bold]Indexed Directories:[/bold] {len(dirs)}")
830
+ for d in dirs[:10]:
831
+ console.print(f" - {d.source_path.name}/ ({d.files_count} files)")
832
+ if len(dirs) > 10:
833
+ console.print(f" ... and {len(dirs) - 10} more")
834
+
835
+ elif action == "remove":
836
+ if not project_path:
837
+ raise typer.BadParameter("Project path required for 'remove' action")
838
+
839
+ project_path = project_path.expanduser().resolve()
840
+ removed = registry.unregister_project(project_path)
841
+
842
+ if removed:
843
+ mapper = PathMapper()
844
+ index_root = mapper.source_to_index_dir(project_path)
845
+ if index_root.exists():
846
+ shutil.rmtree(index_root)
847
+
848
+ if json_mode:
849
+ print_json(success=True, result={"removed": str(project_path)})
850
+ else:
851
+ console.print(f"[green]Removed:[/green] {project_path}")
852
+ else:
853
+ if json_mode:
854
+ print_json(success=False, error=f"Project not found: {project_path}")
855
+ else:
856
+ console.print(f"[yellow]Project not found:[/yellow] {project_path}")
857
+
858
+ else:
859
+ raise typer.BadParameter(f"Unknown action: {action}. Use list, show, or remove.")
860
+
861
+ except typer.BadParameter:
862
+ raise
863
+ except StorageError as exc:
864
+ if json_mode:
865
+ print_json(success=False, error=f"Storage error: {exc}")
866
+ else:
867
+ console.print(f"[red]Projects command failed (storage):[/red] {exc}")
868
+ raise typer.Exit(code=1)
869
+ except PermissionError as exc:
870
+ if json_mode:
871
+ print_json(success=False, error=f"Permission denied: {exc}")
872
+ else:
873
+ console.print(f"[red]Projects command failed (permission denied):[/red] {exc}")
874
+ raise typer.Exit(code=1)
875
+ except CodexLensError as exc:
876
+ if json_mode:
877
+ print_json(success=False, error=str(exc))
878
+ else:
879
+ console.print(f"[red]Projects command failed:[/red] {exc}")
880
+ raise typer.Exit(code=1)
881
+ finally:
882
+ if registry is not None:
883
+ registry.close()
884
+
885
+
886
+ @app.command()
887
+ def config(
888
+ action: str = typer.Argument("show", help="Action: show, set, migrate"),
889
+ key: Optional[str] = typer.Argument(None, help="Config key (for set action)."),
890
+ value: Optional[str] = typer.Argument(None, help="Config value (for set action)."),
891
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
892
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
893
+ ) -> None:
894
+ """Manage CodexLens configuration.
895
+
896
+ Actions:
897
+ - show: Display current configuration
898
+ - set <key> <value>: Set configuration value
899
+ - migrate <new_path>: Migrate indexes to new location
900
+
901
+ Config keys:
902
+ - index_dir: Directory to store indexes (default: ~/.codexlens/indexes)
903
+ """
904
+ _configure_logging(verbose, json_mode)
905
+
906
+ config_file = Path.home() / ".codexlens" / "config.json"
907
+
908
+ def load_config() -> Dict[str, Any]:
909
+ if config_file.exists():
910
+ return json.loads(config_file.read_text(encoding="utf-8"))
911
+ return {}
912
+
913
+ def save_config(cfg: Dict[str, Any]) -> None:
914
+ config_file.parent.mkdir(parents=True, exist_ok=True)
915
+ config_file.write_text(json.dumps(cfg, indent=2), encoding="utf-8")
916
+
917
+ try:
918
+ if action == "show":
919
+ cfg = load_config()
920
+ current_index_dir = os.getenv("CODEXLENS_INDEX_DIR") or cfg.get("index_dir") or str(Path.home() / ".codexlens" / "indexes")
921
+
922
+ result = {
923
+ "config_file": str(config_file),
924
+ "index_dir": current_index_dir,
925
+ "env_override": os.getenv("CODEXLENS_INDEX_DIR"),
926
+ }
927
+
928
+ if json_mode:
929
+ print_json(success=True, result=result)
930
+ else:
931
+ console.print("[bold]CodexLens Configuration[/bold]")
932
+ console.print(f" Config File: {result['config_file']}")
933
+ console.print(f" Index Directory: {result['index_dir']}")
934
+ if result['env_override']:
935
+ console.print(f" [dim](Override via CODEXLENS_INDEX_DIR)[/dim]")
936
+
937
+ elif action == "set":
938
+ if not key:
939
+ raise typer.BadParameter("Config key required for 'set' action")
940
+ if not value:
941
+ raise typer.BadParameter("Config value required for 'set' action")
942
+
943
+ cfg = load_config()
944
+
945
+ if key == "index_dir":
946
+ new_path = Path(value).expanduser().resolve()
947
+ cfg["index_dir"] = str(new_path)
948
+ save_config(cfg)
949
+
950
+ if json_mode:
951
+ print_json(success=True, result={"key": key, "value": str(new_path)})
952
+ else:
953
+ console.print(f"[green]Set {key}=[/green] {new_path}")
954
+ console.print("[yellow]Note: Existing indexes remain at old location. Use 'config migrate' to move them.[/yellow]")
955
+ else:
956
+ raise typer.BadParameter(f"Unknown config key: {key}")
957
+
958
+ elif action == "migrate":
959
+ if not key:
960
+ raise typer.BadParameter("New path required for 'migrate' action")
961
+
962
+ new_path = Path(key).expanduser().resolve()
963
+ mapper = PathMapper()
964
+ old_path = mapper.index_root
965
+
966
+ if not old_path.exists():
967
+ if json_mode:
968
+ print_json(success=False, error="No indexes to migrate")
969
+ else:
970
+ console.print("[yellow]No indexes to migrate.[/yellow]")
971
+ return
972
+
973
+ # Create new directory
974
+ new_path.mkdir(parents=True, exist_ok=True)
975
+
976
+ # Count items to migrate
977
+ items = list(old_path.iterdir())
978
+ migrated = 0
979
+
980
+ with Progress(
981
+ SpinnerColumn(),
982
+ TextColumn("[progress.description]{task.description}"),
983
+ BarColumn(),
984
+ TextColumn("{task.completed}/{task.total}"),
985
+ TimeElapsedColumn(),
986
+ console=console,
987
+ ) as progress:
988
+ task = progress.add_task("Migrating indexes", total=len(items))
989
+
990
+ for item in items:
991
+ dest = new_path / item.name
992
+ if item.is_dir():
993
+ shutil.copytree(item, dest, dirs_exist_ok=True)
994
+ else:
995
+ shutil.copy2(item, dest)
996
+ migrated += 1
997
+ progress.advance(task)
998
+
999
+ # Update config
1000
+ cfg = load_config()
1001
+ cfg["index_dir"] = str(new_path)
1002
+ save_config(cfg)
1003
+
1004
+ # Update registry paths
1005
+ registry = RegistryStore()
1006
+ registry.initialize()
1007
+ registry.update_index_paths(old_path, new_path)
1008
+ registry.close()
1009
+
1010
+ result = {
1011
+ "migrated_from": str(old_path),
1012
+ "migrated_to": str(new_path),
1013
+ "items_migrated": migrated,
1014
+ }
1015
+
1016
+ if json_mode:
1017
+ print_json(success=True, result=result)
1018
+ else:
1019
+ console.print(f"[green]Migrated {migrated} items to:[/green] {new_path}")
1020
+ console.print("[dim]Old indexes can be manually deleted after verifying migration.[/dim]")
1021
+
1022
+ else:
1023
+ raise typer.BadParameter(f"Unknown action: {action}. Use show, set, or migrate.")
1024
+
1025
+ except typer.BadParameter:
1026
+ raise
1027
+ except ConfigError as exc:
1028
+ if json_mode:
1029
+ print_json(success=False, error=f"Configuration error: {exc}")
1030
+ else:
1031
+ console.print(f"[red]Config command failed (config):[/red] {exc}")
1032
+ raise typer.Exit(code=1)
1033
+ except StorageError as exc:
1034
+ if json_mode:
1035
+ print_json(success=False, error=f"Storage error: {exc}")
1036
+ else:
1037
+ console.print(f"[red]Config command failed (storage):[/red] {exc}")
1038
+ raise typer.Exit(code=1)
1039
+ except PermissionError as exc:
1040
+ if json_mode:
1041
+ print_json(success=False, error=f"Permission denied: {exc}")
1042
+ else:
1043
+ console.print(f"[red]Config command failed (permission denied):[/red] {exc}")
1044
+ raise typer.Exit(code=1)
1045
+ except CodexLensError as exc:
1046
+ if json_mode:
1047
+ print_json(success=False, error=str(exc))
1048
+ else:
1049
+ console.print(f"[red]Config command failed:[/red] {exc}")
1050
+ raise typer.Exit(code=1)
1051
+
1052
+
1053
+ @app.command()
1054
+ def migrate(
1055
+ path: Path = typer.Argument(Path("."), exists=True, file_okay=False, dir_okay=True, help="Project root to migrate."),
1056
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1057
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
1058
+ ) -> None:
1059
+ """Migrate project indexes to latest schema (Dual-FTS upgrade).
1060
+
1061
+ Upgrades all _index.db files in the project to schema version 4, which includes:
1062
+ - Dual FTS tables (exact + fuzzy)
1063
+ - Encoding detection support
1064
+ - Incremental indexing metadata
1065
+
1066
+ This is a safe operation that preserves all existing data.
1067
+ Progress is shown during migration.
1068
+ """
1069
+ _configure_logging(verbose, json_mode)
1070
+ base_path = path.expanduser().resolve()
1071
+
1072
+ registry: RegistryStore | None = None
1073
+ try:
1074
+ registry = RegistryStore()
1075
+ registry.initialize()
1076
+ mapper = PathMapper()
1077
+
1078
+ # Find project
1079
+ project_info = registry.get_project(base_path)
1080
+ if not project_info:
1081
+ raise CodexLensError(f"No index found for: {base_path}. Run 'codex-lens init' first.")
1082
+
1083
+ index_dir = mapper.source_to_index_dir(base_path)
1084
+ if not index_dir.exists():
1085
+ raise CodexLensError(f"Index directory not found: {index_dir}")
1086
+
1087
+ # Find all _index.db files
1088
+ index_files = list(index_dir.rglob("_index.db"))
1089
+
1090
+ if not index_files:
1091
+ if json_mode:
1092
+ print_json(success=True, result={"message": "No indexes to migrate", "migrated": 0})
1093
+ else:
1094
+ console.print("[yellow]No indexes found to migrate.[/yellow]")
1095
+ return
1096
+
1097
+ migrated_count = 0
1098
+ error_count = 0
1099
+ already_migrated = 0
1100
+
1101
+ with Progress(
1102
+ SpinnerColumn(),
1103
+ TextColumn("[progress.description]{task.description}"),
1104
+ BarColumn(),
1105
+ TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
1106
+ TextColumn("({task.completed}/{task.total})"),
1107
+ TimeElapsedColumn(),
1108
+ console=console,
1109
+ ) as progress:
1110
+ task = progress.add_task(f"Migrating {len(index_files)} indexes...", total=len(index_files))
1111
+
1112
+ for db_path in index_files:
1113
+ try:
1114
+ store = DirIndexStore(db_path)
1115
+
1116
+ # Check current version
1117
+ with store._lock:
1118
+ conn = store._get_connection()
1119
+ current_version = store._get_schema_version(conn)
1120
+
1121
+ if current_version >= DirIndexStore.SCHEMA_VERSION:
1122
+ already_migrated += 1
1123
+ if verbose:
1124
+ progress.console.print(f"[dim]Already migrated: {db_path.parent.name}[/dim]")
1125
+ elif current_version > 0:
1126
+ # Apply migrations
1127
+ store._apply_migrations(conn, current_version)
1128
+ store._set_schema_version(conn, DirIndexStore.SCHEMA_VERSION)
1129
+ conn.commit()
1130
+ migrated_count += 1
1131
+ if verbose:
1132
+ progress.console.print(f"[green]Migrated: {db_path.parent.name} (v{current_version} → v{DirIndexStore.SCHEMA_VERSION})[/green]")
1133
+ else:
1134
+ # New database, initialize directly
1135
+ store.initialize()
1136
+ migrated_count += 1
1137
+
1138
+ store.close()
1139
+
1140
+ except Exception as e:
1141
+ error_count += 1
1142
+ if verbose:
1143
+ progress.console.print(f"[red]Error migrating {db_path}: {e}[/red]")
1144
+
1145
+ progress.update(task, advance=1)
1146
+
1147
+ result = {
1148
+ "path": str(base_path),
1149
+ "total_indexes": len(index_files),
1150
+ "migrated": migrated_count,
1151
+ "already_migrated": already_migrated,
1152
+ "errors": error_count,
1153
+ }
1154
+
1155
+ if json_mode:
1156
+ print_json(success=True, result=result)
1157
+ else:
1158
+ console.print(f"[green]Migration complete:[/green]")
1159
+ console.print(f" Total indexes: {len(index_files)}")
1160
+ console.print(f" Migrated: {migrated_count}")
1161
+ console.print(f" Already up-to-date: {already_migrated}")
1162
+ if error_count > 0:
1163
+ console.print(f" [yellow]Errors: {error_count}[/yellow]")
1164
+
1165
+ except StorageError as exc:
1166
+ if json_mode:
1167
+ print_json(success=False, error=f"Storage error: {exc}")
1168
+ else:
1169
+ console.print(f"[red]Migration failed (storage):[/red] {exc}")
1170
+ raise typer.Exit(code=1)
1171
+ except CodexLensError as exc:
1172
+ if json_mode:
1173
+ print_json(success=False, error=str(exc))
1174
+ else:
1175
+ console.print(f"[red]Migration failed:[/red] {exc}")
1176
+ raise typer.Exit(code=1)
1177
+ finally:
1178
+ if registry is not None:
1179
+ registry.close()
1180
+
1181
+
1182
+ @app.command()
1183
+ def clean(
1184
+ path: Optional[Path] = typer.Argument(None, help="Project path to clean (removes project index)."),
1185
+ all_indexes: bool = typer.Option(False, "--all", "-a", help="Remove all indexes."),
1186
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1187
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
1188
+ ) -> None:
1189
+ """Remove CodexLens index data.
1190
+
1191
+ Without arguments, shows current index size.
1192
+ With path, removes that project's indexes.
1193
+ With --all, removes all indexes (use with caution).
1194
+ """
1195
+ _configure_logging(verbose, json_mode)
1196
+
1197
+ try:
1198
+ mapper = PathMapper()
1199
+ index_root = mapper.index_root
1200
+
1201
+ if all_indexes:
1202
+ # Remove everything
1203
+ if not index_root.exists():
1204
+ if json_mode:
1205
+ print_json(success=True, result={"cleaned": None, "message": "No indexes to clean"})
1206
+ else:
1207
+ console.print("[yellow]No indexes to clean.[/yellow]")
1208
+ return
1209
+
1210
+ # Calculate size before removal
1211
+ total_size = 0
1212
+ for f in index_root.rglob("*"):
1213
+ if f.is_file():
1214
+ total_size += f.stat().st_size
1215
+
1216
+ # Remove registry first
1217
+ registry_path = _get_registry_path()
1218
+ if registry_path.exists():
1219
+ registry_path.unlink()
1220
+
1221
+ # Remove all indexes
1222
+ shutil.rmtree(index_root)
1223
+
1224
+ result = {
1225
+ "cleaned": str(index_root),
1226
+ "size_freed_mb": round(total_size / (1024 * 1024), 2),
1227
+ }
1228
+
1229
+ if json_mode:
1230
+ print_json(success=True, result=result)
1231
+ else:
1232
+ console.print(f"[green]Removed all indexes:[/green] {result['size_freed_mb']} MB freed")
1233
+
1234
+ elif path:
1235
+ # Remove specific project
1236
+ project_path = path.expanduser().resolve()
1237
+ project_index = mapper.source_to_index_dir(project_path)
1238
+
1239
+ if not project_index.exists():
1240
+ if json_mode:
1241
+ print_json(success=False, error=f"No index found for: {project_path}")
1242
+ else:
1243
+ console.print(f"[yellow]No index found for:[/yellow] {project_path}")
1244
+ return
1245
+
1246
+ # Calculate size
1247
+ total_size = 0
1248
+ for f in project_index.rglob("*"):
1249
+ if f.is_file():
1250
+ total_size += f.stat().st_size
1251
+
1252
+ # Remove from registry
1253
+ registry = RegistryStore()
1254
+ registry.initialize()
1255
+ registry.unregister_project(project_path)
1256
+ registry.close()
1257
+
1258
+ # Remove indexes
1259
+ shutil.rmtree(project_index)
1260
+
1261
+ result = {
1262
+ "cleaned": str(project_path),
1263
+ "index_path": str(project_index),
1264
+ "size_freed_mb": round(total_size / (1024 * 1024), 2),
1265
+ }
1266
+
1267
+ if json_mode:
1268
+ print_json(success=True, result=result)
1269
+ else:
1270
+ console.print(f"[green]Removed indexes for:[/green] {project_path}")
1271
+ console.print(f" Freed: {result['size_freed_mb']} MB")
1272
+
1273
+ else:
1274
+ # Show current status
1275
+ if not index_root.exists():
1276
+ if json_mode:
1277
+ print_json(success=True, result={"index_root": str(index_root), "exists": False})
1278
+ else:
1279
+ console.print("[yellow]No indexes found.[/yellow]")
1280
+ return
1281
+
1282
+ total_size = 0
1283
+ for f in index_root.rglob("*"):
1284
+ if f.is_file():
1285
+ total_size += f.stat().st_size
1286
+
1287
+ registry = RegistryStore()
1288
+ registry.initialize()
1289
+ projects = registry.list_projects()
1290
+ registry.close()
1291
+
1292
+ result = {
1293
+ "index_root": str(index_root),
1294
+ "projects_count": len(projects),
1295
+ "total_size_mb": round(total_size / (1024 * 1024), 2),
1296
+ }
1297
+
1298
+ if json_mode:
1299
+ print_json(success=True, result=result)
1300
+ else:
1301
+ console.print("[bold]Index Status[/bold]")
1302
+ console.print(f" Location: {result['index_root']}")
1303
+ console.print(f" Projects: {result['projects_count']}")
1304
+ console.print(f" Total Size: {result['total_size_mb']} MB")
1305
+ console.print("\n[dim]Use 'clean <path>' to remove a specific project or 'clean --all' to remove everything.[/dim]")
1306
+
1307
+ except StorageError as exc:
1308
+ if json_mode:
1309
+ print_json(success=False, error=f"Storage error: {exc}")
1310
+ else:
1311
+ console.print(f"[red]Clean failed (storage):[/red] {exc}")
1312
+ raise typer.Exit(code=1)
1313
+ except PermissionError as exc:
1314
+ if json_mode:
1315
+ print_json(success=False, error=f"Permission denied: {exc}")
1316
+ else:
1317
+ console.print(f"[red]Clean failed (permission denied):[/red] {exc}")
1318
+ raise typer.Exit(code=1)
1319
+ except CodexLensError as exc:
1320
+ if json_mode:
1321
+ print_json(success=False, error=str(exc))
1322
+ else:
1323
+ console.print(f"[red]Clean failed:[/red] {exc}")
1324
+ raise typer.Exit(code=1)
1325
+
1326
+
1327
+ @app.command("semantic-list")
1328
+ def semantic_list(
1329
+ path: Path = typer.Option(Path("."), "--path", "-p", help="Project path to list metadata from."),
1330
+ offset: int = typer.Option(0, "--offset", "-o", min=0, help="Number of records to skip."),
1331
+ limit: int = typer.Option(50, "--limit", "-n", min=1, max=100, help="Maximum records to return."),
1332
+ tool_filter: Optional[str] = typer.Option(None, "--tool", "-t", help="Filter by LLM tool (gemini/qwen)."),
1333
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1334
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
1335
+ ) -> None:
1336
+ """List semantic metadata entries for indexed files.
1337
+
1338
+ Shows files that have LLM-generated summaries and keywords.
1339
+ Results are aggregated from all index databases in the project.
1340
+ """
1341
+ _configure_logging(verbose, json_mode)
1342
+ base_path = path.expanduser().resolve()
1343
+
1344
+ registry: Optional[RegistryStore] = None
1345
+ try:
1346
+ registry = RegistryStore()
1347
+ registry.initialize()
1348
+ mapper = PathMapper()
1349
+
1350
+ project_info = registry.get_project(base_path)
1351
+ if not project_info:
1352
+ raise CodexLensError(f"No index found for: {base_path}. Run 'codex-lens init' first.")
1353
+
1354
+ index_dir = Path(project_info.index_root)
1355
+ if not index_dir.exists():
1356
+ raise CodexLensError(f"Index directory not found: {index_dir}")
1357
+
1358
+ all_results: list = []
1359
+ total_count = 0
1360
+
1361
+ index_files = sorted(index_dir.rglob("_index.db"))
1362
+
1363
+ for db_path in index_files:
1364
+ try:
1365
+ store = DirIndexStore(db_path)
1366
+ store.initialize()
1367
+
1368
+ results, count = store.list_semantic_metadata(
1369
+ offset=0,
1370
+ limit=1000,
1371
+ llm_tool=tool_filter,
1372
+ )
1373
+
1374
+ source_dir = mapper.index_to_source(db_path.parent)
1375
+ for r in results:
1376
+ r["source_dir"] = str(source_dir)
1377
+
1378
+ all_results.extend(results)
1379
+ total_count += count
1380
+
1381
+ store.close()
1382
+ except Exception as e:
1383
+ if verbose:
1384
+ console.print(f"[yellow]Warning: Error reading {db_path}: {e}[/yellow]")
1385
+
1386
+ all_results.sort(key=lambda x: x["generated_at"], reverse=True)
1387
+ paginated = all_results[offset : offset + limit]
1388
+
1389
+ result = {
1390
+ "path": str(base_path),
1391
+ "total": total_count,
1392
+ "offset": offset,
1393
+ "limit": limit,
1394
+ "count": len(paginated),
1395
+ "entries": paginated,
1396
+ }
1397
+
1398
+ if json_mode:
1399
+ print_json(success=True, result=result)
1400
+ else:
1401
+ if not paginated:
1402
+ console.print("[yellow]No semantic metadata found.[/yellow]")
1403
+ console.print("Run 'codex-lens enhance' to generate metadata for indexed files.")
1404
+ else:
1405
+ table = Table(title=f"Semantic Metadata ({total_count} total)")
1406
+ table.add_column("File", style="cyan", max_width=40)
1407
+ table.add_column("Language", style="dim")
1408
+ table.add_column("Purpose", max_width=30)
1409
+ table.add_column("Keywords", max_width=25)
1410
+ table.add_column("Tool")
1411
+
1412
+ for entry in paginated:
1413
+ keywords_str = ", ".join(entry["keywords"][:3])
1414
+ if len(entry["keywords"]) > 3:
1415
+ keywords_str += f" (+{len(entry['keywords']) - 3})"
1416
+
1417
+ table.add_row(
1418
+ entry["file_name"],
1419
+ entry["language"] or "-",
1420
+ (entry["purpose"] or "-")[:30],
1421
+ keywords_str or "-",
1422
+ entry["llm_tool"] or "-",
1423
+ )
1424
+
1425
+ console.print(table)
1426
+
1427
+ if total_count > len(paginated):
1428
+ console.print(
1429
+ f"[dim]Showing {offset + 1}-{offset + len(paginated)} of {total_count}. "
1430
+ "Use --offset and --limit for pagination.[/dim]"
1431
+ )
1432
+
1433
+ except StorageError as exc:
1434
+ if json_mode:
1435
+ print_json(success=False, error=f"Storage error: {exc}")
1436
+ else:
1437
+ console.print(f"[red]Semantic-list failed (storage):[/red] {exc}")
1438
+ raise typer.Exit(code=1)
1439
+ except CodexLensError as exc:
1440
+ if json_mode:
1441
+ print_json(success=False, error=str(exc))
1442
+ else:
1443
+ console.print(f"[red]Semantic-list failed:[/red] {exc}")
1444
+ raise typer.Exit(code=1)
1445
+ finally:
1446
+ if registry is not None:
1447
+ registry.close()
1448
+
1449
+
1450
+ # ==================== Model Management Commands ====================
1451
+
1452
+ @app.command(name="model-list")
1453
+ def model_list(
1454
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1455
+ ) -> None:
1456
+ """List available embedding models and their installation status.
1457
+
1458
+ Shows 4 model profiles (fast, code, multilingual, balanced) with:
1459
+ - Installation status
1460
+ - Model size and dimensions
1461
+ - Use case recommendations
1462
+ """
1463
+ try:
1464
+ from codexlens.cli.model_manager import list_models
1465
+
1466
+ result = list_models()
1467
+
1468
+ if json_mode:
1469
+ print_json(**result)
1470
+ else:
1471
+ if not result["success"]:
1472
+ console.print(f"[red]Error:[/red] {result.get('error', 'Unknown error')}")
1473
+ raise typer.Exit(code=1)
1474
+
1475
+ data = result["result"]
1476
+ models = data["models"]
1477
+ cache_dir = data["cache_dir"]
1478
+ cache_exists = data["cache_exists"]
1479
+
1480
+ console.print("[bold]Available Embedding Models:[/bold]")
1481
+ console.print(f"Cache directory: [dim]{cache_dir}[/dim] {'(exists)' if cache_exists else '(not found)'}\n")
1482
+
1483
+ table = Table(show_header=True, header_style="bold")
1484
+ table.add_column("Profile", style="cyan")
1485
+ table.add_column("Model Name", style="blue")
1486
+ table.add_column("Dims", justify="right")
1487
+ table.add_column("Size (MB)", justify="right")
1488
+ table.add_column("Status", justify="center")
1489
+ table.add_column("Use Case", style="dim")
1490
+
1491
+ for model in models:
1492
+ status_icon = "[green]✓[/green]" if model["installed"] else "[dim]—[/dim]"
1493
+ size_display = (
1494
+ f"{model['actual_size_mb']:.1f}" if model["installed"]
1495
+ else f"~{model['estimated_size_mb']}"
1496
+ )
1497
+ table.add_row(
1498
+ model["profile"],
1499
+ model["model_name"],
1500
+ str(model["dimensions"]),
1501
+ size_display,
1502
+ status_icon,
1503
+ model["use_case"][:40] + "..." if len(model["use_case"]) > 40 else model["use_case"],
1504
+ )
1505
+
1506
+ console.print(table)
1507
+ console.print("\n[dim]Use 'codexlens model-download <profile>' to download a model[/dim]")
1508
+
1509
+ except ImportError:
1510
+ if json_mode:
1511
+ print_json(success=False, error="fastembed not installed. Install with: pip install codexlens[semantic]")
1512
+ else:
1513
+ console.print("[red]Error:[/red] fastembed not installed")
1514
+ console.print("[yellow]Install with:[/yellow] pip install codexlens[semantic]")
1515
+ raise typer.Exit(code=1)
1516
+
1517
+
1518
+ @app.command(name="model-download")
1519
+ def model_download(
1520
+ profile: str = typer.Argument(..., help="Model profile to download (fast, code, multilingual, balanced)."),
1521
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1522
+ ) -> None:
1523
+ """Download an embedding model by profile name.
1524
+
1525
+ Example:
1526
+ codexlens model-download code # Download code-optimized model
1527
+ """
1528
+ try:
1529
+ from codexlens.cli.model_manager import download_model
1530
+
1531
+ if not json_mode:
1532
+ console.print(f"[bold]Downloading model:[/bold] {profile}")
1533
+ console.print("[dim]This may take a few minutes depending on your internet connection...[/dim]\n")
1534
+
1535
+ # Create progress callback for non-JSON mode
1536
+ progress_callback = None if json_mode else lambda msg: console.print(f"[cyan]{msg}[/cyan]")
1537
+
1538
+ result = download_model(profile, progress_callback=progress_callback)
1539
+
1540
+ if json_mode:
1541
+ print_json(**result)
1542
+ else:
1543
+ if not result["success"]:
1544
+ console.print(f"[red]Error:[/red] {result.get('error', 'Unknown error')}")
1545
+ raise typer.Exit(code=1)
1546
+
1547
+ data = result["result"]
1548
+ console.print(f"[green]✓[/green] Model downloaded successfully!")
1549
+ console.print(f" Profile: {data['profile']}")
1550
+ console.print(f" Model: {data['model_name']}")
1551
+ console.print(f" Cache size: {data['cache_size_mb']:.1f} MB")
1552
+ console.print(f" Location: [dim]{data['cache_path']}[/dim]")
1553
+
1554
+ except ImportError:
1555
+ if json_mode:
1556
+ print_json(success=False, error="fastembed not installed. Install with: pip install codexlens[semantic]")
1557
+ else:
1558
+ console.print("[red]Error:[/red] fastembed not installed")
1559
+ console.print("[yellow]Install with:[/yellow] pip install codexlens[semantic]")
1560
+ raise typer.Exit(code=1)
1561
+
1562
+
1563
+ @app.command(name="model-delete")
1564
+ def model_delete(
1565
+ profile: str = typer.Argument(..., help="Model profile to delete (fast, code, multilingual, balanced)."),
1566
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1567
+ ) -> None:
1568
+ """Delete a downloaded embedding model from cache.
1569
+
1570
+ Example:
1571
+ codexlens model-delete fast # Delete fast model
1572
+ """
1573
+ from codexlens.cli.model_manager import delete_model
1574
+
1575
+ if not json_mode:
1576
+ console.print(f"[bold yellow]Deleting model:[/bold yellow] {profile}")
1577
+
1578
+ result = delete_model(profile)
1579
+
1580
+ if json_mode:
1581
+ print_json(**result)
1582
+ else:
1583
+ if not result["success"]:
1584
+ console.print(f"[red]Error:[/red] {result.get('error', 'Unknown error')}")
1585
+ raise typer.Exit(code=1)
1586
+
1587
+ data = result["result"]
1588
+ console.print(f"[green]✓[/green] Model deleted successfully!")
1589
+ console.print(f" Profile: {data['profile']}")
1590
+ console.print(f" Model: {data['model_name']}")
1591
+ console.print(f" Freed space: {data['deleted_size_mb']:.1f} MB")
1592
+
1593
+
1594
+ @app.command(name="model-info")
1595
+ def model_info(
1596
+ profile: str = typer.Argument(..., help="Model profile to get info (fast, code, multilingual, balanced)."),
1597
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1598
+ ) -> None:
1599
+ """Get detailed information about a model profile.
1600
+
1601
+ Example:
1602
+ codexlens model-info code # Get code model details
1603
+ """
1604
+ from codexlens.cli.model_manager import get_model_info
1605
+
1606
+ result = get_model_info(profile)
1607
+
1608
+ if json_mode:
1609
+ print_json(**result)
1610
+ else:
1611
+ if not result["success"]:
1612
+ console.print(f"[red]Error:[/red] {result.get('error', 'Unknown error')}")
1613
+ raise typer.Exit(code=1)
1614
+
1615
+ data = result["result"]
1616
+ console.print(f"[bold]Model Profile:[/bold] {data['profile']}")
1617
+ console.print(f" Model name: {data['model_name']}")
1618
+ console.print(f" Dimensions: {data['dimensions']}")
1619
+ console.print(f" Status: {'[green]Installed[/green]' if data['installed'] else '[dim]Not installed[/dim]'}")
1620
+ if data['installed'] and data['actual_size_mb']:
1621
+ console.print(f" Cache size: {data['actual_size_mb']:.1f} MB")
1622
+ console.print(f" Location: [dim]{data['cache_path']}[/dim]")
1623
+ else:
1624
+ console.print(f" Estimated size: ~{data['estimated_size_mb']} MB")
1625
+ console.print(f"\n Description: {data['description']}")
1626
+ console.print(f" Use case: {data['use_case']}")
1627
+
1628
+
1629
+ # ==================== Embedding Management Commands ====================
1630
+
1631
+ @app.command(name="embeddings-status")
1632
+ def embeddings_status(
1633
+ path: Optional[Path] = typer.Argument(
1634
+ None,
1635
+ exists=True,
1636
+ help="Path to specific _index.db file or directory containing indexes. If not specified, uses default index root.",
1637
+ ),
1638
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1639
+ ) -> None:
1640
+ """Check embedding status for one or all indexes.
1641
+
1642
+ Shows embedding statistics including:
1643
+ - Number of chunks generated
1644
+ - File coverage percentage
1645
+ - Files missing embeddings
1646
+
1647
+ Examples:
1648
+ codexlens embeddings-status # Check all indexes
1649
+ codexlens embeddings-status ~/.codexlens/indexes/project/_index.db # Check specific index
1650
+ codexlens embeddings-status ~/projects/my-app # Check project (auto-finds index)
1651
+ """
1652
+ from codexlens.cli.embedding_manager import check_index_embeddings, get_embedding_stats_summary
1653
+
1654
+ # Determine what to check
1655
+ if path is None:
1656
+ # Check all indexes in default root
1657
+ index_root = _get_index_root()
1658
+ result = get_embedding_stats_summary(index_root)
1659
+
1660
+ if json_mode:
1661
+ print_json(**result)
1662
+ else:
1663
+ if not result["success"]:
1664
+ console.print(f"[red]Error:[/red] {result.get('error', 'Unknown error')}")
1665
+ raise typer.Exit(code=1)
1666
+
1667
+ data = result["result"]
1668
+ total = data["total_indexes"]
1669
+ with_emb = data["indexes_with_embeddings"]
1670
+ total_chunks = data["total_chunks"]
1671
+
1672
+ console.print(f"[bold]Embedding Status Summary[/bold]")
1673
+ console.print(f"Index root: [dim]{index_root}[/dim]\n")
1674
+ console.print(f"Total indexes: {total}")
1675
+ console.print(f"Indexes with embeddings: [{'green' if with_emb > 0 else 'yellow'}]{with_emb}[/]/{total}")
1676
+ console.print(f"Total chunks: {total_chunks:,}\n")
1677
+
1678
+ if data["indexes"]:
1679
+ table = Table(show_header=True, header_style="bold")
1680
+ table.add_column("Project", style="cyan")
1681
+ table.add_column("Files", justify="right")
1682
+ table.add_column("Chunks", justify="right")
1683
+ table.add_column("Coverage", justify="right")
1684
+ table.add_column("Status", justify="center")
1685
+
1686
+ for idx_stat in data["indexes"]:
1687
+ status_icon = "[green]✓[/green]" if idx_stat["has_embeddings"] else "[dim]—[/dim]"
1688
+ coverage = f"{idx_stat['coverage_percent']:.1f}%" if idx_stat["has_embeddings"] else "—"
1689
+
1690
+ table.add_row(
1691
+ idx_stat["project"],
1692
+ str(idx_stat["total_files"]),
1693
+ f"{idx_stat['total_chunks']:,}" if idx_stat["has_embeddings"] else "0",
1694
+ coverage,
1695
+ status_icon,
1696
+ )
1697
+
1698
+ console.print(table)
1699
+
1700
+ else:
1701
+ # Check specific index or find index for project
1702
+ target_path = path.expanduser().resolve()
1703
+
1704
+ if target_path.is_file() and target_path.name == "_index.db":
1705
+ # Direct index file
1706
+ index_path = target_path
1707
+ elif target_path.is_dir():
1708
+ # Try to find index for this project
1709
+ registry = RegistryStore()
1710
+ try:
1711
+ registry.initialize()
1712
+ mapper = PathMapper()
1713
+ index_path = mapper.source_to_index_db(target_path)
1714
+
1715
+ if not index_path.exists():
1716
+ console.print(f"[red]Error:[/red] No index found for {target_path}")
1717
+ console.print("Run 'codexlens init' first to create an index")
1718
+ raise typer.Exit(code=1)
1719
+ finally:
1720
+ registry.close()
1721
+ else:
1722
+ console.print(f"[red]Error:[/red] Path must be _index.db file or directory")
1723
+ raise typer.Exit(code=1)
1724
+
1725
+ result = check_index_embeddings(index_path)
1726
+
1727
+ if json_mode:
1728
+ print_json(**result)
1729
+ else:
1730
+ if not result["success"]:
1731
+ console.print(f"[red]Error:[/red] {result.get('error', 'Unknown error')}")
1732
+ raise typer.Exit(code=1)
1733
+
1734
+ data = result["result"]
1735
+ has_emb = data["has_embeddings"]
1736
+
1737
+ console.print(f"[bold]Embedding Status[/bold]")
1738
+ console.print(f"Index: [dim]{data['index_path']}[/dim]\n")
1739
+
1740
+ if has_emb:
1741
+ console.print(f"[green]✓[/green] Embeddings available")
1742
+ console.print(f" Total chunks: {data['total_chunks']:,}")
1743
+ console.print(f" Total files: {data['total_files']:,}")
1744
+ console.print(f" Files with embeddings: {data['files_with_chunks']:,}/{data['total_files']}")
1745
+ console.print(f" Coverage: {data['coverage_percent']:.1f}%")
1746
+
1747
+ if data["files_without_chunks"] > 0:
1748
+ console.print(f"\n[yellow]Warning:[/yellow] {data['files_without_chunks']} files missing embeddings")
1749
+ if data["missing_files_sample"]:
1750
+ console.print(" Sample missing files:")
1751
+ for file in data["missing_files_sample"]:
1752
+ console.print(f" [dim]{file}[/dim]")
1753
+ else:
1754
+ console.print(f"[yellow]—[/yellow] No embeddings found")
1755
+ console.print(f" Total files indexed: {data['total_files']:,}")
1756
+ console.print("\n[dim]Generate embeddings with:[/dim]")
1757
+ console.print(f" [cyan]codexlens embeddings-generate {index_path}[/cyan]")
1758
+
1759
+
1760
+ @app.command(name="embeddings-generate")
1761
+ def embeddings_generate(
1762
+ path: Path = typer.Argument(
1763
+ ...,
1764
+ exists=True,
1765
+ help="Path to _index.db file or project directory.",
1766
+ ),
1767
+ model: str = typer.Option(
1768
+ "code",
1769
+ "--model",
1770
+ "-m",
1771
+ help="Model profile: fast, code, multilingual, balanced.",
1772
+ ),
1773
+ force: bool = typer.Option(
1774
+ False,
1775
+ "--force",
1776
+ "-f",
1777
+ help="Force regeneration even if embeddings exist.",
1778
+ ),
1779
+ chunk_size: int = typer.Option(
1780
+ 2000,
1781
+ "--chunk-size",
1782
+ help="Maximum chunk size in characters.",
1783
+ ),
1784
+ recursive: bool = typer.Option(
1785
+ False,
1786
+ "--recursive",
1787
+ "-r",
1788
+ help="Recursively process all _index.db files in directory tree.",
1789
+ ),
1790
+ json_mode: bool = typer.Option(False, "--json", help="Output JSON response."),
1791
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output."),
1792
+ ) -> None:
1793
+ """Generate semantic embeddings for code search.
1794
+
1795
+ Creates vector embeddings for all files in an index to enable
1796
+ semantic search capabilities. Embeddings are stored in the same
1797
+ database as the FTS index.
1798
+
1799
+ Model Profiles:
1800
+ - fast: BAAI/bge-small-en-v1.5 (384 dims, ~80MB)
1801
+ - code: jinaai/jina-embeddings-v2-base-code (768 dims, ~150MB) [recommended]
1802
+ - multilingual: intfloat/multilingual-e5-large (1024 dims, ~1GB)
1803
+ - balanced: mixedbread-ai/mxbai-embed-large-v1 (1024 dims, ~600MB)
1804
+
1805
+ Examples:
1806
+ codexlens embeddings-generate ~/projects/my-app # Auto-find index for project
1807
+ codexlens embeddings-generate ~/.codexlens/indexes/project/_index.db # Specific index
1808
+ codexlens embeddings-generate ~/projects/my-app --model fast --force # Regenerate with fast model
1809
+ """
1810
+ _configure_logging(verbose, json_mode)
1811
+
1812
+ from codexlens.cli.embedding_manager import generate_embeddings, generate_embeddings_recursive
1813
+
1814
+ # Resolve path
1815
+ target_path = path.expanduser().resolve()
1816
+
1817
+ # Determine if we should use recursive mode
1818
+ use_recursive = False
1819
+ index_path = None
1820
+ index_root = None
1821
+
1822
+ if target_path.is_file() and target_path.name == "_index.db":
1823
+ # Direct index file
1824
+ index_path = target_path
1825
+ if recursive:
1826
+ # Use parent directory for recursive processing
1827
+ use_recursive = True
1828
+ index_root = target_path.parent
1829
+ elif target_path.is_dir():
1830
+ if recursive:
1831
+ # Recursive mode: process all _index.db files in directory tree
1832
+ use_recursive = True
1833
+ index_root = target_path
1834
+ else:
1835
+ # Non-recursive: Try to find index for this project
1836
+ registry = RegistryStore()
1837
+ try:
1838
+ registry.initialize()
1839
+ mapper = PathMapper()
1840
+ index_path = mapper.source_to_index_db(target_path)
1841
+
1842
+ if not index_path.exists():
1843
+ console.print(f"[red]Error:[/red] No index found for {target_path}")
1844
+ console.print("Run 'codexlens init' first to create an index")
1845
+ raise typer.Exit(code=1)
1846
+ finally:
1847
+ registry.close()
1848
+ else:
1849
+ console.print(f"[red]Error:[/red] Path must be _index.db file or directory")
1850
+ raise typer.Exit(code=1)
1851
+
1852
+ # Progress callback
1853
+ def progress_update(msg: str):
1854
+ if not json_mode and verbose:
1855
+ console.print(f" {msg}")
1856
+
1857
+ console.print(f"[bold]Generating embeddings[/bold]")
1858
+ if use_recursive:
1859
+ console.print(f"Index root: [dim]{index_root}[/dim]")
1860
+ console.print(f"Mode: [yellow]Recursive[/yellow]")
1861
+ else:
1862
+ console.print(f"Index: [dim]{index_path}[/dim]")
1863
+ console.print(f"Model: [cyan]{model}[/cyan]\n")
1864
+
1865
+ if use_recursive:
1866
+ result = generate_embeddings_recursive(
1867
+ index_root,
1868
+ model_profile=model,
1869
+ force=force,
1870
+ chunk_size=chunk_size,
1871
+ progress_callback=progress_update,
1872
+ )
1873
+ else:
1874
+ result = generate_embeddings(
1875
+ index_path,
1876
+ model_profile=model,
1877
+ force=force,
1878
+ chunk_size=chunk_size,
1879
+ progress_callback=progress_update,
1880
+ )
1881
+
1882
+ if json_mode:
1883
+ print_json(**result)
1884
+ else:
1885
+ if not result["success"]:
1886
+ error_msg = result.get("error", "Unknown error")
1887
+ console.print(f"[red]Error:[/red] {error_msg}")
1888
+
1889
+ # Provide helpful hints
1890
+ if "already has" in error_msg:
1891
+ console.print("\n[dim]Use --force to regenerate existing embeddings[/dim]")
1892
+ elif "Semantic search not available" in error_msg:
1893
+ console.print("\n[dim]Install semantic dependencies:[/dim]")
1894
+ console.print(" [cyan]pip install codexlens[semantic][/cyan]")
1895
+
1896
+ raise typer.Exit(code=1)
1897
+
1898
+ data = result["result"]
1899
+
1900
+ if use_recursive:
1901
+ # Recursive mode output
1902
+ console.print(f"[green]✓[/green] Recursive embeddings generation complete!")
1903
+ console.print(f" Indexes processed: {data['indexes_processed']}")
1904
+ console.print(f" Indexes successful: {data['indexes_successful']}")
1905
+ if data['indexes_failed'] > 0:
1906
+ console.print(f" [yellow]Indexes failed: {data['indexes_failed']}[/yellow]")
1907
+ console.print(f" Total chunks created: {data['total_chunks_created']:,}")
1908
+ console.print(f" Total files processed: {data['total_files_processed']}")
1909
+ if data['total_files_failed'] > 0:
1910
+ console.print(f" [yellow]Total files failed: {data['total_files_failed']}[/yellow]")
1911
+ console.print(f" Model profile: {data['model_profile']}")
1912
+
1913
+ # Show details if verbose
1914
+ if verbose and data.get('details'):
1915
+ console.print("\n[dim]Index details:[/dim]")
1916
+ for detail in data['details']:
1917
+ status_icon = "[green]✓[/green]" if detail['success'] else "[red]✗[/red]"
1918
+ console.print(f" {status_icon} {detail['path']}")
1919
+ if not detail['success'] and detail.get('error'):
1920
+ console.print(f" [dim]Error: {detail['error']}[/dim]")
1921
+ else:
1922
+ # Single index mode output
1923
+ elapsed = data["elapsed_time"]
1924
+
1925
+ console.print(f"[green]✓[/green] Embeddings generated successfully!")
1926
+ console.print(f" Model: {data['model_name']}")
1927
+ console.print(f" Chunks created: {data['chunks_created']:,}")
1928
+ console.print(f" Files processed: {data['files_processed']}")
1929
+
1930
+ if data["files_failed"] > 0:
1931
+ console.print(f" [yellow]Files failed: {data['files_failed']}[/yellow]")
1932
+ if data["failed_files"]:
1933
+ console.print(" [dim]First failures:[/dim]")
1934
+ for file_path, error in data["failed_files"]:
1935
+ console.print(f" [dim]{file_path}: {error}[/dim]")
1936
+
1937
+ console.print(f" Time: {elapsed:.1f}s")
1938
+
1939
+ console.print("\n[dim]Use vector search with:[/dim]")
1940
+ console.print(" [cyan]codexlens search 'your query' --mode pure-vector[/cyan]")