somtum 3.0.0 → 3.1.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 (51) hide show
  1. package/README.md +101 -840
  2. package/dist/cli/doctor.d.ts.map +1 -1
  3. package/dist/cli/doctor.js +29 -27
  4. package/dist/cli/doctor.js.map +1 -1
  5. package/dist/cli/hook.d.ts.map +1 -1
  6. package/dist/cli/hook.js +1 -1
  7. package/dist/cli/hook.js.map +1 -1
  8. package/dist/cli/index.js +11 -6
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/cli/init.d.ts.map +1 -1
  11. package/dist/cli/init.js +31 -8
  12. package/dist/cli/init.js.map +1 -1
  13. package/dist/cli/serve.d.ts.map +1 -1
  14. package/dist/cli/serve.js +2 -0
  15. package/dist/cli/serve.js.map +1 -1
  16. package/dist/cli/stats.d.ts +4 -0
  17. package/dist/cli/stats.d.ts.map +1 -1
  18. package/dist/cli/stats.js +71 -43
  19. package/dist/cli/stats.js.map +1 -1
  20. package/dist/core/ledger.d.ts +28 -0
  21. package/dist/core/ledger.d.ts.map +1 -0
  22. package/dist/core/ledger.js +43 -0
  23. package/dist/core/ledger.js.map +1 -0
  24. package/dist/core/retriever/bm25.d.ts +1 -1
  25. package/dist/core/retriever/bm25.d.ts.map +1 -1
  26. package/dist/core/retriever/bm25.js +11 -1
  27. package/dist/core/retriever/bm25.js.map +1 -1
  28. package/dist/core/schema.d.ts +5 -0
  29. package/dist/core/schema.d.ts.map +1 -1
  30. package/dist/core/schema.js +6 -1
  31. package/dist/core/schema.js.map +1 -1
  32. package/dist/core/session_progress.d.ts +10 -0
  33. package/dist/core/session_progress.d.ts.map +1 -0
  34. package/dist/core/session_progress.js +39 -0
  35. package/dist/core/session_progress.js.map +1 -0
  36. package/dist/db/migrations/006_token_ledger.sql +33 -0
  37. package/dist/hooks/post_session.d.ts +1 -0
  38. package/dist/hooks/post_session.d.ts.map +1 -1
  39. package/dist/hooks/post_session.js +79 -39
  40. package/dist/hooks/post_session.js.map +1 -1
  41. package/dist/hooks/pre_prompt.d.ts.map +1 -1
  42. package/dist/hooks/pre_prompt.js +14 -1
  43. package/dist/hooks/pre_prompt.js.map +1 -1
  44. package/dist/hooks/pre_read.d.ts +16 -2
  45. package/dist/hooks/pre_read.d.ts.map +1 -1
  46. package/dist/hooks/pre_read.js +81 -26
  47. package/dist/hooks/pre_read.js.map +1 -1
  48. package/dist/mcp/tools.d.ts.map +1 -1
  49. package/dist/mcp/tools.js +2 -0
  50. package/dist/mcp/tools.js.map +1 -1
  51. package/package.json +5 -3
package/README.md CHANGED
@@ -1,909 +1,170 @@
1
- <img src="./assets/logo.png" width="500" alt="Somtum Logo">
1
+ <img src="./assets/logo.png" width="420" alt="Somtum">
2
2
 
3
- **Local-first memory and prompt-cache layer for coding agents: Claude Code and Codex.**
3
+ **Long-term memory for Claude Code and Codex that meters every token it spends.**
4
4
 
