@saleem11kh/repomem 0.3.1 → 0.5.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 +655 -212
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +230 -14
- package/dist/cli.js.map +1 -1
- package/dist/config/config.d.ts +20 -0
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +1 -0
- package/dist/config/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/store/adr.d.ts +22 -0
- package/dist/store/adr.d.ts.map +1 -0
- package/dist/store/adr.js +201 -0
- package/dist/store/adr.js.map +1 -0
- package/dist/store/capture.d.ts +39 -0
- package/dist/store/capture.d.ts.map +1 -0
- package/dist/store/capture.js +148 -0
- package/dist/store/capture.js.map +1 -0
- package/dist/store/embeddings.d.ts +34 -0
- package/dist/store/embeddings.d.ts.map +1 -0
- package/dist/store/embeddings.js +250 -0
- package/dist/store/embeddings.js.map +1 -0
- package/dist/store/file-store.d.ts +26 -1
- package/dist/store/file-store.d.ts.map +1 -1
- package/dist/store/file-store.js +105 -16
- package/dist/store/file-store.js.map +1 -1
- package/dist/store/git.d.ts +46 -0
- package/dist/store/git.d.ts.map +1 -0
- package/dist/store/git.js +131 -0
- package/dist/store/git.js.map +1 -0
- package/dist/store/profile.d.ts +18 -0
- package/dist/store/profile.d.ts.map +1 -0
- package/dist/store/profile.js +345 -0
- package/dist/store/profile.js.map +1 -0
- package/dist/tools/mem-context.d.ts.map +1 -1
- package/dist/tools/mem-context.js +249 -33
- package/dist/tools/mem-context.js.map +1 -1
- package/dist/tools/mem-handoff.d.ts.map +1 -1
- package/dist/tools/mem-handoff.js +53 -5
- package/dist/tools/mem-handoff.js.map +1 -1
- package/dist/tools/mem-save.d.ts +5 -0
- package/dist/tools/mem-save.d.ts.map +1 -1
- package/dist/tools/mem-save.js +60 -2
- package/dist/tools/mem-save.js.map +1 -1
- package/dist/tools/mem-search.d.ts.map +1 -1
- package/dist/tools/mem-search.js +26 -14
- package/dist/tools/mem-search.js.map +1 -1
- package/dist/tools/session.d.ts +40 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +159 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/util.d.ts +8 -1
- package/dist/tools/util.d.ts.map +1 -1
- package/dist/tools/util.js +7 -0
- package/dist/tools/util.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,212 +1,655 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
# repomem
|
|
4
|
-
|
|
5
|
-
**Git-native memory for AI coding agents.**
|
|
6
|
-
|
|
7
|
-
`.repomem/` lives in your repo. Commits with your code. Clones with your team.
|
|
8
|
-
Works with Claude Code, Cursor, Gemini CLI, Codex — any MCP-compatible agent.
|
|
9
|
-
|
|
10
|
-
[](https://www.npmjs.com/package/@saleem11kh/repomem)
|
|
11
|
-
[](./LICENSE)
|
|
12
|
-
[](https://github.com/saleem786khan/repomem)
|
|
13
|
-
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## The problem
|
|
19
|
-
|
|
20
|
-
Every AI coding session starts from zero.
|
|
21
|
-
|
|
22
|
-
You spend the first 10–15 minutes re-explaining your folder structure, your deployment order, what your team decided last week, which patterns to use, which ones to avoid. Your teammate picks up your work and has no idea what Claude was told. You switch from Claude Code to Cursor and lose all context. You start a new session on a different machine and rediscover everything from scratch.
|
|
23
|
-
|
|
24
|
-
CLAUDE.md helps — but it's static. It doesn't capture what was done yesterday, decisions made mid-session, or work-in-progress state. claude-mem and Engram are personal — they don't sync with your team and don't travel with the repo.
|
|
25
|
-
|
|
26
|
-
**The root problem: memory lives in the tool, not in the project.**
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## The solution
|
|
31
|
-
|
|
32
|
-
repomem puts memory where code already lives — in the git repo.
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
your-project/
|
|
36
|
-
└── .repomem/
|
|
37
|
-
├── decisions/ ← architectural choices + why
|
|
38
|
-
├── sessions/ ← what was done, what's next
|
|
39
|
-
├── patterns/ ← reusable conventions for this codebase
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# repomem
|
|
4
|
+
|
|
5
|
+
**Git-native memory for AI coding agents.**
|
|
6
|
+
|
|
7
|
+
`.repomem/` lives in your repo. Commits with your code. Clones with your team.
|
|
8
|
+
Works with Claude Code, Cursor, Gemini CLI, Codex — any MCP-compatible agent.
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.com/package/@saleem11kh/repomem)
|
|
11
|
+
[](./LICENSE)
|
|
12
|
+
[](https://github.com/saleem786khan/repomem)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## The problem
|
|
19
|
+
|
|
20
|
+
Every AI coding session starts from zero.
|
|
21
|
+
|
|
22
|
+
You spend the first 10–15 minutes re-explaining your folder structure, your deployment order, what your team decided last week, which patterns to use, which ones to avoid. Your teammate picks up your work and has no idea what Claude was told. You switch from Claude Code to Cursor and lose all context. You start a new session on a different machine and rediscover everything from scratch.
|
|
23
|
+
|
|
24
|
+
CLAUDE.md helps — but it's static. It doesn't capture what was done yesterday, decisions made mid-session, or work-in-progress state. claude-mem and Engram are personal — they don't sync with your team and don't travel with the repo.
|
|
25
|
+
|
|
26
|
+
**The root problem: memory lives in the tool, not in the project.**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## The solution
|
|
31
|
+
|
|
32
|
+
repomem puts memory where code already lives — in the git repo.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
your-project/
|
|
36
|
+
└── .repomem/
|
|
37
|
+
├── decisions/ ← architectural choices + why
|
|
38
|
+
├── sessions/ ← what was done, what's next
|
|
39
|
+
├── patterns/ ← reusable conventions for this codebase
|
|
40
|
+
├── issues/ ← known gotchas, do-not-repeat mistakes
|
|
41
|
+
├── project.md ← auto-generated profile: stack, commands, layout
|
|
42
|
+
└── REPOMEM.md ← auto-generated index of everything above
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Plain markdown files. No database. No cloud. No vendor lock-in.
|
|
46
|
+
|
|
47
|
+
`git add .repomem/ && git commit` → your whole team has the memory.
|
|
48
|
+
`git clone` → new teammate inherits full project context on day one.
|
|
49
|
+
Switch agents → same memory, because it's in the repo, not the tool.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# 1. Install
|
|
57
|
+
npm install -g @saleem11kh/repomem
|
|
58
|
+
|
|
59
|
+
# 2. Scaffold .repomem/ in your project
|
|
60
|
+
cd your-project
|
|
61
|
+
repomem init
|
|
62
|
+
|
|
63
|
+
# 3. Wire it to your agent
|
|
64
|
+
repomem setup claude-code # or: cursor | gemini | codex
|
|
65
|
+
|
|
66
|
+
# 4. Restart the agent, then approve the server when prompted
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Step 4 is not optional.** MCP servers are loaded when the agent starts, so a server
|
|
70
|
+
wired mid-session does not exist in that session. Claude Code additionally requires
|
|
71
|
+
you to approve any server declared in a project's `.mcp.json` the first time you
|
|
72
|
+
launch with it.
|
|
73
|
+
|
|
74
|
+
Verify with `/mcp` — you should see `repomem` connected with six tools. There are no
|
|
75
|
+
slash commands to look for; MCP servers contribute **tools**, which never appear in
|
|
76
|
+
the `/` menu.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Usage
|
|
81
|
+
|
|
82
|
+
### The six tools
|
|
83
|
+
|
|
84
|
+
Your agent calls these; you don't type them.
|
|
85
|
+
|
|
86
|
+
| Tool | Arguments | What it does |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `mem_context` | `task?`, `budget?`, `brief?` | Session-start packet: the project profile, the last session, plus one-line summaries of decisions, patterns, and issues. Call it first. |
|
|
89
|
+
| `mem_get` | `file` | Expand one entry in full — by `type/filename`, bare filename, or `[[wikilink]]` slug. |
|
|
90
|
+
| `mem_search` | `query`, `linked?` | BM25 + recency ranked search across all memory, blended with semantic similarity when enabled. `linked=true` also searches linked repos and the workspace. |
|
|
91
|
+
| `mem_save` | `type`, `title`, `content`, `summary?`, `tags?`, `links?`, `supersedes?`, `session?` | Write a `decision`, `pattern`, `issue`, or `session` note. |
|
|
92
|
+
| `mem_handoff` | `summary`, `done?`, `next?`, `blockers?`, `session?`, `git?` | Close out a session so the next one picks up exactly where you left off. Fills in what changed from git. |
|
|
93
|
+
| `mem_prime` | — | Bootstrap memory on an existing repo from its `CLAUDE.md` / `README.md` / `docs/`. Run once when adopting. |
|
|
94
|
+
|
|
95
|
+
### Progressive disclosure — why context stays small
|
|
96
|
+
|
|
97
|
+
`mem_context` deliberately returns **one-line summaries**, not full bodies. It runs at
|
|
98
|
+
the start of every session; if it dumped everything, a repo with 50 memories would
|
|
99
|
+
burn thousands of tokens before your first message. See
|
|
100
|
+
[Capping the packet](#capping-the-packet) for hard limits.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
## Recent decisions
|
|
104
|
+
- BM25 + recency ranking instead of embeddings — Search is BM25 over raw markdown
|
|
105
|
+
with an exponential recency boost — no embeddings, zero extra deps.
|
|
106
|
+
(decisions/2026-07-26-bm25-recency-ranking-instead-of-embeddings.md)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The agent expands only what it needs with `mem_get`. This is why **every entry should
|
|
110
|
+
have a `summary`** — it's the only thing most future sessions will ever read.
|
|
111
|
+
|
|
112
|
+
### Scoping context to the task
|
|
113
|
+
|
|
114
|
+
Recency is a decent default on a young repo and a poor one on a mature repo — the
|
|
115
|
+
decision that bears on today's work is rarely the newest. Tell `mem_context` what the
|
|
116
|
+
session is about and it ranks by relevance instead:
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
mem_context({ task: "add rate limiting to the payments API" })
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
It uses the same BM25 + recency scoring as `mem_search`, so search and context can
|
|
123
|
+
never disagree about what matters. Entries that don't match the task aren't hidden —
|
|
124
|
+
they keep a zero score and fall back to recency order behind the ones that do. The
|
|
125
|
+
headings change to **Relevant decisions / patterns / issues**, because "Recent" would
|
|
126
|
+
be a lie once the list is relevance-ordered.
|
|
127
|
+
|
|
128
|
+
### Capping the packet
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
mem_context({ task: "rate limiting", budget: 800 })
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`budget` is an approximate token ceiling for the whole packet. The budget is split so
|
|
135
|
+
the prelude can't eat it: **25%** to the project profile, **35%** to the last session,
|
|
136
|
+
the remainder to memory entries. Without that split, a tight budget produced a packet
|
|
137
|
+
with a profile, a session, and no memory in it at all.
|
|
138
|
+
|
|
139
|
+
Entries are then shed lowest-relevance first until the rendered packet actually fits —
|
|
140
|
+
measured, not estimated. Whatever is dropped is always declared:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
_9 further entries not shown (token budget 800) — find them with mem_search._
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Below roughly 290 tokens a full packet cannot be built at all, so it degrades to the
|
|
147
|
+
brief one-line summary plus what a packet would have cost, rather than quietly
|
|
148
|
+
overshooting.
|
|
149
|
+
|
|
150
|
+
Even with no budget set, each type is capped at **20** entries — previously the cap
|
|
151
|
+
was 100, which on a long-lived repo was no cap at all.
|
|
152
|
+
|
|
153
|
+
### Semantic search (optional, off by default)
|
|
154
|
+
|
|
155
|
+
BM25 is precise when you know the vocabulary and useless when you don't — searching
|
|
156
|
+
`cmd` will never find an entry that only says `npx shim`. Embeddings close that gap.
|
|
157
|
+
|
|
158
|
+
**repomem ships no model and adds no dependency.** Bundling a local runtime would
|
|
159
|
+
mean a ~100MB download on install and infrastructure to provision, which is exactly
|
|
160
|
+
what this project exists to avoid. The provider is always something you already run:
|
|
161
|
+
|
|
162
|
+
```jsonc
|
|
163
|
+
// repomem.config.json — Ollama, the common local setup
|
|
164
|
+
{
|
|
165
|
+
"semantic": { "provider": "ollama", "model": "nomic-embed-text" }
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```jsonc
|
|
170
|
+
// …or any OpenAI-compatible endpoint
|
|
171
|
+
{
|
|
172
|
+
"semantic": {
|
|
173
|
+
"provider": "openai-compatible",
|
|
174
|
+
"url": "https://api.example.com/v1/embeddings",
|
|
175
|
+
"model": "text-embedding-3-small",
|
|
176
|
+
"apiKeyEnv": "EMBEDDINGS_API_KEY"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```jsonc
|
|
182
|
+
// …or anything at all: reads text on stdin, prints a JSON array of floats
|
|
183
|
+
{
|
|
184
|
+
"semantic": { "provider": "command", "command": "./my-embedder.sh" }
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Then build the index:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
repomem embed # ✔ Vector cache updated — 12 embedded, 0 reused
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Re-run it after adding memory. Only entries whose content hash changed are
|
|
195
|
+
re-embedded, so a second run over an unchanged repo makes no provider calls at all.
|
|
196
|
+
|
|
197
|
+
**How results combine.** Semantic scores are blended with BM25, not substituted for
|
|
198
|
+
it — `blend` (default `0.5`) is the semantic share. Entries only the vector index
|
|
199
|
+
found are appended, so a semantic hit can surface memory lexical search could never
|
|
200
|
+
reach. Both score sets are normalised to 0–1 first so neither dominates by scale.
|
|
201
|
+
|
|
202
|
+
**It never breaks search.** No config, a missing cache, a stale cache from a
|
|
203
|
+
different model, an unreachable provider, a provider that crashes — all degrade
|
|
204
|
+
silently to plain BM25. Search failing is always worse than search being less clever.
|
|
205
|
+
|
|
206
|
+
**Vectors are not memory.** The cache lives in `.repomem/.cache/` and is gitignored.
|
|
207
|
+
Memory is markdown that travels in git; a re-derivable float array is a local build
|
|
208
|
+
artifact, and committing one would put a model's output in your repo's history.
|
|
209
|
+
|
|
210
|
+
Check the state any time:
|
|
211
|
+
|
|
212
|
+
```console
|
|
213
|
+
$ repomem status
|
|
214
|
+
semantic ollama (nomic-embed-text) — 12 vector(s)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### A normal session
|
|
218
|
+
|
|
219
|
+
**At the start**, the agent calls `mem_context` and immediately knows what was worked
|
|
220
|
+
on last, the key decisions and why, the conventions for this codebase, and known
|
|
221
|
+
gotchas.
|
|
222
|
+
|
|
223
|
+
**During work**, you capture things as they happen:
|
|
224
|
+
|
|
225
|
+
> "Save that as a decision — include why we rejected the alternative."
|
|
226
|
+
|
|
227
|
+
**At the end:**
|
|
228
|
+
|
|
229
|
+
> "Run mem_handoff."
|
|
230
|
+
|
|
231
|
+
Then commit. Nothing is shared with your team until you do:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
git add .repomem/ && git commit -m "chore: update memory"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Making it automatic
|
|
238
|
+
|
|
239
|
+
The default flow depends on you remembering to ask. To remove that:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
repomem setup claude-code --hooks
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
This installs two lifecycle hooks in `.claude/settings.json`, merging with whatever
|
|
246
|
+
is already there:
|
|
247
|
+
|
|
248
|
+
| Hook | Runs | Effect |
|
|
249
|
+
|---|---|---|
|
|
250
|
+
| `SessionStart` | `repomem context` | Every session opens warm — the profile, last session, and memory summaries load without the agent choosing to |
|
|
251
|
+
|
|
252
|
+
| `SessionEnd` | `repomem capture` | What changed is recorded whether or not anyone asked |
|
|
253
|
+
|
|
254
|
+
`repomem capture` writes a session file from git alone — no model, no tokens. It is
|
|
255
|
+
careful about noise:
|
|
256
|
+
|
|
257
|
+
- **Commits are events**, so anything in the window is new and always recorded.
|
|
258
|
+
- **Uncommitted files are state** — they survive from one capture to the next. They
|
|
259
|
+
are recorded once, then only again when the file set actually changes. Otherwise
|
|
260
|
+
hooking capture to every session end would fill `sessions/` with near-identical
|
|
261
|
+
files.
|
|
262
|
+
- Nothing changed means **nothing is written at all**.
|
|
263
|
+
- The summary says outright that no human wrote it, rather than inventing intent it
|
|
264
|
+
cannot know: *"No summary was written by hand, so the intent behind this work is not
|
|
265
|
+
recorded."*
|
|
266
|
+
|
|
267
|
+
A marker under `.repomem/.cache/` (gitignored) tracks the window between runs.
|
|
268
|
+
|
|
269
|
+
Edit the `SessionStart` command to `repomem context --budget 600` if you want a hard
|
|
270
|
+
ceiling on what gets injected into every session.
|
|
271
|
+
|
|
272
|
+
Both commands no-op silently outside a repomem project, so the hooks are safe to
|
|
273
|
+
install globally — a session in an unrelated repo is unaffected.
|
|
274
|
+
|
|
275
|
+
Hooks are a Claude Code feature. Cursor, Gemini CLI, and Codex have no equivalent
|
|
276
|
+
session lifecycle, so `--hooks` warns and skips for them. You can still wire
|
|
277
|
+
`repomem capture` to a shell alias, a cron, or a git hook.
|
|
278
|
+
|
|
279
|
+
⚠️ An auto-captured session records *what* changed, never *why*. It is a floor, not a
|
|
280
|
+
replacement for asking your agent to save a decision — that judgement is the part
|
|
281
|
+
worth keeping.
|
|
282
|
+
|
|
283
|
+
### What to say
|
|
284
|
+
|
|
285
|
+
repomem has no slash commands. You talk to your agent normally; it picks the tool.
|
|
286
|
+
|
|
287
|
+
| You want | Say |
|
|
288
|
+
|---|---|
|
|
289
|
+
| Load context | *"What's in repomem for this project?"* |
|
|
290
|
+
| Capture a choice | *"Save that as a decision, with why we rejected X"* |
|
|
291
|
+
| Capture a convention | *"Save that as a pattern"* |
|
|
292
|
+
| Capture a gotcha | *"Save that as an issue, with the guard against it"* |
|
|
293
|
+
| Replace a stale decision | *"Save this as a decision that supersedes `<filename>`"* |
|
|
294
|
+
| Sweep the whole session | *"Update repomem with what we did — skip anything obvious from the code"* |
|
|
295
|
+
| Close out | *"Run mem_handoff"* |
|
|
296
|
+
| Recall | *"Search repomem for how we handle retries"* |
|
|
297
|
+
|
|
298
|
+
Adding **"skip anything obvious from the code"** matters — otherwise you accumulate
|
|
299
|
+
entries restating function signatures, and the signal-to-noise ratio that makes memory
|
|
300
|
+
worth loading degrades.
|
|
301
|
+
|
|
302
|
+
### Adopting on an existing project
|
|
303
|
+
|
|
304
|
+
`repomem init` scans the repo as it scaffolds — no agent, no model, no API key:
|
|
305
|
+
|
|
306
|
+
```console
|
|
307
|
+
$ repomem init
|
|
308
|
+
✔ Created repomem.config.json (project: payments-service)
|
|
309
|
+
✔ Initialised .repomem/ with decisions, sessions, patterns, issues
|
|
310
|
+
|
|
311
|
+
✔ Wrote .repomem/project.md — 4 stack signal(s), 6 command(s), 9 top-level dir(s), git conventions
|
|
312
|
+
stack: Node.js + TypeScript, Express, Jest, Docker
|
|
313
|
+
✔ Imported 12 ADR(s) into decisions/
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Two things happen automatically.
|
|
317
|
+
|
|
318
|
+
**A project profile** is written to `.repomem/project.md` and inlined at the top of
|
|
319
|
+
every `mem_context` packet — the stack, how to build/test/lint, entry points, the
|
|
320
|
+
directory layout, CI workflows, plus conventions inferred from git history (commit
|
|
321
|
+
style, release tags, and the files that churn most). This is what an agent otherwise
|
|
322
|
+
rediscovers by globbing the tree at the start of every session.
|
|
323
|
+
|
|
324
|
+
**Existing ADRs are imported.** If your repo has `docs/adr/`, `adr/`,
|
|
325
|
+
`docs/decisions/`, or `rfcs/`, those files are already decision-shaped and are copied
|
|
326
|
+
straight into `decisions/` — title, status, and date preserved. Each records its
|
|
327
|
+
`source:`, so re-running skips what's already there instead of duplicating it.
|
|
328
|
+
|
|
329
|
+
Regenerate either at any time:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
repomem scan # refresh project.md, import any new ADRs
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**Prose docs still need judgement**, and that's what `mem_prime` is for. It gathers
|
|
336
|
+
`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `README.md`, and `docs/**.md` and returns them
|
|
337
|
+
with instructions to distil them into memory. Either ask your agent to call it, or
|
|
338
|
+
pipe it from the shell:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
repomem prime # print the packet
|
|
342
|
+
repomem prime | your-agent # or hand it straight to something
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
> "Call `mem_prime`, then save what it surfaces as decisions, patterns, and issues."
|
|
346
|
+
|
|
347
|
+
It **writes nothing itself** — distilling prose needs a model. Re-running is safe: it
|
|
348
|
+
reads the existing count first and is told not to duplicate.
|
|
349
|
+
|
|
350
|
+
If your project has no docs at all, the higher-value move is to point the agent at the
|
|
351
|
+
code:
|
|
352
|
+
|
|
353
|
+
> "Read the source under `src/`, then save what you learned as decisions, patterns,
|
|
354
|
+
> and issues. Give every entry a one-line summary and cross-link related entries."
|
|
355
|
+
|
|
356
|
+
Aim for 5–12 entries. Fewer and `mem_context` says nothing useful; many more in one
|
|
357
|
+
sitting and quality drops.
|
|
358
|
+
|
|
359
|
+
### Handoffs are half-derived
|
|
360
|
+
|
|
361
|
+
`mem_handoff` does not rely on the agent remembering what it touched. Since the
|
|
362
|
+
session knows when it started, repomem asks git directly:
|
|
363
|
+
|
|
364
|
+
```markdown
|
|
365
|
+
## 2026-07-26 14:30 — Handoff
|
|
366
|
+
|
|
367
|
+
Reworked how sessions are identified.
|
|
368
|
+
|
|
369
|
+
_branch: master_
|
|
370
|
+
|
|
371
|
+
**Committed this session:**
|
|
372
|
+
- 1038eb6 fix(cli): route MCP config through cmd.exe on Windows
|
|
373
|
+
- ce365ab chore(repomem): record the Windows MCP spawn gotcha
|
|
374
|
+
|
|
375
|
+
**Still uncommitted:**
|
|
376
|
+
- M src/tools/mem-context.ts
|
|
377
|
+
- ?? src/store/git.ts
|
|
378
|
+
|
|
379
|
+
**Next:**
|
|
380
|
+
- push the tag
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
The agent supplies only what git cannot know — *why*, and *what's next*. Commits and
|
|
384
|
+
uncommitted files are facts, and deriving them is both cheaper and more reliable than
|
|
385
|
+
asking a model to recall them.
|
|
386
|
+
|
|
387
|
+
Notes:
|
|
388
|
+
- Changes under `.repomem/` are filtered out; the handoff is writing there as it runs.
|
|
389
|
+
- Long lists are capped at 20 with an explicit `…and N more`, never silently truncated.
|
|
390
|
+
- Non-git projects, missing `git`, and empty repos all degrade quietly to a handoff
|
|
391
|
+
with no git detail. Pass `git: false` to skip it deliberately.
|
|
392
|
+
- Commits are matched by *time*, so parallel sessions each report the same commits.
|
|
393
|
+
Time is the only signal available without asking agents to tag their own work.
|
|
394
|
+
|
|
395
|
+
### Sessions and parallel agents
|
|
396
|
+
|
|
397
|
+
Each session owns one file:
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
.repomem/sessions/2026-07-26-0917-windows-mcp-fix.md
|
|
401
|
+
.repomem/sessions/2026-07-26-1430-auth-refactor.md
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
`YYYY-MM-DD-HHMM-<name>.md`, where the timestamp is when the session *started* — so it
|
|
405
|
+
stays put as the session appends, and because it's zero-padded, filename order is
|
|
406
|
+
chronological order.
|
|
407
|
+
|
|
408
|
+
Name a session by passing `session` to `mem_save` or `mem_handoff` (*"run mem_handoff,
|
|
409
|
+
call this session auth-refactor"*). Unnamed sessions are `untitled`; naming one later
|
|
410
|
+
renames the file in place, so one session always maps to one file.
|
|
411
|
+
|
|
412
|
+
This matters most when **more than one session runs at once** — two terminals, two
|
|
413
|
+
agents, or two teammates:
|
|
414
|
+
|
|
415
|
+
- Separate files mean no interleaving and **no git merge conflicts**
|
|
416
|
+
- Sessions are linkable: a decision can point at `[[auth-refactor]]`
|
|
417
|
+
- `mem_context` inlines the newest session and lists the others under **Also today**,
|
|
418
|
+
so parallel work is visible without being loaded in full
|
|
419
|
+
- The connecting agent is recorded automatically (`agent: claude-code`), taken from the
|
|
420
|
+
MCP handshake — so parallel sessions from different tools are tellable apart
|
|
421
|
+
|
|
422
|
+
### Anatomy of a memory file
|
|
423
|
+
|
|
424
|
+
```markdown
|
|
425
|
+
---
|
|
426
|
+
date: 2026-07-26
|
|
427
|
+
summary: Search is BM25 over raw markdown with a recency boost — no embeddings.
|
|
428
|
+
tags: [search, ranking]
|
|
429
|
+
---
|
|
430
|
+
# BM25 + recency ranking instead of embeddings
|
|
431
|
+
|
|
432
|
+
Why not embeddings: they add a model dependency and a cache to invalidate, which
|
|
433
|
+
breaks the "plain files, no infra" promise.
|
|
434
|
+
|
|
435
|
+
Related: [[memory-lives-in-the-repo-as-plain-markdown]]
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
- **`summary`** — the one line `mem_context` and `mem_search` show. Always set it.
|
|
439
|
+
- **`tags`** — free-form, for retrieval.
|
|
440
|
+
- **`supersedes`** — on a decision, the filename it replaces. Keeps the history.
|
|
441
|
+
- **`[[wikilinks]]`** — resolve by slug regardless of date prefix. `mem_search` and
|
|
442
|
+
`mem_context` traverse them and show `→ related:`, so linked entries travel together.
|
|
443
|
+
|
|
444
|
+
Filenames are `YYYY-MM-DD-<slug>.md`. The date prefix is load-bearing: it drives
|
|
445
|
+
newest-first ordering and the search recency boost.
|
|
446
|
+
|
|
447
|
+
### Editing and correcting
|
|
448
|
+
|
|
449
|
+
There's no update tool. Two paths:
|
|
450
|
+
|
|
451
|
+
- **Superseding a decision** — `mem_save` with `supersedes: <filename>` records the
|
|
452
|
+
replacement and keeps the history. This is the intended path.
|
|
453
|
+
- **Fixing a mistake** — just edit the markdown file. It's plain text in your repo.
|
|
454
|
+
|
|
455
|
+
⚠️ Saving twice on the same day with the same title **overwrites silently** — the
|
|
456
|
+
filename is `date-slug` and `slugify` truncates at 60 characters, so two long titles
|
|
457
|
+
sharing a prefix collide. Use short, distinct titles.
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## CLI reference
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
repomem Start the MCP server (stdio) — how agents invoke it
|
|
465
|
+
repomem init Scaffold .repomem/, then scan the repo
|
|
466
|
+
repomem scan Regenerate .repomem/project.md and import new ADRs
|
|
467
|
+
repomem prime Print the priming packet for an agent to distil
|
|
468
|
+
repomem embed Build the semantic vector cache (opt-in)
|
|
469
|
+
repomem context Print the session-start memory packet
|
|
470
|
+
[--brief] [--task <what>] [--budget <tokens>]
|
|
471
|
+
repomem capture Record what changed since the last capture
|
|
472
|
+
repomem setup <agent> Wire repomem into claude-code | cursor | gemini | codex
|
|
473
|
+
repomem setup <agent> --hooks
|
|
474
|
+
…and install session hooks (Claude Code only)
|
|
475
|
+
repomem status Show memory counts, configured agents, linked repos
|
|
476
|
+
repomem sync Export all memory to stdout
|
|
477
|
+
repomem import [file] Import a sync bundle (file or stdin) into .repomem/
|
|
478
|
+
repomem pull Fetch remote linked repos' memory from GitHub
|
|
479
|
+
repomem help Show this help
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
`init` is idempotent — re-running it regenerates `REPOMEM.md` without touching config.
|
|
483
|
+
|
|
484
|
+
`sync` and `import` are inverses, for airgapped transfer:
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
repomem sync > bundle.md # on the connected machine
|
|
488
|
+
repomem import bundle.md # on the airgapped one
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Where `setup` writes each agent's config:
|
|
492
|
+
|
|
493
|
+
| Agent | File |
|
|
494
|
+
|---|---|
|
|
495
|
+
| Claude Code | `.mcp.json` (repo root — **not** `.claude/mcp.json`) |
|
|
496
|
+
| Cursor | `.cursor/mcp.json` |
|
|
497
|
+
| Gemini CLI | `.gemini/settings.json` |
|
|
498
|
+
| Codex | `.codex/config.toml` |
|
|
499
|
+
|
|
500
|
+
On Windows the generated command is wrapped in `cmd /c`, because agents spawn MCP
|
|
501
|
+
servers without a shell and `npx` is a `.cmd` shim there. That makes the generated
|
|
502
|
+
config **host-specific** — a teammate on macOS or Linux should re-run `repomem setup`
|
|
503
|
+
to rewrite it.
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Multi-repo
|
|
508
|
+
|
|
509
|
+
Working across microservices? Declare related repos in `repomem.config.json`:
|
|
510
|
+
|
|
511
|
+
```jsonc
|
|
512
|
+
{
|
|
513
|
+
"project": "payments-service",
|
|
514
|
+
"workspace": "../repomem-workspace",
|
|
515
|
+
"linked": [
|
|
516
|
+
{ "repo": "../auth-service", "relation": "depends-on" },
|
|
517
|
+
{ "repo": "../shared-lib", "relation": "consumes" },
|
|
518
|
+
{ "repo": "github:acme/billing-svc", "relation": "depends-on" }
|
|
519
|
+
]
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Linked repos can be **local paths** or **remote GitHub repos** (`github:owner/name`,
|
|
524
|
+
optionally `#ref`). For remotes, run `repomem pull` once — it fetches only their
|
|
525
|
+
`.repomem/` subtree through the GitHub API into a local, gitignored cache. No full
|
|
526
|
+
clone. Set `GITHUB_TOKEN`/`GH_TOKEN` for private repos and higher rate limits.
|
|
527
|
+
|
|
528
|
+
Then `mem_search` with `linked=true` searches current + linked + remote + workspace,
|
|
529
|
+
ranked together and labelled by source:
|
|
530
|
+
|
|
531
|
+
```
|
|
532
|
+
[current] [linked:auth-service] [remote:billing-svc] [workspace]
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Pull is explicit and manual — nothing refreshes in the background.
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Troubleshooting
|
|
540
|
+
|
|
541
|
+
**"I don't see any repomem commands."**
|
|
542
|
+
Expected. MCP servers contribute tools, not slash commands. Check `/mcp` instead — it
|
|
543
|
+
should list `repomem` as connected with six tools.
|
|
544
|
+
|
|
545
|
+
**`/mcp` shows repomem as failed or missing.**
|
|
546
|
+
Three causes, in order of likelihood:
|
|
547
|
+
1. You haven't restarted the agent since running `repomem setup`.
|
|
548
|
+
2. The project's `.mcp.json` was never approved — the prompt only fires at startup.
|
|
549
|
+
3. You're on Windows with a config generated by repomem ≤ 0.3.0, which used a bare
|
|
550
|
+
`npx` command that cannot be spawned without a shell. Re-run `repomem setup`.
|
|
551
|
+
|
|
552
|
+
**Tools appear but every call says `.repomem/ not found`.**
|
|
553
|
+
The server resolves the project root by walking up for `.repomem/` or
|
|
554
|
+
`repomem.config.json`. Run `repomem init` at the repo root.
|
|
555
|
+
|
|
556
|
+
**Working on repomem itself?** Point `.mcp.json` at your local build so you exercise
|
|
557
|
+
your changes rather than the published package:
|
|
558
|
+
|
|
559
|
+
```json
|
|
560
|
+
{ "mcpServers": { "repomem": { "command": "node", "args": ["dist/cli.js"] } } }
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## Compared to alternatives
|
|
566
|
+
|
|
567
|
+
| | repomem | Engram | claude-mem | CLAUDE.md |
|
|
568
|
+
|---|---|---|---|---|
|
|
569
|
+
| Git-committed | ✅ | ❌ | ❌ | ✅ |
|
|
570
|
+
| Team-shared on clone | ✅ | ❌ | ❌ | ✅ |
|
|
571
|
+
| Captures session work | ✅ | ✅ | ✅ | ❌ |
|
|
572
|
+
| Multi-repo support | ✅ | ❌ | ❌ | ❌ |
|
|
573
|
+
| Multi-agent (any MCP) | ✅ | ✅ | ❌ | ✅ |
|
|
574
|
+
| No cloud / no vendor | ✅ | ❌ | ✅ | ✅ |
|
|
575
|
+
| Plain markdown files | ✅ | ❌ | ❌ | ✅ |
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## Roadmap
|
|
580
|
+
|
|
581
|
+
- [x] `repomem init` — scaffold `.repomem/` in any project
|
|
582
|
+
- [x] Six MCP tools (`mem_save`, `mem_search`, `mem_context`, `mem_get`, `mem_handoff`, `mem_prime`)
|
|
583
|
+
- [x] Claude Code, Cursor, Gemini CLI, and Codex wiring
|
|
584
|
+
- [x] Multi-repo `linked` support — local paths and remote GitHub repos
|
|
585
|
+
- [x] Workspace scope (cross-org shared memory repo)
|
|
586
|
+
- [x] `repomem sync` / `import` for airgapped transfer
|
|
587
|
+
- [x] BM25 + recency search ranking
|
|
588
|
+
- [x] Progressive disclosure — `mem_context` summaries + `mem_get` to expand
|
|
589
|
+
- [x] `[[wikilink]]` graph between memories
|
|
590
|
+
- [x] `mem_prime` — bootstrap memory from an existing repo's docs
|
|
591
|
+
- [x] One file per session, with names, timestamps, and agent attribution
|
|
592
|
+
- [x] Git-derived handoffs — "what changed" comes from commits, not recollection
|
|
593
|
+
- [x] `init` learns the repo — stack, commands, layout, ADRs, and git conventions, without an LLM
|
|
594
|
+
- [x] `repomem prime` as a CLI, so onboarding can be scripted end-to-end
|
|
595
|
+
- [x] Auto-capture hooks, so memory does not depend on remembering to ask
|
|
596
|
+
- [x] Task-scoped `mem_context` and a token budget, for repos with lots of memory
|
|
597
|
+
- [x] Optional semantic search layer (off by default, bring-your-own provider)
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
## Status
|
|
602
|
+
|
|
603
|
+
**v0.5.0 — working.** Ten CLI commands and six MCP tools, covered by 97 tests
|
|
604
|
+
including a full-lifecycle end-to-end run against the shipped artifact.
|
|
605
|
+
|
|
606
|
+
`repomem init` on an existing repo now produces populated memory in one command,
|
|
607
|
+
with no agent and no model: a project profile (stack, commands, layout, CI),
|
|
608
|
+
conventions inferred from git history, and any ADRs the repo already has imported
|
|
609
|
+
as decisions. Prose docs still need judgement — that is what `repomem prime` and
|
|
610
|
+
`mem_prime` are for.
|
|
611
|
+
|
|
612
|
+
`repomem setup claude-code --hooks` makes memory load and record itself, so it no
|
|
613
|
+
longer depends on remembering to ask. Sessions are one file each, named and
|
|
614
|
+
attributed, and handoffs derive what changed from git rather than from recollection.
|
|
615
|
+
`mem_context` can be scoped to a task and capped to a token budget. Semantic search
|
|
616
|
+
is available, off by default, and never bundles a model.
|
|
617
|
+
|
|
618
|
+
**What stays manual:** capturing *why* a decision was made. An auto-captured session
|
|
619
|
+
knows what changed and can never know the intent behind it — that judgement is the
|
|
620
|
+
part worth keeping, and the part only you can supply.
|
|
621
|
+
|
|
622
|
+
If this solves a problem you have, **star the repo** — it helps validate that this is
|
|
623
|
+
worth building and tells me which features to prioritise.
|
|
624
|
+
|
|
625
|
+
Have this exact problem on your team? Open an
|
|
626
|
+
[issue](https://github.com/saleem786khan/repomem/issues) describing your setup — I'm
|
|
627
|
+
using real use cases to shape the roadmap.
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## Contributing
|
|
632
|
+
|
|
633
|
+
repomem is being built in public. Contributions welcome at any stage.
|
|
634
|
+
|
|
635
|
+
```bash
|
|
636
|
+
git clone https://github.com/saleem786khan/repomem
|
|
637
|
+
cd repomem
|
|
638
|
+
npm install
|
|
639
|
+
npm test # builds, then runs the suite
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
## License
|
|
647
|
+
|
|
648
|
+
MIT — see [LICENSE](./LICENSE)
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
<div align="center">
|
|
653
|
+
Built by <a href="https://github.com/saleem786khan">Saleem Khan</a> — Solutions Architect with 11 years of enterprise delivery,
|
|
654
|
+
tired of re-explaining the same project to Claude every single morning.
|
|
655
|
+
</div>
|