agentcache 0.1.4 → 0.2.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.
package/README.md CHANGED
@@ -23,7 +23,7 @@ npm install -g agentcache
23
23
  Done. Start a new session in any IDE. AgentCache is already running.
24
24
 
25
25
  No `init`. No `setup`. No config. No second command. The install itself:
26
- 1. Creates `~/.loop/loop.db` (your knowledge store)
26
+ 1. Creates `~/.agentcache/agentcache.db` (your knowledge store)
27
27
  2. Detects installed IDEs (Claude Code, Cursor, Roo Code, Windsurf, Continue, Codex)
28
28
  3. Registers itself as an MCP server in each
29
29
  4. Sets up Claude Code hooks for automatic transcript recovery
@@ -49,7 +49,8 @@ No `init`. No `setup`. No config. No second command. The install itself:
49
49
  │ └────────────┬────────────┘ │
50
50
  │ │ │
51
51
  │ ┌─────────┴─────────┐ │
52
- │ │ ~/.loop/loop.db │ │
52
+ │ │ ~/.agentcache/ │ │
53
+ │ │ agentcache.db │ │
53
54
  │ │ (SQLite + WAL) │ │
54
55
  │ └───────────────────┘ │
55
56
  └─────────────────────────────────────────────────────────────────┘
@@ -57,8 +58,8 @@ No `init`. No `setup`. No config. No second command. The install itself:
57
58
 
58
59
  ### The Cycle
59
60
 
60
- 1. **Session starts** — agent calls `loop_inject_context` → gets compiled rules, lessons, decisions
61
- 2. **During session** — agent calls `loop_compile_submit` incrementally as it learns things
61
+ 1. **Session starts** — agent calls `agentcache_inject_context` → gets compiled rules, lessons, decisions
62
+ 2. **During session** — agent calls `agentcache_compile_submit` incrementally as it learns things
62
63
  3. **Session ends** — knowledge is already saved. If agent didn't submit (abrupt exit), transcript recovery handles it next session.
63
64
 
64
65
  ### Knowledge Types
@@ -78,14 +79,14 @@ AgentCache exposes 8 tools via the Model Context Protocol:
78
79
 
79
80
  | Tool | Purpose |
80
81
  |------|---------|
81
- | `loop_inject_context` | Load compiled knowledge at session start |
82
- | `loop_compile_submit` | Submit observations incrementally during session |
83
- | `loop_compile_cluster` | Resolve clustering when observations overlap existing knowledge |
84
- | `loop_compile_extract` | Process queued transcripts from previous sessions |
85
- | `loop_enforce` | Check tool calls against enforced policy rules |
86
- | `loop_save_observation` | Save a permanent observation (USER authority, never auto-deprecated) |
87
- | `loop_get_knowledge` | Query the knowledge database |
88
- | `loop_deprecate_knowledge` | Mark knowledge as deprecated when it's no longer valid |
82
+ | `agentcache_inject_context` | Load compiled knowledge at session start |
83
+ | `agentcache_compile_submit` | Submit observations incrementally during session |
84
+ | `agentcache_compile_cluster` | Resolve clustering when observations overlap existing knowledge |
85
+ | `agentcache_compile_extract` | Process queued transcripts from previous sessions |
86
+ | `agentcache_enforce` | Check tool calls against enforced policy rules |
87
+ | `agentcache_save_observation` | Save a permanent observation (USER authority, never auto-deprecated) |
88
+ | `agentcache_get_knowledge` | Query the knowledge database |
89
+ | `agentcache_deprecate_knowledge` | Mark knowledge as deprecated when it's no longer valid |
89
90
 
90
91
  ## CLI Commands
91
92
 
@@ -114,7 +115,7 @@ AgentCache uses MCP (Model Context Protocol) as its only interface. Any IDE that
114
115
 
115
116
  ### Developer-Scoped
116
117
 
117
- One database per developer (`~/.loop/loop.db`), not per project. Rules and lessons learned in one project benefit all your projects. Project-specific decisions stay scoped to their project.
118
+ One database per developer (`~/.agentcache/agentcache.db`), not per project. Rules and lessons learned in one project benefit all your projects. Project-specific decisions stay scoped to their project.
118
119
 
119
120
  ### Resilient to Abrupt Exits
120
121
 
@@ -154,11 +155,11 @@ Cursor does not support programmatic auto-approve for MCP tools. After installin
154
155
 
155
156
  ## Data Storage
156
157
 
157
- All data lives in `~/.loop/loop.db` (SQLite with WAL mode for concurrent access).
158
+ All data lives in `~/.agentcache/agentcache.db` (SQLite with WAL mode for concurrent access).
158
159
 
