@nogataka/claw-memory 0.1.1 → 0.1.3

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.
@@ -3,14 +3,14 @@
3
3
  "owner": { "name": "nogataka" },
4
4
  "metadata": {
5
5
  "description": "claw-memory: local semantic memory + raw-log search for Claude Code",
6
- "version": "0.1.1"
6
+ "version": "0.1.3"
7
7
  },
8
8
  "plugins": [
9
9
  {
10
10
  "name": "claw-memory",
11
11
  "source": "./",
12
12
  "description": "Local semantic memory: auto-distill, recall injection, and raw Claude Code + Codex transcript search.",
13
- "version": "0.1.1"
13
+ "version": "0.1.3"
14
14
  }
15
15
  ]
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claw-memory",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Local semantic memory for Claude Code: auto-distills sessions, injects relevant past context, and searches raw Claude Code + Codex transcripts. sqlite-vec + local embeddings, no daemon, no Python.",
5
5
  "author": { "name": "nogataka" },
6
6
  "repository": "https://github.com/nogataka/claw-memory",
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "claw-memory",
3
+ "version": "0.1.2",
4
+ "description": "Local semantic memory for Codex: auto-distills sessions, injects relevant past context via hooks, and searches raw Codex + Claude Code transcripts. sqlite-vec + local embeddings, no daemon, no Python.",
5
+ "skills": "./skills/",
6
+ "mcpServers": "./.mcp.json",
7
+ "hooks": "./hooks/hooks.codex.json",
8
+ "interface": {
9
+ "displayName": "claw-memory",
10
+ "shortDescription": "Local semantic memory + transcript search for Codex",
11
+ "longDescription": "Auto-distills finished sessions into a local sqlite-vec store, injects relevant preferences and past-conversation context at session start via hooks, and exposes memory_recall / memory_search / memory_search_logs MCP tools. Runs fully local with Xenova e5 embeddings — no daemon, no Python.",
12
+ "developerName": "nogataka",
13
+ "category": "productivity",
14
+ "capabilities": ["memory", "context", "search"]
15
+ }
16
+ }
package/README.ja.md CHANGED
@@ -132,9 +132,27 @@ Claude Code を再起動してください。次が自動登録されます。
132
132
  > **プラグインを使わない場合**: `claw-memory install --claude-code` で MCP サーバーと
133
133
  > フックを `~/.claude/settings.json` にマージできます(冪等・バックアップ付き)。
134
134
 
135
- ### 手順 2b — Codex(インストーラ)
135
+ ### 手順 2b — Codex(プラグイン)
136
136
 
137
- Codex には第三者プラグインのマーケットプレイスが無いため、インストーラで登録します。
137
+ Codex は Claude Code と同じプラグイン形式に対応しています。claw-memory は
138
+ `.codex-plugin/plugin.json` を同梱しているため、Codex プラグインとして導入すると
139
+ MCP サーバーと**ライフサイクル hooks の両方**が登録され、Claude Code と同等になります。
140
+
141
+ ```
142
+ codex
143
+ /plugins
144
+ ```
145
+
146
+ プラグインは Codex が互換提供する `${CLAUDE_PLUGIN_ROOT}` を介して次を登録します。
147
+
148
+ - `claw-memory` MCP サーバー(`.mcp.json`)
149
+ - `SessionStart` / `UserPromptSubmit` → **recall 自動注入**(memory ブロックを developer context として)
150
+ - `Stop` → 最近の Codex セッションの**自動 distill**(watermark 重複回避・非同期)
151
+ - `memory-recall` skill
152
+
153
+ ### 手順 2b(代替)— Codex(インストーラ/マーケット非経由)
154
+
155
+ マーケットプレイスではなく npm から導入する場合は CLI で登録します。
138
156
 
