claude-mem at 104,793 Stars: One LLM Call per Tool Event, a 400,000-Character History, and a 10,000-Character Ceiling That Fails Silently

claude-mem at 104,793 stars runs one observer call per tool event and re-sends 400,000 chars of history; a 10,000-char ceiling fails silently

claude-mem is a memory plugin for coding agents: it hooks the lifecycle events of Claude Code (and OpenCode, Codex, Pi, Grok Bot, OpenClaw, Hermes, and others), compresses what the agent did into “observations”, stores them in SQLite plus Chroma, and injects a summary back at the start of the next session. It has 104,793 stars, 9,241 forks, and 320 watchers, and version 15.7.0 was tagged in the last few days.

The interesting part is not that it exists. It is that the version you install in October 2026 configures three things at once, and each one has a number attached that the README does not put in one place: who pays for the compression, how much of your session gets re-read on every event, and how many characters of context are allowed to arrive before it silently arrives as nothing.

Read the repository and all three become legible. That is what this article does: the repo at commit main, 30 October 2026, plus the project’s own issues, its own eval suite, and the pricing page the installer opens.

The numbers first

FactValueWhere it comes from
Stars / forks / watchers104,793 / 9,241 / 320GitHub API, 2026-10-30
Watchers as a share of stars0.31%320 ÷ 104,793
Version / file count / repo size15.7.0 / 3,025 files / 708 MBpackage.json, git ls-files, GitHub size
Release headings in CHANGELOG.md380, from v3.5.6 (2025-09-09) to v15.6.0 (2026-10-29)grep -cE '^## \[[0-9]' CHANGELOG.md
Commits by the owner2,567 of 3,525 (72.8%)/contributors, 2026-10-30
Language variants of the README32docs/i18n/
Default observer model when the provider is “claude”claude-haiku-4-5-20251001src/shared/SettingsDefaultsManager.ts
Default batch size (Claude path)1 event per observer requestsame file

380 version headings in 14 months is about 27 releases a month. That is not a complaint — it is a warning about pinning. There are at least 100 releases on the first API page alone, so “pin a version” is a real decision here, not a formality.

The install is no longer just an install

npx claude-mem install now ends with a sign-in. The README describes it plainly: it “asks you to sign in to claude-mem in your browser (email magic link — no card required). Signing in provisions a memory key for your account and unlocks the claude-mem observer with a 30 Day Free Trial: memory runs off-plan, so you get up to 100% more usage from your plan. When the free trial ends, memory automatically falls back to your Anthropic plan unless you subscribe.”

The installer source explains why that is the default. The provider prompt is a two-option multiselect, and the code comment above it reads: “CMEM Pro pre-selected: it is the recommended path and the one the funnel is built around.” A second comment, above the enrollment step, says: “The billing disclosure lives on the checkout page, not here.”

The offer page it opens is explicit, and disagrees with the README on one word that matters:

  • README, sign-in step: “email magic link — no card required.”
  • cmem.ai/pro, the page the installer sends you to: “30 Day Free Trial · then $30/mo · cancel anytime. Card required. Billing starts after 30 days, or earlier if you spend the included usage. Plans automatically upgrade when you reach their included limit. Prepaid cards aren’t eligible for the free trial.”

Both sentences can be true in sequence — signing in needs no card; starting the trial does — but only one of them is in the README, and the installer is the thing that walks a new user into the other. The tiers are $30 (Pro), $70 (Heavy) and $100 (CMEM Max, “plus billed overages”), with automatic upgrade on hitting the included limit. For a five-person team that is $150/month at Pro, before any usage overage.

Two details worth keeping:

  1. Headless installs are a different product. The settings default is CLAUDE_MEM_PROVIDER: 'claude', with this comment: “the interactive provider prompt defaults to ‘cmem’ (the hosted observer), but headless installs land here — no delivered key exists headlessly, so the settings default stays ‘claude’.” So CI and scripted installs quietly bill your own plan from minute one, with no trial and no sign-in. If you evaluate claude-mem on a build server, you are measuring the paid-by-you path, not the hosted one.
  2. “Up to 100% more usage” is a constant, not a measurement. In src/shared/pro-promo.ts: PLAN_USAGE_GAIN_PERCENT = 100, next to PRO_TRIAL_MAX_DAYS = 30. The same file names the surfaces that carry the pitch — session-start banner, per-message context banner, first-session welcome hint, installer “Next Steps”, viewer header, and the post-trial fallback notice — and explains why: “Almost nobody running the free plugin knows the trial is there, so the pitch rides along with the messages they already read.” That is unusually candid marketing engineering, and it is also the sentence to remember when you see “free” near this project.

What gets captured, and what leaves the machine

