Local-first memory and prompt-cache layer for Claude Code
From the author’s README · Install · not verified by Flowy
$ npm install -g somtum
Repo: riz007/somtum
What's inside
Local-first memory and prompt-cache layer for Claude Code.
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.
Zero-config: one somtum init and every session end is captured automatically. No server, no cloud account, no mandatory tuning.
v2.0.0 — Global DB (
~/.somtum/global.db) · cross-project workspace recall · memory deduplication (superseded_by) ·--show-supersededonsomtum list· stats instrumentation fix · dashboard dark-mode redesignv1.5.0 — Multi-page VitePress docs site ·
somtum list·somtum reset·somtum forget --all· embeddings timeout safety · config crash-resilience ·injection.max_charswired up · warm-start race fix · auth-error hintsv1.3.0 — Auto-inject memories on every prompt ·
updateMCP tool · warm-start after compaction · false-hit detection · workspace scope ·suggest-claude-md· stale memory detection indoctor
LLM agents like Claude Code start every session with a blank slate. That leads to:
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.
Without Somtum With Somtum
──────────────────── ──────────────────────────────────────
Session 1: "We use pnpm Session 1: same work
because of workspace
hoisting"
Session 2: Claude suggests Session 2: Claude already knows about
npm, you correct it pnpm, the auth decisions, and the
again bugfixes from last week
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 in SQLite. On every subsequent prompt, Somtum automatically retrieves the most relevant memories and injects them into context — no manual recall needed.
┌─────────────────────────────────────────────────────────────┐
│ Claude Code Session │
│ │
│ you code · debug · review · make decisions │
└──────────────────────────────┬──────────────────────────────┘
│ SessionEnd / PreCompact
▼
┌─────────────────────────────────────────────────────────────┐
│ Capture Pipeline │
│ │
│ session transcript ──► Haiku extracts observations │
│ │
│ decisions · bug fixes · learnings · commands │
│ │
│ PreCompact ─── writes warm-start file ──► next session │
└──────────────────────────────┬──────────────────────────────┘
│ persisted locally
▼
┌─────────────────────────┐
│ ~/.somtum/projects/ │
│ <project-hash>/ │
│ │
│ db.sqlite │
│ index.md │
│ memories/YYYY-MM/ │
└────────────┬────────────┘
│ every prompt (UserPromptSubmit)
▼
┌─────────────────────────────────────────────────────────────┐
│ Auto-Inject Pipeline (new) │
│ │
│ 1. Prompt cache lookup (exact + fuzzy match) │
│ 2. BM25 recall — top-k relevant memories │
│ 3. Warm-start context (if session just compacted) │
│ │
│ all injected as additionalContext automatically │
└─────────────────────────────────────────────────────────────┘
You work a session debugging an auth bug and refactoring a module. At session end, Somtum extracts something like:
[
{
"kind": "bugfix",
"title": "JWT refresh loop caused by missing expiry check",
"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.",
"files": ["src/auth/refresh.ts"]
},
{
"kind": "decision",
"title": "Use pnpm workspaces — npm hoisting breaks shared types",
"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.",
"files": ["package.json", "pnpm-workspace.yaml"]
}
]
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.
┌─────────────────────────────────────────────────────────────┐
│ Claude Code / Agent │
└──────────┬──────────────────────────────┬───────────────────┘
│ hooks │ MCP tools
▼ ▼
┌─────────────────────┐ ┌──────────────────────────┐
│ Hooks │ │ MCP Tools │
│ │ │ │
│ UserPromptSubmit ──┼─cache──▶│ cache_lookup │
│ ──┼─inject─▶│ recall / get │
│ SessionEnd ────────┼─capture▶│ remember / update │
│ PreCompact ────────┼─warmst─▶│ forget │
│ PreToolUse (Read) ─┼─gate───▶│ stats │
│ │ │ report_false_hit │
└──────────┬──────────┘ └────────────┬─────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Core (TypeScript) │
│ │
│ ┌──────────────┐ ┌─────────────────┐ ┌───────────────┐ │
│ │ PromptCache │ │ MemoryStore │ │ Retriever │ │
│ │ │ │ │ │ │ │
│ │ exact hash │ │ observations │ │ bm25(default) │ │
│ │ fuzzy embed │ │ scope: project │ │ embeddings │ │
│ │ fingerprint │ │ global │ │ index │ │
│ │ false_hits │ │ workspace │ │ hybrid │ │
│ └──────────────┘ │ last_confirmed │ └───────────────┘ │
│ └─────────────────┘ │
└─────────────────────────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────┐
│ SQLite WAL + ~/.somtum/ │
│ /projects/<hash>/ │
│ db.sqlite │
│ index.md │
│ memories/YYYY-MM/<ulid>.md│
│ /session/lh_<id>.json │
│ /warmstart/ws_<id>.json │
└─────────────────────────────┘
| Strategy | How it works | Best for | Cost |
|---|---|---|---|
bm25 | Keyword search over title + body + tags (SQLite FTS5 — no external dependencies) | Exact terms, offline setups | Near-zero |
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 |
index | Sends a compact memory catalog to Haiku; the model picks relevant IDs | Paraphrased or fuzzy queries | 1 Haiku API call |
hybrid | BM25 + embeddings results merged and re-ranked by Haiku | General case (best recall) | BM25 + embeddings + 1 Haiku call |
Default is bm25 — works offline, no setup. Enable hybrid once you have embeddings downloaded.
Caution: Setting
strategy=hybridwithout enabling embeddings causes a silent fallback to BM25 while paying hybrid overhead. Runsomtum doctor— if it showsstrategy=hybridalongsideembeddings: disabled, fix it:somtum config set retrieval.strategy bm25 # match what's actually running # or, to use real hybrid: somtum config set retrieval.embeddings.enabled true && somtum reindex
SessionEnd, UserPromptSubmit, and PreToolUse eventsANTHROPIC_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.npm install -g somtum
pnpm users:
pnpm add -g somtumworks if you have runpnpm setupfirst (setsPNPM_HOME). If you haven't, use npm above.yarn users:
yarn global addis not supported in Yarn v2+ (Berry). Use npm above.
git clone https://github.com/riz007/somtum
cd somtum
pnpm install
pnpm build
pnpm link --global
Somtum uses 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.
FAQ
somtum is a Claude Code plugin with hand-picked skills for development work, indexed on Flowy. Install it with the command on its page. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it