kirograph 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +332 -93
  2. package/dist/bin/commands/caveman.js +19 -2
  3. package/dist/bin/commands/caveman.js.map +2 -2
  4. package/dist/bin/commands/compression.js +109 -0
  5. package/dist/bin/commands/compression.js.map +7 -0
  6. package/dist/bin/commands/context.js +31 -24
  7. package/dist/bin/commands/context.js.map +2 -2
  8. package/dist/bin/commands/exec.js +107 -0
  9. package/dist/bin/commands/exec.js.map +7 -0
  10. package/dist/bin/commands/gain.js +119 -0
  11. package/dist/bin/commands/gain.js.map +7 -0
  12. package/dist/bin/commands/help.js +16 -5
  13. package/dist/bin/commands/help.js.map +2 -2
  14. package/dist/bin/commands/install.js +8 -2
  15. package/dist/bin/commands/install.js.map +2 -2
  16. package/dist/bin/commands/query.js +5 -1
  17. package/dist/bin/commands/query.js.map +2 -2
  18. package/dist/bin/commands/serve.js +2 -2
  19. package/dist/bin/commands/serve.js.map +2 -2
  20. package/dist/bin/commands/uninit.js +65 -41
  21. package/dist/bin/commands/uninit.js.map +2 -2
  22. package/dist/bin/commands/utils.js +16 -0
  23. package/dist/bin/commands/utils.js.map +2 -2
  24. package/dist/bin/installer/cli-agent.js +5 -25
  25. package/dist/bin/installer/cli-agent.js.map +2 -2
  26. package/dist/bin/installer/common.js +154 -0
  27. package/dist/bin/installer/common.js.map +7 -0
  28. package/dist/bin/installer/config-prompt.js +9 -2
  29. package/dist/bin/installer/config-prompt.js.map +2 -2
  30. package/dist/bin/installer/hooks.js +19 -1
  31. package/dist/bin/installer/hooks.js.map +2 -2
  32. package/dist/bin/installer/index.js +104 -86
  33. package/dist/bin/installer/index.js.map +2 -2
  34. package/dist/bin/installer/instructions.js +60 -0
  35. package/dist/bin/installer/instructions.js.map +7 -0
  36. package/dist/bin/installer/mcp.js +6 -36
  37. package/dist/bin/installer/mcp.js.map +2 -2
  38. package/dist/bin/installer/steering.js +116 -40
  39. package/dist/bin/installer/steering.js.map +2 -2
  40. package/dist/bin/installer/targets/claude.js +79 -0
  41. package/dist/bin/installer/targets/claude.js.map +7 -0
  42. package/dist/bin/installer/targets/codex.js +77 -0
  43. package/dist/bin/installer/targets/codex.js.map +7 -0
  44. package/dist/bin/installer/targets/index.js +57 -0
  45. package/dist/bin/installer/targets/index.js.map +7 -0
  46. package/dist/bin/installer/targets/kiro.js +63 -0
  47. package/dist/bin/installer/targets/kiro.js.map +7 -0
  48. package/dist/bin/kirograph.js +7 -1
  49. package/dist/bin/kirograph.js.map +3 -3
  50. package/dist/compression/filters/aws.js +418 -0
  51. package/dist/compression/filters/aws.js.map +7 -0
  52. package/dist/compression/filters/docker.js +153 -0
  53. package/dist/compression/filters/docker.js.map +7 -0
  54. package/dist/compression/filters/files.js +150 -0
  55. package/dist/compression/filters/files.js.map +7 -0
  56. package/dist/compression/filters/generic.js +86 -0
  57. package/dist/compression/filters/generic.js.map +7 -0
  58. package/dist/compression/filters/git.js +272 -0
  59. package/dist/compression/filters/git.js.map +7 -0
  60. package/dist/compression/filters/github.js +137 -0
  61. package/dist/compression/filters/github.js.map +7 -0
  62. package/dist/compression/filters/lint.js +280 -0
  63. package/dist/compression/filters/lint.js.map +7 -0
  64. package/dist/compression/filters/misc.js +212 -0
  65. package/dist/compression/filters/misc.js.map +7 -0
  66. package/dist/compression/filters/package.js +151 -0
  67. package/dist/compression/filters/package.js.map +7 -0
  68. package/dist/compression/filters/test.js +266 -0
  69. package/dist/compression/filters/test.js.map +7 -0
  70. package/dist/compression/index.js +144 -0
  71. package/dist/compression/index.js.map +7 -0
  72. package/dist/compression/naive-cost.js +94 -0
  73. package/dist/compression/naive-cost.js.map +7 -0
  74. package/dist/compression/tracker.js +228 -0
  75. package/dist/compression/tracker.js.map +7 -0
  76. package/dist/compression/types.js +17 -0
  77. package/dist/compression/types.js.map +7 -0
  78. package/dist/config.js +18 -1
  79. package/dist/config.js.map +2 -2
  80. package/dist/mcp/tool-names.js +50 -0
  81. package/dist/mcp/tool-names.js.map +7 -0
  82. package/dist/mcp/tools.js +173 -4
  83. package/dist/mcp/tools.js.map +3 -3
  84. package/package.json +2 -2
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var common_exports = {};
30
+ __export(common_exports, {
31
+ KIROGRAPH_COMMAND: () => KIROGRAPH_COMMAND,
32
+ KIROGRAPH_MCP_ARGS: () => KIROGRAPH_MCP_ARGS,
33
+ KIROGRAPH_SCOPED_TOOLS: () => KIROGRAPH_SCOPED_TOOLS,
34
+ KIROGRAPH_SERVER_NAME: () => KIROGRAPH_SERVER_NAME,
35
+ KIROGRAPH_SYNC_CMD: () => KIROGRAPH_SYNC_CMD,
36
+ KIROGRAPH_TOOLS: () => KIROGRAPH_TOOLS,
37
+ appendImportLine: () => appendImportLine,
38
+ ensureDir: () => ensureDir,
39
+ readJson: () => readJson,
40
+ removeGeneratedBlock: () => removeGeneratedBlock,
41
+ removeImportLine: () => removeImportLine,
42
+ removeMcpServersConfig: () => removeMcpServersConfig,
43
+ upsertGeneratedBlock: () => upsertGeneratedBlock,
44
+ writeJson: () => writeJson,
45
+ writeMcpServersConfig: () => writeMcpServersConfig
46
+ });
47
+ module.exports = __toCommonJS(common_exports);
48
+ var fs = __toESM(require("fs"));
49
+ var path = __toESM(require("path"));
50
+ var import_tool_names = require("../../mcp/tool-names");
51
+ const KIROGRAPH_SERVER_NAME = "kirograph";
52
+ const KIROGRAPH_COMMAND = "kirograph";
53
+ const KIROGRAPH_MCP_ARGS = ["serve", "--mcp"];
54
+ const KIROGRAPH_SYNC_CMD = "kirograph sync-if-dirty --quiet 2>/dev/null || true";
55
+ const KIROGRAPH_TOOLS = import_tool_names.KIROGRAPH_TOOL_NAMES;
56
+ const KIROGRAPH_SCOPED_TOOLS = import_tool_names.KIROGRAPH_TOOL_NAMES.map((name) => `@kirograph/${name}`);
57
+ function ensureDir(p) {
58
+ fs.mkdirSync(p, { recursive: true });
59
+ }
60
+ function readJson(p) {
61
+ try {
62
+ return JSON.parse(fs.readFileSync(p, "utf8"));
63
+ } catch {
64
+ return {};
65
+ }
66
+ }
67
+ function writeJson(p, data) {
68
+ fs.writeFileSync(p, JSON.stringify(data, null, 2) + "\n");
69
+ }
70
+ function writeMcpServersConfig(configPath, serverConfig) {
71
+ ensureDir(path.dirname(configPath));
72
+ const existing = readJson(configPath);
73
+ existing.mcpServers = existing.mcpServers ?? {};
74
+ existing.mcpServers[KIROGRAPH_SERVER_NAME] = serverConfig;
75
+ writeJson(configPath, existing);
76
+ }
77
+ function removeMcpServersConfig(configPath) {
78
+ if (!fs.existsSync(configPath)) return false;
79
+ const existing = readJson(configPath);
80
+ if (!existing.mcpServers?.[KIROGRAPH_SERVER_NAME]) return false;
81
+ delete existing.mcpServers[KIROGRAPH_SERVER_NAME];
82
+ writeJson(configPath, existing);
83
+ return true;
84
+ }
85
+ function appendImportLine(filePath, line, heading) {
86
+ const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : "";
87
+ if (existing.includes(line)) return false;
88
+ const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
89
+ const separator = existing.trim().length > 0 ? "\n" : "";
90
+ fs.writeFileSync(filePath, existing + prefix + separator + heading + "\n" + line + "\n");
91
+ return true;
92
+ }
93
+ function removeImportLine(filePath, line) {
94
+ if (!fs.existsSync(filePath)) return false;
95
+ const original = fs.readFileSync(filePath, "utf8");
96
+ const next = original.split("\n").filter((l) => l.trim() !== line).join("\n").replace(/\n{3,}/g, "\n\n");
97
+ if (next === original) return false;
98
+ fs.writeFileSync(filePath, next.endsWith("\n") ? next : next + "\n");
99
+ return true;
100
+ }
101
+ function upsertGeneratedBlock(filePath, blockId, heading, content) {
102
+ const start = `<!-- kirograph:${blockId}:start -->`;
103
+ const end = `<!-- kirograph:${blockId}:end -->`;
104
+ const block = `${start}
105
+ ${heading}
106
+
107
+ ${content.trim()}
108
+ ${end}`;
109
+ const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : "";
110
+ const pattern = new RegExp(`${escapeRegExp(start)}[\\s\\S]*?${escapeRegExp(end)}`);
111
+ if (pattern.test(existing)) {
112
+ const next = existing.replace(pattern, block);
113
+ if (next === existing) return false;
114
+ fs.writeFileSync(filePath, next.endsWith("\n") ? next : next + "\n");
115
+ return true;
116
+ }
117
+ const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
118
+ const separator = existing.trim().length > 0 ? "\n" : "";
119
+ fs.writeFileSync(filePath, existing + prefix + separator + block + "\n");
120
+ return true;
121
+ }
122
+ function removeGeneratedBlock(filePath, blockId) {
123
+ if (!fs.existsSync(filePath)) return false;
124
+ const start = `<!-- kirograph:${blockId}:start -->`;
125
+ const end = `<!-- kirograph:${blockId}:end -->`;
126
+ const original = fs.readFileSync(filePath, "utf8");
127
+ const pattern = new RegExp(`\\n?${escapeRegExp(start)}[\\s\\S]*?${escapeRegExp(end)}\\n?`);
128
+ const next = original.replace(pattern, "\n").replace(/\n{3,}/g, "\n\n");
129
+ if (next === original) return false;
130
+ fs.writeFileSync(filePath, next.endsWith("\n") ? next : next + "\n");
131
+ return true;
132
+ }
133
+ function escapeRegExp(s) {
134
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
135
+ }
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {
138
+ KIROGRAPH_COMMAND,
139
+ KIROGRAPH_MCP_ARGS,
140
+ KIROGRAPH_SCOPED_TOOLS,
141
+ KIROGRAPH_SERVER_NAME,
142
+ KIROGRAPH_SYNC_CMD,
143
+ KIROGRAPH_TOOLS,
144
+ appendImportLine,
145
+ ensureDir,
146
+ readJson,
147
+ removeGeneratedBlock,
148
+ removeImportLine,
149
+ removeMcpServersConfig,
150
+ upsertGeneratedBlock,
151
+ writeJson,
152
+ writeMcpServersConfig
153
+ });
154
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/bin/installer/common.ts"],
4
+ "sourcesContent": ["import * as fs from 'fs';\nimport * as path from 'path';\nimport { KIROGRAPH_TOOL_NAMES } from '../../mcp/tool-names';\n\nexport type InstallTarget = 'kiro' | 'claude' | 'codex';\n\nexport const KIROGRAPH_SERVER_NAME = 'kirograph';\nexport const KIROGRAPH_COMMAND = 'kirograph';\nexport const KIROGRAPH_MCP_ARGS = ['serve', '--mcp'];\nexport const KIROGRAPH_SYNC_CMD = 'kirograph sync-if-dirty --quiet 2>/dev/null || true';\nexport const KIROGRAPH_TOOLS = KIROGRAPH_TOOL_NAMES;\nexport const KIROGRAPH_SCOPED_TOOLS = KIROGRAPH_TOOL_NAMES.map(name => `@kirograph/${name}`);\n\nexport function ensureDir(p: string): void {\n fs.mkdirSync(p, { recursive: true });\n}\n\nexport function readJson(p: string): any {\n try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return {}; }\n}\n\nexport function writeJson(p: string, data: unknown): void {\n fs.writeFileSync(p, JSON.stringify(data, null, 2) + '\\n');\n}\n\nexport function writeMcpServersConfig(configPath: string, serverConfig: object): void {\n ensureDir(path.dirname(configPath));\n const existing = readJson(configPath);\n existing.mcpServers = existing.mcpServers ?? {};\n existing.mcpServers[KIROGRAPH_SERVER_NAME] = serverConfig;\n writeJson(configPath, existing);\n}\n\nexport function removeMcpServersConfig(configPath: string): boolean {\n if (!fs.existsSync(configPath)) return false;\n const existing = readJson(configPath);\n if (!existing.mcpServers?.[KIROGRAPH_SERVER_NAME]) return false;\n delete existing.mcpServers[KIROGRAPH_SERVER_NAME];\n writeJson(configPath, existing);\n return true;\n}\n\nexport function appendImportLine(filePath: string, line: string, heading: string): boolean {\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';\n if (existing.includes(line)) return false;\n\n const prefix = existing.length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const separator = existing.trim().length > 0 ? '\\n' : '';\n fs.writeFileSync(filePath, existing + prefix + separator + heading + '\\n' + line + '\\n');\n return true;\n}\n\nexport function removeImportLine(filePath: string, line: string): boolean {\n if (!fs.existsSync(filePath)) return false;\n const original = fs.readFileSync(filePath, 'utf8');\n const next = original\n .split('\\n')\n .filter(l => l.trim() !== line)\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n');\n if (next === original) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n}\n\nexport function upsertGeneratedBlock(filePath: string, blockId: string, heading: string, content: string): boolean {\n const start = `<!-- kirograph:${blockId}:start -->`;\n const end = `<!-- kirograph:${blockId}:end -->`;\n const block = `${start}\\n${heading}\\n\\n${content.trim()}\\n${end}`;\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';\n const pattern = new RegExp(`${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}`);\n\n if (pattern.test(existing)) {\n const next = existing.replace(pattern, block);\n if (next === existing) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n }\n\n const prefix = existing.length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const separator = existing.trim().length > 0 ? '\\n' : '';\n fs.writeFileSync(filePath, existing + prefix + separator + block + '\\n');\n return true;\n}\n\nexport function removeGeneratedBlock(filePath: string, blockId: string): boolean {\n if (!fs.existsSync(filePath)) return false;\n const start = `<!-- kirograph:${blockId}:start -->`;\n const end = `<!-- kirograph:${blockId}:end -->`;\n const original = fs.readFileSync(filePath, 'utf8');\n const pattern = new RegExp(`\\\\n?${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}\\\\n?`);\n const next = original.replace(pattern, '\\n').replace(/\\n{3,}/g, '\\n\\n');\n if (next === original) return false;\n fs.writeFileSync(filePath, next.endsWith('\\n') ? next : next + '\\n');\n return true;\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -62,7 +62,7 @@ async function promptConfigOptions(rl) {
62
62
  "Enable semantic embeddings for similarity search? (requires a local embedding model)",
63
63
  "Enables semantic/similarity-based code search. Increases indexing time; the chosen embedding model is downloaded automatically on first use."
64
64
  );
