somtum 1.2.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -224
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +18 -4
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +11 -4
- package/dist/cli/serve.js.map +1 -1
- package/dist/core/extractor.d.ts +1 -0
- package/dist/core/extractor.d.ts.map +1 -1
- package/dist/core/extractor.js +46 -0
- package/dist/core/extractor.js.map +1 -1
- package/dist/dashboard/index.html +450 -936
- package/dist/hooks/post_session.d.ts.map +1 -1
- package/dist/hooks/post_session.js +14 -5
- package/dist/hooks/post_session.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
[](https://www.npmjs.com/package/somtum)
|
|
9
9
|
|
|
10
|
-
Somtum (Thai: ส้มตำ) is named after the vibrant, shredded green papaya salad. Just like its namesake, Somtum
|
|
10
|
+
Somtum (Thai: ส้มตำ) is named after the vibrant, shredded green papaya salad. Just like its namesake, Somtum blends durable observations from your Claude Code 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
11
|
|
|
12
|
-
Zero-config: one `somtum init`
|
|
12
|
+
Zero-config: one `somtum init` and every session end is captured automatically. No server, no cloud account, no mandatory tuning.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -37,18 +37,81 @@ Zero-config: one `somtum init` in an existing Claude Code project and every sess
|
|
|
37
37
|
|
|
38
38
|
## Why Somtum?
|
|
39
39
|
|
|
40
|
-
LLM agents like Claude Code
|
|
40
|
+
LLM agents like Claude Code start every session with a blank slate. That leads to:
|
|
41
41
|
|
|
42
|
-
- **Repetitive
|
|
43
|
-
- **Regressions
|
|
44
|
-
- **
|
|
42
|
+
- **Repetitive context** — re-explaining the same architectural choices every session
|
|
43
|
+
- **Regressions** — Claude suggests a fix you already tried and discarded
|
|
44
|
+
- **Token waste** — reading large files just to "set the scene"
|
|
45
45
|
|
|
46
|
-
**Somtum gives Claude a long-term memory.**
|
|
46
|
+
**Somtum gives Claude a long-term memory.** Once a decision is made or a bug is fixed, it's remembered across all future sessions — without bloating your context window.
|
|
47
|
+
|
|
48
|
+
### What a session looks like with Somtum
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
Without Somtum With Somtum
|
|
52
|
+
──────────────────── ──────────────────────────────────────
|
|
53
|
+
Session 1: "We use pnpm Session 1: same work
|
|
54
|
+
because of workspace
|
|
55
|
+
hoisting"
|
|
56
|
+
|
|
57
|
+
Session 2: Claude suggests Session 2: Claude already knows about
|
|
58
|
+
npm, you correct it pnpm, the auth decisions, and the
|
|
59
|
+
again bugfixes from last week
|
|
60
|
+
```
|
|
47
61
|
|
|
48
62
|
---
|
|
49
63
|
|
|
50
64
|
## How it works
|
|
51
65
|
|
|
66
|
+
At the end of each Claude Code session, Somtum reads the session transcript and asks Claude Haiku to extract the parts worth keeping — decisions, bug fixes, things learned. Those observations are stored locally and injected back into context the next time you ask something related.
|
|
67
|
+
|
|
68
|
+
### Memory lifecycle
|
|
69
|
+
|
|
70
|
+
```mermaid
|
|
71
|
+
sequenceDiagram
|
|
72
|
+
participant You
|
|
73
|
+
participant Claude Code
|
|
74
|
+
participant Somtum Hook
|
|
75
|
+
participant SQLite DB
|
|
76
|
+
|
|
77
|
+
You->>Claude Code: Work on project (coding, debugging, decisions)
|
|
78
|
+
Claude Code->>Somtum Hook: SessionEnd fires automatically
|
|
79
|
+
Somtum Hook->>Claude Code: Extract observations via Haiku
|
|
80
|
+
Somtum Hook->>SQLite DB: Store memories locally
|
|
81
|
+
|
|
82
|
+
Note over You,SQLite DB: Next session
|
|
83
|
+
|
|
84
|
+
You->>Claude Code: Ask about the project
|
|
85
|
+
Claude Code->>SQLite DB: recall() via MCP tool
|
|
86
|
+
SQLite DB-->>Claude Code: Relevant past decisions & fixes
|
|
87
|
+
Claude Code-->>You: Answer informed by prior sessions
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### What gets captured — a concrete example
|
|
91
|
+
|
|
92
|
+
You work a session debugging an auth bug and refactoring a module. At session end, Somtum extracts something like:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
[
|
|
96
|
+
{
|
|
97
|
+
"kind": "bugfix",
|
|
98
|
+
"title": "JWT refresh loop caused by missing expiry check",
|
|
99
|
+
"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.",
|
|
100
|
+
"files": ["src/auth/refresh.ts"]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"kind": "decision",
|
|
104
|
+
"title": "Use pnpm workspaces — npm hoisting breaks shared types",
|
|
105
|
+
"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.",
|
|
106
|
+
"files": ["package.json", "pnpm-workspace.yaml"]
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Next session, when you ask "why are we using pnpm?" or touch `src/auth/refresh.ts`, Claude finds these memories and already has the context.
|
|
112
|
+
|
|
113
|
+
### Architecture
|
|
114
|
+
|
|
52
115
|
```
|
|
53
116
|
┌─────────────────────────────────────────────────────────────┐
|
|
54
117
|
│ Claude Code / Agent │
|
|
@@ -60,8 +123,7 @@ LLM agents like Claude Code typically start every session with a "blank slate."
|
|
|
60
123
|
│ │ │ │
|
|
61
124
|
│ UserPromptSubmit ──┼─────────┼▶ cache_lookup │
|
|
62
125
|
│ SessionEnd ────────┼─────────┼▶ recall / get │
|
|
63
|
-
│
|
|
64
|
-
│ PreToolUse (Read) ─┼─────────┼▶ stats │
|
|
126
|
+
│ PreToolUse (Read) ─┼─────────┼▶ remember / forget │
|
|
65
127
|
└──────────┬──────────┘ └──────────┬───────────┘
|
|
66
128
|
│ │
|
|
67
129
|
▼ ▼
|
|
@@ -71,10 +133,10 @@ LLM agents like Claude Code typically start every session with a "blank slate."
|
|
|
71
133
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
|
72
134
|
│ │ PromptCache │ │ MemoryStore │ │ Retriever │ │
|
|
73
135
|
│ │ │ │ │ │ │ │
|
|
74
|
-
│ │ exact hash │ │ observations │ │ bm25 (
|
|
136
|
+
│ │ exact hash │ │ observations │ │ bm25 (default) │ │
|
|
75
137
|
│ │ fuzzy embed │ │ + embeddings │ │ embeddings │ │
|
|
76
|
-
│ │ fingerprint │ │ + redaction │ │ index
|
|
77
|
-
│ │ invalidation │ │ │ │ hybrid
|
|
138
|
+
│ │ fingerprint │ │ + redaction │ │ index │ │
|
|
139
|
+
│ │ invalidation │ │ │ │ hybrid │ │
|
|
78
140
|
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
|
|
79
141
|
└─────────────────────────────────┬───────────────────────────┘
|
|
80
142
|
│
|
|
@@ -89,14 +151,16 @@ LLM agents like Claude Code typically start every session with a "blank slate."
|
|
|
89
151
|
└─────────────────────────┘
|
|
90
152
|
```
|
|
91
153
|
|
|
92
|
-
###
|
|
154
|
+
### Retrieval strategies
|
|
155
|
+
|
|
156
|
+
| Strategy | How it works | Best for | Cost |
|
|
157
|
+
|---|---|---|---|
|
|
158
|
+
| **`bm25`** | Keyword search over title + body + tags (SQLite FTS5 — no external dependencies) | Exact terms, offline setups | Near-zero |
|
|
159
|
+
| **`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 |
|
|
160
|
+
| **`index`** | Sends a compact memory catalog to Haiku; the model picks relevant IDs | Paraphrased or fuzzy queries | 1 Haiku API call |
|
|
161
|
+
| **`hybrid`** | BM25 + embeddings results merged and re-ranked by Haiku | General case (best recall) | BM25 + embeddings + 1 Haiku call |
|
|
93
162
|
|
|
94
|
-
|
|
95
|
-
| ------------------------ | ---------------------------------------------------------------- | ---------------------------------------- | ----------------------------------- |
|
|
96
|
-
| **`bm25`** | SQLite FTS5 lexical search over title + body + tags | Keyword queries, offline-forever setups | Near-zero |
|
|
97
|
-
| **`embeddings`** | Cosine similarity over 384-dim vectors (bge-small-en-v1.5, ONNX) | Semantic queries, large corpora | ~30 MB model, ~5 ms at 10k memories |
|
|
98
|
-
| **`index`** | Compact catalog sent to Haiku; model picks relevant IDs | Paraphrased queries, zero-embedding mode | 1 Haiku call per query |
|
|
99
|
-
| **`hybrid`** _(default)_ | BM25 top-50 ∪ embeddings top-50 → RRF blend → Haiku rerank | General case | BM25 + embeddings + 1 Haiku call |
|
|
163
|
+
**Default is `bm25`** — works offline, no setup. Enable `hybrid` once you have embeddings downloaded.
|
|
100
164
|
|
|
101
165
|
---
|
|
102
166
|
|
|
@@ -104,16 +168,14 @@ LLM agents like Claude Code typically start every session with a "blank slate."
|
|
|
104
168
|
|
|
105
169
|
- **Node 20+**
|
|
106
170
|
- **Claude Code** — Somtum hooks into Claude Code's `SessionEnd`, `UserPromptSubmit`, and `PreToolUse` events
|
|
107
|
-
- **`ANTHROPIC_API_KEY`** —
|
|
108
|
-
|
|
109
|
-
> `pnpm` is only required if building from source. Global npm/yarn installs have no pnpm dependency.
|
|
171
|
+
- **`ANTHROPIC_API_KEY`** _(optional)_ — if set, Somtum uses the Anthropic API directly for extraction. If not set, Somtum falls back to the `claude` CLI that ships with Claude Code, so **no separate API key is required for Claude Code subscribers**.
|
|
110
172
|
|
|
111
173
|
---
|
|
112
174
|
|
|
113
175
|
## Install
|
|
114
176
|
|
|
115
177
|
```bash
|
|
116
|
-
# npm (recommended
|
|
178
|
+
# npm (recommended)
|
|
117
179
|
npm install -g somtum
|
|
118
180
|
|
|
119
181
|
# yarn
|
|
@@ -141,58 +203,58 @@ pnpm link --global
|
|
|
141
203
|
|
|
142
204
|
### Native module note
|
|
143
205
|
|
|
144
|
-
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.
|
|
206
|
+
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.
|
|
145
207
|
|
|
146
208
|
---
|
|
147
209
|
|
|
148
210
|
## Quickstart
|
|
149
211
|
|
|
150
|
-
### Step 1 —
|
|
212
|
+
### Step 1 — Choose your extraction backend
|
|
151
213
|
|
|
152
|
-
|
|
214
|
+
Somtum needs to call a Claude model at session end to extract observations. Pick one:
|
|
153
215
|
|
|
154
|
-
|
|
216
|
+
**Option A: Claude Code subscription (no extra setup)**
|
|
155
217
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
218
|
+
If you already have Claude Code installed, you're done. Somtum calls `claude --print` automatically when no API key is present. Skip to Step 2.
|
|
219
|
+
|
|
220
|
+
**Option B: Direct Anthropic API key (optional — faster, lets you pick the model)**
|
|
159
221
|
|
|
160
|
-
|
|
222
|
+
Add to `~/.zshrc` (or `~/.bashrc`):
|
|
161
223
|
|
|
162
224
|
```bash
|
|
163
|
-
|
|
225
|
+
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
164
226
|
```
|
|
165
227
|
|
|
166
|
-
|
|
228
|
+
Then reload:
|
|
167
229
|
|
|
168
230
|
```bash
|
|
169
|
-
|
|
231
|
+
source ~/.zshrc
|
|
170
232
|
```
|
|
171
233
|
|
|
234
|
+
> The key must be in your shell profile, not just exported in an open terminal tab. The `SessionEnd` hook inherits the environment of the shell that _started_ Claude Code — not the current terminal.
|
|
235
|
+
|
|
172
236
|
### Step 2 — Install inside a Claude Code project
|
|
173
237
|
|
|
174
|
-
Run this from the **root of the project you work
|
|
238
|
+
Run this from the **root of the project you work on with Claude Code**:
|
|
175
239
|
|
|
176
240
|
```bash
|
|
177
241
|
somtum init
|
|
178
242
|
```
|
|
179
243
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
To enable all features at once:
|
|
244
|
+
To enable all features at once (recommended):
|
|
183
245
|
|
|
184
246
|
```bash
|
|
185
247
|
somtum init --all
|
|
186
248
|
# Installs:
|
|
187
249
|
# - SessionEnd capture hook (memory extraction)
|
|
188
250
|
# - UserPromptSubmit cache hook (prompt cache lookup)
|
|
189
|
-
# - PreToolUse file-gating hook (file
|
|
251
|
+
# - PreToolUse file-gating hook (large file summarization)
|
|
190
252
|
# - MCP server in .mcp.json (Claude can call recall/remember tools)
|
|
191
253
|
```
|
|
192
254
|
|
|
193
255
|
### Step 3 — Use Claude Code normally
|
|
194
256
|
|
|
195
|
-
Open a Claude Code session **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
|
|
257
|
+
Open a Claude Code session **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).
|
|
196
258
|
|
|
197
259
|
### Step 4 — Check your memory
|
|
198
260
|
|
|
@@ -216,7 +278,7 @@ If `somtum stats` shows `memories 0` after a session, see [Troubleshooting](#tro
|
|
|
216
278
|
somtum doctor
|
|
217
279
|
```
|
|
218
280
|
|
|
219
|
-
This checks your API key, DB health, hook installation, migrations, cache, and breakeven ratio
|
|
281
|
+
This checks your API key, DB health, hook installation, migrations, cache, and breakeven ratio — with specific fix instructions for each failing check.
|
|
220
282
|
|
|
221
283
|
---
|
|
222
284
|
|
|
@@ -226,24 +288,29 @@ After your **first** Claude Code session ends:
|
|
|
226
288
|
|
|
227
289
|
**1. Check the hook log**
|
|
228
290
|
|
|
229
|
-
Every hook run appends a timestamped line to `~/.somtum/hook.log`:
|
|
230
|
-
|
|
231
291
|
```bash
|
|
232
292
|
cat ~/.somtum/hook.log
|
|
233
293
|
```
|
|
234
294
|
|
|
235
|
-
A successful run
|
|
295
|
+
A successful run:
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
2026-04-30T10:15:42.123Z [post_session] starting
|
|
299
|
+
2026-04-30T10:15:44.891Z [post_session] ok — inserted=4 cache=2 summaries=1
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Using the `claude` CLI fallback (no API key):
|
|
236
303
|
|
|
237
304
|
```
|
|
238
305
|
2026-04-30T10:15:42.123Z [post_session] starting
|
|
306
|
+
2026-04-30T10:15:42.124Z [post_session] ANTHROPIC_API_KEY not set — will use claude CLI fallback
|
|
239
307
|
2026-04-30T10:15:44.891Z [post_session] ok — inserted=4 cache=2 summaries=1
|
|
240
308
|
```
|
|
241
309
|
|
|
242
|
-
|
|
310
|
+
Neither backend available:
|
|
243
311
|
|
|
244
312
|
```
|
|
245
|
-
2026-04-30T10:15:42.123Z [post_session]
|
|
246
|
-
2026-04-30T10:15:42.131Z [post_session] ERROR: 401 authentication_error
|
|
313
|
+
2026-04-30T10:15:42.123Z [post_session] ERROR: Neither ANTHROPIC_API_KEY nor the claude CLI is available.
|
|
247
314
|
```
|
|
248
315
|
|
|
249
316
|
**2. Check stats**
|
|
@@ -252,7 +319,7 @@ A failed run with a missing API key looks like:
|
|
|
252
319
|
somtum stats
|
|
253
320
|
```
|
|
254
321
|
|
|
255
|
-
You should see `memories
|
|
322
|
+
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.
|
|
256
323
|
|
|
257
324
|
**3. Run doctor**
|
|
258
325
|
|
|
@@ -266,28 +333,24 @@ All checks should show `✓`. The `api_key` and `hooks_installed` checks are the
|
|
|
266
333
|
|
|
267
334
|
## Dashboard
|
|
268
335
|
|
|
269
|
-
Somtum includes a visual memory browser you can open at any time:
|
|
270
|
-
|
|
271
336
|
```bash
|
|
272
337
|
somtum serve
|
|
273
|
-
# Opens http://localhost:3000
|
|
338
|
+
# Opens http://localhost:3000
|
|
274
339
|
```
|
|
275
340
|
|
|
276
|
-
The dashboard
|
|
341
|
+
The dashboard has four views:
|
|
277
342
|
|
|
278
|
-
- **Memory browser** — searchable, filterable list of all captured observations.
|
|
279
|
-
- **Knowledge graph** —
|
|
280
|
-
- **Analytics** — kind breakdown, cache hit rate, retrieval strategy usage,
|
|
343
|
+
- **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.
|
|
344
|
+
- **Knowledge graph** — nodes are memories, edges connect memories that share files or tags. Click a node to open it in the detail panel.
|
|
345
|
+
- **Analytics** — kind breakdown, cache hit rate, retrieval strategy usage, top-referenced files.
|
|
281
346
|
- **Forget button** — soft-delete any memory directly from the browser.
|
|
282
347
|
|
|
283
|
-
|
|
348
|
+
| Flag | Default | Description |
|
|
349
|
+
|---|---|---|
|
|
350
|
+
| `--port <n>` | 3000 | Listen on a custom port |
|
|
351
|
+
| `--no-open` | — | Start server without opening the browser |
|
|
284
352
|
|
|
285
|
-
|
|
286
|
-
| ------------ | -------------------------------------- |
|
|
287
|
-
| `--port <n>` | Listen on a custom port (default 3000) |
|
|
288
|
-
| `--no-open` | Don't auto-open the browser |
|
|
289
|
-
|
|
290
|
-
Press `Ctrl-C` to stop the server.
|
|
353
|
+
Press `Ctrl-C` to stop.
|
|
291
354
|
|
|
292
355
|
---
|
|
293
356
|
|
|
@@ -295,169 +358,171 @@ Press `Ctrl-C` to stop the server.
|
|
|
295
358
|
|
|
296
359
|
### Setup
|
|
297
360
|
|
|
298
|
-
| Command
|
|
299
|
-
|
|
300
|
-
| `somtum init`
|
|
301
|
-
| `somtum init --cache`
|
|
302
|
-
| `somtum init --file-gating` | Also install the PreToolUse file-gating hook
|
|
303
|
-
| `somtum init --all`
|
|
304
|
-
| `somtum init --force`
|
|
305
|
-
| `somtum doctor`
|
|
361
|
+
| Command | Description |
|
|
362
|
+
|---|---|
|
|
363
|
+
| `somtum init` | Install the SessionEnd capture hook |
|
|
364
|
+
| `somtum init --cache` | Also install the UserPromptSubmit cache hook |
|
|
365
|
+
| `somtum init --file-gating` | Also install the PreToolUse file-gating hook |
|
|
366
|
+
| `somtum init --all` | Install all hooks + MCP server |
|
|
367
|
+
| `somtum init --force` | Reinstall even if hooks already present |
|
|
368
|
+
| `somtum doctor` | Check DB health, migrations, hooks, API key, breakeven ratio |
|
|
306
369
|
|
|
307
370
|
### Memory
|
|
308
371
|
|
|
309
|
-
| Command
|
|
310
|
-
|
|
311
|
-
| `somtum search <query>`
|
|
312
|
-
| `somtum search <query> --strategy
|
|
313
|
-
| `somtum search <query> -k 16`
|
|
314
|
-
| `somtum show <id>`
|
|
315
|
-
| `somtum
|
|
316
|
-
| `somtum
|
|
317
|
-
| `somtum
|
|
318
|
-
| `somtum
|
|
372
|
+
| Command | Description |
|
|
373
|
+
|---|---|
|
|
374
|
+
| `somtum search <query>` | Search observations (default: `bm25` strategy) |
|
|
375
|
+
| `somtum search <query> --strategy hybrid` | Force a specific retrieval strategy |
|
|
376
|
+
| `somtum search <query> -k 16` | Return more results |
|
|
377
|
+
| `somtum show <id>` | Print the full body of an observation |
|
|
378
|
+
| `somtum remember` | Manually store an observation |
|
|
379
|
+
| `somtum forget <id>` | Soft-delete an observation |
|
|
380
|
+
| `somtum edit <id>` | Open an observation body in `$EDITOR` |
|
|
381
|
+
| `somtum rebuild` | Regenerate `index.md` from all observations |
|
|
382
|
+
| `somtum reindex` | Recompute embeddings (after enabling embeddings or changing model) |
|
|
319
383
|
|
|
320
384
|
### Stats & Visibility
|
|
321
385
|
|
|
322
|
-
| Command
|
|
323
|
-
|
|
324
|
-
| `somtum stats`
|
|
325
|
-
| `somtum stats --json`
|
|
326
|
-
| `somtum serve`
|
|
327
|
-
| `somtum serve --port <n>` | Use a custom port (default 3000)
|
|
328
|
-
| `somtum serve --no-open`
|
|
329
|
-
|
|
330
|
-
### Data
|
|
331
|
-
|
|
332
|
-
| Command
|
|
333
|
-
|
|
334
|
-
| `somtum export`
|
|
335
|
-
| `somtum export --format jsonl --output obs.jsonl` | Export as JSONL file
|
|
336
|
-
| `somtum export --format markdown`
|
|
337
|
-
| `somtum export --include-deleted`
|
|
338
|
-
| `somtum import <file>`
|
|
339
|
-
| `somtum purge --older-than 30d`
|
|
340
|
-
| `somtum purge --older-than 30d --dry-run`
|
|
341
|
-
|
|
342
|
-
### Stats & visibility
|
|
343
|
-
|
|
344
|
-
| Command | Description |
|
|
345
|
-
| ---------------- | ------------------------------------------- |
|
|
346
|
-
| `somtum reindex` | Embed observations that are missing vectors |
|
|
386
|
+
| Command | Description |
|
|
387
|
+
|---|---|
|
|
388
|
+
| `somtum stats` | Tokens saved, cache hit rate, retrieval breakdown |
|
|
389
|
+
| `somtum stats --json` | Machine-readable JSON output |
|
|
390
|
+
| `somtum serve` | Open the visual dashboard in the browser |
|
|
391
|
+
| `somtum serve --port <n>` | Use a custom port (default 3000) |
|
|
392
|
+
| `somtum serve --no-open` | Start server without opening the browser |
|
|
393
|
+
|
|
394
|
+
### Data Management
|
|
395
|
+
|
|
396
|
+
| Command | Description |
|
|
397
|
+
|---|---|
|
|
398
|
+
| `somtum export` | Export observations to stdout as JSON |
|
|
399
|
+
| `somtum export --format jsonl --output obs.jsonl` | Export as JSONL file |
|
|
400
|
+
| `somtum export --format markdown` | Export as readable Markdown |
|
|
401
|
+
| `somtum export --include-deleted` | Include soft-deleted entries |
|
|
402
|
+
| `somtum import <file>` | Import observations from JSON or JSONL |
|
|
403
|
+
| `somtum purge --older-than 30d` | Hard-delete soft-deleted entries older than 30 days |
|
|
404
|
+
| `somtum purge --older-than 30d --dry-run` | Preview without deleting |
|
|
347
405
|
|
|
348
406
|
### Configuration
|
|
349
407
|
|
|
350
|
-
| Command
|
|
351
|
-
|
|
352
|
-
| `somtum config get`
|
|
353
|
-
| `somtum config get retrieval.strategy`
|
|
354
|
-
| `somtum config set retrieval.strategy hybrid`
|
|
355
|
-
| `somtum config set retrieval.embeddings.enabled true --global` | Write to `~/.somtum/config.json`
|
|
408
|
+
| Command | Description |
|
|
409
|
+
|---|---|
|
|
410
|
+
| `somtum config get` | Print the full resolved config |
|
|
411
|
+
| `somtum config get retrieval.strategy` | Read a single key (dot-separated) |
|
|
412
|
+
| `somtum config set retrieval.strategy hybrid` | Write to `.somtum/config.json` |
|
|
413
|
+
| `somtum config set retrieval.embeddings.enabled true --global` | Write to `~/.somtum/config.json` |
|
|
356
414
|
|
|
357
415
|
### Sync
|
|
358
416
|
|
|
359
|
-
| Command
|
|
360
|
-
|
|
417
|
+
| Command | Description |
|
|
418
|
+
|---|---|
|
|
361
419
|
| `somtum sync status` | Compare local vs remote observation count |
|
|
362
|
-
| `somtum sync push`
|
|
363
|
-
| `somtum sync pull`
|
|
420
|
+
| `somtum sync push` | Export and scp observations to remote |
|
|
421
|
+
| `somtum sync pull` | scp from remote and merge into local DB |
|
|
422
|
+
|
|
423
|
+
Set your remote: `somtum config set sync.remote "user@host:/path/.somtum/projects/<id>"`
|
|
364
424
|
|
|
365
|
-
|
|
366
|
-
Somtum uses hostname-aware syncing to prevent data loss when using multiple devices.
|
|
425
|
+
Somtum uses hostname-aware syncing — merging observations from multiple machines without data loss.
|
|
367
426
|
|
|
368
427
|
---
|
|
369
428
|
|
|
370
429
|
## MCP Server
|
|
371
430
|
|
|
372
|
-
|
|
431
|
+
When you run `somtum init --all`, Somtum registers an MCP server that Claude can call autonomously during a session:
|
|
373
432
|
|
|
374
|
-
| Tool
|
|
375
|
-
|
|
376
|
-
| `recall`
|
|
377
|
-
| `get`
|
|
378
|
-
| `remember`
|
|
379
|
-
| `cache_lookup` |
|
|
380
|
-
| `forget`
|
|
381
|
-
| `stats`
|
|
433
|
+
| Tool | What Claude does with it |
|
|
434
|
+
|---|---|
|
|
435
|
+
| `recall` | Searches memories when unsure about a project detail |
|
|
436
|
+
| `get` | Retrieves the full body of specific observations by ID |
|
|
437
|
+
| `remember` | Stores an observation manually from within a session |
|
|
438
|
+
| `cache_lookup` | Checks the prompt cache directly |
|
|
439
|
+
| `forget` | Soft-deletes an observation |
|
|
440
|
+
| `stats` | Reports tokens saved, cache hit rate, and corpus size |
|
|
382
441
|
|
|
383
442
|
Every MCP response includes a `tokens` field so Claude can account for retrieval cost.
|
|
384
443
|
|
|
385
444
|
---
|
|
386
445
|
|
|
387
|
-
##
|
|
388
|
-
|
|
389
|
-
`somtum serve` opens a local web dashboard at `http://localhost:3000`:
|
|
390
|
-
|
|
391
|
-
- **Memory browser** — search across all observations using BM25, hybrid, or embedding-based retrieval; filter by kind (decision, bugfix, learning, command, file_summary); forget memories directly from the UI.
|
|
392
|
-
- **Knowledge graph** — vis-network graph where nodes are observations, edges represent shared files or tags. Clicking a node selects the memory in the list and vice versa.
|
|
393
|
-
- **Analytics tab** — kind breakdown, token ROI (saved vs. spent), cache hit rate + entry count, retrieval strategy usage, and top files by reference count.
|
|
394
|
-
- **Stat bar** — live counts for total memories, tokens saved, tokens spent, ROI ratio, and cache hit %.
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
somtum serve # opens on port 3000
|
|
398
|
-
somtum serve --port 4000 # custom port
|
|
399
|
-
somtum serve --no-open # don't auto-open the browser
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
---
|
|
403
|
-
|
|
404
|
-
## Storage layout
|
|
446
|
+
## Storage Layout
|
|
405
447
|
|
|
406
448
|
```
|
|
407
449
|
~/.somtum/
|
|
408
|
-
├── config.json ← global config (
|
|
450
|
+
├── config.json ← global config (merged with project config)
|
|
409
451
|
├── hook.log ← timestamped log of every hook execution
|
|
410
452
|
└── projects/
|
|
411
453
|
└── <project_id>/
|
|
412
454
|
├── db.sqlite ← source of truth (SQLite WAL)
|
|
413
|
-
├── index.md ←
|
|
455
|
+
├── index.md ← human-readable mirror (regenerated)
|
|
414
456
|
└── memories/
|
|
415
457
|
└── YYYY-MM/
|
|
416
458
|
└── <ulid>.md ← per-observation markdown files
|
|
417
459
|
```
|
|
418
460
|
|
|
419
|
-
The project ID is derived from the git remote URL (
|
|
461
|
+
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.
|
|
420
462
|
|
|
421
|
-
SQLite is the source of truth.
|
|
463
|
+
SQLite is the source of truth. Edit observations with `somtum edit <id>`, not by hand.
|
|
422
464
|
|
|
423
465
|
---
|
|
424
466
|
|
|
425
467
|
## Configuration
|
|
426
468
|
|
|
427
|
-
Global config lives at `~/.somtum/config.json`. Per-project config at `.somtum/config.json`
|
|
469
|
+
Global config lives at `~/.somtum/config.json`. Per-project config at `.somtum/config.json` overrides it (deep merge).
|
|
470
|
+
|
|
471
|
+
### Most common settings
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
# Enable semantic (embedding-based) search — downloads a 30 MB model once
|
|
475
|
+
somtum config set retrieval.embeddings.enabled true
|
|
476
|
+
somtum reindex
|
|
477
|
+
|
|
478
|
+
# Switch to hybrid retrieval (BM25 + embeddings + rerank) for best recall
|
|
479
|
+
somtum config set retrieval.strategy hybrid
|
|
480
|
+
|
|
481
|
+
# Use LLM-based retrieval (no embeddings required, costs one Haiku call per query)
|
|
482
|
+
somtum config set retrieval.index.enabled true
|
|
483
|
+
somtum config set retrieval.strategy index
|
|
484
|
+
|
|
485
|
+
# Intercept large file reads and summarize them (reduces context bloat)
|
|
486
|
+
somtum config set file_gating.enabled true
|
|
487
|
+
|
|
488
|
+
# Limit observations extracted per session (default: 10)
|
|
489
|
+
somtum config set extraction.max_observations_per_session 5
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Full config reference
|
|
428
493
|
|
|
429
494
|
```jsonc
|
|
430
495
|
{
|
|
431
496
|
"extraction": {
|
|
432
497
|
"model": "claude-haiku-4-5-20251001",
|
|
433
498
|
"trigger": ["SessionEnd", "PreCompact"],
|
|
434
|
-
"max_observations_per_session": 10
|
|
499
|
+
"max_observations_per_session": 10
|
|
435
500
|
},
|
|
436
501
|
"cache": {
|
|
437
502
|
"enabled": true,
|
|
438
503
|
"fuzzy_match": true,
|
|
439
504
|
"fuzzy_threshold": 0.92, // raise to 0.95 once you have signal
|
|
440
505
|
"max_entries": 10000,
|
|
441
|
-
"ttl_days": 90
|
|
506
|
+
"ttl_days": 90
|
|
442
507
|
},
|
|
443
508
|
"retrieval": {
|
|
444
|
-
"strategy": "
|
|
509
|
+
"strategy": "bm25", // bm25 | embeddings | index | hybrid
|
|
445
510
|
"k": 8,
|
|
446
511
|
"rerank_model": "claude-haiku-4-5-20251001",
|
|
447
512
|
"bm25": { "enabled": true },
|
|
448
513
|
"embeddings": {
|
|
449
514
|
"enabled": false, // set true to download the 30 MB ONNX model
|
|
450
|
-
"model": "Xenova/bge-small-en-v1.5"
|
|
515
|
+
"model": "Xenova/bge-small-en-v1.5"
|
|
451
516
|
},
|
|
452
517
|
"index": {
|
|
453
518
|
"enabled": false, // set true to use Haiku as the retriever
|
|
454
|
-
"model": "claude-haiku-4-5-20251001"
|
|
455
|
-
}
|
|
519
|
+
"model": "claude-haiku-4-5-20251001"
|
|
520
|
+
}
|
|
456
521
|
},
|
|
457
522
|
"file_gating": {
|
|
458
523
|
"enabled": false, // set true to intercept large file reads
|
|
459
524
|
"min_file_size_tokens": 500,
|
|
460
|
-
"exclude_globs": ["**/*.env", "**/secrets/**"]
|
|
525
|
+
"exclude_globs": ["**/*.env", "**/secrets/**"]
|
|
461
526
|
},
|
|
462
527
|
"privacy": {
|
|
463
528
|
"telemetry": false,
|
|
@@ -466,37 +531,30 @@ Global config lives at `~/.somtum/config.json`. Per-project config at `.somtum/c
|
|
|
466
531
|
"bearer\\s+[A-Za-z0-9_\\-.]+",
|
|
467
532
|
"sk-[A-Za-z0-9_\\-]{20,}",
|
|
468
533
|
"xox[baprs]-[A-Za-z0-9-]{10,}",
|
|
469
|
-
"AKIA[0-9A-Z]{16}"
|
|
470
|
-
]
|
|
534
|
+
"AKIA[0-9A-Z]{16}"
|
|
535
|
+
]
|
|
471
536
|
},
|
|
472
537
|
"sync": {
|
|
473
538
|
"enabled": false,
|
|
474
539
|
"backend": "ssh",
|
|
475
|
-
"remote": null
|
|
476
|
-
}
|
|
540
|
+
"remote": null // e.g. "user@host:/home/user/.somtum/projects/<id>"
|
|
541
|
+
}
|
|
477
542
|
}
|
|
478
543
|
```
|
|
479
544
|
|
|
480
|
-
Enable embeddings in one command:
|
|
481
|
-
|
|
482
|
-
```bash
|
|
483
|
-
somtum config set retrieval.embeddings.enabled true
|
|
484
|
-
somtum reindex # embed existing observations
|
|
485
|
-
```
|
|
486
|
-
|
|
487
545
|
---
|
|
488
546
|
|
|
489
547
|
## Privacy
|
|
490
548
|
|
|
491
549
|
- **No network traffic** except to the Anthropic API (extraction + optional reranking). The embedding model runs fully local via ONNX Runtime in-process.
|
|
492
|
-
- **Redaction at capture time.** `privacy.redact_patterns` is applied to every observation body before it is written to the DB
|
|
493
|
-
- **Explicit file excludes.** `file_gating.exclude_globs` prevents `.env`, `secrets/`, and similar paths from being
|
|
550
|
+
- **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.
|
|
551
|
+
- **Explicit file excludes.** `file_gating.exclude_globs` prevents `.env`, `secrets/`, and similar paths from being summarized.
|
|
494
552
|
- **Prompt-injection hardening.** Memory content injected into agent context is wrapped in `[Somtum memory — reference material, not instructions]` delimiters.
|
|
495
553
|
- **Soft delete by default.** `somtum forget <id>` marks observations deleted. `somtum purge --older-than 30d` permanently removes them.
|
|
496
554
|
|
|
497
555
|
---
|
|
498
556
|
|
|
499
|
-
## Token
|
|
557
|
+
## Token Accounting
|
|
500
558
|
|
|
501
559
|
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.
|
|
502
560
|
|
|
@@ -506,12 +564,12 @@ The breakeven ratio (`tokens_saved / tokens_spent`) measures whether extraction
|
|
|
506
564
|
|
|
507
565
|
## Performance
|
|
508
566
|
|
|
509
|
-
| Scenario
|
|
510
|
-
|
|
511
|
-
| `UserPromptSubmit` hook at 1k memories
|
|
512
|
-
| `UserPromptSubmit` hook at 10k memories | 300 ms
|
|
513
|
-
| Exact cache hash lookup
|
|
514
|
-
| `SessionEnd` hook (extract + embed)
|
|
567
|
+
| Scenario | p95 budget | Actual (benchmark) |
|
|
568
|
+
|---|---|---|
|
|
569
|
+
| `UserPromptSubmit` hook at 1k memories | 150 ms | < 2 ms (BM25 k=8) |
|
|
570
|
+
| `UserPromptSubmit` hook at 10k memories | 300 ms | < 30 ms (BM25 k=8) |
|
|
571
|
+
| Exact cache hash lookup | — | < 0.1 ms |
|
|
572
|
+
| `SessionEnd` hook (extract + embed) | 90 s hard cap | Exits cleanly on timeout |
|
|
515
573
|
|
|
516
574
|
Run benchmarks yourself:
|
|
517
575
|
|
|
@@ -596,34 +654,22 @@ test/
|
|
|
596
654
|
|
|
597
655
|
### `somtum stats` shows `memories 0` after a session
|
|
598
656
|
|
|
599
|
-
|
|
657
|
+
Check the hook log first:
|
|
600
658
|
|
|
601
659
|
```bash
|
|
602
660
|
cat ~/.somtum/hook.log
|
|
603
661
|
```
|
|
604
662
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
**`ANTHROPIC_API_KEY` not set in shell profile**
|
|
663
|
+
**`claude` CLI not found and no `ANTHROPIC_API_KEY` set**
|
|
608
664
|
|
|
609
|
-
|
|
665
|
+
- If you use Claude Code: run `which claude` — if nothing prints, reinstall Claude Code or add its binary to your `PATH`.
|
|
666
|
+
- If you prefer the direct API: add `export ANTHROPIC_API_KEY="sk-ant-..."` to `~/.zshrc` and `source ~/.zshrc`. Must be in your profile, not just exported in the current terminal tab.
|
|
610
667
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
```bash
|
|
614
|
-
# Add to ~/.zshrc or ~/.bashrc
|
|
615
|
-
echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.zshrc
|
|
616
|
-
source ~/.zshrc
|
|
617
|
-
|
|
618
|
-
# Confirm it's set
|
|
619
|
-
echo $ANTHROPIC_API_KEY
|
|
620
|
-
|
|
621
|
-
# Then open a new Claude session
|
|
622
|
-
```
|
|
668
|
+
Run `somtum doctor` — the `api_key` check tells you exactly which backend is available.
|
|
623
669
|
|
|
624
670
|
**Hook not installed in the right directory**
|
|
625
671
|
|
|
626
|
-
`somtum init` writes the hook to `.claude/settings.json` in the directory where you ran it. If you
|
|
672
|
+
`somtum init` writes the hook to `.claude/settings.json` in the directory where you ran it. If you launch Claude Code from a different directory, it reads a different settings file.
|
|
627
673
|
|
|
628
674
|
Fix: run `somtum init` from the same directory you use to launch Claude Code.
|
|
629
675
|
|
|
@@ -635,17 +681,7 @@ claude # must be launched from ~/my-project
|
|
|
635
681
|
|
|
636
682
|
**Short or trivial session**
|
|
637
683
|
|
|
638
|
-
If the session
|
|
639
|
-
|
|
640
|
-
Try a real working session, then re-check.
|
|
641
|
-
|
|
642
|
-
**Run `somtum doctor`** for a full diagnostic:
|
|
643
|
-
|
|
644
|
-
```bash
|
|
645
|
-
somtum doctor
|
|
646
|
-
```
|
|
647
|
-
|
|
648
|
-
It checks the API key, hook installation, DB health, embeddings, breakeven ratio, and more, with specific fix instructions for each failing check.
|
|
684
|
+
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.
|
|
649
685
|
|
|
650
686
|
---
|
|
651
687
|
|
|
@@ -667,8 +703,6 @@ pnpm build
|
|
|
667
703
|
|
|
668
704
|
### `somtum serve` — port already in use
|
|
669
705
|
|
|
670
|
-
If port 3000 is busy, use `--port`:
|
|
671
|
-
|
|
672
706
|
```bash
|
|
673
707
|
somtum serve --port 3001
|
|
674
708
|
```
|
|
@@ -677,24 +711,18 @@ somtum serve --port 3001
|
|
|
677
711
|
|
|
678
712
|
### Agent appears to keep running after session ends
|
|
679
713
|
|
|
680
|
-
The `SessionEnd` hook has a hard 90-second timeout
|
|
714
|
+
The `SessionEnd` hook has a hard 90-second timeout. If sessions appear stuck, verify you are on v1.1.0+:
|
|
681
715
|
|
|
682
716
|
```bash
|
|
683
717
|
somtum --version
|
|
684
|
-
```
|
|
685
|
-
|
|
686
|
-
And check the log for any long-running operations:
|
|
687
|
-
|
|
688
|
-
```bash
|
|
689
718
|
tail -20 ~/.somtum/hook.log
|
|
690
719
|
```
|
|
691
720
|
|
|
692
721
|
---
|
|
693
722
|
|
|
694
|
-
|
|
695
723
|
### Installation fails (node-gyp / better-sqlite3)
|
|
696
724
|
|
|
697
|
-
|
|
725
|
+
Ensure build tools are installed:
|
|
698
726
|
|
|
699
727
|
- **macOS:** `xcode-select --install`
|
|
700
728
|
- **Ubuntu/Debian:** `sudo apt-get install build-essential python3`
|
|
@@ -704,28 +732,28 @@ If you see errors related to building `better-sqlite3`, ensure build tools are i
|
|
|
704
732
|
|
|
705
733
|
### Embeddings are slow or the model won't download
|
|
706
734
|
|
|
707
|
-
The first `somtum reindex` downloads a ~30 MB ONNX model
|
|
735
|
+
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.
|
|
708
736
|
|
|
709
|
-
|
|
737
|
+
On an air-gapped machine or if you prefer not to use embeddings:
|
|
710
738
|
|
|
711
739
|
```bash
|
|
712
740
|
somtum config set retrieval.embeddings.enabled false
|
|
713
741
|
somtum config set retrieval.strategy bm25
|
|
714
742
|
```
|
|
715
743
|
|
|
716
|
-
BM25
|
|
744
|
+
BM25 works fully offline and is fast at any corpus size.
|
|
717
745
|
|
|
718
746
|
---
|
|
719
747
|
|
|
720
748
|
### Claude isn't using the memories
|
|
721
749
|
|
|
722
|
-
If you are using the MCP server (`somtum init --all`), Claude
|
|
750
|
+
If you are using the MCP server (`somtum init --all`), Claude calls `recall` automatically when uncertain about project details. If it's not happening:
|
|
723
751
|
|
|
724
|
-
1. Confirm `.mcp.json` exists
|
|
725
|
-
2. Restart Claude Code
|
|
726
|
-
3.
|
|
752
|
+
1. Confirm `.mcp.json` exists: `cat .mcp.json`
|
|
753
|
+
2. Restart Claude Code to pick up the MCP config
|
|
754
|
+
3. Prompt explicitly: _"Check your Somtum memory for anything related to our auth setup"_
|
|
727
755
|
|
|
728
|
-
If you are not using the MCP server, memories are injected via
|
|
756
|
+
If you are not using the MCP server, memories are injected via `index.md`. Reference it in your CLAUDE.md:
|
|
729
757
|
|
|
730
758
|
```
|
|
731
759
|
See ~/.somtum/projects/<project_id>/index.md for prior session learnings.
|
|
@@ -735,7 +763,7 @@ See ~/.somtum/projects/<project_id>/index.md for prior session learnings.
|
|
|
735
763
|
|
|
736
764
|
## Contributing
|
|
737
765
|
|
|
738
|
-
Contributions are welcome!
|
|
766
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for the guide.
|
|
739
767
|
|
|
740
768
|
**Important:** This project uses `changesets` for versioning. Every PR must include a changeset file generated by running `pnpm changeset`.
|
|
741
769
|
|