5
- [**Docs**](https://riz007.github.io/somtum/) · [**npm**](https://www.npmjs.com/package/somtum)
6
-
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
5
  [![npm version](https://badge.fury.io/js/somtum.svg)](https://www.npmjs.com/package/somtum)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
7
 
10
- Somtum (Thai: ส้มตำ) is named after the vibrant, shredded green papaya salad. Just like its namesake, Somtum blends durable observations from your Claude Code and Codex sessions — decisions, bugfixes, learnings, file summaries — stores them in a local SQLite database, and injects the relevant ones back into context the next time you work on the same project.
11
-
12
- Zero-config: one `somtum init` and every session end is captured automatically. No server, no cloud account, no mandatory tuning.
13
-
14
- ---
15
-
16
- ## Table of Contents
17
-
18
- - [Why Somtum?](#why-somtum)
19
- - [How it works](#how-it-works)
20
- - [Requirements](#requirements)
21
- - [Install](#install)
22
- - [Quickstart](#quickstart)
23
- - [Verifying the setup](#verifying-the-setup)
24
- - [Dashboard](#dashboard)
25
- - [CLI Reference](#cli-reference)
26
- - [MCP Server](#mcp-server)
27
- - [Storage Layout](#storage-layout)
28
- - [Configuration](#configuration)
29
- - [Privacy](#privacy)
30
- - [Token Accounting](#token-accounting)
31
- - [Performance](#performance)
32
- - [Development](#development)
33
- - [Troubleshooting](#troubleshooting)
34
- - [License](#license)
35
-
36
- > **v3.0.0** — Codex support (`somtum init --agent codex`) · selectable extraction backends incl. Codex CLI and GLM · fixes silently lost sessions and oversized extraction calls · [upgrade guide](https://riz007.github.io/somtum/guide/upgrading-v3)
37
- >
38
- > **v2.0.0** — Global DB (`~/.somtum/global.db`) · cross-project workspace recall · memory deduplication (`superseded_by`) · `--show-superseded` on `somtum list` · stats instrumentation fix · dashboard dark-mode redesign
39
- >
40
- > **v1.5.0** — Multi-page VitePress docs site · `somtum list` · `somtum reset` · `somtum forget --all` · embeddings timeout safety · config crash-resilience · `injection.max_chars` wired up · warm-start race fix · auth-error hints
41
- >
42
- > **v1.3.0** — Auto-inject memories on every prompt · `update` MCP tool · warm-start after compaction · false-hit detection · workspace scope · `suggest-claude-md` · stale memory detection in `doctor`
43
-
44
- ---
45
-
46
- ## Why Somtum?
47
-
48
- Coding agents like Claude Code and Codex start every session with a blank slate. That leads to:
49
-
50
- - **Repetitive context** — re-explaining the same architectural choices every session
51
- - **Regressions** — the agent suggests a fix you already tried and discarded
52
- - **Token waste** — reading large files just to "set the scene"
53
-
54
- **Somtum gives your coding agent a long-term memory.** Once a decision is made or a bug is fixed, it's remembered across all future sessions, in Claude Code and Codex alike, without bloating your context window.
55
-
56
- ### What a session looks like with Somtum
57
-
58
- ```
59
- Without Somtum With Somtum
60
- ──────────────────── ──────────────────────────────────────
61
- Session 1: "We use pnpm Session 1: same work
62
- because of workspace
63
- hoisting"
64
-
65
- Session 2: Claude suggests Session 2: Claude already knows about
66
- npm, you correct it pnpm, the auth decisions, and the
67
- again bugfixes from last week
68
- ```
69
-
70
- ---
71
-
72
- ## How it works
73
-
74
- At the end of each Claude Code or Codex session, Somtum reads the session transcript and asks a small model to extract the parts worth keeping — decisions, bug fixes, things learned. Those observations are stored locally in SQLite. **On every subsequent prompt**, Somtum automatically retrieves the most relevant memories and injects them into context — no manual recall needed.
75
-
76
- ### Memory lifecycle
77
-
78
- ```
79
- ┌─────────────────────────────────────────────────────────────┐
80
- │ Claude Code or Codex session │
81
- │ │
82
- │ you code · debug · review · make decisions │
83
- └──────────────────────────────┬──────────────────────────────┘
84
- │ SessionEnd / PreCompact
85
- ▼
86
- ┌─────────────────────────────────────────────────────────────┐
87
- │ Capture Pipeline │
88
- │ │
89
- │ session transcript ──► Haiku extracts observations │
90
- │ │
91
- │ decisions · bug fixes · learnings · commands │
92
- │ │
93
- │ PreCompact ─── writes warm-start file ──► next session │
94
- └──────────────────────────────┬──────────────────────────────┘
95
- │ persisted locally
96
- ▼
97
- ┌─────────────────────────┐
98
- │ ~/.somtum/projects/ │
99
- │ <project-hash>/ │
100
- │ │
101
- │ db.sqlite │
102
- │ index.md │
103
- │ memories/YYYY-MM/ │
104
- └────────────┬────────────┘
105
- │ every prompt (UserPromptSubmit)
106
- ▼
107
- ┌─────────────────────────────────────────────────────────────┐
108
- │ Auto-Inject Pipeline (new) │
109
- │ │
110
- │ 1. Prompt cache lookup (exact + fuzzy match) │
111
- │ 2. BM25 recall — top-k relevant memories │
112
- │ 3. Warm-start context (if session just compacted) │
113
- │ │
114
- │ all injected as additionalContext automatically │
115
- └─────────────────────────────────────────────────────────────┘
116
- ```
117
-
118
- ### What gets captured — a concrete example
119
-
120
- You work a session debugging an auth bug and refactoring a module. At session end, Somtum extracts something like:
121
-
122
- ```json
123
- [
124
- {
125
- "kind": "bugfix",
126
- "title": "JWT refresh loop caused by missing expiry check",
127
- "body": "The refresh token loop was triggered because we checked token.exp < Date.now() instead of token.exp < Date.now() / 1000. Unix timestamps are in seconds, not milliseconds.",
128
- "files": ["src/auth/refresh.ts"]
129
- },
130
- {
131
- "kind": "decision",
132
- "title": "Use pnpm workspaces — npm hoisting breaks shared types",
133
- "body": "Switched from npm to pnpm because npm's hoisting puts shared type packages in the wrong node_modules scope, breaking type inference across packages.",
134
- "files": ["package.json", "pnpm-workspace.yaml"]
135
- }
136
- ]
137
- ```
138
-
139
- Next session, when you ask "why are we using pnpm?" or touch `src/auth/refresh.ts`, the agent gets these memories and already has the context.
140
-
141
- ### Architecture
142
-
143
- ```
144
- ┌─────────────────────────────────────────────────────────────┐
145
- │ Claude Code / Codex / MCP client │
146
- └──────────┬──────────────────────────────┬───────────────────┘
147
- │ hooks │ MCP tools
148
- ▼ ▼
149
- ┌─────────────────────┐ ┌──────────────────────────┐
150
- │ Hooks │ │ MCP Tools │
151
- │ │ │ │
152
- │ UserPromptSubmit ──┼─cache──▶│ cache_lookup │
153
- │ ──┼─inject─▶│ recall / get │
154
- │ SessionEnd ────────┼─capture▶│ remember / update │
155
- │ PreCompact ────────┼─warmst─▶│ forget │
156
- │ PreToolUse (Read) ─┼─gate───▶│ stats │
157
- │ │ │ report_false_hit │
158
- └──────────┬──────────┘ └────────────┬─────────────┘
159
- │ │
160
- ▼ ▼
161
- ┌─────────────────────────────────────────────────────────────┐
162
- │ Core (TypeScript) │
163
- │ │
164
- │ ┌──────────────┐ ┌─────────────────┐ ┌───────────────┐ │
165
- │ │ PromptCache │ │ MemoryStore │ │ Retriever │ │
166
- │ │ │ │ │ │ │ │
167
- │ │ exact hash │ │ observations │ │ bm25(default) │ │
168
- │ │ fuzzy embed │ │ scope: project │ │ embeddings │ │
169
- │ │ fingerprint │ │ global │ │ index │ │
170
- │ │ false_hits │ │ workspace │ │ hybrid │ │
171
- │ └──────────────┘ │ last_confirmed │ └───────────────┘ │
172
- │ └─────────────────┘ │
173
- └─────────────────────────────────┬───────────────────────────┘
174
- │
175
- ▼
176
- ┌─────────────────────────────┐
177
- │ SQLite WAL + ~/.somtum/ │
178
- │ /projects/<hash>/ │
179
- │ db.sqlite │
180
- │ index.md │
181
- │ memories/YYYY-MM/<ulid>.md│
182
- │ /session/lh_<id>.json │
183
- │ /warmstart/ws_<id>.json │
184
- └─────────────────────────────┘
185
- ```
186
-
187
- ### Retrieval strategies
188
-
189
- | Strategy | How it works | Best for | Cost |
190
- | ---------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------- |
191
- | **`bm25`** | Keyword search over title + body + tags (SQLite FTS5 — no external dependencies) | Exact terms, offline setups | Near-zero |
192
- | **`embeddings`** | Semantic similarity using a 30 MB local model (bge-small-en-v1.5, runs fully in-process) | "What did we decide about auth?" style queries | ~5 ms at 10k memories |
193
- | **`index`** | Sends a compact memory catalog to Haiku; the model picks relevant IDs | Paraphrased or fuzzy queries | 1 Haiku API call |
194
- | **`hybrid`** | BM25 + embeddings results merged and re-ranked by Haiku | General case (best recall) | BM25 + embeddings + 1 Haiku call |
195
-
196
- **Default is `bm25`** — works offline, no setup. Enable `hybrid` once you have embeddings downloaded.
197
-
198
- > **Caution:** Setting `strategy=hybrid` without enabling embeddings causes a silent fallback to BM25 while paying hybrid overhead. Run `somtum doctor` — if it shows `strategy=hybrid` alongside `embeddings: disabled`, fix it:
199
- >
200
- > ```bash
201
- > somtum config set retrieval.strategy bm25 # match what's actually running
202
- > # or, to use real hybrid:
203
- > somtum config set retrieval.embeddings.enabled true && somtum reindex
204
- > ```
205
-
206
- ---
207
-
208
- ## Requirements
8
+ [Docs](https://riz007.github.io/somtum/) · [What it costs](https://riz007.github.io/somtum/guide/costs) · [CLI reference](https://riz007.github.io/somtum/reference/cli) · [Changelog](CHANGELOG.md)
209
9
 
210
- - **Node 20+**
211
- - **Claude Code or Codex** — Somtum hooks into their `SessionEnd`, `PreCompact` and `UserPromptSubmit` events. Both agents share one memory store per project.
212
- - **An extraction backend**, picked automatically in this order:
213
- 1. `ANTHROPIC_API_KEY`, or `ANTHROPIC_AUTH_TOKEN` + `ANTHROPIC_BASE_URL` for Anthropic-compatible providers such as GLM
214
- 2. the `claude` CLI (Claude Code subscribers need no separate key)
215
- 3. the `codex` CLI (ChatGPT/Codex subscribers need no separate key)
10
+ Your coding agent forgets everything when a session ends or its context compacts. Somtum keeps the parts worth keeping (decisions, root causes, commands that finally worked) in a local SQLite database and hands the relevant ones back on later prompts. Claude Code and Codex share the same memory.
216
11
 
217
- Override with `somtum config set extraction.backend anthropic|claude-cli|codex-cli`.
12
+ Memory is paid for in tokens, so Somtum is built to never multiply your bill. It only sends what it hasn't sent before, skips work that can't pay off, caps everything it adds to a prompt, and writes every token it spends to a ledger you can read with `somtum stats`.
218
13
 
219
- ---
14
+ Named after ส้มตำ, the Thai green papaya salad: shredded fine, only what's fresh.
220
15
 
221
- ## Install
16
+ ## Quick start
222
17
 
223
18
  ```bash
224
19
  npm install -g somtum
20
+ cd your-project # the directory you launch your agent from
21
+ somtum init # Claude Code: capture + recall hooks, MCP server
22
+ somtum init --agent codex # Codex (run both if you use both)
23
+ somtum doctor # every line should show ✓
225
24
  ```
226
25
 
227
- > **pnpm users:** `pnpm add -g somtum` works if you have run `pnpm setup` first (sets `PNPM_HOME`). If you haven't, use npm above.
228
- >
229
- > **yarn users:** `yarn global add` is not supported in Yarn v2+ (Berry). Use npm above.
230
-
231
- ### From source
232
-
233
- ```bash
234
- git clone https://github.com/riz007/somtum
235
- cd somtum
236
- pnpm install
237
- pnpm build
238
- pnpm link --global
239
- ```
240
-
241
- ### Native module note
242
-
243
- Somtum uses [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3), which contains a native C++ addon. On most platforms (macOS, Linux x64/arm64, Windows x64) a prebuilt binary is downloaded automatically. On Alpine Linux / musl or unusual architectures, the addon compiles from source — `python`, `make`, and `gcc` must be available. If the install fails with a node-gyp error, install those build tools and retry.
244
-
245
- ---
246
-
247
- ## Quickstart
248
-
249
- ### Step 1 — Check your extraction backend
250
-
251
- At the end of each session Somtum asks a small model to pull out what's worth remembering. It uses the first backend available, so most people need to do nothing:
252
-
253
- | You have | Backend used |
254
- | --- | --- |
255
- | `ANTHROPIC_API_KEY` in your shell profile | Anthropic API (Haiku) |
256
- | `ANTHROPIC_AUTH_TOKEN` + `ANTHROPIC_BASE_URL` (GLM or another Anthropic-compatible provider) | that provider |
257
- | Claude Code installed (`which claude` prints a path) | `claude` CLI, on your subscription |
258
- | Codex installed (`which codex` prints a path) | `codex` CLI, on your ChatGPT plan |
259
-
260
- > Keys must be in your shell profile, not just exported in an open terminal tab. Hooks inherit the environment of the shell that _started_ the agent.
261
-
262
- ### Step 2 — Install in your project
263
-
264
- Run from the **root of the project you open in your agent**.
265
-
266
- **Claude Code**
267
-
268
- ```bash
269
- somtum init --all
270
- # Installs:
271
- # - SessionEnd + PreCompact capture hooks (memory extraction)
272
- # - UserPromptSubmit hook (auto-inject + prompt cache)
273
- # - PreToolUse file-gating hook (large file summarization)
274
- # - MCP server in .mcp.json (recall/remember tools)
275
- ```
276
-
277
- > Use `--all`. A plain `somtum init` installs only the capture hooks: memories are saved but not injected, and the agent sees them only if it calls the MCP `recall` tool.
278
-
279
- **Codex** (or both, on the same project; they share one memory store):
26
+ Then use your agent as usual. Memories appear after your first substantial session ends or compacts:
280
27
 
281
28
  ```bash
282
- somtum init --agent codex
283
- # Installs:
284
- # - .codex/hooks.json SessionEnd + PreCompact capture, UserPromptSubmit injection
285
- # - .codex/config.toml [mcp_servers.somtum]
29
+ somtum list # what was remembered
30
+ somtum stats # what it cost
286
31
  ```
287
32
 
288
- Codex only loads project-level config for trusted projects. Sessions are read from `~/.codex/sessions` (or `$CODEX_HOME/sessions`).
33
+ Requires Node 20+ and one way to run a small model for extraction. Somtum uses the first one it finds: `ANTHROPIC_API_KEY` (or an Anthropic-compatible provider through `ANTHROPIC_AUTH_TOKEN` + `ANTHROPIC_BASE_URL`), then the `claude` CLI, then the `codex` CLI. If you can run your agent, you already have one.
289
34
 
290
- ### Step 3 — Verify your setup
35
+ ## What it does
291
36
 
292
- Run doctor immediately after init to confirm everything is connected:
37
+ **Captures.** When a session ends or compacts, Somtum sends the turns it hasn't seen yet to a small model (Claude Haiku by default) and stores what comes back as short typed records:
293
38
 
294
- ```bash
295
- somtum doctor
39
+ ```json
40
+ {
41
+ "kind": "bugfix",
42
+ "title": "JWT refresh loop: exp is in seconds, not ms",
43
+ "body": "Compared token.exp against Date.now(); must divide by 1000.",
44
+ "files": ["src/auth/refresh.ts"]
45
+ }
296
46
  ```
297
47
 
298
- All checks should show `✓`. The two most important are:
48
+ **Recalls.** On each prompt, a local keyword search (SQLite FTS5, no network) picks up to 3 relevant memories and adds them to the agent's context, capped at 1,500 characters. Nothing is added when nothing matches, and a memory that's already in the session's context isn't added again.
299
49
 
300
- - **`extraction_backend`** — confirms Somtum has a model to extract memories with
301
- - **`hooks_installed`** — confirms hooks are registered for Claude Code, Codex, or both
50
+ **Shares.** Claude Code and Codex read and write one memory per project. Any MCP client can use the `recall` and `remember` tools. Memories saved with `scope: "global"` follow you into every project.
302
51
 
303
- Do not start your first session until all checks pass. Each failing check shows an inline fix command.
52
+ Everything is stored under `~/.somtum/`. Data leaves your machine only in model calls through the backend you chose: extraction, plus file summaries if you turn on file gating.
304
53
 
305
- ### Step 4 — Use your agent normally
54
+ ## What it costs
306
55
 
307
- Open Claude Code or Codex **from the same directory** where you ran `somtum init`. Work as you normally would. When the session ends, the hook extracts observations automatically in the background (capped at 90 seconds).
56
+ Somtum spends tokens in two places: on extraction, and on the context it adds to your prompts. Both are bounded, and both are metered.
308
57
 
309
- ### Step 5 — Check your memory
58
+ | Cost | When | Bound | Turn it down |
59
+ | --- | --- | --- | --- |
60
+ | Extraction | Session end or compaction | Only turns not yet extracted, at most 60k tokens. No call when fewer than 500 new tokens. | `extraction.min_new_tokens`, `extraction.max_observations_per_session` |
61
+ | Injected memories | A prompt that matches stored memories | Up to 3 memories, 1,500 characters (about 375 tokens). A memory already in context is not re-sent. | `injection.k`, `injection.max_chars`, `injection.enabled` |
62
+ | File summaries | Only if you enable file gating | One small-model call per large file that changed | `file_gating.enabled` (off by default) |
310
63
 
311
- ```bash
312
- # How many observations were captured?
313
- somtum stats
314
-
315
- # Search memory
316
- somtum search "auth jwt rotation"
317
- somtum search "why we use pnpm" --strategy hybrid
64
+ `somtum stats` reads the ledger. This is real output:
318
65
 
319
- # Open the visual dashboard
320
- somtum serve
321
66
  ```
322
-
323
- If `somtum stats` shows `memories 0` after a session, see [Troubleshooting](#troubleshooting).
324
-
325
- ---
326
-
327
- ## Verifying the setup
328
-
329
- After your **first** session ends:
330
-
331
- **1. Check the hook log**
332
-
333
- ```bash
334
- cat ~/.somtum/hook.log
67
+ Somtum's own token use, metered (all time)
68
+ extraction 4 calls 54,785 tok 1 skipped
69
+ injected context 14 prompts 4,060 tok added to your agent's input
70
+ total 58,845 tok
335
71
  ```
336
72
 
337
- A successful run:
73
+ Use `somtum stats --since 7d` for a window, or `--json` to feed it into something else. Extraction runs on whatever backend you configured. On the `claude` or `codex` CLI, it draws on your existing plan rather than a separate bill.
338
74
 
339
- ```
340
- 2026-04-30T10:15:42.123Z [post_session] starting
341
- 2026-04-30T10:15:44.891Z [post_session] ok — inserted=4 superseded=1 cache=2 summaries=1
342
- ```
75
+ ### Measured: not paying twice for the same transcript
343
76
 
344
- Each run also logs which backend it used:
77
+ Through v3.0, a session that compacted and then ended was extracted twice, and the second call re-sent everything the first had already processed. Somtum now keeps a per-session cursor and sends only new turns. These numbers come from replaying three real Claude Code sessions through the pipeline with a stub model, each compacting once at 60% of its length. Tokens are counted over the exact extraction requests, using the same tokenizer approximation `somtum stats` uses:
345
78
 
346
- ```
347
- 2026-04-30T10:15:42.124Z [post_session] extraction backend: claude-cli
348
- ```
79
+ | Session | Turns | v3.0 extraction tokens | v3.1 extraction tokens | Saved |
80
+ | --- | ---: | ---: | ---: | ---: |
81
+ | Web app redesign | 309 | 64,577 | 41,756 | 35% |
82
+ | API service | 36 | 47,892 | 25,498 | 47% |
83
+ | Course assignment | 132 | 21,966 | 13,029 | 41% |
349
84
 
350
- Neither backend available:
85
+ ### What Somtum cannot measure
351
86
 
352
- ```
353
- 2026-04-30T10:15:42.123Z [post_session] ERROR: No extraction backend: set ANTHROPIC_API_KEY (or ANTHROPIC_AUTH_TOKEN + ANTHROPIC_BASE_URL), or install the claude or codex CLI.
354
- ```
87
+ The tokens you save because the agent already knew something (the npm-vs-pnpm argument you didn't have again) never show up in any transcript, so Somtum can't count them. `somtum stats` shows a heuristic estimate for this and labels it as one. Somtum also only sees what's in transcripts: model calls your agent makes that never appear there are invisible to it. For whole-agent spend, use your agent's own usage reporting, such as Claude Code's OpenTelemetry export.
355
88
 
356
- **2. Check stats**
89
+ ## File gating (opt-in)
357
90
 
358
- ```bash
359
- somtum stats
360
- ```
91
+ With file gating on, the first time the agent tries to read a whole large file in a session, Somtum answers with a summary of it, generated earlier, as long as the file hasn't changed since. If the agent needs the actual contents, it reads the file again and that read goes through. Partial reads (with an offset or limit) are never gated.
361
92
 
362
- You should see `memories > 0` after a substantive session. Short or trivial sessions (no decisions, no bug fixes) correctly return 0 — the extractor only keeps durable observations.
363
-
364
- **3. Run doctor**
93
+ Whether this saves anything depends on how often a summary is enough, so it's metered on both sides. `somtum stats` shows full reads avoided, summary tokens shown, and files read anyway, plus the net. After 10 gated reads, `somtum doctor` tells you to turn it off if the net is negative.
365
94
 
366
95
  ```bash
367
- somtum doctor
96
+ somtum init --file-gating # installs the hook and turns it on for this project
368
97
  ```
369
98
 
370
- All checks should show `✓`. The `api_key` and `hooks_installed` checks are the two most commonly failing.
371
-
372
- ---
99
+ Claude Code only.
373
100
 
374
- ## Dashboard
101
+ ## Everyday commands
375
102
 
376
- ```bash
377
- somtum serve
378
- # Opens http://localhost:3000
379
- ```
380
-
381
- The dashboard has four views:
382
-
383
- - **Memory browser** — searchable, filterable list of all captured observations. Switch between BM25, hybrid, and embeddings strategies live. Click any memory to see its full body, files, and tags.
384
- - **Knowledge graph** — nodes are memories, edges connect memories that share files or tags. Click a node to open it in the detail panel.
385
- - **Analytics** — kind breakdown, cache hit rate, retrieval strategy usage, top-referenced files.
386
- - **Forget button** — soft-delete any memory directly from the browser.
387
-
388
- | Flag | Default | Description |
389
- | ------------ | ------- | ---------------------------------------- |
390
- | `--port <n>` | 3000 | Listen on a custom port |
391
- | `--no-open` | — | Start server without opening the browser |
392
-
393
- Press `Ctrl-C` to stop.
394
-
395
- ---
396
-
397
- ## CLI Reference
398
-
399
- ### Setup
400
-
401
- | Command | Description |
402
- | --------------------------- | ------------------------------------------------------------ |
403
- | `somtum init` | Install the SessionEnd capture hook |
404
- | `somtum init --cache` | Also install the UserPromptSubmit cache + auto-inject hook |
405
- | `somtum init --file-gating` | Also install the PreToolUse file-gating hook |
406
- | `somtum init --all` | Install all hooks + MCP server |
407
- | `somtum init --force` | Reinstall even if hooks already present |
408
- | `somtum doctor` | Check DB health, migrations, hooks, API key, breakeven ratio, stale memories |
409
-
410
- ### Memory
411
-
412
- | Command | Description |
413
- | -------------------------------------------- | ----------------------------------------------------------------------------- |
414
- | `somtum list` | List stored memories (most recent first, superseded hidden by default) |
415
- | `somtum list --kind decision` | Filter by kind: `decision \| learning \| bugfix \| command \| file_summary` |
416
- | `somtum list --limit 20` | Limit to 20 results |
417
- | `somtum list --json` | Machine-readable JSON output |
418
- | `somtum list --show-superseded` | Include memories that have been superseded by a newer duplicate |
419
- | `somtum search <query>` | Search observations (default: `bm25` strategy) |
420
- | `somtum search <query> --strategy hybrid` | Force a specific retrieval strategy |
421
- | `somtum search <query> -k 16` | Return more results |
422
- | `somtum show <id>` | Print the full body of an observation |
423
- | `somtum remember` | Manually store an observation |
424
- | `somtum forget <id>` | Soft-delete an observation by id |
425
- | `somtum forget --all` | Soft-delete **all** observations in the current project |
426
- | `somtum edit <id>` | Open an observation body in `$EDITOR` |
427
- | `somtum rebuild` | Regenerate `index.md` from all observations |
428
- | `somtum reindex` | Recompute embeddings (after enabling embeddings or changing model) |
429
- | `somtum suggest-claude-md` | Suggest CLAUDE.md additions from accumulated observations (interactive) |
430
- | `somtum suggest-claude-md --dry-run` | Preview suggestions without writing |
431
- | `somtum suggest-claude-md --yes --limit 20` | Auto-confirm, limit to top 20 by tokens saved |
432
-
433
- ### Stats & Visibility
434
-
435
- | Command | Description |
436
- | ------------------------- | ------------------------------------------------- |
437
- | `somtum stats` | Tokens saved, cache hit rate, retrieval breakdown |
438
- | `somtum stats --json` | Machine-readable JSON output |
439
- | `somtum serve` | Open the visual dashboard in the browser |
440
- | `somtum serve --port <n>` | Use a custom port (default 3000) |
441
- | `somtum serve --no-open` | Start server without opening the browser |
442
-
443
- ### Data Management
444
-
445
- | Command | Description |
446
- | ------------------------------------------------- | ------------------------------------------------------------------------- |
447
- | `somtum export` | Export observations to stdout as JSON |
448
- | `somtum export --format jsonl --output obs.jsonl` | Export as JSONL file |
449
- | `somtum export --format markdown` | Export as readable Markdown |
450
- | `somtum export --include-deleted` | Include soft-deleted entries |
451
- | `somtum import <file>` | Import observations from JSON or JSONL |
452
- | `somtum purge --older-than 30d` | Hard-delete soft-deleted entries older than 30 days |
453
- | `somtum purge --older-than 30d --dry-run` | Preview without deleting |
454
- | `somtum reset` | **Permanently** wipe all memories for the current project (asks to confirm) |
455
- | `somtum reset --yes` | Skip confirmation (useful in CI or scripts) |
456
-
457
- ### Configuration
458
-
459
- | Command | Description |
460
- | -------------------------------------------------------------- | --------------------------------- |
461
- | `somtum config get` | Print the full resolved config |
462
- | `somtum config get retrieval.strategy` | Read a single key (dot-separated) |
463
- | `somtum config set retrieval.strategy hybrid` | Write to `.somtum/config.json` |
464
- | `somtum config set retrieval.embeddings.enabled true --global` | Write to `~/.somtum/config.json` |
465
-
466
- ### Sync
467
-
468
- | Command | Description |
469
- | -------------------- | ----------------------------------------- |
470
- | `somtum sync status` | Compare local vs remote observation count |
471
- | `somtum sync push` | Export and scp observations to remote |
472
- | `somtum sync pull` | scp from remote and merge into local DB |
473
-
474
- Set your remote: `somtum config set sync.remote "user@host:/path/.somtum/projects/<id>"`
475
-
476
- Somtum uses hostname-aware syncing — merging observations from multiple machines without data loss.
477
-
478
- ---
479
-
480
- ## MCP Server
481
-
482
- When you run `somtum init --all` (Claude Code) or `somtum init --agent codex`, Somtum registers an MCP server the agent can call on its own during a session. Any other MCP client can use it too: point it at `somtum mcp` over stdio.
483
-
484
- | Tool | What the agent does with it |
485
- | ------------------- | --------------------------------------------------------------------------------------------------------------- |
486
- | `recall` | Searches memories when unsure about a project detail. Merges project + global DB results. Accepts `strategy` |
487
- | `get` | Retrieves full observation bodies by ID. Checks global DB if not found in project DB. Bumps `last_confirmed_at` |
488
- | `remember` | Stores an observation manually. `scope='global'` routes to `~/.somtum/global.db`; returns `stored_in` field |
489
- | `update` | Updates an existing observation's title, body, tags, or files. Redaction applied |
490
- | `cache_lookup` | Checks the prompt cache directly |
491
- | `report_false_hit` | Reports that a cached response didn't answer the question (tunes fuzzy threshold data) |
492
- | `forget` | Soft-deletes an observation |
493
- | `stats` | Reports tokens saved, cache hit rate, false-hit count, corpus size, and `global_memories` count |
494
-
495
- Every MCP response includes a `tokens` field so the agent can account for retrieval cost.
496
-
497
- ### Memory scope
498
-
499
- Observations now carry a `scope` field:
500
-
501
- | Scope | Meaning | Use it when |
502
- | ----------- | --------------------------------------------------------------- | ---------------------------------------------------- |
503
- | `project` | Default. Visible only in this project. | Most decisions, bugfixes, and learnings. |
504
- | `workspace` | Shared across projects via the `recall` MCP tool. | Team conventions, preferred libraries, global rules. |
505
- | `global` | Same as workspace; reserved for personal preferences that span all your projects. | Your personal coding preferences. |
506
-
507
- ```
508
- # Store a workspace-scoped observation from within a session:
509
- remember("Always use pnpm for Node projects", body="...", scope="workspace")
510
- ```
103
+ | Command | What it does |
104
+ | --- | --- |
105
+ | `somtum doctor` | Checks setup: backend, hooks, database, and whether file gating pays off |
106
+ | `somtum stats` | Metered token use, memory counts, cache stats |
107
+ | `somtum list` / `somtum search <query>` | Browse or search memories |
108
+ | `somtum show <id>` / `somtum edit <id>` / `somtum forget <id>` | Read, fix or delete one memory |
109
+ | `somtum serve` | Local dashboard: memory browser, graph, analytics |
110
+ | `somtum suggest-claude-md` | Suggest `CLAUDE.md` additions from your memories |
111
+ | `somtum export` / `somtum import` | Move memories as JSON, JSONL or Markdown |
511
112
 
512
- ---
113
+ Full list: [CLI reference](https://riz007.github.io/somtum/reference/cli). Settings: [configuration](https://riz007.github.io/somtum/reference/configuration).
513
114
 
514
- ## Storage Layout
115
+ ## How it works
515
116
 
516
117
  ```
517
- ~/.somtum/
518
- ├── config.json ← global config (merged with project config)
519
- ├── hook.log ← timestamped log of every hook execution
520
- ├── global.db ← global-scope memories (scope='global'), queried
521
- │ alongside every project DB on recall + auto-inject
522
- ├── session/
523
- │ └── lh_<id>.json ← last cache-hit state per project (false-hit detection)
524
- │ files older than 24 h are evicted automatically
525
- ├── warmstart/
526
- │ └── ws_<id>_<timestamp>.json ← warm-start context written after PreCompact (30 min TTL)
527
- │ timestamped so concurrent windows don't clobber each other
528
- └── projects/
529
- └── <project_id>/
530
- ├── db.sqlite ← source of truth (SQLite WAL)
531
- ├── index.md ← human-readable mirror (regenerated)
532
- └── memories/
533
- └── YYYY-MM/
534
- └── <ulid>.md ← per-observation markdown files
118
+ Claude Code / Codex
119
+ │ SessionEnd, PreCompact ─────► extract new turns ─► small model ─► observations
120
+ │ │
121
+ │ UserPromptSubmit ◄───── top memories (FTS5/BM25, local) ◄──────┤
122
+ │ │
123
+ │ PreToolUse Read (opt-in) ◄───── file summary instead of full read ◄────┤
124
+ │ ▼
125
+ │ MCP: recall · remember · get · update · forget · stats ~/.somtum/projects/<id>/db.sqlite
126
+ │ ~/.somtum/global.db
127
+ │ token ledger (every event above)
535
128
  ```
536
129
 
537
- The project ID is derived from the git remote URL (or directory path if no remote). The same project maps to the same ID across machines as long as the remote URL matches.
538
-
539
- SQLite is the source of truth. Edit observations with `somtum edit <id>`, not by hand.
540
-
541
- ---
542
-
543
- ## Configuration
130
+ Details, including retrieval strategies, deduplication and warm starts after compaction: [How it works](https://riz007.github.io/somtum/guide/how-it-works).
544
131
 
545
- Global config lives at `~/.somtum/config.json`. Per-project config at `.somtum/config.json` overrides it (deep merge).
546
-
547
- ### Most common settings
548
-
549
- ```bash
550
- # Enable semantic (embedding-based) search — downloads a 30 MB model once
551
- somtum config set retrieval.embeddings.enabled true
552
- somtum reindex
132
+ ## Upgrading from 3.0
553
133
 
554
- # Switch to hybrid retrieval (BM25 + embeddings + rerank) for best recall
555
- somtum config set retrieval.strategy hybrid
556
-
557
- # Use LLM-based retrieval (no embeddings required, costs one Haiku call per query)
558
- somtum config set retrieval.index.enabled true
559
- somtum config set retrieval.strategy index
560
-
561
- # Disable file-gating (on by default — intercepts large file reads and serves cached summary)
562
- somtum config set file_gating.enabled false
563
-
564
- # Limit observations extracted per session (default: 10)
565
- somtum config set extraction.max_observations_per_session 5
566
-
567
- # Pin the extraction backend (default: auto) and the model codex exec uses
568
- somtum config set extraction.backend codex-cli
569
- somtum config set extraction.codex_model <model>
570
-
571
- # Control automatic memory injection on every prompt (default: on)
572
- somtum config set injection.enabled false # turn off auto-inject
573
- somtum config set injection.k 5 # inject more memories (default: 3)
574
- somtum config set injection.max_chars 3000 # raise injection size cap (default: 1500)
575
- ```
576
-
577
- ### Full config reference
578
-
579
- ```jsonc
580
- {
581
- "extraction": {
582
- "model": "claude-haiku-4-5-20251001",
583
- "trigger": ["SessionEnd", "PreCompact"],
584
- "max_observations_per_session": 10,
585
- },
586
- "cache": {
587
- "enabled": true,
588
- "fuzzy_match": true,
589
- "fuzzy_threshold": 0.92, // raise to 0.95 once you have false-hit signal
590
- "max_entries": 10000,
591
- "ttl_days": 90,
592
- },
593
- "retrieval": {
594
- "strategy": "bm25", // bm25 | embeddings | index | hybrid
595
- "k": 8,
596
- "rerank_model": "claude-haiku-4-5-20251001",
597
- "bm25": { "enabled": true },
598
- "embeddings": {
599
- "enabled": false, // set true to download the 30 MB ONNX model
600
- "model": "Xenova/bge-small-en-v1.5",
601
- },
602
- "index": {
603
- "enabled": false, // set true to use Haiku as the retriever
604
- "model": "claude-haiku-4-5-20251001",
605
- },
606
- },
607
- // Auto-inject: BM25-retrieved memories prepended to every UserPromptSubmit.
608
- // Uses the hot path (< 2 ms at 1k memories). Disable if you prefer pull-only.
609
- "injection": {
610
- "enabled": true,
611
- "k": 3, // max memories injected per prompt
612
- "max_chars": 1500, // hard cap on injected text
613
- "min_relevance_score": 0, // raise (e.g. 1.0) to only inject high-scoring matches
614
- "show_budget": true, // prepend "[somtum] injected N/M memories (~X tokens)" line
615
- },
616
- "file_gating": {
617
- "enabled": true, // intercepts large file reads; serves cached summary instead
618
- "min_file_size_tokens": 300,
619
- "exclude_globs": ["**/*.env", "**/secrets/**"],
620
- },
621
- "privacy": {
622
- "telemetry": false,
623
- "redact_patterns": [
624
- "api[_-]?key\\s*[:=]\\s*[\"']?[A-Za-z0-9_\\-]{8,}[\"']?",
625
- "bearer\\s+[A-Za-z0-9_\\-.]+",
626
- "sk-[A-Za-z0-9_\\-]{20,}",
627
- "xox[baprs]-[A-Za-z0-9-]{10,}",
628
- "AKIA[0-9A-Z]{16}",
629
- ],
630
- },
631
- "sync": {
632
- "enabled": false,
633
- "backend": "ssh",
634
- "remote": null, // e.g. "user@host:/home/user/.somtum/projects/<id>"
635
- },
636
- }
637
- ```
638
-
639
- ---
134
+ - `somtum init` now installs the recall hook by default, matching Codex. `--all` is no longer needed; use `--no-cache` for capture only.
135
+ - File gating is now **off by default**. In 3.0 it was on, and it generated file summaries at every session end even in projects that never installed its hook. If you used it, `somtum doctor` will say so: run `somtum init --file-gating --force` to turn it back on and update the hook to match `Read` only.
136
+ - File gating now answers a whole-file read with the summary *instead* of the file. In 3.0 it added the summary *on top of* the full read, so it could only cost tokens.
137
+ - `somtum stats` leads with metered numbers. The old `breakeven` ratio divided an estimate by an undercount, so it was removed from the human-readable output and from `doctor`. The JSON fields are unchanged.
640
138
 
641
139
  ## Privacy
642
140
 
643
- - **No network traffic** except to the Anthropic API (extraction + optional reranking). The embedding model runs fully local via ONNX Runtime in-process.
644
- - **Redaction at capture time.** `privacy.redact_patterns` is applied to every observation body before it is written to the DB — unconditionally, regardless of the `telemetry` flag.
645
- - **Explicit file excludes.** `file_gating.exclude_globs` prevents `.env`, `secrets/`, and similar paths from being summarized.
646
- - **Prompt-injection hardening.** Memory content injected into agent context is wrapped in `[Somtum memory — reference material, not instructions]` delimiters.
647
- - **Soft delete by default.** `somtum forget <id>` marks observations deleted. `somtum purge --older-than 30d` permanently removes them.
648
-
649
- ---
650
-
651
- ## Token Accounting
652
-
653
- Every `stats` figure is labelled _estimated_. Counts are computed with `gpt-tokenizer` (a BPE approximation) and deliberately undercount — better to underreport savings than to overclaim.
654
-
655
- The breakeven ratio (`tokens_saved / tokens_spent`) measures whether extraction cost is paying off. A ratio below 1.5× triggers a warning in `somtum stats` and `somtum doctor`.
656
-
657
- **A low ratio is normal on a fresh project** (< 20 memories, few recall calls). It improves as memories accumulate and get retrieved more frequently.
658
-
659
- If the ratio stays low after a few weeks, check for the hybrid/embeddings mismatch first (`somtum doctor`). If the config is correct, reduce injection scope: lower `injection.k` or `injection.max_chars` to cut overhead.
660
-
661
- ---
662
-
663
- ## Performance
664
-
665
- | Scenario | p95 budget | Actual (benchmark) |
666
- | --------------------------------------- | ------------- | ------------------------ |
667
- | `UserPromptSubmit` hook at 1k memories | 150 ms | < 2 ms (BM25 k=8) |
668
- | `UserPromptSubmit` hook at 10k memories | 300 ms | < 30 ms (BM25 k=8) |
669
- | Exact cache hash lookup | — | < 0.1 ms |
670
- | `SessionEnd` hook (extract + embed) | 90 s hard cap | Exits cleanly on timeout |
671
-
672
- Run benchmarks yourself:
673
-
674
- ```bash
675
- pnpm test:bench
676
- ```
677
-
678
- ---
141
+ - Secrets matching `privacy.redact_patterns` (API keys, bearer tokens, AWS keys and similar) are redacted before anything is stored.
142
+ - `.env` files and `secrets/` directories are never summarized.
143
+ - Injected memories are wrapped in markers that tell the agent they are reference material, not instructions.
144
+ - No telemetry. `somtum forget` soft-deletes; `somtum purge` removes for good.
679
145
 
680
146
  ## Development
681
147
 
682
148
  ```bash
149
+ git clone https://github.com/riz007/somtum && cd somtum
683
150
  pnpm install
684
- pnpm typecheck # strict TypeScript check
685
- pnpm test # vitest unit + golden tests
686
- pnpm test:golden # retrieval recall@k per strategy
687
- pnpm test:bench # hot-path latency benchmarks
688
- pnpm lint # eslint
689
- pnpm fmt # prettier
690
- pnpm build # tsc + copy migrations + copy dashboard → dist/
151
+ pnpm test # unit, integration and golden retrieval tests
152
+ pnpm typecheck && pnpm lint
153
+ pnpm build # dist/, then `pnpm link --global` to try your build
691
154
  ```
692
155
 
693
- ### Project layout
694
-
695
- ```
696
- src/
697
- cli/
698
- index.ts # commander CLI entry point
699
- init.ts # somtum init — installs hooks + MCP config
700
- serve.ts # somtum serve — local dashboard server
701
- stats.ts # somtum stats
702
- doctor.ts # somtum doctor — health checks
703
- hook.ts # internal: dispatches hook events by name
704
- search.ts / show.ts / forget.ts / edit.ts
705
- list.ts # somtum list
706
- reset.ts # somtum reset — wipe project DB
707
- export.ts / import.ts / purge.ts / sync.ts / rebuild.ts / reindex.ts
708
- config_cmd.ts
709
- suggest_claude_md.ts # somtum suggest-claude-md
710
- core/
711
- db.ts # SQLite setup, migration runner
712
- store.ts # MemoryStore — CRUD for observations
713
- cache.ts # PromptCache — exact + fuzzy lookup
714
- retriever/ # bm25, embeddings, hybrid, index, factory
715
- extractor.ts # session transcript → observations
716
- llm_backend.ts # picks the extraction backend
717
- index_gen.ts # renders index.md (incremental past 1k obs)
718
- memory_files.ts # writes memories/<YYYY-MM>/<ulid>.md
719
- retrieval_stats.ts
720
- embeddings.ts # Embedder interface + encode/decode utils
721
- privacy.ts # redact() — runs on every capture
722
- tokens.ts # gpt-tokenizer wrapper
723
- hooks/
724
- post_session.ts # SessionEnd/PreCompact: extract → store → index → warm-start
725
- pre_prompt.ts # UserPromptSubmit: cache lookup + auto-inject + false-hit detection
726
- pre_read.ts # PreToolUse: file gating
727
- mcp/ # MCP server + tool implementations
728
- dashboard/
729
- index.html # single-page dashboard (served by somtum serve)
730
- config.ts # global + project config merge
731
- index.ts # public API for embedding Somtum
732
- src/db/migrations/ # NNN_name.sql migration files
733
- test/
734
- golden/ # per-strategy retrieval golden sets
735
- bench/ # hot-path latency benchmarks
736
- fixtures/ # synthetic session transcripts
737
- ```
738
-
739
- ### Adding a new observation kind
740
-
741
- 1. Extend the zod enum in `src/core/schema.ts`
742
- 2. Update the extractor prompt in `src/core/extractor.ts`
743
- 3. Add a fixture in `test/fixtures/` and an assertion
744
- 4. Update `src/core/index_gen.ts` to render the new section
745
-
746
- ### Adding a new MCP tool
747
-
748
- 1. Define args + response with zod in `src/mcp/tools.ts`
749
- 2. Register it in `src/mcp/server.ts`
750
- 3. Response **must** include a `tokens` field
751
- 4. Add an integration test in `src/mcp/server.test.ts`
156
+ Where things live:
752
157
 
753
- ---
754
-
755
- ## Troubleshooting
756
-
757
- ### `somtum stats` shows `memories 0` after a session
758
-
759
- Check the hook log first:
760
-
761
- ```bash
762
- cat ~/.somtum/hook.log
763
- ```
764
-
765
- **No extraction backend**
766
-
767
- - Claude Code users: run `which claude`. Codex users: run `which codex`. If nothing prints, install the CLI or add it to your `PATH`.
768
- - API users: add `export ANTHROPIC_API_KEY="sk-ant-..."` to `~/.zshrc` and `source ~/.zshrc`. It must be in your profile, not just exported in the current terminal tab.
769
-
770
- Run `somtum doctor`: the `extraction_backend` check shows which backend will be used.
771
-
772
- **Hook not installed in the right directory**
773
-
774
- `somtum init` writes hooks into the directory where you ran it (`.claude/settings.json` or `.codex/hooks.json`). If you launch the agent from a different directory, it reads different settings.
775
-
776
- Fix: run `somtum init` from the same directory you launch the agent from.
777
-
778
- ```bash
779
- cd ~/my-project
780
- somtum init
781
- claude # must be launched from ~/my-project
782
- ```
783
-
784
- **Short or trivial session**
785
-
786
- If the session had no decisions, bug fixes, or learnings (e.g. you just asked Claude to say hello), the extractor correctly returns 0 observations.
787
-
788
- ---
789
-
790
- ### `somtum serve` opens the browser but shows "Connection refused"
791
-
792
- This was a bug fixed in v1.1.0. Upgrade:
793
-
794
- ```bash
795
- npm install -g somtum@latest
796
- ```
797
-
798
- If you installed from source, rebuild:
799
-
800
- ```bash
801
- pnpm build
802
- ```
803
-
804
- ---
805
-
806
- ### `somtum serve` — port already in use
807
-
808
- ```bash
809
- somtum serve --port 3001
810
- ```
811
-
812
- ---
813
-
814
- ### Agent appears to keep running after session ends
815
-
816
- The `SessionEnd` hook has a hard 90-second timeout. If sessions appear stuck, verify you are on v1.1.0+:
817
-
818
- ```bash
819
- somtum --version
820
- tail -20 ~/.somtum/hook.log
821
- ```
822
-
823
- ---
824
-
825
- ### Installation fails (node-gyp / better-sqlite3)
826
-
827
- Ensure build tools are installed:
828
-
829
- - **macOS:** `xcode-select --install`
830
- - **Ubuntu/Debian:** `sudo apt-get install build-essential python3`
831
- - **Windows:** `npm install --global --production windows-build-tools`
832
-
833
- ---
834
-
835
- ### Embeddings are slow or the model won't download
836
-
837
- The first `somtum reindex` downloads a ~30 MB ONNX model from Hugging Face. This requires internet access and may be slow. Subsequent runs use the cached model.
838
-
839
- On an air-gapped machine or if you prefer not to use embeddings:
840
-
841
- ```bash
842
- somtum config set retrieval.embeddings.enabled false
843
- somtum config set retrieval.strategy bm25
844
- ```
845
-
846
- BM25 works fully offline and is fast at any corpus size.
847
-
848
- ---
849
-
850
- ### Claude doesn't seem to have context from previous sessions
851
-
852
- **Auto-inject is the first thing to check.** Since v1.3.0, Somtum automatically injects top-k memories into every `UserPromptSubmit` via the cache hook — no manual recall step needed.
853
-
854
- 1. Confirm the cache hook is installed: `somtum doctor` → look for `hooks_installed ✓`
855
- 2. If not installed: `somtum init --cache` (or `somtum init --all`)
856
- 3. Confirm injection is enabled: `somtum config get injection.enabled` → should be `true`
857
- 4. Check that memories actually exist: `somtum stats` → `memories > 0`
858
-
859
- **Using the MCP server** (`somtum init --all`), Claude can also call `recall` directly when uncertain. If it's not happening:
860
-
861
- 1. Confirm `.mcp.json` exists: `cat .mcp.json`
862
- 2. Restart Claude Code to pick up the MCP config
863
-
864
- ### Stale memory warning in `somtum doctor`
865
-
866
- `doctor` warns when memories are older than 90 days with no confirmed retrievals. These are observations that have never come up in a search. Options:
867
-
868
- ```bash
869
- # Review them before deciding
870
- somtum search "old topic"
871
-
872
- # Promote useful ones to workspace scope via MCP
873
- remember("...", scope="workspace")
874
-
875
- # Remove irrelevant ones
876
- somtum purge --older-than 90d
877
- ```
878
-
879
- ---
880
-
881
- ### Starting fresh — wiping all memories
882
-
883
- To hard-reset a project's memory (irreversible):
884
-
885
- ```bash
886
- somtum reset
887
- # Permanently delete all memories for this project? [y/N] y
888
- # somtum: reset complete — project <id> wiped.
889
- ```
890
-
891
- To just clear everything softly (recoverable via `somtum export --include-deleted`):
892
-
893
- ```bash
894
- somtum forget --all
895
- ```
896
-
897
- ---
898
-
899
- ## Contributing
900
-
901
- Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for the guide.
902
-
903
- **Important:** This project uses `changesets` for versioning. Every PR must include a changeset file generated by running `pnpm changeset`.
158
+ | Path | What |
159
+ | --- | --- |
160
+ | `src/hooks/` | The three hook handlers: `post_session` (capture), `pre_prompt` (recall), `pre_read` (file gating) |
161
+ | `src/core/` | Store, retrieval, extraction, token ledger, transcript parsing |
162
+ | `src/agents/` | One adapter per agent transcript format. Add an agent here |
163
+ | `src/cli/` | One file per command |
164
+ | `src/db/migrations/` | Numbered, additive SQL migrations |
904
165
 
905
- ---
166
+ Two rules for changes: a hook must never break or block the agent's session, and any new token spend must be bounded and recorded in the ledger. Every PR needs a changeset (`pnpm changeset`). See [CONTRIBUTING.md](CONTRIBUTING.md) and [SPEC.md](SPEC.md) for what's planned.
906
167
 
907
168
  ## License
908
169
 
909
- Licensed under the [MIT License](LICENSE).
170
+ [MIT](LICENSE)