139
157
  ```bash
140
158
  claw-memory install --codex
@@ -143,11 +161,12 @@ claw-memory install --codex
143
161
  これは冪等に次を行います。
144
162
 
145
163
  - `~/.codex/config.toml` に `[mcp_servers.claw-memory]` を追記(`config.toml.bak` にバックアップ)
164
+ - `~/.codex/hooks.json` に recall/distill hooks をマージ(バックアップあり・既存 hook は保全)
146
165
  - `memory-recall` skill を配置
147
166
  - `AGENTS.md` に「セッション冒頭で `memory_recall` を呼ぶ」指示を追記
148
167
 
149
- Codex を再起動してください。**Codex 側の自動 distill は手動のみ**(Stop フック相当が無い
150
- ため)。定期的に自分で実行します。
168
+ Codex を再起動してください。**recall 注入・自動 distill hooks で自動実行**され、手動操作は不要です。
169
+ 必要に応じて手動バックフィルも可能です。
151
170
 
152
171
  ```bash
153
172
  claw-memory distill-codex --recent # 最近の Codex セッションを蒸留(watermark で重複回避)
@@ -262,6 +281,14 @@ claw-memory uninstall [--codex | --claude-code]
262
281
  claw-memory ui --open # http://localhost:4319
263
282
  ```
264
283
 
284
+ **Claude Code プラグインだけ**で導入した場合(グローバル npm 未導入)、`claw-memory`
285
+ コマンドは `PATH` に乗りません。その場合は `npx` 経由で起動してください。
286
+
287
+ ```bash
288
+ npx @nogataka/claw-memory ui --open # http://localhost:4319
289
+ npx @nogataka/claw-memory ui --port 5000 --open
290
+ ```
291
+
265
292
  読み取り専用。プロジェクト・要約・会話チャンク(type / concepts / files 付き)・好みを
266
293
  閲覧でき、**🔎 ログ検索** で Claude Code + Codex の生ログを全文検索できます。開いている間
267
294
  は SSE で自動更新。それ以外はバックグラウンドで何も動きません — 確認したい時だけ起動して
@@ -272,7 +299,7 @@ claw-memory ui --open # http://localhost:4319
272
299
  ## アンインストール
273
300
 
274
301
  ```bash
275
- claw-memory uninstall --codex # config.toml ブロック + skill + AGENTS 記述を除去
302
+ claw-memory uninstall --codex # config.toml ブロック + hooks + skill + AGENTS 記述を除去
276
303
  claw-memory uninstall --claude-code # settings.json から mcp + フックを除去
277
304
  # Claude Code プラグイン: /plugin uninstall claw-memory
278
305
  npm uninstall -g @nogataka/claw-memory
package/README.md CHANGED
@@ -137,9 +137,27 @@ No manual config. To verify, run `/mcp` and look for `claw-memory`.
137
137
  > **Not using the plugin?** Run `claw-memory install --claude-code` to merge the MCP
138
138
  > server and hooks into `~/.claude/settings.json` (idempotent, backs up the file).
139
139
 
140
- ### Step 2b — Codex (installer)
140
+ ### Step 2b — Codex (plugin)
141
141
 
142
- Codex has no third-party plugin marketplace, so register via the installer:
142
+ Codex supports the same plugin format as Claude Code. claw-memory ships a
143
+ `.codex-plugin/plugin.json` manifest, so installing it as a Codex plugin wires up
144
+ the MCP server **and** the lifecycle hooks — full parity with Claude Code:
145
+
146
+ ```
147
+ codex
148
+ /plugins
149
+ ```
150
+
151
+ The plugin registers, via Codex's `${CLAUDE_PLUGIN_ROOT}` (provided for compatibility):
152
+
153
+ - the `claw-memory` MCP server (`.mcp.json`),
154
+ - `SessionStart` / `UserPromptSubmit` → **auto recall injection** (memory block as developer context),
155
+ - `Stop` → **auto distill** of recent Codex sessions (watermark-deduped, async), and
156
+ - the `memory-recall` skill.
157
+
158
+ ### Step 2b (alt) — Codex (installer, no marketplace)
159
+
160
+ If you install from npm instead of the plugin marketplace, register via the CLI:
143
161
 
