Four-layer long-term memory (L0 Conversation → L1 Atom → L2 Scene → L3 Persona) for Claude Code, inspired by Tencent/TencentDB-Agent-Memory. Fully local — no external Gateway, no paid API, no Python.
Auto-invoked ships a router so the right skill fires automatically as you prompt. No remembering which skill to call.
Normal is the plain upstream plugin, installed as-is. You invoke its skills yourself.
The plugin> /plugin marketplace add baodq97/tencentdb-agent-memory> /plugin install tencentdb-agent-memory@tencentdb-agent-memoryAuto-invocation> /plugin marketplace add flowy-sh/flowy-core> /plugin install flowy-core> /plugin install flowy-tencentdb-agent-memory
Repo: baodq97/tencentdb-agent-memory
What's inside
Four-layer long-term memory (L0 Conversation → L1 Atom → L2 Scene → L3 Persona) for Claude Code, inspired by Tencent/TencentDB-Agent-Memory.
Fully local — no external Gateway, no paid API, no Python. All extraction and consolidation is done by the Claude agent itself.
# Add marketplace
claude plugin marketplace add https://github.com/baodq97/tencentdb-agent-memory
# Install plugin
claude plugin install tencentdb-agent-memory
The tmem CLI is also published on npm, CLI-only (no plugin assets), for use
outside Claude Code:
npx @baodq97/tmem <command> # run once, no install
npm i -g @baodq97/tmem # or install globally → `tmem`
tmem version # resolved version + path + node
tmem update # check npm for a newer release (--apply to install)
Requires Node ≥ 24 (node:sqlite DatabaseSync is flag-free from 24). The
embedding model (~314 MB, EmbeddingGemma-300M GGUF) downloads on first embed use
into ~/.memory-tencentdb/models/, not at install.
# Inside Claude Code:
/memory-init
# → installs deps, links tmem CLI, creates store
# → hints: "ask me to seed memories"
# then say "seed memories" → agent extracts L1 atoms
# then say "consolidate memories" → agent builds scenes + persona
# done — hybrid recall is now active automatically
| Hook | Action |
|---|---|
SessionStart | Inject the tier-0 persona core once per session (<persona-core>) + keep the global tmem shim current |
UserPromptSubmit | Hybrid recall (FTS5 + vector + RRF, relevance-floored) + L2 scene-navigation index -> inject <memory-context>. Scoped to the project store; tmem recall on the CLI still reads global + project. |
Stop | Auto-capture turn; spawn a detached headless consolidation once N new turns have accumulated |
SessionEnd | Mark session as pending for later seeding; spawn consolidation for a session that produced ≥3 new turns |
Hooks never block — failures degrade to no injection.
Consolidation runs outside the session, as a detached claude -p subprocess
that outlives it, so it costs the session no context and cannot be skipped by the
session declining to dispatch. Two arms fire it: a turn counter, and the session
boundary — the median session is short enough that a counter alone never reaches
most projects. Success is a measured store delta, never the child's exit code
(a validating run reported success while the store was byte-for-byte unchanged);
every run appends its verdict, cost and delta to consolidation_runs.jsonl, which
tmem status summarises. Turn it off with tmem config auto-consolidate off.
Each turn, the UserPromptSubmit hook builds a <memory-context> block from three layers:
conditional persona bullets this prompt actually reaches for, plus a short always-on insurance line (see How the persona reaches the agent).tmem scene <name> (progressive disclosure — cheap always-on index, full read only when needed).Tune the scene-navigation budget with tmem config scene-max-tokens N (0 disables it).
A consolidated persona grows well past what any per-turn budget can carry (~39k chars here). Rather than truncate it, each bullet is classified by duty and delivered on the channel that duty needs:
| Duty | Tier | Channel | Budget |
|---|---|---|---|
always | 0 | SessionStart hook → <persona-core>, once per session | persona-max-tokens (default 1200) |
conditional | 1 | UserPromptSubmit recall → <persona>, query-matched per turn | ~105 tokens |
reference | 2 | on demand — tmem persona --section <name> | none (never injected) |
Tier 0 is paid once per session, not per turn, which is what makes a budget that size affordable. The tier-0 block also carries a one-line index of every section name — including sections it delivered nothing from — so the tier-2 pointer is something the agent can actually act on.
Tier 0 delivers a bullet whole or not at all — bullets over 600 chars are skipped, never truncated. A rule cut before its exceptions reads as a different, stricter rule, which is worse than its absence. Tier 1 still truncates, deliberately: tier 1 is cover, tier 0 is contract. Write persona bullets one rule at a time, operative clause first.
Inspect the split with tmem persona --sections; tune tier 0 with tmem config persona-max-tokens N (0 is rejected — trimming is fine, switching persona conditioning off silently is not).
This does not fully solve persona delivery. On a 39k-char / 81-bullet persona, tier 0 delivers 13 of the 47 always-duty bullets — the always class alone is ~22k source chars against a 4,800-char budget, and 11 of those bullets are over the 600-char eligibility threshold. Closing that needs a synthesised core section on the consolidator side, which is not built yet.
tmem view)tmem view # start a session-keyed localhost server, print the URL
tmem view --query "<q>" # preselect the Context lens with a recall query
tmem view --snapshot # export the payload JSON once and exit (before/after measurement)
A read-only lens on the store, answering "does the agent actually know me?" — which persona bullets reach the agent, on which tier, and what the store's health gaps are. It opens every database with DatabaseSync(..., { readOnly: true }), so "never writes" is enforced by SQLite rather than by discipline.
The URL carries a per-session key and is required verbatim: the page renders raw captured prompts from every project, so localhost alone is not the boundary. Session output goes to <root>/view/, never inside a repo. Use --static to pin the numbers while you read them.
| Type | Name | Purpose |
|---|---|---|
| Command | /memory-init | Install deps, link tmem CLI, init store |
| Command | /contrib | Contributor intelligence (see below) |
| Skill | memory-seed | Agent extracts L1 atoms from conversation history |
| Skill | memory-consolidate | Agent builds L2 scenes + L3 persona |
| Skill | memory-view | Opens the tmem view visualiser and reads the feedback back |
| Skill | tmem-cli | CLI reference for memory inspection/management |
| Skill | contrib-profile | Orchestrates the /contrib pipeline end to end |
| Skill | contrib-ingest / contrib-consolidate / contrib-synthesize | Internal /contrib phases (not user-invocable) |
| Agent | memory-consolidator | Dispatched after /memory-seed only; automatic runs are headless |
| Module | scripts/persona_projection.js | Pure persona duty classification + tier 0/1 projection; shared by the hook, the CLI and the visualiser |
| Module | scripts/scene_nav.js | Pure <scene-navigation> renderer + budget arithmetic; shared by recall and the visualiser |
The two Module rows are shared pure cores (no require, no I/O). They exist because recall and the visualiser must agree on the same arithmetic, and the visualiser cannot import the recall path — doing so would pull node:sqlite into a layer whose contract is that it does no I/O (a test enforces it). One renderer, one projection, two callers.
Installed automatically by /memory-init. Available in terminal and used by skills.
tmem status Memory stats
tmem search <query> FTS5 keyword search (global + current project)
tmem search <query> --all Cross-project: search every project store, labelled by store
tmem projects List all memory stores (slug, records, scenes)
tmem migrate-fragments [--apply] Collapse legacy cwd-keyed fragment stores into their project root
tmem recall <query> Hybrid recall (FTS5 + vector + RRF) + L2 scene-navigation
tmem persona Show persona
tmem persona --sections List persona sections (bullets + always/conditional/reference split)
tmem persona --section <name> Print one persona section on demand (tier 2)
tmem view [--query <q>] Open the memory visualiser (session-keyed localhost server)
tmem view --snapshot [--stdout] Export the visualiser payload JSON once and exit
tmem scenes list List scene blocks
tmem scene <name> Print one full scene block (project-first, then global)
tmem scenes dedup [--dry-run] Remove duplicate scenes
tmem changelog [--last N] Recent memory changes
tmem sync [--full] Embed missing vectors (delta); --full rebuilds both
populations (atoms + scene-fact vectors) and re-stamps
the store's embedding generation
tmem atoms [global|project|all] Dump L1 atoms as JSON
tmem sessions List pending sessions
tmem init Initialize memory store
tmem mark-done Mark consolidation complete (counter + cascade marker)
tmem config consolidate-every N Set the counter-arm threshold (default 10 new turns)
tmem config consolidate-on-session-end N Session-arm threshold (default 3 new turns)
tmem config auto-consolidate [on|off] Headless auto-consolidation (default on)
tmem config consolidate-model NAME Model for the headless child (default sonnet)
tmem config consolidate-max-runs-per-day N Machine-wide daily cap (default 12)
tmem config consolidate-budget-usd N Per-run budget ceiling
tmem config scene-max-tokens N Set L2 scene-navigation token budget (default 200, 0 disables)
tmem config persona-max-tokens N Set the tier-0 persona budget (default 1200; 0 rejected)
tmem config recall [on|off] Toggle per-turn recall injection for this project
tmem daemon start Warm + serve the embed daemon (foreground, like `ollama serve`)
tmem daemon status Health-ping the daemon (ready/warming/failed/down + pid)
tmem daemon stop Stop the daemon + clear its pidfile
/contrib)Profile how a top GitHub engineer works — and learn from them.
Prerequisite: an authenticated gh CLI (gh auth login). All data lives in
<global>/contributors/ — the self-memory feature is never touched.
Paste a GitHub link (or a handle) and say what you want — the contrib-profile skill takes it A→Z for you:
"Analyze how this engineer works: https://github.com/sindresorhus/ky" "Profile https://github.com/torvalds and show me the playbook"
It resolves the target (picks the right repo if you only give a user), runs the whole pipeline, and hands back the persona + learnable playbook. Prefer to drive it yourself? Ask "how do I use /contrib" and it guides you through the steps below instead.
/contrib add <user> <owner/repo>
gh fetches their PRs, commits (allFAQ
tencentdb-agent-memory is a Claude Code plugin of 8 hand-picked skills with a FLOW.md router. Install it once and the right skill fires as you prompt, with no slash command to remember. It is built for development work. It includes contrib-consolidate, contrib-ingest, contrib-profile. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it