@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.
Files changed (57) hide show
  1. package/README.md +655 -212
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +230 -14
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config/config.d.ts +20 -0
  6. package/dist/config/config.d.ts.map +1 -1
  7. package/dist/config/config.js +1 -0
  8. package/dist/config/config.js.map +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +10 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/store/adr.d.ts +22 -0
  13. package/dist/store/adr.d.ts.map +1 -0
  14. package/dist/store/adr.js +201 -0
  15. package/dist/store/adr.js.map +1 -0
  16. package/dist/store/capture.d.ts +39 -0
  17. package/dist/store/capture.d.ts.map +1 -0
  18. package/dist/store/capture.js +148 -0
  19. package/dist/store/capture.js.map +1 -0
  20. package/dist/store/embeddings.d.ts +34 -0
  21. package/dist/store/embeddings.d.ts.map +1 -0
  22. package/dist/store/embeddings.js +250 -0
  23. package/dist/store/embeddings.js.map +1 -0
  24. package/dist/store/file-store.d.ts +26 -1
  25. package/dist/store/file-store.d.ts.map +1 -1
  26. package/dist/store/file-store.js +105 -16
  27. package/dist/store/file-store.js.map +1 -1
  28. package/dist/store/git.d.ts +46 -0
  29. package/dist/store/git.d.ts.map +1 -0
  30. package/dist/store/git.js +131 -0
  31. package/dist/store/git.js.map +1 -0
  32. package/dist/store/profile.d.ts +18 -0
  33. package/dist/store/profile.d.ts.map +1 -0
  34. package/dist/store/profile.js +345 -0
  35. package/dist/store/profile.js.map +1 -0
  36. package/dist/tools/mem-context.d.ts.map +1 -1
  37. package/dist/tools/mem-context.js +249 -33
  38. package/dist/tools/mem-context.js.map +1 -1
  39. package/dist/tools/mem-handoff.d.ts.map +1 -1
  40. package/dist/tools/mem-handoff.js +53 -5
  41. package/dist/tools/mem-handoff.js.map +1 -1
  42. package/dist/tools/mem-save.d.ts +5 -0
  43. package/dist/tools/mem-save.d.ts.map +1 -1
  44. package/dist/tools/mem-save.js +60 -2
  45. package/dist/tools/mem-save.js.map +1 -1
  46. package/dist/tools/mem-search.d.ts.map +1 -1
  47. package/dist/tools/mem-search.js +26 -14
  48. package/dist/tools/mem-search.js.map +1 -1
  49. package/dist/tools/session.d.ts +40 -0
  50. package/dist/tools/session.d.ts.map +1 -0
  51. package/dist/tools/session.js +159 -0
  52. package/dist/tools/session.js.map +1 -0
  53. package/dist/tools/util.d.ts +8 -1
  54. package/dist/tools/util.d.ts.map +1 -1
  55. package/dist/tools/util.js +7 -0
  56. package/dist/tools/util.js.map +1 -1
  57. 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