65
- const patch = { enableEmbeddings, useVecIndex: false, semanticEngine: "cosine", typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: "off" };
65
+ const patch = { enableEmbeddings, useVecIndex: false, semanticEngine: "cosine", typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: "off", shellCompressionLevel: "normal" };
66
66
  if (enableEmbeddings) {
67
67
  const modelChoice = await (0, import_prompts.arrowSelect)(
68
68
  rl,
@@ -141,13 +141,20 @@ async function promptConfigOptions(rl) {
141
141
  "Enable architecture analysis (package graph + layer detection)?",
142
142
  "Detects packages from manifests (package.json, go.mod, Cargo.toml, etc.) and architectural layers (api, service, data, ui, shared) from file structure. Enables kirograph_architecture, kirograph_coupling, and kirograph_package MCP tools."
143
143
  );
144
- const cavemanChoice = await (0, import_prompts.arrowSelect)(rl, "Caveman mode \u2014 agent communication style:", [
144
+ const cavemanChoice = await (0, import_prompts.arrowSelect)(rl, "Caveman mode: agent communication style:", [
145
145
  { value: "off", label: "off", description: "Normal responses" },
146
146
  { value: "lite", label: "lite", description: "Compact, no filler, full sentences" },
147
147
  { value: "full", label: "full", description: "Fragments, no articles, short synonyms" },
148
148
  { value: "ultra", label: "ultra", description: "Max compression, abbreviations, \u2192 for causality" }
149
149
  ]);
150
150
  patch.cavemanMode = cavemanChoice;
151
+ const compressionChoice = await (0, import_prompts.arrowSelect)(rl, "Shell compression: default level for kirograph_exec:", [
152
+ { value: "off", label: "off", description: "No compression hook or steering (tool still available)" },
153
+ { value: "normal", label: "normal", description: "Balanced: removes noise, keeps structure (recommended)" },
154
+ { value: "aggressive", label: "aggressive", description: "More compact: groups by category, limits output" },
155
+ { value: "ultra", label: "ultra", description: "Maximum compression: counts and summaries only" }
156
+ ]);
157
+ patch.shellCompressionLevel = compressionChoice;
151
158
  return patch;
152
159
  }
153
160
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/installer/config-prompt.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph Installer \u2014 configuration prompting\n */\n\nimport * as readline from 'readline';\nimport { KiroGraphConfig } from '../../config';\ntype CavemanMode = 'lite' | 'full' | 'ultra';\nimport { ask, askBool, arrowSelect, dim, reset, violet } from './prompts';\nexport type ConfigPatch = Pick<KiroGraphConfig, 'enableEmbeddings' | 'useVecIndex' | 'semanticEngine' | 'typesenseDashboard' | 'qdrantDashboard' | 'extractDocstrings' | 'trackCallSites' | 'enableArchitecture' | 'cavemanMode'> & { embeddingModel?: string; embeddingDim?: number };\nexport type SemanticEngine = KiroGraphConfig['semanticEngine'];\n\nexport const DEFAULT_EMBEDDING_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\n\n/** Well-known embedding models with their output dimensions. */\nconst PRESET_MODELS = [\n {\n value: 'nomic-ai/nomic-embed-text-v1.5',\n label: 'nomic-embed-text-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~130MB \u00B7 Best quality for code search (recommended)',\n },\n {\n value: 'onnx-community/embeddinggemma-300m-ONNX',\n label: 'embeddinggemma-300m',\n dim: 768,\n description: '768-dim \u00B7 ~300MB \u00B7 Google Gemma-based, multilingual, 2048-token context',\n },\n {\n value: 'Xenova/all-MiniLM-L6-v2',\n label: 'all-MiniLM-L6-v2',\n dim: 384,\n description: '384-dim \u00B7 ~23MB \u00B7 Fast and lightweight, lower accuracy',\n },\n {\n value: 'BAAI/bge-base-en-v1.5',\n label: 'bge-base-en-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~110MB \u00B7 Strong general-purpose alternative to nomic',\n },\n {\n value: '__other__',\n label: 'Other',\n dim: 768,\n description: 'Enter a custom HuggingFace model ID and embedding dimension',\n },\n] as const;\n\nexport async function promptConfigOptions(rl: readline.Interface): Promise<ConfigPatch> {\n const enableEmbeddings = await askBool(\n rl,\n 'Enable semantic embeddings for similarity search? (requires a local embedding model)',\n 'Enables semantic/similarity-based code search. Increases indexing time; the chosen embedding model is downloaded automatically on first use.',\n );\n\n const patch: ConfigPatch = { enableEmbeddings, useVecIndex: false, semanticEngine: 'cosine', typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: 'off' };\n\n if (enableEmbeddings) {\n // \u2500\u2500 Model selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const modelChoice = await arrowSelect<string>(\n rl,\n 'Choose an embedding model:',\n PRESET_MODELS.map(m => ({ value: m.value, label: m.label, description: m.description })),\n );\n\n let embeddingModel: string;\n let embeddingDim: number;\n\n if (modelChoice === '__other__') {\n console.log(`\\n ${dim}Enter a HuggingFace model ID in the format org/model-name.${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Model identifier:${reset} `)).trim();\n if (raw.includes('/')) { embeddingModel = raw; break; }\n console.log(` Expected a HuggingFace model ID in the format org/model-name (e.g. nomic-ai/nomic-embed-text-v1.5).`);\n }\n console.log(`\\n ${dim}Enter the embedding output dimension for this model (check the model card on HuggingFace).${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Embedding dimension (e.g. 768, 384):${reset} `)).trim();\n const n = parseInt(raw, 10);\n if (!isNaN(n) && n > 0) { embeddingDim = n; break; }\n console.log(` Expected a positive integer (e.g. 768, 384, 1536).`);\n }\n } else {\n const preset = PRESET_MODELS.find(m => m.value === modelChoice)!;\n embeddingModel = preset.value;\n embeddingDim = preset.dim;\n }\n\n patch.embeddingModel = embeddingModel;\n patch.embeddingDim = embeddingDim;\n\n // \u2500\u2500 Engine selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const semanticEngine = await arrowSelect<SemanticEngine>(rl, 'Choose the semantic search engine:', [\n { value: 'cosine', label: 'cosine', description: 'In-process cosine similarity. No extra deps. Best for small/medium projects.' },\n { value: 'sqlite-vec', label: 'sqlite-vec', description: 'ANN index. Sub-linear search. Best for large codebases. Needs: better-sqlite3, sqlite-vec (native).' },\n { value: 'orama', label: 'orama', description: 'Hybrid search (full-text + vector). Pure JS. Needs: @orama/orama, @orama/plugin-data-persistence.' },\n { value: 'pglite', label: 'pglite', description: 'Hybrid search via PostgreSQL + pgvector. Exact results. Pure WASM. Needs: @electric-sql/pglite.' },\n { value: 'lancedb', label: 'lancedb', description: 'ANN search via LanceDB (Apache Lance columnar format). Pure JS. Needs: @lancedb/lancedb.' },\n { value: 'qdrant', label: 'qdrant', description: 'ANN search via Qdrant embedded binary (HNSW index, Cosine). Needs: qdrant-local.' },\n { value: 'typesense', label: 'typesense', description: 'ANN search via Typesense (auto-downloaded binary, HNSW, Cosine). Needs: typesense.' },\n ]);\n patch.semanticEngine = semanticEngine;\n patch.useVecIndex = semanticEngine === 'sqlite-vec';\n\n if (semanticEngine === 'typesense') {\n patch.typesenseDashboard = await askBool(\n rl,\n 'Open Typesense dashboard after indexing?',\n 'Serves the Typesense Dashboard locally and opens it in your browser after indexing completes.',\n );\n }\n\n if (semanticEngine === 'qdrant') {\n patch.qdrantDashboard = await askBool(\n rl,\n 'Open Qdrant dashboard after indexing?',\n 'Downloads the Qdrant Web UI (first time only) and opens it in your browser after indexing completes.',\n );\n }\n }\n\n patch.extractDocstrings = await askBool(\n rl,\n 'Extract docstrings from source files?',\n 'Enriches symbol metadata and improves context quality. Slightly increases indexing time.',\n );\n\n patch.trackCallSites = await askBool(\n rl,\n 'Track call sites to enable caller/callee graph traversal?',\n 'Enables the kirograph_callers and kirograph_callees MCP tools for graph traversal. Increases index size.',\n );\n\n patch.enableArchitecture = await askBool(\n rl,\n 'Enable architecture analysis (package graph + layer detection)?',\n 'Detects packages from manifests (package.json, go.mod, Cargo.toml, etc.) and architectural layers (api, service, data, ui, shared) from file structure. Enables kirograph_architecture, kirograph_coupling, and kirograph_package MCP tools.',\n );\n\n const cavemanChoice = await arrowSelect(rl, 'Caveman mode \u2014 agent communication style:', [\n { value: 'off', label: 'off', description: 'Normal responses' },\n { value: 'lite', label: 'lite', description: 'Compact, no filler, full sentences' },\n { value: 'full', label: 'full', description: 'Fragments, no articles, short synonyms' },\n { value: 'ultra', label: 'ultra', description: 'Max compression, abbreviations, \u2192 for causality' },\n ]);\n patch.cavemanMode = cavemanChoice as CavemanMode | 'off';\n\n return patch;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph Installer \u2014 configuration prompting\n */\n\nimport * as readline from 'readline';\nimport { KiroGraphConfig } from '../../config';\ntype CavemanMode = 'lite' | 'full' | 'ultra';\nimport { ask, askBool, arrowSelect, dim, reset, violet } from './prompts';\nexport type ConfigPatch = Pick<KiroGraphConfig, 'enableEmbeddings' | 'useVecIndex' | 'semanticEngine' | 'typesenseDashboard' | 'qdrantDashboard' | 'extractDocstrings' | 'trackCallSites' | 'enableArchitecture' | 'cavemanMode' | 'shellCompressionLevel'> & { embeddingModel?: string; embeddingDim?: number };\nexport type SemanticEngine = KiroGraphConfig['semanticEngine'];\n\nexport const DEFAULT_EMBEDDING_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\n\n/** Well-known embedding models with their output dimensions. */\nconst PRESET_MODELS = [\n {\n value: 'nomic-ai/nomic-embed-text-v1.5',\n label: 'nomic-embed-text-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~130MB \u00B7 Best quality for code search (recommended)',\n },\n {\n value: 'onnx-community/embeddinggemma-300m-ONNX',\n label: 'embeddinggemma-300m',\n dim: 768,\n description: '768-dim \u00B7 ~300MB \u00B7 Google Gemma-based, multilingual, 2048-token context',\n },\n {\n value: 'Xenova/all-MiniLM-L6-v2',\n label: 'all-MiniLM-L6-v2',\n dim: 384,\n description: '384-dim \u00B7 ~23MB \u00B7 Fast and lightweight, lower accuracy',\n },\n {\n value: 'BAAI/bge-base-en-v1.5',\n label: 'bge-base-en-v1.5',\n dim: 768,\n description: '768-dim \u00B7 ~110MB \u00B7 Strong general-purpose alternative to nomic',\n },\n {\n value: '__other__',\n label: 'Other',\n dim: 768,\n description: 'Enter a custom HuggingFace model ID and embedding dimension',\n },\n] as const;\n\nexport async function promptConfigOptions(rl: readline.Interface): Promise<ConfigPatch> {\n const enableEmbeddings = await askBool(\n rl,\n 'Enable semantic embeddings for similarity search? (requires a local embedding model)',\n 'Enables semantic/similarity-based code search. Increases indexing time; the chosen embedding model is downloaded automatically on first use.',\n );\n\n const patch: ConfigPatch = { enableEmbeddings, useVecIndex: false, semanticEngine: 'cosine', typesenseDashboard: false, qdrantDashboard: false, extractDocstrings: true, trackCallSites: true, enableArchitecture: false, cavemanMode: 'off', shellCompressionLevel: 'normal' };\n\n if (enableEmbeddings) {\n // \u2500\u2500 Model selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const modelChoice = await arrowSelect<string>(\n rl,\n 'Choose an embedding model:',\n PRESET_MODELS.map(m => ({ value: m.value, label: m.label, description: m.description })),\n );\n\n let embeddingModel: string;\n let embeddingDim: number;\n\n if (modelChoice === '__other__') {\n console.log(`\\n ${dim}Enter a HuggingFace model ID in the format org/model-name.${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Model identifier:${reset} `)).trim();\n if (raw.includes('/')) { embeddingModel = raw; break; }\n console.log(` Expected a HuggingFace model ID in the format org/model-name (e.g. nomic-ai/nomic-embed-text-v1.5).`);\n }\n console.log(`\\n ${dim}Enter the embedding output dimension for this model (check the model card on HuggingFace).${reset}`);\n while (true) {\n const raw = (await ask(rl, ` ${violet}Embedding dimension (e.g. 768, 384):${reset} `)).trim();\n const n = parseInt(raw, 10);\n if (!isNaN(n) && n > 0) { embeddingDim = n; break; }\n console.log(` Expected a positive integer (e.g. 768, 384, 1536).`);\n }\n } else {\n const preset = PRESET_MODELS.find(m => m.value === modelChoice)!;\n embeddingModel = preset.value;\n embeddingDim = preset.dim;\n }\n\n patch.embeddingModel = embeddingModel;\n patch.embeddingDim = embeddingDim;\n\n // \u2500\u2500 Engine selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const semanticEngine = await arrowSelect<SemanticEngine>(rl, 'Choose the semantic search engine:', [\n { value: 'cosine', label: 'cosine', description: 'In-process cosine similarity. No extra deps. Best for small/medium projects.' },\n { value: 'sqlite-vec', label: 'sqlite-vec', description: 'ANN index. Sub-linear search. Best for large codebases. Needs: better-sqlite3, sqlite-vec (native).' },\n { value: 'orama', label: 'orama', description: 'Hybrid search (full-text + vector). Pure JS. Needs: @orama/orama, @orama/plugin-data-persistence.' },\n { value: 'pglite', label: 'pglite', description: 'Hybrid search via PostgreSQL + pgvector. Exact results. Pure WASM. Needs: @electric-sql/pglite.' },\n { value: 'lancedb', label: 'lancedb', description: 'ANN search via LanceDB (Apache Lance columnar format). Pure JS. Needs: @lancedb/lancedb.' },\n { value: 'qdrant', label: 'qdrant', description: 'ANN search via Qdrant embedded binary (HNSW index, Cosine). Needs: qdrant-local.' },\n { value: 'typesense', label: 'typesense', description: 'ANN search via Typesense (auto-downloaded binary, HNSW, Cosine). Needs: typesense.' },\n ]);\n patch.semanticEngine = semanticEngine;\n patch.useVecIndex = semanticEngine === 'sqlite-vec';\n\n if (semanticEngine === 'typesense') {\n patch.typesenseDashboard = await askBool(\n rl,\n 'Open Typesense dashboard after indexing?',\n 'Serves the Typesense Dashboard locally and opens it in your browser after indexing completes.',\n );\n }\n\n if (semanticEngine === 'qdrant') {\n patch.qdrantDashboard = await askBool(\n rl,\n 'Open Qdrant dashboard after indexing?',\n 'Downloads the Qdrant Web UI (first time only) and opens it in your browser after indexing completes.',\n );\n }\n }\n\n patch.extractDocstrings = await askBool(\n rl,\n 'Extract docstrings from source files?',\n 'Enriches symbol metadata and improves context quality. Slightly increases indexing time.',\n );\n\n patch.trackCallSites = await askBool(\n rl,\n 'Track call sites to enable caller/callee graph traversal?',\n 'Enables the kirograph_callers and kirograph_callees MCP tools for graph traversal. Increases index size.',\n );\n\n patch.enableArchitecture = await askBool(\n rl,\n 'Enable architecture analysis (package graph + layer detection)?',\n 'Detects packages from manifests (package.json, go.mod, Cargo.toml, etc.) and architectural layers (api, service, data, ui, shared) from file structure. Enables kirograph_architecture, kirograph_coupling, and kirograph_package MCP tools.',\n );\n\n const cavemanChoice = await arrowSelect(rl, 'Caveman mode: agent communication style:', [\n { value: 'off', label: 'off', description: 'Normal responses' },\n { value: 'lite', label: 'lite', description: 'Compact, no filler, full sentences' },\n { value: 'full', label: 'full', description: 'Fragments, no articles, short synonyms' },\n { value: 'ultra', label: 'ultra', description: 'Max compression, abbreviations, \u2192 for causality' },\n ]);\n patch.cavemanMode = cavemanChoice as CavemanMode | 'off';\n\n const compressionChoice = await arrowSelect(rl, 'Shell compression: default level for kirograph_exec:', [\n { value: 'off', label: 'off', description: 'No compression hook or steering (tool still available)' },\n { value: 'normal', label: 'normal', description: 'Balanced: removes noise, keeps structure (recommended)' },\n { value: 'aggressive', label: 'aggressive', description: 'More compact: groups by category, limits output' },\n { value: 'ultra', label: 'ultra', description: 'Maximum compression: counts and summaries only' },\n ]);\n patch.shellCompressionLevel = compressionChoice as KiroGraphConfig['shellCompressionLevel'];\n\n return patch;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -112,6 +112,19 @@ const HOOKS = [
112
112
  when: { type: "agentStop" },
113
113
  then: { type: "runCommand", command: "kirograph sync-if-dirty --quiet 2>/dev/null || true" }
114
114
  }
115
+ },
116
+ {
117
+ filename: "kirograph-compress-hint.json",
118
+ hook: {
119
+ name: "KiroGraph Compression Hint",
120
+ version: "1.0.0",
121
+ description: "Remind the agent to use kirograph_exec for shell commands that benefit from token compression (git, gh, test, lint, build, docker, aws, grep).",
122
+ when: { type: "preToolUse", toolTypes: ["shell"] },
123
+ then: {
124
+ type: "askAgent",
125
+ prompt: "If this shell command is a git operation, GitHub CLI, test runner, linter, build tool, file listing, grep/rg, docker/kubectl, AWS CLI, or package manager command, consider using the kirograph_exec MCP tool instead for 60-90% token savings. The tool compresses output automatically while preserving error details."
126
+ }
127
+ }
115
128
  }
116
129
  ];
117
130
  function ensureDir(p) {
@@ -154,7 +167,7 @@ function migrateOnIdleHooks(hooksDir) {
154
167
  }
155
168
  }
156
169
  }
157
- function writeHooks(kiroDir) {
170
+ function writeHooks(kiroDir, opts) {
158
171
  const hooksDir = path.join(kiroDir, "hooks");
159
172
  ensureDir(hooksDir);
160
173
  migrateOnIdleHooks(hooksDir);
@@ -164,6 +177,11 @@ function writeHooks(kiroDir) {
164
177
  if (fs.existsSync(p)) fs.unlinkSync(p);
165
178
  }
166
179
  for (const { filename, hook } of HOOKS) {
180
+ if (filename === "kirograph-compress-hint.json" && opts?.enableCompression === false) {
181
+ const p = path.join(hooksDir, filename);
182
+ if (fs.existsSync(p)) fs.unlinkSync(p);
183
+ continue;
184
+ }
167
185
  writeJson(path.join(hooksDir, filename), hook);
168
186
  }
169
187
  console.log(` \u2713 Auto-sync hooks written to ${hooksDir}`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/installer/hooks.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph Installer \u2014 Kiro hook file management\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { logWarn } from '../../errors';\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst FILE_PATTERNS = [\n '**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx',\n '**/*.py', '**/*.go', '**/*.rs', '**/*.java',\n '**/*.cs', '**/*.rb', '**/*.php', '**/*.swift',\n '**/*.kt', '**/*.dart',\n '**/*.ex', '**/*.exs',\n '**/*.scala', '**/*.sc', '**/*.lua', '**/*.zig',\n '**/*.sh', '**/*.bash', '**/*.ml', '**/*.mli',\n '**/*.elm', '**/*.sol', '**/*.vue', '**/*.m',\n '**/*.yaml', '**/*.yml',\n '**/*.tf', '**/*.tfvars',\n '**/*.css', '**/*.scss', '**/*.sass',\n '**/*.html',\n];\n\nconst HOOKS: Array<{ filename: string; hook: object }> = [\n {\n filename: 'kirograph-mark-dirty-on-save.json',\n hook: {\n name: 'KiroGraph Mark Dirty on Save',\n version: '1.0.0',\n description: 'Mark the KiroGraph index as dirty when source files are saved. Sync is deferred to agent idle.',\n when: { type: 'fileEdited', patterns: FILE_PATTERNS },\n then: { type: 'runCommand', command: 'kirograph mark-dirty 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-mark-dirty-on-create.json',\n hook: {\n name: 'KiroGraph Mark Dirty on Create',\n version: '1.0.0',\n description: 'Mark the KiroGraph index as dirty when source files are created.',\n when: { type: 'fileCreated', patterns: FILE_PATTERNS },\n then: { type: 'runCommand', command: 'kirograph mark-dirty 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-sync-on-delete.json',\n hook: {\n name: 'KiroGraph Sync on Delete',\n version: '1.0.0',\n description: 'Remove deleted files from the KiroGraph index immediately.',\n when: { type: 'fileDeleted', patterns: FILE_PATTERNS },\n then: { type: 'runCommand', command: 'kirograph sync-if-dirty 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-sync-if-dirty.json',\n hook: {\n name: 'KiroGraph Deferred Sync',\n version: '1.0.0',\n description: 'Sync the KiroGraph index when the agent is idle and a dirty marker is present. Batches multiple rapid saves into one sync.',\n when: { type: 'agentStop' },\n then: { type: 'runCommand', command: 'kirograph sync-if-dirty --quiet 2>/dev/null || true' },\n },\n },\n];\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction ensureDir(p: string): void {\n fs.mkdirSync(p, { recursive: true });\n}\n\nfunction writeJson(p: string, data: unknown): void {\n fs.writeFileSync(p, JSON.stringify(data, null, 2) + '\\n');\n}\n\nfunction migrateOnIdleHooks(hooksDir: string): void {\n if (!fs.existsSync(hooksDir)) return;\n let files: string[];\n try {\n files = fs.readdirSync(hooksDir).filter(f => f.endsWith('.json'));\n } catch {\n return;\n }\n for (const file of files) {\n const filePath = path.join(hooksDir, file);\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf8');\n } catch {\n logWarn(`KiroGraph installer: could not read hook file ${filePath}`);\n continue;\n }\n let obj: any;\n try {\n obj = JSON.parse(raw);\n } catch {\n logWarn(`KiroGraph installer: could not parse hook file ${filePath}`);\n continue;\n }\n if (obj?.when?.type === 'onIdle') {\n obj.when.type = 'agentStop';\n try {\n fs.writeFileSync(filePath, JSON.stringify(obj, null, 2) + '\\n');\n } catch {\n logWarn(`KiroGraph installer: could not write migrated hook file ${filePath}`);\n }\n }\n }\n}\n\n// \u2500\u2500 Public \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function writeHooks(kiroDir: string): void {\n const hooksDir = path.join(kiroDir, 'hooks');\n ensureDir(hooksDir);\n\n migrateOnIdleHooks(hooksDir);\n\n const oldHooks = ['kirograph-sync-on-save.json', 'kirograph-sync-on-create.json'];\n for (const old of oldHooks) {\n const p = path.join(hooksDir, old);\n if (fs.existsSync(p)) fs.unlinkSync(p);\n }\n\n for (const { filename, hook } of HOOKS) {\n writeJson(path.join(hooksDir, filename), hook);\n }\n\n console.log(` \u2713 Auto-sync hooks written to ${hooksDir}`);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph Installer \u2014 Kiro hook file management\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { logWarn } from '../../errors';\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst FILE_PATTERNS = [\n '**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx',\n '**/*.py', '**/*.go', '**/*.rs', '**/*.java',\n '**/*.cs', '**/*.rb', '**/*.php', '**/*.swift',\n '**/*.kt', '**/*.dart',\n '**/*.ex', '**/*.exs',\n '**/*.scala', '**/*.sc', '**/*.lua', '**/*.zig',\n '**/*.sh', '**/*.bash', '**/*.ml', '**/*.mli',\n '**/*.elm', '**/*.sol', '**/*.vue', '**/*.m',\n '**/*.yaml', '**/*.yml',\n '**/*.tf', '**/*.tfvars',\n '**/*.css', '**/*.scss', '**/*.sass',\n '**/*.html',\n];\n\nconst HOOKS: Array<{ filename: string; hook: object }> = [\n {\n filename: 'kirograph-mark-dirty-on-save.json',\n hook: {\n name: 'KiroGraph Mark Dirty on Save',\n version: '1.0.0',\n description: 'Mark the KiroGraph index as dirty when source files are saved. Sync is deferred to agent idle.',\n when: { type: 'fileEdited', patterns: FILE_PATTERNS },\n then: { type: 'runCommand', command: 'kirograph mark-dirty 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-mark-dirty-on-create.json',\n hook: {\n name: 'KiroGraph Mark Dirty on Create',\n version: '1.0.0',\n description: 'Mark the KiroGraph index as dirty when source files are created.',\n when: { type: 'fileCreated', patterns: FILE_PATTERNS },\n then: { type: 'runCommand', command: 'kirograph mark-dirty 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-sync-on-delete.json',\n hook: {\n name: 'KiroGraph Sync on Delete',\n version: '1.0.0',\n description: 'Remove deleted files from the KiroGraph index immediately.',\n when: { type: 'fileDeleted', patterns: FILE_PATTERNS },\n then: { type: 'runCommand', command: 'kirograph sync-if-dirty 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-sync-if-dirty.json',\n hook: {\n name: 'KiroGraph Deferred Sync',\n version: '1.0.0',\n description: 'Sync the KiroGraph index when the agent is idle and a dirty marker is present. Batches multiple rapid saves into one sync.',\n when: { type: 'agentStop' },\n then: { type: 'runCommand', command: 'kirograph sync-if-dirty --quiet 2>/dev/null || true' },\n },\n },\n {\n filename: 'kirograph-compress-hint.json',\n hook: {\n name: 'KiroGraph Compression Hint',\n version: '1.0.0',\n description: 'Remind the agent to use kirograph_exec for shell commands that benefit from token compression (git, gh, test, lint, build, docker, aws, grep).',\n when: { type: 'preToolUse', toolTypes: ['shell'] },\n then: {\n type: 'askAgent',\n prompt: 'If this shell command is a git operation, GitHub CLI, test runner, linter, build tool, file listing, grep/rg, docker/kubectl, AWS CLI, or package manager command, consider using the kirograph_exec MCP tool instead for 60-90% token savings. The tool compresses output automatically while preserving error details.',\n },\n },\n },\n];\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction ensureDir(p: string): void {\n fs.mkdirSync(p, { recursive: true });\n}\n\nfunction writeJson(p: string, data: unknown): void {\n fs.writeFileSync(p, JSON.stringify(data, null, 2) + '\\n');\n}\n\nfunction migrateOnIdleHooks(hooksDir: string): void {\n if (!fs.existsSync(hooksDir)) return;\n let files: string[];\n try {\n files = fs.readdirSync(hooksDir).filter(f => f.endsWith('.json'));\n } catch {\n return;\n }\n for (const file of files) {\n const filePath = path.join(hooksDir, file);\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf8');\n } catch {\n logWarn(`KiroGraph installer: could not read hook file ${filePath}`);\n continue;\n }\n let obj: any;\n try {\n obj = JSON.parse(raw);\n } catch {\n logWarn(`KiroGraph installer: could not parse hook file ${filePath}`);\n continue;\n }\n if (obj?.when?.type === 'onIdle') {\n obj.when.type = 'agentStop';\n try {\n fs.writeFileSync(filePath, JSON.stringify(obj, null, 2) + '\\n');\n } catch {\n logWarn(`KiroGraph installer: could not write migrated hook file ${filePath}`);\n }\n }\n }\n}\n\n// \u2500\u2500 Public \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function writeHooks(kiroDir: string, opts?: { enableCompression?: boolean }): void {\n const hooksDir = path.join(kiroDir, 'hooks');\n ensureDir(hooksDir);\n\n migrateOnIdleHooks(hooksDir);\n\n const oldHooks = ['kirograph-sync-on-save.json', 'kirograph-sync-on-create.json'];\n for (const old of oldHooks) {\n const p = path.join(hooksDir, old);\n if (fs.existsSync(p)) fs.unlinkSync(p);\n }\n\n for (const { filename, hook } of HOOKS) {\n // Skip compression hook if compression is disabled\n if (filename === 'kirograph-compress-hint.json' && opts?.enableCompression === false) {\n // Remove the hook file if it exists from a previous install\n const p = path.join(hooksDir, filename);\n if (fs.existsSync(p)) fs.unlinkSync(p);\n continue;\n }\n writeJson(path.join(hooksDir, filename), hook);\n }\n\n console.log(` \u2713 Auto-sync hooks written to ${hooksDir}`);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -31,8 +31,9 @@ __export(installer_exports, {
31
31
  runInstaller: () => runInstaller
32
32
  });
33
33
  module.exports = __toCommonJS(installer_exports);
34
- var path = __toESM(require("path"));
35
34
  var readline = __toESM(require("readline"));
35
+ var fs = __toESM(require("fs"));
36
+ var path = __toESM(require("path"));
36
37
  var import_child_process = require("child_process");
37
38
  var import_config = require("../../config");
38
39
  var import_banner = require("../banner");
@@ -40,120 +41,138 @@ var import_progress = require("../progress");
40
41
  var import_ui = require("../ui");
41
42
  var import_prompts = require("./prompts");
42
43
  var import_config_prompt = require("./config-prompt");
43
- var import_mcp = require("./mcp");
44
- var import_hooks = require("./hooks");
45
- var import_steering = require("./steering");
46
- var import_cli_agent = require("./cli-agent");
47
44
  var import_dashboard = require("./dashboard");
48
45
  var import_qdrant_dashboard = require("./qdrant-dashboard");
49
- async function runInstaller() {
46
+ var import_targets = require("./targets");
47
+ async function runInstaller(target = "kiro") {
50
48
  (0, import_banner.printBanner)();
51
49
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
52
50
  try {
53
51
  const cwd = process.cwd();
54
- const kiroDir = path.join(cwd, ".kiro");
52
+ const installer = (0, import_targets.getTargetInstaller)(target);
55
53
  console.log(` Workspace: ${cwd}
56
54
  `);
57
- const proceed = await (0, import_prompts.ask)(rl, " Install KiroGraph for this Kiro workspace? (Y/n) ");
55
+ const proceed = await (0, import_prompts.ask)(rl, ` Install KiroGraph for ${installer.label}? (Y/n) `);
58
56
  if (proceed.toLowerCase() === "n") {
59
57
  console.log(" Cancelled.");
60
58
  rl.close();
61
59
  return;
62
60
  }
63
61
  console.log();
64
- (0, import_mcp.writeMcpConfig)(kiroDir);
65
- (0, import_hooks.writeHooks)(kiroDir);
66
- const patch = await (0, import_config_prompt.promptConfigOptions)(rl);
62
+ installer.installEarly(cwd);
63
+ const alreadyInitialized = fs.existsSync(path.join(cwd, ".kirograph"));
64
+ let cavemanMode = "off";
65
+ let shellCompressionLevel = "normal";
66
+ let shouldOfferIndex = false;
67
+ let typesenseDashboard = false;
68
+ let qdrantDashboard = false;
67
69
  try {
68
- await (0, import_config.updateConfig)(cwd, patch);
69
- console.log(`
70
+ if (alreadyInitialized) {
71
+ const config = await (0, import_config.loadConfig)(cwd);
72
+ cavemanMode = config.cavemanMode ?? "off";
73
+ shellCompressionLevel = config.shellCompressionLevel ?? "normal";
74
+ console.log(` \u2713 Reusing existing KiroGraph data in ${cwd}/.kirograph/`);
75
+ console.log(` \u2022 semanticEngine: ${config.semanticEngine}`);
76
+ console.log(` \u2022 enableEmbeddings: ${config.enableEmbeddings}`);
77
+ console.log(` \u2022 enableArchitecture: ${config.enableArchitecture}`);
78
+ console.log(` \u2022 cavemanMode: ${cavemanMode}`);
79
+ console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);
80
+ } else {
81
+ shouldOfferIndex = true;
82
+ const patch = await (0, import_config_prompt.promptConfigOptions)(rl);
83
+ await (0, import_config.updateConfig)(cwd, patch);
84
+ cavemanMode = patch.cavemanMode ?? "off";
85
+ shellCompressionLevel = patch.shellCompressionLevel ?? "normal";
86
+ typesenseDashboard = patch.typesenseDashboard;
87
+ qdrantDashboard = patch.qdrantDashboard;
88
+ console.log(`
70
89
  Configuration saved to ${cwd}/.kirograph/config.json`);
71
- console.log(` \u2022 enableEmbeddings: ${patch.enableEmbeddings}`);
72
- if ("embeddingModel" in patch) {
73
- console.log(` \u2022 embeddingModel: ${patch.embeddingModel} ${import_ui.dim}(${patch.embeddingDim}-dim)${import_ui.reset}`);
74
- }
75
- if (patch.enableEmbeddings) {
76
- console.log(` \u2022 semanticEngine: ${patch.semanticEngine}`);
77
- if (patch.semanticEngine === "sqlite-vec") {
78
- console.log(`
90
+ console.log(` \u2022 enableEmbeddings: ${patch.enableEmbeddings}`);
91
+ if ("embeddingModel" in patch) {
92
+ console.log(` \u2022 embeddingModel: ${patch.embeddingModel} ${import_ui.dim}(${patch.embeddingDim}-dim)${import_ui.reset}`);
93
+ }
94
+ if (patch.enableEmbeddings) {
95
+ console.log(` \u2022 semanticEngine: ${patch.semanticEngine}`);
96
+ if (patch.semanticEngine === "sqlite-vec") {
97
+ console.log(`
79
98
  Installing sqlite-vec dependencies...`);
80
- const result = (0, import_child_process.spawnSync)("npm", ["install", "better-sqlite3", "sqlite-vec"], { stdio: "inherit", shell: true });
81
- if (result.status === 0) {
82
- console.log(` \u2713 better-sqlite3 and sqlite-vec installed`);
83
- } else {
84
- console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
85
- console.warn(` npm install better-sqlite3 sqlite-vec`);
86
- }
87
- } else if (patch.semanticEngine === "orama") {
88
- console.log(`
99
+ const result = (0, import_child_process.spawnSync)("npm", ["install", "better-sqlite3", "sqlite-vec"], { stdio: "inherit", shell: true });
100
+ if (result.status === 0) {
101
+ console.log(` \u2713 better-sqlite3 and sqlite-vec installed`);
102
+ } else {
103
+ console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
104
+ console.warn(` npm install better-sqlite3 sqlite-vec`);
105
+ }
106
+ } else if (patch.semanticEngine === "orama") {
107
+ console.log(`
89
108
  Installing Orama dependencies...`);
90
- const result = (0, import_child_process.spawnSync)("npm", ["install", "@orama/orama", "@orama/plugin-data-persistence"], { stdio: "inherit", shell: true });
91
- if (result.status === 0) {
92
- console.log(` \u2713 @orama/orama and @orama/plugin-data-persistence installed`);
93
- } else {
94
- console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
95
- console.warn(` npm install @orama/orama @orama/plugin-data-persistence`);
96
- }
97
- } else if (patch.semanticEngine === "pglite") {
98
- console.log(`
109
+ const result = (0, import_child_process.spawnSync)("npm", ["install", "@orama/orama", "@orama/plugin-data-persistence"], { stdio: "inherit", shell: true });
110
+ if (result.status === 0) {
111
+ console.log(` \u2713 @orama/orama and @orama/plugin-data-persistence installed`);
112
+ } else {
113
+ console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
114
+ console.warn(` npm install @orama/orama @orama/plugin-data-persistence`);
115
+ }
116
+ } else if (patch.semanticEngine === "pglite") {
117
+ console.log(`
99
118
  Installing PGlite dependencies...`);
100
- const result = (0, import_child_process.spawnSync)("npm", ["install", "@electric-sql/pglite"], { stdio: "inherit", shell: true });
101
- if (result.status === 0) {
102
- console.log(` \u2713 @electric-sql/pglite installed`);
103
- } else {
104
- console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
105
- console.warn(` npm install @electric-sql/pglite`);
106
- }
107
- } else if (patch.semanticEngine === "lancedb") {
108
- console.log(`
119
+ const result = (0, import_child_process.spawnSync)("npm", ["install", "@electric-sql/pglite"], { stdio: "inherit", shell: true });
120
+ if (result.status === 0) {
121
+ console.log(` \u2713 @electric-sql/pglite installed`);
122
+ } else {
123
+ console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
124
+ console.warn(` npm install @electric-sql/pglite`);
125
+ }
126
+ } else if (patch.semanticEngine === "lancedb") {
127
+ console.log(`
109
128
  Installing LanceDB dependencies...`);
110
- const result = (0, import_child_process.spawnSync)("npm", ["install", "@lancedb/lancedb"], { stdio: "inherit", shell: true });
111
- if (result.status === 0) {
112
- console.log(` \u2713 @lancedb/lancedb installed`);
113
- } else {
114
- console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
115
- console.warn(` npm install @lancedb/lancedb`);
116
- }
117
- } else if (patch.semanticEngine === "qdrant") {
118
- console.log(`
129
+ const result = (0, import_child_process.spawnSync)("npm", ["install", "@lancedb/lancedb"], { stdio: "inherit", shell: true });
130
+ if (result.status === 0) {
131
+ console.log(` \u2713 @lancedb/lancedb installed`);
132
+ } else {
133
+ console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
134
+ console.warn(` npm install @lancedb/lancedb`);
135
+ }
136
+ } else if (patch.semanticEngine === "qdrant") {
137
+ console.log(`
119
138
  Installing Qdrant dependencies...`);
120
- const result = (0, import_child_process.spawnSync)("npm", ["install", "qdrant-local"], { stdio: "inherit", shell: true });
121
- if (result.status === 0) {
122
- console.log(` \u2713 qdrant-local installed`);
123
- } else {
124
- console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
125
- console.warn(` npm install qdrant-local`);
126
- }
127
- } else if (patch.semanticEngine === "typesense") {
128
- console.log(`
139
+ const result = (0, import_child_process.spawnSync)("npm", ["install", "qdrant-local"], { stdio: "inherit", shell: true });
140
+ if (result.status === 0) {
141
+ console.log(` \u2713 qdrant-local installed`);
142
+ } else {
143
+ console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
144
+ console.warn(` npm install qdrant-local`);
145
+ }
146
+ } else if (patch.semanticEngine === "typesense") {
147
+ console.log(`
129
148
  Installing Typesense dependencies...`);
130
- const result = (0, import_child_process.spawnSync)("npm", ["install", "typesense"], { stdio: "inherit", shell: true });
131
- if (result.status === 0) {
132
- console.log(` \u2713 typesense installed`);
133
- console.log(` \u2139 The Typesense binary (~37MB) will be auto-downloaded on first index run.`);
134
- } else {
135
- console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
136
- console.warn(` npm install typesense`);
149
+ const result = (0, import_child_process.spawnSync)("npm", ["install", "typesense"], { stdio: "inherit", shell: true });
150
+ if (result.status === 0) {
151
+ console.log(` \u2713 typesense installed`);
152
+ console.log(` \u2139 The Typesense binary (~37MB) will be auto-downloaded on first index run.`);
153
+ } else {
154
+ console.warn(` \u2717 npm install failed (exit ${result.status}). Run manually:`);
155
+ console.warn(` npm install typesense`);
156
+ }
137
157
  }
138
158
  }
159
+ console.log(` \u2022 extractDocstrings: ${patch.extractDocstrings}`);
160
+ console.log(` \u2022 trackCallSites: ${patch.trackCallSites}`);
161
+ console.log(` \u2022 enableArchitecture: ${patch.enableArchitecture}`);
162
+ console.log(` \u2022 cavemanMode: ${cavemanMode}`);
163
+ console.log(` \u2022 shellCompressionLevel: ${shellCompressionLevel}`);
139
164
  }
140
- console.log(` \u2022 extractDocstrings: ${patch.extractDocstrings}`);
141
- console.log(` \u2022 trackCallSites: ${patch.trackCallSites}`);
142
- console.log(` \u2022 enableArchitecture: ${patch.enableArchitecture}`);
143
- console.log(` \u2022 cavemanMode: ${patch.cavemanMode ?? "off"}`);
144
- (0, import_steering.writeSteering)(kiroDir, patch.cavemanMode ?? "off");
145
- (0, import_cli_agent.writeCliAgent)(kiroDir);
165
+ installer.installLate(cwd, cavemanMode, shellCompressionLevel);
146
166
  } catch (err) {
147
167
  const reason = err instanceof Error ? err.message : String(err);
148
168
  console.error(`
149
169
  \u2717 Failed to write configuration: ${reason}`);
150
170
  process.exit(1);
151
171
  }
152
- if (patch.qdrantDashboard) {
172
+ if (qdrantDashboard) {
153
173
  await (0, import_qdrant_dashboard.ensureQdrantUI)(cwd);
154
174
  }
155
- const doIndex = await (0, import_prompts.ask)(rl, "\n Initialize and index this project now? (Y/n) ");
156
- if (doIndex.toLowerCase() !== "n") {
175
+ if (shouldOfferIndex && (await (0, import_prompts.ask)(rl, "\n Initialize and index this project now? (Y/n) ")).toLowerCase() !== "n") {
157
176
  const KiroGraph = (await Promise.resolve().then(() => require("../../index.js"))).default;
158
177
  const fileBytes = /* @__PURE__ */ new Map();
159
178
  const modelProgress = (file, loaded, total, done) => {
@@ -197,7 +216,7 @@ async function runInstaller() {
197
216
  process.stdout.write("\n");
198
217
  console.log(` \u2713 Indexed ${result.filesIndexed} files, ${result.nodesCreated} symbols, ${result.edgesCreated} edges`);
199
218
  cg.close();
200
- if (patch.typesenseDashboard) {
219
+ if (typesenseDashboard) {
201
220
  const dashboardServer = await (0, import_dashboard.openTypesenseDashboard)(cwd);
202
221
  console.log(` ${import_ui.dim}Press Ctrl+C to stop the dashboard server when done.${import_ui.reset}`);
203
222
  await new Promise((resolve) => {
@@ -211,12 +230,11 @@ async function runInstaller() {
211
230
  });
212
231
  return;
213
232
  }
214
- if (patch.qdrantDashboard) {
233
+ if (qdrantDashboard) {
215
234
  await (0, import_qdrant_dashboard.openQdrantDashboard)(cwd);
216
235
  }
217
236
  }
218
- console.log("\n Done! Restart Kiro IDE for the MCP server to load.");
219
- console.log(' For Kiro CLI, use the "kirograph" agent: kiro-cli --agent kirograph\n');
237
+ installer.printNextSteps(cwd);
220
238
  } finally {
221
239
  rl.close();
222
240
  }