@nogataka/claw-memory 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.2"
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.2"
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.2",
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 で重複回避)
@@ -272,7 +291,7 @@ claw-memory ui --open # http://localhost:4319
272
291
  ## アンインストール
273
292
 
274
293
  ```bash
275
- claw-memory uninstall --codex # config.toml ブロック + skill + AGENTS 記述を除去
294
+ claw-memory uninstall --codex # config.toml ブロック + hooks + skill + AGENTS 記述を除去
276
295
  claw-memory uninstall --claude-code # settings.json から mcp + フックを除去
277
296
  # Claude Code プラグイン: /plugin uninstall claw-memory
278
297
  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)
@@ -277,7 +296,7 @@ background otherwise — start it only when you want to inspect.
277
296
  ## Uninstall
278
297
 
279
298
  ```bash
280
- claw-memory uninstall --codex # remove config.toml block + skill + AGENTS note
299
+ claw-memory uninstall --codex # remove config.toml block + hooks + skill + AGENTS note
281
300
  claw-memory uninstall --claude-code # remove mcp + hooks from settings.json
282
301
  # Claude Code plugin: /plugin uninstall claw-memory
283
302
  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");
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nogataka/claw-memory",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
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"