stackmem 1.0.20 → 1.0.22
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 +81 -155
- package/dist/cli.js +404 -63
- package/dist/scoring.js +74 -0
- package/dist/tests/regression.test.js +248 -0
- package/package.json +3 -2
- package/src/cli.ts +443 -60
- package/src/scoring.ts +88 -0
- package/src/tests/regression.test.ts +304 -0
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# stackmem
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Persistent memory for AI coding agents. Zero config. Installs in 60 seconds.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## The problem
|
|
6
|
+
|
|
7
|
+
Every session with an AI coding agent starts from zero. You re-explain the same stack, the same constraints, the same "we tried that and it didn't work" — and the agent repeats mistakes it already made last week, because nothing it learned last session survived the chat closing.
|
|
6
8
|
|
|
7
9
|
## Install
|
|
8
10
|
|
|
@@ -10,196 +12,116 @@ stackmem is a CLI and an MCP server that stores that context in Supabase and han
|
|
|
10
12
|
npm install -g stackmem
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
cm init <project> .
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
`cm init <project> .` does three things automatically:
|
|
20
|
-
|
|
21
|
-
1. Installs a git post-commit hook
|
|
22
|
-
2. Registers the stackmem MCP server with Claude Code
|
|
23
|
-
3. Writes a CLAUDE.md to the project
|
|
24
|
-
|
|
25
|
-
After that, memories load automatically when you open Claude Code and save automatically on every commit. No further setup needed.
|
|
26
|
-
|
|
27
|
-
## Usage
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
cm start <project>
|
|
31
|
-
cm save <project> <type> <content> [--force]
|
|
32
|
-
cm fix <project> <problem> <solution>
|
|
33
|
-
cm analyze <project> <path>
|
|
34
|
-
cm search <project> <query>
|
|
35
|
-
cm resolve <project> <memory-id>
|
|
36
|
-
cm delete <project> <memory-id>
|
|
37
|
-
cm context <project> <task>
|
|
38
|
-
cm compress <project>
|
|
39
|
-
cm init <project> <path>
|
|
40
|
-
cm help
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### cm start
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
$ cm start myapp
|
|
47
|
-
Loaded 2 memory(ies) for "myapp".
|
|
48
|
-
|
|
49
|
-
Decisions (1)
|
|
50
|
-
-------------
|
|
51
|
-
[294fba3a-aef3-472a-933f-b6bfd41c7cfa] Use Supabase for persistence layer
|
|
52
|
-
linked: 793a0053-83b6-463a-9e6d-df8b7c2fbed8
|
|
53
|
-
|
|
54
|
-
Constraints (1)
|
|
55
|
-
---------------
|
|
56
|
-
[793a0053-83b6-463a-9e6d-df8b7c2fbed8] Service role key must never be exposed to a client
|
|
57
|
-
linked: 294fba3a-aef3-472a-933f-b6bfd41c7cfa
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### cm save
|
|
61
|
-
|
|
62
|
-
`type` is one of `decision`, `rejection`, `constraint`, `discovery`.
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
$ cm save myapp decision "Use ilike search across memories and execution_log"
|
|
66
|
-
Saved decision [294fba3a-aef3-472a-933f-b6bfd41c7cfa] for "myapp".
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
If the new content contradicts something already stored, it asks first.
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
$ cm save myapp decision "We switched from Supabase to Postgres directly"
|
|
73
|
-
Conflict detected:
|
|
74
|
-
Old: Use Supabase for persistence layer
|
|
75
|
-
New: We switched from Supabase to Postgres directly
|
|
76
|
-
|
|
77
|
-
Keep old or replace? (k/r): r
|
|
78
|
-
Replaced with new memory [b1a2c3d4-5678-90ab-cdef-1234567890ab].
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
`--force` skips the prompt and always replaces. Use it from scripts.
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
$ cm save myapp decision "We switched from Supabase to Postgres directly" --force
|
|
85
|
-
Replaced with new memory [b1a2c3d4-5678-90ab-cdef-1234567890ab].
|
|
86
|
-
Saved decision [b1a2c3d4-5678-90ab-cdef-1234567890ab] for "myapp".
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### cm fix
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
$ cm fix myapp "tsc failed with Node16 module resolution error" "switched moduleResolution to Node16"
|
|
93
|
-
Fix recorded for "myapp".
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### cm analyze
|
|
15
|
+
## Setup
|
|
97
16
|
|
|
98
17
|
```
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
functions: 24
|
|
102
|
-
classes: 0
|
|
18
|
+
cd myproject
|
|
19
|
+
cm init myapp .
|
|
103
20
|
```
|
|
104
21
|
|
|
105
|
-
Runs tree-sitter over the project and writes an AST index to `.coding-memory/ast-index.db`.
|
|
106
|
-
|
|
107
|
-
### cm search
|
|
108
|
-
|
|
109
|
-
Checks memories and past fixes in the same query.
|
|
110
|
-
|
|
111
22
|
```
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
23
|
+
✓ .gitignore created
|
|
24
|
+
✓ Git hook installed
|
|
25
|
+
✓ MCP server registered
|
|
26
|
+
✓ CLAUDE.md written
|
|
27
|
+
✓ .cursorrules written
|
|
28
|
+
✓ .windsurfrules written
|
|
29
|
+
✓ Seeded 2 memories from project scan
|
|
30
|
+
✓ Backend connection verified
|
|
115
31
|
|
|
116
|
-
|
|
117
|
-
Problem: tsc failed with Node16 module resolution error
|
|
118
|
-
Solution: switched moduleResolution to Node16
|
|
32
|
+
stackmem is live. Open Claude Code and ask "what do you know about this project?" to verify.
|
|
119
33
|
```
|
|
120
34
|
|
|
121
|
-
|
|
35
|
+
That's it. Open Claude Code and ask "what do you know about this project?" to verify.
|
|
122
36
|
|
|
123
|
-
|
|
124
|
-
$ cm resolve myapp 294fba3a-aef3-472a-933f-b6bfd41c7cfa
|
|
125
|
-
Resolved memory [294fba3a-aef3-472a-933f-b6bfd41c7cfa]
|
|
37
|
+
## How it works
|
|
126
38
|
|
|
127
|
-
|
|
128
|
-
Deleted memory [793a0053-83b6-463a-9e6d-df8b7c2fbed8]
|
|
129
|
-
```
|
|
39
|
+
Four layers, each feeding the next:
|
|
130
40
|
|
|
131
|
-
|
|
41
|
+
- **Capture** — a git post-commit hook saves memories automatically on every commit: removed dependencies, new config files, auth-related files, TODOs, schema changes, and the commit message itself when it's substantive. No manual annotation. **97.9% automation rate** across stackmem's own real development history.
|
|
42
|
+
- **Semantic organization** — hybrid containment-trigram scoring deduplicates new memories against existing ones, links related memories bidirectionally, and resolves contradictions ("we switched from X to Y") automatically.
|
|
43
|
+
- **Temporal ranking** — an exponential decay score ranks memories by recency and access frequency, then a 2000-token budget decides what actually gets injected.
|
|
44
|
+
- **Delivery** — an MCP server, an 18-command CLI, and the Memory Vault web dashboard all read from the same store and deliver it back into every new session.
|
|
132
45
|
|
|
133
|
-
|
|
46
|
+
## Claude Code (automatic)
|
|
134
47
|
|
|
135
|
-
|
|
136
|
-
$ cm context myapp "fix the module resolution error in the build"
|
|
137
|
-
## Project Context: myapp
|
|
138
|
-
### Task: fix the module resolution error in the build
|
|
48
|
+
`cm init` registers the stackmem MCP server in `~/.claude.json`. Memories load automatically at the start of every session — nothing to configure, nothing to remember to run.
|
|
139
49
|
|
|
140
|
-
|
|
141
|
-
- Service role key must never be exposed to a client
|
|
50
|
+
## Cursor and Windsurf (automatic)
|
|
142
51
|
|
|
143
|
-
|
|
144
|
-
- schema change: migrations/003_add_access_count.sql
|
|
52
|
+
`cm init` writes `.cursorrules` and `.windsurfrules` directly from your project's live memories, and the git hook keeps them current — `cm sync` regenerates and commits both files automatically after every push. You never have to remember to refresh them by hand.
|
|
145
53
|
|
|
146
|
-
*(41/2000 tokens used)*
|
|
147
54
|
```
|
|
55
|
+
# stackmem — project memory (auto-updated)
|
|
56
|
+
## Project: myapp
|
|
148
57
|
|
|
149
|
-
|
|
58
|
+
### Constraints
|
|
59
|
+
- required env vars: DATABASE_URL, API_KEY
|
|
150
60
|
|
|
151
|
-
###
|
|
61
|
+
### Discoveries
|
|
62
|
+
- tech stack: express
|
|
152
63
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Compressed 3 memories into 1 summary
|
|
157
|
-
Compression complete. 2 clusters compressed.
|
|
64
|
+
---
|
|
65
|
+
*Last updated: 10/13/2026, 5:37:45 PM*
|
|
66
|
+
*Run `cm start` for full details with decay scores*
|
|
158
67
|
```
|
|
159
68
|
|
|
160
|
-
|
|
69
|
+
## CLI commands (all 18)
|
|
161
70
|
|
|
162
|
-
|
|
71
|
+
| Command | Description |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `cm start [project]` | Load all unresolved memories, decay-ranked and budget-capped, grouped by type with linked memory ids. |
|
|
74
|
+
| `cm save [project] <type> <content>` | Save a new memory (`decision`, `constraint`, `discovery`, or `rejection`). Links to related memories automatically; prompts on contradiction unless `--force`. |
|
|
75
|
+
| `cm fix [project] <problem> <solution>` | Record a problem and its solution for future reference. |
|
|
76
|
+
| `cm analyze [project] <path>` | Build a Tree-Sitter AST index (files, functions, classes) for the codebase. |
|
|
77
|
+
| `cm search [--project <name>] <query>` | Search memories and past fixes for a project matching a query. |
|
|
78
|
+
| `cm resolve [project] <memory-id>` | Mark a memory as resolved. |
|
|
79
|
+
| `cm delete [project] <memory-id>` | Delete a memory and any links referencing it. |
|
|
80
|
+
| `cm inspect [project] <memory-id>` | Show a single memory's full detail: type, content, decay score, access count, linked memories, and related fixes. |
|
|
81
|
+
| `cm compress [project]` | Cluster related memories (needs 20+) and collapse clusters of 3+ into a summary memory. |
|
|
82
|
+
| `cm init <project> <path>` | Install the git hook, register the MCP server, seed memories from the project scan, and write `.gitignore`, `CLAUDE.md`, `.cursorrules`, and `.windsurfrules`. |
|
|
83
|
+
| `cm sync` | Regenerate `.cursorrules` and `.windsurfrules` from current memories and recent fixes. |
|
|
84
|
+
| `cm context [--project <name>] <task>` | Return the top 5 memories most relevant to a specific task, capped at 2000 tokens. |
|
|
85
|
+
| `cm session-end [project]` | Capture what happened in a session and extract memories, errors, and rejected approaches. |
|
|
86
|
+
| `cm doctor` | Check every integration point — backend, MCP registration, `.stackmem`, git hook, memory count — and report what's broken. |
|
|
87
|
+
| `cm undo [project]` | Delete the most recently saved unresolved memory. |
|
|
88
|
+
| `cm export [filename]` | Export all unresolved memories, fixes, and links to a JSON file. |
|
|
89
|
+
| `cm import [project] <filename>` | Import memories and fixes from a file produced by `cm export`. |
|
|
90
|
+
| `cm help` | Show the full help message. |
|
|
163
91
|
|
|
164
|
-
|
|
165
|
-
$ cm init myapp .
|
|
166
|
-
coding-memory hook installed for project myapp at .
|
|
167
|
-
```
|
|
92
|
+
## The Memory Vault
|
|
168
93
|
|
|
169
|
-
|
|
94
|
+
`stackmem-vault.vercel.app`
|
|
170
95
|
|
|
171
|
-
|
|
96
|
+
Sign in with GitHub. View every project you track, each with its memory count and last activity. Four tabs per project: **Memories** (typed, with decay scores and resolve/delete actions), **Fixes** (problem/solution pairs), **Graph** (a D3.js force-directed view of your actual knowledge network — nodes are memories, edges are semantic links), and **Timeline** (every memory chronologically, including resolved ones). A global search bar queries memories and fixes across every project at once.
|
|
172
97
|
|
|
173
|
-
|
|
174
|
-
$ cm help
|
|
175
|
-
cm — coding memory CLI
|
|
98
|
+
## How memory works
|
|
176
99
|
|
|
177
|
-
|
|
178
|
-
Load all unresolved memories for a project, sorted by decay
|
|
179
|
-
score and capped at a 2000 token context budget.
|
|
100
|
+
Memories are decisions, constraints, discoveries, and rejections, scoped to a project. Fixes are stored separately as a problem string and the solution that closed it, so the same error doesn't cost another 20 minutes next month.
|
|
180
101
|
|
|
181
|
-
|
|
182
|
-
Save a new memory. Prompts before overwriting a contradiction
|
|
183
|
-
unless --force is passed.
|
|
102
|
+
Every save checks new content against existing memories with a **hybrid score**: 0.7 × entity containment (shared terms over the size of the smaller set) + 0.3 × character-trigram Jaccard overlap. The trigram component catches lexical near-misses that containment alone can't — e.g. `"removed dependency: node:path"` vs `"removed dependency: node:url"`, which share identical entity sets but diverge in the actual package name. Above 0.85 with no negation word, it's a duplicate and gets skipped. With a negation word like "switched" or "no longer" and a score above 0.4, it's a contradiction.
|
|
184
103
|
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
## How it works
|
|
104
|
+
`cm save` stops and asks whether to keep the old memory or replace it, unless `--force` is passed. The MCP `save_memory` tool always replaces automatically, since nothing is watching stdin on that path.
|
|
189
105
|
|
|
190
|
-
|
|
106
|
+
New memories are also compared against everything else and linked above a lower threshold of 0.15, using the same hybrid score. `cm start` and `cm context` show those links without any manual tagging.
|
|
191
107
|
|
|
192
|
-
|
|
108
|
+
Relevance decays over time: `score = (1 + ln(1 + accessCount)) * exp(-0.05 * daysSinceCreated)`. Frequently accessed memories decay slower, but nothing survives forever. The 0.05 constant works out to roughly a 14-day half life.
|
|
193
109
|
|
|
194
|
-
cm
|
|
110
|
+
`cm start` and `cm context` cap output at 2000 tokens. They fill from the highest-ranked memory down until the next one would push past that limit.
|
|
195
111
|
|
|
196
|
-
|
|
112
|
+
Past 20 unresolved memories, `cm compress` clusters related memories by hybrid score above 0.2 using union-find. Clusters of 3 or more collapse into a single summary memory.
|
|
197
113
|
|
|
198
|
-
|
|
114
|
+
## Benchmark results
|
|
199
115
|
|
|
200
|
-
|
|
116
|
+
Measured against stackmem's own real production data — not synthetic fixtures.
|
|
201
117
|
|
|
202
|
-
|
|
118
|
+
| Metric | Result |
|
|
119
|
+
|---|---|
|
|
120
|
+
| Token reduction vs. full codebase dump | 99.4% (36,579 → 226 tokens) |
|
|
121
|
+
| Duplicate detection F1 | 0.974 (P=1.00, R=0.95) |
|
|
122
|
+
| Contradiction detection F1 | 0.947 (P=1.00, R=0.90) |
|
|
123
|
+
| Semantic linking SNR | 7.8x (linked: 0.69, random: 0.09) |
|
|
124
|
+
| Automation rate | 97.9% (47/48 memories auto-captured) |
|
|
203
125
|
|
|
204
126
|
## Research
|
|
205
127
|
|
|
@@ -210,3 +132,7 @@ Ideas taken from a few papers, not implementations of them.
|
|
|
210
132
|
- A-MEM: Agentic Memory for LLM Agents (arXiv:2502.12110, NeurIPS 2025)
|
|
211
133
|
- SWE-MeM: Learning Adaptive Memory Management for Long-Horizon Coding Agents (arXiv:2606.28434)
|
|
212
134
|
- AtomMem: Learnable Dynamic Agentic Memory with Atomic Memory Operation (arXiv:2601.08323)
|
|
135
|
+
|
|
136
|
+
## Paper
|
|
137
|
+
|
|
138
|
+
[stackmem: MCP, Tree-Sitter AST Graphs, Hybrid Containment-Trigram Scoring, and Temporal Decay for Persistent AI Coding Agent Memory](https://github.com/arushlagudu/coding-memory/blob/main/docs/paper.pdf)
|