k0ntext 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +623 -0
  3. package/bin/k0ntext.js +12 -0
  4. package/dist/agents/cleanup-agent.d.ts +39 -0
  5. package/dist/agents/cleanup-agent.d.ts.map +1 -0
  6. package/dist/agents/cleanup-agent.js +56 -0
  7. package/dist/agents/cleanup-agent.js.map +1 -0
  8. package/dist/agents/performance-agent.d.ts +37 -0
  9. package/dist/agents/performance-agent.d.ts.map +1 -0
  10. package/dist/agents/performance-agent.js +91 -0
  11. package/dist/agents/performance-agent.js.map +1 -0
  12. package/dist/analyzer/index.d.ts +5 -0
  13. package/dist/analyzer/index.d.ts.map +1 -0
  14. package/dist/analyzer/index.js +5 -0
  15. package/dist/analyzer/index.js.map +1 -0
  16. package/dist/analyzer/intelligent-analyzer.d.ts +111 -0
  17. package/dist/analyzer/intelligent-analyzer.d.ts.map +1 -0
  18. package/dist/analyzer/intelligent-analyzer.js +537 -0
  19. package/dist/analyzer/intelligent-analyzer.js.map +1 -0
  20. package/dist/cli/commands/cleanup.d.ts +3 -0
  21. package/dist/cli/commands/cleanup.d.ts.map +1 -0
  22. package/dist/cli/commands/cleanup.js +24 -0
  23. package/dist/cli/commands/cleanup.js.map +1 -0
  24. package/dist/cli/commands/export.d.ts +9 -0
  25. package/dist/cli/commands/export.d.ts.map +1 -0
  26. package/dist/cli/commands/export.js +72 -0
  27. package/dist/cli/commands/export.js.map +1 -0
  28. package/dist/cli/commands/import.d.ts +9 -0
  29. package/dist/cli/commands/import.d.ts.map +1 -0
  30. package/dist/cli/commands/import.js +62 -0
  31. package/dist/cli/commands/import.js.map +1 -0
  32. package/dist/cli/commands/performance.d.ts +9 -0
  33. package/dist/cli/commands/performance.d.ts.map +1 -0
  34. package/dist/cli/commands/performance.js +36 -0
  35. package/dist/cli/commands/performance.js.map +1 -0
  36. package/dist/cli/commands/validate.d.ts +9 -0
  37. package/dist/cli/commands/validate.d.ts.map +1 -0
  38. package/dist/cli/commands/validate.js +82 -0
  39. package/dist/cli/commands/validate.js.map +1 -0
  40. package/dist/cli/commands/watch.d.ts +9 -0
  41. package/dist/cli/commands/watch.d.ts.map +1 -0
  42. package/dist/cli/commands/watch.js +72 -0
  43. package/dist/cli/commands/watch.js.map +1 -0
  44. package/dist/cli/generate.d.ts +3 -0
  45. package/dist/cli/generate.d.ts.map +1 -0
  46. package/dist/cli/generate.js +194 -0
  47. package/dist/cli/generate.js.map +1 -0
  48. package/dist/cli/index.d.ts +9 -0
  49. package/dist/cli/index.d.ts.map +1 -0
  50. package/dist/cli/index.js +448 -0
  51. package/dist/cli/index.js.map +1 -0
  52. package/dist/cli/sync.d.ts +26 -0
  53. package/dist/cli/sync.d.ts.map +1 -0
  54. package/dist/cli/sync.js +163 -0
  55. package/dist/cli/sync.js.map +1 -0
  56. package/dist/config/cleanup-config.d.ts +26 -0
  57. package/dist/config/cleanup-config.d.ts.map +1 -0
  58. package/dist/config/cleanup-config.js +21 -0
  59. package/dist/config/cleanup-config.js.map +1 -0
  60. package/dist/db/client.d.ts +284 -0
  61. package/dist/db/client.d.ts.map +1 -0
  62. package/dist/db/client.js +688 -0
  63. package/dist/db/client.js.map +1 -0
  64. package/dist/db/index.d.ts +6 -0
  65. package/dist/db/index.d.ts.map +1 -0
  66. package/dist/db/index.js +6 -0
  67. package/dist/db/index.js.map +1 -0
  68. package/dist/db/schema.d.ts +41 -0
  69. package/dist/db/schema.d.ts.map +1 -0
  70. package/dist/db/schema.js +226 -0
  71. package/dist/db/schema.js.map +1 -0
  72. package/dist/embeddings/index.d.ts +5 -0
  73. package/dist/embeddings/index.d.ts.map +1 -0
  74. package/dist/embeddings/index.js +5 -0
  75. package/dist/embeddings/index.js.map +1 -0
  76. package/dist/embeddings/openrouter.d.ts +133 -0
  77. package/dist/embeddings/openrouter.d.ts.map +1 -0
  78. package/dist/embeddings/openrouter.js +455 -0
  79. package/dist/embeddings/openrouter.js.map +1 -0
  80. package/dist/index.d.ts +14 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +18 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/mcp.d.ts +29 -0
  85. package/dist/mcp.d.ts.map +1 -0
  86. package/dist/mcp.js +257 -0
  87. package/dist/mcp.js.map +1 -0
  88. package/docs/ARCHIVE/MIGRATE_TO_NEW_REPO.md +222 -0
  89. package/docs/ARCHIVE/MIGRATE_TO_UNIFIED.md +220 -0
  90. package/docs/CLEANUP.md +76 -0
  91. package/docs/MCP_QUICKSTART.md +219 -0
  92. package/docs/QUICKSTART.md +119 -0
  93. package/docs/TROUBLESHOOTING.md +611 -0
  94. package/package.json +100 -0
  95. package/skills/context-optimize/SKILL.md +86 -0
  96. package/skills/implement/SKILL.md +150 -0
  97. package/skills/plan/SKILL.md +143 -0
  98. package/skills/research/SKILL.md +103 -0
  99. package/skills/validate/SKILL.md +62 -0
  100. package/skills/verify-docs/SKILL.md +77 -0
  101. package/src/agents/cleanup-agent.ts +96 -0
  102. package/src/agents/performance-agent.ts +117 -0
  103. package/src/analyzer/index.ts +10 -0
  104. package/src/analyzer/intelligent-analyzer.ts +640 -0
  105. package/src/cli/commands/cleanup.ts +26 -0
  106. package/src/cli/commands/export.ts +82 -0
  107. package/src/cli/commands/import.ts +73 -0
  108. package/src/cli/commands/performance.ts +40 -0
  109. package/src/cli/commands/validate.ts +98 -0
  110. package/src/cli/commands/watch.ts +83 -0
  111. package/src/cli/generate.ts +219 -0
  112. package/src/cli/index.ts +510 -0
  113. package/src/cli/sync.ts +194 -0
  114. package/src/config/cleanup-config.ts +42 -0
  115. package/src/db/client.ts +949 -0
  116. package/src/db/index.ts +19 -0
  117. package/src/db/schema.ts +241 -0
  118. package/src/embeddings/index.ts +11 -0
  119. package/src/embeddings/openrouter.ts +592 -0
  120. package/src/index.ts +57 -0
  121. package/src/mcp.ts +354 -0
  122. package/templates/AI_CONTEXT.md.template +245 -0
  123. package/templates/base/README.md +260 -0
  124. package/templates/base/RPI_WORKFLOW_PLAN.md +325 -0
  125. package/templates/base/agents/api-developer.md +76 -0
  126. package/templates/base/agents/context-engineer.md +525 -0
  127. package/templates/base/agents/core-architect.md +76 -0
  128. package/templates/base/agents/database-ops.md +76 -0
  129. package/templates/base/agents/deployment-ops.md +76 -0
  130. package/templates/base/agents/integration-hub.md +76 -0
  131. package/templates/base/analytics/README.md +114 -0
  132. package/templates/base/automation/config.json +58 -0
  133. package/templates/base/automation/generators/code-mapper.js +308 -0
  134. package/templates/base/automation/generators/index-builder.js +321 -0
  135. package/templates/base/automation/hooks/post-commit.sh +83 -0
  136. package/templates/base/automation/hooks/pre-commit.sh +103 -0
  137. package/templates/base/ci-templates/README.md +108 -0
  138. package/templates/base/ci-templates/github-actions/context-check.yml +144 -0
  139. package/templates/base/ci-templates/github-actions/validate-docs.yml +105 -0
  140. package/templates/base/commands/analytics.md +238 -0
  141. package/templates/base/commands/auto-sync.md +172 -0
  142. package/templates/base/commands/collab.md +194 -0
  143. package/templates/base/commands/context-optimize.md +226 -0
  144. package/templates/base/commands/help.md +485 -0
  145. package/templates/base/commands/rpi-implement.md +164 -0
  146. package/templates/base/commands/rpi-plan.md +147 -0
  147. package/templates/base/commands/rpi-research.md +145 -0
  148. package/templates/base/commands/session-resume.md +144 -0
  149. package/templates/base/commands/session-save.md +112 -0
  150. package/templates/base/commands/validate-all.md +77 -0
  151. package/templates/base/commands/verify-docs-current.md +86 -0
  152. package/templates/base/config/base.json +57 -0
  153. package/templates/base/config/environments/development.json +13 -0
  154. package/templates/base/config/environments/production.json +17 -0
  155. package/templates/base/config/environments/staging.json +13 -0
  156. package/templates/base/config/local.json.example +21 -0
  157. package/templates/base/context/.meta/generated-at.json +18 -0
  158. package/templates/base/context/ARCHITECTURE_SNAPSHOT.md +156 -0
  159. package/templates/base/context/CODE_TO_WORKFLOW_MAP.md +94 -0
  160. package/templates/base/context/FILE_OWNERSHIP.md +57 -0
  161. package/templates/base/context/INTEGRATION_POINTS.md +92 -0
  162. package/templates/base/context/KNOWN_GOTCHAS.md +195 -0
  163. package/templates/base/context/TESTING_MAP.md +95 -0
  164. package/templates/base/context/WORKFLOW_INDEX.md +129 -0
  165. package/templates/base/context/workflows/WORKFLOW_TEMPLATE.md +294 -0
  166. package/templates/base/indexes/agents/CAPABILITY_MATRIX.md +255 -0
  167. package/templates/base/indexes/agents/CATEGORY_INDEX.md +44 -0
  168. package/templates/base/indexes/code/CATEGORY_INDEX.md +38 -0
  169. package/templates/base/indexes/routing/CATEGORY_INDEX.md +39 -0
  170. package/templates/base/indexes/search/CATEGORY_INDEX.md +39 -0
  171. package/templates/base/indexes/workflows/CATEGORY_INDEX.md +38 -0
  172. package/templates/base/knowledge/README.md +98 -0
  173. package/templates/base/knowledge/sessions/README.md +88 -0
  174. package/templates/base/knowledge/sessions/TEMPLATE.md +150 -0
  175. package/templates/base/knowledge/shared/decisions/0001-adopt-context-engineering.md +144 -0
  176. package/templates/base/knowledge/shared/decisions/README.md +49 -0
  177. package/templates/base/knowledge/shared/decisions/TEMPLATE.md +123 -0
  178. package/templates/base/knowledge/shared/patterns/README.md +62 -0
  179. package/templates/base/knowledge/shared/patterns/TEMPLATE.md +120 -0
  180. package/templates/base/plans/PLAN_TEMPLATE.md +316 -0
  181. package/templates/base/plans/active/.gitkeep +0 -0
  182. package/templates/base/plans/completed/.gitkeep +0 -0
  183. package/templates/base/research/RESEARCH_TEMPLATE.md +245 -0
  184. package/templates/base/research/active/.gitkeep +0 -0
  185. package/templates/base/research/completed/.gitkeep +0 -0
  186. package/templates/base/schemas/agent.schema.json +141 -0
  187. package/templates/base/schemas/anchors.schema.json +54 -0
  188. package/templates/base/schemas/automation.schema.json +93 -0
  189. package/templates/base/schemas/command.schema.json +134 -0
  190. package/templates/base/schemas/hashes.schema.json +40 -0
  191. package/templates/base/schemas/manifest.schema.json +117 -0
  192. package/templates/base/schemas/plan.schema.json +136 -0
  193. package/templates/base/schemas/research.schema.json +115 -0
  194. package/templates/base/schemas/roles.schema.json +34 -0
  195. package/templates/base/schemas/session.schema.json +77 -0
  196. package/templates/base/schemas/settings.schema.json +244 -0
  197. package/templates/base/schemas/staleness.schema.json +53 -0
  198. package/templates/base/schemas/team-config.schema.json +42 -0
  199. package/templates/base/schemas/workflow.schema.json +126 -0
  200. package/templates/base/session/checkpoints/.gitkeep +2 -0
  201. package/templates/base/session/current/state.json +20 -0
  202. package/templates/base/session/history/.gitkeep +2 -0
  203. package/templates/base/settings.json +3 -0
  204. package/templates/base/standards/COMPATIBILITY.md +219 -0
  205. package/templates/base/standards/EXTENSION_GUIDELINES.md +280 -0
  206. package/templates/base/standards/QUALITY_CHECKLIST.md +211 -0
  207. package/templates/base/standards/README.md +66 -0
  208. package/templates/base/sync/anchors.json +6 -0
  209. package/templates/base/sync/hashes.json +6 -0
  210. package/templates/base/sync/staleness.json +10 -0
  211. package/templates/base/team/README.md +168 -0
  212. package/templates/base/team/config.json +79 -0
  213. package/templates/base/team/roles.json +145 -0
  214. package/templates/base/tools/bin/claude-context.js +151 -0
  215. package/templates/base/tools/lib/anchor-resolver.js +276 -0
  216. package/templates/base/tools/lib/config-loader.js +363 -0
  217. package/templates/base/tools/lib/detector.js +350 -0
  218. package/templates/base/tools/lib/diagnose.js +206 -0
  219. package/templates/base/tools/lib/drift-detector.js +373 -0
  220. package/templates/base/tools/lib/errors.js +199 -0
  221. package/templates/base/tools/lib/index.js +36 -0
  222. package/templates/base/tools/lib/init.js +192 -0
  223. package/templates/base/tools/lib/logger.js +230 -0
  224. package/templates/base/tools/lib/placeholder.js +201 -0
  225. package/templates/base/tools/lib/session-manager.js +354 -0
  226. package/templates/base/tools/lib/validate.js +521 -0
  227. package/templates/base/tools/package.json +49 -0
  228. package/templates/handlebars/aider-config.hbs +146 -0
  229. package/templates/handlebars/antigravity.hbs +377 -0
  230. package/templates/handlebars/claude.hbs +183 -0
  231. package/templates/handlebars/cline.hbs +62 -0
  232. package/templates/handlebars/continue-config.hbs +116 -0
  233. package/templates/handlebars/copilot.hbs +130 -0
  234. package/templates/handlebars/partials/gotcha-list.hbs +11 -0
  235. package/templates/handlebars/partials/header.hbs +3 -0
  236. package/templates/handlebars/partials/workflow-summary.hbs +16 -0
  237. package/templates/handlebars/windsurf-rules.hbs +69 -0
  238. package/templates/hooks/post-commit.hbs +28 -0
  239. package/templates/hooks/pre-commit.hbs +46 -0