On every hook event the plugin decides whether the event is worth an observation. The skip list is small: CLAUDE_MEM_SKIP_TOOLS defaults to ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion. Everything else — Bash commands and their output, file reads, edits, searches — is captured, and the observer prompt carries two variable fields, <parameters> and <outcome>, each capped at 16,000 characters by OBS_PROMPT_FIELD_MAX_CHARS.

Then those fields go to a model. Which model depends on the provider you picked:

ProviderModelWho pays
Hosted observer (cmem)cmem-observer, which the repo’s own price table maps to deepseek/deepseek-v4-flashCMEM allowance, then $30/mo
Anthropic plan (claude)claude-haiku-4-5-20251001Your plan
OpenRoutercohere/north-mini-code:freeThe free model, until it is retired
Gemini / OpenAI-compatibleYour keyYour key

That last row is not hypothetical. The OpenRouter default used to be xiaomi/mimo-v2-flash:free; issue #3659 is titled “xiaomi/mimo-v2-flash:free is deprecated on OpenRouter”, and the code now keeps a RETIRED_OPENROUTER_DEFAULT_MODELS set specifically because a fresh install writes every default into settings.json on first load — so a retired free model stays frozen on disk in every existing install.

The arithmetic nobody puts in the README

The plugin’s cost model is not per session. It is per event, and the history is re-sent each time. Three defaults make that concrete:

  • CLAUDE_MEM_CLAUDE_OBSERVATION_BATCH_SIZE: '1' — “Queued same-context events per Claude observer prompt (1-32). 1 = one event per prompt.” One LLM request per captured tool event.
  • CLAUDE_MEM_OBSERVER_MAX_CONVERSATION_CHARS: '400000' — the conversation is retired once it crosses 400,000 characters, roughly 100,000 tokens.
  • src/sdk/prompts.ts: “the prompt is appended to session.conversationHistory, which every later observation in the session re-sends in full. A browser-automation session taking a few hundred screenshots replays all of it, every time.”

So input tokens grow roughly quadratically with event count until the 400,000-character reset, then jump back to the briefing. Using the repo’s own price table (anthropic/claude-haiku-4.5 at $1.00 in / $5.00 out per million tokens, list price, 2026-09-08) and 4,000 characters of prompt scaffolding, 600 output tokens per observation, and chars ÷ 4 as a token estimate:

Captured events1,000-char payload4,000-char payload16,000-char payload
20$0.31$0.46$1.09
60$1.94$3.31$3.30
200$10.01$10.40$11.15
600$31.75$33.12$33.95

These are estimates, not invoices: real payload sizes vary, and my token estimate is the one the code itself uses. But the shape is the finding. Past roughly 113 events the conversation sits at its 400,000-character ceiling, so every additional captured event re-reads about 100,000 input tokens — about $0.10 on Haiku list price, about $0.009 on the hosted observer’s DeepSeek — and payload size stops mattering because the history dominates the prompt.

Two practical readings. On the hosted plan the observer is genuinely cheap, which is why $30/month with “usage included” can work. On your own Anthropic plan, a single long agent session that captures 600 tool events is spending tens of millions of input tokens on bookkeeping, and those tokens come out of the same window your actual work needs. The 100% claim is a claim about your remaining quota; nothing in the repo measures it.

The 10,000-character ceiling, and the fact that it fails silently

This is the most useful piece of engineering journalism in the repository, and it was written by the maintainer, as a comment in src/services/context/ContextBudget.ts:

