claude-memory-admin 1.0.0 → 1.0.1

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 CHANGED
@@ -3,7 +3,8 @@
3
3
  [![CI](https://github.com/linkdotnet/claude-memory-admin/actions/workflows/ci.yml/badge.svg)](https://github.com/linkdotnet/claude-memory-admin/actions/workflows/ci.yml)
4
4
  [![npm](https://img.shields.io/npm/v/claude-memory-admin)](https://www.npmjs.com/package/claude-memory-admin)
5
5
 
6
- Browse, audit and prune the **auto memory** Claude Code writes for each project.
6
+ Browse, audit and prune the memory Claude Code writes for itself: the **auto
7
+ memory** kept per project, and the **subagent memory** kept per agent.
7
8
 
8
9
  ```bash
9
10
  npm install -g claude-memory-admin
@@ -13,6 +14,11 @@ claude-memory-admin
13
14
  It opens `http://localhost:4173` and reads `~/.claude/projects/*/memory/`.
14
15
  Nothing leaves your machine; the server binds `127.0.0.1` only.
15
16
 
17
+ This project is built heavily with AI tooling: most of the code, the tests
18
+ and this README were written by Claude Code, with a human directing the design
19
+ and reviewing what landed. Fitting for a tool about what Claude writes for
20
+ itself, and worth saying out loud.
21
+
16
22
  <sub>Brought to you by [BitSpire](https://bitspire.ch/).</sub>
17
23
 
18
24
  ---
@@ -37,6 +43,21 @@ Claude Code keeps two kinds of memory. This tool is about the second one:
37
43
  | Lives in | `./CLAUDE.md`, `~/.claude/CLAUDE.md` | `~/.claude/projects/<project>/memory/` |
38
44
  | Contains | rules and instructions | learnings Claude picked up |
39
45
 
46
+ Subagents declaring `memory:` in their frontmatter get their own directories,
47
+ which hold exactly the same thing under a different name, so they are shown
48
+ alongside the projects:
49
+
50
+ | Scope | Lives in |
51
+ | --- | --- |
52
+ | `user` | `~/.claude/agent-memory/<agent>/` |
53
+ | `project` | `<repo>/.claude/agent-memory/<agent>/` |
54
+ | `local` | `<repo>/.claude/agent-memory-local/<agent>/` |
55
+
56
+ The project-scoped ones are found under the repositories this tool already
57
+ resolved from your session transcripts, so it never goes looking through
58
+ directories it has no reason to believe in. A `project`-scoped store is checked
59
+ into git, and the app says so before you delete anything from one.
60
+
40
61
  The auto memory directory holds `MEMORY.md` (a concise index) plus one topic
41
62
  file per memory, cross-linked with `[[wikilinks]]`.
42
63
 
@@ -51,8 +72,23 @@ project is to the cliff, and makes it quick to get back under it.
51
72
  (`-Users-me-repos-Blog`) and the slugification is lossy. The true path is
52
73
  recovered from the `cwd` field in the session transcripts stored next to each
53
74
  memory directory; anything that cannot be confirmed is shown as the raw slug
54
- rather than a plausible guess. `autoMemoryDirectory` in `~/.claude/settings.json`
55
- is honoured if you have moved the store.
75
+ rather than a plausible guess. Claude Code keys the store on the git
76
+ repository, so one memory directory serves every worktree and subdirectory of
77
+ a repo: when the transcripts disagree, the repository root wins and the other
78
+ directories are listed under the project name.
79
+ - **A store keeps its name after its evidence expires.** Claude Code sweeps
80
+ session transcripts on a retention period but never touches `memory/`, so a
81
+ project eventually loses the only proof of what it was called. **Remember
82
+ path** records one you confirm, and is the single thing this app writes
83
+ outside a `memory/` directory.
84
+ - **Where the store is** is read the way Claude Code reads it: `autoMemoryDirectory`
85
+ from any settings layer, managed policy through project and local, not just
86
+ `~/.claude/settings.json`. A value that is neither absolute nor `~/`-prefixed
87
+ is reported rather than quietly ignored.
88
+ - **Whether Claude is still writing.** A project with `autoMemoryEnabled` off, or
89
+ `CLAUDE_CODE_DISABLE_AUTO_MEMORY` set, has a store that will never grow again,
90
+ which on disk is indistinguishable from one Claude has not learned anything
91
+ about yet. The project header says which it is, and names the file that decided.
56
92
  - **Search across every project**: names, descriptions, bodies and index hooks,
57
93
  with snippets and match highlighting. Press `/` to jump to it.
58
94
  - **Read each memory** with its frontmatter as structured metadata and
@@ -62,8 +98,19 @@ project is to the cliff, and makes it quick to get back under it.
62
98
  a neighbour, which is the only practical way to read a dense cluster.
63
99
  - **Health**: orphans, dangling pointers, broken wikilinks, files linked only
64
100
  mid-sentence, `name` fields that disagree with the filename.
101
+ - **Dates you can trust.** Claude Code stamps `modified` into frontmatter, but
102
+ only on files that already have some, and never adds frontmatter to a file
103
+ without it. Anything falling back to the file's mtime is labelled, because
104
+ mtime is reset by any copy or restore.
105
+ - **Context**: what a session starting in this project would load as
106
+ *instructions*, which is the other half of the startup budget (see below).
65
107
  - **Delete with cascade**, always reversible.
66
108
 
109
+ Everything above works the same on both kinds of store. The load meter, graph,
110
+ health checks and trash never needed to know which they were reading: a subagent
111
+ memory directory is a `MEMORY.md` index plus topic files under the same 200-line
112
+ / 25KB limit.
113
+
67
114
  ## Keeping MEMORY.md small
68
115
 
69
116
  The **Prune** tab exists because a bloated index costs tokens on every single
@@ -72,6 +119,10 @@ session and, past the limit, silently stops loading.
72
119
  - **Load meter**. How much of the 200-line / 25KB budget the index uses, and
73
120
  which of the two is binding. Frontmatter and HTML comments are excluded,
74
121
  because Claude Code strips those before loading.
122
+ - **The cutoff, drawn where it falls**. Past the limit, the MEMORY.md tab rules a
123
+ line across the file and dims everything below it, and Prune names the memories
124
+ 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.
75
126
  - **Long hooks**. The hook is the text after the dash in `MEMORY.md`. A
76
127
  400-character hook can cost more than the memory it points at, and shortening
77
128
  it is the cheapest win available.
@@ -84,6 +135,36 @@ session and, past the limit, silently stops loading.
84
135
  Anthropic's own guidance for the index: one line per entry, detail in the topic
85
136
  files, merge or drop stale entries.
86
137
 
138
+ ## The other half of the budget
139
+
140
+ `MEMORY.md` is not the only thing loaded at the start of every session. The
141
+ **Context** tab resolves what else is, in load order: managed policy, your
142
+ `~/.claude/CLAUDE.md` and `~/.claude/rules/`, every `CLAUDE.md` and
143
+ `CLAUDE.local.md` from the filesystem root down to the project, `.claude/CLAUDE.md`,
144
+ and `.claude/rules/`, with `@path` imports expanded and `claudeMdExcludes` applied.
145
+
146
+ Unlike `MEMORY.md`, none of it is truncated: `CLAUDE.md` files load in full
147
+ however long they are. So the tab reports cost rather than a cliff, and separates
148
+ what every session pays for from the path-scoped rules that only load on a match.
149
+
150
+ It also finds the failures that leave a file silently doing nothing:
151
+
152
+ - Imports that do not resolve, chains past the four-hop maximum, and cycles.
153
+ - Imports resolving outside the project, which Claude Code asks you to approve
154
+ once and which stay disabled if you decline.
155
+ - A `paths:` glob with a `[` that cannot be read as a bracket expression. It is
156
+ invalid, so it matches nothing and the rule never applies.
157
+ - Brace expansion past the 1,000-pattern budget, where the pattern is used
158
+ unexpanded and its literal braces match no file either.
159
+ - An `AGENTS.md` that no `CLAUDE.md` imports. Claude Code reads `CLAUDE.md`.
160
+
161
+ Backticks are respected, so a `` `@README` `` in your prose is not reported as an
162
+ import, and neither is an email address.
163
+
164
+ This is re-derived from the documented resolution rules rather than reported by
165
+ Claude Code, and the tab says so. Run `/context` in a session for the ground
166
+ truth, or the `InstructionsLoaded` hook to log exactly what loaded and why.
167
+
87
168
  ## Deleting is reversible
88
169
 
89
170
  Delete shows a preview first: the exact lines that will go, the prose mentions it
@@ -127,6 +208,10 @@ claude-memory-admin --root /tmp/memory-snapshot
127
208
  - Binds `127.0.0.1`; no telemetry, no network calls.
128
209
  - Every write target must resolve to a plain `.md` file inside that project's own
129
210
  `memory/` directory. `..`, absolute paths and subdirectories are refused.
211
+ - One exception, and only when you ask for it: **Remember path** writes
212
+ `~/.claude-memory-admin/paths.json`. It holds folder slugs and the directory
213
+ paths you confirmed, never memory content, and forgetting the last entry
214
+ deletes the file. Nothing creates it until you use the action.
130
215
  - `MEMORY.md` is replaced atomically (temp file, `fsync`, `rename`) with a backup
131
216
  restored if anything throws.
132
217
  - A test asserts that parsing and rewriting every real `MEMORY.md` with no
@@ -152,15 +237,21 @@ frontend is plain ES modules the browser loads directly. Two runtime dependencie
152
237
  | `bin/claude-memory-admin.mjs` | CLI entry point and argument parsing |
153
238
  | `server.mjs` | HTTP server: static files + JSON API |
154
239
  | `src/projects.mjs` | Project discovery, slug → real path resolution |
240
+ | `src/settings.mjs` | Layered reads of Claude Code's settings files |
241
+ | `src/pathcache.mjs` | The opt-in record of confirmed project paths |
242
+ | `src/stores.mjs` | Store discovery: auto memory and the three agent scopes |
243
+ | `src/instructions.mjs` | CLAUDE.md chain, `@` imports and rules resolution |
155
244
  | `src/parse.mjs` | `MEMORY.md` and frontmatter parsers, wikilinks |
156
245
  | `src/model.mjs` | Joins index, files, graph and health into one model |
157
246
  | `src/stats.mjs` | Load-limit accounting and overlap detection |
158
- | `src/search.mjs` | Full-text search across projects |
247
+ | `src/search.mjs` | Full-text search across every store |
159
248
  | `src/mutate.mjs` | Delete / restore / unlink, the only code that writes |
160
249
  | `public/` | Frontend |
161
250
 
162
- Tests run against a committed fixture store under `test/fixtures/store/`, which
163
- encodes the awkward shapes real memory directories contain. Your own
251
+ Tests run against committed fixtures under `test/fixtures/`: a projects store
252
+ encoding the awkward shapes real memory directories contain, including one index
253
+ deliberately past the load limit, an `agents/` tree covering all three subagent
254
+ scopes, and an `instructions/` tree covering the import and glob edge cases. Your own
164
255
  `~/.claude/projects` is additionally checked when it exists, always on a
165
256
  throwaway copy.
166
257
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-memory-admin",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Browse, audit and prune the auto memory Claude Code keeps under ~/.claude/projects",
5
5
  "keywords": [
6
6
  "claude",