@@ -0,0 +1,510 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * AI Context CLI
5
+ *
6
+ * Unified CLI for AI Context Engineering.
7
+ * Supports initialization, MCP server, context generation, and cross-tool sync.
8
+ */
9
+
10
+ import { Command } from 'commander';
11
+ import chalk from 'chalk';
12
+ import ora from 'ora';
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ import { fileURLToPath } from 'url';
16
+
17
+ import { createIntelligentAnalyzer } from '../analyzer/intelligent-analyzer.js';
18
+ import { hasOpenRouterKey } from '../embeddings/openrouter.js';
19
+ import { generateCommand } from './generate.js';
20
+ import { syncCommand } from './sync.js';
21
+ import { cleanupCommand } from './commands/cleanup.js';
22
+ import { validateCommand } from './commands/validate.js';
23
+ import { exportCommand } from './commands/export.js';
24
+ import { importCommand } from './commands/import.js';
25
+ import { performanceCommand } from './commands/performance.js';
26
+ import { watchCommand } from './commands/watch.js';
27
+
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = path.dirname(__filename);
30
+
31
+ // Read package.json for version
32
+ const packageJsonPath = path.join(__dirname, '../../package.json');
33
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
34
+
35
+ // Supported AI tools
36
+ const AI_TOOLS = ['claude', 'copilot', 'cline', 'antigravity', 'windsurf', 'aider', 'continue', 'cursor', 'gemini', 'all'];
37
+
38
+ /**
39
+ * ASCII Banner
40
+ */
41
+ function showBanner(): void {
42
+ console.log(`
43
+ ${chalk.cyan('╔═══════════════════════════════════════════════════════════════╗')}
44
+ ${chalk.cyan('║')} ${chalk.bold.white('K0ntext')} ${chalk.gray('v' + packageJson.version)} ${chalk.cyan('║')}
45
+ ${chalk.cyan('║')} ${chalk.gray('Unified context engineering for all AI coding assistants')} ${chalk.cyan('║')}
46
+ ${chalk.cyan('╚═══════════════════════════════════════════════════════════════╝')}
47
+ `);
48
+ }
49
+
50
+ /**
51
+ * Parse AI tools from comma-separated string
52
+ */
53
+ function _parseAiTools(toolsString: string): string[] {
54
+ const tools = toolsString.split(',').map(t => t.trim().toLowerCase());
55
+ const invalid = tools.filter(t => !AI_TOOLS.includes(t));
56
+
57
+ if (invalid.length > 0) {
58
+ console.error(chalk.red(`\n✖ Error: Invalid AI tools: ${invalid.join(', ')}`));
59
+ console.error(chalk.gray(` Valid options: ${AI_TOOLS.join(', ')}`));
60
+ process.exit(1);
61
+ }
62
+
63
+ const allTools = AI_TOOLS.filter(t => t !== 'all');
64
+ return tools.includes('all') ? allTools : tools;
65
+ }
66
+
67
+ /**
68
+ * Create the CLI program
69
+ */
70
+ function createProgram(): Command {
71
+ const program = new Command();
72
+
73
+ program
74
+ .name('k0ntext')
75
+ .description('Unified AI Context Engineering - Intelligent context for all AI coding assistants')
76
+ .version(packageJson.version);
77
+
78
+ // ==================== Init Command ====================
79
+ program
80
+ .command('init')
81
+ .description('Initialize AI context for a project with intelligent analysis')
82
+ .argument('[project-name]', 'Name of the project (defaults to current directory)')
83
+ .option('--no-intelligent', 'Skip OpenRouter-powered intelligent analysis')
84
+ .action(async (projectName, options) => {
85
+ showBanner();
86
+
87
+ const targetDir = projectName
88
+ ? path.resolve(process.cwd(), projectName)
89
+ : process.cwd();
90
+
91
+ const spinner = ora();
92
+
93
+ // Check for OpenRouter API key
94
+ const hasApiKey = hasOpenRouterKey();
95
+ if (!hasApiKey && options.intelligent !== false) {
96
+ console.log(chalk.yellow('\n⚠ OPENROUTER_API_KEY not found'));
97
+ console.log(chalk.gray(' Set OPENROUTER_API_KEY for intelligent analysis'));
98
+ console.log(chalk.gray(' Get your key at: https://openrouter.ai/keys\n'));
99
+ console.log(chalk.gray(' Continuing with basic analysis...\n'));
100
+ }
101
+
102
+ try {
103
+ // Create analyzer
104
+ spinner.start('Analyzing project...');
105
+ const analyzer = createIntelligentAnalyzer(targetDir);
106
+
107
+ // Run analysis
108
+ const analysis = await analyzer.analyze();
109
+ spinner.succeed('Analysis complete');
110
+
111
+ // Display results
112
+ console.log(`\n${chalk.bold('Analysis Results:')}`);
113
+ console.log(` ${chalk.cyan('•')} Documents: ${analysis.existingContext.files.filter(f => f.type === 'doc').length} found`);
114
+ console.log(` ${chalk.cyan('•')} Tool Configs: ${analysis.existingContext.tools.length} configured (${analysis.existingContext.tools.join(', ') || 'none'})`);
115
+ console.log(` ${chalk.cyan('•')} Tech Stack: ${analysis.techStack.languages.join(', ') || 'Unknown'}`);
116
+
117
+ if (analyzer.isIntelligentModeAvailable()) {
118
+ console.log(` ${chalk.green('✓')} Intelligent Analysis: Enabled`);
119
+ if (analysis.workflows.length > 0) {
120
+ console.log(` ${chalk.cyan('•')} Workflows Discovered: ${analysis.workflows.length}`);
121
+ }
122
+ } else {
123
+ console.log(` ${chalk.yellow('○')} Intelligent Analysis: Disabled (no API key)`);
124
+ }
125
+
126
+ console.log(`\n${chalk.bold('Summary:')}`);
127
+ console.log(analysis.summary);
128
+
129
+ if (analysis.suggestions.workflows.length > 0) {
130
+ console.log(`\n${chalk.bold('Suggested Workflows to Document:')}`);
131
+ for (const workflow of analysis.suggestions.workflows.slice(0, 5)) {
132
+ console.log(` ${chalk.cyan('•')} ${workflow}`);
133
+ }
134
+ }
135
+
136
+ console.log(`\n${chalk.green('✓')} AI Context initialized successfully!`);
137
+ console.log(`\n${chalk.bold('Next Steps:')}`);
138
+ console.log(` ${chalk.cyan('1.')} Run ${chalk.white('k0ntext stats')} to view database statistics`);
139
+ console.log(` ${chalk.cyan('2.')} Run ${chalk.white('k0ntext mcp')} to start the MCP server`);
140
+ console.log(` ${chalk.cyan('3.')} Run ${chalk.white('k0ntext --help')} to explore all available commands`);
141
+
142
+ } catch (error) {
143
+ spinner.fail('Analysis failed');
144
+ console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
145
+ process.exit(1);
146
+ }
147
+ });
148
+
149
+ // ==================== Generate Command ====================
150
+ program.addCommand(generateCommand);
151
+
152
+ // ==================== MCP Command ====================
153
+ program
154
+ .command('mcp')
155
+ .description('Start the MCP server for AI tools to connect')
156
+ .option('--db <path>', 'Database file path', '.ai-context.db')
157
+ .action(async (options) => {
158
+ const projectRoot = process.cwd();
159
+
160
+ console.error(chalk.cyan('AI Context MCP Server starting...'));
161
+ console.error(chalk.gray(`Project root: ${projectRoot}`));
162
+ console.error(chalk.gray(`Database: ${options.db}`));
163
+
164
+ // Dynamic import of server module
165
+ try {
166
+ const { startServer } = await import('../mcp.js');
167
+ await startServer({
168
+ projectRoot,
169
+ dbPath: options.db
170
+ });
171
+ } catch (error) {
172
+ console.error(chalk.red(`\nError starting MCP server: ${error instanceof Error ? error.message : error}`));
173
+ process.exit(1);
174
+ }
175
+ });
176
+
177
+ // ==================== Sync Command ====================
178
+ program.addCommand(syncCommand);
179
+
180
+ // ==================== Cleanup Command ====================
181
+ program.addCommand(cleanupCommand);
182
+
183
+ // ==================== Validate Command ====================
184
+ program.addCommand(validateCommand);
185
+
186
+ // ==================== Export Command ====================
187
+ program.addCommand(exportCommand);
188
+
189
+ // ==================== Import Command ====================
190
+ program.addCommand(importCommand);
191
+
192
+ // ==================== Performance Command ====================
193
+ program.addCommand(performanceCommand);
194
+
195
+ // ==================== Watch Command ====================
196
+ program.addCommand(watchCommand);
197
+
198
+ // ==================== Index Command ====================
199
+ program
200
+ .command('index')
201
+ .description('Index codebase content into the database')
202
+ .option('--docs', 'Index documentation files only')
203
+ .option('--code', 'Index source code only')
204
+ .option('--tools', 'Index AI tool configurations only')
205
+ .option('--all', 'Index everything (default)')
206
+ .option('-v, --verbose', 'Show detailed output')
207
+ .action(async (options) => {
208
+ showBanner();
209
+
210
+ const spinner = ora();
211
+ let db: any;
212
+
213
+ try {
214
+ spinner.start('Discovering content...');
215
+
216
+ const analyzer = createIntelligentAnalyzer(process.cwd());
217
+ const { DatabaseClient } = await import('../db/client.js');
218
+ db = new DatabaseClient(process.cwd());
219
+
220
+ let discoveredCount = 0;
221
+ let indexedCount = 0;
222
+ const allIndexedFiles: string[] = []; // Track all indexed files for embeddings
223
+
224
+ if (options.all || (!options.docs && !options.code && !options.tools)) {
225
+ // Discover everything
226
+ const [docs, code, tools] = await Promise.all([
227
+ analyzer.discoverDocs(),
228
+ analyzer.discoverCode(),
229
+ analyzer.discoverToolConfigs()
230
+ ]);
231
+ discoveredCount = docs.length + code.length + tools.length;
232
+
233
+ spinner.text = `Indexing ${discoveredCount} files...`;
234
+
235
+ // Store docs in database
236
+ for (const doc of docs) {
237
+ const content = fs.existsSync(doc.path) ? fs.readFileSync(doc.path, 'utf-8').slice(0, 50000) : '';
238
+ db.upsertItem({
239
+ type: 'doc',
240
+ name: path.basename(doc.relativePath),
241
+ content,
242
+ filePath: doc.relativePath,
243
+ metadata: { size: doc.size }
244
+ });
245
+ indexedCount++;
246
+ allIndexedFiles.push(doc.relativePath);
247
+ }
248
+
249
+ // Store tool configs in database
250
+ for (const config of tools) {
251
+ const content = fs.existsSync(config.path) ? fs.readFileSync(config.path, 'utf-8').slice(0, 50000) : '';
252
+ db.upsertItem({
253
+ type: 'tool_config',
254
+ name: `${config.tool}:${path.basename(config.relativePath)}`,
255
+ content,
256
+ filePath: config.relativePath,
257
+ metadata: { tool: config.tool, size: config.size }
258
+ });
259
+ indexedCount++;
260
+ allIndexedFiles.push(config.relativePath);
261
+ }
262
+
263
+ // Store code in database (first N files to avoid overwhelming the db)
264
+ const maxCodeFiles = 100;
265
+ for (const codeFile of code.slice(0, maxCodeFiles)) {
266
+ const content = fs.existsSync(codeFile.path) ? fs.readFileSync(codeFile.path, 'utf-8').slice(0, 20000) : '';
267
+ db.upsertItem({
268
+ type: 'code',
269
+ name: path.basename(codeFile.relativePath),
270
+ content,
271
+ filePath: codeFile.relativePath,
272
+ metadata: { size: codeFile.size }
273
+ });
274
+ indexedCount++;
275
+ allIndexedFiles.push(codeFile.relativePath);
276
+ }
277
+ if (code.length > maxCodeFiles) {
278
+ console.log(chalk.gray(`\nNote: Indexed first ${maxCodeFiles} of ${code.length} code files.`));
279
+ }
280
+ } else {
281
+ if (options.docs) {
282
+ const docs = await analyzer.discoverDocs();
283
+ discoveredCount += docs.length;
284
+ spinner.text = `Indexing ${docs.length} docs...`;
285
+ for (const doc of docs) {
286
+ const content = fs.existsSync(doc.path) ? fs.readFileSync(doc.path, 'utf-8').slice(0, 50000) : '';
287
+ db.upsertItem({
288
+ type: 'doc',
289
+ name: path.basename(doc.relativePath),
290
+ content,
291
+ filePath: doc.relativePath,
292
+ metadata: { size: doc.size }
293
+ });
294
+ indexedCount++;
295
+ allIndexedFiles.push(doc.relativePath);
296
+ }
297
+ }
298
+ if (options.code) {
299
+ const code = await analyzer.discoverCode();
300
+ discoveredCount += code.length;
301
+ const maxCodeFiles = 100;
302
+ spinner.text = `Indexing code files...`;
303
+ for (const codeFile of code.slice(0, maxCodeFiles)) {
304
+ const content = fs.existsSync(codeFile.path) ? fs.readFileSync(codeFile.path, 'utf-8').slice(0, 20000) : '';
305
+ db.upsertItem({
306
+ type: 'code',
307
+ name: path.basename(codeFile.relativePath),
308
+ content,
309
+ filePath: codeFile.relativePath,
310
+ metadata: { size: codeFile.size }
311
+ });
312
+ indexedCount++;
313
+ allIndexedFiles.push(codeFile.relativePath);
314
+ }
315
+ if (code.length > maxCodeFiles) {
316
+ console.log(chalk.gray(`\nNote: Indexed first ${maxCodeFiles} of ${code.length} code files.`));
317
+ }
318
+ }
319
+ if (options.tools) {
320
+ const tools = await analyzer.discoverToolConfigs();
321
+ discoveredCount += tools.length;
322
+ spinner.text = `Indexing ${tools.length} tool configs...`;
323
+ for (const config of tools) {
324
+ const content = fs.existsSync(config.path) ? fs.readFileSync(config.path, 'utf-8').slice(0, 50000) : '';
325
+ db.upsertItem({
326
+ type: 'tool_config',
327
+ name: `${config.tool}:${path.basename(config.relativePath)}`,
328
+ content,
329
+ filePath: config.relativePath,
330
+ metadata: { tool: config.tool, size: config.size }
331
+ });
332
+ indexedCount++;
333
+ allIndexedFiles.push(config.relativePath);
334
+ }
335
+ }
336
+ }
337
+
338
+ // Generate embeddings if OpenRouter is available
339
+ let embeddingsCount = 0;
340
+ if (hasOpenRouterKey() && indexedCount > 0) {
341
+ spinner.text = `Generating embeddings for ${indexedCount} files...`;
342
+
343
+ try {
344
+ const embeddings = await analyzer.generateEmbeddings(
345
+ allIndexedFiles.map(fp => ({
346
+ path: path.resolve(process.cwd(), fp),
347
+ relativePath: fp,
348
+ type: 'code' as const,
349
+ size: 0
350
+ }))
351
+ );
352
+
353
+ spinner.text = `Storing ${embeddings.size} embeddings...`;
354
+ for (const [filePath, embedding] of embeddings.entries()) {
355
+ db.insertEmbedding(filePath, embedding);
356
+ embeddingsCount++;
357
+ }
358
+ } catch (error) {
359
+ spinner.warn(`Indexed ${indexedCount} files (embeddings failed: ${error instanceof Error ? error.message : error})`);
360
+ embeddingsCount = 0;
361
+ }
362
+ }
363
+
364
+ if (embeddingsCount > 0) {
365
+ spinner.succeed(`Discovered ${discoveredCount} files, indexed ${indexedCount} into database, generated ${embeddingsCount} embeddings`);
366
+ } else {
367
+ spinner.succeed(`Discovered ${discoveredCount} files, indexed ${indexedCount} into database`);
368
+ }
369
+
370
+ } catch (error) {
371
+ spinner.fail('Indexing failed');
372
+ console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
373
+ process.exit(1);
374
+ } finally {
375
+ if (db && typeof db.close === 'function') {
376
+ try {
377
+ db.close();
378
+ } catch {
379
+ // Ignore close errors
380
+ }
381
+ }
382
+ }
383
+ });
384
+
385
+ // ==================== Search Command ====================
386
+ program
387
+ .command('search <query>')
388
+ .description('Search across indexed content')
389
+ .option('-t, --type <type>', 'Filter by type (workflow, agent, command, code, doc)')
390
+ .option('-l, --limit <n>', 'Maximum results', '10')
391
+ .option('-m, --mode <mode>', 'Search mode: text, semantic, hybrid (default: hybrid)', 'hybrid')
392
+ .action(async (query, options) => {
393
+ const spinner = ora();
394
+ let db: any;
395
+
396
+ try {
397
+ const limit =
398
+ typeof options.limit === 'string'
399
+ ? Number.parseInt(options.limit, 10) || 10
400
+ : 10;
401
+
402
+ const mode = options.mode || 'hybrid';
403
+
404
+ spinner.start('Searching...');
405
+
406
+ const { DatabaseClient } = await import('../db/client.js');
407
+ db = new DatabaseClient(process.cwd());
408
+
409
+ let items: Array<{ type: string; name?: string; id?: string; filePath?: string }>;
410
+
411
+ if (mode === 'semantic') {
412
+ // Semantic search requires query embedding
413
+ const { createIntelligentAnalyzer } = await import('../analyzer/intelligent-analyzer.js');
414
+ const analyzer = createIntelligentAnalyzer(process.cwd());
415
+
416
+ if (!analyzer.isIntelligentModeAvailable()) {
417
+ spinner.fail('Semantic search requires OPENROUTER_API_KEY');
418
+ process.exit(1);
419
+ }
420
+
421
+ const queryEmbedding = await analyzer.embedText(query);
422
+ const results = db.searchByEmbedding(queryEmbedding, limit);
423
+ items = results.map((r: { item: { type: string; name?: string; id?: string; filePath?: string } }) => r.item);
424
+ } else if (mode === 'text') {
425
+ // Pure text search
426
+ const results = db.searchText(query, options.type);
427
+ items = Array.isArray(results) ? results.slice(0, limit) : [];
428
+ } else {
429
+ // Hybrid search (default)
430
+ const { createIntelligentAnalyzer } = await import('../analyzer/intelligent-analyzer.js');
431
+ const analyzer = createIntelligentAnalyzer(process.cwd());
432
+
433
+ let queryEmbedding: number[] | null = null;
434
+ if (analyzer.isIntelligentModeAvailable()) {
435
+ queryEmbedding = await analyzer.embedText(query);
436
+ }
437
+
438
+ const results = db.hybridSearch(query, queryEmbedding, { limit, type: options.type });
439
+ // Unwrap items from { item, similarity } structure
440
+ items = Array.isArray(results) ? results.slice(0, limit).map((r: { item: { type: string; name?: string; id?: string; filePath?: string } }) => r.item) : [];
441
+ }
442
+
443
+ spinner.stop();
444
+
445
+ if (items.length === 0) {
446
+ console.log(chalk.yellow('\nNo matching results found.'));
447
+ return;
448
+ }
449
+
450
+ console.log(chalk.bold(`\nSearch results for "${query}":`));
451
+
452
+ for (const [index, item] of items.entries()) {
453
+ const idx = chalk.cyan(`#${index + 1}`);
454
+ const title = item.name || item.id || '(untitled)';
455
+ const typeLabel = item.type ? String(item.type) : 'item';
456
+ const pathInfo = item.filePath ? chalk.gray(` (${item.filePath})`) : '';
457
+
458
+ console.log(` ${idx} ${chalk.bold(String(title))} [${typeLabel}]${pathInfo}`);
459
+ }
460
+
461
+ } catch (error) {
462
+ spinner.fail('Search failed');
463
+ console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
464
+ process.exit(1);
465
+ } finally {
466
+ if (db && typeof db.close === 'function') {
467
+ try {
468
+ db.close();
469
+ } catch {
470
+ // Ignore close errors
471
+ }
472
+ }
473
+ }
474
+ });
475
+
476
+ // ==================== Stats Command ====================
477
+ program
478
+ .command('stats')
479
+ .description('Show database and indexing statistics')
480
+ .action(async () => {
481
+ showBanner();
482
+
483
+ try {
484
+ const { DatabaseClient } = await import('../db/client.js');
485
+ const db = new DatabaseClient(process.cwd());
486
+
487
+ const stats = db.getStats();
488
+
489
+ console.log(`${chalk.bold('Database Statistics:')}`);
490
+ console.log(` ${chalk.cyan('•')} Context Items: ${stats.items}`);
491
+ console.log(` ${chalk.cyan('•')} Relations: ${stats.relations}`);
492
+ console.log(` ${chalk.cyan('•')} Git Commits: ${stats.commits}`);
493
+ console.log(` ${chalk.cyan('•')} Embeddings: ${stats.embeddings}`);
494
+ console.log(` ${chalk.cyan('•')} Tool Configs: ${stats.toolConfigs}`);
495
+ console.log(` ${chalk.cyan('•')} Database Path: ${db.getPath()}`);
496
+
497
+ db.close();
498
+
499
+ } catch (error) {
500
+ console.error(chalk.red(`\nError: ${error instanceof Error ? error.message : error}`));
501
+ process.exit(1);
502
+ }
503
+ });
504
+
505
+ return program;
506
+ }
507
+
508
+ // Main entry point
509
+ const program = createProgram();
510
+ program.parse();