“Claude Code delivers a hook’s stdout verbatim up to 10,000 characters. One character more and the whole block is written to disk and replaced by a ~2KB preview stub, so the model receives no context at all — and the hook still reports success, which is why this failed silently (#3802, #1899).”

Read that again: over the limit, the agent gets no memory, and the hook reports success. There is no error in the log, no warning in the UI, nothing to grep. The agent simply behaves as if it never had memory, and you conclude the memory feature does not work well.

The issue history shows the ceiling being rediscovered three times:

IssueTitleOpenedClosed
#1899[BUG] SessionStart additionalContext > 10KB silently truncated to 2KB preview2026-04-152026-04-25
#3802Context builder should fit Claude Code’s ~10K per-hook-output limit by selection, not counts (re-raising #1899 with fresh measurements)2026-08-302026-09-11
#5079SessionStart systemMessage exceeds Claude Code’s 10,000-char cap: footer appended after the preview trim2026-10-262026-10-26

#5079 is the one to notice. The budget trim was working; what broke it was the footer. The SessionStart message now carries the viewer link, the trial line, the trial countdown and the TeamBrain discovery line, and a preview fitted to exactly the limit plus those lines went over — so promotional lines evicted the memory. The fix reserves 512 characters (TERMINAL_BANNER_RESERVE_CHARS) for them.

Today the builder measures instead of counting: render, and while the block is over budget, drop the most expensive item and render again. The drop order is documented — full observation narratives first, then the last-session summary, then the prior session’s final reply, then timeline sessions halved, then observations halved. Whole items only, never half an item.

Which means: on a busy project, what you actually receive at session start is a timeline, not narratives. “Memory” degrades by design into “a list of things that happened”, and the only way to know which you got is to look. The sizes involved are in the same file: an observation title runs ~150–320 characters, a session-summary line ~250–600, and the last-session summary block 1–5K on its own.

You can settle this in one command, without reading any of the above:

claude-mem hook claude-code SessionStart | wc -c

If that number is near 10,000, you are at the ceiling and the last thing trimmed may be the thing you wanted. If it is above 10,000, the model is seeing a stub. Either way the hook exits successfully, so exit code tells you nothing.

The File Read Gate: it changes how your agent reads code

Installing claude-mem also installs a gate that is on by default. When Claude Code tries to Read a code file of 32 KB or more that already has observations, the gate denies the read and hands back the file’s observation timeline plus directions to smart_outline, smart_unfold, get_observations, or a Read with offset/limit. Files under 32 KB are never blocked; Markdown, YAML, TOML and JSON are never blocked.

The project’s own eval README documents both sides honestly, which is rare:

  • On the 49 KB test file: “the same block saved 35% on Sonnet and 32% on Opus.”
  • On the 19 KB file, before the 32 KB threshold existed: “the same question cost Sonnet 6% less with the gate on but Opus 20% more. Opus ran smart_outline and then read about 70% of the file through targeted Reads, so the block saved almost nothing and still cost four extra turns.”

So the gate is a real win on large files and a real loss on small ones, and the deny size was tuned after measuring that. If your codebase is mostly 10–30 KB modules you will not meet the gate; if it is vendored bundles and 3,000-line files, you will meet it constantly, and the four extra turns are yours.

The gate also has a dependency worth knowing about: it needs the tree-sitter CLI, which plugin installs do not ship, so the worker downloads it from GitHub releases in the background on first start and only runs a binary whose SHA-256 matches the digest it pins. No network, no gate — and per the docs, the read then goes through with the timeline as context.

What protects your data by default: less than you would guess

This is where the defaults deserve attention, because they are all defensible individually and collectively thin:

ControlDefaultConsequence
<private> tagsManual, per messageYou must remember to wrap secrets before they are captured
Automatic secret redactionOff — CLAUDE_MEM_REDACT_ENABLED is opt-in16 built-in patterns (AWS, GitHub, OpenAI, Anthropic, Slack, JWT, PEM, Stripe, npm, cmem_, cm_pro_, URL credentials) do nothing until you enable them
TelemetryOn (PostHog), opt-outWhitelist-scrubbed: keys like paths, prompts and emails are dropped regardless of caller
Tool-use retention0 = keep foreverNothing is purged
Near-duplicate dedupOff — CLAUDE_MEM_DEDUP_ENABLED: 'false'content_hash only drops byte-identical rows (issue #3038)
Semantic injectionOff — CLAUDE_MEM_SEMANTIC_INJECT: 'false'Retrieval is keyword/timeline-first
ScreenshotsOffUploaded to cmem.ai only with Cloud Sync on

The project says the quiet part itself. In docs/server-architecture-and-team-vision.md: “Default-private mode. <private> tags require user discipline. A team-mode default-private (opt-in to share) inverts the trust model and probably should exist for regulated environments.” That is the maintainer agreeing the current model depends on the user doing the right thing every time — and the anti-redaction default means the machine is not doing it for you.

Credit where it is due on telemetry: it is on by default, but the scrubbing is a whitelist rather than a deny-list, the docs enumerate every collected field, PostHog session replay is documented as not applicable because the local viewer loads no browser SDK, and high-volume events are rolled up per session rather than streamed. That is better than most tools this size.

The open-core line is drawn in the repo

docs/ip-boundary.md states the structure without euphemism: Apache-2.0 covers the core engine, server, CLI, SDKs, MCP tools, adapters, tests and docs. Fourteen areas are reserved: Magic Recall hosted cloud, team/org memory sync, admin dashboard, SSO/SAML/SCIM, enterprise RBAC, audit-log UI, DLP/policy engine, premium knowledge agents, managed evals, customer deployment tooling, enterprise observability, support/SLA workflows, internal eval datasets, private customer connectors.

Read that list as a roadmap of what you will never be able to self-host, regardless of how Apache-2.0 the licence badge is. For an individual that is fine. For a team that needs SSO and an audit log, the open-source path ends exactly where the $30–$100 seats begin — which is a legitimate business model, and also the thing to plan around before you build a workflow on it.

How to evaluate it in one afternoon

Do not take my numbers or the README’s. These eight checks settle the claims that actually matter, in the order that costs least:

  1. Count what arrives. claude-mem hook claude-code SessionStart | wc -c in a project with a few weeks of history. Under 10,000, and well under, is the goal.
  2. Count what it costs. sqlite3 ~/.claude-mem/claude-mem.db "select count(*) from observations;" after a normal day, then multiply by the per-event cost shape above. If you are on the Anthropic provider, watch your plan usage the same day.
  3. Prove the redaction default to yourself. Put a fake ghp_ token in a Bash command with redaction off, then query the observations table for it. If it is there, you now know why CLAUDE_MEM_REDACT_ENABLED exists.
  4. Test <private> at the edge. Wrap a string in <private>, run a session, grep the local database for it. The docs say it strips at the hook layer; verify the string never hit SQLite.
  5. Decide about the gate. If your repository is large files, time one task with the gate on and off. If it is small modules, confirm you never meet the 32 KB threshold.
  6. Read your own settings file. ~/.claude-mem/settings.json is seeded with every default on first load, including a retired OpenRouter model id if you installed before the change. Persisted values win over code defaults forever — that is why RETIRED_OPENROUTER_DEFAULT_MODELS exists.
  7. Ask what happens on day 31. The README says memory “automatically falls back to your Anthropic plan”. Nowhere in the repo or on the offer page is it stated how long cloud-synced data is retained after a trial lapses, or how to export it. Get that in writing before you put team context behind it.
  8. Pin. 380 releases in 14 months means main is a moving target with a 900-commit month behind it. Pick a tag and read its changelog.

FAQ

Is claude-mem free? The plugin is Apache-2.0 and the local path costs nothing to install. The compression runs on a model and someone pays: the hosted observer during the 30-day trial, then $30/month (Pro), or your own Anthropic plan / OpenRouter / Gemini key. Headless and CI installs default to your Anthropic plan immediately.

What does it actually store? SQLite (~/.claude-mem/claude-mem.db) holds sessions, observations and summaries; Chroma holds embeddings for hybrid search; screenshots are off by default. Tool inputs and outputs are truncated to 16,000 characters per field for the observer prompt, but the local log is kept at full fidelity — the docs are explicit that the local logger never passes through the scrubber.

Why did my memory stop working? Three known ways, all silent: a SessionStart block over 10,000 characters (delivered as a 2 KB stub, hook reports success), a npm -g install (README: installs “the SDK/library only — it does not register the plugin hooks or set up the worker service”), or an OpenRouter free model that was retired upstream.

Does it work with agents other than Claude Code? The repo carries adapters for OpenCode, T3 Code, Antigravity, OMP, Pi, DeepSeek Harness, Cursor, Grok Bot, OpenClaw and Hermes, and the README documents per-IDE installs. The Grok Bot path is different in kind: Grok Bot has no host hooks, so it watches chat log files, defaults to CMEM Pro, and runs a pilot that appends [awareness] lines into the bot’s own memory log.

Is it maintained? Yes, intensively, by essentially one person: 2,567 of 3,525 commits on the first page of contributors are the owner’s, with a PostHog bot (65), GitHub Copilot (61) and a Cursor agent (17) among the top contributors. 380 releases in 14 months. Bus factor one, release velocity very high — which is why pinning matters more here than in a slower project.

Should a team adopt it? As a per-developer convenience, with redaction on and retention set: yes. As shared team memory, no — team sync, RBAC and the audit log are on the reserved list, so the answer is CMEM Pro seats plus a conversation about what leaves the machine. As a security-sensitive install where nobody will remember to type <private>: not until default-private mode exists.

The verdict

claude-mem solves a real problem, and it solves it with more engineering honesty than most projects at 100,000 stars: the eval suite measures the token cost of its own feature and reports the case where it loses, the budget builder documents the ceiling that used to eat memory silently, and the IP boundary file tells you where the free tier ends. Those are the artifacts of a maintainer who expects to be audited.

The defaults, though, are a sales funnel and a cost layer wearing a memory feature. One observer request per tool event with the whole conversation re-sent, a 400,000-character cap that makes the marginal event cost about a dime on Haiku, a hosted observer preselected in the installer with the billing terms deliberately left to the checkout page, and redaction off until you ask. None of that is dishonest — every bit of it is written down, in the code and in the docs. It is just written down in five different files, which is the same as not being written down for most people who type npx claude-mem install.

Install it, then spend twenty minutes on the eight checks above. The tool is worth it; the default configuration is not the one you should run with.