kly 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/commands/output.ts","../src/commands/shared.ts","../src/commands/build.ts","../src/commands/dependents.ts","../src/commands/enrich.ts","../src/commands/gc.ts","../src/commands/graph.ts","../src/commands/history.ts","../src/commands/hook.ts","../src/commands/init.ts","../src/commands/overview.ts","../src/commands/query.ts","../src/commands/show.ts","../src/cli.ts"],"sourcesContent":["/**\n * Unified output utilities for all CLI commands.\n *\n * Default: JSON to stdout (agent-first).\n * --pretty: Human-readable to stdout.\n * Errors/warnings: always to stderr.\n */\n\nexport interface OutputOptions {\n pretty?: boolean;\n}\n\n/** Output data as JSON (default) or human-readable (--pretty). */\nexport function output(\n data: unknown,\n opts: OutputOptions,\n prettyFormatter?: (data: unknown) => string,\n): void {\n if (opts.pretty && prettyFormatter) {\n process.stdout.write(prettyFormatter(data) + \"\\n\");\n } else {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n }\n}\n\n/** Output error to stderr and exit. Optionally show a hint with correct usage. */\nexport function error(message: string, hint?: string): never {\n let msg = `Error: ${message}`;\n if (hint) {\n msg += `\\n ${hint}`;\n }\n process.stderr.write(msg + \"\\n\");\n process.exit(1);\n}\n\n/** Output warning to stderr. */\nexport function warn(message: string): void {\n process.stderr.write(`Warning: ${message}\\n`);\n}\n\n/** Output info to stderr (for progress/status messages that shouldn't pollute stdout). */\nexport function info(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n","import { isInitialized } from \"../config\";\nimport { error } from \"./output\";\n\nexport function ensureInitialized(root: string): void {\n if (!isInitialized(root)) {\n error(\"Not initialized.\", \"kly init --provider <provider> --api-key <key>\");\n }\n}\n","import { buildIndex } from \"../indexer\";\nimport { info } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface BuildOptions {\n full?: boolean;\n quiet?: boolean;\n}\n\nexport async function runBuild(root: string, options: BuildOptions = {}): Promise<void> {\n ensureInitialized(root);\n\n if (!options.quiet) {\n info(\"building index...\");\n }\n\n try {\n const result = await buildIndex(root, {\n full: options.full,\n quiet: options.quiet,\n onProgress: (progress) => {\n if (!options.quiet) {\n const pct =\n progress.total > 0 ? Math.round((progress.completed / progress.total) * 100) : 100;\n let msg = `indexing [${pct}%] ${progress.current || \"...\"}`;\n if (progress.skipped > 0) {\n msg += ` (${progress.skipped} unchanged)`;\n }\n // Write progress to stderr so it doesn't pollute stdout\n process.stderr.write(`\\r${msg}`);\n }\n },\n });\n\n if (!options.quiet) {\n // Clear the progress line\n process.stderr.write(\"\\r\\x1b[K\");\n\n const parts: string[] = [];\n if (result.newFiles > 0) parts.push(`${result.newFiles} new`);\n if (result.updatedFiles > 0) parts.push(`${result.updatedFiles} updated`);\n if (result.deletedFiles > 0) parts.push(`${result.deletedFiles} deleted`);\n if (result.unchangedFiles > 0) parts.push(`${result.unchangedFiles} unchanged`);\n\n const summary = parts.length > 0 ? parts.join(\", \") : \"no changes\";\n const duration = (result.durationMs / 1000).toFixed(1);\n\n const lines = [`indexed ${result.totalFiles} files (${summary})`, `branch: ${result.branch}`];\n if (result.commit) {\n lines.push(`commit: ${result.commit.slice(0, 7)}`);\n }\n lines.push(`duration: ${duration}s`);\n\n process.stdout.write(lines.join(\"\\n\") + \"\\n\");\n }\n } catch (err) {\n process.stderr.write(`\\r\\x1b[K`);\n process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n}\n","import { openDatabase } from \"../store\";\nimport { type OutputOptions, error, output } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface DependentsOptions extends OutputOptions {}\n\nfunction formatDependents(data: unknown): string {\n const result = data as { file: string; dependents: string[] };\n\n if (result.dependents.length === 0) {\n return `${result.file} is not imported by any indexed file`;\n }\n\n const lines: string[] = [`${result.file} is imported by ${result.dependents.length} file(s)`, \"\"];\n\n for (const dep of result.dependents) {\n lines.push(` ${dep}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function runDependents(\n root: string,\n filePath: string,\n options: DependentsOptions = {},\n): void {\n ensureInitialized(root);\n\n const db = openDatabase(root);\n try {\n const fileIndex = db.getFile(filePath);\n if (!fileIndex) {\n error(`File not found in index: ${filePath}`, `kly query \"${filePath.split(\"/\").pop()}\"`);\n }\n\n const dependents = db.getDependents(filePath);\n const data = { file: filePath, dependents };\n\n output(data, options, formatDependents);\n } finally {\n db.close();\n }\n}\n","import { enrichErrorStack } from \"../enrich\";\nimport { openDatabase } from \"../store\";\nimport type { ErrorFrame } from \"../types\";\nimport { error } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface EnrichOptions {\n frames?: string;\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Uint8Array[] = [];\n process.stdin.on(\"data\", (chunk: Uint8Array) => chunks.push(chunk));\n process.stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n process.stdin.on(\"error\", reject);\n\n // If stdin is a TTY (no pipe), error immediately\n if (process.stdin.isTTY) {\n reject(new Error(\"no input\"));\n }\n });\n}\n\nfunction parseFrames(input: string): ErrorFrame[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(input);\n } catch {\n error(\"Invalid JSON input.\", 'echo \\'[{\"file\":\"src/foo.ts\",\"line\":42}]\\' | kly enrich');\n }\n\n if (!Array.isArray(parsed)) {\n error(\n \"Input must be a JSON array of ErrorFrame objects.\",\n 'kly enrich --frames \\'[{\"file\":\"src/foo.ts\",\"line\":42}]\\'',\n );\n }\n\n for (const [i, frame] of parsed.entries()) {\n if (!frame.file || typeof frame.file !== \"string\") {\n error(`Frame ${i}: missing or invalid \"file\" field.`);\n }\n if (typeof frame.line !== \"number\") {\n error(`Frame ${i}: missing or invalid \"line\" field.`);\n }\n }\n\n return parsed as ErrorFrame[];\n}\n\nexport async function runEnrich(root: string, options: EnrichOptions = {}): Promise<void> {\n ensureInitialized(root);\n\n let input: string;\n\n if (options.frames) {\n input = options.frames;\n } else {\n try {\n input = await readStdin();\n } catch {\n error(\n \"No input provided. Pass frames via --frames or stdin.\",\n 'echo \\'[{\"file\":\"src/foo.ts\",\"line\":42}]\\' | kly enrich\\n kly enrich --frames \\'[{\"file\":\"src/foo.ts\",\"line\":42}]\\'',\n );\n }\n }\n\n const frames = parseFrames(input.trim());\n\n if (frames.length === 0) {\n error(\"Empty frames array.\");\n }\n\n const db = openDatabase(root);\n try {\n const result = enrichErrorStack(db, root, frames);\n // enrich always outputs JSON (structured data, no pretty mode)\n process.stdout.write(JSON.stringify(result, null, 2) + \"\\n\");\n } finally {\n db.close();\n }\n}\n","import { execSync } from \"node:child_process\";\n\nimport { isGitRepo } from \"../git\";\nimport { listBranchDbs, loadState, removeBranchDb, saveState } from \"../store\";\nimport { info, warn } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport function runGc(root: string): void {\n ensureInitialized(root);\n\n if (!isGitRepo(root)) {\n warn(\"not a git repository, nothing to clean\");\n return;\n }\n\n // Get list of active branches\n const branchOutput = execSync(\"git branch --format='%(refname:short)'\", {\n cwd: root,\n encoding: \"utf-8\",\n }).trim();\n\n const activeBranches = new Set(\n branchOutput\n .split(\"\\n\")\n .filter(Boolean)\n .map((b) => b.replace(/'/g, \"\").replace(/\\//g, \"--\")),\n );\n\n // Always keep \"default\"\n activeBranches.add(\"default\");\n\n const dbNames = listBranchDbs(root);\n const state = loadState(root);\n let cleaned = 0;\n\n for (const dbName of dbNames) {\n // Keep active branches and detached HEAD dbs (user should clean those manually)\n if (activeBranches.has(dbName) || dbName.startsWith(\"_detached--\")) {\n continue;\n }\n\n removeBranchDb(root, dbName);\n delete state.branches[dbName];\n cleaned++;\n info(`removed: ${dbName}.db`);\n }\n\n if (cleaned > 0) {\n saveState(root, state);\n info(`cleaned ${cleaned} stale database(s)`);\n } else {\n info(\"no stale databases found\");\n }\n}\n","import {\n type GraphFormat,\n buildDependencyGraph,\n generateMermaid,\n renderGraphAscii,\n renderGraphSvg,\n} from \"../graph\";\nimport { openDatabase } from \"../store\";\nimport { type OutputOptions, error, output } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface GraphOptions extends OutputOptions {\n focus?: string;\n depth?: number;\n format?: GraphFormat;\n}\n\nfunction formatGraph(data: unknown): string {\n const graph = data as {\n nodes: Array<{ path: string; name: string; language: string }>;\n edges: Array<{ from: string; to: string }>;\n };\n\n if (graph.nodes.length === 0) {\n return \"no files indexed yet. run `kly build` first.\";\n }\n\n if (graph.edges.length === 0) {\n return \"no dependencies found between indexed files.\";\n }\n\n // Build adjacency: forward (imports) and reverse (imported by)\n const forward = new Map<string, string[]>();\n const reverse = new Map<string, string[]>();\n for (const edge of graph.edges) {\n if (!forward.has(edge.from)) forward.set(edge.from, []);\n forward.get(edge.from)!.push(edge.to);\n if (!reverse.has(edge.to)) reverse.set(edge.to, []);\n reverse.get(edge.to)!.push(edge.from);\n }\n\n const lines: string[] = [`${graph.nodes.length} node(s), ${graph.edges.length} edge(s)`, \"\"];\n\n for (const node of graph.nodes) {\n lines.push(node.path);\n const deps = forward.get(node.path) || [];\n const dependents = reverse.get(node.path) || [];\n for (const d of deps) {\n lines.push(` -> ${d}`);\n }\n for (const d of dependents) {\n lines.push(` <- ${d}`);\n }\n if (deps.length === 0 && dependents.length === 0) {\n lines.push(\" (no connections)\");\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n}\n\nexport function runGraph(root: string, options: GraphOptions = {}): void {\n ensureInitialized(root);\n\n const depth = options.depth ?? 2;\n const format = options.format ?? (options.pretty ? \"ascii\" : \"mermaid\");\n\n const db = openDatabase(root);\n try {\n const graph = buildDependencyGraph(db, { focus: options.focus, depth });\n\n if (options.focus && !graph.nodes.has(options.focus)) {\n error(`File not in index: ${options.focus}`, `kly query \"${options.focus.split(\"/\").pop()}\"`);\n }\n\n if (format === \"mermaid\" || format === \"ascii\" || format === \"svg\") {\n const mermaid = generateMermaid(graph);\n\n if (graph.nodes.size === 0) {\n console.log(\"no files indexed yet. run `kly build` first.\");\n return;\n }\n if (graph.edges.length === 0) {\n console.log(\"no dependencies found between indexed files.\");\n return;\n }\n\n switch (format) {\n case \"mermaid\":\n console.log(mermaid);\n break;\n case \"ascii\":\n console.log(renderGraphAscii(mermaid));\n break;\n case \"svg\":\n console.log(renderGraphSvg(mermaid));\n break;\n }\n return;\n }\n\n const data = {\n nodes: Array.from(graph.nodes.values()),\n edges: graph.edges,\n };\n\n output(data, options, formatGraph);\n } finally {\n db.close();\n }\n}\n","import { getFileHistory } from \"../git\";\nimport { type OutputOptions, output } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface HistoryOptions extends OutputOptions {\n limit?: number;\n}\n\nfunction formatHistory(data: unknown): string {\n const result = data as {\n file: string;\n commits: Array<{\n hash: string;\n author: string;\n date: number;\n message: string;\n }>;\n };\n\n if (result.commits.length === 0) {\n return `no git history found for ${result.file}`;\n }\n\n const lines: string[] = [];\n\n for (const c of result.commits) {\n const date = new Date(c.date * 1000).toISOString().slice(0, 10);\n lines.push(`${c.hash.slice(0, 7)} @${c.author} ${date} ${c.message}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function runHistory(root: string, filePath: string, options: HistoryOptions = {}): void {\n ensureInitialized(root);\n\n const limit = options.limit ?? 5;\n const commits = getFileHistory(root, filePath, limit);\n\n const data = { file: filePath, commits };\n output(data, options, formatHistory);\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { error, info, warn } from \"./output\";\n\nconst HOOK_BEGIN = \"# BEGIN kly\";\nconst HOOK_END = \"# END kly\";\nconst HOOK_CONTENT = `${HOOK_BEGIN}\nkly build --quiet 2>/dev/null || true\n${HOOK_END}`;\n\nexport function runHook(root: string, action: string): void {\n if (action !== \"install\" && action !== \"uninstall\") {\n error(\"Invalid action.\", \"kly hook install\\n kly hook uninstall\");\n }\n\n const gitDir = path.join(root, \".git\");\n if (!fs.existsSync(gitDir)) {\n error(\"Not a git repository.\");\n }\n\n const hooksDir = path.join(gitDir, \"hooks\");\n const hookPath = path.join(hooksDir, \"post-commit\");\n\n if (action === \"install\") {\n installHook(hooksDir, hookPath);\n } else {\n uninstallHook(hookPath);\n }\n}\n\nfunction installHook(hooksDir: string, hookPath: string): void {\n if (!fs.existsSync(hooksDir)) {\n fs.mkdirSync(hooksDir, { recursive: true });\n }\n\n if (fs.existsSync(hookPath)) {\n const content = fs.readFileSync(hookPath, \"utf-8\");\n if (content.includes(HOOK_BEGIN)) {\n info(\"kly hook already installed (no-op)\");\n return;\n }\n // Append to existing hook\n fs.appendFileSync(hookPath, `\\n${HOOK_CONTENT}\\n`);\n } else {\n fs.writeFileSync(hookPath, `#!/bin/sh\\n${HOOK_CONTENT}\\n`, { mode: 0o755 });\n }\n\n info(\"installed post-commit hook\");\n}\n\nfunction uninstallHook(hookPath: string): void {\n if (!fs.existsSync(hookPath)) {\n warn(\"no post-commit hook found (no-op)\");\n return;\n }\n\n const content = fs.readFileSync(hookPath, \"utf-8\");\n if (!content.includes(HOOK_BEGIN)) {\n warn(\"kly hook not found in post-commit (no-op)\");\n return;\n }\n\n // Remove the kly block\n const regex = new RegExp(`\\\\n?${HOOK_BEGIN}[\\\\s\\\\S]*?${HOOK_END}\\\\n?`, \"g\");\n const updated = content.replace(regex, \"\\n\").trim();\n\n if (updated === \"#!/bin/sh\" || updated === \"\") {\n fs.unlinkSync(hookPath);\n } else {\n fs.writeFileSync(hookPath, updated + \"\\n\", { mode: 0o755 });\n }\n\n info(\"uninstalled post-commit hook\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport * as p from \"@clack/prompts\";\n\nimport { initKlyDir, isInitialized } from \"../config\";\nimport type { KlyConfig } from \"../types\";\nimport { runHook } from \"./hook\";\nimport { info } from \"./output\";\n\nexport interface InitOptions {\n provider?: string;\n model?: string;\n apiKey?: string;\n hook?: boolean;\n include?: string[];\n exclude?: string[];\n}\n\nconst VALID_PROVIDERS = [\"openrouter\", \"anthropic\", \"openai\", \"google\", \"mistral\", \"groq\"];\n\nconst DEFAULT_MODELS: Record<string, string> = {\n openrouter: \"anthropic/claude-haiku-4.5\",\n anthropic: \"claude-haiku-4.5\",\n openai: \"gpt-4o-mini\",\n google: \"gemini-2.0-flash\",\n mistral: \"mistral-small-latest\",\n groq: \"llama-3.1-8b-instant\",\n};\n\nconst DEFAULT_INCLUDE = [\"**/*.ts\", \"**/*.tsx\", \"**/*.js\", \"**/*.jsx\", \"**/*.swift\"];\nconst DEFAULT_EXCLUDE = [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/.git/**\",\n \"**/.kly/**\",\n \"**/vendor/**\",\n \"**/*.d.ts\",\n \"**/*.test.*\",\n \"**/*.spec.*\",\n \"**/__tests__/**\",\n];\n\nexport async function runInit(root: string, options: InitOptions = {}): Promise<void> {\n // If provider and api-key are provided, run non-interactively\n if (options.provider && options.apiKey) {\n runNonInteractive(root, options);\n return;\n }\n\n // Fallback to interactive mode\n await runInteractive(root, options);\n}\n\nfunction runNonInteractive(root: string, options: InitOptions): void {\n if (!VALID_PROVIDERS.includes(options.provider!)) {\n process.stderr.write(\n `Error: Invalid provider \"${options.provider}\".\\n Valid providers: ${VALID_PROVIDERS.join(\", \")}\\n kly init --provider openrouter --api-key <key>\\n`,\n );\n process.exit(1);\n }\n\n const config: KlyConfig = {\n llm: {\n provider: options.provider!,\n model: options.model || DEFAULT_MODELS[options.provider!] || \"\",\n apiKey: options.apiKey!,\n },\n include: options.include?.length ? options.include : DEFAULT_INCLUDE,\n exclude: options.exclude?.length ? options.exclude : DEFAULT_EXCLUDE,\n };\n\n initKlyDir(root, config);\n info(\"initialized .kly/ directory\");\n\n if (options.hook) {\n const isGit = fs.existsSync(path.join(root, \".git\"));\n if (isGit) {\n runHook(root, \"install\");\n info(\"installed post-commit hook\");\n } else {\n process.stderr.write(\"Warning: Not a git repo, skipping hook install.\\n\");\n }\n }\n}\n\nasync function runInteractive(root: string, _options: InitOptions): Promise<void> {\n p.intro(\"kly init\");\n\n if (isInitialized(root)) {\n p.log.warn(\".kly/ directory already exists, reconfiguring...\");\n }\n\n const provider = await p.select({\n message: \"Select LLM provider\",\n options: [\n { value: \"openrouter\", label: \"OpenRouter\", hint: \"recommended, supports all models\" },\n { value: \"anthropic\", label: \"Anthropic\" },\n { value: \"openai\", label: \"OpenAI\" },\n { value: \"google\", label: \"Google\" },\n { value: \"mistral\", label: \"Mistral\" },\n { value: \"groq\", label: \"Groq\" },\n ],\n });\n\n if (p.isCancel(provider)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n const apiKey = await p.password({\n message: `Enter your ${provider} API key`,\n validate: (value) => {\n if (!value || value.trim().length === 0) {\n return \"API key is required\";\n }\n },\n });\n\n if (p.isCancel(apiKey)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n const model = await p.text({\n message: \"Model name\",\n initialValue: DEFAULT_MODELS[provider] || \"\",\n validate: (value) => {\n if (!value || value.trim().length === 0) {\n return \"Model name is required\";\n }\n },\n });\n\n if (p.isCancel(model)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n const config: KlyConfig = {\n llm: {\n provider,\n model,\n apiKey,\n },\n include: DEFAULT_INCLUDE,\n exclude: DEFAULT_EXCLUDE,\n };\n\n initKlyDir(root, config);\n\n p.log.success(\"Initialized .kly/ directory\");\n p.log.info(\"Edit .kly/config.yaml to customize settings\");\n\n // Offer to install git hook if in a git repo\n const isGit = fs.existsSync(path.join(root, \".git\"));\n if (isGit) {\n const installHook = await p.confirm({\n message: \"Install post-commit hook for automatic indexing?\",\n initialValue: true,\n });\n\n if (!p.isCancel(installHook) && installHook) {\n runHook(root, \"install\");\n }\n }\n\n p.outro(\"Done!\");\n}\n","import { openDatabase } from \"../store\";\nimport { type OutputOptions, output } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface OverviewOptions extends OutputOptions {}\n\nfunction formatOverview(data: unknown): string {\n const overview = data as {\n totalFiles: number;\n languages: Record<string, number>;\n files: Array<{ path: string; name: string; description: string }>;\n };\n\n if (overview.totalFiles === 0) {\n return \"no files indexed yet. run `kly build` first.\";\n }\n\n const lines: string[] = [`total_files: ${overview.totalFiles}`, \"\", \"languages:\"];\n\n const sorted = Object.entries(overview.languages).sort(([, a], [, b]) => b - a);\n for (const [lang, count] of sorted) {\n const pct = ((count / overview.totalFiles) * 100).toFixed(1);\n lines.push(` ${lang}: ${count} (${pct}%)`);\n }\n\n lines.push(\"\", \"files:\");\n for (const file of overview.files) {\n lines.push(` ${file.path}`);\n if (file.description) {\n lines.push(` ${file.description}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function runOverview(root: string, options: OverviewOptions = {}): void {\n ensureInitialized(root);\n\n const db = openDatabase(root);\n try {\n const totalFiles = db.getFileCount();\n const languages = db.getLanguageStats();\n const allFiles = db.getAllFiles();\n\n const data = {\n totalFiles,\n languages,\n files: allFiles.map((f) => ({\n path: f.path,\n name: f.name,\n description: f.description,\n })),\n };\n\n output(data, options, formatOverview);\n } finally {\n db.close();\n }\n}\n","import { getModel } from \"@mariozechner/pi-ai\";\nimport type { Api, Model, Provider } from \"@mariozechner/pi-ai\";\n\nimport { loadConfig } from \"../config\";\nimport type { SearchResult } from \"../database\";\nimport { searchFiles, searchFilesWithRerank } from \"../query\";\nimport { openDatabase } from \"../store\";\nimport { type OutputOptions, info, output } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface QueryOptions extends OutputOptions {\n rerank?: boolean;\n limit?: number;\n}\n\nfunction formatResults(data: unknown): string {\n const results = data as Array<{\n path: string;\n name: string;\n description: string;\n score: number;\n summary: string;\n symbols: string[];\n }>;\n\n if (results.length === 0) {\n return \"no matching files found\";\n }\n\n const lines: string[] = [`found ${results.length} file(s)`, \"\"];\n\n for (const r of results) {\n lines.push(r.path);\n lines.push(` name: ${r.name}`);\n lines.push(` description: ${r.description}`);\n lines.push(` score: ${r.score.toFixed(2)}`);\n if (r.summary) {\n const summary = r.summary.replace(/\\s+/g, \" \").trim();\n lines.push(` summary: ${summary.length > 120 ? summary.slice(0, 117) + \"...\" : summary}`);\n }\n if (r.symbols.length > 0) {\n const shown = r.symbols.slice(0, 5);\n const more = r.symbols.length - shown.length;\n lines.push(` symbols: ${shown.join(\", \")}${more > 0 ? ` (+${more} more)` : \"\"}`);\n }\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\").trimEnd();\n}\n\nfunction toOutputData(results: SearchResult[]) {\n return results.map((r) => ({\n path: r.file.path,\n name: r.file.name,\n description: r.file.description,\n score: r.score,\n summary: r.file.summary,\n language: r.file.language,\n symbols: r.file.symbols.map((s) => s.name),\n }));\n}\n\nexport async function runQuery(\n root: string,\n description: string,\n options: QueryOptions = {},\n): Promise<void> {\n ensureInitialized(root);\n\n const limit = options.limit ?? 10;\n const db = openDatabase(root);\n\n try {\n let results: SearchResult[];\n\n if (options.rerank) {\n const config = loadConfig(root);\n const model = (getModel as (p: Provider, m: string) => Model<Api>)(\n config.llm.provider,\n config.llm.model,\n );\n\n const envKeyMap: Record<string, string> = {\n openrouter: \"OPENROUTER_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n google: \"GOOGLE_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n groq: \"GROQ_API_KEY\",\n xai: \"XAI_API_KEY\",\n };\n const envKey =\n envKeyMap[config.llm.provider] || `${config.llm.provider.toUpperCase()}_API_KEY`;\n if (config.llm.apiKey && !process.env[envKey]) {\n process.env[envKey] = config.llm.apiKey;\n }\n\n if (options.pretty) {\n info(\"reranking results with LLM...\");\n }\n results = await searchFilesWithRerank(db, model, description, limit);\n } else {\n results = searchFiles(db, description, limit);\n }\n\n const data = toOutputData(results);\n output(data, options, formatResults);\n } finally {\n db.close();\n }\n}\n","import { openDatabase } from \"../store\";\nimport { type OutputOptions, error, output } from \"./output\";\nimport { ensureInitialized } from \"./shared\";\n\nexport interface ShowOptions extends OutputOptions {}\n\nfunction formatFile(data: unknown): string {\n const file = data as {\n path: string;\n name: string;\n description: string;\n language: string;\n summary: string;\n imports: string[];\n exports: string[];\n symbols: Array<{ kind: string; name: string; description: string }>;\n hash: string;\n indexedAt: string;\n };\n\n const lines: string[] = [\n `path: ${file.path}`,\n `name: ${file.name}`,\n `language: ${file.language}`,\n `description: ${file.description}`,\n ];\n\n if (file.summary) {\n lines.push(`summary: ${file.summary}`);\n }\n\n if (file.imports.length > 0) {\n lines.push(\"\", `imports (${file.imports.length}):`);\n for (const imp of file.imports) {\n lines.push(` ${imp}`);\n }\n }\n\n if (file.exports.length > 0) {\n lines.push(\"\", `exports (${file.exports.length}):`);\n for (const exp of file.exports) {\n lines.push(` ${exp}`);\n }\n }\n\n if (file.symbols.length > 0) {\n lines.push(\"\", `symbols (${file.symbols.length}):`);\n for (const s of file.symbols) {\n lines.push(` ${s.kind} ${s.name}`);\n if (s.description) {\n lines.push(` ${s.description}`);\n }\n }\n }\n\n lines.push(\"\", `hash: ${file.hash}`, `indexed_at: ${file.indexedAt}`);\n\n return lines.join(\"\\n\");\n}\n\nexport function runShow(root: string, filePath: string, options: ShowOptions = {}): void {\n ensureInitialized(root);\n\n const db = openDatabase(root);\n try {\n const fileIndex = db.getFile(filePath);\n\n if (!fileIndex) {\n error(`File not found in index: ${filePath}`, `kly query \"${filePath.split(\"/\").pop()}\"`);\n }\n\n const data = {\n path: fileIndex.path,\n name: fileIndex.name,\n description: fileIndex.description,\n language: fileIndex.language,\n summary: fileIndex.summary,\n imports: fileIndex.imports,\n exports: fileIndex.exports,\n symbols: fileIndex.symbols,\n hash: fileIndex.hash,\n indexedAt: new Date(fileIndex.indexedAt).toISOString(),\n };\n\n output(data, options, formatFile);\n } finally {\n db.close();\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\n\nimport { runBuild } from \"./commands/build\";\nimport { runDependents } from \"./commands/dependents\";\nimport { runEnrich } from \"./commands/enrich\";\nimport { runGc } from \"./commands/gc\";\nimport { runGraph } from \"./commands/graph\";\nimport { runHistory } from \"./commands/history\";\nimport { runHook } from \"./commands/hook\";\nimport { runInit } from \"./commands/init\";\nimport { runOverview } from \"./commands/overview\";\nimport { runQuery } from \"./commands/query\";\nimport { runShow } from \"./commands/show\";\n\nconst program = new Command();\n\nprogram\n .name(\"kly\")\n .description(\"Code repository file-level indexing tool\")\n .version(\"0.2.0\")\n .showHelpAfterError()\n .showSuggestionAfterError();\n\n// --- init ---\n\nprogram\n .command(\"init\")\n .description(\"Initialize kly in the current repository\")\n .option(\n \"--provider <name>\",\n \"LLM provider (openrouter, anthropic, openai, google, mistral, groq)\",\n )\n .option(\"--model <name>\", \"Model name (default: provider-specific)\")\n .option(\"--api-key <key>\", \"API key (or set via env variable)\")\n .option(\"--hook\", \"Also install post-commit hook\")\n .option(\"--include <glob...>\", \"File include patterns\")\n .option(\"--exclude <glob...>\", \"File exclude patterns\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly init --provider openrouter --api-key sk-or-xxx\n kly init --provider anthropic --model claude-haiku-4.5 --api-key sk-ant-xxx --hook\n kly init # interactive mode (no flags)\n`,\n )\n .action(async (options) => {\n await runInit(process.cwd(), options);\n });\n\n// --- build ---\n\nprogram\n .command(\"build\")\n .description(\"Build or update the repository index\")\n .option(\"--full\", \"Force full rebuild\")\n .option(\"--quiet\", \"Suppress output (for git hooks)\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly build # incremental build\n kly build --full # full rebuild\n kly build --full --quiet # CI / git hook mode\n`,\n )\n .action(async (options: { full?: boolean; quiet?: boolean }) => {\n await runBuild(process.cwd(), options);\n });\n\n// --- query ---\n\nprogram\n .command(\"query <text>\")\n .description(\"Search indexed files by natural language description\")\n .option(\"--rerank\", \"Use LLM to rerank results for better relevance\")\n .option(\"--limit <n>\", \"Maximum results\", \"10\")\n .option(\"--pretty\", \"Human-readable output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly query \"authentication middleware\"\n kly query \"error handling\" --limit 5\n kly query \"database migration\" --rerank\n kly query \"auth\" --pretty\n`,\n )\n .action(async (text: string, options: { rerank?: boolean; limit?: string; pretty?: boolean }) => {\n await runQuery(process.cwd(), text, {\n rerank: options.rerank,\n limit: options.limit ? parseInt(options.limit, 10) : undefined,\n pretty: options.pretty,\n });\n });\n\n// --- show ---\n\nprogram\n .command(\"show <path>\")\n .description(\"Show indexed metadata for a file\")\n .option(\"--pretty\", \"Human-readable output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly show src/auth.ts\n kly show src/auth.ts --pretty\n`,\n )\n .action((filePath: string, options: { pretty?: boolean }) => {\n runShow(process.cwd(), filePath, options);\n });\n\n// --- overview ---\n\nprogram\n .command(\"overview\")\n .description(\"Show repository index summary with language breakdown\")\n .option(\"--pretty\", \"Human-readable output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly overview\n kly overview --pretty\n`,\n )\n .action((options: { pretty?: boolean }) => {\n runOverview(process.cwd(), options);\n });\n\n// --- graph ---\n\nprogram\n .command(\"graph\")\n .description(\"Show file dependency graph\")\n .option(\"--focus <path>\", \"Focus on a specific file\")\n .option(\"--depth <n>\", \"Traversal depth\", \"2\")\n .option(\n \"--format <type>\",\n \"Output format: mermaid, json, ascii, svg (default: mermaid, or ascii with --pretty)\",\n )\n .option(\"--pretty\", \"Human-readable output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly graph\n kly graph --format ascii\n kly graph --format svg --focus src/auth.ts --depth 3\n kly graph --format mermaid\n kly graph --pretty\n`,\n )\n .action((options: { focus?: string; depth?: string; format?: string; pretty?: boolean }) => {\n runGraph(process.cwd(), {\n focus: options.focus,\n depth: options.depth ? parseInt(options.depth, 10) : undefined,\n format: options.format as \"json\" | \"mermaid\" | \"ascii\" | \"svg\" | undefined,\n pretty: options.pretty,\n });\n });\n\n// --- dependents ---\n\nprogram\n .command(\"dependents <path>\")\n .description(\"Show files that import the given file (reverse dependencies)\")\n .option(\"--pretty\", \"Human-readable output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly dependents src/database.ts\n kly dependents src/types.ts --pretty\n`,\n )\n .action((filePath: string, options: { pretty?: boolean }) => {\n runDependents(process.cwd(), filePath, options);\n });\n\n// --- history ---\n\nprogram\n .command(\"history <path>\")\n .description(\"Show recent git modification history for a file\")\n .option(\"--limit <n>\", \"Number of commits\", \"5\")\n .option(\"--pretty\", \"Human-readable output\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly history src/auth.ts\n kly history src/auth.ts --limit 10\n kly history src/auth.ts --pretty\n`,\n )\n .action((filePath: string, options: { limit?: string; pretty?: boolean }) => {\n runHistory(process.cwd(), filePath, {\n limit: options.limit ? parseInt(options.limit, 10) : undefined,\n pretty: options.pretty,\n });\n });\n\n// --- enrich ---\n\nprogram\n .command(\"enrich\")\n .description(\"Enrich error stack frames with file descriptions, dependencies, and git history\")\n .option(\"--frames <json>\", \"Error frames as JSON string\")\n .addHelpText(\n \"after\",\n `\nInput: JSON array of ErrorFrame objects via --frames or stdin.\nEach frame: { \"file\": \"path\", \"line\": number, \"column?\": number, \"function?\": \"name\" }\n\nExamples:\n echo '[{\"file\":\"src/auth.ts\",\"line\":42}]' | kly enrich\n kly enrich --frames '[{\"file\":\"src/auth.ts\",\"line\":42,\"function\":\"validate\"}]'\n cat error-frames.json | kly enrich\n`,\n )\n .action(async (options: { frames?: string }) => {\n await runEnrich(process.cwd(), options);\n });\n\n// --- hook ---\n\nprogram\n .command(\"hook <action>\")\n .description(\"Install or uninstall the post-commit hook\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly hook install\n kly hook uninstall\n`,\n )\n .action((action: string) => {\n runHook(process.cwd(), action);\n });\n\n// --- gc ---\n\nprogram\n .command(\"gc\")\n .description(\"Remove databases for deleted git branches\")\n .addHelpText(\n \"after\",\n `\nExamples:\n kly gc\n`,\n )\n .action(() => {\n runGc(process.cwd());\n });\n\nawait program.parseAsync();\n"],"mappings":"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"}