159
160
  ```
160
- ~/.loop/
161
- └── loop.db # All knowledge, observations, sessions, pending queue
161
+ ~/.agentcache/
162
+ └── agentcache.db # All knowledge, observations, sessions, pending queue
162
163
  ```
163
164
 
164
165
  No data leaves your machine. No network calls. No telemetry. No accounts.
@@ -193,8 +194,8 @@ Projects are identified by a hash of their full filesystem path, not just the fo
193
194
  ## Contributing
194
195
 
195
196
  ```bash
196
- git clone https://github.com/raghav-a21ai/loop-eng
197
- cd loop-eng
197
+ git clone https://github.com/raghav-a21ai/agentcache
198
+ cd agentcache
198
199
  npm install
199
200
  npm run build
200
201
  npm test
@@ -90,14 +90,14 @@ function isVscodeExtensionIde(ide) {
90
90
  return ide.name === "Roo Code" || ide.name === "Continue";
91
91
  }
92
92
  var ALL_TOOLS = [
93
- "loop_inject_context",
94
- "loop_compile_submit",
95
- "loop_compile_cluster",
96
- "loop_compile_extract",
97
- "loop_enforce",
98
- "loop_save_observation",
99
- "loop_get_knowledge",
100
- "loop_deprecate_knowledge"
93
+ "agentcache_inject_context",
94
+ "agentcache_compile_submit",
95
+ "agentcache_compile_cluster",
96
+ "agentcache_compile_extract",
97
+ "agentcache_enforce",
98
+ "agentcache_save_observation",
99
+ "agentcache_get_knowledge",
100
+ "agentcache_deprecate_knowledge"
101
101
  ];
102
102
  function registerMcpServer(ide) {
103
103
  if (!ide.detected) return false;
@@ -126,14 +126,17 @@ function registerClaudeCode() {
126
126
  }
127
127
  }
128
128
  if (!config.mcpServers) config.mcpServers = {};
129
- if (config.mcpServers.agentcache) return false;
130
- config.mcpServers.agentcache = {
131
- type: "stdio",
132
- command: "agentcache",
133
- args: ["serve"],
134
- env: {}
135
- };
136
- writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2));
129
+ let serverRegistered = false;
130
+ if (!config.mcpServers.agentcache) {
131
+ config.mcpServers.agentcache = {
132
+ type: "stdio",
133
+ command: "agentcache",
134
+ args: ["serve"],
135
+ env: {}
136
+ };
137
+ writeFileSync(claudeJsonPath, JSON.stringify(config, null, 2));
138
+ serverRegistered = true;
139
+ }
137
140
  const settingsPath = join2(homedir2(), ".claude", "settings.json");
138
141
  if (existsSync2(join2(homedir2(), ".claude"))) {
139
142
  let settings = {};
@@ -148,14 +151,18 @@ function registerClaudeCode() {
148
151
  if (!settings.permissions.allow) settings.permissions.allow = [];
149
152
  const allowList = settings.permissions.allow;
150
153
  const mcpPerms = ALL_TOOLS.map((t) => `mcp__agentcache__${t}`);
154
+ let permsUpdated = false;
151
155
  for (const perm of mcpPerms) {
152
156
  if (!allowList.includes(perm)) {
153
157
  allowList.push(perm);
158
+ permsUpdated = true;
154
159
  }
155
160
  }
156
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
161
+ if (permsUpdated) {
162
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
163
+ }
157
164
  }
158
- return true;
165
+ return serverRegistered;
159
166
  }
160
167
  function registerMcpJson(ide) {
161
168
  let config = {};
@@ -167,7 +174,7 @@ function registerMcpJson(ide) {
167
174
  }
168
175
  }
169
176
  if (!config.mcpServers) config.mcpServers = {};
170
- if (config.mcpServers.agentcache) return false;
177
+ const existing = config.mcpServers.agentcache;
171
178
  if (isVscodeExtensionIde(ide)) {
172
179
  const nodeBin = findNodeBinary();
173
180
  const script = findAgentcacheScript();
@@ -177,16 +184,18 @@ function registerMcpJson(ide) {
177
184
  alwaysAllow: ALL_TOOLS,
178
185
  disabled: false
179
186
  };
180
- } else {
187
+ } else if (!existing) {
181
188
  const agentcacheBin = findAgentcacheScript();
182
189
  config.mcpServers.agentcache = {
183
190
  command: agentcacheBin,
184
191
  args: ["serve"]
185
192
  };
193
+ } else {
194
+ return false;
186
195
  }
187
196
  mkdirSync(dirname(ide.mcpConfigPath), { recursive: true });
188
197
  writeFileSync(ide.mcpConfigPath, JSON.stringify(config, null, 2));
189
- return true;
198
+ return !existing;
190
199
  }
191
200
  function registerContinue(ide) {
192
201
  const configPath = ide.mcpConfigPath;
@@ -245,17 +254,17 @@ function registerClaudeHooks() {
245
254
  }
246
255
  if (!settings.hooks) settings.hooks = {};
247
256
  const hooks = settings.hooks;
248
- const loopHooks = {
257
+ const agentcacheHooks = {
249
258
  Stop: [{ matcher: "", hooks: [{ type: "command", command: "agentcache compile-session" }] }],
250
259
  SessionStart: [{ matcher: "", hooks: [{ type: "command", command: "agentcache discover" }] }],
251
260
  PreToolUse: [{ matcher: "", hooks: [{ type: "command", command: "agentcache enforce" }] }]
252
261
  };
253
262
  let registered = false;
254
- for (const [event, hookConfig] of Object.entries(loopHooks)) {
263
+ for (const [event, hookConfig] of Object.entries(agentcacheHooks)) {
255
264
  if (!hooks[event]) hooks[event] = [];
256
265
  const existing = hooks[event];
257
- const hasLoop = existing.some((h) => h.hooks?.some((hh) => hh.command?.includes("agentcache")));
258
- if (!hasLoop) {
266
+ const hasAgentcache = existing.some((h) => h.hooks?.some((hh) => hh.command?.includes("agentcache")));
267
+ if (!hasAgentcache) {
259
268
  hooks[event].push(...hookConfig);
260
269
  registered = true;
261
270
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getClaudeTranscriptsDir,
3
3
  getContinueSessionsDir
4
- } from "./chunk-VPEEZXLK.js";
4
+ } from "./chunk-WHP4Z32Z.js";
5
5
  import {
6
6
  __export
7
7
  } from "./chunk-MLKGABMK.js";
@@ -1,8 +1,8 @@
1
1
  // src/policy/engine.ts
2
2
  var HARDCODED_BLOCKS = [
3
- { pattern: /git\s+push\s+--force\s+(origin\s+)?(main|master)/i, reason: "Force-push to main/master is blocked by Loop policy" },
4
- { pattern: /rm\s+-rf\s+[\/~]/i, reason: "Destructive rm -rf on root or home is blocked by Loop policy" },
5
- { pattern: />\s*(.*\.(env|pem|key))/i, reason: "Writing to sensitive files (.env, .pem, .key) is blocked by Loop policy" }
3
+ { pattern: /git\s+push\s+--force\s+(origin\s+)?(main|master)/i, reason: "Force-push to main/master is blocked by AgentCache policy" },
4
+ { pattern: /rm\s+-rf\s+[\/~]/i, reason: "Destructive rm -rf on root or home is blocked by AgentCache policy" },
5
+ { pattern: />\s*(.*\.(env|pem|key))/i, reason: "Writing to sensitive files (.env, .pem, .key) is blocked by AgentCache policy" }
6
6
  ];
7
7
  function evaluatePolicy(input, enforcedRules) {
8
8
  const command = extractCommand(input.tool_name, input.tool_input);
@@ -1,6 +1,6 @@
1
1
  // src/utils/paths.ts
2
- import { existsSync } from "fs";
3
- import { join } from "path";
2
+ import { existsSync, renameSync, mkdirSync } from "fs";
3
+ import { join, dirname } from "path";
4
4
  import { homedir } from "os";
5
5
  import { createHash } from "crypto";
6
6
 
@@ -26,15 +26,23 @@ function getGitRoot(cwd) {
26
26
  }
27
27
 
28
28
  // src/utils/paths.ts
29
- function getGlobalLoopDir() {
30
- return join(homedir(), ".loop");
29
+ function getDataDir() {
30
+ return join(homedir(), ".agentcache");
31
31
  }
32
32
  function getDbPath() {
33
- return join(getGlobalLoopDir(), "loop.db");
33
+ return join(getDataDir(), "agentcache.db");
34
34
  }
35
- function isLoopInitialized() {
35
+ function isInitialized() {
36
36
  return existsSync(getDbPath());
37
37
  }
38
+ function migrateFromLegacy() {
39
+ const legacyDb = join(homedir(), ".loop", "loop.db");
40
+ const newDb = getDbPath();
41
+ if (existsSync(legacyDb) && !existsSync(newDb)) {
42
+ mkdirSync(dirname(newDb), { recursive: true });
43
+ renameSync(legacyDb, newDb);
44
+ }
45
+ }
38
46
  function findProjectRoot(cwd) {
39
47
  const dir = cwd || process.cwd();
40
48
  const gitRoot = getGitRoot(dir);
@@ -57,9 +65,10 @@ function getContinueSessionsDir() {
57
65
 
58
66
  export {
59
67
  getGitContext,
60
- getGlobalLoopDir,
68
+ getDataDir,
61
69
  getDbPath,
62
- isLoopInitialized,
70
+ isInitialized,
71
+ migrateFromLegacy,
63
72
  findProjectRoot,
64
73
  getProjectId,
65
74
  getProjectDisplayName,
package/dist/cli.js CHANGED
@@ -4,16 +4,16 @@
4
4
  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.0");
7
- program.command("setup").description("Detect IDEs and register Loop (runs automatically on install)").action(async () => {
8
- const { runSetup } = await import("./setup-YHD2FO4N.js");
7
+ program.command("setup").description("Detect IDEs and register AgentCache (runs automatically on install)").action(async () => {
8
+ const { runSetup } = await import("./setup-YCFTG2KT.js");
9
9
  await runSetup();
10
10
  });
11
- program.command("serve").description("Start Loop MCP server (spawned by IDEs automatically)").action(async () => {
11
+ program.command("serve").description("Start AgentCache MCP server (spawned by IDEs automatically)").action(async () => {
12
12
  const { startMcpServer } = await import("./mcp.js");
13
13
  await startMcpServer();
14
14
  });
15
15
  program.command("compile-session").description("Stop hook: queue transcript for compilation").action(async () => {
16
- const { handleStop } = await import("./stop-DRL3LXFQ.js");
16
+ const { handleStop } = await import("./stop-6MKD743B.js");
17
17
  let payload;
18
18
  try {
19
19
  let data = "";
@@ -28,11 +28,11 @@ program.command("compile-session").description("Stop hook: queue transcript for
28
28
  await handleStop(payload);
29
29
  });
30
30
  program.command("discover").description("SessionStart hook: discover uncompiled transcripts").action(async () => {
31
- const { handleSessionStart } = await import("./session-start-ILEPFZZC.js");
31
+ const { handleSessionStart } = await import("./session-start-BIY7CBXU.js");
32
32
  await handleSessionStart();
33
33
  });
34
34
  program.command("enforce").description("PreToolUse hook: policy enforcement").action(async () => {
35
- const { handlePreToolUse } = await import("./pre-tool-use-2P5P6JWE.js");
35
+ const { handlePreToolUse } = await import("./pre-tool-use-TPCPTJXS.js");
36
36
  let data = "";
37
37
  for await (const chunk of process.stdin) {
38
38
  data += chunk;
@@ -45,10 +45,10 @@ program.command("enforce").description("PreToolUse hook: policy enforcement").ac
45
45
  process.stdout.write("{}");
46
46
  }
47
47
  });
48
- program.command("status").description("Show Loop knowledge stats").action(async () => {
49
- const { getDbPath, isLoopInitialized, findProjectRoot, getProjectId, getProjectDisplayName } = await import("./paths-TWJ7GAJY.js");
50
- if (!isLoopInitialized()) {
51
- console.log("Loop not initialized. Run: agentcache setup");
48
+ program.command("status").description("Show AgentCache knowledge stats").action(async () => {
49
+ const { getDbPath, isInitialized, findProjectRoot, getProjectId, getProjectDisplayName } = await import("./paths-LEZQCRKI.js");
50
+ if (!isInitialized()) {
51
+ console.log("AgentCache not initialized. Run: agentcache setup");
52
52
  return;
53
53
  }
54
54
  const { SqliteKnowledgeRepository } = await import("./sqlite-5V565IV3.js");
@@ -65,7 +65,7 @@ program.command("status").description("Show Loop knowledge stats").action(async
65
65
  const projectItems = items.filter((i) => i.scope === "project");
66
66
  const pending = repo.getPendingCount();
67
67
  repo.close();
68
- console.log(`Loop \u2014 ${displayName} (${project})`);
68
+ console.log(`AgentCache \u2014 ${displayName} (${project})`);
69
69
  console.log(` ${items.length} items (${globalItems.length} global, ${projectItems.length} project)`);
70
70
  console.log(` ${rules.length} rules | ${lessons.length} lessons | ${decisions.length} decisions | ${context.length} context`);
71
71
  if (pending > 0) console.log(` ${pending} sessions pending compilation`);
package/dist/mcp.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  evaluatePolicy
3
- } from "./chunk-PYGRUQNL.js";
3
+ } from "./chunk-T7BJPANN.js";
4
4
  import {
5
5
  parseTranscript
6
- } from "./chunk-QGG25FWV.js";
6
+ } from "./chunk-OSFK44XC.js";
7
7
  import {
8
8
  findProjectRoot,
9
9
  getDbPath,
10
10
  getGitContext,
11
11
  getProjectId,
12
- isLoopInitialized
13
- } from "./chunk-VPEEZXLK.js";
12
+ isInitialized
13
+ } from "./chunk-WHP4Z32Z.js";
14
14
  import {
15
15
  SqliteKnowledgeRepository
16
16
  } from "./chunk-MMSMDJ4O.js";
@@ -528,7 +528,7 @@ function saveCompileRun(repo, sessionId, project, observationsProcessed, autoRei
528
528
  }
529
529
  function formatDiagnostics(extracted, autoReinforced, created, reinforced, superseded, deprecated, ignored, project, sessionId) {
530
530
  return [
531
- `Loop Compiler v${COMPILER_VERSION}`,
531
+ `AgentCache Compiler v${COMPILER_VERSION}`,
532
532
  `Project: ${project} | Session: ${sessionId}`,
533
533
  ` ${extracted} observations processed`,
534
534
  autoReinforced > 0 ? ` ${autoReinforced} auto-reinforced (no LLM needed)` : "",
@@ -570,7 +570,7 @@ async function startMcpServer() {
570
570
  { name: "agentcache", version: "0.1.0" },
571
571
  {
572
572
  capabilities: { tools: {} },
573
- instructions: "AgentCache is your knowledge cache. At the START of every session, call loop_inject_context to load compiled rules, lessons, decisions, and context. Submit observations INCREMENTALLY via loop_compile_submit as you learn them \u2014 do not wait until session end."
573
+ instructions: "AgentCache is your knowledge cache. At the START of every session, call agentcache_inject_context to load compiled rules, lessons, decisions, and context. Submit observations INCREMENTALLY via agentcache_compile_submit as you learn them \u2014 do not wait until session end."
574
574
  }
575
575
  );
576
576
  server.oninitialized = async () => {
@@ -582,7 +582,7 @@ async function startMcpServer() {
582
582
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
583
583
  tools: [
584
584
  {
585
- name: "loop_inject_context",
585
+ name: "agentcache_inject_context",
586
586
  description: "Get compiled engineering knowledge for this project. Returns global rules/lessons (apply everywhere) + project-specific decisions/context. Call this at the START of every session.",
587
587
  inputSchema: {
588
588
  type: "object",
@@ -593,7 +593,7 @@ async function startMcpServer() {
593
593
  }
594
594
  },
595
595
  {
596
- name: "loop_compile_submit",
596
+ name: "agentcache_compile_submit",
597
597
  description: "Submit observations extracted from your session. Call this INCREMENTALLY \u2014 each time you learn a rule, lesson, decision, or context item. Do NOT batch until end of session; sessions can terminate without warning.",
598
598
  inputSchema: {
599
599
  type: "object",
@@ -619,12 +619,12 @@ async function startMcpServer() {
619
619
  }
620
620
  },
621
621
  {
622
- name: "loop_compile_cluster",
623
- description: "Submit clustering decisions when loop_compile_submit returns needs_clustering. Determines whether observations create new knowledge or relate to existing items.",
622
+ name: "agentcache_compile_cluster",
623
+ description: "Submit clustering decisions when agentcache_compile_submit returns needs_clustering. Determines whether observations create new knowledge or relate to existing items.",
624
624
  inputSchema: {
625
625
  type: "object",
626
626
  properties: {
627
- sessionId: { type: "string", description: "Session ID from loop_compile_submit response" },
627
+ sessionId: { type: "string", description: "Session ID from agentcache_compile_submit response" },
628
628
  clusters: {
629
629
  type: "array",
630
630
  items: {
@@ -644,8 +644,8 @@ async function startMcpServer() {
644
644
  }
645
645
  },
646
646
  {
647
- name: "loop_compile_extract",
648
- description: "For PREVIOUS sessions stored as transcript files. Reads a queued transcript and returns an extraction prompt for you to process. After processing, call loop_compile_submit with the results.",
647
+ name: "agentcache_compile_extract",
648
+ description: "For PREVIOUS sessions stored as transcript files. Reads a queued transcript and returns an extraction prompt for you to process. After processing, call agentcache_compile_submit with the results.",
649
649
  inputSchema: {
650
650
  type: "object",
651
651
  properties: {
@@ -655,8 +655,8 @@ async function startMcpServer() {
655
655
  }
656
656
  },
657
657
  {
658
- name: "loop_enforce",
659
- description: "Check if a tool call is allowed by Loop's policy rules. Call this BEFORE executing risky operations (file deletions, force pushes, etc). Returns allow or block with reason.",
658
+ name: "agentcache_enforce",
659
+ description: "Check if a tool call is allowed by AgentCache policy rules. Call this BEFORE executing risky operations (file deletions, force pushes, etc). Returns allow or block with reason.",
660
660
  inputSchema: {
661
661
  type: "object",
662
662
  properties: {
@@ -668,7 +668,7 @@ async function startMcpServer() {
668
668
  }
669
669
  },
670
670
  {
671
- name: "loop_save_observation",
671
+ name: "agentcache_save_observation",
672
672
  description: "Save a single observation immediately with USER authority (never overwritten by compiler). Use for important rules or decisions that should persist permanently.",
673
673
  inputSchema: {
674
674
  type: "object",
@@ -683,8 +683,8 @@ async function startMcpServer() {
683
683
  }
684
684
  },
685
685
  {
686
- name: "loop_get_knowledge",
687
- description: "Query knowledge items from Loop's compiled database.",
686
+ name: "agentcache_get_knowledge",
687
+ description: "Query knowledge items from AgentCache knowledge database.",
688
688
  inputSchema: {
689
689
  type: "object",
690
690
  properties: {
@@ -697,7 +697,7 @@ async function startMcpServer() {
697
697
  }
698
698
  },
699
699
  {
700
- name: "loop_deprecate_knowledge",
700
+ name: "agentcache_deprecate_knowledge",
701
701
  description: "Mark a knowledge item as deprecated. Use when a rule, lesson, or decision is no longer valid. Works on both auto-compiled and user-saved items.",
702
702
  inputSchema: {
703
703
  type: "object",
@@ -711,15 +711,15 @@ async function startMcpServer() {
711
711
  ]
712
712
  }));
713
713
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
714
- if (!isLoopInitialized()) {
715
- return { content: [{ type: "text", text: "Loop not initialized. Run: agentcache setup" }], isError: true };
714
+ if (!isInitialized()) {
715
+ return { content: [{ type: "text", text: "AgentCache not initialized. Run: agentcache setup" }], isError: true };
716
716
  }
717
717
  const repo = new SqliteKnowledgeRepository(getDbPath());
718
718
  const projectRoot = getResolvedProjectRoot();
719
719
  const detectedProject = getResolvedProjectId();
720
720
  try {
721
721
  switch (request.params.name) {
722
- case "loop_inject_context": {
722
+ case "agentcache_inject_context": {
723
723
  const args = request.params.arguments || {};
724
724
  const project = args.project || detectedProject;
725
725
  const items = repo.getKnowledgeForContext(project);
@@ -740,17 +740,17 @@ async function startMcpServer() {
740
740
  if (context.length) {
741
741
  output += "# Context\n" + context.map((c) => `- ${c.content}`).join("\n") + "\n\n";
742
742
  }
743
- if (!output) output = "No compiled knowledge yet. This will populate as you use Loop across sessions.\n";
743
+ if (!output) output = "No compiled knowledge yet. This will populate as you use AgentCache across sessions.\n";
744
744
  const pendingCount = repo.getPendingCount();
745
745
  if (pendingCount > 0) {
746
- output = `<!-- ${pendingCount} previous session(s) pending compilation. Call loop_compile_extract to process. -->
746
+ output = `<!-- ${pendingCount} previous session(s) pending compilation. Call agentcache_compile_extract to process. -->
747
747
 
748
748
  ` + output;
