project-memory-mcp 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.
- package/README.md +640 -0
- package/dist/hooks/_bootstrap-context.js +99 -0
- package/dist/hooks/_bootstrap-context.js.map +1 -0
- package/dist/hooks/auto-memory.js +155 -0
- package/dist/hooks/auto-memory.js.map +1 -0
- package/dist/hooks/auto-save.js +155 -0
- package/dist/hooks/auto-save.js.map +1 -0
- package/dist/hooks/codex-notify.js +97 -0
- package/dist/hooks/codex-notify.js.map +1 -0
- package/dist/hooks/cursor.js +32 -0
- package/dist/hooks/cursor.js.map +1 -0
- package/dist/hooks/extractors.js +318 -0
- package/dist/hooks/extractors.js.map +1 -0
- package/dist/scripts/test-hooks.js +142 -0
- package/dist/scripts/test-hooks.js.map +1 -0
- package/dist/server.js +44 -0
- package/dist/server.js.map +1 -0
- package/dist/src/config.js +29 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/domain.js +52 -0
- package/dist/src/domain.js.map +1 -0
- package/dist/src/logger.js +5 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/main.js +21 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/maintenance.js +150 -0
- package/dist/src/maintenance.js.map +1 -0
- package/dist/src/runtime.js +52 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/setup.js +547 -0
- package/dist/src/setup.js.map +1 -0
- package/dist/src/storage.js +103 -0
- package/dist/src/storage.js.map +1 -0
- package/dist/src/tools.js +392 -0
- package/dist/src/tools.js.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/docs/LOCAL_SETUP.md +223 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
# Project Memory MCP Server
|
|
2
|
+
|
|
3
|
+
Shared, project-scoped memory for **Claude Code**, **Codex**, and **Gemini CLI** — so all three agents remember the same context.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You (any CLI) ──► MCP Server ──► .ai/memory.json (per project)
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
This repository ships a Node.js MCP server that persists project facts/decisions into `<project>/.ai/memory.json`. Any supported CLI can read/write the same file, so switching between Claude, Codex, and Gemini feels stateful: load context with `memory_get_bundle`, perform work, and save what changed with `memory_save`.
|
|
10
|
+
|
|
11
|
+
## Why Project Memory MCP?
|
|
12
|
+
|
|
13
|
+
- **Shared context** – one `.ai/memory.json` per repo keeps Claude, Codex, and Gemini in sync.
|
|
14
|
+
- **Batteries included tools** – search, bundle generation, pinning, proposals, auto-compaction.
|
|
15
|
+
- **Silent capture** – optional hooks auto-save versions, deps, and commits at the end of a session.
|
|
16
|
+
- **CLI + programmatic** – run the stdio server via `project-memory-mcp` or import the build artifacts in Node projects.
|
|
17
|
+
|
|
18
|
+
## Installation Options
|
|
19
|
+
|
|
20
|
+
Pick the workflow that fits your team:
|
|
21
|
+
|
|
22
|
+
### 1. Global CLI (recommended for everyday use)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -g project-memory-mcp
|
|
26
|
+
project-memory-mcp setup
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This installs the CLI once, adds a globally available `project-memory-mcp` command, and stores the server inside your global npm cache.
|
|
30
|
+
|
|
31
|
+
### 2. On-demand via npx (no global install)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx project-memory-mcp setup
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
npx downloads the package on first run and reuses the cached copy afterwards. Great for trying the tool or wiring up a single machine.
|
|
38
|
+
|
|
39
|
+
### 3. Local clone (development / hacking)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/nicobailon/project-memory-mcp-js.git
|
|
43
|
+
cd project-memory-mcp-js
|
|
44
|
+
npm install
|
|
45
|
+
npm run build
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then point your CLI at `node /absolute/path/dist/server.js`. This is also how you contribute and run the hook tests. See [Local development](#local-development) for details.
|
|
49
|
+
|
|
50
|
+
## Quick Start (any install path)
|
|
51
|
+
|
|
52
|
+
1. **Run the setup wizard** inside the repo you want to enable (or pass `--project /path`):
|
|
53
|
+
```bash
|
|
54
|
+
project-memory-mcp setup # global install
|
|
55
|
+
# or
|
|
56
|
+
npx project-memory-mcp setup # on-demand
|
|
57
|
+
```
|
|
58
|
+
2. Choose how the CLI should spawn the server (`npx`, global binary, `node dist/server.js`, or a custom command).
|
|
59
|
+
3. Pick which CLIs to configure (Claude Code, Gemini CLI, Codex CLI).
|
|
60
|
+
4. Ask your CLI: “Call `memory_status` and show the output.” You should see the correct `projectRoot` and `.ai/memory.json`.
|
|
61
|
+
|
|
62
|
+
Prefer the manual route or need automation flags? Jump to [Local development](#local-development) and `docs/LOCAL_SETUP.md`.
|
|
63
|
+
|
|
64
|
+
## Run it as a project dependency
|
|
65
|
+
|
|
66
|
+
If you want every teammate to install the server via your project’s `package.json`, add it as a dev dependency:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm install --save-dev project-memory-mcp
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Now you can expose scripts:
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
{
|
|
76
|
+
"scripts": {
|
|
77
|
+
"memory:serve": "project-memory-mcp serve",
|
|
78
|
+
"memory:setup": "project-memory-mcp setup --yes --runner node"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
From there your CLI entries can point at `npx project-memory-mcp` or `node ./node_modules/project-memory-mcp/dist/server.js`. The published package bundles the `dist/` tree, so no build step is needed on consumer machines.
|
|
84
|
+
|
|
85
|
+
## Local development
|
|
86
|
+
|
|
87
|
+
Working out of this repo?
|
|
88
|
+
|
|
89
|
+
1. `npm install`
|
|
90
|
+
2. `npm run build`
|
|
91
|
+
3. `npm run test:hooks` (optional smoke test for hook flows)
|
|
92
|
+
4. Wire your CLIs using `node dist/server.js` or `project-memory-mcp` (after linking via `npm link`)
|
|
93
|
+
|
|
94
|
+
See [`docs/LOCAL_SETUP.md`](docs/LOCAL_SETUP.md) for the long-form guide, env overrides, troubleshooting, and hook wiring defaults.
|
|
95
|
+
|
|
96
|
+
## CLI Setup & Tool Map
|
|
97
|
+
|
|
98
|
+
Already installed globally, via npx, or from source? Run the wizard from the repo you want to enable:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Install globally (recommended)
|
|
102
|
+
npm install -g project-memory-mcp
|
|
103
|
+
|
|
104
|
+
# Or use npx (no install needed)
|
|
105
|
+
npx project-memory-mcp
|
|
106
|
+
|
|
107
|
+
# Or clone and run locally
|
|
108
|
+
git clone https://github.com/nicobailon/project-memory-mcp-js.git
|
|
109
|
+
cd project-memory-mcp-js && npm install && npm run build && npm start
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
| What you want | Tool to call |
|
|
113
|
+
|---|---|
|
|
114
|
+
| Check setup is correct | `memory_status` |
|
|
115
|
+
| Load context before a task | `memory_get_bundle` |
|
|
116
|
+
| Save something to memory | `memory_save` |
|
|
117
|
+
| Search past memory | `memory_search` |
|
|
118
|
+
|
|
119
|
+
That's the core loop: **get bundle → do work → save what matters**.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Quick setup (per project)
|
|
124
|
+
|
|
125
|
+
1. **Install the package** (pick one)
|
|
126
|
+
```bash
|
|
127
|
+
npm install -g project-memory-mcp # global install
|
|
128
|
+
# or use npx — no install needed
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
2. **Run the guided setup (recommended)**
|
|
132
|
+
```bash
|
|
133
|
+
# from the repo you want to wire up (or pass --project)
|
|
134
|
+
npx project-memory-mcp setup
|
|
135
|
+
# or, after a global install:
|
|
136
|
+
project-memory-mcp setup
|
|
137
|
+
```
|
|
138
|
+
- Prompts for the project directory (defaults to your current working folder).
|
|
139
|
+
- Lets you choose how to launch the MCP server (`npx`, global binary, `node /path/to/dist/server.js`, or a custom command).
|
|
140
|
+
- Lets you pick which CLIs to configure (Claude Code, Gemini CLI, Codex CLI).
|
|
141
|
+
- Automatically updates `~/.claude.json` (with a `.bak` backup) and runs the necessary `gemini mcp` / `codex mcp` commands so they point at the right project.
|
|
142
|
+
- Flags: `--project /path`, `--cli claude,gemini`, `--runner global`, `--yes`, `--command`, and `--args` let you script it or skip prompts. Run `project-memory-mcp setup --help` for the full list.
|
|
143
|
+
- Requires the corresponding CLIs to already be installed and on your `PATH`.
|
|
144
|
+
|
|
145
|
+
<details>
|
|
146
|
+
<summary>Prefer the fully manual wiring? Expand for the original commands.</summary>
|
|
147
|
+
|
|
148
|
+
- **Claude Code** – edit `~/.claude.json` and add:
|
|
149
|
+
```json
|
|
150
|
+
"mcpServers": {
|
|
151
|
+
"project-memory": {
|
|
152
|
+
"command": "npx",
|
|
153
|
+
"args": ["project-memory-mcp"],
|
|
154
|
+
"cwd": "/path/to/my-app"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
Restart Claude inside `/path/to/my-app`.
|
|
159
|
+
- **Gemini CLI**
|
|
160
|
+
```bash
|
|
161
|
+
cd /path/to/my-app
|
|
162
|
+
gemini mcp add project-memory npx project-memory-mcp --trust
|
|
163
|
+
gemini mcp list # should show CONNECTED
|
|
164
|
+
/mcp # (in-session) inspect tools/resources
|
|
165
|
+
```
|
|
166
|
+
Edit `.gemini/settings.json` if you need custom `cwd` or env vars.
|
|
167
|
+
- **Codex CLI**
|
|
168
|
+
```bash
|
|
169
|
+
cd /path/to/my-app
|
|
170
|
+
codex mcp add project-memory npx project-memory-mcp
|
|
171
|
+
codex mcp list
|
|
172
|
+
```
|
|
173
|
+
Always start `codex` from `/path/to/my-app` so the server detects the right root.
|
|
174
|
+
</details>
|
|
175
|
+
|
|
176
|
+
3. **Verify routing**
|
|
177
|
+
- In that project, ask your CLI to `Call memory_status and show the output.` You should see `projectRoot` = `/path/to/my-app` and `memoryFilePath` = `/path/to/my-app/.ai/memory.json`. If not, fix the MCP config (`cwd`, env vars, etc.) before continuing.
|
|
178
|
+
- Need a reminder of commands? Run `memory_help` anytime for the cheat sheet.
|
|
179
|
+
|
|
180
|
+
> Prefer the long-form guide (env overrides, troubleshooting, auto hooks)? See `docs/LOCAL_SETUP.md`.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Daily Workflow
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
1. memory_get_bundle → load relevant context for your task
|
|
188
|
+
2. ... do your work ...
|
|
189
|
+
3. memory_save → store what changed / what you learned
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Any model (Claude, Codex, Gemini) can then pick up where another left off.
|
|
193
|
+
|
|
194
|
+
<details>
|
|
195
|
+
<summary><strong>Example: save context</strong></summary>
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
Call MCP tool `memory_save` with:
|
|
199
|
+
- title: "Project runtime versions"
|
|
200
|
+
- type: "fact"
|
|
201
|
+
- content: "PHP 7.4.33, Laravel 5.6.40"
|
|
202
|
+
- tags: ["php","laravel","environment"]
|
|
203
|
+
- source: "claude"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
</details>
|
|
207
|
+
|
|
208
|
+
<details>
|
|
209
|
+
<summary><strong>Example: load context</strong></summary>
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
Call `memory_get_bundle` with prompt "I am fixing login API bugs" and maxItems 12.
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
### Automatic compaction & archives
|
|
218
|
+
|
|
219
|
+
- The server automatically compacts when more than **400** active items exist (see `CONFIG.autoCompact`). Oldest entries are moved to `.ai/memory-archive.json`, and a summary note is added so you still know what was archived.
|
|
220
|
+
- To trigger compaction manually (or tune thresholds per project), call `memory_compact` and provide overrides such as `{ "maxItems": 250 }`.
|
|
221
|
+
- Archived content stays available for future manual review—`memory_get_bundle` only surfaces the most relevant active notes while summaries keep the historical trail discoverable.
|
|
222
|
+
- Want zero-click context? Configure the optional `dist/hooks/auto-memory.js` script (`... start` on `UserPromptSubmit`, `... stop` on `Stop`) to auto-inject bundles and auto-save transcripts.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Reference
|
|
227
|
+
|
|
228
|
+
<details>
|
|
229
|
+
<summary><strong>All Tools</strong></summary>
|
|
230
|
+
|
|
231
|
+
### Read
|
|
232
|
+
|
|
233
|
+
| Tool | Purpose |
|
|
234
|
+
|---|---|
|
|
235
|
+
| `memory_help` | Quick-start usage tips + sample prompts |
|
|
236
|
+
| `memory_status` | Show resolved project root, memory file path, counts, revision |
|
|
237
|
+
| `memory_search` | Keyword/tag search over saved items |
|
|
238
|
+
| `memory_get_bundle` | Compact ranked memory bundle for current task |
|
|
239
|
+
| `memory_list_proposals` | List proposals by status |
|
|
240
|
+
|
|
241
|
+
### Write (direct)
|
|
242
|
+
|
|
243
|
+
| Tool | Purpose |
|
|
244
|
+
|---|---|
|
|
245
|
+
| `memory_save` | Save memory item immediately (no approval step) |
|
|
246
|
+
| `memory_pin` | Pin or unpin an existing item |
|
|
247
|
+
|
|
248
|
+
### Write (gated)
|
|
249
|
+
|
|
250
|
+
| Tool | Purpose |
|
|
251
|
+
|---|---|
|
|
252
|
+
| `memory_propose` | Create proposals (pending approval) |
|
|
253
|
+
| `memory_approve_proposal` | Approve/reject proposal, optional edits |
|
|
254
|
+
|
|
255
|
+
### Maintenance
|
|
256
|
+
|
|
257
|
+
| Tool | Purpose |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `memory_compact` | Archive older items into `.ai/memory-archive.json` and add a summary note, keeping the active store lean |
|
|
260
|
+
|
|
261
|
+
All write tools accept an optional `projectRoot` input for multi-project routing.
|
|
262
|
+
|
|
263
|
+
</details>
|
|
264
|
+
|
|
265
|
+
### Tool invocation cheatsheet
|
|
266
|
+
|
|
267
|
+
| Tool | Minimal CLI prompt | Notes |
|
|
268
|
+
|---|---|---|
|
|
269
|
+
| `memory_status` | `Call memory_status and show the output.` | Confirms `projectRoot` + `.ai/memory.json` before you start. |
|
|
270
|
+
| `memory_help` | `Call memory_help.` | Returns this cheat sheet + best-practice prompts. |
|
|
271
|
+
| `memory_get_bundle` | `Call memory_get_bundle with {"prompt":"Fixing login bugs"}` | Adjust `maxItems`, `types`, or `projectRoot` per task. |
|
|
272
|
+
| `memory_save` | `Call memory_save with {"title":"New API",...}` | Provide `content`; optionally `tags`, `pinned`, `source`. |
|
|
273
|
+
| `memory_search` | `Call memory_search with {"query":"redis"}` | Add `includeContent`, `tags`, or `types` filters. |
|
|
274
|
+
| `memory_propose` | `Call memory_propose with {"items":[...],"reason":"code review"}` | Use when you want an approval step before saving. |
|
|
275
|
+
| `memory_approve_proposal` | `Call memory_approve_proposal with {"proposalId":"prop_...","action":"approve"}` | Include `edits` to tweak proposal content before approval. |
|
|
276
|
+
| `memory_pin` | `Call memory_pin with {"itemId":"mem_...","pinned":true}` | Pinning keeps key notes surfaced in bundles. |
|
|
277
|
+
| `memory_compact` | `Call memory_compact with {"maxItems":250}` | Keeps the active store lean; omit payload to use defaults. |
|
|
278
|
+
|
|
279
|
+
Usage tips:
|
|
280
|
+
|
|
281
|
+
- **Claude Code / Codex CLI**: type the phrase exactly (e.g. “Call memory_status…”). They’ll run the tool and return the output inline.
|
|
282
|
+
- **Gemini CLI**: either type the sentence or run `memory_compact {"maxItems":250}` directly in the terminal. `/mcp` shows the live list of tools + descriptions.
|
|
283
|
+
|
|
284
|
+
<details>
|
|
285
|
+
<summary><strong>Data Model</strong></summary>
|
|
286
|
+
|
|
287
|
+
`memory.json` structure:
|
|
288
|
+
|
|
289
|
+
| Field | Description |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `version` | Format version (currently `1`) |
|
|
292
|
+
| `project` | Metadata: `id`, `root`, timestamps |
|
|
293
|
+
| `items` | Approved/saved memory entries |
|
|
294
|
+
| `proposals` | Gated workflow entries (`pending`, `approved`, `rejected`) |
|
|
295
|
+
| `revision` | Incremented on every write |
|
|
296
|
+
|
|
297
|
+
</details>
|
|
298
|
+
|
|
299
|
+
<details>
|
|
300
|
+
<summary><strong>Memory Resolution Rules</strong></summary>
|
|
301
|
+
|
|
302
|
+
`projectRoot` is resolved in this priority:
|
|
303
|
+
|
|
304
|
+
1. Tool input `projectRoot` (if provided)
|
|
305
|
+
2. `MEMORY_PROJECT_ROOT` env var
|
|
306
|
+
3. Nearest ancestor with `.git`
|
|
307
|
+
4. Current working directory
|
|
308
|
+
|
|
309
|
+
Storage path:
|
|
310
|
+
|
|
311
|
+
- `MEMORY_FILE_PATH` env var if set (relative paths resolve from project root)
|
|
312
|
+
- Otherwise `<projectRoot>/.ai/memory.json`
|
|
313
|
+
|
|
314
|
+
</details>
|
|
315
|
+
|
|
316
|
+
<details>
|
|
317
|
+
<summary><strong>Update and Delete</strong></summary>
|
|
318
|
+
|
|
319
|
+
There is no `memory_update` or `memory_delete` tool yet.
|
|
320
|
+
|
|
321
|
+
**To update:** save a corrected item with `memory_save`. Add a tag like `supersedes:<old_id>` and optionally `memory_pin` the new one.
|
|
322
|
+
|
|
323
|
+
**To delete all:** `rm -f <projectRoot>/.ai/memory.json`
|
|
324
|
+
|
|
325
|
+
**To delete one item:** manually edit the `items` array in the JSON file.
|
|
326
|
+
|
|
327
|
+
</details>
|
|
328
|
+
|
|
329
|
+
<details>
|
|
330
|
+
<summary><strong>Environment Variables</strong></summary>
|
|
331
|
+
|
|
332
|
+
| Variable | Purpose |
|
|
333
|
+
|---|---|
|
|
334
|
+
| `MEMORY_PROJECT_ROOT` | Force a specific project root |
|
|
335
|
+
| `MEMORY_FILE_PATH` | Override the memory file path (relative resolves from project root) |
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
MEMORY_PROJECT_ROOT=/path/to/project npm run start
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
</details>
|
|
342
|
+
|
|
343
|
+
<details>
|
|
344
|
+
<summary><strong>File Layout</strong></summary>
|
|
345
|
+
|
|
346
|
+
```text
|
|
347
|
+
server.ts # entrypoint (source)
|
|
348
|
+
dist/server.js # entrypoint (runtime)
|
|
349
|
+
src/main.ts # MCP bootstrap and transport connection
|
|
350
|
+
src/tools.ts # tool registration and handlers
|
|
351
|
+
src/storage.ts # lock, load/write, atomic persistence
|
|
352
|
+
src/runtime.ts # project root/path resolution
|
|
353
|
+
src/domain.ts # scoring/tokenization/validation helpers
|
|
354
|
+
src/config.ts # constants
|
|
355
|
+
src/logger.ts # stderr logger
|
|
356
|
+
.ai/memory.json # persisted project memory (per project)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Add `.ai/` to `.gitignore` if you don't want memory committed to the repo.
|
|
360
|
+
|
|
361
|
+
</details>
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Troubleshooting
|
|
366
|
+
|
|
367
|
+
| Problem | Fix |
|
|
368
|
+
|---|---|
|
|
369
|
+
| `memory.json` not created | Call `memory_status` — project root is probably wrong. Fix `cwd` (Claude) or run CLI from correct folder. |
|
|
370
|
+
| Server not available in CLI | Check CLI MCP config. Confirm `node -v` works and server file exists. |
|
|
371
|
+
| Data not saved | You must call a write tool (`memory_save` or approve a proposal). Chat alone does not persist. |
|
|
372
|
+
|
|
373
|
+
### Testing checklist
|
|
374
|
+
|
|
375
|
+
1. Configure CLI MCP server for target project
|
|
376
|
+
2. Restart CLI session
|
|
377
|
+
3. `memory_status` returns expected path
|
|
378
|
+
4. `memory_save` returns success
|
|
379
|
+
5. `memory_search` finds the saved item
|
|
380
|
+
6. Verify another CLI (Claude/Gemini/Codex) can see the same item
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
<details>
|
|
385
|
+
<summary><strong>Auto-Save Hook (Claude Code + Gemini CLI + Codex CLI)</strong></summary>
|
|
386
|
+
|
|
387
|
+
The `hooks/` directory contains hooks that **automatically capture** memory items from your session — no manual `memory_save` needed for routine facts.
|
|
388
|
+
|
|
389
|
+
### How it works
|
|
390
|
+
|
|
391
|
+
The auto-save hook runs **silently in the background** after each session:
|
|
392
|
+
|
|
393
|
+
1. **Trigger**: When your CLI session ends:
|
|
394
|
+
- Claude Code: on `Stop` event (Ctrl+C or session end)
|
|
395
|
+
- Gemini CLI: on `SessionEnd` event
|
|
396
|
+
- Codex CLI: on notify events (when configured)
|
|
397
|
+
|
|
398
|
+
2. **Processing**:
|
|
399
|
+
- `dist/hooks/auto-save.js` reads the session transcript (JSONL or JSON format)
|
|
400
|
+
- Heuristic extractors analyze tool calls and results
|
|
401
|
+
- Extracts structured facts like versions, dependencies, commits, error fixes
|
|
402
|
+
|
|
403
|
+
3. **Saving**:
|
|
404
|
+
- Deduplicates against existing memory using title hashing and similarity checks
|
|
405
|
+
- Saves new items to `.ai/memory.json` with `source: "auto-hook"` and `tags: ["auto-hook"]`
|
|
406
|
+
- Updates cursor in `.ai/.auto-save-cursor.json` to track progress
|
|
407
|
+
|
|
408
|
+
4. **Next session**: Only processes new transcript lines since last cursor position
|
|
409
|
+
|
|
410
|
+
### What gets captured automatically
|
|
411
|
+
|
|
412
|
+
| Category | Example Command | Extracted Item | Type |
|
|
413
|
+
|---|---|---|---|
|
|
414
|
+
| **Version checks** | `node -v` | "node version: v20.11.0" | fact |
|
|
415
|
+
| | `python --version` | "python version: 3.11.5" | fact |
|
|
416
|
+
| | `npm -v`, `pip -v`, `go version` | version facts | fact |
|
|
417
|
+
| **Dependencies** | `npm install express` | "Added dependency: express" | fact |
|
|
418
|
+
| | `pip install requests` | "Added dependency: requests" | fact |
|
|
419
|
+
| | `cargo add tokio` | "Added dependency: tokio" | fact |
|
|
420
|
+
| **Git commits** | `git commit -m "fix auth bug"` | "Commit: fix auth bug" | note |
|
|
421
|
+
| **Error fixes** | Command fails → retried command succeeds | "Resolved: [error summary]" | fact |
|
|
422
|
+
| **File changes** | Write/Edit tool calls | "Files modified this session (5)" | note |
|
|
423
|
+
|
|
424
|
+
All auto-saved items get these tags:
|
|
425
|
+
- `auto-hook` - identifies auto-captured items
|
|
426
|
+
- Category-specific tags: `version`, `environment`, `dependency`, `commit`, `error-resolution`, `file-changes`
|
|
427
|
+
|
|
428
|
+
### Example: What you'll see
|
|
429
|
+
|
|
430
|
+
**During session:**
|
|
431
|
+
```bash
|
|
432
|
+
$ node -v
|
|
433
|
+
v20.11.0
|
|
434
|
+
$ npm install express
|
|
435
|
+
added 57 packages
|
|
436
|
+
$ git commit -m "Add express server"
|
|
437
|
+
[main abc1234] Add express server
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**After session ends** (automatic, silent):
|
|
441
|
+
|
|
442
|
+
Your `.ai/memory.json` will contain:
|
|
443
|
+
```json
|
|
444
|
+
{
|
|
445
|
+
"items": [
|
|
446
|
+
{
|
|
447
|
+
"id": "mem_a1b2c3d4",
|
|
448
|
+
"type": "fact",
|
|
449
|
+
"title": "node version: v20.11.0",
|
|
450
|
+
"content": "Detected via `node -v`",
|
|
451
|
+
"tags": ["version", "environment", "auto-hook"],
|
|
452
|
+
"source": "auto-hook",
|
|
453
|
+
"createdAt": "2026-02-12T13:39:17.364Z"
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
"id": "mem_e5f6g7h8",
|
|
457
|
+
"type": "fact",
|
|
458
|
+
"title": "Added dependency: express",
|
|
459
|
+
"content": "Installed via `npm install express`",
|
|
460
|
+
"tags": ["dependency", "auto-hook"],
|
|
461
|
+
"source": "auto-hook",
|
|
462
|
+
"createdAt": "2026-02-12T13:39:18.123Z"
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"id": "mem_i9j0k1l2",
|
|
466
|
+
"type": "note",
|
|
467
|
+
"title": "Commit: Add express server",
|
|
468
|
+
"content": "Full command: git commit -m \"Add express server\"",
|
|
469
|
+
"tags": ["commit", "auto-hook"],
|
|
470
|
+
"source": "auto-hook",
|
|
471
|
+
"createdAt": "2026-02-12T13:39:19.456Z"
|
|
472
|
+
}
|
|
473
|
+
]
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Setup per CLI
|
|
478
|
+
|
|
479
|
+
#### Claude Code (already configured)
|
|
480
|
+
|
|
481
|
+
This repo includes `.claude/settings.json`:
|
|
482
|
+
```json
|
|
483
|
+
{
|
|
484
|
+
"hooks": {
|
|
485
|
+
"Stop": [{
|
|
486
|
+
"hooks": [{
|
|
487
|
+
"type": "command",
|
|
488
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/dist/hooks/auto-save.js\"",
|
|
489
|
+
"async": true,
|
|
490
|
+
"timeout": 15
|
|
491
|
+
}]
|
|
492
|
+
}]
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Status**: ✅ Works automatically in this project
|
|
498
|
+
|
|
499
|
+
**To disable**: Remove or rename `.claude/settings.json`
|
|
500
|
+
|
|
501
|
+
**Environment**: Hook receives `CLAUDE_PROJECT_DIR` env var pointing to project root
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
#### Gemini CLI (already configured)
|
|
506
|
+
|
|
507
|
+
This repo includes `.gemini/settings.json`:
|
|
508
|
+
```json
|
|
509
|
+
{
|
|
510
|
+
"hooks": {
|
|
511
|
+
"SessionEnd": [{
|
|
512
|
+
"matcher": "*",
|
|
513
|
+
"hooks": [{
|
|
514
|
+
"name": "auto-save",
|
|
515
|
+
"type": "command",
|
|
516
|
+
"command": "node \"$GEMINI_PROJECT_DIR/dist/hooks/auto-save.js\""
|
|
517
|
+
}]
|
|
518
|
+
}]
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**Status**: ✅ Works automatically in this project
|
|
524
|
+
|
|
525
|
+
**To disable**: Remove or rename `.gemini/settings.json`
|
|
526
|
+
|
|
527
|
+
**Environment**: Hook receives `GEMINI_PROJECT_DIR` env var pointing to project root
|
|
528
|
+
|
|
529
|
+
**Important**: Gemini hooks must output valid JSON to stdout. The hook returns `{}` for compatibility.
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
#### Codex CLI (needs manual setup)
|
|
534
|
+
|
|
535
|
+
**Setup required**: Edit your global Codex config at `~/.codex/config.toml`:
|
|
536
|
+
|
|
537
|
+
```toml
|
|
538
|
+
# Enable history persistence (required for hooks to access transcript)
|
|
539
|
+
[history]
|
|
540
|
+
persistence = "save-all" # or just true
|
|
541
|
+
|
|
542
|
+
# Add the notify hook (adjust path to your installation)
|
|
543
|
+
[notify]
|
|
544
|
+
command = ["node", "/absolute/path/to/project-memory-mcp-js/dist/hooks/codex-notify.js"]
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Replace `/absolute/path/to/project-memory-mcp-js` with your actual installation path.
|
|
548
|
+
|
|
549
|
+
**Optional**: Pass explicit history file path:
|
|
550
|
+
```toml
|
|
551
|
+
[notify]
|
|
552
|
+
command = ["node", "/path/to/dist/hooks/codex-notify.js", "--history", "/path/to/history.jsonl"]
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**To disable**: Remove the `[notify]` section from `config.toml`
|
|
556
|
+
|
|
557
|
+
**Environment**: Hook receives `CODEX_PROJECT_DIR` env var pointing to project root
|
|
558
|
+
|
|
559
|
+
**How it works**:
|
|
560
|
+
1. Codex calls `codex-notify.js` with its notification payload
|
|
561
|
+
2. The notify hook parses Codex's payload format and forwards it to `auto-save.js`
|
|
562
|
+
3. Same extraction and saving process as Claude/Gemini
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
### Deduplication strategy
|
|
567
|
+
|
|
568
|
+
The hook prevents duplicate items using multiple strategies:
|
|
569
|
+
|
|
570
|
+
1. **Title hash tracking**: SHA-256 hash of each title stored in cursor file
|
|
571
|
+
2. **Jaccard similarity**: Compares word overlap between new and existing titles (threshold: 80%)
|
|
572
|
+
3. **Cross-session dedup**: Hashes persist across sessions to prevent re-capturing the same facts
|
|
573
|
+
4. **Cursor position**: Only processes new transcript lines since last run
|
|
574
|
+
|
|
575
|
+
### Cursor tracking
|
|
576
|
+
|
|
577
|
+
State tracked in `.ai/.auto-save-cursor.json`:
|
|
578
|
+
```json
|
|
579
|
+
{
|
|
580
|
+
"sessionId": "current-session-id",
|
|
581
|
+
"lastLineIndex": 42,
|
|
582
|
+
"itemHashes": ["hash1", "hash2", "..."],
|
|
583
|
+
"updatedAt": "2026-02-12T13:39:17.658Z"
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
- `sessionId` - Current session ID (resets cursor position on session change)
|
|
588
|
+
- `lastLineIndex` - Last processed transcript line (0-indexed)
|
|
589
|
+
- `itemHashes` - Recent title hashes (keeps last 200 for dedup)
|
|
590
|
+
- `updatedAt` - Last update timestamp
|
|
591
|
+
|
|
592
|
+
**Session change behavior**: When `sessionId` changes, `lastLineIndex` resets to -1 but `itemHashes` are preserved for cross-session deduplication.
|
|
593
|
+
|
|
594
|
+
### Minimum threshold
|
|
595
|
+
|
|
596
|
+
To reduce noise, the hook only processes transcripts with **at least 2 assistant messages** in the new lines since last cursor position.
|
|
597
|
+
|
|
598
|
+
Single-turn exchanges are skipped.
|
|
599
|
+
|
|
600
|
+
### Testing the hook
|
|
601
|
+
|
|
602
|
+
**Automated test** (all three CLIs):
|
|
603
|
+
```bash
|
|
604
|
+
npm run test:hooks
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
This creates a test transcript and verifies all three hooks work correctly.
|
|
608
|
+
|
|
609
|
+
**Manual test** (single hook):
|
|
610
|
+
```bash
|
|
611
|
+
echo '{"session_id":"test","transcript_path":"/tmp/test.jsonl","cwd":"'$(pwd)'"}' | node dist/hooks/auto-save.js
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
**Verify saved items**:
|
|
615
|
+
```bash
|
|
616
|
+
# Check memory file
|
|
617
|
+
cat .ai/memory.json | jq '.items[] | select(.source == "auto-hook")'
|
|
618
|
+
|
|
619
|
+
# Check cursor
|
|
620
|
+
cat .ai/.auto-save-cursor.json
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### Troubleshooting
|
|
624
|
+
|
|
625
|
+
| Issue | Solution |
|
|
626
|
+
|---|---|
|
|
627
|
+
| Hook not running | Check CLI settings file exists (`.claude/settings.json`, `.gemini/settings.json`) or Codex `config.toml` |
|
|
628
|
+
| No items saved | Check transcript has at least 2 assistant messages. Try running `node -v` and ending session. |
|
|
629
|
+
| Items not appearing | Verify `.ai/memory.json` exists and check for errors in hook stderr |
|
|
630
|
+
| Duplicates appearing | Check cursor file `.ai/.auto-save-cursor.json` is being updated |
|
|
631
|
+
| Codex hook not working | Ensure `history.persistence` is enabled and history file exists |
|
|
632
|
+
|
|
633
|
+
**Debug mode**: Run hook manually with test payload to see errors:
|
|
634
|
+
```bash
|
|
635
|
+
node dist/hooks/auto-save.js < test-payload.json
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
</details>
|
|
639
|
+
|
|
640
|
+
---
|