agentcache 0.4.0 → 0.4.2

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.
@@ -1,75 +1,7 @@
1
- // src/utils/ide-detector.ts
2
- import { existsSync } from "fs";
3
- import { join } from "path";
4
- import { homedir } from "os";
5
- function getRooConfigPath() {
6
- const home = homedir();
7
- if (process.platform === "darwin") {
8
- return join(home, "Library/Application Support/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
9
- }
10
- if (process.platform === "win32") {
11
- return join(process.env.APPDATA || join(home, "AppData/Roaming"), "Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
12
- }
13
- return join(home, ".config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json");
14
- }
15
- function getWindsurfConfigPath() {
16
- const home = homedir();
17
- return join(home, ".codeium", "windsurf", "mcp_config.json");
18
- }
19
- function getContinueConfigPath() {
20
- const home = homedir();
21
- return join(home, ".continue", "mcpServers", "agentcache.json");
22
- }
23
- function getCodexConfigPath() {
24
- const home = homedir();
25
- return join(home, ".codex", "config.toml");
26
- }
27
- function detectInstalledIdes() {
28
- const home = homedir();
29
- return [
30
- {
31
- name: "Claude Code",
32
- detected: existsSync(join(home, ".claude")),
33
- mcpConfigPath: join(home, ".claude.json"),
34
- mcpConfigFormat: "claude-settings"
35
- },
36
- {
37
- name: "Cursor",
38
- detected: existsSync(join(home, ".cursor")),
39
- mcpConfigPath: join(home, ".cursor", "mcp.json"),
40
- mcpConfigFormat: "mcp-json"
41
- },
42
- {
43
- name: "Roo Code",
44
- detected: existsSync(getRooConfigPath()),
45
- mcpConfigPath: getRooConfigPath(),
46
- mcpConfigFormat: "mcp-json"
47
- },
48
- {
49
- name: "Windsurf",
50
- detected: existsSync(join(home, ".codeium", "windsurf")) || existsSync(join(home, ".windsurf")),
51
- mcpConfigPath: getWindsurfConfigPath(),
52
- mcpConfigFormat: "mcp-json"
53
- },
54
- {
55
- name: "Continue",
56
- detected: existsSync(join(home, ".continue")),
57
- mcpConfigPath: getContinueConfigPath(),
58
- mcpConfigFormat: "continue-dir"
59
- },
60
- {
61
- name: "Codex",
62
- detected: existsSync(join(home, ".codex")),
63
- mcpConfigPath: getCodexConfigPath(),
64
- mcpConfigFormat: "codex-toml"
65
- }
66
- ];
67
- }
68
-
69
1
  // src/utils/ide-registrar.ts
70
- import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync, appendFileSync } from "fs";
71
- import { join as join2, dirname } from "path";
72
- import { homedir as homedir2 } from "os";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync } from "fs";
3
+ import { join, dirname } from "path";
4
+ import { homedir } from "os";
73
5
  import { execSync } from "child_process";
