ziiagentmemory 0.1.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 (160) hide show
  1. package/.env.example +175 -0
  2. package/AGENTS.md +124 -0
  3. package/LICENSE +190 -0
  4. package/README.md +1546 -0
  5. package/dist/cli.d.mts +5 -0
  6. package/dist/cli.d.mts.map +1 -0
  7. package/dist/cli.mjs +2859 -0
  8. package/dist/cli.mjs.map +1 -0
  9. package/dist/config-ChC9EtgV.mjs +259 -0
  10. package/dist/config-ChC9EtgV.mjs.map +1 -0
  11. package/dist/connect-JnsJXc68.mjs +1075 -0
  12. package/dist/connect-JnsJXc68.mjs.map +1 -0
  13. package/dist/hooks/notification.d.mts +1 -0
  14. package/dist/hooks/notification.mjs +74 -0
  15. package/dist/hooks/notification.mjs.map +1 -0
  16. package/dist/hooks/post-commit.d.mts +1 -0
  17. package/dist/hooks/post-commit.mjs +101 -0
  18. package/dist/hooks/post-commit.mjs.map +1 -0
  19. package/dist/hooks/post-tool-failure.d.mts +1 -0
  20. package/dist/hooks/post-tool-failure.mjs +75 -0
  21. package/dist/hooks/post-tool-failure.mjs.map +1 -0
  22. package/dist/hooks/post-tool-use.d.mts +1 -0
  23. package/dist/hooks/post-tool-use.mjs +120 -0
  24. package/dist/hooks/post-tool-use.mjs.map +1 -0
  25. package/dist/hooks/pre-compact.d.mts +1 -0
  26. package/dist/hooks/pre-compact.mjs +78 -0
  27. package/dist/hooks/pre-compact.mjs.map +1 -0
  28. package/dist/hooks/pre-tool-use.d.mts +1 -0
  29. package/dist/hooks/pre-tool-use.mjs +84 -0
  30. package/dist/hooks/pre-tool-use.mjs.map +1 -0
  31. package/dist/hooks/prompt-submit.d.mts +1 -0
  32. package/dist/hooks/prompt-submit.mjs +67 -0
  33. package/dist/hooks/prompt-submit.mjs.map +1 -0
  34. package/dist/hooks/session-end.d.mts +1 -0
  35. package/dist/hooks/session-end.mjs +60 -0
  36. package/dist/hooks/session-end.mjs.map +1 -0
  37. package/dist/hooks/session-start.d.mts +1 -0
  38. package/dist/hooks/session-start.mjs +85 -0
  39. package/dist/hooks/session-start.mjs.map +1 -0
  40. package/dist/hooks/stop.d.mts +1 -0
  41. package/dist/hooks/stop.mjs +44 -0
  42. package/dist/hooks/stop.mjs.map +1 -0
  43. package/dist/hooks/subagent-start.d.mts +1 -0
  44. package/dist/hooks/subagent-start.mjs +73 -0
  45. package/dist/hooks/subagent-start.mjs.map +1 -0
  46. package/dist/hooks/subagent-stop.d.mts +1 -0
  47. package/dist/hooks/subagent-stop.mjs +74 -0
  48. package/dist/hooks/subagent-stop.mjs.map +1 -0
  49. package/dist/hooks/task-completed.d.mts +1 -0
  50. package/dist/hooks/task-completed.mjs +73 -0
  51. package/dist/hooks/task-completed.mjs.map +1 -0
  52. package/dist/image-refs-BKLmp_sD.mjs +34 -0
  53. package/dist/image-refs-BKLmp_sD.mjs.map +1 -0
  54. package/dist/image-refs-C2YU7BIm.mjs +34 -0
  55. package/dist/image-refs-C2YU7BIm.mjs.map +1 -0
  56. package/dist/index.d.mts +2 -0
  57. package/dist/index.mjs +22324 -0
  58. package/dist/index.mjs.map +1 -0
  59. package/dist/keyed-mutex-DTHtcZrt.mjs +88 -0
  60. package/dist/keyed-mutex-DTHtcZrt.mjs.map +1 -0
  61. package/dist/logger-BEB7pCI9.mjs +43 -0
  62. package/dist/logger-BEB7pCI9.mjs.map +1 -0
  63. package/dist/schema-CNiCWzV9.mjs +78 -0
  64. package/dist/schema-CNiCWzV9.mjs.map +1 -0
  65. package/dist/src-Cr3pH_uH.mjs +20745 -0
  66. package/dist/src-Cr3pH_uH.mjs.map +1 -0
  67. package/dist/standalone-C6KzNkt5.mjs +700 -0
  68. package/dist/standalone-C6KzNkt5.mjs.map +1 -0
  69. package/dist/standalone.d.mts +25 -0
  70. package/dist/standalone.d.mts.map +1 -0
  71. package/dist/standalone.mjs +1867 -0
  72. package/dist/standalone.mjs.map +1 -0
  73. package/dist/tools-registry-DCt2KAWA.mjs +1145 -0
  74. package/dist/tools-registry-DCt2KAWA.mjs.map +1 -0
  75. package/docker-compose.yml +47 -0
  76. package/iii-config.docker.yaml +53 -0
  77. package/iii-config.yaml +61 -0
  78. package/package.json +99 -0
  79. package/plugin/.claude-plugin/plugin.json +13 -0
  80. package/plugin/.codex-plugin/plugin.json +15 -0
  81. package/plugin/.mcp.copilot.json +15 -0
  82. package/plugin/.mcp.json +13 -0
  83. package/plugin/hooks/hooks.codex.json +67 -0
  84. package/plugin/hooks/hooks.copilot.json +72 -0
  85. package/plugin/hooks/hooks.json +125 -0
  86. package/plugin/opencode/README.md +229 -0
  87. package/plugin/opencode/agentmemory-capture.ts +687 -0
  88. package/plugin/opencode/commands/recall.md +19 -0
  89. package/plugin/opencode/commands/remember.md +19 -0
  90. package/plugin/opencode/plugin.json +12 -0
  91. package/plugin/plugin.json +15 -0
  92. package/plugin/scripts/diagnostics.mjs +551 -0
  93. package/plugin/scripts/notification.d.mts +1 -0
  94. package/plugin/scripts/notification.mjs +74 -0
  95. package/plugin/scripts/notification.mjs.map +1 -0
  96. package/plugin/scripts/post-commit.d.mts +1 -0
  97. package/plugin/scripts/post-commit.mjs +101 -0
  98. package/plugin/scripts/post-commit.mjs.map +1 -0
  99. package/plugin/scripts/post-tool-failure.d.mts +1 -0
  100. package/plugin/scripts/post-tool-failure.mjs +75 -0
  101. package/plugin/scripts/post-tool-failure.mjs.map +1 -0
  102. package/plugin/scripts/post-tool-use.d.mts +1 -0
  103. package/plugin/scripts/post-tool-use.mjs +120 -0
  104. package/plugin/scripts/post-tool-use.mjs.map +1 -0
  105. package/plugin/scripts/pre-compact.d.mts +1 -0
  106. package/plugin/scripts/pre-compact.mjs +78 -0
  107. package/plugin/scripts/pre-compact.mjs.map +1 -0
  108. package/plugin/scripts/pre-tool-use.d.mts +1 -0
  109. package/plugin/scripts/pre-tool-use.mjs +84 -0
  110. package/plugin/scripts/pre-tool-use.mjs.map +1 -0
  111. package/plugin/scripts/prompt-submit.d.mts +1 -0
  112. package/plugin/scripts/prompt-submit.mjs +67 -0
  113. package/plugin/scripts/prompt-submit.mjs.map +1 -0
  114. package/plugin/scripts/session-end.d.mts +1 -0
  115. package/plugin/scripts/session-end.mjs +60 -0
  116. package/plugin/scripts/session-end.mjs.map +1 -0
  117. package/plugin/scripts/session-start.d.mts +1 -0
  118. package/plugin/scripts/session-start.mjs +85 -0
  119. package/plugin/scripts/session-start.mjs.map +1 -0
  120. package/plugin/scripts/stop.d.mts +1 -0
  121. package/plugin/scripts/stop.mjs +44 -0
  122. package/plugin/scripts/stop.mjs.map +1 -0
  123. package/plugin/scripts/subagent-start.d.mts +1 -0
  124. package/plugin/scripts/subagent-start.mjs +73 -0
  125. package/plugin/scripts/subagent-start.mjs.map +1 -0
  126. package/plugin/scripts/subagent-stop.d.mts +1 -0
  127. package/plugin/scripts/subagent-stop.mjs +74 -0
  128. package/plugin/scripts/subagent-stop.mjs.map +1 -0
  129. package/plugin/scripts/task-completed.d.mts +1 -0
  130. package/plugin/scripts/task-completed.mjs +73 -0
  131. package/plugin/scripts/task-completed.mjs.map +1 -0
  132. package/plugin/skills/_shared/TROUBLESHOOTING.md +38 -0
  133. package/plugin/skills/agentmemory-agents/REFERENCE.md +28 -0
  134. package/plugin/skills/agentmemory-agents/SKILL.md +34 -0
  135. package/plugin/skills/agentmemory-architecture/SKILL.md +33 -0
  136. package/plugin/skills/agentmemory-config/REFERENCE.md +42 -0
  137. package/plugin/skills/agentmemory-config/SKILL.md +37 -0
  138. package/plugin/skills/agentmemory-hooks/REFERENCE.md +20 -0
  139. package/plugin/skills/agentmemory-hooks/SKILL.md +39 -0
  140. package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +65 -0
  141. package/plugin/skills/agentmemory-mcp-tools/SKILL.md +39 -0
  142. package/plugin/skills/agentmemory-rest-api/REFERENCE.md +129 -0
  143. package/plugin/skills/agentmemory-rest-api/SKILL.md +43 -0
  144. package/plugin/skills/commit-context/EXAMPLES.md +71 -0
  145. package/plugin/skills/commit-context/SKILL.md +64 -0
  146. package/plugin/skills/commit-history/EXAMPLES.md +71 -0
  147. package/plugin/skills/commit-history/SKILL.md +62 -0
  148. package/plugin/skills/forget/EXAMPLES.md +75 -0
  149. package/plugin/skills/forget/SKILL.md +66 -0
  150. package/plugin/skills/handoff/EXAMPLES.md +56 -0
  151. package/plugin/skills/handoff/SKILL.md +68 -0
  152. package/plugin/skills/recall/EXAMPLES.md +74 -0
  153. package/plugin/skills/recall/SKILL.md +60 -0
  154. package/plugin/skills/recap/EXAMPLES.md +60 -0
  155. package/plugin/skills/recap/SKILL.md +63 -0
  156. package/plugin/skills/remember/EXAMPLES.md +67 -0
  157. package/plugin/skills/remember/SKILL.md +61 -0
  158. package/plugin/skills/session-history/EXAMPLES.md +59 -0
  159. package/plugin/skills/session-history/SKILL.md +61 -0
  160. package/plugin/skills/write-agentmemory-skill/SKILL.md +40 -0
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ //#region src/hooks/session-end.ts
3
+ function isSdkChildContext(payload) {
4
+ if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
5
+ if (!payload || typeof payload !== "object") return false;
6
+ return payload.entrypoint === "sdk-ts";
7
+ }
8
+ const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
9
+ const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
10
+ function authHeaders() {
11
+ const h = { "Content-Type": "application/json" };
12
+ if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
13
+ return h;
14
+ }
15
+ async function main() {
16
+ let input = "";
17
+ for await (const chunk of process.stdin) input += chunk;
18
+ let data;
19
+ try {
20
+ data = JSON.parse(input);
21
+ } catch {
22
+ return;
23
+ }
24
+ if (isSdkChildContext(data)) return;
25
+ const sessionId = data.session_id || data.sessionId || "unknown";
26
+ fetch(`${REST_URL}/agentmemory/session/end`, {
27
+ method: "POST",
28
+ headers: authHeaders(),
29
+ body: JSON.stringify({ sessionId }),
30
+ signal: AbortSignal.timeout(3e4)
31
+ }).catch(() => {});
32
+ if (process.env["CONSOLIDATION_ENABLED"] === "true") {
33
+ fetch(`${REST_URL}/agentmemory/crystals/auto`, {
34
+ method: "POST",
35
+ headers: authHeaders(),
36
+ body: JSON.stringify({ olderThanDays: 0 }),
37
+ signal: AbortSignal.timeout(6e4)
38
+ }).catch(() => {});
39
+ fetch(`${REST_URL}/agentmemory/consolidate-pipeline`, {
40
+ method: "POST",
41
+ headers: authHeaders(),
42
+ body: JSON.stringify({
43
+ tier: "all",
44
+ force: true
45
+ }),
46
+ signal: AbortSignal.timeout(12e4)
47
+ }).catch(() => {});
48
+ }
49
+ if (process.env["CLAUDE_MEMORY_BRIDGE"] === "true") fetch(`${REST_URL}/agentmemory/claude-bridge/sync`, {
50
+ method: "POST",
51
+ headers: authHeaders(),
52
+ signal: AbortSignal.timeout(3e4)
53
+ }).catch(() => {});
54
+ setTimeout(() => process.exit(0), 1500).unref();
55
+ }
56
+ main();
57
+ //#endregion
58
+ export {};
59
+
60
+ //# sourceMappingURL=session-end.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-end.mjs","names":[],"sources":["../../src/hooks/session-end.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n\r\n fetch(`${REST_URL}/agentmemory/session/end`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ sessionId }),\r\n signal: AbortSignal.timeout(30000),\r\n }).catch(() => {});\r\n\r\n if (process.env[\"CONSOLIDATION_ENABLED\"] === \"true\") {\r\n fetch(`${REST_URL}/agentmemory/crystals/auto`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ olderThanDays: 0 }),\r\n signal: AbortSignal.timeout(60000),\r\n }).catch(() => {});\r\n\r\n fetch(`${REST_URL}/agentmemory/consolidate-pipeline`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ tier: \"all\", force: true }),\r\n signal: AbortSignal.timeout(120000),\r\n }).catch(() => {});\r\n }\r\n\r\n if (process.env[\"CLAUDE_MEMORY_BRIDGE\"] === \"true\") {\r\n fetch(`${REST_URL}/agentmemory/claude-bridge/sync`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n signal: AbortSignal.timeout(30000),\r\n }).catch(() => {});\r\n }\r\n\r\n setTimeout(() => process.exit(0), 1500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;AAEA,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;AAErE,OAAM,GAAG,SAAS,2BAA2B;EAC3C,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU,EAAE,WAAW,CAAC;EACnC,QAAQ,YAAY,QAAQ,IAAM;EACnC,CAAC,CAAC,YAAY,GAAG;AAElB,KAAI,QAAQ,IAAI,6BAA6B,QAAQ;AACnD,QAAM,GAAG,SAAS,6BAA6B;GAC7C,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU,EAAE,eAAe,GAAG,CAAC;GAC1C,QAAQ,YAAY,QAAQ,IAAM;GACnC,CAAC,CAAC,YAAY,GAAG;AAElB,QAAM,GAAG,SAAS,oCAAoC;GACpD,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IAAE,MAAM;IAAO,OAAO;IAAM,CAAC;GAClD,QAAQ,YAAY,QAAQ,KAAO;GACpC,CAAC,CAAC,YAAY,GAAG;;AAGpB,KAAI,QAAQ,IAAI,4BAA4B,OAC1C,OAAM,GAAG,SAAS,kCAAkC;EAClD,QAAQ;EACR,SAAS,aAAa;EACtB,QAAQ,YAAY,QAAQ,IAAM;EACnC,CAAC,CAAC,YAAY,GAAG;AAGpB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,KAAK,CAAC,OAAO;;AAGjD,MAAM"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from "node:child_process";
3
+ import { basename } from "node:path";
4
+ //#region src/hooks/_project.ts
5
+ function resolveProject(cwd) {
6
+ const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
7
+ if (explicit && explicit.trim()) return explicit.trim();
8
+ const dir = cwd && cwd.trim() ? cwd : process.cwd();
9
+ try {
10
+ const top = execSync("git rev-parse --show-toplevel", {
11
+ cwd: dir,
12
+ stdio: [
13
+ "ignore",
14
+ "pipe",
15
+ "ignore"
16
+ ],
17
+ timeout: 500
18
+ }).toString().trim();
19
+ if (top) return basename(top);
20
+ } catch {}
21
+ return basename(dir);
22
+ }
23
+ //#endregion
24
+ //#region src/hooks/session-start.ts
25
+ function isSdkChildContext(payload) {
26
+ if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
27
+ if (!payload || typeof payload !== "object") return false;
28
+ return payload.entrypoint === "sdk-ts";
29
+ }
30
+ const INJECT_CONTEXT = process.env["AGENTMEMORY_INJECT_CONTEXT"] === "true";
31
+ const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
32
+ const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
33
+ const INJECT_TIMEOUT_MS = 1500;
34
+ const REGISTER_TIMEOUT_MS = 800;
35
+ function authHeaders() {
36
+ const h = { "Content-Type": "application/json" };
37
+ if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
38
+ return h;
39
+ }
40
+ async function main() {
41
+ let input = "";
42
+ for await (const chunk of process.stdin) input += chunk;
43
+ let data;
44
+ try {
45
+ data = JSON.parse(input);
46
+ } catch {
47
+ return;
48
+ }
49
+ if (isSdkChildContext(data)) return;
50
+ const sessionId = data.session_id || data.sessionId || `ses_${Date.now().toString(36)}`;
51
+ const cwd = data.cwd || process.cwd();
52
+ const project = resolveProject(data.cwd);
53
+ const url = `${REST_URL}/agentmemory/session/start`;
54
+ const init = {
55
+ method: "POST",
56
+ headers: authHeaders(),
57
+ body: JSON.stringify({
58
+ sessionId,
59
+ project,
60
+ cwd
61
+ })
62
+ };
63
+ if (!INJECT_CONTEXT) {
64
+ fetch(url, {
65
+ ...init,
66
+ signal: AbortSignal.timeout(REGISTER_TIMEOUT_MS)
67
+ }).catch(() => {});
68
+ return;
69
+ }
70
+ try {
71
+ const res = await fetch(url, {
72
+ ...init,
73
+ signal: AbortSignal.timeout(INJECT_TIMEOUT_MS)
74
+ });
75
+ if (res.ok) {
76
+ const result = await res.json();
77
+ if (result.context) process.stdout.write(result.context);
78
+ }
79
+ } catch {}
80
+ }
81
+ main();
82
+ //#endregion
83
+ export {};
84
+
85
+ //# sourceMappingURL=session-start.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/session-start.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\n// Inlined from ./sdk-guard so each hook bundles to a single self-contained\r\n// .mjs (matches the pattern used by every other hook entry in tsdown.config).\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\n// Session-start hook.\r\n//\r\n// Always registers the session for observation tracking (so memories\r\n// captured on PostToolUse get attached to the right session). Only writes\r\n// project context to stdout — which Claude Code prepends to the very first\r\n// turn — when AGENTMEMORY_INJECT_CONTEXT=true. Default off as of 0.8.10\r\n// (#143); see pre-tool-use.ts for the full explanation.\r\nconst INJECT_CONTEXT = process.env[\"AGENTMEMORY_INJECT_CONTEXT\"] === \"true\";\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\n// When the server is unreachable a 5s timeout multiplies hard under\r\n// concurrent fan-out (Slack bots, multi-agent harnesses) and becomes a\r\n// positive feedback loop that OOM-kills iii-engine (#221). Cap tight on\r\n// both paths and skip the await entirely when the response is unused.\r\nconst INJECT_TIMEOUT_MS = 1500;\r\nconst REGISTER_TIMEOUT_MS = 800;\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId =\r\n ((data.session_id || data.sessionId) as string) ||\r\n `ses_${Date.now().toString(36)}`;\r\n const cwd = (data.cwd as string) || process.cwd();\r\n const project = resolveProject(data.cwd as string | undefined);\r\n\r\n const url = `${REST_URL}/agentmemory/session/start`;\r\n const init: RequestInit = {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ sessionId, project, cwd }),\r\n };\r\n\r\n if (!INJECT_CONTEXT) {\r\n // Pure telemetry path: caller never reads the response, so don't\r\n // block on it. AbortSignal.timeout caps the wait the event loop\r\n // gives the pending socket before exit.\r\n fetch(url, {\r\n ...init,\r\n signal: AbortSignal.timeout(REGISTER_TIMEOUT_MS),\r\n }).catch(() => {});\r\n return;\r\n }\r\n\r\n try {\r\n const res = await fetch(url, {\r\n ...init,\r\n signal: AbortSignal.timeout(INJECT_TIMEOUT_MS),\r\n });\r\n if (res.ok) {\r\n const result = (await res.json()) as { context?: string };\r\n if (result.context) {\r\n process.stdout.write(result.context);\r\n }\r\n }\r\n } catch {\r\n // silently fail -- don't block Claude Code startup\r\n }\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACbtB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAU9D,MAAM,iBAAiB,QAAQ,IAAI,kCAAkC;AAErE,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAMpD,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB;AAE5B,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YACF,KAAK,cAAc,KAAK,aAC1B,OAAO,KAAK,KAAK,CAAC,SAAS,GAAG;CAChC,MAAM,MAAO,KAAK,OAAkB,QAAQ,KAAK;CACjD,MAAM,UAAU,eAAe,KAAK,IAA0B;CAE9D,MAAM,MAAM,GAAG,SAAS;CACxB,MAAM,OAAoB;EACxB,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GAAE;GAAW;GAAS;GAAK,CAAC;EAClD;AAED,KAAI,CAAC,gBAAgB;AAInB,QAAM,KAAK;GACT,GAAG;GACH,QAAQ,YAAY,QAAQ,oBAAoB;GACjD,CAAC,CAAC,YAAY,GAAG;AAClB;;AAGF,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,KAAK;GAC3B,GAAG;GACH,QAAQ,YAAY,QAAQ,kBAAkB;GAC/C,CAAC;AACF,MAAI,IAAI,IAAI;GACV,MAAM,SAAU,MAAM,IAAI,MAAM;AAChC,OAAI,OAAO,QACT,SAAQ,OAAO,MAAM,OAAO,QAAQ;;SAGlC;;AAKV,MAAM"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ //#region src/hooks/stop.ts
3
+ function isSdkChildContext(payload) {
4
+ if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
5
+ if (!payload || typeof payload !== "object") return false;
6
+ return payload.entrypoint === "sdk-ts";
7
+ }
8
+ const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
9
+ const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
10
+ function authHeaders() {
11
+ const h = { "Content-Type": "application/json" };
12
+ if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
13
+ return h;
14
+ }
15
+ async function main() {
16
+ let input = "";
17
+ for await (const chunk of process.stdin) input += chunk;
18
+ let data;
19
+ try {
20
+ data = JSON.parse(input);
21
+ } catch {
22
+ return;
23
+ }
24
+ if (isSdkChildContext(data)) return;
25
+ const sessionId = data.session_id || data.sessionId || "unknown";
26
+ fetch(`${REST_URL}/agentmemory/summarize`, {
27
+ method: "POST",
28
+ headers: authHeaders(),
29
+ body: JSON.stringify({ sessionId }),
30
+ signal: AbortSignal.timeout(12e4)
31
+ }).catch(() => {});
32
+ fetch(`${REST_URL}/agentmemory/session/end`, {
33
+ method: "POST",
34
+ headers: authHeaders(),
35
+ body: JSON.stringify({ sessionId }),
36
+ signal: AbortSignal.timeout(5e3)
37
+ }).catch(() => {});
38
+ setTimeout(() => process.exit(0), 1500).unref();
39
+ }
40
+ main();
41
+ //#endregion
42
+ export {};
43
+
44
+ //# sourceMappingURL=stop.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.mjs","names":[],"sources":["../../src/hooks/stop.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\n// Inlined — see src/hooks/sdk-guard.ts for canonical version. Kept local\r\n// per-hook so tsdown does not emit a shared hashed chunk that would churn\r\n// the diff on every rebuild.\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) {\r\n // Do not summarize from inside a Claude Agent SDK child session;\r\n // would re-enter agent-sdk provider and loop (see sdk-guard.ts).\r\n return;\r\n }\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n\r\n fetch(`${REST_URL}/agentmemory/summarize`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ sessionId }),\r\n signal: AbortSignal.timeout(120000),\r\n }).catch(() => {});\r\n\r\n fetch(`${REST_URL}/agentmemory/session/end`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({ sessionId }),\r\n signal: AbortSignal.timeout(5000),\r\n }).catch(() => {});\r\n\r\n setTimeout(() => process.exit(0), 1500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;AAKA,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAGzB;CAGF,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;AAErE,OAAM,GAAG,SAAS,yBAAyB;EACzC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU,EAAE,WAAW,CAAC;EACnC,QAAQ,YAAY,QAAQ,KAAO;EACpC,CAAC,CAAC,YAAY,GAAG;AAElB,OAAM,GAAG,SAAS,2BAA2B;EAC3C,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU,EAAE,WAAW,CAAC;EACnC,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAElB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,KAAK,CAAC,OAAO;;AAGjD,MAAM"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from "node:child_process";
3
+ import { basename } from "node:path";
4
+ //#region src/hooks/_project.ts
5
+ function resolveProject(cwd) {
6
+ const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
7
+ if (explicit && explicit.trim()) return explicit.trim();
8
+ const dir = cwd && cwd.trim() ? cwd : process.cwd();
9
+ try {
10
+ const top = execSync("git rev-parse --show-toplevel", {
11
+ cwd: dir,
12
+ stdio: [
13
+ "ignore",
14
+ "pipe",
15
+ "ignore"
16
+ ],
17
+ timeout: 500
18
+ }).toString().trim();
19
+ if (top) return basename(top);
20
+ } catch {}
21
+ return basename(dir);
22
+ }
23
+ //#endregion
24
+ //#region src/hooks/subagent-start.ts
25
+ function isSdkChildContext(payload) {
26
+ if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
27
+ if (!payload || typeof payload !== "object") return false;
28
+ return payload.entrypoint === "sdk-ts";
29
+ }
30
+ const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
31
+ const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
32
+ const TIMEOUT_MS = 800;
33
+ function authHeaders() {
34
+ const h = { "Content-Type": "application/json" };
35
+ if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
36
+ return h;
37
+ }
38
+ async function main() {
39
+ let input = "";
40
+ for await (const chunk of process.stdin) input += chunk;
41
+ let data;
42
+ try {
43
+ data = JSON.parse(input);
44
+ } catch {
45
+ return;
46
+ }
47
+ if (isSdkChildContext(data)) return;
48
+ const sessionId = data.session_id || data.sessionId || "unknown";
49
+ const agentId = data.agent_id || data.agentName;
50
+ const agentType = data.agent_type || data.agentDisplayName || data.agentName;
51
+ fetch(`${REST_URL}/agentmemory/observe`, {
52
+ method: "POST",
53
+ headers: authHeaders(),
54
+ body: JSON.stringify({
55
+ hookType: "subagent_start",
56
+ sessionId,
57
+ project: resolveProject(data.cwd),
58
+ cwd: data.cwd || process.cwd(),
59
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
60
+ data: {
61
+ agent_id: agentId,
62
+ agent_type: agentType
63
+ }
64
+ }),
65
+ signal: AbortSignal.timeout(TIMEOUT_MS)
66
+ }).catch(() => {});
67
+ setTimeout(() => process.exit(0), 500).unref();
68
+ }
69
+ main();
70
+ //#endregion
71
+ export {};
72
+
73
+ //# sourceMappingURL=subagent-start.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-start.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/subagent-start.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\n// Inlined from ./sdk-guard so each hook bundles to a single self-contained\r\n// .mjs (matches the pattern used by every other hook entry in tsdown.config).\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\n// Passive telemetry only — nothing reads the response, so the previous\r\n// `await` was pure latency. Tightened from 2000ms to a defensive cap so a\r\n// slow/unreachable server can't stack onto every concurrent subagent\r\n// startup (#221).\r\nconst TIMEOUT_MS = 800;\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n const agentId = data.agent_id || data.agentName;\r\n const agentType = data.agent_type || data.agentDisplayName || data.agentName;\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"subagent_start\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: {\r\n agent_id: agentId,\r\n agent_type: agentType,\r\n },\r\n }),\r\n signal: AbortSignal.timeout(TIMEOUT_MS),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACbtB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAMpD,MAAM,aAAa;AAEnB,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;CACrE,MAAM,UAAU,KAAK,YAAY,KAAK;CACtC,MAAM,YAAY,KAAK,cAAc,KAAK,oBAAoB,KAAK;AAEnE,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM;IACJ,UAAU;IACV,YAAY;IACb;GACF,CAAC;EACF,QAAQ,YAAY,QAAQ,WAAW;EACxC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,MAAM"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from "node:child_process";
3
+ import { basename } from "node:path";
4
+ //#region src/hooks/_project.ts
5
+ function resolveProject(cwd) {
6
+ const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
7
+ if (explicit && explicit.trim()) return explicit.trim();
8
+ const dir = cwd && cwd.trim() ? cwd : process.cwd();
9
+ try {
10
+ const top = execSync("git rev-parse --show-toplevel", {
11
+ cwd: dir,
12
+ stdio: [
13
+ "ignore",
14
+ "pipe",
15
+ "ignore"
16
+ ],
17
+ timeout: 500
18
+ }).toString().trim();
19
+ if (top) return basename(top);
20
+ } catch {}
21
+ return basename(dir);
22
+ }
23
+ //#endregion
24
+ //#region src/hooks/subagent-stop.ts
25
+ function isSdkChildContext(payload) {
26
+ if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
27
+ if (!payload || typeof payload !== "object") return false;
28
+ return payload.entrypoint === "sdk-ts";
29
+ }
30
+ const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
31
+ const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
32
+ function authHeaders() {
33
+ const h = { "Content-Type": "application/json" };
34
+ if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
35
+ return h;
36
+ }
37
+ async function main() {
38
+ let input = "";
39
+ for await (const chunk of process.stdin) input += chunk;
40
+ let data;
41
+ try {
42
+ data = JSON.parse(input);
43
+ } catch {
44
+ return;
45
+ }
46
+ if (isSdkChildContext(data)) return;
47
+ const sessionId = data.session_id || data.sessionId || "unknown";
48
+ const agentId = data.agent_id || data.agentName;
49
+ const agentType = data.agent_type || data.agentDisplayName || data.agentName;
50
+ const lastMsg = typeof data.last_assistant_message === "string" ? data.last_assistant_message.slice(0, 4e3) : "";
51
+ fetch(`${REST_URL}/agentmemory/observe`, {
52
+ method: "POST",
53
+ headers: authHeaders(),
54
+ body: JSON.stringify({
55
+ hookType: "subagent_stop",
56
+ sessionId,
57
+ project: resolveProject(data.cwd),
58
+ cwd: data.cwd || process.cwd(),
59
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
60
+ data: {
61
+ agent_id: agentId,
62
+ agent_type: agentType,
63
+ last_message: lastMsg
64
+ }
65
+ }),
66
+ signal: AbortSignal.timeout(2e3)
67
+ }).catch(() => {});
68
+ setTimeout(() => process.exit(0), 500).unref();
69
+ }
70
+ main();
71
+ //#endregion
72
+ export {};
73
+
74
+ //# sourceMappingURL=subagent-stop.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-stop.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/subagent-stop.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = ((data.session_id || data.sessionId) as string) || \"unknown\";\r\n const agentId = data.agent_id || data.agentName;\r\n const agentType = data.agent_type || data.agentDisplayName || data.agentName;\r\n const lastMsg =\r\n typeof data.last_assistant_message === \"string\"\r\n ? data.last_assistant_message.slice(0, 4000)\r\n : \"\";\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"subagent_stop\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: {\r\n agent_id: agentId,\r\n agent_type: agentType,\r\n last_message: lastMsg,\r\n },\r\n }),\r\n signal: AbortSignal.timeout(2000),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAc,KAAK,cAAc,KAAK,aAAyB;CACrE,MAAM,UAAU,KAAK,YAAY,KAAK;CACtC,MAAM,YAAY,KAAK,cAAc,KAAK,oBAAoB,KAAK;CACnE,MAAM,UACJ,OAAO,KAAK,2BAA2B,WACnC,KAAK,uBAAuB,MAAM,GAAG,IAAK,GAC1C;AAEN,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM;IACJ,UAAU;IACV,YAAY;IACZ,cAAc;IACf;GACF,CAAC;EACF,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,MAAM"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from "node:child_process";
3
+ import { basename } from "node:path";
4
+ //#region src/hooks/_project.ts
5
+ function resolveProject(cwd) {
6
+ const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
7
+ if (explicit && explicit.trim()) return explicit.trim();
8
+ const dir = cwd && cwd.trim() ? cwd : process.cwd();
9
+ try {
10
+ const top = execSync("git rev-parse --show-toplevel", {
11
+ cwd: dir,
12
+ stdio: [
13
+ "ignore",
14
+ "pipe",
15
+ "ignore"
16
+ ],
17
+ timeout: 500
18
+ }).toString().trim();
19
+ if (top) return basename(top);
20
+ } catch {}
21
+ return basename(dir);
22
+ }
23
+ //#endregion
24
+ //#region src/hooks/task-completed.ts
25
+ function isSdkChildContext(payload) {
26
+ if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
27
+ if (!payload || typeof payload !== "object") return false;
28
+ return payload.entrypoint === "sdk-ts";
29
+ }
30
+ const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
31
+ const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
32
+ function authHeaders() {
33
+ const h = { "Content-Type": "application/json" };
34
+ if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;
35
+ return h;
36
+ }
37
+ async function main() {
38
+ let input = "";
39
+ for await (const chunk of process.stdin) input += chunk;
40
+ let data;
41
+ try {
42
+ data = JSON.parse(input);
43
+ } catch {
44
+ return;
45
+ }
46
+ if (isSdkChildContext(data)) return;
47
+ const sessionId = data.session_id || "unknown";
48
+ fetch(`${REST_URL}/agentmemory/observe`, {
49
+ method: "POST",
50
+ headers: authHeaders(),
51
+ body: JSON.stringify({
52
+ hookType: "task_completed",
53
+ sessionId,
54
+ project: resolveProject(data.cwd),
55
+ cwd: data.cwd || process.cwd(),
56
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
57
+ data: {
58
+ task_id: data.task_id,
59
+ task_subject: data.task_subject,
60
+ task_description: typeof data.task_description === "string" ? data.task_description.slice(0, 2e3) : "",
61
+ teammate_name: data.teammate_name,
62
+ team_name: data.team_name
63
+ }
64
+ }),
65
+ signal: AbortSignal.timeout(2e3)
66
+ }).catch(() => {});
67
+ setTimeout(() => process.exit(0), 500).unref();
68
+ }
69
+ main();
70
+ //#endregion
71
+ export {};
72
+
73
+ //# sourceMappingURL=task-completed.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-completed.mjs","names":[],"sources":["../../src/hooks/_project.ts","../../src/hooks/task-completed.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\r\nimport { basename } from \"node:path\";\r\n\r\n// Resolution order: AGENTMEMORY_PROJECT_NAME env → git toplevel basename → cwd basename.\r\nexport function resolveProject(cwd?: string): string {\r\n const explicit = process.env[\"AGENTMEMORY_PROJECT_NAME\"];\r\n if (explicit && explicit.trim()) return explicit.trim();\r\n const dir = cwd && cwd.trim() ? cwd : process.cwd();\r\n try {\r\n const top = execSync(\"git rev-parse --show-toplevel\", {\r\n cwd: dir,\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n timeout: 500,\r\n })\r\n .toString()\r\n .trim();\r\n if (top) return basename(top);\r\n } catch {}\r\n return basename(dir);\r\n}\r\n","#!/usr/bin/env node\r\nimport { resolveProject } from \"./_project.js\";\r\n\r\nfunction isSdkChildContext(payload: unknown): boolean {\r\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\r\n if (!payload || typeof payload !== \"object\") return false;\r\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\r\n}\r\n\r\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\r\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\r\n\r\nfunction authHeaders(): Record<string, string> {\r\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\r\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\r\n return h;\r\n}\r\n\r\nasync function main() {\r\n let input = \"\";\r\n for await (const chunk of process.stdin) {\r\n input += chunk;\r\n }\r\n\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(input);\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isSdkChildContext(data)) return;\r\n\r\n const sessionId = (data.session_id as string) || \"unknown\";\r\n\r\n fetch(`${REST_URL}/agentmemory/observe`, {\r\n method: \"POST\",\r\n headers: authHeaders(),\r\n body: JSON.stringify({\r\n hookType: \"task_completed\",\r\n sessionId,\r\n project: resolveProject(data.cwd as string | undefined),\r\n cwd: (data.cwd as string | undefined) || process.cwd(),\r\n timestamp: new Date().toISOString(),\r\n data: {\r\n task_id: data.task_id,\r\n task_subject: data.task_subject,\r\n task_description: typeof data.task_description === \"string\"\r\n ? data.task_description.slice(0, 2000)\r\n : \"\",\r\n teammate_name: data.teammate_name,\r\n team_name: data.team_name,\r\n },\r\n }),\r\n signal: AbortSignal.timeout(2000),\r\n }).catch(() => {});\r\n setTimeout(() => process.exit(0), 500).unref();\r\n}\r\n\r\nmain();\r\n"],"mappings":";;;;AAIA,SAAgB,eAAe,KAAsB;CACnD,MAAM,WAAW,QAAQ,IAAI;AAC7B,KAAI,YAAY,SAAS,MAAM,CAAE,QAAO,SAAS,MAAM;CACvD,MAAM,MAAM,OAAO,IAAI,MAAM,GAAG,MAAM,QAAQ,KAAK;AACnD,KAAI;EACF,MAAM,MAAM,SAAS,iCAAiC;GACpD,KAAK;GACL,OAAO;IAAC;IAAU;IAAQ;IAAS;GACnC,SAAS;GACV,CAAC,CACC,UAAU,CACV,MAAM;AACT,MAAI,IAAK,QAAO,SAAS,IAAI;SACvB;AACR,QAAO,SAAS,IAAI;;;;ACftB,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;CAE7B,MAAM,YAAa,KAAK,cAAyB;AAEjD,OAAM,GAAG,SAAS,uBAAuB;EACvC,QAAQ;EACR,SAAS,aAAa;EACtB,MAAM,KAAK,UAAU;GACnB,UAAU;GACV;GACA,SAAS,eAAe,KAAK,IAA0B;GACvD,KAAM,KAAK,OAA8B,QAAQ,KAAK;GACtD,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,MAAM;IACJ,SAAS,KAAK;IACd,cAAc,KAAK;IACnB,kBAAkB,OAAO,KAAK,qBAAqB,WAC/C,KAAK,iBAAiB,MAAM,GAAG,IAAK,GACpC;IACJ,eAAe,KAAK;IACpB,WAAW,KAAK;IACjB;GACF,CAAC;EACF,QAAQ,YAAY,QAAQ,IAAK;EAClC,CAAC,CAAC,YAAY,GAAG;AAClB,kBAAiB,QAAQ,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO;;AAGhD,MAAM"}
@@ -0,0 +1,38 @@
1
+ # Troubleshooting agentmemory skills
2
+
3
+ Shared recovery steps for all user-invocable agentmemory skills. Each skill's
4
+ Troubleshooting section points here instead of duplicating the block.
5
+
6
+ ## "MCP tool not available"
7
+
8
+ If a `memory_*` MCP tool does not appear, the stdio MCP shim never started.
9
+ Walk these in order:
10
+
11
+ 1. Run `/plugin list` in the host and confirm `agentmemory` shows as enabled.
12
+ 2. Restart the host. The plugin's `.mcp.json` is only read on startup, so a
13
+ freshly installed or re-enabled plugin will not register tools mid-session.
14
+ 3. Check `/mcp` and confirm the `agentmemory` server shows a live connection.
15
+
16
+ ## REST fallback
17
+
18
+ When the MCP tools stay unavailable but the daemon is running, call the REST
19
+ API directly:
20
+
21
+ 1. Set `AGENTMEMORY_URL` to the daemon base URL (default `http://localhost:3111`).
22
+ 2. Add `Authorization: Bearer $AGENTMEMORY_SECRET` ONLY when `AGENTMEMORY_SECRET`
23
+ is set. The default localhost daemon is open and rejects a stray header.
24
+
25
+ Endpoint map by skill:
26
+
27
+ | Skill | REST call |
28
+ | --------------- | --------------------------------------------------------------- |
29
+ | remember | `POST /agentmemory/remember` |
30
+ | recall | `POST /agentmemory/smart-search` |
31
+ | recap | `GET /agentmemory/sessions` + `POST /agentmemory/smart-search` |
32
+ | handoff | `GET /agentmemory/sessions` + `POST /agentmemory/smart-search` |
33
+ | session-history | `GET /agentmemory/sessions` |
34
+ | commit-context | `GET /agentmemory/session/by-commit?sha=<sha>` |
35
+ | commit-history | `GET /agentmemory/commits` (URL-encode every query param) |
36
+
37
+ The daemon reads `.mcp.json` on startup only, so any port or auth change needs a
38
+ restart before either transport sees it.
@@ -0,0 +1,28 @@
1
+ # agentmemory connect adapters reference
2
+
3
+ Generated from `src/cli/connect/index.ts`. Do not edit the block below by hand; run `npm run skills:gen` after adding or removing an adapter.
4
+
5
+ <!-- AUTOGEN:agents START - generated by scripts/skills/generate.ts, do not edit by hand -->
6
+ `agentmemory connect <agent>` wires the memory server into a host agent. 18 adapters:
7
+
8
+ | Agent | Name | Protocol |
9
+ | --- | --- | --- |
10
+ | Antigravity | `antigravity` | Using MCP via mcp_config.json. Antigravity replaces Gemini CLI (sunset 2026-06-18). |
11
+ | Claude Code | `claude-code` | Using MCP. Hooks are also available, see https://github.com/rohitg00/agentmemory#claude-code-one-block-paste-it. |
12
+ | Cline | `cline` | Using MCP via ~/.cline/mcp.json (CLI). VS Code users: add the same block via Cline Settings → MCP Servers → Edit JSON. |
13
+ | Codex CLI | `codex` | Using MCP. Hooks ship via the Codex plugin; on Codex Desktop, also pass --with-hooks to install the global hooks.json workaround for openai/codex#16430. |
14
+ | Continue | `continue` | Using MCP via ~/.continue/config.yaml (preferred) or config.json (legacy, only when no yaml). |
15
+ | GitHub Copilot CLI | `copilot-cli` | Using MCP. Install the plugin too for full hooks/skills coverage. |
16
+ | Cursor | `cursor` | Using MCP (the only protocol Cursor speaks). Memory bridge runs at :3111 underneath. |
17
+ | Droid (Factory.ai) | `droid` | Using MCP via ~/.factory/mcp.json. The `/mcp` slash command inside droid lists configured servers. |
18
+ | Gemini CLI | `gemini-cli` | Using MCP (the only protocol Gemini CLI speaks). Memory bridge runs at :3111 underneath. |
19
+ | Hermes Agent | `hermes` | Using MCP. Hooks are also available, see https://github.com/rohitg00/agentmemory/tree/main/integrations/hermes. |
20
+ | Kiro | `kiro` | Using MCP via ~/.kiro/settings/mcp.json (user-level). Workspace overrides live in .kiro/settings/mcp.json. |
21
+ | OpenClaw | `openclaw` | Using MCP. Hooks are also available, see https://github.com/rohitg00/agentmemory/tree/main/integrations/openclaw. |
22
+ | OpenCode | `opencode` | Using MCP via ~/.config/opencode/opencode.json (top-level `mcp` key). For full auto-capture, also install the bundled plugin in plugin/opencode/. |
23
+ | OpenHuman | `openhuman` | Using native hooks (REST API at :3111). MCP not required. |
24
+ | pi | `pi` | Using native hooks (REST API at :3111). MCP not required. |
25
+ | Qwen Code | `qwen` | Using MCP via ~/.qwen/settings.json. Qwen Code's hook system can also be wired separately, see docs. |
26
+ | Warp | `warp` | Using MCP via ~/.warp/.mcp.json. Skills auto-discover from .claude/skills/ if the Claude Code plugin is also installed. |
27
+ | Zed | `zed` | Using MCP via ~/.config/zed/settings.json (key: context_servers). |
28
+ <!-- AUTOGEN:agents END -->
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: agentmemory-agents
3
+ description: How agentmemory wires into host coding agents via the connect command. Use when installing agentmemory into a specific agent, when asked which agents are supported, or when a connect adapter writes the wrong config path.
4
+ user-invocable: false
5
+ ---
6
+
7
+ `agentmemory connect <agent>` merges the memory server into a host agent's config and preserves any existing servers. REST is the underlying protocol; for MCP-only hosts the adapter wires the stdio MCP bridge.
8
+
9
+ ## Quick start
10
+
11
+ ```bash
12
+ agentmemory connect claude-code # or cursor, codex, gemini-cli, ...
13
+ ```
14
+
15
+ After wiring, restart the host or run its MCP reload (for example `/mcp` in Claude Code) so it picks up the server. Then confirm the agent lists agentmemory's tools.
16
+
17
+ ## Workflow
18
+
19
+ 1. Detect the calling agent. If unknown, default to `claude-code`.
20
+ 2. Run `agentmemory connect <name>` using a name from the table in REFERENCE.md.
21
+ 3. Verify: the host should show the full tool set with a server running. Only 7 tools means the MCP shim could not reach a server (see ../_shared/TROUBLESHOOTING.md).
22
+
23
+ ## Notes
24
+
25
+ - The action skills (remember, recall, and the rest) are installed separately with `npx skills add rohitg00/agentmemory`. `connect` makes tools available; skills teach the agent when to use them.
26
+ - Windows: use WSL2. Native Windows runs the server but `connect` is not supported there.
27
+
28
+ ## See also
29
+
30
+ - agentmemory-mcp-tools, agentmemory-rest-api, agentmemory-hooks.
31
+
32
+ ## Reference
33
+
34
+ The full adapter list with display names and protocol notes lives in REFERENCE.md, generated from `src/cli/connect/`.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: agentmemory-architecture
3
+ description: How agentmemory is built, the iii engine primitives it runs on, its storage model, ports, and the viewer. Use when reasoning about how memory is stored or retrieved end to end, when extending the system, or when answering how agentmemory works under the hood.
4
+ user-invocable: false
5
+ ---
6
+
7
+ agentmemory is a memory server for coding agents. It runs locally, captures observations, indexes them for hybrid retrieval, and serves them back over REST and MCP. It is built on the iii engine.
8
+
9
+ ## iii primitives
10
+
11
+ Everything is a function, a trigger, or worker state on the iii engine. There is no separate plugin system; the worker registers functions (`mem::*`) and HTTP triggers (`api::*`) and the engine routes calls. agentmemory does not bypass iii; new capability is a new function plus a trigger.
12
+
13
+ ## Retrieval model
14
+
15
+ Recall is hybrid: BM25 keyword search plus vector similarity plus graph expansion over linked concepts. The default install needs no API key because embeddings run on-device and BM25 needs none. An LLM provider only adds richer summaries and auto-injection, both opt-in.
16
+
17
+ ## Storage and lifecycle
18
+
19
+ Memories carry content, concepts, files, importance, and timestamps, grouped into sessions and optionally linked to commits. A lifecycle of capture, compress, consolidate, and forget keeps the store useful over time rather than letting it grow unbounded.
20
+
21
+ ## Ports
22
+
23
+ REST is the anchor at 3111. Streams = N+1 (3112), viewer = N+2 (3113), engine = N+46023 (49134). `--instance N` shifts the whole block by N*100.
24
+
25
+ ## Viewer
26
+
27
+ A real-time web viewer at `http://localhost:3113` shows memory building as sessions run. Useful for demos and for confirming capture is working.
28
+
29
+ ## See also
30
+
31
+ - agentmemory-mcp-tools and agentmemory-rest-api for the surfaces.
32
+ - agentmemory-hooks for automatic capture.
33
+ - agentmemory-config for ports and feature flags.