claude-memory-admin 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -15
- package/package.json +8 -2
- package/public/app.mjs +849 -408
- package/public/graph.mjs +32 -76
- package/public/index.html +34 -29
- package/public/markdown.mjs +74 -0
- package/public/styles.css +2 -439
- package/public/ui.mjs +309 -0
- package/server.mjs +82 -5
- package/src/instructions.mjs +123 -21
- package/src/model.mjs +4 -1
- package/src/mutate.mjs +355 -1
- package/src/parse.mjs +176 -0
- package/src/settings.mjs +120 -19
- package/src/stores.mjs +34 -4
package/README.md
CHANGED
|
@@ -97,13 +97,16 @@ project is to the cliff, and makes it quick to get back under it.
|
|
|
97
97
|
- **Graph** the wikilinks between memories. Hovering dims everything that is not
|
|
98
98
|
a neighbour, which is the only practical way to read a dense cluster.
|
|
99
99
|
- **Health**: orphans, dangling pointers, broken wikilinks, files linked only
|
|
100
|
-
mid-sentence, `name` fields that disagree with the filename.
|
|
100
|
+
mid-sentence, `name` fields that disagree with the filename. An orphan can be
|
|
101
|
+
given the `MEMORY.md` bullet it is missing without leaving the page.
|
|
101
102
|
- **Dates you can trust.** Claude Code stamps `modified` into frontmatter, but
|
|
102
103
|
only on files that already have some, and never adds frontmatter to a file
|
|
103
104
|
without it. Anything falling back to the file's mtime is labelled, because
|
|
104
105
|
mtime is reset by any copy or restore.
|
|
105
106
|
- **Context**: what a session starting in this project would load as
|
|
106
107
|
*instructions*, which is the other half of the startup budget (see below).
|
|
108
|
+
- **Settings**: every layer Claude Code would read, side by side, with the value
|
|
109
|
+
that wins and the ones it shadows (see below).
|
|
107
110
|
- **Delete with cascade**, always reversible.
|
|
108
111
|
|
|
109
112
|
Everything above works the same on both kinds of store. The load meter, graph,
|
|
@@ -122,13 +125,28 @@ session and, past the limit, silently stops loading.
|
|
|
122
125
|
- **The cutoff, drawn where it falls**. Past the limit, the MEMORY.md tab rules a
|
|
123
126
|
line across the file and dims everything below it, and Prune names the memories
|
|
124
127
|
that stopped being loaded. Because the stripping shifts every line, the cutoff
|
|
125
|
-
is mapped back to real line numbers rather than counted in the loaded text.
|
|
128
|
+
is mapped back to real line numbers rather than counted in the loaded text. The
|
|
129
|
+
tab reads the index either **rendered** — headings, lists and clickable entries,
|
|
130
|
+
with pointers to files that do not exist struck through — or as **source**, with
|
|
131
|
+
line numbers. Either way the cutoff is drawn in the same place. The choice is
|
|
132
|
+
remembered.
|
|
126
133
|
- **Long hooks**. The hook is the text after the dash in `MEMORY.md`. A
|
|
127
134
|
400-character hook can cost more than the memory it points at, and shortening
|
|
128
|
-
it is the cheapest win available.
|
|
135
|
+
it is the cheapest win available. **Edit hook** rewrites one in place, with the
|
|
136
|
+
projected load meter next to the character count, and changes nothing but the
|
|
137
|
+
text after the separator - the indent, title, link and the separator character
|
|
138
|
+
itself are kept byte for byte, so a project that writes ` - ` keeps writing it.
|
|
139
|
+
- **Move above the cutoff**. Past the limit, an entry is on disk but invisible.
|
|
140
|
+
**Move up** relocates its bullet, and the indented lines under it, to the end
|
|
141
|
+
of any section that starts above the cutoff. It moves one entry rather than
|
|
142
|
+
making room, so whatever is now last drops below the line instead - the tab
|
|
143
|
+
says so before you do it.
|
|
129
144
|
- **Possible overlap**. Pairs of memories ranked by shared *rare* vocabulary, to
|
|
130
145
|
surface the same lesson saved three times from three sessions. It is a hint,
|
|
131
|
-
not a verdict.
|
|
146
|
+
not a verdict. **Merge** folds one into the other: the body moves under a
|
|
147
|
+
heading you name, every `[[wikilink]]` that pointed at the source is repointed
|
|
148
|
+
rather than broken, a link the survivor had to the source becomes plain text
|
|
149
|
+
instead of a self-link, and the two index bullets collapse to one.
|
|
132
150
|
- **Bulk prune**. Sort by age, size, or inbound links, tick several, delete them
|
|
133
151
|
as one restore point.
|
|
134
152
|
|
|
@@ -157,15 +175,54 @@ It also finds the failures that leave a file silently doing nothing:
|
|
|
157
175
|
- Brace expansion past the 1,000-pattern budget, where the pattern is used
|
|
158
176
|
unexpanded and its literal braces match no file either.
|
|
159
177
|
- An `AGENTS.md` that no `CLAUDE.md` imports. Claude Code reads `CLAUDE.md`.
|
|
178
|
+
- A markdown file sitting in `~/.claude` that nothing in the chain reaches. It
|
|
179
|
+
looks load-bearing and loads nothing, which is what happens when the import
|
|
180
|
+
that pulled it in is deleted or its content is inlined.
|
|
160
181
|
|
|
161
182
|
Backticks are respected, so a `` `@README` `` in your prose is not reported as an
|
|
162
183
|
import, and neither is an email address.
|
|
163
184
|
|
|
185
|
+
Every file listed opens in place, so you can read what actually loads without
|
|
186
|
+
leaving the tab. Nothing here is editable: the app never rewrites a `CLAUDE.md`.
|
|
187
|
+
|
|
188
|
+
### The user scope on its own
|
|
189
|
+
|
|
190
|
+
The half of that chain no project owns — managed policy, `~/.claude/CLAUDE.md`,
|
|
191
|
+
`~/.claude/rules/` and their imports — is also a **Global** entry at the top of
|
|
192
|
+
the sidebar. It is what every session on the machine pays for before a project is
|
|
193
|
+
even chosen, and it resolves without a project directory, so it is there even when
|
|
194
|
+
no project's real path could be recovered from a transcript.
|
|
195
|
+
|
|
196
|
+
It holds instructions rather than memory, so it is read-only and has no MEMORY.md,
|
|
197
|
+
graph or trash. Search does not reach into it.
|
|
198
|
+
|
|
164
199
|
This is re-derived from the documented resolution rules rather than reported by
|
|
165
200
|
Claude Code, and the tab says so. Run `/context` in a session for the ground
|
|
166
201
|
truth, or the `InstructionsLoaded` hook to log exactly what loaded and why.
|
|
167
202
|
|
|
168
|
-
##
|
|
203
|
+
## Which settings are actually in force
|
|
204
|
+
|
|
205
|
+
Five files can set the keys this tool cares about, and the one everybody edits,
|
|
206
|
+
`~/.claude/settings.json`, is the weakest of them. The **Settings** tab reads all
|
|
207
|
+
five and shows, per key, the value that wins and the ones it shadows, struck
|
|
208
|
+
through, each labelled with the file it came from:
|
|
209
|
+
|
|
210
|
+
`autoMemoryEnabled`, `autoMemoryDirectory`, `claudeMdExcludes` and
|
|
211
|
+
`cleanupPeriodDays`, plus `CLAUDE_CODE_DISABLE_AUTO_MEMORY` when it is set in the
|
|
212
|
+
environment, where it outranks every file.
|
|
213
|
+
|
|
214
|
+
It also names the failures that are otherwise silent:
|
|
215
|
+
|
|
216
|
+
- A settings file that exists but is not valid JSON. Claude Code ignores the
|
|
217
|
+
whole file, so every value in it is doing nothing, and nothing says so.
|
|
218
|
+
- A file that parses but is not an object, or cannot be read at all.
|
|
219
|
+
- An `autoMemoryDirectory` that is neither absolute nor `~/`-prefixed.
|
|
220
|
+
- A value Claude Code accepts the key of but not the number, like a
|
|
221
|
+
`cleanupPeriodDays` below 1: the tab shows what is written *and* what applies.
|
|
222
|
+
|
|
223
|
+
The tab is read-only. It reports what is configured; it never writes a setting.
|
|
224
|
+
|
|
225
|
+
## Everything it writes is reversible
|
|
169
226
|
|
|
170
227
|
Delete shows a preview first: the exact lines that will go, the prose mentions it
|
|
171
228
|
will deliberately leave alone, and which other memories link here and will break.
|
|
@@ -181,8 +238,19 @@ exists. The markup goes and the words stay, so `see [[gone]] for details` become
|
|
|
181
238
|
`see gone for details`.
|
|
182
239
|
|
|
183
240
|
Everything lands in `memory/.trash/` with a restore record and comes back from the
|
|
184
|
-
Trash tab
|
|
185
|
-
|
|
241
|
+
Trash tab, one undo per operation however many files it touched.
|
|
242
|
+
|
|
243
|
+
The app never writes a memory file of its own. It edits `MEMORY.md` a line at a
|
|
244
|
+
time - a hook rewritten, a bullet added or moved - and each of those keeps every
|
|
245
|
+
other byte of the file. Adding a bullet to a project that has no `MEMORY.md` yet
|
|
246
|
+
is the one case where a file is created, and undoing it deletes that file again,
|
|
247
|
+
but only if nothing has touched it since. **Merge** is the one action that
|
|
248
|
+
rewrites prose inside a memory, which is why it shows you every file it will
|
|
249
|
+
touch first.
|
|
250
|
+
|
|
251
|
+
Each index edit keeps a copy of the whole `MEMORY.md` in the trash rather than a
|
|
252
|
+
note of which lines changed, so undo means writing back the exact bytes that were
|
|
253
|
+
there instead of recomputing them.
|
|
186
254
|
|
|
187
255
|
## Usage
|
|
188
256
|
|
|
@@ -215,8 +283,12 @@ claude-memory-admin --root /tmp/memory-snapshot
|
|
|
215
283
|
- `MEMORY.md` is replaced atomically (temp file, `fsync`, `rename`) with a backup
|
|
216
284
|
restored if anything throws.
|
|
217
285
|
- A test asserts that parsing and rewriting every real `MEMORY.md` with no
|
|
218
|
-
deletions reproduces it byte for byte
|
|
219
|
-
|
|
286
|
+
deletions reproduces it byte for byte, that rewriting a hook and putting the
|
|
287
|
+
original back does too, and that no edit ever disturbs a line it was not
|
|
288
|
+
aimed at. Real indexes are hand-written prose with headings and nested bullets,
|
|
289
|
+
and mangling one would be silent.
|
|
290
|
+
- Every index edit is guarded by the text the browser last saw, so an edit made
|
|
291
|
+
against a stale view is refused rather than applied to the wrong line.
|
|
220
292
|
|
|
221
293
|
## Development
|
|
222
294
|
|
|
@@ -226,26 +298,33 @@ cd claude-memory-admin
|
|
|
226
298
|
npm install
|
|
227
299
|
npm start # or: node server.mjs
|
|
228
300
|
npm test # runs on a throwaway copy of your real store
|
|
301
|
+
npm run dev:css # only when editing styles/app.css
|
|
229
302
|
```
|
|
230
303
|
|
|
231
|
-
No bundler and no build step: the backend is `node:http` plus `node:fs`,
|
|
232
|
-
frontend is plain ES modules the browser loads directly. Two runtime
|
|
233
|
-
`marked` and `dompurify`, both only for rendering memory bodies safely.
|
|
304
|
+
No bundler and no build step to run it: the backend is `node:http` plus `node:fs`,
|
|
305
|
+
and the frontend is plain ES modules the browser loads directly. Two runtime
|
|
306
|
+
dependencies, `marked` and `dompurify`, both only for rendering memory bodies safely.
|
|
307
|
+
|
|
308
|
+
Styling is the one thing that is compiled. `styles/app.css` is the Tailwind v4
|
|
309
|
+
source and `public/styles.css` is its committed output, so an installed copy is
|
|
310
|
+
ready to serve and never builds anything. After editing the source, run
|
|
311
|
+
`npm run build:css` and commit the result — CI rebuilds it and fails on drift.
|
|
234
312
|
|
|
235
313
|
| Path | Purpose |
|
|
236
314
|
| --- | --- |
|
|
237
315
|
| `bin/claude-memory-admin.mjs` | CLI entry point and argument parsing |
|
|
238
316
|
| `server.mjs` | HTTP server: static files + JSON API |
|
|
239
317
|
| `src/projects.mjs` | Project discovery, slug → real path resolution |
|
|
240
|
-
| `src/settings.mjs` | Layered reads of Claude Code's settings files |
|
|
318
|
+
| `src/settings.mjs` | Layered reads of Claude Code's settings files, and the report behind the Settings tab |
|
|
241
319
|
| `src/pathcache.mjs` | The opt-in record of confirmed project paths |
|
|
242
|
-
| `src/stores.mjs` | Store discovery: auto memory and the three agent scopes |
|
|
320
|
+
| `src/stores.mjs` | Store discovery: the user scope, auto memory and the three agent scopes |
|
|
243
321
|
| `src/instructions.mjs` | CLAUDE.md chain, `@` imports and rules resolution |
|
|
244
322
|
| `src/parse.mjs` | `MEMORY.md` and frontmatter parsers, wikilinks |
|
|
245
323
|
| `src/model.mjs` | Joins index, files, graph and health into one model |
|
|
246
324
|
| `src/stats.mjs` | Load-limit accounting and overlap detection |
|
|
247
325
|
| `src/search.mjs` | Full-text search across every store |
|
|
248
|
-
| `src/mutate.mjs` | Delete /
|
|
326
|
+
| `src/mutate.mjs` | Delete / edit / merge / restore, the only code that writes |
|
|
327
|
+
| `styles/app.css` | Tailwind source, compiled to `public/styles.css` |
|
|
249
328
|
| `public/` | Frontend |
|
|
250
329
|
|
|
251
330
|
Tests run against committed fixtures under `test/fixtures/`: a projects store
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-memory-admin",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Browse, audit and prune the auto memory Claude Code keeps under ~/.claude/projects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -54,10 +54,16 @@
|
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"start": "node bin/claude-memory-admin.mjs",
|
|
57
|
-
"test": "node --test test/*.test.mjs"
|
|
57
|
+
"test": "node --test test/*.test.mjs",
|
|
58
|
+
"build:css": "tailwindcss -i styles/app.css -o public/styles.css --minify",
|
|
59
|
+
"dev:css": "tailwindcss -i styles/app.css -o public/styles.css --watch",
|
|
60
|
+
"prepublishOnly": "npm run build:css"
|
|
58
61
|
},
|
|
59
62
|
"dependencies": {
|
|
60
63
|
"dompurify": "^3.2.7",
|
|
61
64
|
"marked": "^16.4.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@tailwindcss/cli": "^4.3.3"
|
|
62
68
|
}
|
|
63
69
|
}
|