74
6
  function findNodeBinary() {
75
7
  try {
@@ -83,7 +15,7 @@ function findAgentcacheScript() {
83
15
  const binPath = execSync("which agentcache", { encoding: "utf-8" }).trim();
84
16
  return binPath;
85
17
  } catch {
86
- return join2(dirname(dirname(__dirname)), "dist", "cli.js");
18
+ return join(dirname(dirname(__dirname)), "dist", "cli.js");
87
19
  }
88
20
  }
89
21
  function isVscodeExtensionIde(ide) {
@@ -116,9 +48,9 @@ function registerMcpServer(ide) {
116
48
  return false;
117
49
  }
118
50
  function registerClaudeCode() {
119
- const claudeJsonPath = join2(homedir2(), ".claude.json");
51
+ const claudeJsonPath = join(homedir(), ".claude.json");
120
52
  let config = {};
121
- if (existsSync2(claudeJsonPath)) {
53
+ if (existsSync(claudeJsonPath)) {
122
54
  try {
123
55
  config = JSON.parse(readFileSync(claudeJsonPath, "utf-8"));
124
56
  } catch {
@@ -137,10 +69,10 @@ function registerClaudeCode() {
137
69
  writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2));
138
70
  serverRegistered = true;
139
71
  }
140
- const settingsPath = join2(homedir2(), ".claude", "settings.json");
141
- if (existsSync2(join2(homedir2(), ".claude"))) {
72
+ const settingsPath = join(homedir(), ".claude", "settings.json");
73
+ if (existsSync(join(homedir(), ".claude"))) {
142
74
  let settings = {};
143
- if (existsSync2(settingsPath)) {
75
+ if (existsSync(settingsPath)) {
144
76
  try {
145
77
  settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
146
78
  } catch {
@@ -164,7 +96,7 @@ function registerClaudeCode() {
164
96
  }
165
97
  function registerMcpJson(ide) {
166
98
  let config = {};
167
- if (existsSync2(ide.mcpConfigPath)) {
99
+ if (existsSync(ide.mcpConfigPath)) {
168
100
  try {
169
101
  config = JSON.parse(readFileSync(ide.mcpConfigPath, "utf-8"));
170
102
  } catch {
@@ -212,7 +144,7 @@ function registerContinue(ide) {
212
144
  }
213
145
  function registerCodex(ide) {
214
146
  const configPath = ide.mcpConfigPath;
215
- if (existsSync2(configPath)) {
147
+ if (existsSync(configPath)) {
216
148
  const content = readFileSync(configPath, "utf-8");
217
149
  if (content.includes("[mcp_servers.agentcache]")) return false;
218
150
  }
@@ -223,7 +155,7 @@ args = ["serve"]
223
155
  default_tools_approval_mode = "auto"
224
156
  `;
225
157
  mkdirSync(dirname(configPath), { recursive: true });
226
- if (existsSync2(configPath)) {
158
+ if (existsSync(configPath)) {
227
159
  appendFileSync(configPath, tomlBlock);
228
160
  } else {
229
161
  writeFileSync(configPath, tomlBlock.trimStart());
@@ -231,10 +163,10 @@ default_tools_approval_mode = "auto"
231
163
  return true;
232
164
  }
233
165
  function registerClaudeHooks() {
234
- const settingsPath = join2(homedir2(), ".claude", "settings.json");
235
- if (!existsSync2(join2(homedir2(), ".claude"))) return false;
166
+ const settingsPath = join(homedir(), ".claude", "settings.json");
167
+ if (!existsSync(join(homedir(), ".claude"))) return false;
236
168
  let settings = {};
237
- if (existsSync2(settingsPath)) {
169
+ if (existsSync(settingsPath)) {
238
170
  try {
239
171
  settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
240
172
  } catch {
@@ -265,7 +197,6 @@ function registerClaudeHooks() {
265
197
  }
266
198
 
267
199
  export {
268
- detectInstalledIdes,
269
200
  registerMcpServer,
270
201
  registerClaudeHooks
271
202
  };
@@ -139,19 +139,62 @@ function parse3(path) {
139
139
  return events;
140
140
  }
141
141
 
142
- // src/utils/transcript-parsers/roo-code-json.ts
143
- var roo_code_json_exports = {};
144
- __export(roo_code_json_exports, {
142
+ // src/utils/transcript-parsers/cursor-jsonl.ts
143
+ var cursor_jsonl_exports = {};
144
+ __export(cursor_jsonl_exports, {
145
145
  canParse: () => canParse4,
146
146
  parse: () => parse4
147
147
  });
148
148
  import { readFileSync as readFileSync4 } from "fs";
149
149
  function canParse4(path) {
150
- return path.includes("roo-cline/tasks/") && path.endsWith("api_conversation_history.json");
150
+ if (!path.endsWith(".jsonl")) return false;
151
+ return path.includes(".cursor/projects/") && path.includes("/agent-transcripts/");
151
152
  }
152
153
  function parse4(path) {
153
154
  const content = readFileSync4(path, "utf-8");
154
155
  const events = [];
156
+ for (const line of content.split("\n")) {
157
+ if (!line.trim()) continue;
158
+ try {
159
+ const obj = JSON.parse(line);
160
+ if (obj.role === "user" && obj.message?.content) {
161
+ const blocks = Array.isArray(obj.message.content) ? obj.message.content : [{ type: "text", text: obj.message.content }];
162
+ const text = blocks.filter((c) => c.type === "text").map((c) => c.text).join("\n");
163
+ if (text) events.push({ type: "message", role: "user", content: text });
164
+ } else if (obj.role === "assistant" && obj.message?.content) {
165
+ const blocks = Array.isArray(obj.message.content) ? obj.message.content : [{ type: "text", text: obj.message.content }];
166
+ for (const block of blocks) {
167
+ if (block.type === "text" && block.text) {
168
+ events.push({ type: "message", role: "assistant", content: block.text });
169
+ } else if (block.type === "tool_use") {
170
+ events.push({
171
+ type: "tool_use",
172
+ tool_name: block.name,
173
+ tool_input: block.input
174
+ });
175
+ }
176
+ }
177
+ }
178
+ } catch {
179
+ continue;
180
+ }
181
+ }
182
+ return events;
183
+ }
184
+
185
+ // src/utils/transcript-parsers/roo-code-json.ts
186
+ var roo_code_json_exports = {};
187
+ __export(roo_code_json_exports, {
188
+ canParse: () => canParse5,
189
+ parse: () => parse5
190
+ });
191
+ import { readFileSync as readFileSync5 } from "fs";
192
+ function canParse5(path) {
193
+ return path.includes("roo-cline/tasks/") && path.endsWith("api_conversation_history.json");
194
+ }
195
+ function parse5(path) {
196
+ const content = readFileSync5(path, "utf-8");
197
+ const events = [];
155
198
  try {
156
199
  const messages = JSON.parse(content);
157
200
  if (!Array.isArray(messages)) return [];
@@ -182,7 +225,7 @@ function parse4(path) {
182
225
  }
183
226
 
184
227
  // src/utils/transcript-parsers/index.ts
185
- var parsers = [codex_jsonl_exports, roo_code_json_exports, claude_jsonl_exports, continue_json_exports];
228
+ var parsers = [codex_jsonl_exports, cursor_jsonl_exports, roo_code_json_exports, claude_jsonl_exports, continue_json_exports];
186
229
  function parseTranscriptAuto(path) {
187
230
  for (const parser of parsers) {
188
231
  if (parser.canParse(path)) return parser.parse(path);
@@ -194,6 +237,31 @@ function parseTranscriptAuto(path) {
194
237
  function parseTranscript(path) {
195
238
  return parseTranscriptAuto(path);
196
239
  }
240
+ function findLatestTranscript() {
241
+ const baseDir = getClaudeTranscriptsDir();
242
+ if (!existsSync(baseDir)) return null;
243
+ let latest = null;
244
+ try {
245
+ const dirs = readdirSync(baseDir).map((d) => join(baseDir, d)).filter((d) => statSync(d).isDirectory());
246
+ for (const dir of dirs) {
247
+ try {
248
+ const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
249
+ for (const file of files) {
250
+ const fullPath = join(dir, file);
251
+ const mtime = statSync(fullPath).mtimeMs;
252
+ if (!latest || mtime > latest.mtime) {
253
+ latest = { path: fullPath, mtime };
254
+ }
255
+ }
256
+ } catch {
257
+ continue;
258
+ }
259
+ }
260
+ } catch {
261
+ return null;
262
+ }
263
+ return latest?.path ?? null;
264
+ }
197
265
  function findAllClaudeTranscripts() {
198
266
  const baseDir = getClaudeTranscriptsDir();
199
267
  if (!existsSync(baseDir)) return [];
@@ -247,6 +315,37 @@ function findAllCodexTranscripts() {
247
315
  walkDir(baseDir);
248
316
  return transcripts;
249
317
  }
318
+ function findAllCursorTranscripts() {
319
+ const baseDir = join(homedir(), ".cursor", "projects");
320
+ if (!existsSync(baseDir)) return [];
321
+ const transcripts = [];
322
+ try {
323
+ for (const projectDir of readdirSync(baseDir)) {
324
+ const agentDir = join(baseDir, projectDir, "agent-transcripts");
325
+ if (!existsSync(agentDir)) continue;
326
+ try {
327
+ for (const sessionDir of readdirSync(agentDir)) {
328
+ const sessionPath = join(agentDir, sessionDir);
329
+ if (!statSync(sessionPath).isDirectory()) continue;
330
+ try {
331
+ for (const file of readdirSync(sessionPath)) {
332
+ if (file.endsWith(".jsonl")) {
333
+ const full = join(sessionPath, file);
334
+ if (statSync(full).size > 100) {
335
+ transcripts.push(full);
336
+ }
337
+ }
338
+ }
339
+ } catch {
340
+ }
341
+ }
342
+ } catch {
343
+ }
344
+ }
345
+ } catch {
346
+ }
347
+ return transcripts;
348
+ }
250
349
  function findAllRooCodeTranscripts() {
251
350
  const possibleDirs = [
252
351
  join(homedir(), "Library", "Application Support", "Code", "User", "globalStorage", "rooveterinaryinc.roo-cline", "tasks"),
@@ -267,15 +366,23 @@ function findAllRooCodeTranscripts() {
267
366
  }
268
367
  return transcripts;
269
368
  }
369
+ function findAllGooseSessionIds() {
370
+ const dbPath = join(homedir(), ".local", "share", "goose", "sessions", "sessions.db");
371
+ if (!existsSync(dbPath)) return [];
372
+ return [dbPath];
373
+ }
270
374
  function getGooseDbPath() {
271
375
  return join(homedir(), ".local", "share", "goose", "sessions", "sessions.db");
272
376
  }
273
377
 
274
378
  export {
275
379
  parseTranscript,
380
+ findLatestTranscript,
276
381
  findAllClaudeTranscripts,
277
382
  findAllContinueTranscripts,
278
383
  findAllCodexTranscripts,
384
+ findAllCursorTranscripts,
279
385
  findAllRooCodeTranscripts,
386
+ findAllGooseSessionIds,
280
387
  getGooseDbPath
281
388
  };
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ import { Command } from "commander";
5
5
  var program = new Command();
6
6
  program.name("agentcache").description("Engineering Knowledge Compiler \u2014 universal, zero-config").version("0.3.1");
7
7
  program.command("setup").description("Detect IDEs and register AgentCache (runs automatically on install)").action(async () => {
8
- const { runSetup } = await import("./setup-HE7ZHOEI.js");
8
+ const { runSetup } = await import("./setup-CVG35TUZ.js");
9
9
  await runSetup();
10
10
  });
11
11
  program.command("serve").description("Start AgentCache MCP server (spawned by IDEs automatically)").action(async () => {
@@ -14,7 +14,7 @@ program.command("serve").description("Start AgentCache MCP server (spawned by ID
14
14
  });
15
15
  program.command("compile-session").description("Stop hook: queue transcript for compilation").action(async () => {
16
16
  try {
17
- const { handleStop } = await import("./stop-YDXXQJCE.js");
17
+ const { handleStop } = await import("./stop-WGGRX6TQ.js");
18
18
  let payload;
19
19
  try {
20
20
  let data = "";
@@ -34,7 +34,7 @@ program.command("compile-session").description("Stop hook: queue transcript for
34
34
  });
35
35
  program.command("discover").description("SessionStart hook: discover uncompiled transcripts").action(async () => {
36
36
  try {
37
- const { handleSessionStart } = await import("./session-start-2OKCIAGB.js");
37
+ const { handleSessionStart } = await import("./session-start-DGMGEAJU.js");
38
38
  await handleSessionStart();
39
39
  } catch (err) {
40
40
  process.stderr.write(`agentcache discover: ${err.message}
@@ -47,7 +47,7 @@ program.command("enforce").description("PreToolUse hook: policy enforcement").ac
47
47
  data += chunk;
48
48
  }
49
49
  try {
50
- const { handlePreToolUse } = await import("./pre-tool-use-D3GM3GEQ.js");
50
+ const { handlePreToolUse } = await import("./pre-tool-use-A4AJHZOJ.js");
51
51
  const input = JSON.parse(data);
52
52
  const result = handlePreToolUse(input);
53
53
  process.stdout.write(JSON.stringify(result));
@@ -63,7 +63,7 @@ program.command("review").description("Review quarantined observations \u2014 ap
63
63
  console.log("AgentCache not initialized. Run: agentcache setup");
64
64
  return;
65
65
  }
66
- const { SqliteKnowledgeRepository } = await import("./sqlite-MHG4WEHL.js");
66
+ const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
67
67
  const repo = new SqliteKnowledgeRepository(getDbPath());
68
68
  const project = getProjectId(findProjectRoot());
69
69
  const items = repo.getQuarantinedItems(project);
@@ -108,7 +108,7 @@ program.command("promote <id>").description("Promote a specific quarantined item
108
108
  console.log("AgentCache not initialized. Run: agentcache setup");
109
109
  return;
110
110
  }
111
- const { SqliteKnowledgeRepository } = await import("./sqlite-MHG4WEHL.js");
111
+ const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
112
112
  const repo = new SqliteKnowledgeRepository(getDbPath());
113
113
  const item = repo.getKnowledgeItem(id);
114
114
  if (!item) {
@@ -127,7 +127,7 @@ program.command("add-rule <content>").description("Add an enforced policy rule (
127
127
  console.log("AgentCache not initialized. Run: agentcache setup");
128
128
  return;
129
129
  }
130
- const { SqliteKnowledgeRepository } = await import("./sqlite-MHG4WEHL.js");
130
+ const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
131
131
  const { computeCanonicalHash } = await import("./3-canonicalizer-HIN2F7SZ.js");
132
132
  const repo = new SqliteKnowledgeRepository(getDbPath());
133
133
  const project = getProjectId(findProjectRoot());
@@ -185,7 +185,7 @@ program.command("doctor").description("Diagnose AgentCache installation and repo
185
185
  const dbPath = getDbPath();
186
186
  if (existsSync(dbPath)) {
187
187
  try {
188
- const { SqliteKnowledgeRepository } = await import("./sqlite-MHG4WEHL.js");
188
+ const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
189
189
  const repo = new SqliteKnowledgeRepository(dbPath);
190
190
  repo.close();
191
191
  pass(`Database accessible: ${dbPath}`);
@@ -202,40 +202,99 @@ program.command("doctor").description("Diagnose AgentCache installation and repo
202
202
  warning("Not initialized yet \u2014 run: agentcache setup");
203
203
  }
204
204
  console.log("\nIDE registrations:");
205
- const claudeJson = join(homedir(), ".claude.json");
206
- if (existsSync(claudeJson)) {
207
- try {
208
- const config = JSON.parse(readFileSync(claudeJson, "utf-8"));
209
- if (config.mcpServers?.agentcache) {
210
- pass("Claude Code: registered");
205
+ const { detectInstalledIdes } = await import("./ide-detector-5TRCR4F5.js");
206
+ const ides = detectInstalledIdes();
207
+ for (const ide of ides) {
208
+ if (!ide.detected) continue;
209
+ if (ide.mcpConfigFormat === "claude-settings") {
210
+ const claudeJson = join(homedir(), ".claude.json");
211
+ if (existsSync(claudeJson)) {
212
+ try {
213
+ const config = JSON.parse(readFileSync(claudeJson, "utf-8"));
214
+ if (config.mcpServers?.agentcache) {
215
+ pass("Claude Code: registered");
216
+ } else {
217
+ warning("Claude Code: detected but not registered");
218
+ }
219
+ } catch {
220
+ warning("Claude Code: config unreadable");
221
+ }
211
222
  } else {
212
- warning("Claude Code: ~/.claude.json exists but no agentcache server");
223
+ warning("Claude Code: detected but not registered");
213
224
  }
214
- } catch {
215
- warning("Claude Code: ~/.claude.json unreadable");
216
- }
217
- } else {
218
- warning("Claude Code: not registered");
219
- }
220
- const settingsPath = join(homedir(), ".claude", "settings.json");
221
- if (existsSync(settingsPath)) {
222
- try {
223
- const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
224
- const perms = settings.permissions?.allow || [];
225
- if (perms.some((p) => p.includes("agentcache"))) {
226
- pass("Claude Code permissions: auto-approved");
225
+ const settingsPath = join(homedir(), ".claude", "settings.json");
226
+ if (existsSync(settingsPath)) {
227
+ try {
228
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
229
+ const perms = settings.permissions?.allow || [];
230
+ if (perms.some((p) => p.includes("agentcache"))) {
231
+ pass("Claude Code permissions: auto-approved");
232
+ } else {
233
+ warning("Claude Code permissions: not in allow list");
234
+ }
235
+ if (settings.hooks?.Stop?.some((h) => JSON.stringify(h).includes("agentcache"))) {
236
+ pass("Claude Code hooks: registered");
237
+ } else {
238
+ warning("Claude Code hooks: not registered");
239
+ }
240
+ } catch {
241
+ warning("Claude Code settings: unreadable");
242
+ }
243
+ }
244
+ } else if (ide.mcpConfigFormat === "codex-toml") {
245
+ if (existsSync(ide.mcpConfigPath)) {
246
+ try {
247
+ const content = readFileSync(ide.mcpConfigPath, "utf-8");
248
+ if (content.includes("[mcp_servers.agentcache]")) {
249
+ pass(`${ide.name}: registered`);
250
+ } else {
251
+ warning(`${ide.name}: detected but not registered`);
252
+ }
253
+ } catch {
254
+ warning(`${ide.name}: config unreadable`);
255
+ }
227
256
  } else {
228
- warning("Claude Code permissions: not in allow list");
257
+ warning(`${ide.name}: detected but not registered`);
229
258
  }
230
- if (settings.hooks?.Stop?.some((h) => JSON.stringify(h).includes("agentcache"))) {
231
- pass("Claude Code hooks: registered");
259
+ } else {
260
+ if (existsSync(ide.mcpConfigPath)) {
261
+ try {
262
+ const config = JSON.parse(readFileSync(ide.mcpConfigPath, "utf-8"));
263
+ if (config.mcpServers?.agentcache) {
264
+ pass(`${ide.name}: registered`);
265
+ } else {
266
+ warning(`${ide.name}: detected but not registered`);
267
+ }
268
+ } catch {
269
+ warning(`${ide.name}: config unreadable`);
270
+ }
232
271
  } else {
233
- warning("Claude Code hooks: not registered");
272
+ warning(`${ide.name}: detected but not registered`);
234
273
  }
235
- } catch {
236
- warning("Claude Code settings: unreadable");
237
274
  }
238
275
  }
276
+ const notDetected = ides.filter((i) => !i.detected).map((i) => i.name);
277
+ if (notDetected.length > 0) {
278
+ console.log(` \xB7 Not detected: ${notDetected.join(", ")}`);
279
+ }
280
+ console.log("\nTranscript sources:");
281
+ const { findAllClaudeTranscripts, findAllCursorTranscripts, findAllContinueTranscripts, findAllCodexTranscripts, findAllRooCodeTranscripts } = await import("./transcript-JWSGSDSF.js");
282
+ const sources = [
283
+ { name: "Claude Code", fn: findAllClaudeTranscripts },
284
+ { name: "Cursor", fn: findAllCursorTranscripts },
285
+ { name: "Continue", fn: findAllContinueTranscripts },
286
+ { name: "Codex", fn: findAllCodexTranscripts },
287
+ { name: "Roo Code", fn: findAllRooCodeTranscripts }
288
+ ];
289
+ let totalTranscripts = 0;
290
+ for (const src of sources) {
291
+ const count = src.fn().length;
292
+ totalTranscripts += count;
293
+ if (count > 0) pass(`${src.name}: ${count} transcripts`);
294
+ }
295
+ if (totalTranscripts === 0) {
296
+ warning("No transcripts found from any IDE");
297
+ }
239
298
  console.log("\nLLM backends (for compile-all):");
240
299
  const backends = ["claude", "codex", "gemini", "copilot", "aider", "goose"];
241
300
  const found = [];
@@ -267,7 +326,7 @@ ${ok} passed, ${warn} warnings, ${fail} errors`);
267
326
  if (fail > 0) process.exit(1);
268
327
  });
269
328
  program.command("compile-all").description("Batch-compile all unprocessed transcripts using an available LLM CLI").action(async () => {
270
- const { runCompileAll } = await import("./compile-all-GFWXWRPX.js");
329
+ const { runCompileAll } = await import("./compile-all-PTWTZVP5.js");
271
330
  await runCompileAll();
272
331
  });
273
332
  program.command("status").description("Show AgentCache knowledge stats").action(async () => {
@@ -276,7 +335,7 @@ program.command("status").description("Show AgentCache knowledge stats").action(
276
335
  console.log("AgentCache not initialized. Run: agentcache setup");
277
336
  return;
278
337
  }
279
- const { SqliteKnowledgeRepository } = await import("./sqlite-MHG4WEHL.js");
338
+ const { SqliteKnowledgeRepository } = await import("./sqlite-NM2BVHUY.js");
280
339
  const repo = new SqliteKnowledgeRepository(getDbPath());
281
340
  const projectRoot = findProjectRoot();
282
341
  const project = getProjectId(projectRoot);
@@ -3,28 +3,29 @@ import {
3
3
  processExtraction,
4
4
  startCompile
5
5
  } from "./chunk-CUBZRYS5.js";
6
+ import "./chunk-GGAATZKM.js";
7
+ import {
8
+ acquireLock,
9
+ releaseLock
10
+ } from "./chunk-JUDLOBOC.js";
11
+ import {
12
+ SqliteKnowledgeRepository
13
+ } from "./chunk-PSASDZQE.js";
6
14
  import {
7
15
  findAllClaudeTranscripts,
8
16
  findAllCodexTranscripts,
9
17
  findAllContinueTranscripts,
18
+ findAllCursorTranscripts,
10
19
  findAllRooCodeTranscripts,
11
20
  getGooseDbPath,
12
21
  parseTranscript
13
- } from "./chunk-IGCH7SZT.js";
14
- import {
15
- acquireLock,
16
- releaseLock
17
- } from "./chunk-JUDLOBOC.js";
18
- import "./chunk-GGAATZKM.js";
22
+ } from "./chunk-WTXSZBQE.js";
19
23
  import {
20
24
  getDbPath,
21
25
  getGitRoot,
22
26
  getProjectId,
23
27
  isInitialized
24
28
  } from "./chunk-T4COG3XD.js";
25
- import {
26
- SqliteKnowledgeRepository
27
- } from "./chunk-ESDTP63R.js";
28
29
  import {
29
30
  __esm,
30
31
  __export,
@@ -294,6 +295,7 @@ function discoverAllTranscripts(repo) {
294
295
  const results = [];
295
296
  const allPaths = [
296
297
  ...findAllClaudeTranscripts(),
298
+ ...findAllCursorTranscripts(),
297
299
  ...findAllContinueTranscripts(),
298
300
  ...findAllCodexTranscripts(),
299
301
  ...findAllRooCodeTranscripts()
@@ -311,6 +313,14 @@ function inferProjectRoot(transcriptPath) {
311
313
  const slug = transcriptPath.split(".claude/projects/")[1]?.split("/")[0] || "";
312
314
  if (slug.startsWith("-")) return slug.replace(/-/g, "/");
313
315
  }
316
+ if (transcriptPath.includes(".cursor/projects/")) {
317
+ const slug = transcriptPath.split(".cursor/projects/")[1]?.split("/")[0] || "";
318
+ if (slug) {
319
+ const asPath = "/" + slug.replace(/-/g, "/");
320
+ const root = getGitRoot(asPath);
321
+ if (root) return root;
322
+ }
323
+ }
314
324
  try {
315
325
  const events = parseTranscript(transcriptPath);
316
326
  for (const event of events) {
@@ -0,0 +1,7 @@
1
+ import {
2
+ detectInstalledIdes
3
+ } from "./chunk-5UO7NJPQ.js";
4
+ import "./chunk-KFQGP6VL.js";
5
+ export {
6
+ detectInstalledIdes
7
+ };