brainbank 0.9.1 → 0.9.4

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.
package/bin/brainbank CHANGED
@@ -11,7 +11,7 @@ ROOT="$DIR/.."
11
11
 
12
12
  # Use compiled dist if available (npm install), fall back to tsx for development
13
13
  if [ -f "$ROOT/dist/cli.js" ]; then
14
- exec node "$ROOT/dist/cli.js" "$@"
14
+ exec node --disable-warning=ExperimentalWarning "$ROOT/dist/cli.js" "$@"
15
15
  else
16
16
  export TSX_TSCONFIG_PATH="$ROOT/tsconfig.json"
17
17
  exec "$ROOT/node_modules/.bin/tsx" "$ROOT/src/cli/index.ts" "$@"
package/dist/cli.js CHANGED
@@ -59,7 +59,7 @@ function buildBrainbankMcpBlock(config) {
59
59
  if (openaiKey) env.OPENAI_API_KEY = openaiKey;
60
60
  const block = {
61
61
  command: nodeBin,
62
- args: [resolvedCliJs, "mcp"]
62
+ args: ["--disable-warning=ExperimentalWarning", resolvedCliJs, "mcp"]
63
63
  };
64
64
  if (Object.keys(env).length > 0) {
65
65
  block.env = env;
@@ -108,9 +108,68 @@ async function autoExportMcp(repoPath) {
108
108
  console.log(` ${c.green("\u2713")} Exported MCP config to ${c.dim(path.relative(process.env.HOME ?? "", target.configPath))}`);
109
109
  }
110
110
  __name(autoExportMcp, "autoExportMcp");
111
+ var BRAINBANK_SECTION_MARKER = "<!-- brainbank:start -->";
112
+ var BRAINBANK_SECTION_END = "<!-- brainbank:end -->";
113
+ var GLOBAL_GEMINI = path.join(process.env.HOME ?? "~", ".gemini", "GEMINI.md");
114
+ function buildGeminiSection() {
115
+ return `${BRAINBANK_SECTION_MARKER}
116
+
117
+ ## BrainBank \u2014 Code Intelligence
118
+
119
+ When \`brainbank_context\` and \`brainbank_files\` MCP tools are available, **always use them instead of \`grep_search\` or \`list_dir\`**.
120
+
121
+ **\`brainbank_context\`** \u2014 semantic search. Use \`path:\` to scope, \`compact: false\`, \`sources: { code: 25, docs: 0, git: 0 }\`.
122
+
123
+ **\`brainbank_files\`** \u2014 read full indexed files (\`lines: true\` always). Only works with files tracked by the index \u2014 for \`.env\`, \`docker-compose.yml\`, etc. use \`view_file\`.
124
+
125
+ **Sources rule:** Default to code-only (\`docs: 0\`). Only add \`docs\` when the user explicitly asks about documentation. Never mix code and docs in the same query \u2014 fire separate queries.
126
+
127
+ ### Output handling (critical)
128
+
129
+ BrainBank may return results **inline** or save them to an **output file**:
130
+
131
+ - **Inline:** read and proceed normally.
132
+ - **File result** (saved to \`output.txt\`): show the path as a clickable link, ask user to paste, then **STOP and WAIT**:
133
+
134
+ \u{1F4CB} Output: [output.txt](file:///path/to/output.txt) \u2014 _"Could you paste the context output here?"_
135
+
136
+ Do **NOT** read the file yourself. Wait for the paste before proceeding.
137
+
138
+ ${BRAINBANK_SECTION_END}
139
+ `;
140
+ }
141
+ __name(buildGeminiSection, "buildGeminiSection");
142
+ function hasGeminiSection(geminiPath) {
143
+ if (!fs.existsSync(geminiPath)) return false;
144
+ const content = fs.readFileSync(geminiPath, "utf-8");
145
+ return content.includes(BRAINBANK_SECTION_MARKER);
146
+ }
147
+ __name(hasGeminiSection, "hasGeminiSection");
148
+ function appendGeminiSection(geminiPath) {
149
+ const section = buildGeminiSection();
150
+ if (fs.existsSync(geminiPath)) {
151
+ fs.appendFileSync(geminiPath, section);
152
+ } else {
153
+ fs.writeFileSync(geminiPath, `# GEMINI.md
154
+ ${section}`);
155
+ }
156
+ }
157
+ __name(appendGeminiSection, "appendGeminiSection");
158
+ function replaceGeminiSection(geminiPath) {
159
+ const content = fs.readFileSync(geminiPath, "utf-8");
160
+ const startIdx = content.indexOf(BRAINBANK_SECTION_MARKER);
161
+ const endIdx = content.indexOf(BRAINBANK_SECTION_END);
162
+ if (startIdx === -1 || endIdx === -1) return;
163
+ const before = content.slice(0, startIdx);
164
+ const after = content.slice(endIdx + BRAINBANK_SECTION_END.length);
165
+ const section = buildGeminiSection();
166
+ fs.writeFileSync(geminiPath, before + section + after);
167
+ }
168
+ __name(replaceGeminiSection, "replaceGeminiSection");
111
169
  async function cmdMcpExport() {
112
170
  const targetName = args[1] || getFlag("target") || "antigravity";
113
171
  const repoPath = getFlag("repo") || ".";
172
+ const { confirm } = await import("@inquirer/prompts");
114
173
  const target = TARGETS[targetName];
115
174
  if (!target) {
116
175
  console.error(c.red(`Unknown export target: ${targetName}`));
@@ -119,18 +178,44 @@ async function cmdMcpExport() {
119
178
  }
120
179
  const config = await getConfig(repoPath);
121
180
  const block = buildBrainbankMcpBlock(config);
122
- const { created } = mergeAndWrite(target.configPath, block);
123
181
  console.log(c.bold(`
124
182
  \u2501\u2501\u2501 MCP Export: ${target.label} \u2501\u2501\u2501
125
183
  `));
126
- console.log(` ${c.green("\u2713")} ${created ? "Created" : "Updated"} ${c.dim(target.configPath)}`);
127
- console.log(` ${c.dim("Node:")} ${block.command}`);
128
- console.log(` ${c.dim("CLI:")} ${block.args[0]}`);
129
- const envKeys = block.env ? Object.keys(block.env) : [];
130
- if (envKeys.length > 0) {
131
- console.log(` ${c.dim("Keys:")} ${envKeys.join(", ")}`);
184
+ const mcpExists = hasBrainbankMcpEntry(target.configPath);
185
+ let writeMcp = true;
186
+ if (mcpExists) {
187
+ console.log(` ${c.yellow("\u25CF")} MCP config already has brainbank entry`);
188
+ const cliPath = block.args.find((a) => !a.startsWith("--")) ?? block.args[0];
189
+ console.log(` ${c.dim(" New:")} ${block.command} ${cliPath}`);
190
+ const envKeys = block.env ? Object.keys(block.env) : [];
191
+ if (envKeys.length > 0) console.log(` ${c.dim(" Keys:")} ${envKeys.join(", ")}`);
192
+ writeMcp = await confirm({ message: "Override existing brainbank MCP entry?", default: true });
193
+ }
194
+ if (writeMcp) {
195
+ const { created } = mergeAndWrite(target.configPath, block);
196
+ console.log(` ${c.green("\u2713")} ${created ? "Created" : "Updated"} ${c.dim(target.configPath)}`);
132
197
  } else {
133
- console.log(` ${c.yellow("\u26A0")} No API keys found. Set env vars or add keys to .brainbank/config.json`);
198
+ console.log(` ${c.dim("MCP config \u2014 skipped")}`);
199
+ }
200
+ const geminiHasSection = hasGeminiSection(GLOBAL_GEMINI);
201
+ if (geminiHasSection) {
202
+ console.log(` ${c.yellow("\u25CF")} ~/.gemini/GEMINI.md already has BrainBank section`);
203
+ const override = await confirm({ message: "Override existing BrainBank section?", default: false });
204
+ if (override) {
205
+ replaceGeminiSection(GLOBAL_GEMINI);
206
+ console.log(` ${c.green("\u2713")} Replaced BrainBank section in ${c.dim("~/.gemini/GEMINI.md")}`);
207
+ } else {
208
+ console.log(` ${c.dim("GEMINI.md \u2014 skipped")}`);
209
+ }
210
+ } else {
211
+ const addGemini = await confirm({
212
+ message: "Add BrainBank instructions to ~/.gemini/GEMINI.md? (teaches AI tools how to use BrainBank)",
213
+ default: true
214
+ });
215
+ if (addGemini) {
216
+ appendGeminiSection(GLOBAL_GEMINI);
217
+ console.log(` ${c.green("\u2713")} Added BrainBank section to ${c.dim("~/.gemini/GEMINI.md")}`);
218
+ }
134
219
  }
135
220
  console.log(`
136
221
  ${c.dim("Restart your IDE to apply changes.")}
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/index.ts","../src/cli/commands/mcp-export.ts","../src/cli/commands/scan.ts","../src/cli/commands/collection.ts","../src/cli/commands/kv.ts","../src/cli/commands/docs.ts","../src/cli/commands/search.ts","../src/cli/server-client.ts","../src/cli/commands/context.ts","../src/cli/commands/files.ts","../src/cli/commands/stats.ts","../src/cli/commands/reembed.ts","../src/cli/commands/watch.ts","../src/cli/commands/mcp.ts","../src/cli/commands/daemon.ts","../src/cli/commands/status.ts","../src/cli/commands/help.ts","../src/cli/index.ts"],"sourcesContent":["/**\n * brainbank index [path] — Interactive scan → select → index\n *\n * Scans the repo first, shows a summary tree, and prompts the user\n * with checkboxes to select which modules to index. Use --yes to skip.\n */\n\nimport type { ScanResult, ScanModule } from './scan.ts';\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { c, args, getFlag, hasFlag, stripFlags } from '@/cli/utils.ts';\nimport { createBrain, getConfig, registerConfigCollections } from '@/cli/factory/index.ts';\nimport { findDocsPlugin } from '@/cli/utils.ts';\nimport { autoExportMcp } from './mcp-export.ts';\nimport { scanRepo } from './scan.ts';\n\nexport async function cmdIndex(): Promise<void> {\n const positional = stripFlags(args);\n const repoPath = positional[1] || '.';\n const force = hasFlag('force');\n const depth = parseInt(getFlag('depth') || '500', 10);\n const onlyRaw = getFlag('only');\n const docsPath = getFlag('docs');\n const skipPrompt = hasFlag('yes') || hasFlag('y');\n\n\n const scan = scanRepo(repoPath);\n printScanTree(scan, depth);\n\n\n let modules: string[];\n\n if (onlyRaw) {\n // --only flag: explicit module selection\n modules = onlyRaw.split(',').map(s => s.trim());\n } else if (scan.config.plugins && scan.config.plugins.length > 0) {\n // Config exists with plugins field — use it as source of truth\n modules = scan.config.plugins;\n console.log(c.dim(`\\n Using config: plugins = [${modules.join(', ')}]\\n`));\n } else if (skipPrompt) {\n modules = buildDefaultModules(scan);\n } else {\n modules = await promptModules(scan);\n if (modules.length === 0) {\n console.log(c.dim('\\n Nothing selected. Exiting.\\n'));\n return;\n }\n\n // Clean screen and show selection summary\n console.clear();\n console.log(c.bold('\\n━━━ BrainBank ━━━\\n'));\n console.log(' Selected modules:');\n for (const m of modules) {\n console.log(` ${c.green('✓')} ${m}`);\n }\n console.log('');\n }\n\n // If --docs is passed, auto-include 'docs' in modules\n if (docsPath && !modules.includes('docs')) {\n modules.push('docs');\n }\n\n // Auto-generate config.json if it doesn't exist yet\n if (!scan.config.exists && !skipPrompt) {\n await saveConfig(scan.repoPath, modules);\n }\n\n\n console.log(c.bold(`\\n━━━ Indexing: ${modules.join(', ')} ━━━`));\n\n const brain = await createBrain(repoPath);\n await brain.initialize();\n\n const config = await getConfig(repoPath);\n await registerConfigCollections(brain, repoPath, config);\n\n if (docsPath) {\n const absDocsPath = path.resolve(docsPath);\n const collName = path.basename(absDocsPath);\n try {\n const docsPlugin = findDocsPlugin(brain);\n await docsPlugin?.addCollection({\n name: collName,\n path: absDocsPath,\n pattern: '**/*.md',\n ignore: ['deprecated/**', 'node_modules/**'],\n });\n console.log(c.dim(` Registered docs collection: ${collName}`));\n } catch {\n console.log(c.yellow(` Warning: docs module not loaded, skipping --docs`));\n }\n }\n\n const result = await brain.index({\n modules,\n forceReindex: force,\n pluginOptions: { depth },\n onProgress: (stage, msg) => {\n process.stdout.write(`\\r ${c.cyan(stage.toUpperCase())} ${msg} `);\n },\n });\n\n console.log('\\n');\n for (const [name, value] of Object.entries(result)) {\n if (!value) continue;\n const v = value as Record<string, unknown>;\n if (typeof v.indexed === 'number') {\n const parts = [`${v.indexed} indexed`, `${v.skipped ?? 0} skipped`];\n if (typeof v.chunks === 'number') parts.push(`${v.chunks} chunks`);\n if (typeof v.removed === 'number' && v.removed > 0) parts.push(`${v.removed} removed`);\n console.log(` ${c.green(name)}: ${parts.join(', ')}`);\n } else {\n console.log(` ${c.green(name)}: done`);\n }\n }\n\n const stats = brain.stats();\n console.log(`\\n ${c.bold('Totals')}:`);\n for (const [name, s] of Object.entries(stats)) {\n if (!s || typeof s !== 'object') continue;\n const entries = Object.entries(s as Record<string, unknown>)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ');\n console.log(` ${name}: ${entries}`);\n }\n\n brain.close();\n\n // Auto-export MCP config to Antigravity if detected and not already configured\n await autoExportMcp(repoPath);\n}\n\n\nfunction printScanTree(scan: ScanResult, depth: number): void {\n console.clear();\n console.log(c.bold('\\n━━━ BrainBank Scan ━━━'));\n console.log(c.dim(` Repo: ${scan.repoPath}`));\n\n // Multi-repo detection\n if (scan.gitSubdirs.length > 0) {\n console.log(c.cyan(`\\n 🔀 Multi-repo — ${scan.gitSubdirs.length} git repos detected`));\n for (const sub of scan.gitSubdirs) {\n console.log(c.dim(` └── ${sub.name}`));\n }\n }\n\n // Dynamic module display\n for (const mod of scan.modules) {\n console.log('');\n if (mod.available) {\n const extra = mod.name === 'git' ? ` (depth: ${depth})` : '';\n console.log(` ${mod.icon} ${c.bold(capitalizeFirst(mod.name))} — ${mod.summary}${extra}`);\n if (mod.details) {\n for (const d of mod.details) {\n console.log(c.dim(` ${d}`));\n }\n }\n } else {\n console.log(` ${mod.icon} ${c.dim(`${capitalizeFirst(mod.name)} — ${mod.summary}`)}`);\n }\n }\n\n // Config ignore\n if (scan.config.ignore?.length) {\n console.log(c.dim(` Ignore: ${scan.config.ignore.join(', ')}`));\n }\n\n // Config & DB\n console.log('');\n if (scan.config.exists) {\n console.log(` ⚙️ ${c.dim('Config:')} .brainbank/config.json ${c.green('✓')}`);\n }\n if (scan.db?.exists) {\n const ago = scan.db.lastModified ? timeSince(scan.db.lastModified) : '';\n console.log(` 💾 ${c.dim('DB:')} ${scan.db.sizeMB} MB${ago ? `, last indexed ${ago}` : ''}`);\n } else {\n console.log(` 💾 ${c.dim('DB: new (first index)')}`);\n }\n console.log('');\n}\n\n\n/** Build the default list of available modules based on scan. */\nfunction buildDefaultModules(scan: ScanResult): string[] {\n return scan.modules.filter(m => m.available && m.checked).map(m => m.name);\n}\n\n/** Interactive checkbox prompt via @inquirer/prompts. */\nasync function promptModules(scan: ScanResult): Promise<string[]> {\n const { checkbox } = await import('@inquirer/prompts');\n console.log(c.dim(' ─────────────────────────────────────────\\n'));\n\n const choices = scan.modules.map((m: ScanModule) => ({\n name: `${capitalizeFirst(m.name).padEnd(6)} — ${m.summary}`,\n value: m.name,\n checked: m.checked && m.available,\n disabled: m.available ? undefined : m.disabled,\n }));\n\n return checkbox<string>({\n message: 'Select modules to index:\\n',\n choices,\n });\n}\n\n\nfunction timeSince(date: Date): string {\n const seconds = Math.floor((Date.now() - date.getTime()) / 1000);\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n\n/** Capitalize first letter. */\nfunction capitalizeFirst(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/** Generate .brainbank/config.json from the selected modules. */\nasync function saveConfig(repoPath: string, modules: string[]): Promise<void> {\n const { select, confirm } = await import('@inquirer/prompts');\n\n // Embedding provider selection\n const envEmbedding = process.env.BRAINBANK_EMBEDDING;\n const embedding = await select<string>({\n message: 'Embedding provider:',\n choices: [\n {\n name: 'perplexity-context — best accuracy (recommended)',\n value: 'perplexity-context',\n },\n {\n name: 'perplexity — fast, high quality',\n value: 'perplexity',\n },\n {\n name: 'openai — text-embedding-3-small',\n value: 'openai',\n },\n {\n name: 'local — offline, no API key needed',\n value: 'local',\n },\n ],\n default: envEmbedding ?? 'perplexity-context',\n });\n\n // Pruner selection\n const pruner = await select<string>({\n message: 'Noise pruner:',\n choices: [\n {\n name: 'haiku — AI-powered noise filter (recommended)',\n value: 'haiku',\n },\n {\n name: 'none — no pruning',\n value: 'none',\n },\n ],\n default: 'haiku',\n });\n\n const configDir = path.join(repoPath, '.brainbank');\n const configPath = path.join(configDir, 'config.json');\n\n const config: Record<string, unknown> = {\n plugins: modules,\n embedding,\n };\n\n if (pruner !== 'none') {\n config.pruner = pruner;\n }\n\n // Key management: detect available keys and offer to save\n const detectedKeys: Record<string, string> = {};\n const needsPerplexity = embedding.startsWith('perplexity');\n const needsAnthropic = pruner === 'haiku';\n const needsOpenai = embedding === 'openai';\n\n if (needsPerplexity && process.env.PERPLEXITY_API_KEY) {\n detectedKeys.perplexity = process.env.PERPLEXITY_API_KEY;\n }\n if (needsAnthropic && process.env.ANTHROPIC_API_KEY) {\n detectedKeys.anthropic = process.env.ANTHROPIC_API_KEY;\n }\n if (needsOpenai && process.env.OPENAI_API_KEY) {\n detectedKeys.openai = process.env.OPENAI_API_KEY;\n }\n\n if (Object.keys(detectedKeys).length > 0) {\n const keyNames = Object.keys(detectedKeys).join(', ');\n const saveKeys = await confirm({\n message: `Save API keys (${keyNames}) to config.json? (portable, no env vars needed)`,\n default: true,\n });\n if (saveKeys) {\n config.keys = detectedKeys;\n }\n }\n\n fs.mkdirSync(configDir, { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n');\n console.log(c.green(` ✓ Saved ${path.relative(process.cwd(), configPath)}`));\n}\n\n","/**\n * brainbank mcp:export [target] — Export MCP server config for AI IDEs.\n *\n * Generates the MCP server config block for brainbank and merges it into\n * the target IDE's config file. Currently supports: antigravity.\n *\n * Detects: node path, cli.js path, API keys from config or env vars.\n */\n\nimport type { ProjectConfig } from '@/cli/factory/config-loader.ts';\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { c, args, getFlag } from '@/cli/utils.ts';\nimport { getConfig } from '@/cli/factory/index.ts';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/** Supported export targets and their config file paths. */\nconst TARGETS: Record<string, { configPath: string; label: string }> = {\n antigravity: {\n configPath: path.join(process.env.HOME ?? '~', '.gemini', 'antigravity', 'mcp_config.json'),\n label: 'Gemini Antigravity',\n },\n};\n\ninterface McpServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\n\ninterface McpConfig {\n mcpServers: Record<string, McpServerConfig>;\n}\n\n/**\n * Build the brainbank MCP server config block.\n * Resolves node binary, dist/cli.js path, and API keys.\n */\nfunction buildBrainbankMcpBlock(config: ProjectConfig | null): McpServerConfig {\n const nodeBin = process.execPath;\n\n // Resolve dist/cli.js from the global install location (node_prefix/lib/node_modules/brainbank/dist/cli.js)\n const globalCliJs = path.join(path.dirname(nodeBin), '..', 'lib', 'node_modules', 'brainbank', 'dist', 'cli.js');\n // Fallback: relative to this file (dev / npm link)\n const localCliJs = path.resolve(__dirname, '..', '..', 'dist', 'cli.js');\n const resolvedCliJs = fs.existsSync(globalCliJs) ? globalCliJs : localCliJs;\n\n const env: Record<string, string> = {};\n\n // Resolve API keys: config.keys > env vars\n const keys = config?.keys;\n const perplexityKey = keys?.perplexity ?? process.env.PERPLEXITY_API_KEY;\n const anthropicKey = keys?.anthropic ?? process.env.ANTHROPIC_API_KEY;\n const openaiKey = keys?.openai ?? process.env.OPENAI_API_KEY;\n\n if (perplexityKey) env.PERPLEXITY_API_KEY = perplexityKey;\n if (anthropicKey) env.ANTHROPIC_API_KEY = anthropicKey;\n if (openaiKey) env.OPENAI_API_KEY = openaiKey;\n\n const block: McpServerConfig = {\n command: nodeBin,\n args: [resolvedCliJs, 'mcp'],\n };\n\n if (Object.keys(env).length > 0) {\n block.env = env;\n }\n\n return block;\n}\n\n/**\n * Load existing MCP config, merge brainbank entry, and write back.\n * Preserves all other server entries.\n */\nfunction mergeAndWrite(targetPath: string, block: McpServerConfig): { created: boolean } {\n let existing: McpConfig = { mcpServers: {} };\n const created = !fs.existsSync(targetPath);\n\n if (!created) {\n try {\n const raw = fs.readFileSync(targetPath, 'utf-8');\n existing = JSON.parse(raw) as McpConfig;\n if (!existing.mcpServers) existing.mcpServers = {};\n } catch {\n // Corrupt or empty file — start fresh\n existing = { mcpServers: {} };\n }\n }\n\n existing.mcpServers.brainbank = block;\n\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, JSON.stringify(existing, null, 2) + '\\n');\n\n return { created };\n}\n\n/** Check if an MCP config already has a brainbank entry. */\nexport function hasBrainbankMcpEntry(targetPath: string): boolean {\n if (!fs.existsSync(targetPath)) return false;\n try {\n const raw = fs.readFileSync(targetPath, 'utf-8');\n const config = JSON.parse(raw) as McpConfig;\n return !!config.mcpServers?.brainbank;\n } catch {\n return false;\n }\n}\n\n/** Auto-export: called after index when Antigravity is detected. */\nexport async function autoExportMcp(repoPath: string): Promise<void> {\n const target = TARGETS.antigravity;\n if (!target) return;\n\n // Only auto-export if Antigravity dir exists\n const antigravityDir = path.dirname(target.configPath);\n if (!fs.existsSync(antigravityDir)) return;\n\n // Only auto-export if brainbank isn't already configured\n if (hasBrainbankMcpEntry(target.configPath)) return;\n\n const config = await getConfig(repoPath);\n const block = buildBrainbankMcpBlock(config);\n mergeAndWrite(target.configPath, block);\n console.log(` ${c.green('✓')} Exported MCP config to ${c.dim(path.relative(process.env.HOME ?? '', target.configPath))}`);\n}\n\n/** CLI command: brainbank mcp:export [target] */\nexport async function cmdMcpExport(): Promise<void> {\n const targetName = args[1] || getFlag('target') || 'antigravity';\n const repoPath = getFlag('repo') || '.';\n\n const target = TARGETS[targetName];\n if (!target) {\n console.error(c.red(`Unknown export target: ${targetName}`));\n console.error(c.dim(` Available: ${Object.keys(TARGETS).join(', ')}`));\n process.exit(1);\n }\n\n const config = await getConfig(repoPath);\n const block = buildBrainbankMcpBlock(config);\n const { created } = mergeAndWrite(target.configPath, block);\n\n console.log(c.bold(`\\n━━━ MCP Export: ${target.label} ━━━\\n`));\n console.log(` ${c.green('✓')} ${created ? 'Created' : 'Updated'} ${c.dim(target.configPath)}`);\n console.log(` ${c.dim('Node:')} ${block.command}`);\n console.log(` ${c.dim('CLI:')} ${block.args[0]}`);\n\n const envKeys = block.env ? Object.keys(block.env) : [];\n if (envKeys.length > 0) {\n console.log(` ${c.dim('Keys:')} ${envKeys.join(', ')}`);\n } else {\n console.log(` ${c.yellow('⚠')} No API keys found. Set env vars or add keys to .brainbank/config.json`);\n }\n\n console.log(`\\n ${c.dim('Restart your IDE to apply changes.')}\\n`);\n}\n","/**\n * brainbank scan — Lightweight repo scanner for the interactive index flow.\n *\n * Scans the filesystem WITHOUT initializing BrainBank. Returns a ScanResult\n * describing what's available to index via dynamic ScanModule descriptors.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { SUPPORTED_EXTENSIONS, isIgnoredDir, isIgnoredFile } from '@/lib/languages.ts';\n\n\n/** A single scannable module (plugin). */\nexport interface ScanModule {\n /** Plugin name (e.g. 'code', 'git', 'docs'). */\n name: string;\n /** Whether there's content available to index. */\n available: boolean;\n /** Human-readable summary (e.g. '1243 files (5 languages)'). */\n summary: string;\n /** Emoji icon for display. */\n icon: string;\n /** Whether checked by default in the prompt. */\n checked: boolean;\n /** Reason this module is disabled (shown in prompt). */\n disabled?: string;\n /** Detail lines for the scan tree (e.g. per-language breakdown). */\n details?: string[];\n}\n\nexport interface ScanResult {\n repoPath: string;\n modules: ScanModule[];\n config: { exists: boolean; ignore?: string[]; plugins?: string[] };\n db: { exists: boolean; sizeMB: number; lastModified?: Date } | null;\n gitSubdirs: { name: string }[];\n}\n\n\n/** Scan a repo path and return what's available to index. */\nexport function scanRepo(repoPath: string): ScanResult {\n const resolved = path.resolve(repoPath);\n const gitSubdirs = scanGitSubdirs(resolved);\n\n return {\n repoPath: resolved,\n modules: scanModules(resolved, gitSubdirs),\n config: scanConfig(resolved),\n db: scanDb(resolved),\n gitSubdirs,\n };\n}\n\n/** Produce ScanModule descriptors for known plugin types. */\nfunction scanModules(repoPath: string, gitSubdirs: { name: string }[]): ScanModule[] {\n return [\n scanCodeModule(repoPath),\n scanGitModule(repoPath, gitSubdirs),\n scanDocsModule(repoPath),\n ];\n}\n\n\n/** Scan for indexable code files. */\nfunction scanCodeModule(repoPath: string): ScanModule {\n const byLanguage = new Map<string, number>();\n let total = 0;\n\n function walk(dir: string): void {\n let entries: fs.Dirent[];\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\n catch { return; }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const isDir = entry.isDirectory() || (entry.isSymbolicLink() && (() => { try { return fs.statSync(fullPath).isDirectory(); } catch { return false; } })());\n if (isDir) {\n if (isIgnoredDir(entry.name)) continue;\n walk(fullPath);\n } else if (entry.isFile()) {\n if (isIgnoredFile(entry.name)) continue;\n const ext = path.extname(entry.name).toLowerCase();\n const lang = SUPPORTED_EXTENSIONS[ext];\n if (!lang) continue;\n byLanguage.set(lang, (byLanguage.get(lang) ?? 0) + 1);\n total++;\n }\n }\n }\n\n walk(repoPath);\n\n if (total === 0) {\n return { name: 'code', available: false, summary: 'no supported source files found', icon: '📁', checked: false, disabled: 'nothing to index' };\n }\n\n const langCount = byLanguage.size;\n const sorted = [...byLanguage.entries()].sort((a, b) => b[1] - a[1]);\n const maxShow = 7;\n const shown = sorted.slice(0, maxShow);\n const remaining = sorted.length - maxShow;\n\n const details: string[] = [];\n for (let i = 0; i < shown.length; i++) {\n const [lang, count] = shown[i];\n const isLast = i === shown.length - 1 && remaining <= 0;\n const prefix = isLast ? '└──' : '├──';\n details.push(`${prefix} ${lang.padEnd(14)} ${count} files`);\n }\n if (remaining > 0) {\n details.push(`└── ...and ${remaining} more`);\n }\n\n return {\n name: 'code',\n available: true,\n summary: `${total} files (${langCount} language${langCount > 1 ? 's' : ''})`,\n icon: '📁',\n checked: true,\n details,\n };\n}\n\n/** Scan for git history. */\nfunction scanGitModule(repoPath: string, gitSubdirs: { name: string }[]): ScanModule {\n const stats = scanGitStats(repoPath, gitSubdirs);\n\n if (!stats) {\n return { name: 'git', available: false, summary: 'no .git directory found', icon: '📜', checked: false, disabled: 'not a git repo' };\n }\n\n const details: string[] = [];\n if (stats.lastMessage) {\n details.push(`Last: ${stats.lastMessage} (${stats.lastDate})`);\n }\n\n return {\n name: 'git',\n available: true,\n summary: `${stats.commitCount.toLocaleString()} commits`,\n icon: '📜',\n checked: true,\n details,\n };\n}\n\n/** Scan for document collections. */\nfunction scanDocsModule(repoPath: string): ScanModule {\n const collections = scanDocsCollections(repoPath);\n\n if (collections.length === 0) {\n return { name: 'docs', available: false, summary: 'no documents found', icon: '📄', checked: false, disabled: 'no .md/.mdx files' };\n }\n\n const totalFiles = collections.reduce((s, d) => s + d.fileCount, 0);\n const details = collections.map((d, i) => {\n const isLast = i === collections.length - 1;\n const prefix = isLast ? '└──' : '├──';\n return `${prefix} ${d.name.padEnd(10)} → ${d.path} (${d.fileCount} files)`;\n });\n\n return {\n name: 'docs',\n available: true,\n summary: `${collections.length} collection${collections.length > 1 ? 's' : ''} (${totalFiles} files)`,\n icon: '📄',\n checked: true,\n details,\n };\n}\n\n\n/** Get git stats. Supports single repo and multi-repo aggregation. */\nfunction scanGitStats(repoPath: string, gitSubdirs: { name: string }[]): { commitCount: number; lastMessage: string; lastDate: string } | null {\n if (fs.existsSync(path.join(repoPath, '.git'))) {\n return gitStats(repoPath);\n }\n\n if (gitSubdirs.length === 0) return null;\n\n let totalCommits = 0;\n let latestMessage = '';\n let latestDate = '';\n\n for (const sub of gitSubdirs) {\n const stats = gitStats(path.join(repoPath, sub.name));\n if (stats) {\n totalCommits += stats.commitCount;\n if (!latestMessage) {\n latestMessage = stats.lastMessage;\n latestDate = stats.lastDate;\n }\n }\n }\n\n return totalCommits > 0\n ? { commitCount: totalCommits, lastMessage: latestMessage, lastDate: latestDate }\n : null;\n}\n\n/** Get git stats for a single directory. */\nfunction gitStats(dir: string): { commitCount: number; lastMessage: string; lastDate: string } | null {\n try {\n const count = parseInt(execSync('git rev-list --count HEAD', { cwd: dir, encoding: 'utf-8' }).trim(), 10);\n const log = execSync('git log -1 --format=\"%s|%ar\"', { cwd: dir, encoding: 'utf-8' }).trim();\n const [lastMessage, lastDate] = log.split('|');\n return { commitCount: count, lastMessage: lastMessage ?? '', lastDate: lastDate ?? '' };\n } catch {\n return null;\n }\n}\n\n/** Scan for document collections (config + auto-detect). */\nfunction scanDocsCollections(repoPath: string): { name: string; path: string; fileCount: number }[] {\n const results: { name: string; path: string; fileCount: number }[] = [];\n const seen = new Set<string>();\n\n // 1. Read explicit collections from config.json\n const configPath = path.join(repoPath, '.brainbank', 'config.json');\n try {\n if (fs.existsSync(configPath)) {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const docsCfg = config?.docs as Record<string, unknown> | undefined;\n const collections = docsCfg?.collections as { name: string; path: string }[] | undefined;\n if (collections) {\n for (const coll of collections) {\n const absPath = path.resolve(repoPath, coll.path);\n results.push({ name: coll.name, path: coll.path, fileCount: countDocs(absPath) });\n seen.add(absPath);\n }\n }\n }\n } catch {}\n\n // 2. Auto-detect .md/.mdx in the repo root and top-level dirs\n const rootDocs = countDocsShallow(repoPath);\n if (rootDocs > 0) {\n results.push({ name: '(root)', path: '.', fileCount: rootDocs });\n }\n\n try {\n for (const entry of fs.readdirSync(repoPath, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (isIgnoredDir(entry.name)) continue;\n if (entry.name.startsWith('.')) continue;\n\n const dirPath = path.join(repoPath, entry.name);\n if (seen.has(dirPath)) continue;\n\n const count = countDocs(dirPath);\n if (count > 0) {\n results.push({ name: entry.name, path: `./${entry.name}`, fileCount: count });\n }\n }\n } catch {}\n\n return results;\n}\n\n/** Count .md/.mdx files recursively in a directory. */\nfunction countDocs(dir: string): number {\n let count = 0;\n try {\n for (const e of fs.readdirSync(dir, { withFileTypes: true })) {\n const ePath = path.join(dir, e.name);\n const isDir = e.isDirectory() || (e.isSymbolicLink() && (() => { try { return fs.statSync(ePath).isDirectory(); } catch { return false; } })());\n if (isDir) {\n if (isIgnoredDir(e.name)) continue;\n count += countDocs(ePath);\n } else if ((e.isFile() || e.isSymbolicLink()) && /\\.mdx?$/i.test(e.name)) {\n count++;\n }\n }\n } catch {}\n return count;\n}\n\n/** Count .md/.mdx files in a directory (non-recursive, root level only). */\nfunction countDocsShallow(dir: string): number {\n let count = 0;\n try {\n for (const e of fs.readdirSync(dir, { withFileTypes: true })) {\n if (e.isFile() && /\\.mdx?$/i.test(e.name)) count++;\n }\n } catch {}\n return count;\n}\n\n/** Check if config.json exists and read key fields. */\nfunction scanConfig(repoPath: string): ScanResult['config'] {\n const configPath = path.join(repoPath, '.brainbank', 'config.json');\n if (!fs.existsSync(configPath)) return { exists: false };\n\n try {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const codeCfg = config?.code as Record<string, unknown> | undefined;\n return {\n exists: true,\n ignore: codeCfg?.ignore as string[] | undefined,\n plugins: config?.plugins as string[] | undefined,\n };\n } catch {\n return { exists: false };\n }\n}\n\n/** Check DB existence and size. */\nfunction scanDb(repoPath: string): ScanResult['db'] {\n const dbPath = path.join(repoPath, '.brainbank', 'data', 'brainbank.db');\n if (!fs.existsSync(dbPath)) return { exists: false, sizeMB: 0 };\n\n try {\n const stat = fs.statSync(dbPath);\n return {\n exists: true,\n sizeMB: Math.round(stat.size / 1024 / 1024 * 10) / 10,\n lastModified: stat.mtime,\n };\n } catch {\n return { exists: false, sizeMB: 0 };\n }\n}\n\n/** Detect subdirectories with their own .git (mono-repo). Respects `repos` whitelist from config. */\nfunction scanGitSubdirs(repoPath: string): ScanResult['gitSubdirs'] {\n if (fs.existsSync(path.join(repoPath, '.git'))) return [];\n\n try {\n let subdirs = fs.readdirSync(repoPath, { withFileTypes: true })\n .filter(e => {\n if (e.name.startsWith('.')) return false;\n const isDir = e.isDirectory() || (e.isSymbolicLink() && (() => { try { return fs.statSync(path.join(repoPath, e.name)).isDirectory(); } catch { return false; } })());\n return isDir;\n })\n .filter(e => fs.existsSync(path.join(repoPath, e.name, '.git')))\n .map(e => ({ name: e.name }));\n\n // Apply repos whitelist from config if present\n const configRepos = readReposFromConfig(repoPath);\n if (configRepos) {\n subdirs = subdirs.filter(s => configRepos.includes(s.name));\n }\n\n return subdirs;\n } catch {\n return [];\n }\n}\n\n/** Read the `repos` whitelist from .brainbank/config.json. Returns null if not set. */\nfunction readReposFromConfig(repoPath: string): string[] | null {\n const configPath = path.join(repoPath, '.brainbank', 'config.json');\n try {\n if (!fs.existsSync(configPath)) return null;\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const repos = config.repos;\n if (Array.isArray(repos) && repos.every(r => typeof r === 'string')) {\n return repos as string[];\n }\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * brainbank collection add|list|remove — Document collection management\n */\n\nimport { c, args, getFlag, stripFlags, findDocsPlugin } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdCollection(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1];\n\n if (sub === 'add') {\n const path = pos[2];\n const name = getFlag('name');\n const pattern = getFlag('pattern') ?? '**/*.md';\n const context = getFlag('context');\n const ignoreRaw = getFlag('ignore');\n\n if (!path || !name) {\n console.log(c.red('Usage: brainbank collection add <path> --name <name> [--pattern \"**/*.md\"] [--ignore \"glob\"] [--context \"description\"]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red('Docs plugin not loaded. Install @brainbank/docs.')); process.exit(1); }\n await docsPlugin.addCollection({\n name,\n path,\n pattern,\n ignore: ignoreRaw ? ignoreRaw.split(',') : [],\n context: context ?? undefined,\n });\n console.log(c.green(`✓ Collection '${name}' added: ${path} (${pattern})`));\n if (context) console.log(c.dim(` Context: ${context}`));\n brain.close();\n return;\n }\n\n if (sub === 'list') {\n const brain = await createBrain();\n await brain.initialize();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.yellow(' Docs plugin not loaded.')); brain.close(); return; }\n const collections = docsPlugin.listCollections();\n if (collections.length === 0) {\n console.log(c.yellow(' No collections registered.'));\n } else {\n console.log(c.bold('\\n━━━ Collections ━━━\\n'));\n for (const col of collections) {\n console.log(` ${c.cyan(col.name)} ${c.dim('→')} ${col.path}`);\n console.log(` Pattern: ${col.pattern ?? '**/*.md'}`);\n if (col.context) console.log(` Context: ${c.dim(col.context)}`);\n }\n }\n brain.close();\n return;\n }\n\n if (sub === 'remove') {\n const name = pos[2];\n if (!name) {\n console.log(c.red('Usage: brainbank collection remove <name>'));\n process.exit(1);\n }\n const brain = await createBrain();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red('Docs plugin not loaded.')); process.exit(1); }\n await docsPlugin.removeCollection(name);\n console.log(c.green(`✓ Collection '${name}' removed.`));\n brain.close();\n return;\n }\n\n console.log(c.red('Usage: brainbank collection <add|list|remove>'));\n process.exit(1);\n}\n","/**\n * brainbank kv add|search|list|trim|clear — Dynamic KV collection management\n */\n\nimport { c, args, getFlag, stripFlags } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdKv(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1];\n\n if (sub === 'add') {\n const collName = pos[2];\n const content = pos.slice(3).join(' ');\n const metaRaw = getFlag('meta');\n\n if (!collName || !content) {\n console.log(c.red(\"Usage: brainbank kv add <collection> <content> [--meta '{\\\"key\\\":\\\"val\\\"}']\"));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const meta = metaRaw ? JSON.parse(metaRaw) : {};\n const id = await coll.add(content, meta);\n console.log(c.green(`✓ Added item #${id} to '${collName}'`));\n brain.close();\n return;\n }\n\n if (sub === 'search') {\n const collName = pos[2];\n const query = pos.slice(3).join(' ');\n const k = parseInt(getFlag('k') || '5', 10);\n const mode = (getFlag('mode') || 'hybrid') as 'hybrid' | 'vector' | 'keyword';\n\n if (!collName || !query) {\n console.log(c.red('Usage: brainbank kv search <collection> <query> [--k 5] [--mode hybrid|keyword|vector]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const results = await coll.search(query, { k, mode });\n\n if (results.length === 0) {\n console.log(c.yellow(' No results found.'));\n } else {\n console.log(c.bold(`\\n━━━ ${collName}: \"${query}\" ━━━\\n`));\n for (const r of results) {\n const score = Math.round((r.score ?? 0) * 100);\n console.log(` ${c.cyan(`[${score}%]`)} ${r.content}`);\n if (Object.keys(r.metadata).length > 0) {\n console.log(` ${c.dim(JSON.stringify(r.metadata))}`);\n }\n }\n }\n brain.close();\n return;\n }\n\n if (sub === 'list') {\n const collName = pos[2];\n const limit = parseInt(getFlag('limit') || '20', 10);\n\n if (!collName) {\n const brain = await createBrain();\n await brain.initialize();\n const names = brain.listCollectionNames();\n if (names.length === 0) {\n console.log(c.yellow(' No KV collections found.'));\n } else {\n console.log(c.bold('\\n━━━ KV Collections ━━━\\n'));\n for (const n of names) {\n const coll = brain.collection(n);\n console.log(` ${c.cyan(n)} — ${coll.count()} items`);\n }\n }\n brain.close();\n return;\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const items = coll.list({ limit });\n if (items.length === 0) {\n console.log(c.yellow(` Collection '${collName}' is empty.`));\n } else {\n console.log(c.bold(`\\n━━━ ${collName} (${coll.count()} items) ━━━\\n`));\n for (const item of items) {\n const age = Math.round((Date.now() / 1000 - item.createdAt) / 60);\n console.log(` #${item.id} ${c.dim(`(${age}m ago)`)} ${item.content.slice(0, 80)}`);\n }\n }\n brain.close();\n return;\n }\n\n if (sub === 'trim') {\n const collName = pos[2];\n const keep = parseInt(getFlag('keep') || '0', 10);\n\n if (!collName || keep <= 0) {\n console.log(c.red('Usage: brainbank kv trim <collection> --keep <n>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const result = await coll.trim({ keep });\n console.log(c.green(`✓ Trimmed ${result.removed} items from '${collName}' (kept ${keep})`));\n brain.close();\n return;\n }\n\n if (sub === 'clear') {\n const collName = pos[2];\n if (!collName) {\n console.log(c.red('Usage: brainbank kv clear <collection>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const before = coll.count();\n coll.clear();\n console.log(c.green(`✓ Cleared ${before} items from '${collName}'`));\n brain.close();\n return;\n }\n\n console.log(c.red('Usage: brainbank kv <add|search|list|trim|clear>'));\n process.exit(1);\n}\n\n","/**\n * brainbank docs — Index document collections\n * brainbank dsearch — Search documents only\n */\n\nimport { c, args, getFlag, stripFlags, findDocsPlugin } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdDocs(): Promise<void> {\n const collection = getFlag('collection');\n const brain = await createBrain();\n\n console.log(c.bold('\\n━━━ BrainBank Docs Index ━━━\\n'));\n\n const opts: { collections?: string[]; onProgress?: (collection: string, file: string, current: number, total: number) => void } = {};\n if (collection) opts.collections = [collection];\n opts.onProgress = (col: string, file: string, cur: number, total: number) => {\n process.stdout.write(`\\r ${c.cyan(col)} [${cur}/${total}] ${file} `);\n };\n\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red(' Docs plugin not loaded. Install @brainbank/docs.')); process.exit(1); }\n\n const results = await docsPlugin.indexDocs(opts);\n\n console.log('\\n');\n for (const [name, stat] of Object.entries(results) as [string, { indexed: number; skipped: number; removed: number; chunks: number }][]) {\n const removedStr = stat.removed > 0 ? `, ${c.red(String(stat.removed) + ' removed')}` : '';\n console.log(` ${c.green(name)}: ${stat.indexed} indexed, ${stat.skipped} skipped${removedStr}, ${stat.chunks} chunks`);\n }\n\n brain.close();\n}\n\nexport async function cmdDocSearch(): Promise<void> {\n const query = stripFlags(args).slice(1).join(' ');\n if (!query) {\n console.log(c.red('Usage: brainbank dsearch <query>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n const collection = getFlag('collection');\n const k = parseInt(getFlag('k') || '8', 10);\n\n console.log(c.bold(`\\n━━━ BrainBank Doc Search: \"${query}\" ━━━\\n`));\n\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) {\n console.log(c.red('Docs plugin not loaded. Install @brainbank/docs.'));\n process.exit(1);\n }\n const results = await docsPlugin.search(query, { collection: collection ?? undefined, k });\n\n if (results.length === 0) {\n console.log(c.yellow(' No results found.'));\n brain.close();\n return;\n }\n\n for (const r of results) {\n const score = Math.round(r.score * 100);\n const ctx = r.context ? ` — ${c.dim(r.context)}` : '';\n console.log(`${c.magenta(`[DOC ${score}%]`)} ${c.bold(r.filePath!)} [${r.type === 'document' ? r.metadata.collection ?? '' : ''}]${ctx}`);\n const preview = r.content.split('\\n').slice(0, 4).join('\\n');\n console.log(c.dim(preview));\n console.log('');\n }\n\n brain.close();\n}\n","/**\n * brainbank search — Semantic search (vector)\n * brainbank hsearch — Hybrid search (vector + BM25)\n * brainbank ksearch — Keyword search (BM25)\n *\n * Source filtering:\n * --code 10 Max code results\n * --git 0 Skip git results\n * --docs 5 Max document results\n * --notes 10 Custom plugin results\n * --slack_messages 5 Custom collection results\n *\n * Any --<name> <number> flag is treated as a source filter.\n */\n\nimport { c, args, stripFlags, printResults } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\n/**\n * Parse dynamic source flags: each `--<name> <number>` becomes `{ name: number }`.\n *\n * Known non-source flags (--repo, --depth, etc.) are excluded.\n * Returns sources map + the query string (positional args).\n */\nfunction parseSourceFlags(): { sources: Record<string, number>; query: string } {\n const NON_SOURCE_FLAGS = new Set([\n 'repo', 'depth', 'collection', 'pattern', 'context', 'name',\n 'keep', 'reranker', 'pruner', 'only', 'docs-path', 'mode', 'limit',\n 'ignore', 'meta', 'k', 'yes', 'y', 'force', 'verbose',\n ]);\n\n const sources: Record<string, number> = {};\n const positional: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n if (args[i].startsWith('--')) {\n const name = args[i].slice(2);\n\n // Skip boolean flags\n if (name === 'yes' || name === 'force' || name === 'verbose') continue;\n\n // If next arg is a number and flag is not a known non-source flag\n const next = args[i + 1];\n if (next !== undefined && /^\\d+$/.test(next) && !NON_SOURCE_FLAGS.has(name)) {\n sources[name] = parseInt(next, 10);\n i++; // skip the value\n continue;\n }\n\n // Known value flag — skip its value\n if (NON_SOURCE_FLAGS.has(name) && next !== undefined && !next.startsWith('--')) {\n i++;\n }\n continue;\n }\n positional.push(args[i]);\n }\n\n const query = positional.slice(1).join(' '); // skip command name\n return { sources, query };\n}\n\n/** Print active source filters. */\nfunction printFilterInfo(sources: Record<string, number>): void {\n const entries = Object.entries(sources);\n if (entries.length === 0) return;\n const parts = entries.map(([k, v]) => `${k}=${v}`);\n console.log(c.dim(` Sources: ${parts.join(', ')}`));\n}\n\n/** Build search options from sources map. */\nfunction buildSearchOptions(sources: Record<string, number>): { sources: Record<string, number>; source: 'cli' } {\n return Object.keys(sources).length > 0 ? { sources, source: 'cli' } : { sources: {}, source: 'cli' };\n}\n\nexport async function cmdSearch(): Promise<void> {\n const { sources, query } = parseSourceFlags();\n if (!query) {\n console.log(c.red('Usage: brainbank search <query> [--code <n>] [--git <n>] [--<source> <n>]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n console.log(c.bold(`\\n━━━ BrainBank Search: \"${query}\" ━━━\\n`));\n printFilterInfo(sources);\n\n const opts = buildSearchOptions(sources);\n const results = await brain.search(query, opts);\n printResults(results);\n brain.close();\n}\n\nexport async function cmdHybridSearch(): Promise<void> {\n const { sources, query } = parseSourceFlags();\n if (!query) {\n console.log(c.red('Usage: brainbank hsearch <query> [--code <n>] [--git <n>] [--docs <n>] [--<source> <n>]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n console.log(c.bold(`\\n━━━ BrainBank Hybrid Search: \"${query}\" ━━━`));\n console.log(c.dim(` Mode: vector + BM25 → Reciprocal Rank Fusion`));\n printFilterInfo(sources);\n console.log('');\n\n const opts = buildSearchOptions(sources);\n const results = await brain.hybridSearch(query, opts);\n printResults(results);\n brain.close();\n}\n\nexport async function cmdKeywordSearch(): Promise<void> {\n const { sources, query } = parseSourceFlags();\n if (!query) {\n console.log(c.red('Usage: brainbank ksearch <query> [--code <n>] [--git <n>] [--<source> <n>]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n console.log(c.bold(`\\n━━━ BrainBank Keyword Search: \"${query}\" ━━━`));\n console.log(c.dim(` Mode: BM25 full-text (instant)`));\n printFilterInfo(sources);\n console.log('');\n\n const opts = buildSearchOptions(sources);\n const results = await brain.searchBM25(query, opts);\n printResults(results);\n brain.close();\n}\n","/**\n * ServerClient — Lightweight HTTP client for the BrainBank daemon.\n *\n * Used by CLI commands to delegate to a running HTTP server\n * instead of loading models locally. Falls back gracefully\n * (returns null) if the server is unreachable.\n */\n\nimport * as http from 'node:http';\n\nimport { isServerRunning } from '@/services/daemon.ts';\n\ninterface ContextOptions {\n task: string;\n repo?: string;\n sources?: Record<string, number>;\n pathPrefix?: string;\n affectedFiles?: string[];\n}\n\n/**\n * Try to get context from the running HTTP server.\n * Returns the context string if successful, null if server is unreachable.\n */\nexport async function tryServerContext(options: ContextOptions): Promise<string | null> {\n const info = isServerRunning();\n if (!info) return null;\n\n try {\n const body = JSON.stringify({\n task: options.task,\n repo: options.repo,\n sources: options.sources,\n pathPrefix: options.pathPrefix,\n affectedFiles: options.affectedFiles,\n });\n\n const response = await httpPost(info.port, '/context', body);\n const data = JSON.parse(response) as { context?: string; error?: string };\n\n if (data.error) return null;\n return data.context ?? null;\n } catch {\n // Server unreachable or error — fall back to local\n return null;\n }\n}\n\n/**\n * Try to trigger indexing on the running HTTP server.\n * Returns the result if successful, null if server is unreachable.\n */\nexport async function tryServerIndex(repo?: string, forceReindex?: boolean): Promise<Record<string, unknown> | null> {\n const info = isServerRunning();\n if (!info) return null;\n\n try {\n const body = JSON.stringify({ repo, forceReindex });\n const response = await httpPost(info.port, '/index', body);\n const data = JSON.parse(response) as { result?: Record<string, unknown>; error?: string };\n\n if (data.error) return null;\n return data.result ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check server health. Returns health info or null.\n */\nexport async function serverHealth(): Promise<{\n ok: boolean;\n pid: number;\n port: number;\n uptime: number;\n workspaces: number;\n} | null> {\n const info = isServerRunning();\n if (!info) return null;\n\n try {\n const response = await httpGet(info.port, '/health');\n return JSON.parse(response) as { ok: boolean; pid: number; port: number; uptime: number; workspaces: number };\n } catch {\n return null;\n }\n}\n\n// ── HTTP helpers ────────────────────────────────────\n\nfunction httpPost(port: number, path: string, body: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const req = http.request({\n hostname: '127.0.0.1',\n port,\n path,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(body),\n },\n timeout: 120_000, // 2 minutes — context queries can be slow on first load\n }, (res) => {\n const chunks: Buffer[] = [];\n res.on('data', (chunk: Buffer) => chunks.push(chunk));\n res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n });\n\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(); reject(new Error('Request timed out')); });\n req.write(body);\n req.end();\n });\n}\n\nfunction httpGet(port: number, path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const req = http.request({\n hostname: '127.0.0.1',\n port,\n path,\n method: 'GET',\n timeout: 5_000,\n }, (res) => {\n const chunks: Buffer[] = [];\n res.on('data', (chunk: Buffer) => chunks.push(chunk));\n res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n });\n\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(); reject(new Error('Request timed out')); });\n req.end();\n });\n}\n","/**\n * brainbank context <task> — Get formatted context for a task\n * brainbank context add <collection> <path> <description>\n * brainbank context list\n *\n * Source filtering (same as search commands):\n * --code 20 Max code results (default: 20)\n * --git 5 Max git results\n * --no-git Skip git results\n * --no-code Skip code results\n * --path <dir> Filter results to files under this path prefix\n * --ignore <paths> Exclude paths (comma-separated or repeated: --ignore a,b --ignore c)\n */\n\nimport { c, args, stripFlags, getFlag, getFlagAll, findDocsPlugin } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\nimport { tryServerContext } from '@/cli/server-client.ts';\n\n/** Parse --code N, --git N, --no-git, --no-code flags into sources map. */\nfunction parseContextFlags(): Record<string, number> {\n const NON_SOURCE = new Set([\n 'repo', 'depth', 'collection', 'pattern', 'context', 'name',\n 'keep', 'reranker', 'pruner', 'only', 'docs-path', 'mode', 'limit',\n 'ignore', 'meta', 'k', 'yes', 'y', 'force', 'verbose', 'path',\n ]);\n const sources: Record<string, number> = {};\n for (let i = 0; i < args.length; i++) {\n if (!args[i].startsWith('--')) continue;\n const name = args[i].slice(2);\n // --no-git, --no-code → set to 0\n if (name.startsWith('no-')) {\n sources[name.slice(3)] = 0;\n continue;\n }\n // --code 20, --git 5\n const next = args[i + 1];\n if (next !== undefined && /^\\d+$/.test(next) && !NON_SOURCE.has(name)) {\n sources[name] = parseInt(next, 10);\n i++;\n }\n }\n return sources;\n}\n\nexport async function cmdContext(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1];\n\n // brainbank context add <collection> <path> <description>\n if (sub === 'add') {\n const collection = pos[2];\n const path = pos[3];\n const desc = pos.slice(4).join(' ');\n\n if (!collection || !path || !desc) {\n console.log(c.red('Usage: brainbank context add <collection> <path> <description>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red('Docs plugin not loaded.')); process.exit(1); }\n docsPlugin.addContext(collection, path, desc);\n console.log(c.green(`✓ Context added: ${collection}:${path} → \"${desc}\"`));\n brain.close();\n return;\n }\n\n // brainbank context list\n if (sub === 'list') {\n const brain = await createBrain();\n await brain.initialize();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.yellow(' Docs plugin not loaded.')); brain.close(); return; }\n const contexts = docsPlugin.listContexts();\n if (contexts.length === 0) {\n console.log(c.yellow(' No contexts configured.'));\n } else {\n console.log(c.bold('\\n━━━ Contexts ━━━\\n'));\n for (const ctx of contexts) {\n console.log(` ${c.cyan(ctx.collection)}:${ctx.path} → ${c.dim(ctx.context)}`);\n }\n }\n brain.close();\n return;\n }\n\n // brainbank context <task> — get formatted context\n const task = stripFlags(args).slice(1).join(' ');\n if (!task) {\n console.log(c.red('Usage: brainbank context <task description>'));\n console.log(c.dim(' brainbank context add <collection> <path> <description>'));\n console.log(c.dim(' brainbank context list'));\n process.exit(1);\n }\n\n const sources = parseContextFlags();\n const pathPrefix = getFlag('path');\n const ignorePaths = getFlagAll('ignore');\n const repo = getFlag('repo');\n\n // Parse BrainBankQL field flags\n const fields = parseFieldFlags();\n\n // Try HTTP server delegation first\n const serverResult = await tryServerContext({\n task,\n repo: repo ?? process.cwd(),\n sources: Object.keys(sources).length > 0 ? sources : undefined,\n pathPrefix,\n });\n\n if (serverResult !== null) {\n console.log(serverResult);\n return;\n }\n\n // Fall back to local\n const brain = await createBrain();\n const context = await brain.getContext(task, {\n sources: Object.keys(sources).length > 0 ? sources : undefined,\n pathPrefix,\n ignorePaths: ignorePaths.length > 0 ? ignorePaths : undefined,\n source: 'cli',\n fields: Object.keys(fields).length > 0 ? fields : undefined,\n });\n console.log(context);\n brain.close();\n}\n\n/** Parse BrainBankQL field flags: --lines, --symbols, --compact, --no-callTree, --callTree.depth=N, etc. */\nfunction parseFieldFlags(): Record<string, unknown> {\n const FIELD_BOOLEANS = new Set(['lines', 'symbols', 'compact', 'expander']);\n const FIELD_NEGATABLE = new Set(['callTree', 'imports']);\n const fields: Record<string, unknown> = {};\n\n for (let i = 0; i < args.length; i++) {\n if (!args[i].startsWith('--')) continue;\n const raw = args[i].slice(2);\n\n // --no-callTree, --no-imports → set to false\n if (raw.startsWith('no-')) {\n const name = raw.slice(3);\n if (FIELD_NEGATABLE.has(name)) {\n fields[name] = false;\n }\n continue;\n }\n\n // --callTree.depth=4 → { depth: 4 }\n const dotIdx = raw.indexOf('.');\n if (dotIdx > 0) {\n const fieldName = raw.slice(0, dotIdx);\n const rest = raw.slice(dotIdx + 1);\n const eqIdx = rest.indexOf('=');\n if (eqIdx > 0) {\n const key = rest.slice(0, eqIdx);\n const val = parseInt(rest.slice(eqIdx + 1), 10);\n if (!isNaN(val)) {\n fields[fieldName] = { [key]: val };\n }\n }\n continue;\n }\n\n // --lines, --symbols, --compact, --expander → true\n if (FIELD_BOOLEANS.has(raw)) {\n fields[raw] = true;\n }\n }\n\n return fields;\n}\n","/**\n * brainbank files <path|glob> [...paths] [--lines]\n *\n * Fetch full file contents from the index.\n * Use after `brainbank context` to view complete files identified by search.\n */\n\nimport { c, args, getFlag } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdFiles(): Promise<void> {\n // Collect positional args (file patterns) — skip 'files' command itself\n const patterns: string[] = [];\n const showLines = args.includes('--lines');\n\n for (let i = 1; i < args.length; i++) {\n if (args[i].startsWith('--')) {\n // Skip --lines and --repo <value>\n if (args[i] === '--repo') {\n i++; // skip value\n }\n continue;\n }\n patterns.push(args[i]);\n }\n\n if (patterns.length === 0) {\n console.log(c.red('Usage: brainbank files <path|glob> [...paths] [--lines]'));\n console.log(c.dim(' Exact: brainbank files src/auth/login.ts'));\n console.log(c.dim(' Directory: brainbank files src/graph/'));\n console.log(c.dim(' Glob: brainbank files \"src/**/*.service.ts\"'));\n console.log(c.dim(' Fuzzy: brainbank files plugin.ts'));\n console.log(c.dim(' Lines: brainbank files src/plugin.ts --lines'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const results = brain.resolveFiles(patterns);\n\n if (results.length === 0) {\n console.log(c.yellow('No matching files found in the index.'));\n console.log(c.dim('Run `brainbank index` first to index your codebase.'));\n brain.close();\n return;\n }\n\n // Format output\n for (const r of results) {\n const meta = r.metadata as Record<string, unknown>;\n const startLine = (meta.startLine as number) ?? 1;\n\n console.log(c.bold(`\\n── ${r.filePath} ──\\n`));\n\n if (showLines) {\n const codeLines = r.content.split('\\n');\n const pad = String(startLine + codeLines.length - 1).length;\n for (let i = 0; i < codeLines.length; i++) {\n const lineNum = c.dim(`${String(startLine + i).padStart(pad)}|`);\n console.log(`${lineNum} ${codeLines[i]}`);\n }\n } else {\n console.log(r.content);\n }\n }\n\n console.log(c.dim(`\\n${results.length} file(s) resolved.`));\n brain.close();\n}\n","/** brainbank stats — Show index statistics. */\n\nimport { c } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\n/** Convert camelCase/snake_case stat keys to human-readable labels. */\nfunction formatStatKey(key: string): string {\n return key\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\n .padEnd(16);\n}\n\nexport async function cmdStats(): Promise<void> {\n const brain = await createBrain();\n await brain.initialize();\n\n const s = brain.stats();\n\n console.log(c.bold('\\n━━━ BrainBank Stats ━━━\\n'));\n console.log(` ${c.cyan('Plugins')}: ${brain.plugins.join(', ')}\\n`);\n\n for (const [name, pluginStats] of Object.entries(s)) {\n if (!pluginStats) continue;\n console.log(` ${c.cyan(name)}`);\n for (const [key, value] of Object.entries(pluginStats)) {\n console.log(` ${formatStatKey(key)}${value}`);\n }\n console.log('');\n }\n\n const kvNames = brain.listCollectionNames();\n if (kvNames.length > 0) {\n console.log(` ${c.cyan('KV Collections')}`);\n for (const name of kvNames) {\n const coll = brain.collection(name);\n console.log(` ${name}: ${coll.count()} items`);\n }\n console.log('');\n }\n\n brain.close();\n}\n","/** brainbank reembed — Re-embed all vectors. */\n\nimport { c } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdReembed(): Promise<void> {\n const brain = await createBrain();\n await brain.initialize();\n\n console.log(c.bold('\\n━━━ BrainBank Re-embed ━━━\\n'));\n console.log(c.dim(' Regenerating vectors with current embedding provider...'));\n console.log(c.dim(' Text, FTS, and metadata remain unchanged.\\n'));\n\n const result = await brain.reembed({\n onProgress: (table: string, current: number, total: number) => {\n process.stdout.write(`\\r ${c.cyan(table.padEnd(8))} ${current}/${total}`);\n },\n });\n\n console.log('\\n');\n for (const [name, count] of Object.entries(result.counts)) {\n if (count > 0) {\n const label = name.charAt(0).toUpperCase() + name.slice(1);\n console.log(` ${c.green('✓')} ${label.padEnd(8)} ${count} vectors`);\n }\n }\n console.log(`\\n ${c.bold('Total')}: ${result.total} vectors regenerated\\n`);\n\n brain.close();\n}\n","/** brainbank watch — Watch for file changes. */\n\nimport { c } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\nimport { loadConfig } from '@/cli/factory/config-loader.ts';\n\nexport async function cmdWatch(): Promise<void> {\n const brain = await createBrain();\n await brain.initialize();\n\n // Read ignore patterns from config (code.ignore + top-level ignore)\n const config = await loadConfig(brain.config.repoPath);\n const codeIgnore = (config?.code as Record<string, unknown> | undefined)?.ignore as string[] ?? [];\n\n console.log(c.bold('\\n━━━ BrainBank Watch ━━━\\n'));\n console.log(c.dim(` Watching ${brain.config.repoPath} for changes...`));\n if (codeIgnore.length > 0) {\n console.log(c.dim(` Ignoring: ${codeIgnore.join(', ')}`));\n }\n console.log(c.dim(' Press Ctrl+C to stop.\\n'));\n\n const watcher = brain.watch({\n debounceMs: 2000,\n ignore: codeIgnore,\n onIndex: (sourceId: string, pluginName: string) => {\n const ts = new Date().toLocaleTimeString();\n console.log(` ${c.dim(ts)} ${c.green('✓')} ${c.cyan(pluginName)}: ${sourceId}`);\n },\n onError: (err: Error) => {\n console.error(` ${c.red('✗')} ${err.message}`);\n },\n });\n\n process.on('SIGINT', () => {\n console.log(c.dim('\\n Stopping watcher...'));\n watcher.close();\n brain.close();\n process.exit(0);\n });\n\n await new Promise(() => {});\n}\n\n","/** brainbank mcp — Start MCP server (stdio). Requires @brainbank/mcp. */\n\nimport { c } from '@/cli/utils.ts';\n\nexport async function cmdMcp(): Promise<void> {\n try {\n await import('@brainbank/mcp');\n } catch {\n console.error(c.red('Error: @brainbank/mcp is not installed.'));\n console.error(c.dim(' Install: npm i @brainbank/mcp'));\n process.exit(1);\n }\n}\n","/**\n * brainbank daemon — HTTP daemon for CLI delegation.\n *\n * brainbank daemon → Start foreground\n * brainbank daemon start → Start background (fork + PID file)\n * brainbank daemon stop → Stop background daemon\n * brainbank daemon restart → Stop + start\n */\n\nimport { c, args, getFlag, stripFlags } from '@/cli/utils.ts';\nimport { isServerRunning, removePid, DEFAULT_PORT } from '@/services/daemon.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdDaemon(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1]; // start | stop | undefined\n\n if (sub === 'stop') return stopDaemon();\n if (sub === 'restart') { stopDaemon(); return forkDaemon(); }\n if (sub === 'start') return forkDaemon();\n return startForeground();\n}\n\n// ── Foreground ──────────────────────────────────\n\nasync function startForeground(): Promise<void> {\n const port = parseInt(getFlag('port') ?? String(DEFAULT_PORT), 10);\n const { HttpServer } = await import('@/services/http-server.ts');\n\n const server = new HttpServer({\n port,\n factory: async (repoPath: string) => {\n const brain = await createBrain(repoPath);\n await brain.initialize();\n return brain;\n },\n onError: (repo, err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(c.red(` Pool error [${repo}]: ${msg}`));\n },\n onLog: (msg) => console.log(c.dim(` ${msg}`)),\n });\n\n console.log(c.bold('\\n━━━ BrainBank HTTP Daemon ━━━\\n'));\n\n await server.start();\n\n console.log(c.dim(` Port: ${port}`));\n console.log(c.dim(' Press Ctrl+C to stop.\\n'));\n\n const shutdown = () => {\n console.log(c.dim('\\n Shutting down...'));\n server.close();\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n await new Promise(() => {});\n}\n\n// ── Background ──────────────────────────────────\n\nasync function forkDaemon(): Promise<void> {\n const port = parseInt(getFlag('port') ?? String(DEFAULT_PORT), 10);\n const { fork } = await import('node:child_process');\n\n const existing = isServerRunning();\n if (existing) {\n console.log(c.yellow(` Daemon already running (PID ${existing.pid}, port ${existing.port})`));\n return;\n }\n\n const child = fork(process.argv[1], ['daemon', '--port', String(port)], {\n detached: true,\n stdio: 'ignore',\n });\n\n child.unref();\n\n console.log(c.green(` ✓ Daemon started (PID ${child.pid}, port ${port})`));\n console.log(c.dim(' Stop with: brainbank daemon stop'));\n}\n\nfunction stopDaemon(): void {\n const info = isServerRunning();\n if (!info) {\n console.log(c.yellow(' No daemon running.'));\n return;\n }\n\n try {\n process.kill(info.pid, 'SIGTERM');\n removePid();\n console.log(c.green(` ✓ Daemon stopped (PID ${info.pid})`));\n } catch {\n removePid();\n console.log(c.yellow(` PID ${info.pid} not found. Cleaned up stale PID file.`));\n }\n}\n","/**\n * Status Command — Show BrainBank server status.\n *\n * Usage: brainbank status\n */\n\nimport { c } from '@/cli/utils.ts';\nimport { serverHealth } from '@/cli/server-client.ts';\nimport { isServerRunning } from '@/services/daemon.ts';\n\nfunction formatUptime(seconds: number): string {\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n const remainMinutes = minutes % 60;\n return remainMinutes > 0 ? `${hours}h ${remainMinutes}m` : `${hours}h`;\n}\n\nexport async function cmdStatus(): Promise<void> {\n const info = isServerRunning();\n\n if (!info) {\n console.log(`\\n ${c.dim('HTTP Server:')} ${c.yellow('stopped')}\\n`);\n console.log(c.dim(' Start with: brainbank daemon'));\n console.log('');\n return;\n }\n\n // Try to get detailed health from the server\n const health = await serverHealth();\n\n if (health) {\n const uptime = formatUptime(health.uptime);\n console.log(`\\n ${c.dim('HTTP Server:')} ${c.green('running')}`);\n console.log(` ${c.dim('PID:')} ${health.pid}`);\n console.log(` ${c.dim('Port:')} ${health.port}`);\n console.log(` ${c.dim('Uptime:')} ${uptime}`);\n console.log(` ${c.dim('Workspaces:')} ${health.workspaces}`);\n console.log('');\n } else {\n // PID file exists but server not responding\n console.log(`\\n ${c.dim('HTTP Server:')} ${c.yellow('stale')} (PID ${info.pid} not responding)`);\n console.log(c.dim(' The PID file may be stale. Restart with: brainbank daemon'));\n console.log('');\n }\n}\n","/** brainbank help — Show CLI usage. */\n\nimport { c } from '@/cli/utils.ts';\n\nexport function showHelp(): void {\n console.log(c.bold('\\n━━━ BrainBank — Semantic Knowledge Bank ━━━\\n'));\n console.log(c.bold('Indexing:'));\n console.log(` ${c.cyan('index')} ${c.dim('(i)')} [path] Index code + git history`);\n console.log(` ${c.cyan('collection add')} <path> --name Add a document collection`);\n console.log(` ${c.cyan('collection list')} List collections`);\n console.log(` ${c.cyan('collection remove')} <name> Remove a collection`);\n console.log(` ${c.cyan('docs')} [--collection <name>] Index document collections`);\n console.log('');\n console.log(c.bold('Search:'));\n console.log(` ${c.cyan('search')} <query> Semantic search (vector)`);\n console.log(` ${c.cyan('hsearch')} <query> Hybrid search (${c.bold('best quality')})`);\n console.log(` ${c.cyan('ksearch')} <query> Keyword search (BM25, instant)`);\n console.log(` ${c.cyan('dsearch')} <query> Document search`);\n console.log(c.dim(' All search commands accept --<source> <n> to filter by source'));\n console.log('');\n console.log(c.bold('Context:'));\n console.log(` ${c.cyan('context')} <task> Get formatted context for a task`);\n console.log(` ${c.cyan('context add')} <col> <path> <desc> Add context metadata`);\n console.log(` ${c.cyan('context list')} List all context metadata`);\n console.log(` ${c.cyan('files')} <path|glob> [...] [--lines] View full indexed files directly`);\n console.log('');\n console.log(c.bold('KV Store:'));\n console.log(` ${c.cyan('kv add')} <coll> <content> Add item to a collection`);\n console.log(` ${c.cyan('kv search')} <coll> <query> Search a collection`);\n console.log(` ${c.cyan('kv list')} [coll] List collections or items`);\n console.log(` ${c.cyan('kv trim')} <coll> --keep <n> Keep only N most recent`);\n console.log(` ${c.cyan('kv clear')} <coll> Clear all items`);\n console.log('');\n console.log(c.bold('Utility:'));\n console.log(` ${c.cyan('stats')} Show index statistics`);\n console.log(` ${c.cyan('reembed')} Re-embed all vectors`);\n console.log(` ${c.cyan('watch')} Watch files, auto-re-index`);\n console.log(` ${c.cyan('mcp')} Start MCP server (stdio)`);\n console.log(` ${c.cyan('mcp:export')} [target] Export MCP config (antigravity)`);\n console.log(` ${c.cyan('daemon')} Start HTTP daemon (foreground)`);\n console.log(` ${c.cyan('daemon start')} Start HTTP daemon (background)`);\n console.log(` ${c.cyan('daemon stop')} Stop background daemon`);\n console.log(` ${c.cyan('daemon restart')} Restart background daemon`);\n console.log(` ${c.cyan('status')} Show daemon status`);\n console.log(` ${c.cyan('--version')} ${c.dim('(-v)')} Show version`);\n console.log('');\n console.log(c.bold('Options:'));\n console.log(` ${c.dim('--repo <path>')} Repository path (default: .)`);\n console.log(` ${c.dim('--force')} Force re-index all files`);\n console.log(` ${c.dim('--depth <n>')} Git history depth (default: 500)`);\n console.log(` ${c.dim('--collection <name>')} Filter by collection`);\n console.log(` ${c.dim('--pattern <glob>')} Collection glob (default: **/*.md)`);\n console.log(` ${c.dim('--context <desc>')} Context description`);\n console.log(` ${c.dim('--<source> <n>')} Source filter: max results from <source> (0 = skip)`);\n console.log(` ${c.dim('--path <dir>')} Filter context results to files under this path prefix`);\n console.log(` ${c.dim('--ignore <globs>')} Ignore glob patterns for code indexing (comma-separated)`);\n console.log(` ${c.dim('--yes / -y')} Skip interactive prompt (auto-select all available)`);\n console.log(` ${c.dim('--reranker <name>')} Reranker to use (qwen3)`);\n console.log(` ${c.dim('--port <n>')} HTTP daemon port (default: 8181)`);\n console.log('');\n console.log(c.bold('Examples:'));\n console.log(c.dim(' brainbank index .'));\n console.log(c.dim(' brainbank index . --ignore \"sdk/**,vendor/**\"'));\n console.log(c.dim(' brainbank kv add errors \"Fixed null pointer in api.ts\"'));\n console.log(c.dim(' brainbank kv search errors \"null pointer\"'));\n console.log(c.dim(' brainbank kv list'));\n console.log(c.dim(' brainbank hsearch \"authentication middleware\"'));\n console.log(c.dim(' brainbank hsearch \"auth\" --code 0 --git 10 # git only'));\n console.log(c.dim(' brainbank search \"handler\" --git 0 # code only'));\n console.log(c.dim(' brainbank hsearch \"api\" --docs 10 --code 0 --git 0 # docs only'));\n console.log(c.dim(' brainbank context \"auth flow\" | pbcopy # → clipboard'));\n console.log(c.dim(' brainbank daemon start # background HTTP'));\n console.log(c.dim(' brainbank mcp # MCP stdio'));\n console.log(c.dim(' brainbank mcp:export antigravity # export MCP config'));\n}\n","#!/usr/bin/env node\n\n/**\n * BrainBank — CLI Entry Point\n *\n * Dispatcher that routes commands to their handler modules.\n */\n\nimport { args, c } from './utils.ts';\nimport { cmdIndex } from './commands/index.ts';\nimport { cmdCollection } from './commands/collection.ts';\nimport { cmdKv } from './commands/kv.ts';\nimport { cmdDocs, cmdDocSearch } from './commands/docs.ts';\nimport { cmdSearch, cmdHybridSearch, cmdKeywordSearch } from './commands/search.ts';\nimport { cmdContext } from './commands/context.ts';\nimport { cmdFiles } from './commands/files.ts';\nimport { cmdStats } from './commands/stats.ts';\nimport { cmdReembed } from './commands/reembed.ts';\nimport { cmdWatch } from './commands/watch.ts';\nimport { cmdMcp } from './commands/mcp.ts';\nimport { cmdMcpExport } from './commands/mcp-export.ts';\nimport { cmdDaemon } from './commands/daemon.ts';\nimport { cmdStatus } from './commands/status.ts';\nimport { showHelp } from './commands/help.ts';\nimport { VERSION } from '@/constants.ts';\n\nconst command = args[0];\n\nasync function main(): Promise<void> {\n switch (command) {\n case '--version':\n case '-v':\n console.log(`brainbank v${VERSION}`);\n break;\n case 'i':\n case 'index': return cmdIndex();\n case 'collection': return cmdCollection();\n case 'kv': return cmdKv();\n case 'docs': return cmdDocs();\n case 'dsearch': return cmdDocSearch();\n case 'search': return cmdSearch();\n case 'hsearch': return cmdHybridSearch();\n case 'ksearch': return cmdKeywordSearch();\n case 'context': return cmdContext();\n case 'files': return cmdFiles();\n case 'stats': return cmdStats();\n case 'reembed': return cmdReembed();\n case 'watch': return cmdWatch();\n case 'mcp': return cmdMcp();\n case 'mcp:export': return cmdMcpExport();\n case 'serve': return cmdMcp(); // backward compat\n case 'daemon': return cmdDaemon();\n case 'status': return cmdStatus();\n case 'help':\n case '--help':\n case '-h':\n showHelp();\n break;\n default:\n if (command) console.log(c.red(`Unknown command: ${command}\\n`));\n showHelp();\n process.exit(command ? 1 : 0);\n }\n}\n\nmain().catch(err => {\n console.error(c.red(`Error: ${err.message}`));\n if (process.env.BRAINBANK_DEBUG) console.error(err.stack);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","fs","path","path","brain","coll","path","resolve","path","brain","c"]}
1
+ {"version":3,"sources":["../src/cli/commands/index.ts","../src/cli/commands/mcp-export.ts","../src/cli/commands/scan.ts","../src/cli/commands/collection.ts","../src/cli/commands/kv.ts","../src/cli/commands/docs.ts","../src/cli/commands/search.ts","../src/cli/server-client.ts","../src/cli/commands/context.ts","../src/cli/commands/files.ts","../src/cli/commands/stats.ts","../src/cli/commands/reembed.ts","../src/cli/commands/watch.ts","../src/cli/commands/mcp.ts","../src/cli/commands/daemon.ts","../src/cli/commands/status.ts","../src/cli/commands/help.ts","../src/cli/index.ts"],"sourcesContent":["/**\n * brainbank index [path] — Interactive scan → select → index\n *\n * Scans the repo first, shows a summary tree, and prompts the user\n * with checkboxes to select which modules to index. Use --yes to skip.\n */\n\nimport type { ScanResult, ScanModule } from './scan.ts';\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { c, args, getFlag, hasFlag, stripFlags } from '@/cli/utils.ts';\nimport { createBrain, getConfig, registerConfigCollections } from '@/cli/factory/index.ts';\nimport { findDocsPlugin } from '@/cli/utils.ts';\nimport { autoExportMcp } from './mcp-export.ts';\nimport { scanRepo } from './scan.ts';\n\nexport async function cmdIndex(): Promise<void> {\n const positional = stripFlags(args);\n const repoPath = positional[1] || '.';\n const force = hasFlag('force');\n const depth = parseInt(getFlag('depth') || '500', 10);\n const onlyRaw = getFlag('only');\n const docsPath = getFlag('docs');\n const skipPrompt = hasFlag('yes') || hasFlag('y');\n\n\n const scan = scanRepo(repoPath);\n printScanTree(scan, depth);\n\n\n let modules: string[];\n\n if (onlyRaw) {\n // --only flag: explicit module selection\n modules = onlyRaw.split(',').map(s => s.trim());\n } else if (scan.config.plugins && scan.config.plugins.length > 0) {\n // Config exists with plugins field — use it as source of truth\n modules = scan.config.plugins;\n console.log(c.dim(`\\n Using config: plugins = [${modules.join(', ')}]\\n`));\n } else if (skipPrompt) {\n modules = buildDefaultModules(scan);\n } else {\n modules = await promptModules(scan);\n if (modules.length === 0) {\n console.log(c.dim('\\n Nothing selected. Exiting.\\n'));\n return;\n }\n\n // Clean screen and show selection summary\n console.clear();\n console.log(c.bold('\\n━━━ BrainBank ━━━\\n'));\n console.log(' Selected modules:');\n for (const m of modules) {\n console.log(` ${c.green('✓')} ${m}`);\n }\n console.log('');\n }\n\n // If --docs is passed, auto-include 'docs' in modules\n if (docsPath && !modules.includes('docs')) {\n modules.push('docs');\n }\n\n // Auto-generate config.json if it doesn't exist yet\n if (!scan.config.exists && !skipPrompt) {\n await saveConfig(scan.repoPath, modules);\n }\n\n\n console.log(c.bold(`\\n━━━ Indexing: ${modules.join(', ')} ━━━`));\n\n const brain = await createBrain(repoPath);\n await brain.initialize();\n\n const config = await getConfig(repoPath);\n await registerConfigCollections(brain, repoPath, config);\n\n if (docsPath) {\n const absDocsPath = path.resolve(docsPath);\n const collName = path.basename(absDocsPath);\n try {\n const docsPlugin = findDocsPlugin(brain);\n await docsPlugin?.addCollection({\n name: collName,\n path: absDocsPath,\n pattern: '**/*.md',\n ignore: ['deprecated/**', 'node_modules/**'],\n });\n console.log(c.dim(` Registered docs collection: ${collName}`));\n } catch {\n console.log(c.yellow(` Warning: docs module not loaded, skipping --docs`));\n }\n }\n\n const result = await brain.index({\n modules,\n forceReindex: force,\n pluginOptions: { depth },\n onProgress: (stage, msg) => {\n process.stdout.write(`\\r ${c.cyan(stage.toUpperCase())} ${msg} `);\n },\n });\n\n console.log('\\n');\n for (const [name, value] of Object.entries(result)) {\n if (!value) continue;\n const v = value as Record<string, unknown>;\n if (typeof v.indexed === 'number') {\n const parts = [`${v.indexed} indexed`, `${v.skipped ?? 0} skipped`];\n if (typeof v.chunks === 'number') parts.push(`${v.chunks} chunks`);\n if (typeof v.removed === 'number' && v.removed > 0) parts.push(`${v.removed} removed`);\n console.log(` ${c.green(name)}: ${parts.join(', ')}`);\n } else {\n console.log(` ${c.green(name)}: done`);\n }\n }\n\n const stats = brain.stats();\n console.log(`\\n ${c.bold('Totals')}:`);\n for (const [name, s] of Object.entries(stats)) {\n if (!s || typeof s !== 'object') continue;\n const entries = Object.entries(s as Record<string, unknown>)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ');\n console.log(` ${name}: ${entries}`);\n }\n\n brain.close();\n\n // Auto-export MCP config to Antigravity if detected and not already configured\n await autoExportMcp(repoPath);\n}\n\n\nfunction printScanTree(scan: ScanResult, depth: number): void {\n console.clear();\n console.log(c.bold('\\n━━━ BrainBank Scan ━━━'));\n console.log(c.dim(` Repo: ${scan.repoPath}`));\n\n // Multi-repo detection\n if (scan.gitSubdirs.length > 0) {\n console.log(c.cyan(`\\n 🔀 Multi-repo — ${scan.gitSubdirs.length} git repos detected`));\n for (const sub of scan.gitSubdirs) {\n console.log(c.dim(` └── ${sub.name}`));\n }\n }\n\n // Dynamic module display\n for (const mod of scan.modules) {\n console.log('');\n if (mod.available) {\n const extra = mod.name === 'git' ? ` (depth: ${depth})` : '';\n console.log(` ${mod.icon} ${c.bold(capitalizeFirst(mod.name))} — ${mod.summary}${extra}`);\n if (mod.details) {\n for (const d of mod.details) {\n console.log(c.dim(` ${d}`));\n }\n }\n } else {\n console.log(` ${mod.icon} ${c.dim(`${capitalizeFirst(mod.name)} — ${mod.summary}`)}`);\n }\n }\n\n // Config ignore\n if (scan.config.ignore?.length) {\n console.log(c.dim(` Ignore: ${scan.config.ignore.join(', ')}`));\n }\n\n // Config & DB\n console.log('');\n if (scan.config.exists) {\n console.log(` ⚙️ ${c.dim('Config:')} .brainbank/config.json ${c.green('✓')}`);\n }\n if (scan.db?.exists) {\n const ago = scan.db.lastModified ? timeSince(scan.db.lastModified) : '';\n console.log(` 💾 ${c.dim('DB:')} ${scan.db.sizeMB} MB${ago ? `, last indexed ${ago}` : ''}`);\n } else {\n console.log(` 💾 ${c.dim('DB: new (first index)')}`);\n }\n console.log('');\n}\n\n\n/** Build the default list of available modules based on scan. */\nfunction buildDefaultModules(scan: ScanResult): string[] {\n return scan.modules.filter(m => m.available && m.checked).map(m => m.name);\n}\n\n/** Interactive checkbox prompt via @inquirer/prompts. */\nasync function promptModules(scan: ScanResult): Promise<string[]> {\n const { checkbox } = await import('@inquirer/prompts');\n console.log(c.dim(' ─────────────────────────────────────────\\n'));\n\n const choices = scan.modules.map((m: ScanModule) => ({\n name: `${capitalizeFirst(m.name).padEnd(6)} — ${m.summary}`,\n value: m.name,\n checked: m.checked && m.available,\n disabled: m.available ? undefined : m.disabled,\n }));\n\n return checkbox<string>({\n message: 'Select modules to index:\\n',\n choices,\n });\n}\n\n\nfunction timeSince(date: Date): string {\n const seconds = Math.floor((Date.now() - date.getTime()) / 1000);\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n\n/** Capitalize first letter. */\nfunction capitalizeFirst(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/** Generate .brainbank/config.json from the selected modules. */\nasync function saveConfig(repoPath: string, modules: string[]): Promise<void> {\n const { select, confirm } = await import('@inquirer/prompts');\n\n // Embedding provider selection\n const envEmbedding = process.env.BRAINBANK_EMBEDDING;\n const embedding = await select<string>({\n message: 'Embedding provider:',\n choices: [\n {\n name: 'perplexity-context — best accuracy (recommended)',\n value: 'perplexity-context',\n },\n {\n name: 'perplexity — fast, high quality',\n value: 'perplexity',\n },\n {\n name: 'openai — text-embedding-3-small',\n value: 'openai',\n },\n {\n name: 'local — offline, no API key needed',\n value: 'local',\n },\n ],\n default: envEmbedding ?? 'perplexity-context',\n });\n\n // Pruner selection\n const pruner = await select<string>({\n message: 'Noise pruner:',\n choices: [\n {\n name: 'haiku — AI-powered noise filter (recommended)',\n value: 'haiku',\n },\n {\n name: 'none — no pruning',\n value: 'none',\n },\n ],\n default: 'haiku',\n });\n\n const configDir = path.join(repoPath, '.brainbank');\n const configPath = path.join(configDir, 'config.json');\n\n const config: Record<string, unknown> = {\n plugins: modules,\n embedding,\n };\n\n if (pruner !== 'none') {\n config.pruner = pruner;\n }\n\n // Key management: detect available keys and offer to save\n const detectedKeys: Record<string, string> = {};\n const needsPerplexity = embedding.startsWith('perplexity');\n const needsAnthropic = pruner === 'haiku';\n const needsOpenai = embedding === 'openai';\n\n if (needsPerplexity && process.env.PERPLEXITY_API_KEY) {\n detectedKeys.perplexity = process.env.PERPLEXITY_API_KEY;\n }\n if (needsAnthropic && process.env.ANTHROPIC_API_KEY) {\n detectedKeys.anthropic = process.env.ANTHROPIC_API_KEY;\n }\n if (needsOpenai && process.env.OPENAI_API_KEY) {\n detectedKeys.openai = process.env.OPENAI_API_KEY;\n }\n\n if (Object.keys(detectedKeys).length > 0) {\n const keyNames = Object.keys(detectedKeys).join(', ');\n const saveKeys = await confirm({\n message: `Save API keys (${keyNames}) to config.json? (portable, no env vars needed)`,\n default: true,\n });\n if (saveKeys) {\n config.keys = detectedKeys;\n }\n }\n\n fs.mkdirSync(configDir, { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\\n');\n console.log(c.green(` ✓ Saved ${path.relative(process.cwd(), configPath)}`));\n}\n\n","/**\n * brainbank mcp:export [target] — Export MCP server config for AI IDEs.\n *\n * Generates the MCP server config block for brainbank and merges it into\n * the target IDE's config file. Currently supports: antigravity.\n *\n * Detects: node path, cli.js path, API keys from config or env vars.\n */\n\nimport type { ProjectConfig } from '@/cli/factory/config-loader.ts';\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { c, args, getFlag } from '@/cli/utils.ts';\nimport { getConfig } from '@/cli/factory/index.ts';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/** Supported export targets and their config file paths. */\nconst TARGETS: Record<string, { configPath: string; label: string }> = {\n antigravity: {\n configPath: path.join(process.env.HOME ?? '~', '.gemini', 'antigravity', 'mcp_config.json'),\n label: 'Gemini Antigravity',\n },\n};\n\ninterface McpServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\n\ninterface McpConfig {\n mcpServers: Record<string, McpServerConfig>;\n}\n\n/**\n * Build the brainbank MCP server config block.\n * Resolves node binary, dist/cli.js path, and API keys.\n */\nfunction buildBrainbankMcpBlock(config: ProjectConfig | null): McpServerConfig {\n const nodeBin = process.execPath;\n\n // Resolve dist/cli.js from the global install location (node_prefix/lib/node_modules/brainbank/dist/cli.js)\n const globalCliJs = path.join(path.dirname(nodeBin), '..', 'lib', 'node_modules', 'brainbank', 'dist', 'cli.js');\n // Fallback: relative to this file (dev / npm link)\n const localCliJs = path.resolve(__dirname, '..', '..', 'dist', 'cli.js');\n const resolvedCliJs = fs.existsSync(globalCliJs) ? globalCliJs : localCliJs;\n\n const env: Record<string, string> = {};\n\n // Resolve API keys: config.keys > env vars\n const keys = config?.keys;\n const perplexityKey = keys?.perplexity ?? process.env.PERPLEXITY_API_KEY;\n const anthropicKey = keys?.anthropic ?? process.env.ANTHROPIC_API_KEY;\n const openaiKey = keys?.openai ?? process.env.OPENAI_API_KEY;\n\n if (perplexityKey) env.PERPLEXITY_API_KEY = perplexityKey;\n if (anthropicKey) env.ANTHROPIC_API_KEY = anthropicKey;\n if (openaiKey) env.OPENAI_API_KEY = openaiKey;\n\n const block: McpServerConfig = {\n command: nodeBin,\n args: ['--disable-warning=ExperimentalWarning', resolvedCliJs, 'mcp'],\n };\n\n if (Object.keys(env).length > 0) {\n block.env = env;\n }\n\n return block;\n}\n\n/**\n * Load existing MCP config, merge brainbank entry, and write back.\n * Preserves all other server entries.\n */\nfunction mergeAndWrite(targetPath: string, block: McpServerConfig): { created: boolean } {\n let existing: McpConfig = { mcpServers: {} };\n const created = !fs.existsSync(targetPath);\n\n if (!created) {\n try {\n const raw = fs.readFileSync(targetPath, 'utf-8');\n existing = JSON.parse(raw) as McpConfig;\n if (!existing.mcpServers) existing.mcpServers = {};\n } catch {\n // Corrupt or empty file — start fresh\n existing = { mcpServers: {} };\n }\n }\n\n existing.mcpServers.brainbank = block;\n\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, JSON.stringify(existing, null, 2) + '\\n');\n\n return { created };\n}\n\n/** Check if an MCP config already has a brainbank entry. */\nexport function hasBrainbankMcpEntry(targetPath: string): boolean {\n if (!fs.existsSync(targetPath)) return false;\n try {\n const raw = fs.readFileSync(targetPath, 'utf-8');\n const config = JSON.parse(raw) as McpConfig;\n return !!config.mcpServers?.brainbank;\n } catch {\n return false;\n }\n}\n\n/** Auto-export: called after index when Antigravity is detected. */\nexport async function autoExportMcp(repoPath: string): Promise<void> {\n const target = TARGETS.antigravity;\n if (!target) return;\n\n // Only auto-export if Antigravity dir exists\n const antigravityDir = path.dirname(target.configPath);\n if (!fs.existsSync(antigravityDir)) return;\n\n // Only auto-export if brainbank isn't already configured\n if (hasBrainbankMcpEntry(target.configPath)) return;\n\n const config = await getConfig(repoPath);\n const block = buildBrainbankMcpBlock(config);\n mergeAndWrite(target.configPath, block);\n console.log(` ${c.green('✓')} Exported MCP config to ${c.dim(path.relative(process.env.HOME ?? '', target.configPath))}`);\n}\n\n// ── GEMINI.md BrainBank Section ──────────────────────────────\n\nconst BRAINBANK_SECTION_MARKER = '<!-- brainbank:start -->';\nconst BRAINBANK_SECTION_END = '<!-- brainbank:end -->';\n\n/** Global GEMINI.md path — ~/.gemini/GEMINI.md (shared across all projects). */\nconst GLOBAL_GEMINI = path.join(process.env.HOME ?? '~', '.gemini', 'GEMINI.md');\n\nfunction buildGeminiSection(): string {\n return `${BRAINBANK_SECTION_MARKER}\n\n## BrainBank — Code Intelligence\n\nWhen \\`brainbank_context\\` and \\`brainbank_files\\` MCP tools are available, **always use them instead of \\`grep_search\\` or \\`list_dir\\`**.\n\n**\\`brainbank_context\\`** — semantic search. Use \\`path:\\` to scope, \\`compact: false\\`, \\`sources: { code: 25, docs: 0, git: 0 }\\`.\n\n**\\`brainbank_files\\`** — read full indexed files (\\`lines: true\\` always). Only works with files tracked by the index — for \\`.env\\`, \\`docker-compose.yml\\`, etc. use \\`view_file\\`.\n\n**Sources rule:** Default to code-only (\\`docs: 0\\`). Only add \\`docs\\` when the user explicitly asks about documentation. Never mix code and docs in the same query — fire separate queries.\n\n### Output handling (critical)\n\nBrainBank may return results **inline** or save them to an **output file**:\n\n- **Inline:** read and proceed normally.\n- **File result** (saved to \\`output.txt\\`): show the path as a clickable link, ask user to paste, then **STOP and WAIT**:\n\n 📋 Output: [output.txt](file:///path/to/output.txt) — _\"Could you paste the context output here?\"_\n\n Do **NOT** read the file yourself. Wait for the paste before proceeding.\n\n${BRAINBANK_SECTION_END}\n`;\n}\n\n/** Check if GEMINI.md already has the brainbank section. */\nfunction hasGeminiSection(geminiPath: string): boolean {\n if (!fs.existsSync(geminiPath)) return false;\n const content = fs.readFileSync(geminiPath, 'utf-8');\n return content.includes(BRAINBANK_SECTION_MARKER);\n}\n\n/** Append BrainBank section to GEMINI.md (creates if doesn't exist). */\nfunction appendGeminiSection(geminiPath: string): void {\n const section = buildGeminiSection();\n if (fs.existsSync(geminiPath)) {\n fs.appendFileSync(geminiPath, section);\n } else {\n fs.writeFileSync(geminiPath, `# GEMINI.md\\n${section}`);\n }\n}\n\n/** Replace BrainBank section between markers in GEMINI.md. */\nfunction replaceGeminiSection(geminiPath: string): void {\n const content = fs.readFileSync(geminiPath, 'utf-8');\n const startIdx = content.indexOf(BRAINBANK_SECTION_MARKER);\n const endIdx = content.indexOf(BRAINBANK_SECTION_END);\n if (startIdx === -1 || endIdx === -1) return;\n\n const before = content.slice(0, startIdx);\n const after = content.slice(endIdx + BRAINBANK_SECTION_END.length);\n const section = buildGeminiSection();\n fs.writeFileSync(geminiPath, before + section + after);\n}\n\n/** CLI command: brainbank mcp:export [target] */\nexport async function cmdMcpExport(): Promise<void> {\n const targetName = args[1] || getFlag('target') || 'antigravity';\n const repoPath = getFlag('repo') || '.';\n const { confirm } = await import('@inquirer/prompts');\n\n const target = TARGETS[targetName];\n if (!target) {\n console.error(c.red(`Unknown export target: ${targetName}`));\n console.error(c.dim(` Available: ${Object.keys(TARGETS).join(', ')}`));\n process.exit(1);\n }\n\n const config = await getConfig(repoPath);\n const block = buildBrainbankMcpBlock(config);\n\n console.log(c.bold(`\\n━━━ MCP Export: ${target.label} ━━━\\n`));\n\n // ── MCP Config ────────────────────────────────────────────\n const mcpExists = hasBrainbankMcpEntry(target.configPath);\n let writeMcp = true;\n\n if (mcpExists) {\n console.log(` ${c.yellow('●')} MCP config already has brainbank entry`);\n const cliPath = block.args.find(a => !a.startsWith('--')) ?? block.args[0];\n console.log(` ${c.dim(' New:')} ${block.command} ${cliPath}`);\n const envKeys = block.env ? Object.keys(block.env) : [];\n if (envKeys.length > 0) console.log(` ${c.dim(' Keys:')} ${envKeys.join(', ')}`);\n writeMcp = await confirm({ message: 'Override existing brainbank MCP entry?', default: true });\n }\n\n if (writeMcp) {\n const { created } = mergeAndWrite(target.configPath, block);\n console.log(` ${c.green('✓')} ${created ? 'Created' : 'Updated'} ${c.dim(target.configPath)}`);\n } else {\n console.log(` ${c.dim('MCP config — skipped')}`);\n }\n\n // ── Global GEMINI.md (~/.gemini/GEMINI.md) ────────────────\n const geminiHasSection = hasGeminiSection(GLOBAL_GEMINI);\n\n if (geminiHasSection) {\n console.log(` ${c.yellow('●')} ~/.gemini/GEMINI.md already has BrainBank section`);\n const override = await confirm({ message: 'Override existing BrainBank section?', default: false });\n if (override) {\n replaceGeminiSection(GLOBAL_GEMINI);\n console.log(` ${c.green('✓')} Replaced BrainBank section in ${c.dim('~/.gemini/GEMINI.md')}`);\n } else {\n console.log(` ${c.dim('GEMINI.md — skipped')}`);\n }\n } else {\n const addGemini = await confirm({\n message: 'Add BrainBank instructions to ~/.gemini/GEMINI.md? (teaches AI tools how to use BrainBank)',\n default: true,\n });\n if (addGemini) {\n appendGeminiSection(GLOBAL_GEMINI);\n console.log(` ${c.green('✓')} Added BrainBank section to ${c.dim('~/.gemini/GEMINI.md')}`);\n }\n }\n\n console.log(`\\n ${c.dim('Restart your IDE to apply changes.')}\\n`);\n}\n","/**\n * brainbank scan — Lightweight repo scanner for the interactive index flow.\n *\n * Scans the filesystem WITHOUT initializing BrainBank. Returns a ScanResult\n * describing what's available to index via dynamic ScanModule descriptors.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { SUPPORTED_EXTENSIONS, isIgnoredDir, isIgnoredFile } from '@/lib/languages.ts';\n\n\n/** A single scannable module (plugin). */\nexport interface ScanModule {\n /** Plugin name (e.g. 'code', 'git', 'docs'). */\n name: string;\n /** Whether there's content available to index. */\n available: boolean;\n /** Human-readable summary (e.g. '1243 files (5 languages)'). */\n summary: string;\n /** Emoji icon for display. */\n icon: string;\n /** Whether checked by default in the prompt. */\n checked: boolean;\n /** Reason this module is disabled (shown in prompt). */\n disabled?: string;\n /** Detail lines for the scan tree (e.g. per-language breakdown). */\n details?: string[];\n}\n\nexport interface ScanResult {\n repoPath: string;\n modules: ScanModule[];\n config: { exists: boolean; ignore?: string[]; plugins?: string[] };\n db: { exists: boolean; sizeMB: number; lastModified?: Date } | null;\n gitSubdirs: { name: string }[];\n}\n\n\n/** Scan a repo path and return what's available to index. */\nexport function scanRepo(repoPath: string): ScanResult {\n const resolved = path.resolve(repoPath);\n const gitSubdirs = scanGitSubdirs(resolved);\n\n return {\n repoPath: resolved,\n modules: scanModules(resolved, gitSubdirs),\n config: scanConfig(resolved),\n db: scanDb(resolved),\n gitSubdirs,\n };\n}\n\n/** Produce ScanModule descriptors for known plugin types. */\nfunction scanModules(repoPath: string, gitSubdirs: { name: string }[]): ScanModule[] {\n return [\n scanCodeModule(repoPath),\n scanGitModule(repoPath, gitSubdirs),\n scanDocsModule(repoPath),\n ];\n}\n\n\n/** Scan for indexable code files. */\nfunction scanCodeModule(repoPath: string): ScanModule {\n const byLanguage = new Map<string, number>();\n let total = 0;\n\n function walk(dir: string): void {\n let entries: fs.Dirent[];\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); }\n catch { return; }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const isDir = entry.isDirectory() || (entry.isSymbolicLink() && (() => { try { return fs.statSync(fullPath).isDirectory(); } catch { return false; } })());\n if (isDir) {\n if (isIgnoredDir(entry.name)) continue;\n walk(fullPath);\n } else if (entry.isFile()) {\n if (isIgnoredFile(entry.name)) continue;\n const ext = path.extname(entry.name).toLowerCase();\n const lang = SUPPORTED_EXTENSIONS[ext];\n if (!lang) continue;\n byLanguage.set(lang, (byLanguage.get(lang) ?? 0) + 1);\n total++;\n }\n }\n }\n\n walk(repoPath);\n\n if (total === 0) {\n return { name: 'code', available: false, summary: 'no supported source files found', icon: '📁', checked: false, disabled: 'nothing to index' };\n }\n\n const langCount = byLanguage.size;\n const sorted = [...byLanguage.entries()].sort((a, b) => b[1] - a[1]);\n const maxShow = 7;\n const shown = sorted.slice(0, maxShow);\n const remaining = sorted.length - maxShow;\n\n const details: string[] = [];\n for (let i = 0; i < shown.length; i++) {\n const [lang, count] = shown[i];\n const isLast = i === shown.length - 1 && remaining <= 0;\n const prefix = isLast ? '└──' : '├──';\n details.push(`${prefix} ${lang.padEnd(14)} ${count} files`);\n }\n if (remaining > 0) {\n details.push(`└── ...and ${remaining} more`);\n }\n\n return {\n name: 'code',\n available: true,\n summary: `${total} files (${langCount} language${langCount > 1 ? 's' : ''})`,\n icon: '📁',\n checked: true,\n details,\n };\n}\n\n/** Scan for git history. */\nfunction scanGitModule(repoPath: string, gitSubdirs: { name: string }[]): ScanModule {\n const stats = scanGitStats(repoPath, gitSubdirs);\n\n if (!stats) {\n return { name: 'git', available: false, summary: 'no .git directory found', icon: '📜', checked: false, disabled: 'not a git repo' };\n }\n\n const details: string[] = [];\n if (stats.lastMessage) {\n details.push(`Last: ${stats.lastMessage} (${stats.lastDate})`);\n }\n\n return {\n name: 'git',\n available: true,\n summary: `${stats.commitCount.toLocaleString()} commits`,\n icon: '📜',\n checked: true,\n details,\n };\n}\n\n/** Scan for document collections. */\nfunction scanDocsModule(repoPath: string): ScanModule {\n const collections = scanDocsCollections(repoPath);\n\n if (collections.length === 0) {\n return { name: 'docs', available: false, summary: 'no documents found', icon: '📄', checked: false, disabled: 'no .md/.mdx files' };\n }\n\n const totalFiles = collections.reduce((s, d) => s + d.fileCount, 0);\n const details = collections.map((d, i) => {\n const isLast = i === collections.length - 1;\n const prefix = isLast ? '└──' : '├──';\n return `${prefix} ${d.name.padEnd(10)} → ${d.path} (${d.fileCount} files)`;\n });\n\n return {\n name: 'docs',\n available: true,\n summary: `${collections.length} collection${collections.length > 1 ? 's' : ''} (${totalFiles} files)`,\n icon: '📄',\n checked: true,\n details,\n };\n}\n\n\n/** Get git stats. Supports single repo and multi-repo aggregation. */\nfunction scanGitStats(repoPath: string, gitSubdirs: { name: string }[]): { commitCount: number; lastMessage: string; lastDate: string } | null {\n if (fs.existsSync(path.join(repoPath, '.git'))) {\n return gitStats(repoPath);\n }\n\n if (gitSubdirs.length === 0) return null;\n\n let totalCommits = 0;\n let latestMessage = '';\n let latestDate = '';\n\n for (const sub of gitSubdirs) {\n const stats = gitStats(path.join(repoPath, sub.name));\n if (stats) {\n totalCommits += stats.commitCount;\n if (!latestMessage) {\n latestMessage = stats.lastMessage;\n latestDate = stats.lastDate;\n }\n }\n }\n\n return totalCommits > 0\n ? { commitCount: totalCommits, lastMessage: latestMessage, lastDate: latestDate }\n : null;\n}\n\n/** Get git stats for a single directory. */\nfunction gitStats(dir: string): { commitCount: number; lastMessage: string; lastDate: string } | null {\n try {\n const count = parseInt(execSync('git rev-list --count HEAD', { cwd: dir, encoding: 'utf-8' }).trim(), 10);\n const log = execSync('git log -1 --format=\"%s|%ar\"', { cwd: dir, encoding: 'utf-8' }).trim();\n const [lastMessage, lastDate] = log.split('|');\n return { commitCount: count, lastMessage: lastMessage ?? '', lastDate: lastDate ?? '' };\n } catch {\n return null;\n }\n}\n\n/** Scan for document collections (config + auto-detect). */\nfunction scanDocsCollections(repoPath: string): { name: string; path: string; fileCount: number }[] {\n const results: { name: string; path: string; fileCount: number }[] = [];\n const seen = new Set<string>();\n\n // 1. Read explicit collections from config.json\n const configPath = path.join(repoPath, '.brainbank', 'config.json');\n try {\n if (fs.existsSync(configPath)) {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const docsCfg = config?.docs as Record<string, unknown> | undefined;\n const collections = docsCfg?.collections as { name: string; path: string }[] | undefined;\n if (collections) {\n for (const coll of collections) {\n const absPath = path.resolve(repoPath, coll.path);\n results.push({ name: coll.name, path: coll.path, fileCount: countDocs(absPath) });\n seen.add(absPath);\n }\n }\n }\n } catch {}\n\n // 2. Auto-detect .md/.mdx in the repo root and top-level dirs\n const rootDocs = countDocsShallow(repoPath);\n if (rootDocs > 0) {\n results.push({ name: '(root)', path: '.', fileCount: rootDocs });\n }\n\n try {\n for (const entry of fs.readdirSync(repoPath, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (isIgnoredDir(entry.name)) continue;\n if (entry.name.startsWith('.')) continue;\n\n const dirPath = path.join(repoPath, entry.name);\n if (seen.has(dirPath)) continue;\n\n const count = countDocs(dirPath);\n if (count > 0) {\n results.push({ name: entry.name, path: `./${entry.name}`, fileCount: count });\n }\n }\n } catch {}\n\n return results;\n}\n\n/** Count .md/.mdx files recursively in a directory. */\nfunction countDocs(dir: string): number {\n let count = 0;\n try {\n for (const e of fs.readdirSync(dir, { withFileTypes: true })) {\n const ePath = path.join(dir, e.name);\n const isDir = e.isDirectory() || (e.isSymbolicLink() && (() => { try { return fs.statSync(ePath).isDirectory(); } catch { return false; } })());\n if (isDir) {\n if (isIgnoredDir(e.name)) continue;\n count += countDocs(ePath);\n } else if ((e.isFile() || e.isSymbolicLink()) && /\\.mdx?$/i.test(e.name)) {\n count++;\n }\n }\n } catch {}\n return count;\n}\n\n/** Count .md/.mdx files in a directory (non-recursive, root level only). */\nfunction countDocsShallow(dir: string): number {\n let count = 0;\n try {\n for (const e of fs.readdirSync(dir, { withFileTypes: true })) {\n if (e.isFile() && /\\.mdx?$/i.test(e.name)) count++;\n }\n } catch {}\n return count;\n}\n\n/** Check if config.json exists and read key fields. */\nfunction scanConfig(repoPath: string): ScanResult['config'] {\n const configPath = path.join(repoPath, '.brainbank', 'config.json');\n if (!fs.existsSync(configPath)) return { exists: false };\n\n try {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const codeCfg = config?.code as Record<string, unknown> | undefined;\n return {\n exists: true,\n ignore: codeCfg?.ignore as string[] | undefined,\n plugins: config?.plugins as string[] | undefined,\n };\n } catch {\n return { exists: false };\n }\n}\n\n/** Check DB existence and size. */\nfunction scanDb(repoPath: string): ScanResult['db'] {\n const dbPath = path.join(repoPath, '.brainbank', 'data', 'brainbank.db');\n if (!fs.existsSync(dbPath)) return { exists: false, sizeMB: 0 };\n\n try {\n const stat = fs.statSync(dbPath);\n return {\n exists: true,\n sizeMB: Math.round(stat.size / 1024 / 1024 * 10) / 10,\n lastModified: stat.mtime,\n };\n } catch {\n return { exists: false, sizeMB: 0 };\n }\n}\n\n/** Detect subdirectories with their own .git (mono-repo). Respects `repos` whitelist from config. */\nfunction scanGitSubdirs(repoPath: string): ScanResult['gitSubdirs'] {\n if (fs.existsSync(path.join(repoPath, '.git'))) return [];\n\n try {\n let subdirs = fs.readdirSync(repoPath, { withFileTypes: true })\n .filter(e => {\n if (e.name.startsWith('.')) return false;\n const isDir = e.isDirectory() || (e.isSymbolicLink() && (() => { try { return fs.statSync(path.join(repoPath, e.name)).isDirectory(); } catch { return false; } })());\n return isDir;\n })\n .filter(e => fs.existsSync(path.join(repoPath, e.name, '.git')))\n .map(e => ({ name: e.name }));\n\n // Apply repos whitelist from config if present\n const configRepos = readReposFromConfig(repoPath);\n if (configRepos) {\n subdirs = subdirs.filter(s => configRepos.includes(s.name));\n }\n\n return subdirs;\n } catch {\n return [];\n }\n}\n\n/** Read the `repos` whitelist from .brainbank/config.json. Returns null if not set. */\nfunction readReposFromConfig(repoPath: string): string[] | null {\n const configPath = path.join(repoPath, '.brainbank', 'config.json');\n try {\n if (!fs.existsSync(configPath)) return null;\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as Record<string, unknown>;\n const repos = config.repos;\n if (Array.isArray(repos) && repos.every(r => typeof r === 'string')) {\n return repos as string[];\n }\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * brainbank collection add|list|remove — Document collection management\n */\n\nimport { c, args, getFlag, stripFlags, findDocsPlugin } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdCollection(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1];\n\n if (sub === 'add') {\n const path = pos[2];\n const name = getFlag('name');\n const pattern = getFlag('pattern') ?? '**/*.md';\n const context = getFlag('context');\n const ignoreRaw = getFlag('ignore');\n\n if (!path || !name) {\n console.log(c.red('Usage: brainbank collection add <path> --name <name> [--pattern \"**/*.md\"] [--ignore \"glob\"] [--context \"description\"]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red('Docs plugin not loaded. Install @brainbank/docs.')); process.exit(1); }\n await docsPlugin.addCollection({\n name,\n path,\n pattern,\n ignore: ignoreRaw ? ignoreRaw.split(',') : [],\n context: context ?? undefined,\n });\n console.log(c.green(`✓ Collection '${name}' added: ${path} (${pattern})`));\n if (context) console.log(c.dim(` Context: ${context}`));\n brain.close();\n return;\n }\n\n if (sub === 'list') {\n const brain = await createBrain();\n await brain.initialize();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.yellow(' Docs plugin not loaded.')); brain.close(); return; }\n const collections = docsPlugin.listCollections();\n if (collections.length === 0) {\n console.log(c.yellow(' No collections registered.'));\n } else {\n console.log(c.bold('\\n━━━ Collections ━━━\\n'));\n for (const col of collections) {\n console.log(` ${c.cyan(col.name)} ${c.dim('→')} ${col.path}`);\n console.log(` Pattern: ${col.pattern ?? '**/*.md'}`);\n if (col.context) console.log(` Context: ${c.dim(col.context)}`);\n }\n }\n brain.close();\n return;\n }\n\n if (sub === 'remove') {\n const name = pos[2];\n if (!name) {\n console.log(c.red('Usage: brainbank collection remove <name>'));\n process.exit(1);\n }\n const brain = await createBrain();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red('Docs plugin not loaded.')); process.exit(1); }\n await docsPlugin.removeCollection(name);\n console.log(c.green(`✓ Collection '${name}' removed.`));\n brain.close();\n return;\n }\n\n console.log(c.red('Usage: brainbank collection <add|list|remove>'));\n process.exit(1);\n}\n","/**\n * brainbank kv add|search|list|trim|clear — Dynamic KV collection management\n */\n\nimport { c, args, getFlag, stripFlags } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdKv(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1];\n\n if (sub === 'add') {\n const collName = pos[2];\n const content = pos.slice(3).join(' ');\n const metaRaw = getFlag('meta');\n\n if (!collName || !content) {\n console.log(c.red(\"Usage: brainbank kv add <collection> <content> [--meta '{\\\"key\\\":\\\"val\\\"}']\"));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const meta = metaRaw ? JSON.parse(metaRaw) : {};\n const id = await coll.add(content, meta);\n console.log(c.green(`✓ Added item #${id} to '${collName}'`));\n brain.close();\n return;\n }\n\n if (sub === 'search') {\n const collName = pos[2];\n const query = pos.slice(3).join(' ');\n const k = parseInt(getFlag('k') || '5', 10);\n const mode = (getFlag('mode') || 'hybrid') as 'hybrid' | 'vector' | 'keyword';\n\n if (!collName || !query) {\n console.log(c.red('Usage: brainbank kv search <collection> <query> [--k 5] [--mode hybrid|keyword|vector]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const results = await coll.search(query, { k, mode });\n\n if (results.length === 0) {\n console.log(c.yellow(' No results found.'));\n } else {\n console.log(c.bold(`\\n━━━ ${collName}: \"${query}\" ━━━\\n`));\n for (const r of results) {\n const score = Math.round((r.score ?? 0) * 100);\n console.log(` ${c.cyan(`[${score}%]`)} ${r.content}`);\n if (Object.keys(r.metadata).length > 0) {\n console.log(` ${c.dim(JSON.stringify(r.metadata))}`);\n }\n }\n }\n brain.close();\n return;\n }\n\n if (sub === 'list') {\n const collName = pos[2];\n const limit = parseInt(getFlag('limit') || '20', 10);\n\n if (!collName) {\n const brain = await createBrain();\n await brain.initialize();\n const names = brain.listCollectionNames();\n if (names.length === 0) {\n console.log(c.yellow(' No KV collections found.'));\n } else {\n console.log(c.bold('\\n━━━ KV Collections ━━━\\n'));\n for (const n of names) {\n const coll = brain.collection(n);\n console.log(` ${c.cyan(n)} — ${coll.count()} items`);\n }\n }\n brain.close();\n return;\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const items = coll.list({ limit });\n if (items.length === 0) {\n console.log(c.yellow(` Collection '${collName}' is empty.`));\n } else {\n console.log(c.bold(`\\n━━━ ${collName} (${coll.count()} items) ━━━\\n`));\n for (const item of items) {\n const age = Math.round((Date.now() / 1000 - item.createdAt) / 60);\n console.log(` #${item.id} ${c.dim(`(${age}m ago)`)} ${item.content.slice(0, 80)}`);\n }\n }\n brain.close();\n return;\n }\n\n if (sub === 'trim') {\n const collName = pos[2];\n const keep = parseInt(getFlag('keep') || '0', 10);\n\n if (!collName || keep <= 0) {\n console.log(c.red('Usage: brainbank kv trim <collection> --keep <n>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const result = await coll.trim({ keep });\n console.log(c.green(`✓ Trimmed ${result.removed} items from '${collName}' (kept ${keep})`));\n brain.close();\n return;\n }\n\n if (sub === 'clear') {\n const collName = pos[2];\n if (!collName) {\n console.log(c.red('Usage: brainbank kv clear <collection>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const coll = brain.collection(collName);\n const before = coll.count();\n coll.clear();\n console.log(c.green(`✓ Cleared ${before} items from '${collName}'`));\n brain.close();\n return;\n }\n\n console.log(c.red('Usage: brainbank kv <add|search|list|trim|clear>'));\n process.exit(1);\n}\n\n","/**\n * brainbank docs — Index document collections\n * brainbank dsearch — Search documents only\n */\n\nimport { c, args, getFlag, stripFlags, findDocsPlugin } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdDocs(): Promise<void> {\n const collection = getFlag('collection');\n const brain = await createBrain();\n\n console.log(c.bold('\\n━━━ BrainBank Docs Index ━━━\\n'));\n\n const opts: { collections?: string[]; onProgress?: (collection: string, file: string, current: number, total: number) => void } = {};\n if (collection) opts.collections = [collection];\n opts.onProgress = (col: string, file: string, cur: number, total: number) => {\n process.stdout.write(`\\r ${c.cyan(col)} [${cur}/${total}] ${file} `);\n };\n\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red(' Docs plugin not loaded. Install @brainbank/docs.')); process.exit(1); }\n\n const results = await docsPlugin.indexDocs(opts);\n\n console.log('\\n');\n for (const [name, stat] of Object.entries(results) as [string, { indexed: number; skipped: number; removed: number; chunks: number }][]) {\n const removedStr = stat.removed > 0 ? `, ${c.red(String(stat.removed) + ' removed')}` : '';\n console.log(` ${c.green(name)}: ${stat.indexed} indexed, ${stat.skipped} skipped${removedStr}, ${stat.chunks} chunks`);\n }\n\n brain.close();\n}\n\nexport async function cmdDocSearch(): Promise<void> {\n const query = stripFlags(args).slice(1).join(' ');\n if (!query) {\n console.log(c.red('Usage: brainbank dsearch <query>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n const collection = getFlag('collection');\n const k = parseInt(getFlag('k') || '8', 10);\n\n console.log(c.bold(`\\n━━━ BrainBank Doc Search: \"${query}\" ━━━\\n`));\n\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) {\n console.log(c.red('Docs plugin not loaded. Install @brainbank/docs.'));\n process.exit(1);\n }\n const results = await docsPlugin.search(query, { collection: collection ?? undefined, k });\n\n if (results.length === 0) {\n console.log(c.yellow(' No results found.'));\n brain.close();\n return;\n }\n\n for (const r of results) {\n const score = Math.round(r.score * 100);\n const ctx = r.context ? ` — ${c.dim(r.context)}` : '';\n console.log(`${c.magenta(`[DOC ${score}%]`)} ${c.bold(r.filePath!)} [${r.type === 'document' ? r.metadata.collection ?? '' : ''}]${ctx}`);\n const preview = r.content.split('\\n').slice(0, 4).join('\\n');\n console.log(c.dim(preview));\n console.log('');\n }\n\n brain.close();\n}\n","/**\n * brainbank search — Semantic search (vector)\n * brainbank hsearch — Hybrid search (vector + BM25)\n * brainbank ksearch — Keyword search (BM25)\n *\n * Source filtering:\n * --code 10 Max code results\n * --git 0 Skip git results\n * --docs 5 Max document results\n * --notes 10 Custom plugin results\n * --slack_messages 5 Custom collection results\n *\n * Any --<name> <number> flag is treated as a source filter.\n */\n\nimport { c, args, stripFlags, printResults } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\n/**\n * Parse dynamic source flags: each `--<name> <number>` becomes `{ name: number }`.\n *\n * Known non-source flags (--repo, --depth, etc.) are excluded.\n * Returns sources map + the query string (positional args).\n */\nfunction parseSourceFlags(): { sources: Record<string, number>; query: string } {\n const NON_SOURCE_FLAGS = new Set([\n 'repo', 'depth', 'collection', 'pattern', 'context', 'name',\n 'keep', 'reranker', 'pruner', 'only', 'docs-path', 'mode', 'limit',\n 'ignore', 'meta', 'k', 'yes', 'y', 'force', 'verbose',\n ]);\n\n const sources: Record<string, number> = {};\n const positional: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n if (args[i].startsWith('--')) {\n const name = args[i].slice(2);\n\n // Skip boolean flags\n if (name === 'yes' || name === 'force' || name === 'verbose') continue;\n\n // If next arg is a number and flag is not a known non-source flag\n const next = args[i + 1];\n if (next !== undefined && /^\\d+$/.test(next) && !NON_SOURCE_FLAGS.has(name)) {\n sources[name] = parseInt(next, 10);\n i++; // skip the value\n continue;\n }\n\n // Known value flag — skip its value\n if (NON_SOURCE_FLAGS.has(name) && next !== undefined && !next.startsWith('--')) {\n i++;\n }\n continue;\n }\n positional.push(args[i]);\n }\n\n const query = positional.slice(1).join(' '); // skip command name\n return { sources, query };\n}\n\n/** Print active source filters. */\nfunction printFilterInfo(sources: Record<string, number>): void {\n const entries = Object.entries(sources);\n if (entries.length === 0) return;\n const parts = entries.map(([k, v]) => `${k}=${v}`);\n console.log(c.dim(` Sources: ${parts.join(', ')}`));\n}\n\n/** Build search options from sources map. */\nfunction buildSearchOptions(sources: Record<string, number>): { sources: Record<string, number>; source: 'cli' } {\n return Object.keys(sources).length > 0 ? { sources, source: 'cli' } : { sources: {}, source: 'cli' };\n}\n\nexport async function cmdSearch(): Promise<void> {\n const { sources, query } = parseSourceFlags();\n if (!query) {\n console.log(c.red('Usage: brainbank search <query> [--code <n>] [--git <n>] [--<source> <n>]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n console.log(c.bold(`\\n━━━ BrainBank Search: \"${query}\" ━━━\\n`));\n printFilterInfo(sources);\n\n const opts = buildSearchOptions(sources);\n const results = await brain.search(query, opts);\n printResults(results);\n brain.close();\n}\n\nexport async function cmdHybridSearch(): Promise<void> {\n const { sources, query } = parseSourceFlags();\n if (!query) {\n console.log(c.red('Usage: brainbank hsearch <query> [--code <n>] [--git <n>] [--docs <n>] [--<source> <n>]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n console.log(c.bold(`\\n━━━ BrainBank Hybrid Search: \"${query}\" ━━━`));\n console.log(c.dim(` Mode: vector + BM25 → Reciprocal Rank Fusion`));\n printFilterInfo(sources);\n console.log('');\n\n const opts = buildSearchOptions(sources);\n const results = await brain.hybridSearch(query, opts);\n printResults(results);\n brain.close();\n}\n\nexport async function cmdKeywordSearch(): Promise<void> {\n const { sources, query } = parseSourceFlags();\n if (!query) {\n console.log(c.red('Usage: brainbank ksearch <query> [--code <n>] [--git <n>] [--<source> <n>]'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n console.log(c.bold(`\\n━━━ BrainBank Keyword Search: \"${query}\" ━━━`));\n console.log(c.dim(` Mode: BM25 full-text (instant)`));\n printFilterInfo(sources);\n console.log('');\n\n const opts = buildSearchOptions(sources);\n const results = await brain.searchBM25(query, opts);\n printResults(results);\n brain.close();\n}\n","/**\n * ServerClient — Lightweight HTTP client for the BrainBank daemon.\n *\n * Used by CLI commands to delegate to a running HTTP server\n * instead of loading models locally. Falls back gracefully\n * (returns null) if the server is unreachable.\n */\n\nimport * as http from 'node:http';\n\nimport { isServerRunning } from '@/services/daemon.ts';\n\ninterface ContextOptions {\n task: string;\n repo?: string;\n sources?: Record<string, number>;\n pathPrefix?: string;\n affectedFiles?: string[];\n}\n\n/**\n * Try to get context from the running HTTP server.\n * Returns the context string if successful, null if server is unreachable.\n */\nexport async function tryServerContext(options: ContextOptions): Promise<string | null> {\n const info = isServerRunning();\n if (!info) return null;\n\n try {\n const body = JSON.stringify({\n task: options.task,\n repo: options.repo,\n sources: options.sources,\n pathPrefix: options.pathPrefix,\n affectedFiles: options.affectedFiles,\n });\n\n const response = await httpPost(info.port, '/context', body);\n const data = JSON.parse(response) as { context?: string; error?: string };\n\n if (data.error) return null;\n return data.context ?? null;\n } catch {\n // Server unreachable or error — fall back to local\n return null;\n }\n}\n\n/**\n * Try to trigger indexing on the running HTTP server.\n * Returns the result if successful, null if server is unreachable.\n */\nexport async function tryServerIndex(repo?: string, forceReindex?: boolean): Promise<Record<string, unknown> | null> {\n const info = isServerRunning();\n if (!info) return null;\n\n try {\n const body = JSON.stringify({ repo, forceReindex });\n const response = await httpPost(info.port, '/index', body);\n const data = JSON.parse(response) as { result?: Record<string, unknown>; error?: string };\n\n if (data.error) return null;\n return data.result ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check server health. Returns health info or null.\n */\nexport async function serverHealth(): Promise<{\n ok: boolean;\n pid: number;\n port: number;\n uptime: number;\n workspaces: number;\n} | null> {\n const info = isServerRunning();\n if (!info) return null;\n\n try {\n const response = await httpGet(info.port, '/health');\n return JSON.parse(response) as { ok: boolean; pid: number; port: number; uptime: number; workspaces: number };\n } catch {\n return null;\n }\n}\n\n// ── HTTP helpers ────────────────────────────────────\n\nfunction httpPost(port: number, path: string, body: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const req = http.request({\n hostname: '127.0.0.1',\n port,\n path,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(body),\n },\n timeout: 120_000, // 2 minutes — context queries can be slow on first load\n }, (res) => {\n const chunks: Buffer[] = [];\n res.on('data', (chunk: Buffer) => chunks.push(chunk));\n res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n });\n\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(); reject(new Error('Request timed out')); });\n req.write(body);\n req.end();\n });\n}\n\nfunction httpGet(port: number, path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const req = http.request({\n hostname: '127.0.0.1',\n port,\n path,\n method: 'GET',\n timeout: 5_000,\n }, (res) => {\n const chunks: Buffer[] = [];\n res.on('data', (chunk: Buffer) => chunks.push(chunk));\n res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n });\n\n req.on('error', reject);\n req.on('timeout', () => { req.destroy(); reject(new Error('Request timed out')); });\n req.end();\n });\n}\n","/**\n * brainbank context <task> — Get formatted context for a task\n * brainbank context add <collection> <path> <description>\n * brainbank context list\n *\n * Source filtering (same as search commands):\n * --code 20 Max code results (default: 20)\n * --git 5 Max git results\n * --no-git Skip git results\n * --no-code Skip code results\n * --path <dir> Filter results to files under this path prefix\n * --ignore <paths> Exclude paths (comma-separated or repeated: --ignore a,b --ignore c)\n */\n\nimport { c, args, stripFlags, getFlag, getFlagAll, findDocsPlugin } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\nimport { tryServerContext } from '@/cli/server-client.ts';\n\n/** Parse --code N, --git N, --no-git, --no-code flags into sources map. */\nfunction parseContextFlags(): Record<string, number> {\n const NON_SOURCE = new Set([\n 'repo', 'depth', 'collection', 'pattern', 'context', 'name',\n 'keep', 'reranker', 'pruner', 'only', 'docs-path', 'mode', 'limit',\n 'ignore', 'meta', 'k', 'yes', 'y', 'force', 'verbose', 'path',\n ]);\n const sources: Record<string, number> = {};\n for (let i = 0; i < args.length; i++) {\n if (!args[i].startsWith('--')) continue;\n const name = args[i].slice(2);\n // --no-git, --no-code → set to 0\n if (name.startsWith('no-')) {\n sources[name.slice(3)] = 0;\n continue;\n }\n // --code 20, --git 5\n const next = args[i + 1];\n if (next !== undefined && /^\\d+$/.test(next) && !NON_SOURCE.has(name)) {\n sources[name] = parseInt(next, 10);\n i++;\n }\n }\n return sources;\n}\n\nexport async function cmdContext(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1];\n\n // brainbank context add <collection> <path> <description>\n if (sub === 'add') {\n const collection = pos[2];\n const path = pos[3];\n const desc = pos.slice(4).join(' ');\n\n if (!collection || !path || !desc) {\n console.log(c.red('Usage: brainbank context add <collection> <path> <description>'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.red('Docs plugin not loaded.')); process.exit(1); }\n docsPlugin.addContext(collection, path, desc);\n console.log(c.green(`✓ Context added: ${collection}:${path} → \"${desc}\"`));\n brain.close();\n return;\n }\n\n // brainbank context list\n if (sub === 'list') {\n const brain = await createBrain();\n await brain.initialize();\n const docsPlugin = findDocsPlugin(brain);\n if (!docsPlugin) { console.log(c.yellow(' Docs plugin not loaded.')); brain.close(); return; }\n const contexts = docsPlugin.listContexts();\n if (contexts.length === 0) {\n console.log(c.yellow(' No contexts configured.'));\n } else {\n console.log(c.bold('\\n━━━ Contexts ━━━\\n'));\n for (const ctx of contexts) {\n console.log(` ${c.cyan(ctx.collection)}:${ctx.path} → ${c.dim(ctx.context)}`);\n }\n }\n brain.close();\n return;\n }\n\n // brainbank context <task> — get formatted context\n const task = stripFlags(args).slice(1).join(' ');\n if (!task) {\n console.log(c.red('Usage: brainbank context <task description>'));\n console.log(c.dim(' brainbank context add <collection> <path> <description>'));\n console.log(c.dim(' brainbank context list'));\n process.exit(1);\n }\n\n const sources = parseContextFlags();\n const pathPrefix = getFlag('path');\n const ignorePaths = getFlagAll('ignore');\n const repo = getFlag('repo');\n\n // Parse BrainBankQL field flags\n const fields = parseFieldFlags();\n\n // Try HTTP server delegation first\n const serverResult = await tryServerContext({\n task,\n repo: repo ?? process.cwd(),\n sources: Object.keys(sources).length > 0 ? sources : undefined,\n pathPrefix,\n });\n\n if (serverResult !== null) {\n console.log(serverResult);\n return;\n }\n\n // Fall back to local\n const brain = await createBrain();\n const context = await brain.getContext(task, {\n sources: Object.keys(sources).length > 0 ? sources : undefined,\n pathPrefix,\n ignorePaths: ignorePaths.length > 0 ? ignorePaths : undefined,\n source: 'cli',\n fields: Object.keys(fields).length > 0 ? fields : undefined,\n });\n console.log(context);\n brain.close();\n}\n\n/** Parse BrainBankQL field flags: --lines, --symbols, --compact, --no-callTree, --callTree.depth=N, etc. */\nfunction parseFieldFlags(): Record<string, unknown> {\n const FIELD_BOOLEANS = new Set(['lines', 'symbols', 'compact', 'expander']);\n const FIELD_NEGATABLE = new Set(['callTree', 'imports']);\n const fields: Record<string, unknown> = {};\n\n for (let i = 0; i < args.length; i++) {\n if (!args[i].startsWith('--')) continue;\n const raw = args[i].slice(2);\n\n // --no-callTree, --no-imports → set to false\n if (raw.startsWith('no-')) {\n const name = raw.slice(3);\n if (FIELD_NEGATABLE.has(name)) {\n fields[name] = false;\n }\n continue;\n }\n\n // --callTree.depth=4 → { depth: 4 }\n const dotIdx = raw.indexOf('.');\n if (dotIdx > 0) {\n const fieldName = raw.slice(0, dotIdx);\n const rest = raw.slice(dotIdx + 1);\n const eqIdx = rest.indexOf('=');\n if (eqIdx > 0) {\n const key = rest.slice(0, eqIdx);\n const val = parseInt(rest.slice(eqIdx + 1), 10);\n if (!isNaN(val)) {\n fields[fieldName] = { [key]: val };\n }\n }\n continue;\n }\n\n // --lines, --symbols, --compact, --expander → true\n if (FIELD_BOOLEANS.has(raw)) {\n fields[raw] = true;\n }\n }\n\n return fields;\n}\n","/**\n * brainbank files <path|glob> [...paths] [--lines]\n *\n * Fetch full file contents from the index.\n * Use after `brainbank context` to view complete files identified by search.\n */\n\nimport { c, args, getFlag } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdFiles(): Promise<void> {\n // Collect positional args (file patterns) — skip 'files' command itself\n const patterns: string[] = [];\n const showLines = args.includes('--lines');\n\n for (let i = 1; i < args.length; i++) {\n if (args[i].startsWith('--')) {\n // Skip --lines and --repo <value>\n if (args[i] === '--repo') {\n i++; // skip value\n }\n continue;\n }\n patterns.push(args[i]);\n }\n\n if (patterns.length === 0) {\n console.log(c.red('Usage: brainbank files <path|glob> [...paths] [--lines]'));\n console.log(c.dim(' Exact: brainbank files src/auth/login.ts'));\n console.log(c.dim(' Directory: brainbank files src/graph/'));\n console.log(c.dim(' Glob: brainbank files \"src/**/*.service.ts\"'));\n console.log(c.dim(' Fuzzy: brainbank files plugin.ts'));\n console.log(c.dim(' Lines: brainbank files src/plugin.ts --lines'));\n process.exit(1);\n }\n\n const brain = await createBrain();\n await brain.initialize();\n const results = brain.resolveFiles(patterns);\n\n if (results.length === 0) {\n console.log(c.yellow('No matching files found in the index.'));\n console.log(c.dim('Run `brainbank index` first to index your codebase.'));\n brain.close();\n return;\n }\n\n // Format output\n for (const r of results) {\n const meta = r.metadata as Record<string, unknown>;\n const startLine = (meta.startLine as number) ?? 1;\n\n console.log(c.bold(`\\n── ${r.filePath} ──\\n`));\n\n if (showLines) {\n const codeLines = r.content.split('\\n');\n const pad = String(startLine + codeLines.length - 1).length;\n for (let i = 0; i < codeLines.length; i++) {\n const lineNum = c.dim(`${String(startLine + i).padStart(pad)}|`);\n console.log(`${lineNum} ${codeLines[i]}`);\n }\n } else {\n console.log(r.content);\n }\n }\n\n console.log(c.dim(`\\n${results.length} file(s) resolved.`));\n brain.close();\n}\n","/** brainbank stats — Show index statistics. */\n\nimport { c } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\n/** Convert camelCase/snake_case stat keys to human-readable labels. */\nfunction formatStatKey(key: string): string {\n return key\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\n .padEnd(16);\n}\n\nexport async function cmdStats(): Promise<void> {\n const brain = await createBrain();\n await brain.initialize();\n\n const s = brain.stats();\n\n console.log(c.bold('\\n━━━ BrainBank Stats ━━━\\n'));\n console.log(` ${c.cyan('Plugins')}: ${brain.plugins.join(', ')}\\n`);\n\n for (const [name, pluginStats] of Object.entries(s)) {\n if (!pluginStats) continue;\n console.log(` ${c.cyan(name)}`);\n for (const [key, value] of Object.entries(pluginStats)) {\n console.log(` ${formatStatKey(key)}${value}`);\n }\n console.log('');\n }\n\n const kvNames = brain.listCollectionNames();\n if (kvNames.length > 0) {\n console.log(` ${c.cyan('KV Collections')}`);\n for (const name of kvNames) {\n const coll = brain.collection(name);\n console.log(` ${name}: ${coll.count()} items`);\n }\n console.log('');\n }\n\n brain.close();\n}\n","/** brainbank reembed — Re-embed all vectors. */\n\nimport { c } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdReembed(): Promise<void> {\n const brain = await createBrain();\n await brain.initialize();\n\n console.log(c.bold('\\n━━━ BrainBank Re-embed ━━━\\n'));\n console.log(c.dim(' Regenerating vectors with current embedding provider...'));\n console.log(c.dim(' Text, FTS, and metadata remain unchanged.\\n'));\n\n const result = await brain.reembed({\n onProgress: (table: string, current: number, total: number) => {\n process.stdout.write(`\\r ${c.cyan(table.padEnd(8))} ${current}/${total}`);\n },\n });\n\n console.log('\\n');\n for (const [name, count] of Object.entries(result.counts)) {\n if (count > 0) {\n const label = name.charAt(0).toUpperCase() + name.slice(1);\n console.log(` ${c.green('✓')} ${label.padEnd(8)} ${count} vectors`);\n }\n }\n console.log(`\\n ${c.bold('Total')}: ${result.total} vectors regenerated\\n`);\n\n brain.close();\n}\n","/** brainbank watch — Watch for file changes. */\n\nimport { c } from '@/cli/utils.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\nimport { loadConfig } from '@/cli/factory/config-loader.ts';\n\nexport async function cmdWatch(): Promise<void> {\n const brain = await createBrain();\n await brain.initialize();\n\n // Read ignore patterns from config (code.ignore + top-level ignore)\n const config = await loadConfig(brain.config.repoPath);\n const codeIgnore = (config?.code as Record<string, unknown> | undefined)?.ignore as string[] ?? [];\n\n console.log(c.bold('\\n━━━ BrainBank Watch ━━━\\n'));\n console.log(c.dim(` Watching ${brain.config.repoPath} for changes...`));\n if (codeIgnore.length > 0) {\n console.log(c.dim(` Ignoring: ${codeIgnore.join(', ')}`));\n }\n console.log(c.dim(' Press Ctrl+C to stop.\\n'));\n\n const watcher = brain.watch({\n debounceMs: 2000,\n ignore: codeIgnore,\n onIndex: (sourceId: string, pluginName: string) => {\n const ts = new Date().toLocaleTimeString();\n console.log(` ${c.dim(ts)} ${c.green('✓')} ${c.cyan(pluginName)}: ${sourceId}`);\n },\n onError: (err: Error) => {\n console.error(` ${c.red('✗')} ${err.message}`);\n },\n });\n\n process.on('SIGINT', () => {\n console.log(c.dim('\\n Stopping watcher...'));\n watcher.close();\n brain.close();\n process.exit(0);\n });\n\n await new Promise(() => {});\n}\n\n","/** brainbank mcp — Start MCP server (stdio). Requires @brainbank/mcp. */\n\nimport { c } from '@/cli/utils.ts';\n\nexport async function cmdMcp(): Promise<void> {\n try {\n await import('@brainbank/mcp');\n } catch {\n console.error(c.red('Error: @brainbank/mcp is not installed.'));\n console.error(c.dim(' Install: npm i @brainbank/mcp'));\n process.exit(1);\n }\n}\n","/**\n * brainbank daemon — HTTP daemon for CLI delegation.\n *\n * brainbank daemon → Start foreground\n * brainbank daemon start → Start background (fork + PID file)\n * brainbank daemon stop → Stop background daemon\n * brainbank daemon restart → Stop + start\n */\n\nimport { c, args, getFlag, stripFlags } from '@/cli/utils.ts';\nimport { isServerRunning, removePid, DEFAULT_PORT } from '@/services/daemon.ts';\nimport { createBrain } from '@/cli/factory/index.ts';\n\nexport async function cmdDaemon(): Promise<void> {\n const pos = stripFlags(args);\n const sub = pos[1]; // start | stop | undefined\n\n if (sub === 'stop') return stopDaemon();\n if (sub === 'restart') { stopDaemon(); return forkDaemon(); }\n if (sub === 'start') return forkDaemon();\n return startForeground();\n}\n\n// ── Foreground ──────────────────────────────────\n\nasync function startForeground(): Promise<void> {\n const port = parseInt(getFlag('port') ?? String(DEFAULT_PORT), 10);\n const { HttpServer } = await import('@/services/http-server.ts');\n\n const server = new HttpServer({\n port,\n factory: async (repoPath: string) => {\n const brain = await createBrain(repoPath);\n await brain.initialize();\n return brain;\n },\n onError: (repo, err) => {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(c.red(` Pool error [${repo}]: ${msg}`));\n },\n onLog: (msg) => console.log(c.dim(` ${msg}`)),\n });\n\n console.log(c.bold('\\n━━━ BrainBank HTTP Daemon ━━━\\n'));\n\n await server.start();\n\n console.log(c.dim(` Port: ${port}`));\n console.log(c.dim(' Press Ctrl+C to stop.\\n'));\n\n const shutdown = () => {\n console.log(c.dim('\\n Shutting down...'));\n server.close();\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n await new Promise(() => {});\n}\n\n// ── Background ──────────────────────────────────\n\nasync function forkDaemon(): Promise<void> {\n const port = parseInt(getFlag('port') ?? String(DEFAULT_PORT), 10);\n const { fork } = await import('node:child_process');\n\n const existing = isServerRunning();\n if (existing) {\n console.log(c.yellow(` Daemon already running (PID ${existing.pid}, port ${existing.port})`));\n return;\n }\n\n const child = fork(process.argv[1], ['daemon', '--port', String(port)], {\n detached: true,\n stdio: 'ignore',\n });\n\n child.unref();\n\n console.log(c.green(` ✓ Daemon started (PID ${child.pid}, port ${port})`));\n console.log(c.dim(' Stop with: brainbank daemon stop'));\n}\n\nfunction stopDaemon(): void {\n const info = isServerRunning();\n if (!info) {\n console.log(c.yellow(' No daemon running.'));\n return;\n }\n\n try {\n process.kill(info.pid, 'SIGTERM');\n removePid();\n console.log(c.green(` ✓ Daemon stopped (PID ${info.pid})`));\n } catch {\n removePid();\n console.log(c.yellow(` PID ${info.pid} not found. Cleaned up stale PID file.`));\n }\n}\n","/**\n * Status Command — Show BrainBank server status.\n *\n * Usage: brainbank status\n */\n\nimport { c } from '@/cli/utils.ts';\nimport { serverHealth } from '@/cli/server-client.ts';\nimport { isServerRunning } from '@/services/daemon.ts';\n\nfunction formatUptime(seconds: number): string {\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n const remainMinutes = minutes % 60;\n return remainMinutes > 0 ? `${hours}h ${remainMinutes}m` : `${hours}h`;\n}\n\nexport async function cmdStatus(): Promise<void> {\n const info = isServerRunning();\n\n if (!info) {\n console.log(`\\n ${c.dim('HTTP Server:')} ${c.yellow('stopped')}\\n`);\n console.log(c.dim(' Start with: brainbank daemon'));\n console.log('');\n return;\n }\n\n // Try to get detailed health from the server\n const health = await serverHealth();\n\n if (health) {\n const uptime = formatUptime(health.uptime);\n console.log(`\\n ${c.dim('HTTP Server:')} ${c.green('running')}`);\n console.log(` ${c.dim('PID:')} ${health.pid}`);\n console.log(` ${c.dim('Port:')} ${health.port}`);\n console.log(` ${c.dim('Uptime:')} ${uptime}`);\n console.log(` ${c.dim('Workspaces:')} ${health.workspaces}`);\n console.log('');\n } else {\n // PID file exists but server not responding\n console.log(`\\n ${c.dim('HTTP Server:')} ${c.yellow('stale')} (PID ${info.pid} not responding)`);\n console.log(c.dim(' The PID file may be stale. Restart with: brainbank daemon'));\n console.log('');\n }\n}\n","/** brainbank help — Show CLI usage. */\n\nimport { c } from '@/cli/utils.ts';\n\nexport function showHelp(): void {\n console.log(c.bold('\\n━━━ BrainBank — Semantic Knowledge Bank ━━━\\n'));\n console.log(c.bold('Indexing:'));\n console.log(` ${c.cyan('index')} ${c.dim('(i)')} [path] Index code + git history`);\n console.log(` ${c.cyan('collection add')} <path> --name Add a document collection`);\n console.log(` ${c.cyan('collection list')} List collections`);\n console.log(` ${c.cyan('collection remove')} <name> Remove a collection`);\n console.log(` ${c.cyan('docs')} [--collection <name>] Index document collections`);\n console.log('');\n console.log(c.bold('Search:'));\n console.log(` ${c.cyan('search')} <query> Semantic search (vector)`);\n console.log(` ${c.cyan('hsearch')} <query> Hybrid search (${c.bold('best quality')})`);\n console.log(` ${c.cyan('ksearch')} <query> Keyword search (BM25, instant)`);\n console.log(` ${c.cyan('dsearch')} <query> Document search`);\n console.log(c.dim(' All search commands accept --<source> <n> to filter by source'));\n console.log('');\n console.log(c.bold('Context:'));\n console.log(` ${c.cyan('context')} <task> Get formatted context for a task`);\n console.log(` ${c.cyan('context add')} <col> <path> <desc> Add context metadata`);\n console.log(` ${c.cyan('context list')} List all context metadata`);\n console.log(` ${c.cyan('files')} <path|glob> [...] [--lines] View full indexed files directly`);\n console.log('');\n console.log(c.bold('KV Store:'));\n console.log(` ${c.cyan('kv add')} <coll> <content> Add item to a collection`);\n console.log(` ${c.cyan('kv search')} <coll> <query> Search a collection`);\n console.log(` ${c.cyan('kv list')} [coll] List collections or items`);\n console.log(` ${c.cyan('kv trim')} <coll> --keep <n> Keep only N most recent`);\n console.log(` ${c.cyan('kv clear')} <coll> Clear all items`);\n console.log('');\n console.log(c.bold('Utility:'));\n console.log(` ${c.cyan('stats')} Show index statistics`);\n console.log(` ${c.cyan('reembed')} Re-embed all vectors`);\n console.log(` ${c.cyan('watch')} Watch files, auto-re-index`);\n console.log(` ${c.cyan('mcp')} Start MCP server (stdio)`);\n console.log(` ${c.cyan('mcp:export')} [target] Export MCP config (antigravity)`);\n console.log(` ${c.cyan('daemon')} Start HTTP daemon (foreground)`);\n console.log(` ${c.cyan('daemon start')} Start HTTP daemon (background)`);\n console.log(` ${c.cyan('daemon stop')} Stop background daemon`);\n console.log(` ${c.cyan('daemon restart')} Restart background daemon`);\n console.log(` ${c.cyan('status')} Show daemon status`);\n console.log(` ${c.cyan('--version')} ${c.dim('(-v)')} Show version`);\n console.log('');\n console.log(c.bold('Options:'));\n console.log(` ${c.dim('--repo <path>')} Repository path (default: .)`);\n console.log(` ${c.dim('--force')} Force re-index all files`);\n console.log(` ${c.dim('--depth <n>')} Git history depth (default: 500)`);\n console.log(` ${c.dim('--collection <name>')} Filter by collection`);\n console.log(` ${c.dim('--pattern <glob>')} Collection glob (default: **/*.md)`);\n console.log(` ${c.dim('--context <desc>')} Context description`);\n console.log(` ${c.dim('--<source> <n>')} Source filter: max results from <source> (0 = skip)`);\n console.log(` ${c.dim('--path <dir>')} Filter context results to files under this path prefix`);\n console.log(` ${c.dim('--ignore <globs>')} Ignore glob patterns for code indexing (comma-separated)`);\n console.log(` ${c.dim('--yes / -y')} Skip interactive prompt (auto-select all available)`);\n console.log(` ${c.dim('--reranker <name>')} Reranker to use (qwen3)`);\n console.log(` ${c.dim('--port <n>')} HTTP daemon port (default: 8181)`);\n console.log('');\n console.log(c.bold('Examples:'));\n console.log(c.dim(' brainbank index .'));\n console.log(c.dim(' brainbank index . --ignore \"sdk/**,vendor/**\"'));\n console.log(c.dim(' brainbank kv add errors \"Fixed null pointer in api.ts\"'));\n console.log(c.dim(' brainbank kv search errors \"null pointer\"'));\n console.log(c.dim(' brainbank kv list'));\n console.log(c.dim(' brainbank hsearch \"authentication middleware\"'));\n console.log(c.dim(' brainbank hsearch \"auth\" --code 0 --git 10 # git only'));\n console.log(c.dim(' brainbank search \"handler\" --git 0 # code only'));\n console.log(c.dim(' brainbank hsearch \"api\" --docs 10 --code 0 --git 0 # docs only'));\n console.log(c.dim(' brainbank context \"auth flow\" | pbcopy # → clipboard'));\n console.log(c.dim(' brainbank daemon start # background HTTP'));\n console.log(c.dim(' brainbank mcp # MCP stdio'));\n console.log(c.dim(' brainbank mcp:export antigravity # export MCP config'));\n}\n","#!/usr/bin/env node\n\n/**\n * BrainBank — CLI Entry Point\n *\n * Dispatcher that routes commands to their handler modules.\n */\n\nimport { args, c } from './utils.ts';\nimport { cmdIndex } from './commands/index.ts';\nimport { cmdCollection } from './commands/collection.ts';\nimport { cmdKv } from './commands/kv.ts';\nimport { cmdDocs, cmdDocSearch } from './commands/docs.ts';\nimport { cmdSearch, cmdHybridSearch, cmdKeywordSearch } from './commands/search.ts';\nimport { cmdContext } from './commands/context.ts';\nimport { cmdFiles } from './commands/files.ts';\nimport { cmdStats } from './commands/stats.ts';\nimport { cmdReembed } from './commands/reembed.ts';\nimport { cmdWatch } from './commands/watch.ts';\nimport { cmdMcp } from './commands/mcp.ts';\nimport { cmdMcpExport } from './commands/mcp-export.ts';\nimport { cmdDaemon } from './commands/daemon.ts';\nimport { cmdStatus } from './commands/status.ts';\nimport { showHelp } from './commands/help.ts';\nimport { VERSION } from '@/constants.ts';\n\nconst command = args[0];\n\nasync function main(): Promise<void> {\n switch (command) {\n case '--version':\n case '-v':\n console.log(`brainbank v${VERSION}`);\n break;\n case 'i':\n case 'index': return cmdIndex();\n case 'collection': return cmdCollection();\n case 'kv': return cmdKv();\n case 'docs': return cmdDocs();\n case 'dsearch': return cmdDocSearch();\n case 'search': return cmdSearch();\n case 'hsearch': return cmdHybridSearch();\n case 'ksearch': return cmdKeywordSearch();\n case 'context': return cmdContext();\n case 'files': return cmdFiles();\n case 'stats': return cmdStats();\n case 'reembed': return cmdReembed();\n case 'watch': return cmdWatch();\n case 'mcp': return cmdMcp();\n case 'mcp:export': return cmdMcpExport();\n case 'serve': return cmdMcp(); // backward compat\n case 'daemon': return cmdDaemon();\n case 'status': return cmdStatus();\n case 'help':\n case '--help':\n case '-h':\n showHelp();\n break;\n default:\n if (command) console.log(c.red(`Unknown command: ${command}\\n`));\n showHelp();\n process.exit(command ? 1 : 0);\n }\n}\n\nmain().catch(err => {\n console.error(c.red(`Error: ${err.message}`));\n if (process.env.BRAINBANK_DEBUG) console.error(err.stack);\n process.exit(1);\n});\n"],"mappings":"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","names":["fs","path","fs","path","path","brain","coll","path","resolve","path","brain","c"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainbank",
3
- "version": "0.9.1",
3
+ "version": "0.9.4",
4
4
  "description": "Pluggable semantic memory for AI agents — hybrid search (vector + BM25) in a single SQLite file. Built-in code, git, and docs indexers. Bring your own.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -64,7 +64,7 @@ function buildBrainbankMcpBlock(config: ProjectConfig | null): McpServerConfig {
64
64
 
65
65
  const block: McpServerConfig = {
66
66
  command: nodeBin,
67
- args: [resolvedCliJs, 'mcp'],
67
+ args: ['--disable-warning=ExperimentalWarning', resolvedCliJs, 'mcp'],
68
68
  };
69
69
 
70
70
  if (Object.keys(env).length > 0) {
@@ -131,10 +131,77 @@ export async function autoExportMcp(repoPath: string): Promise<void> {
131
131
  console.log(` ${c.green('✓')} Exported MCP config to ${c.dim(path.relative(process.env.HOME ?? '', target.configPath))}`);
132
132
  }
133
133
 
134
+ // ── GEMINI.md BrainBank Section ──────────────────────────────
135
+
136
+ const BRAINBANK_SECTION_MARKER = '<!-- brainbank:start -->';
137
+ const BRAINBANK_SECTION_END = '<!-- brainbank:end -->';
138
+
139
+ /** Global GEMINI.md path — ~/.gemini/GEMINI.md (shared across all projects). */
140
+ const GLOBAL_GEMINI = path.join(process.env.HOME ?? '~', '.gemini', 'GEMINI.md');
141
+
142
+ function buildGeminiSection(): string {
143
+ return `${BRAINBANK_SECTION_MARKER}
144
+
145
+ ## BrainBank — Code Intelligence
146
+
147
+ When \`brainbank_context\` and \`brainbank_files\` MCP tools are available, **always use them instead of \`grep_search\` or \`list_dir\`**.
148
+
149
+ **\`brainbank_context\`** — semantic search. Use \`path:\` to scope, \`compact: false\`, \`sources: { code: 25, docs: 0, git: 0 }\`.
150
+
151
+ **\`brainbank_files\`** — read full indexed files (\`lines: true\` always). Only works with files tracked by the index — for \`.env\`, \`docker-compose.yml\`, etc. use \`view_file\`.
152
+
153
+ **Sources rule:** Default to code-only (\`docs: 0\`). Only add \`docs\` when the user explicitly asks about documentation. Never mix code and docs in the same query — fire separate queries.
154
+
155
+ ### Output handling (critical)
156
+
157
+ BrainBank may return results **inline** or save them to an **output file**:
158
+
159
+ - **Inline:** read and proceed normally.
160
+ - **File result** (saved to \`output.txt\`): show the path as a clickable link, ask user to paste, then **STOP and WAIT**:
161
+
162
+ 📋 Output: [output.txt](file:///path/to/output.txt) — _"Could you paste the context output here?"_
163
+
164
+ Do **NOT** read the file yourself. Wait for the paste before proceeding.
165
+
166
+ ${BRAINBANK_SECTION_END}
167
+ `;
168
+ }
169
+
170
+ /** Check if GEMINI.md already has the brainbank section. */
171
+ function hasGeminiSection(geminiPath: string): boolean {
172
+ if (!fs.existsSync(geminiPath)) return false;
173
+ const content = fs.readFileSync(geminiPath, 'utf-8');
174
+ return content.includes(BRAINBANK_SECTION_MARKER);
175
+ }
176
+
177
+ /** Append BrainBank section to GEMINI.md (creates if doesn't exist). */
178
+ function appendGeminiSection(geminiPath: string): void {
179
+ const section = buildGeminiSection();
180
+ if (fs.existsSync(geminiPath)) {
181
+ fs.appendFileSync(geminiPath, section);
182
+ } else {
183
+ fs.writeFileSync(geminiPath, `# GEMINI.md\n${section}`);
184
+ }
185
+ }
186
+
187
+ /** Replace BrainBank section between markers in GEMINI.md. */
188
+ function replaceGeminiSection(geminiPath: string): void {
189
+ const content = fs.readFileSync(geminiPath, 'utf-8');
190
+ const startIdx = content.indexOf(BRAINBANK_SECTION_MARKER);
191
+ const endIdx = content.indexOf(BRAINBANK_SECTION_END);
192
+ if (startIdx === -1 || endIdx === -1) return;
193
+
194
+ const before = content.slice(0, startIdx);
195
+ const after = content.slice(endIdx + BRAINBANK_SECTION_END.length);
196
+ const section = buildGeminiSection();
197
+ fs.writeFileSync(geminiPath, before + section + after);
198
+ }
199
+
134
200
  /** CLI command: brainbank mcp:export [target] */
135
201
  export async function cmdMcpExport(): Promise<void> {
136
202
  const targetName = args[1] || getFlag('target') || 'antigravity';
137
203
  const repoPath = getFlag('repo') || '.';
204
+ const { confirm } = await import('@inquirer/prompts');
138
205
 
139
206
  const target = TARGETS[targetName];
140
207
  if (!target) {
@@ -145,18 +212,50 @@ export async function cmdMcpExport(): Promise<void> {
145
212
 
146
213
  const config = await getConfig(repoPath);
147
214
  const block = buildBrainbankMcpBlock(config);
148
- const { created } = mergeAndWrite(target.configPath, block);
149
215
 
150
216
  console.log(c.bold(`\n━━━ MCP Export: ${target.label} ━━━\n`));
151
- console.log(` ${c.green('✓')} ${created ? 'Created' : 'Updated'} ${c.dim(target.configPath)}`);
152
- console.log(` ${c.dim('Node:')} ${block.command}`);
153
- console.log(` ${c.dim('CLI:')} ${block.args[0]}`);
154
217
 
155
- const envKeys = block.env ? Object.keys(block.env) : [];
156
- if (envKeys.length > 0) {
157
- console.log(` ${c.dim('Keys:')} ${envKeys.join(', ')}`);
218
+ // ── MCP Config ────────────────────────────────────────────
219
+ const mcpExists = hasBrainbankMcpEntry(target.configPath);
220
+ let writeMcp = true;
221
+
222
+ if (mcpExists) {
223
+ console.log(` ${c.yellow('●')} MCP config already has brainbank entry`);
224
+ const cliPath = block.args.find(a => !a.startsWith('--')) ?? block.args[0];
225
+ console.log(` ${c.dim(' New:')} ${block.command} ${cliPath}`);
226
+ const envKeys = block.env ? Object.keys(block.env) : [];
227
+ if (envKeys.length > 0) console.log(` ${c.dim(' Keys:')} ${envKeys.join(', ')}`);
228
+ writeMcp = await confirm({ message: 'Override existing brainbank MCP entry?', default: true });
229
+ }
230
+
231
+ if (writeMcp) {
232
+ const { created } = mergeAndWrite(target.configPath, block);
233
+ console.log(` ${c.green('✓')} ${created ? 'Created' : 'Updated'} ${c.dim(target.configPath)}`);
234
+ } else {
235
+ console.log(` ${c.dim('MCP config — skipped')}`);
236
+ }
237
+
238
+ // ── Global GEMINI.md (~/.gemini/GEMINI.md) ────────────────
239
+ const geminiHasSection = hasGeminiSection(GLOBAL_GEMINI);
240
+
241
+ if (geminiHasSection) {
242
+ console.log(` ${c.yellow('●')} ~/.gemini/GEMINI.md already has BrainBank section`);
243
+ const override = await confirm({ message: 'Override existing BrainBank section?', default: false });
244
+ if (override) {
245
+ replaceGeminiSection(GLOBAL_GEMINI);
246
+ console.log(` ${c.green('✓')} Replaced BrainBank section in ${c.dim('~/.gemini/GEMINI.md')}`);
247
+ } else {
248
+ console.log(` ${c.dim('GEMINI.md — skipped')}`);
249
+ }
158
250
  } else {
159
- console.log(` ${c.yellow('⚠')} No API keys found. Set env vars or add keys to .brainbank/config.json`);
251
+ const addGemini = await confirm({
252
+ message: 'Add BrainBank instructions to ~/.gemini/GEMINI.md? (teaches AI tools how to use BrainBank)',
253
+ default: true,
254
+ });
255
+ if (addGemini) {
256
+ appendGeminiSection(GLOBAL_GEMINI);
257
+ console.log(` ${c.green('✓')} Added BrainBank section to ${c.dim('~/.gemini/GEMINI.md')}`);
258
+ }
160
259
  }
161
260
 
162
261
  console.log(`\n ${c.dim('Restart your IDE to apply changes.')}\n`);