- [![npm](https://img.shields.io/npm/v/@saleem11kh/repomem?color=7F77DD&label=npm)](https://www.npmjs.com/package/@saleem11kh/repomem)
11
- [![license](https://img.shields.io/badge/license-MIT-1D9E75)](./LICENSE)
12
- [![status](https://img.shields.io/badge/status-early%20development-amber)](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
- ```
42
-
43
- Plain markdown files. No database. No cloud. No vendor lock-in.
44
-
45
- `git add .repomem/ && git commit` your whole team has the memory.
46
- `git clone` → new teammate inherits full project context on day one.
47
- Switch agents same memory, because it's in the repo, not the tool.
48
-
49
- ---
50
-
51
- ## How it works
52
-
53
- repomem runs as an MCP server. Your AI agent gets 4 tools:
54
-
55
- | Tool | What it does |
56
- |---|---|
57
- | `mem_save` | Save a decision, pattern, issue, or session note (with a one-line summary + `[[links]]`) |
58
- | `mem_search` | Search across all memory files instantly (BM25 + recency ranked) |
59
- | `mem_context` | Get a lean context packet at session start — summaries, not full bodies |
60
- | `mem_get` | Expand a single entry (by file or `[[wikilink]]`) only when you need it |
61
- | `mem_handoff` | Write today's session file, ready to commit |
62
- | `mem_prime` | Bootstrap memory on an existing repo from its CLAUDE.md / docs |
63
-
64
- At the start of every session, your agent calls `mem_context()` and immediately knows:
65
- - What was worked on last session
66
- - Key architectural decisions and why they were made
67
- - Patterns and conventions for this specific codebase
68
- - Known issues to avoid repeating
69
- - What's next
70
-
71
- To keep context small, `mem_context` returns **one-line summaries**; the agent expands
72
- only what it needs with `mem_get`. Entries can cross-link with `[[wikilinks]]`, so related
73
- decisions, patterns, and issues travel together. Already have a context-rich repo? Run
74
- `mem_prime` once to seed memory from your existing `CLAUDE.md` and `docs/`.
75
-
76
- ---
77
-
78
- ## Quick start
79
-
80
- ```bash
81
- # Install
82
- npm install -g @saleem11kh/repomem
83
-
84
- # Initialize in your project
85
- cd your-project
86
- repomem init
87
-
88
- # Wire to Claude Code
89
- repomem setup claude-code
90
-
91
- # Wire to Cursor
92
- repomem setup cursor
93
-
94
- # Wire to Gemini CLI
95
- repomem setup gemini
96
- ```
97
-
98
- That's it. Your agent now has persistent memory that lives in your repo.
99
-
100
- ---
101
-
102
- ## Multi-repo support
103
-
104
- Working across microservices or a multi-repo setup? repomem handles it.
105
-
106
- ```json
107
- // repomem.config.json
108
- {
109
- "project": "payments-service",
110
- "workspace": "../repomem-workspace",
111
- "linked": [
112
- { "repo": "../auth-service", "relation": "depends-on" },
113
- { "repo": "../shared-lib", "relation": "consumes" },
114
- { "repo": "github:acme/billing-svc", "relation": "depends-on" }
115
- ]
116
- }
117
- ```
118
-
119
- Linked repos can be **local paths** or **remote GitHub repos** (`github:owner/name`,
120
- optionally `#ref`). For remotes, run `repomem pull` once to fetch their `.repomem/`
121
- into a local, gitignored cache — no full clone needed. A `GITHUB_TOKEN`/`GH_TOKEN`
122
- env var is used for private repos and higher rate limits.
123
-
124
- When your agent calls `mem_search` with `linked=true`, repomem searches:
125
- 1. Current repo memory
126
- 2. Linked repo memory local paths and pulled remotes (contracts, shared patterns)
127
- 3. Workspace memory (org-wide decisions)
128
-
129
- Results are ranked (TF-IDF + recency) and labelled by source:
130
- `[current] [linked:auth-service] [remote:billing-svc] [workspace]`
131
-
132
- Cross-repository context that actually travels with the code — not locked in a personal tool on one machine.
133
-
134
- ---
135
-
136
- ## Compared to alternatives
137
-
138
- | | repomem | Engram | claude-mem | CLAUDE.md |
139
- |---|---|---|---|---|
140
- | Git-committed | | | | ✅ |
141
- | Team-shared on clone | ✅ | ❌ | ❌ | ✅ |
142
- | Captures session work | ✅ | ✅ | ✅ | ❌ |
143
- | Multi-repo support | | | | |
144
- | Multi-agent (any MCP) | ✅ | ✅ | ❌ | ✅ |
145
- | No cloud / no vendor | ✅ | ❌ | ✅ | ✅ |
146
- | Plain markdown files | | | | |
147
-
148
- ---
149
-
150
- ## Roadmap
151
-
152
- - [x] npm package claimed
153
- - [x] `repomem init` scaffold `.repomem/` in any project
154
- - [x] 4 core MCP tools (`mem_save`, `mem_search`, `mem_context`, `mem_handoff`)
155
- - [x] Claude Code wiring (`repomem setup claude-code`)
156
- - [x] Cursor wiring
157
- - [x] Gemini CLI / Codex wiring
158
- - [x] Multi-repo `linked` support (local paths)
159
- - [x] Workspace scope (cross-org shared memory repo)
160
- - [x] `repomem sync` export `.repomem/` to stdout for sharing
161
- - [x] Remote linked repos (read `.repomem/` from GitHub without cloning, via `repomem pull`)
162
- - [x] `repomem import` — import a sync bundle for airgapped environments
163
- - [x] Smarter search ranking (BM25 + recency weighting)
164
- - [x] Progressive disclosure — `mem_context` summaries + `mem_get` to expand
165
- - [x] `[[wikilink]]` graph between memories (traversed by search + context)
166
- - [x] `mem_prime` — bootstrap memory from an existing repo's docs
167
- - [ ] Optional semantic search layer (off by default, local embedding cache)
168
-
169
- ---
170
-
171
- ## Status
172
-
173
- **v0.2 — working.** `init`, `setup`, `status`, `sync`, `import`, `pull`, and six
174
- MCP tools (`mem_save`, `mem_search`, `mem_context`, `mem_get`, `mem_handoff`,
175
- `mem_prime`) are implemented and tested. Context is token-lean by default
176
- (summaries + `mem_get` to expand), memories cross-link with `[[wikilinks]]`, and
177
- `mem_prime` bootstraps an existing repo from its docs. Multi-repo search spans
178
- local `linked` paths, remote GitHub repos (pulled into a local cache), and a
179
- shared `workspace`, ranked by BM25 with a recency boost.
180
-
181
- If this solves a problem you have, **star the repo** — it helps validate that this is worth building and tells me which features to prioritise first.
182
-
183
- Have this exact problem on your team? Open an [issue](https://github.com/saleem786khan/repomem/issues) describing your setup — I'm using real use cases to shape the v0.1 feature set.
184
-
185
- ---
186
-
187
- ## Contributing
188
-
189
- repomem is being built in public. Contributions welcome at any stage.
190
-
191
- ```bash
192
- git clone https://github.com/saleem786khan/repomem
193
- cd repomem
194
- npm install
195
- npm run dev
196
- ```
197
-
198
- See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to get involved.
199
- Good first issues will be labelled once the scaffold is up.
200
-
201
- ---
202
-
203
- ## License
204
-
205
- MIT — see [LICENSE](./LICENSE)
206
-
207
- ---
208
-
209
- <div align="center">
210
- Built by <a href="https://github.com/saleem786khan">Saleem Khan</a> — Solutions Architect with 11 years of enterprise delivery,
211
- tired of re-explaining the same project to Claude every single morning.
212
- </div>
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
+ [![npm](https://img.shields.io/npm/v/@saleem11kh/repomem?color=7F77DD&label=npm)](https://www.npmjs.com/package/@saleem11kh/repomem)
11
+ [![license](https://img.shields.io/badge/license-MIT-1D9E75)](./LICENSE)
12
+ [![status](https://img.shields.io/badge/status-early%20development-amber)](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>