749
749
  }
750
- output += "\n---\nIMPORTANT: Submit observations incrementally as they happen during this session.\nWhen you learn something (rule, lesson, decision, context), call loop_compile_submit immediately.\nDo NOT wait until the end \u2014 sessions can terminate without warning.\n";
750
+ output += "\n---\nIMPORTANT: Submit observations incrementally as they happen during this session.\nWhen you learn something (rule, lesson, decision, context), call agentcache_compile_submit immediately.\nDo NOT wait until the end \u2014 sessions can terminate without warning.\n";
751
751
  return { content: [{ type: "text", text: output.trim() }] };
752
752
  }
753
- case "loop_compile_submit": {
753
+ case "agentcache_compile_submit": {
754
754
  const args = request.params.arguments;
755
755
  const project = args.project || detectedProject;
756
756
  const sessionId = `sess_${randomUUID4().slice(0, 8)}`;
@@ -768,14 +768,14 @@ async function startMcpServer() {
768
768
  content: [{ type: "text", text: JSON.stringify({ status: "needs_clustering", sessionId: result.sessionId, clusteringContext: result.clusteringPrompt }) }]
769
769
  };
770
770
  }
771
- case "loop_compile_cluster": {
771
+ case "agentcache_compile_cluster": {
772
772
  const args = request.params.arguments;
773
773
  const project = args.project || detectedProject;
774
774
  const responseText = JSON.stringify({ clusters: args.clusters });
775
775
  const result = processClustering(repo, responseText, args.sessionId, project, projectRoot);
776
776
  return { content: [{ type: "text", text: JSON.stringify({ status: "complete", diagnostics: result.diagnostics }) }] };
777
777
  }
778
- case "loop_compile_extract": {
778
+ case "agentcache_compile_extract": {
779
779
  const args = request.params.arguments || {};
780
780
  const entry = repo.popPendingTranscript();
781
781
  if (!entry) {
@@ -793,14 +793,14 @@ async function startMcpServer() {
793
793
  const state = startCompile(events, sessionId, project, entry.projectRoot || projectRoot, repo, entry.transcriptPath);
794
794
  return { content: [{ type: "text", text: JSON.stringify({ sessionId: state.sessionId, prompt: state.prompt }) }] };
795
795
  }
796
- case "loop_enforce": {
796
+ case "agentcache_enforce": {
797
797
  const args = request.params.arguments;
798
798
  const project = args.project || detectedProject;
799
799
  const input = { tool_name: args.tool_name, tool_input: args.tool_input || {} };
800
800
  const result = evaluatePolicy(input, repo.getEnforcedRules(project));
801
801
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
802
802
  }
803
- case "loop_save_observation": {
803
+ case "agentcache_save_observation": {
804
804
  const args = request.params.arguments;
805
805
  const project = args.project || detectedProject;
806
806
  const scope = args.scope || defaultScope(args.type);
@@ -849,7 +849,7 @@ async function startMcpServer() {
849
849
  });
850
850
  return { content: [{ type: "text", text: JSON.stringify({ saved: true, scope }) }] };
851
851
  }
852
- case "loop_get_knowledge": {
852
+ case "agentcache_get_knowledge": {
853
853
  const args = request.params.arguments || {};
854
854
  const project = args.project || detectedProject;
855
855
  const items = repo.getKnowledgeItems(project, {
@@ -860,7 +860,7 @@ async function startMcpServer() {
860
860
  const summary = filtered.map((i) => `[${i.id}] [${i.scope}/${i.confidence}] (${i.type}) ${i.content}`).join("\n");
861
861
  return { content: [{ type: "text", text: summary || "No knowledge items found." }] };
862
862
  }
863
- case "loop_deprecate_knowledge": {
863
+ case "agentcache_deprecate_knowledge": {
864
864
  const args = request.params.arguments;
865
865
  const item = repo.getKnowledgeItem(args.id);
866
866
  if (!item) {
@@ -2,20 +2,22 @@ import {
2
2
  findProjectRoot,
3
3
  getClaudeTranscriptsDir,
4
4
  getContinueSessionsDir,
5
+ getDataDir,
5
6
  getDbPath,
6
- getGlobalLoopDir,
7
7
  getProjectDisplayName,
8
8
  getProjectId,
9
- isLoopInitialized
10
- } from "./chunk-VPEEZXLK.js";
9
+ isInitialized,
10
+ migrateFromLegacy
11
+ } from "./chunk-WHP4Z32Z.js";
11
12
  import "./chunk-MLKGABMK.js";
12
13
  export {
13
14
  findProjectRoot,
14
15
  getClaudeTranscriptsDir,
15
16
  getContinueSessionsDir,
17
+ getDataDir,
16
18
  getDbPath,
17
- getGlobalLoopDir,
18
19
  getProjectDisplayName,
19
20
  getProjectId,
20
- isLoopInitialized
21
+ isInitialized,
22
+ migrateFromLegacy
21
23
  };
@@ -2,11 +2,12 @@ import {
2
2
  detectInstalledIdes,
3
3
  registerClaudeHooks,
4
4
  registerMcpServer
5
- } from "./chunk-MKQKD2PY.js";
5
+ } from "./chunk-LDQPTAZ7.js";
6
6
  import {
7
+ getDataDir,
7
8
  getDbPath,
8
- getGlobalLoopDir
9
- } from "./chunk-VPEEZXLK.js";
9
+ migrateFromLegacy
10
+ } from "./chunk-WHP4Z32Z.js";
10
11
  import {
11
12
  SqliteKnowledgeRepository
12
13
  } from "./chunk-MMSMDJ4O.js";
@@ -18,7 +19,8 @@ if (process.env.CI) {
18
19
  process.exit(0);
19
20
  }
20
21
  try {
21
- mkdirSync(getGlobalLoopDir(), { recursive: true });
22
+ migrateFromLegacy();
23
+ mkdirSync(getDataDir(), { recursive: true });
22
24
  const repo = new SqliteKnowledgeRepository(getDbPath());
23
25
  repo.close();
24
26
  const ides = detectInstalledIdes().filter((i) => i.detected);
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  evaluatePolicy
3
- } from "./chunk-PYGRUQNL.js";
3
+ } from "./chunk-T7BJPANN.js";
4
4
  import {
5
5
  findProjectRoot,
6
6
  getDbPath,
7
7
  getProjectId,
8
- isLoopInitialized
9
- } from "./chunk-VPEEZXLK.js";
8
+ isInitialized
9
+ } from "./chunk-WHP4Z32Z.js";
10
10
  import {
11
11
  SqliteKnowledgeRepository
12
12
  } from "./chunk-MMSMDJ4O.js";
@@ -14,7 +14,7 @@ import "./chunk-MLKGABMK.js";
14
14
 
15
15
  // src/hooks/pre-tool-use.ts
16
16
  function handlePreToolUse(input) {
17
- if (!isLoopInitialized()) return {};
17
+ if (!isInitialized()) return {};
18
18
  const projectRoot = findProjectRoot();
19
19
  const repo = new SqliteKnowledgeRepository(getDbPath());
20
20
  try {
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  findAllClaudeTranscripts,
3
3
  findAllContinueTranscripts
4
- } from "./chunk-QGG25FWV.js";
4
+ } from "./chunk-OSFK44XC.js";
5
5
  import {
6
6
  getDbPath,
7
7
  getProjectId,
8
- isLoopInitialized
9
- } from "./chunk-VPEEZXLK.js";
8
+ isInitialized
9
+ } from "./chunk-WHP4Z32Z.js";
10
10
  import {
11
11
  SqliteKnowledgeRepository
12
12
  } from "./chunk-MMSMDJ4O.js";
@@ -25,7 +25,7 @@ function inferProjectRootFromTranscriptPath(path) {
25
25
  return dir;
26
26
  }
27
27
  async function handleSessionStart() {
28
- if (!isLoopInitialized()) return;
28
+ if (!isInitialized()) return;
29
29
  const repo = new SqliteKnowledgeRepository(getDbPath());
30
30
  const compiledPaths = new Set(repo.getAllCompiledTranscriptPaths());
31
31
  const allTranscripts = [
@@ -2,11 +2,12 @@ import {
2
2
  detectInstalledIdes,
3
3
  registerClaudeHooks,
4
4
  registerMcpServer
5
- } from "./chunk-MKQKD2PY.js";
5
+ } from "./chunk-LDQPTAZ7.js";
6
6
  import {
7
+ getDataDir,
7
8
  getDbPath,
8
- getGlobalLoopDir
9
- } from "./chunk-VPEEZXLK.js";
9
+ migrateFromLegacy
10
+ } from "./chunk-WHP4Z32Z.js";
10
11
  import {
11
12
  SqliteKnowledgeRepository
12
13
  } from "./chunk-MMSMDJ4O.js";
@@ -15,13 +16,14 @@ import "./chunk-MLKGABMK.js";
15
16
  // src/setup.ts
16
17
  import { mkdirSync } from "fs";
17
18
  async function runSetup() {
18
- mkdirSync(getGlobalLoopDir(), { recursive: true });
19
+ migrateFromLegacy();
20
+ mkdirSync(getDataDir(), { recursive: true });
19
21
  const repo = new SqliteKnowledgeRepository(getDbPath());
20
22
  repo.close();
21
23
  const ides = detectInstalledIdes();
22
24
  const detected = ides.filter((i) => i.detected);
23
25
  console.log(`
24
- Loop setup complete.`);
26
+ AgentCache setup complete.`);
25
27
  console.log(` Central DB: ${getDbPath()}
26
28
  `);
27
29
  if (detected.length === 0) {
@@ -40,7 +42,7 @@ Loop setup complete.`);
40
42
  Claude Code hooks: registered (Stop, SessionStart, PreToolUse)`);
41
43
  }
42
44
  console.log(`
43
- Done. Loop compiles knowledge across all sessions and IDEs.`);
45
+ Done. AgentCache compiles knowledge across all sessions and IDEs.`);
44
46
  }
45
47
  export {
46
48
  runSetup
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  findLatestTranscript
3
- } from "./chunk-QGG25FWV.js";
3
+ } from "./chunk-OSFK44XC.js";
4
4
  import {
5
5
  findProjectRoot,
6
6
  getDbPath,
7
7
  getProjectId,
8
- isLoopInitialized
9
- } from "./chunk-VPEEZXLK.js";
8
+ isInitialized
9
+ } from "./chunk-WHP4Z32Z.js";
10
10
  import {
11
11
  SqliteKnowledgeRepository
12
12
  } from "./chunk-MMSMDJ4O.js";
@@ -15,7 +15,7 @@ import "./chunk-MLKGABMK.js";
15
15
  // src/hooks/stop.ts
16
16
  import { randomUUID } from "crypto";
17
17
  async function handleStop(payload) {
18
- if (!isLoopInitialized()) return;
18
+ if (!isInitialized()) return;
19
19
  const transcriptPath = payload?.transcript_path || findLatestTranscript();
20
20
  if (!transcriptPath) return;
21
21
  const repo = new SqliteKnowledgeRepository(getDbPath());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentcache",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Knowledge cache for AI agents — learns how you work, remembers across sessions, works everywhere",
5
5
  "type": "module",
6
6
  "license": "MIT",