144
162
  ```bash
145
163
  claw-memory install --codex
@@ -148,11 +166,12 @@ claw-memory install --codex
148
166
  This idempotently:
149
167
 
150
168
  - adds `[mcp_servers.claw-memory]` to `~/.codex/config.toml` (backed up to `config.toml.bak`),
169
+ - merges recall/distill hooks into `~/.codex/hooks.json` (backed up; your own hooks are preserved),
151
170
  - installs the `memory-recall` skill, and
152
171
  - appends an `AGENTS.md` instruction telling the agent to call `memory_recall` at session start.
153
172
 
154
- Restart Codex. **Auto-distill is manual on Codex** (no equivalent of the Stop hook) — run
155
- it yourself periodically:
173
+ Restart Codex. **Recall injection and auto-distill now run via hooks** no manual step needed.
174
+ You can still backfill on demand:
156
175
 
157
176
  ```bash
158
177
  claw-memory distill-codex --recent # distill recent Codex sessions (watermark-deduped)
@@ -267,6 +286,14 @@ session ends (Stop hook / distill-codex) session starts (SessionStart hook / m
267
286
  claw-memory ui --open # http://localhost:4319
268
287
  ```
269
288
 
289
+ If you installed via the **Claude Code plugin only** (no global npm install), the
290
+ `claw-memory` binary isn't on your `PATH`. Run the viewer through `npx` instead:
291
+
292
+ ```bash
293
+ npx @nogataka/claw-memory ui --open # http://localhost:4319
294
+ npx @nogataka/claw-memory ui --port 5000 --open
295
+ ```
296
+
270
297
  Read-only. Browse projects, session summaries, conversation chunks (with type /
271
298
  concepts / files), and preferences; toggle **🔎 ログ検索** to full-text search raw
272
299
  Claude Code + Codex transcripts. Live-updates via SSE while open. Nothing runs in the
@@ -277,7 +304,7 @@ background otherwise — start it only when you want to inspect.
277
304
  ## Uninstall
278
305
 
279
306
  ```bash
280
- claw-memory uninstall --codex # remove config.toml block + skill + AGENTS note
307
+ claw-memory uninstall --codex # remove config.toml block + hooks + skill + AGENTS note
281
308
  claw-memory uninstall --claude-code # remove mcp + hooks from settings.json
282
309
  # Claude Code plugin: /plugin uninstall claw-memory
283
310
  npm uninstall -g @nogataka/claw-memory
package/dist/cli.js CHANGED
@@ -88,7 +88,7 @@ async function main() {
88
88
  if (target === "codex") {
89
89
  const { installCodex } = await import("./core/installer/codex.js");
90
90
  console.log("claw-memory installed for Codex:\n " + installCodex().join("\n "));
91
- console.log("\n注意: Codex を再起動してください。自動 distill は手動 (`claw-memory distill-codex --recent`)。");
91
+ console.log("\n注意: Codex を再起動してください。recall 注入・自動 distill hooks で自動実行されます。");
92
92
  }
93
93
  else {
94
94
  const { installClaude } = await import("./core/installer/claude.js");
@@ -13,7 +13,17 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, rmSyn
13
13
  const CODEX_DIR = join(homedir(), ".codex");
14
14
  const CONFIG = join(CODEX_DIR, "config.toml");
15
15
  const AGENTS = join(CODEX_DIR, "AGENTS.md");
16
+ const HOOKS = join(CODEX_DIR, "hooks.json");
16
17
  const SKILL_DIR = join(CODEX_DIR, "skills", "memory-recall");
18
+ // Codex lifecycle hooks for the manual (non-plugin) install path. Mirrors the
19
+ // Claude Code hook wiring: recall on session start / prompt, distill on stop.
20
+ // Codex Stop carries no Claude-format transcript, so distill scans recent Codex
21
+ // session files (watermark-guarded) instead of a single transcript_path.
22
+ const HOOK_EVENTS = [
23
+ ["SessionStart", "hook recall", false],
24
+ ["UserPromptSubmit", "hook recall", false],
25
+ ["Stop", "distill-codex --limit 5", true],
26
+ ];
17
27
  const BEGIN = "# >>> claw-memory >>>";
18
28
  const END = "# <<< claw-memory <<<";
19
29
  const A_BEGIN = "<!-- >>> claw-memory >>> -->";
@@ -24,18 +34,73 @@ function tomlStr(s) {
24
34
  }
25
35
  /** Prefer a globally installed `claw-memory`; otherwise run via npx. */
26
36
  function resolveCommand() {
37
+ const bin = resolveBin();
38
+ return bin
39
+ ? { command: bin, args: ["mcp"] }
40
+ : { command: "npx", args: ["-y", "@nogataka/claw-memory@latest", "mcp"] };
41
+ }
42
+ /** Absolute path to a globally installed `claw-memory`, or null. */
43
+ function resolveBin() {
27
44
  try {
28
45
  const found = execFileSync("command", ["-v", "claw-memory"], {
29
46
  shell: "/bin/bash",
30
47
  encoding: "utf-8",
31
- }).trim();
32
- if (found)
33
- return { command: found.split("\n")[0], args: ["mcp"] };
48
+ }).trim().split("\n")[0];
49
+ return found || null;
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ /** How to invoke the CLI from a hook command line. */
56
+ function cliInvoker() {
57
+ return resolveBin() ?? "npx -y @nogataka/claw-memory@latest";
58
+ }
59
+ function readHooks() {
60
+ if (!existsSync(HOOKS))
61
+ return {};
62
+ try {
63
+ return JSON.parse(readFileSync(HOOKS, "utf-8"));
34
64
  }
35
65
  catch {
36
- // not on PATH
66
+ return {};
37
67
  }
38
- return { command: "npx", args: ["-y", "@nogataka/claw-memory@latest", "mcp"] };
68
+ }
69
+ /** A hook command is ours if it runs the claw-memory CLI recall/distill subcommand. */
70
+ function isOurHook(cmd) {
71
+ return cmd.includes("claw-memory") && (cmd.includes("hook recall") || cmd.includes("distill-codex"));
72
+ }
73
+ /** Merge our recall/distill hooks into ~/.codex/hooks.json, replacing stale ones. */
74
+ function installHooks() {
75
+ const cli = cliInvoker();
76
+ const f = readHooks();
77
+ f.hooks = f.hooks ?? {};
78
+ for (const [event, sub, isAsync] of HOOK_EVENTS) {
79
+ const list = (f.hooks[event] ?? []).filter((g) => !g.hooks?.some((h) => isOurHook(h.command)));
80
+ list.push({ hooks: [{ type: "command", command: `${cli} ${sub}`, async: isAsync }] });
81
+ f.hooks[event] = list;
82
+ }
83
+ if (existsSync(HOOKS))
84
+ copyFileSync(HOOKS, HOOKS + ".bak");
85
+ writeFileSync(HOOKS, JSON.stringify(f, null, 2) + "\n");
86
+ }
87
+ /** Remove our hooks from ~/.codex/hooks.json, preserving the user's own. */
88
+ function removeHooks() {
89
+ if (!existsSync(HOOKS))
90
+ return false;
91
+ const f = readHooks();
92
+ if (!f.hooks)
93
+ return false;
94
+ for (const event of Object.keys(f.hooks)) {
95
+ f.hooks[event] = f.hooks[event]
96
+ .map((g) => ({ ...g, hooks: (g.hooks ?? []).filter((h) => !isOurHook(h.command)) }))
97
+ .filter((g) => g.hooks.length > 0);
98
+ if (f.hooks[event].length === 0)
99
+ delete f.hooks[event];
100
+ }
101
+ copyFileSync(HOOKS, HOOKS + ".bak");
102
+ writeFileSync(HOOKS, JSON.stringify(f, null, 2) + "\n");
103
+ return true;
39
104
  }
40
105
  /** Insert or replace the marker-delimited block in `content`. */
41
106
  function upsertBlock(content, begin, end, block) {
@@ -98,6 +163,9 @@ export function installCodex() {
98
163
  const agentsPrev = existsSync(AGENTS) ? readFileSync(AGENTS, "utf-8") : "";
99
164
  writeFileSync(AGENTS, upsertBlock(agentsPrev, A_BEGIN, A_END, agentsBlock));
100
165
  done.push("AGENTS.md: recall instruction");
166
+ // 4) lifecycle hooks: auto recall (SessionStart/UserPromptSubmit) + auto distill (Stop)
167
+ installHooks();
168
+ done.push("hooks.json: SessionStart/UserPromptSubmit→recall, Stop→distill-codex");
101
169
  return done;
102
170
  }
103
171
  export function uninstallCodex() {
@@ -111,6 +179,9 @@ export function uninstallCodex() {
111
179
  writeFileSync(AGENTS, removeBlock(readFileSync(AGENTS, "utf-8"), A_BEGIN, A_END));
112
180
  done.push("AGENTS.md: removed claw-memory block");
113
181
  }
182
+ if (removeHooks()) {
183
+ done.push("hooks.json: removed claw-memory hooks");
184
+ }
114
185
  try {
115
186
  rmSync(SKILL_DIR, { recursive: true, force: true });
116
187
  done.push("skill: removed");
package/dist/core/llm.js CHANGED
@@ -63,6 +63,11 @@ async function completeAgentSdk(prompt, model) {
63
63
  maxTurns: 1,
64
64
  allowedTools: [],
65
65
  permissionMode: "bypassPermissions",
66
+ // SDK isolation: do NOT load ~/.claude or project settings into the
67
+ // distillation sub-session. Otherwise the user's own hooks (e.g. a Stop
68
+ // hook that plays a sound) and claw-memory's own hooks fire on every
69
+ // spawned sub-session — a beep storm and needless recursion.
70
+ settingSources: [],
66
71
  env: buildFullSdkEnv(),
67
72
  },
68
73
  });
@@ -0,0 +1,37 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "\"$CLAUDE_PLUGIN_ROOT/hooks/run-hook.cmd\" claw-hook.sh hook recall",
9
+ "async": false
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "UserPromptSubmit": [
15
+ {
16
+ "hooks": [
17
+ {
18
+ "type": "command",
19
+ "command": "\"$CLAUDE_PLUGIN_ROOT/hooks/run-hook.cmd\" claw-hook.sh hook recall",
20
+ "async": false
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "Stop": [
26
+ {
27
+ "hooks": [
28
+ {
29
+ "type": "command",
30
+ "command": "\"$CLAUDE_PLUGIN_ROOT/hooks/run-hook.cmd\" claw-hook.sh distill-codex --limit 5",
31
+ "async": true
32
+ }
33
+ ]
34
+ }
35
+ ]
36
+ }
37
+ }
package/hooks/hooks.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" claw-hook.sh hook recall",
8
+ "command": "\"$CLAUDE_PLUGIN_ROOT/hooks/run-hook.cmd\" claw-hook.sh hook recall",
9
9
  "async": false
10
10
  }
11
11
  ]
@@ -16,7 +16,7 @@
16
16
  "hooks": [
17
17
  {
18
18
  "type": "command",
19
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" claw-hook.sh hook recall",
19
+ "command": "\"$CLAUDE_PLUGIN_ROOT/hooks/run-hook.cmd\" claw-hook.sh hook recall",
20
20
  "async": false
21
21
  }
22
22
  ]
@@ -27,7 +27,7 @@
27
27
  "hooks": [
28
28
  {
29
29
  "type": "command",
30
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.cmd\" claw-hook.sh hook distill",
30
+ "command": "\"$CLAUDE_PLUGIN_ROOT/hooks/run-hook.cmd\" claw-hook.sh hook distill",
31
31
  "async": true
32
32
  }
33
33
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nogataka/claw-memory",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "Independent, in-process semantic memory MCP server (sqlite-vec + local Xenova e5) with a lightweight web viewer. No daemon, no Python. Installable as a Claude Code plugin and a Codex MCP server.",
6
6
  "license": "MIT",
@@ -26,6 +26,7 @@
26
26
  "hooks",
27
27
  "skills",
28
28
  ".claude-plugin",
29
+ ".codex-plugin",
29
30
  ".mcp.json",
30
31
  "README.md",
31
32
  "README.ja.md"