Token-efficient persistent project memory for Claude Code. Hook-enforced behaviors, stable entry IDs, reference-counted retrieval that gets sharper the more you use it.
Naive memory systems either dump the whole context (expensive) or rely on the model to remember (unreliable). thinkbetter keeps a compact grep-able file per project, injects only what is actionable, and gets cheaper as references accumulate.
- SessionStart emits zero output on clean sessions.
- UserPromptSubmit injects at most 4 scored hits, deduplicated against what was already shown this session.
- Reference counter promotes hot entries; cold entries quietly stop competing.
- Hot files auto-seed
🌱 stubentries so the log builds itself. - Errors go to a log file, never to chat.
/plugin install simple11337/thinkbetter
Or clone and install locally:
git clone https://github.com/simple11337/thinkbetter ~/.claude/plugins-local/thinkbetter
Requires Node.js on PATH (the hooks are .mjs scripts).
- Start a session in any project. thinkbetter creates
.think-better/context.cbwithgoal:pending. - The first SessionStart injects a directive asking you to set the goal via
AskUserQuestion. Answer, then edit the@Sline. - Work normally. Edits are logged as
Alines. After 3 edits and ~30 lines on the same file, a🌱 stubEentry appears. - Refine stubs with
/thinkbetter-log <file>. Use/thinkbetter-get <id|#tag|file>for surgical lookups. - Check the savings with
/thinkbetter-stats.
E<ID>[!|+] <risk> <file:line> <unit> [#tags] | <core> [| flags [| decision]]
A <ts> <file> <action> <span>
<ID>stable forever:E001,E002...!= P0 (always inject),+= P1 (important), no modifier = P2.- risk:
✓holds,⚠flag,✗broken. - tags: lowercase, no-space, prefixed
#. Field is optional. flagsanddecisioncolumns are optional.
Headers:
@S <date> <goal>
@T E:N R:N X:N P0:N A:N
Example entries:
E007! ✗ src/auth.ts:42 loginFn #auth#sec | accepts empty pw | 🐛 critical | 📌 reject in v2
E008 ✓ src/util.ts:10 fmtDate | pads single-digit days
E009+ ⚠ api/users.go:88 ListUsers #api | unbounded query
| Command | Purpose |
|---|---|
/thinkbetter-show |
session line, stats, P0, and risks |
/thinkbetter-get <id|#tag|file|P0|risk|broken> |
direct node access via index |
/thinkbetter-log [file-or-unit] |
promote or refine an entry |
/thinkbetter-stats |
token estimate, top-cited entries, stub count, last errors |
/thinkbetter-compact [days] |
drop old A lines (E lines always kept) |
/thinkbetter-reset [reason] |
archive current session, start fresh |
- Every
Eline injected via UserPromptSubmit increments a reference counter in.think-better/state.json. The score function addslog2(1 + refs)(capped at 3), so frequently-cited entries surface faster on later prompts. - Hot files generate stub entries automatically. The first edit costs zero memory tokens; the third edit seeds an entry you can later refine.
- Session dedup ensures the same entry never appears twice in one session.
- Cold entries (no refs after 30+ days) lose the boost and stop competing for the four inject slots.
Net effect: a project with 5 sessions of history behaves like a brand-new memory. A project with 50 sessions of history behaves like a tuned local RAG over your own decisions.
Rough per-session figures versus a naive 10-line memory dump:
| Stage | Naive dump | thinkbetter v0.5 |
|---|---|---|
| SessionStart, clean session | ~400 tokens | 0 |
| SessionStart, with 2 P0 + 1 risk | ~400 tokens | ~70 |
| UserPromptSubmit, no match | ~200 tokens | 0 |
| UserPromptSubmit, 4 hits | ~200 tokens | ~90 |
| Format overhead per entry | 50-80 tokens | 22-30 tokens |
Across 100 sessions of moderate use this is on the order of 30,000-80,000 tokens saved, before counting the cost of restated entries that ID references avoid.
Four hooks installed by the plugin:
SessionStart– injects forced question-round directive ongoal:pending, then up to 4 actionable entries.UserPromptSubmit– scoresElines against the prompt, dedups, injects top hits, increments refs.PostToolUseon Edit/Write/MultiEdit – appendsAlines with 10-min coalesce, refreshes stats, rebuilds the index, counts edits per file, seeds🌱 stubentries on hot files.Stop– one short systemMessage when broken entries exist, stubs need refinement, or 10+ activities have produced no entries.
All hooks fail open and log to .think-better/errors.log.
.think-better/context.cb– the canonical memory file..think-better/index.cb– hook-maintained tag/file/priority/risk → ID buckets for O(1) lookups..think-better/state.json– per-session shown IDs, reference counters, metrics. Never injected..think-better/errors.log– hook failures.
- The forced question round is hook-injected but the actual
AskUserQuestioncall is up to the model. If the model ignores the directive, the goal stayspendingand the directive re-fires next session. - The
stealthskill pairing is described inSKILL.md; it is invoked by the model, not the hook. - Token figures are estimates, not benchmarks.
- The plugin assumes Node.js is on PATH.
MIT. See LICENSE.