Configuration
Settings File
Settings are managed in~/.claude-mem/settings.json. The file is auto-created with defaults on first run.
Choose bundled skills
All bundled skills are enabled by default. To hide unwanted skills from Claude Code’s listing and slash commands, add their folder names tosettings.json:
make-plan, not
claude-mem:make-plan. Names are case-sensitive; paths and wildcards are rejected.
The environment variable CLAUDE_MEM_SKILLS_DISABLED overrides the file, including
an empty value. Save the preference in settings.json if it must survive updates
started by a process that does not inherit your shell’s environment.
The installer applies the list to the installed version cache and marketplace
copy on install, update, and repair. The published package and source checkout
keep every skill. New skills introduced by an update remain enabled unless named
in the list. This controls plugin skill discovery, not memory capture or MCP tools.
Four skills always stay enabled, because claude-mem reads their files while it runs.
If you list one of them, it is left in place and the installer and SessionStart
hook print a warning naming it:
Claude Code’s SessionStart hook also reapplies the list after marketplace updates
and settings changes. When it reports that selection changed, restart Claude Code
to reload its skill listing: the current session may have already loaded the old
list. Removing a name, or setting the list to
"", restores that skill through
the same flow. Other hosts may cache their own copy and need a reinstall/reload.
Skills are moved, not deleted, to .claude-mem-disabled-skills beside the installed
skills directory. If an update supplies a new copy in the same directory, the
older copy is preserved in .claude-mem-disabled-skills/.history; enabling the
skill uses the new copy. These are install-local backups, not a backup of custom
edits across reinstalls, which already replace the installed plugin tree.
Use the normal updater rather than overlaying a partial plugin tree: if a partial
update removes an upstream skill but leaves its parked copy, re-enabling it can
restore that older copy.
An invalid setting or unsafe path leaves skill content in place and reports the
problem; install and repair still finish. Symbolic links, foreign backup directories, and incomplete skill
folders are refused. Concurrent sessions serialize changes with the empty
.claude-mem-skill-selection.lock directory. If a process is killed during a
change, close the other sessions, inspect the installed tree, remove that empty
lock directory, and restart to finish applying the saved selection.
Core Settings
Subagent & Dynamic Workflow filtering
Claude Code Dynamic Workflows fan a single prompt out to tens-to-hundreds of parallel subagents (agent_type: workflow-subagent).
Every tool call by every subagent fires a PostToolUse hook, so claude-mem creates one
provider-analyzed observation per call — a single run can emit hundreds-to-thousands
of low-signal observations. That can exhaust the configured provider’s free-tier quota
(HTTP 429) and drop the rest of the run, including valuable main-session work.
Two settings let you filter these out before any worker round-trip or provider call.
Both default to off, so existing behavior is preserved.
-
Drop all subagent noise (recommended for heavy workflow users):
This is the robust lever — it catches every subagent tool call (one that carries both an agent id and an agent type) regardless of type. Main-session observations are kept, including
claude --agent <type>main threads and transcript-watch hosts such as Grok Bot seats, which carry only one of the two. -
Surgically drop specific agent types (keep some subagents, drop others):
Add a comma-separated list of
agent_typevalues. The two settings combine as a union: a subagent observation is skipped if the global toggle is on or itsagent_typeis in the list.
Subagent summaries are already skipped automatically; these settings add the same
control for observations. Durable cross-session knowledge generally comes from the
main session, so dropping ephemeral subagent steps usually improves signal-to-noise.
SessionStart already leaves subagent rows out of injected context by default
(CLAUDE_MEM_CONTEXT_MAIN_AGENT_ONLY); these settings go further and skip capturing
them at all, which also saves the observer’s provider tokens.
Gemini Provider Settings
See Gemini Provider for detailed configuration and rate-limit information.
Codex Subscription Provider Settings
Runcodex login as the user running the worker, then install with npx claude-mem install --provider codex. Add --model gpt-6-luna to choose that model, or select Codex and enter a model in the viewer settings. Codex uses the local CLI subscription login; it does not require an OpenAI API key.
Reinstalling without --model keeps the saved Codex model. On a first install the setting is empty and Codex chooses its default. Clear the Codex Model field in the viewer to return to the default later.
The worker uses an isolated
codex app-server session for observations and summaries. Codex CLI authentication must be a file-backed ChatGPT login; API-key login is not accepted. Each request uses the shared CLAUDE_MEM_LLM_TIMEOUT_MS deadline. See docs/codex-provider.md in the repository for how failures pause and recover.
OpenRouter Provider Settings
See OpenRouter Provider for detailed configuration, free model list, and usage guide.
OpenAI-Compatible Provider Settings
ForCLAUDE_MEM_PROVIDER=openai-compatible: any endpoint that speaks /chat/completions, hosted or local.
See OpenAI-Compatible Provider for presets and setup.
My Work Summary Settings
My Work can generate readable card wording using the configured OpenRouter or OpenAI-compatible chat-completions endpoint. By default it runs only when the primary observer provider is OpenRouter, as before; it never uses another endpoint or a quota-fallback key on its own. Select a provider explicitly to use that endpoint for summaries, including an OpenAI-compatible primary or a provider configured only as a fallback. Explicit selection can incur the endpoint’s usual charges. Generated wording is presentation-only; recorded work and status remain unchanged.My Work Refresh Models
The My Work refresh (goals, grouping, review, focus and story steps) runs on one agent: Claude Code, Codex, Gemini, or the API provider you selected (seeCLAUDE_MEM_WORK_VIEW_AGENT below for which one). By default the light steps (grouping, focus) use a small model and the others a stronger one: haiku/sonnet on Claude Code, flash-lite/flash on Gemini, and Codex’s CLI default for the careful steps. On Claude Code the refresh runs on your Claude subscription, so set a model here to cap it, for example haiku. Each setting puts every step of that agent on one model and is read at the start of every refresh.
Quota Fallback Settings
See Quota Fallback for how the fallback starts and ends.
Quota Guard Settings
With subscription auth, the observer stops once a usage window reaches its threshold. A window the provider has already rejected always stops it, whatever the threshold. The five-hour window also stops it at 85% or more within 15 minutes of its reset, even below its threshold. API-key auth never stops. Thresholds are fractions from 0 to 1 (0.93 = 93%). A value outside that range, such as 93, falls back to the default, with a warning in the worker log. A blank value uses the default.
Observer Budget Settings
These apply to every observer provider. The observer’s conversation runs in generations. When one fills its budget, claude-mem retires it and starts a fresh one, briefed with the session’s own observations. The budget is the smaller ofCLAUDE_MEM_OBSERVER_MAX_CONVERSATION_CHARS and half the observer model’s context window (about 4 characters per token). Each tool call’s parameters and outcome are capped at a tenth of the window, 16,000 characters at most.
If the provider still rejects a request as too long for the model’s window, the observer retires the generation and retries the same work in a fresh one, the same way it handles Claude’s “Prompt is too long”.
For these HTTP providers, the observer’s instructions and output format are sent as the system message, and the user’s request as the first user message. A reply cut off at the output-token cap is logged as a warning that names the cap.
Long-Lived Claude Token
With subscription auth, the observer normally reads your Claude Code login from the credential store at every spawn. That login’s access token lasts about 8 hours, and the stored login itself has an end date (claude auth status --json shows it as loginExpiresAt). When it lapses, memory capture stops until you run claude auth login again.
To run the observer without that dependency, create a long-lived token and give it to claude-mem:
-
Run
claude setup-tokenand finish the sign-in. It prints a token tied to your Claude subscription. -
Add it to
~/.claude-mem/.env:
Replace the token when it expires (
claude setup-token again). If the token is a JWT whose expiry has passed, the observer logs a warning and falls back to the credential store.
The token applies to every Claude profile. If you set CLAUDE_MEM_CLAUDE_CONFIG_DIR, the observer bills the token’s account rather than that profile’s stored login, but it still tracks quota pauses per profile. Changing the setting therefore starts a fresh quota view even though the account stays the same.
Claude Gateway Settings
Gateway credentials live in~/.claude-mem/.env, not settings.json.
Use LiteLLM Gateway when you want
CLAUDE_MEM_PROVIDER=claude to route through LiteLLM while preserving the Claude Agent SDK worker path.
If an Anthropic-compatible gateway rejects the
thinking parameter with a 400, the worker’s observer drops the parameter for the rest of that session and retries the same batch, so nothing is lost while you change the setting. The server’s provider doesn’t retry; set omit for such a gateway.
System Configuration
Grok Bot Brainbeat Webhook
Optional. SetCLAUDE_MEM_GROK_BOT_WEBHOOK_URL and claude-mem POSTs every observation that matches the Grok Bot awareness triggers (CLAUDE_MEM_GROK_BOT_AWARENESS_TRIGGER_TYPES / CLAUDE_MEM_GROK_BOT_AWARENESS_TRIGGER_CONCEPTS, default types decision,bugfix,security_alert,sensitive) to that URL. It is independent of every Telegram setting.
Each matching observation is sent as one JSON POST:
Notion Export
Optional. Copies each new observation into a Notion database as it is stored. See Notion Export for setup and the database schema.Near-Duplicate Deduplication
Opt-in (off by default) dedup of observations whose titles describe the same recurring work but are worded slightly differently, socontent_hash (byte-identical only) misses them.
Two deterministic tiers:
- Tier 0 — exact-normalized-title → safe silent auto-merge: a new observation whose
title matches an existing one after lowercasing / whitespace-collapse / punctuation-strip
is collapsed onto the existing row and its
occurrence_countis bumped (cross-session, within the same project, the same host platform and the same agent scope: main session work never merges into a subagent row, which SessionStart leaves out). Rows stored before an upgrade are re-keyed byPOST /api/dedup/scan. - Tier 1 — IDF-weighted similarity → review-only near-duplicate candidates are
recorded in
observation_dedup_candidates(never auto-merged), so distinct work that differs only in one rare token (rdlp-apivsrdlp-plugin) is never silently destroyed.
After enabling on an existing database, run a one-time scan to backfill the IDF model and
surface accumulated near-duplicates:
POST /api/dedup/scan (worker, localhost-only).
Review candidates via GET /api/dedup/candidates?project=<name> (add &status=pending to see only
unreviewed ones), and record a verdict with POST /api/dedup/candidates/<id>/resolve and a body of
{"status": "distinct"} or {"status": "dismissed"}. A later scan keeps the verdict.
Screenshots and Images
claude-mem keeps the screenshots and images that tools return (browser screenshots, aRead of an image file inside the project) and shows them on
the request they belong to in My Work, both on this computer and at
work.cmem.ai. Keeping images is on by default. Letting the observer model
look at them is a separate switch that is off by default: keeping images
never sends one to a model.
To stop keeping images, turn off Keep images under Images in the
memory viewer’s Settings (/viewer on your worker’s port), or set
CLAUDE_MEM_MEDIA_CAPTURE_ENABLED to false. Images already kept stay until
their event is deleted. An install whose settings.json still holds the old
false default is moved to true once, on the first worker start after the
update; a false you set after that is kept.
What is stored. Only PNG, JPEG and WebP images, at most four per tool
event and 3 MiB each, are accepted. Each one is converted to two WebP
copies: a full-size viewer copy and a smaller copy (longest edge 1536 px,
at most 256 KiB) for the model. Conversion strips EXIF/GPS metadata. The
original bytes are not kept: the image body is replaced by a short
descriptor before the tool result is written to the database, so the raw
base64 never reaches
tool_uses, the observer prompt, logs or sync. If the
image came from a file, its path is recorded so the viewer can tell you
whether that file still exists; the path is shown only when you ask for
source details in the image viewer and never appears in feeds, logs or sync.
Where it lives. Converted copies are written under
<data dir>/media-v1/<attachment-id>/ (by default ~/.claude-mem/media-v1/),
readable only by your user. The worker serves them only to the viewer page on
the same loopback port; other origins, LAN clients and proxies are refused.
How long it is kept. Images are kept on this computer until their event
is deleted: an image lives as long as an observation or its source tool event
still references it. There is no total size cap and no age limit; each image
is at most about 3.25 MiB on disk and an event keeps at most four.
Deleting an observation, a session or a project removes the references at
once; the files are removed by a background cleanup within about 30 seconds
(retried with backoff if the disk refuses). Images are never kept for
analytics.
Cloud upload. When capture is on and Cloud Sync is
configured, each converted image is uploaded privately to your cmem.ai account
so your other devices and My Work at work.cmem.ai can show it; they download
it on first view. Deleting
it locally also deletes the cloud copy. Observation text syncs without the
image bytes.
Third-party image inference. When inference is on and the observer
endpoint qualifies (OpenRouter directly, or the cmem.ai gateway), the
model-sized copy of each image in the current tool event is sent with that
one observer request to the model provider behind that endpoint (OpenRouter
and the provider it routes to). It is not re-sent in later turns, summaries
or context injection. Other providers stay text-only. If the endpoint rejects
images, the turn is resent once without them and the images are marked
“not inspected”.
Logs and metrics about images contain only attachment IDs, byte sizes,
dimensions, the conversion recipe, error codes and timings. They never contain
pixels, paths, URLs, captions or your text. The cmem.ai gateway additionally
receives an X-Cmem-Correlation header holding a random request ID, the retry
attempt number and up to four hashed event IDs, so metered usage can be tied to
a request.
Model Configuration
Configure which Claude model compresses your observations (only applies whenCLAUDE_MEM_PROVIDER=claude).
Available Models
Each alias follows the newest model of its tier, so new releases (usually cheaper or better for the price) reach you without a settings change. A full model ID, such as
claude-sonnet-5, pins that one version and never updates. Installs that had the old shipped default claude-haiku-4-5-20251001 saved are moved to haiku automatically, except gateway installs (see Manual Configuration below).
Picking via the Installer
npx claude-mem install prompts for the Claude model (when the Claude provider is selected) and persists the choice to ~/.claude-mem/settings.json.
Manual Configuration
Edit~/.claude-mem/settings.json:
haiku moves to each new Haiku release on its own. A full model ID such as claude-haiku-4-5-20251001 pins that one version and never updates, so use one only when you deliberately want to stay on it. Installs that saved the old default, claude-haiku-4-5-20251001, are moved to haiku automatically, except gateway installs (an ANTHROPIC_BASE_URL in ~/.claude-mem/.env, or the auth method set to gateway), which keep their saved model because the gateway decides which model names it accepts.
Mode Configuration
Configure the active workflow mode and language.Settings
Examples
Spanish Code Mode:Project Names
claude-mem files every observation under a project name, and SessionStart injects the memory stored for the current project.- Inside a git repository the name is the repository root’s folder name, so every subfolder shares it. A git worktree is stored as
<repo>/<worktree>(a worktree whose folder has the repository’s own name, like Codex’s~/.codex/worktrees/<id>/<repo>, is stored as<repo>) and a git submodule as<superproject>/<path>; both also read their parent repository’s memory. Memory a submodule stored under its own folder name before it was grouped this way stays readable from it. When a worktree or submodule checkout is deleted, the worker folds its memory into the parent repository at its next start (merged or not), so nothing is stranded. - With
CLAUDE_MEM_PROJECT_NAME_SOURCE=git-remotea repository that has anoriginremote is named by itsorg/reposlug instead (e.g.thedotmack/claude-mem), so renaming or re-cloning the folder keeps its memory, two repositories with the same folder name stay apart, and every worktree of the repository shares the slug (a submodule, being a repository of its own, is named by its ownorigin). Memory stored under the folder-based names stays readable, and a deleted worktree’s memory from before the switch is still folded into the repository. Repositories without a usableorigin(or with a local one) keep the folder-based name. - Outside git the name is the current folder’s name. To give a non-git project one name across all of its subfolders, put an empty
.claude-mem-projectfile (or a.claude-mem.json) in its root folder: every folder below it then uses the root folder’s name. Memory stored under a subfolder’s own name before you added the file stays readable from that subfolder. Marker files in your home directory, the system temp directory or Claude’s config directory are ignored, so they can never fold unrelated folders together. - Named environments (
CLAUDE_MEM_PROJECT_ENVIRONMENTS) group several folders, git or not, into one project and win over every rule above. For example,[{"name": "acme", "patterns": ["~/work/acme/**"]}]files everything under~/work/acmeasacme, and SessionStart labels it as an environment. Memory those folders stored under their own names stays readable from them; to fold it into the environment for good, runnpx claude-mem project merge <old-name> acme(it runs inside claude-mem’s worker whenever the worker is running). The merge rewrites nothing (rows are marked as merged, the way a worktree folds into its repository) and brings along memory already folded into the old name, such as a merged worktree’s. It reaches your other devices through cloud sync and updates semantic search; if that last step fails, the command says so, and running it again retries it.
Choosing an environment’s memory scope
By default, naming an environment retains the folder and git-remote keys it previously read. To keep a business or package inside a larger repository from reading the parent’s entire history, setinherit explicitly:
- Omitted
inheritkeeps existing behavior: derived keys and the environment key are readable. inherit: []reads only the environment key and memory explicitly merged or adopted into it.inherit: ["shared"]reads the environment and the listed project keys, including their existing merged history, without automatically adding parent, folder, or remote-derived keys. Entries are project names, not environment names to resolve recursively or path patterns.
name. This changes the checkout’s default read scope for
SessionStart, semantic injection, file context, and MCP queries for that project;
it does not move or delete stored history. Ordinary worktrees and submodules with
no explicit inheritance configuration keep their existing behavior.
Reading a project’s memory does not merge the environment’s history back into
that project. Automatic orphan adoption uses recorded folder-derived identity,
not the environment’s read scope.
inherit must be an array of non-empty project names. Names are trimmed and
deduplicated, and cannot contain commas (the query protocol uses commas to
separate projects). An invalid explicit value raises a configuration error rather
than reverting to the broader derived scope; correct it before using those hooks.
This setting selects default context, not access permissions. Explicit queries
for other projects and CLAUDE_MEM_CONTEXT_PROJECTS=all can still read a broader
scope. Previously performed whole-project merges also remain in effect.
Environment patterns and CLAUDE_MEM_EXCLUDED_PROJECTS use the same glob rules. A complete **/ segment matches zero or more directories: ~/work/**/private matches both ~/work/private and ~/work/team/private. Add a trailing /** to match their descendants too.
Files and Directories
Data Directory Structure
The data directory location depends on the environment:- Production (installed plugin):
~/.claude-mem/(always, regardless of CLAUDE_PLUGIN_ROOT) - Development: Can be overridden with
CLAUDE_MEM_DATA_DIR
Plugin Directory Structure
Plugin Configuration
Hooks Configuration
Hooks are registered inplugin/hooks/hooks.json. Each runtime hook is one exec-form entry with no shell, {"command": "claude-mem", "args": ["hook", "claude-code", "<event>"]}. Claude Code finds claude-mem on PATH: a small compiled launcher that npx claude-mem install / update place at ~/.local/bin (POSIX) or %LOCALAPPDATA%\claude-mem\bin (Windows). The launcher runs the single dispatcher, worker-service.cjs hook claude-code <event>, under Bun. The events wired up are:
Setup→version-check.js(installs missing plugin dependencies, records.install-version). The only bash entry; Claude Code fires it only forclaude --init/--maintenance.SessionStart→claude-mem start(worker, async), thenhook claude-code context(context injection); at startup alsonode ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-launcher.cjs, which places or refreshes the launcher for marketplace-only installsUserPromptSubmit→hook claude-code session-initPreToolUse(matcherRead) →hook claude-code file-context(synchronous: adds the file’s observation timeline as context and can block whole-file Reads; see File Read Gate)PostToolUse(matcher*) →hook claude-code observationStop→hook claude-code summarizeSessionEnd→hook claude-code session-end
hooks.json entries are generated by scripts/build-hooks.js and shipped with the plugin; do not hand-edit them in the marketplace copy unless you know what you’re doing. npx claude-mem doctor shows a Hook launcher row for the claude-mem the hooks will run.
Turning off the tool hooks
These switches are read from the hook’s environment only, not from~/.claude-mem/settings.json. Set them under the env block in ~/.claude/settings.json (Claude Code passes that block to every hook) or export them in your shell:
Claude Code still launches each hook. The
claude-mem hook launcher checks these switches before resolving the plugin or starting Bun, so a disabled tool hook does not load the worker bundle. The Codex shell hooks check them before starting Node; the Codex Windows launcher still starts Node, then checks the switch before resolving scripts or starting Bun. These switches do not change the feature settings in settings.json.
Turning off the end-of-session summary
Orchestrators that launch short headless runs (a
codex exec review of a staged diff, say) usually set CLAUDE_MEM_DISABLE_OBSERVATION=1 so nothing the run observes is captured. The summary switch completes the picture for those runs: they keep reading claude-mem context at session start, but their Stop no longer writes a summary of an intermediate diff into the project’s recent summaries. Unlike the tool-hook switches, this check runs inside the summarize handler, so the hook process still starts and reads its input before the summary is skipped.
Search Configuration
Claude-Mem provides MCP search tools for querying your project history. No configuration required - MCP tools are automatically available in Claude Code sessions. Search operations are provided via:- MCP Server: 3 tools (search, timeline, get_observations) with progressive disclosure
- HTTP API: 10 endpoints on the worker service port (per-user, default
37700 + (uid % 100); see~/.claude-mem/settings.json) - Auto-Invocation: Claude recognizes natural language queries about past work
Worker Service Management
Worker service is managed by Bun as a background process. The worker auto-starts on first session and runs continuously in the background.Observation TV Remote Access
The worker binds to127.0.0.1 by default and has no request authentication — the loopback bind is its only defence. CLAUDE_MEM_TV_TOKEN adds a read-only broadcast surface so a second device on your LAN (a phone, an iPad, a spare monitor) can watch Observation TV and do nothing else.
Mint a token:
Booting with a non-loopback host and no token logs a
SECURITY warning; the worker still binds.
A local port-forward reopens the whole API. The guard exempts loopback by socket peer, so anything that arrives as loopback bypasses it entirely — including ssh -L <port>:127.0.0.1:<port> <box> from another device, or any local forwarding proxy. To the worker that traffic is indistinguishable from the operator’s own browser, so it gets the full API, GET /api/settings and its provider API keys included. This is the one concrete way “the device can do nothing else” stops being true: only forward the port to devices you would hand the machine to.
Docker and bridge networking. With CLAUDE_MEM_WORKER_HOST=0.0.0.0 inside a bridge-network container, requests from the host’s own browser arrive from the bridge gateway address, not 127.0.0.1. Once a token is set, that browser is treated as remote like any other device and must supply ?token= to open the TV — and the React viewer at / is denied outright, exactly as it is for any other remote device.
Open the TV on the second device at http://<lan-ip>:<port>/tv.html?token=<secret>.
The React viewer at / stops working remotely when a token is set. That is intended — the viewer needs the write and settings routes the guard denies. Loopback is never gated, so the viewer keeps working normally on the machine running the worker.
Treat the URL as the secret. The token rides in the query string for /stream because the browser’s EventSource API cannot set request headers. It is not written to the worker log (the request logger records req.path, which excludes the query string), but it will be in the browser’s history on the device you open it on. Authorization: Bearer <token> and X-Api-Key: <token> also work for anything that can set headers.
This is plain HTTP. The token stops an unauthenticated device from reading the stream; it does not encrypt it. Anyone who can sniff your LAN sees observation titles. For a home network that is the accepted tradeoff; for anything else, terminate TLS in front of the worker (out of scope here) — and still never a tunnel to the unmodified worker, which would publish GET /api/settings and its provider API keys to the open internet.
Use the exact paths. The allowlist is exact-match and case-sensitive: /tv.html, /tv, /stream, /api/observations and nothing else. A trailing slash or a different case — /tv/, /API/observations, /api/observations/by-file — returns 404 even with a valid token. That is deliberate fail-closed behavior, not a bug.
The TV’s ?project= and ?source= filters are client-side only. They are display filters, not access control — a token holder still receives every project’s observations.
Accepted risks, stated plainly:
GET /api/observationsreturns full observation bodies —narrative,facts,text,files_read,files_modified— for every project on the box, not just the four fields the TV renders. A token holder can page through the entire memory database withoffset./streamis unfiltered. It carries every observation for every project on the box, plus the project catalog and processing status. There is no per-client filtering.- No rate limiting. A token holder can hammer
GET /api/observationsfreely. - The token is readable on loopback via
GET /api/settings, exactly like your provider API keys are today. It is deliberately not writable throughPOST /api/settings(that route is unauthenticated), so it can only be set by someone with filesystem or environment access. /streamis not side-effect-free. Every new connection triggers aninitial_loadbroadcast to all connected clients, and the client list is unbounded. A token holder reconnecting in a loop can therefore disturb the operator’s own local viewer. This is pre-existing worker behavior; the token is what newly makes it reachable from the LAN.
Manual Configuration
Edit~/.claude-mem/settings.json:
Watching Off-LAN (cmem.ai Pro)
Everything above is the LAN path. Watching from outside your network — on cellular, at a coffee shop, from another house — is a cmem.ai Pro feature: openhttps://cmem.ai/tv in any browser while signed in to your account. It requires Cloud Sync to be enabled, because the hosted page reads titles your worker has already pushed to your sync hub.
No token, no open port, no inbound connection. This path needs neither CLAUDE_MEM_TV_TOKEN nor a non-loopback CLAUDE_MEM_WORKER_HOST — both belong to the LAN path and have no effect on it, so leave them at their defaults. The box never accepts an inbound connection for the hosted TV; the worker only ever dials out. No tunnel (cloudflared, ngrok, or anything like them) is needed, and none is recommended.
The hosted TV surface shows observation titles and nothing else. It never renders narratives, facts, file lists, snippets or prompt text.
That is not the same as “only titles leave your machine.” The hosted TV is a feature of cloud sync, and cloud sync uploads your observation narratives and your full prompt text to the sync hub under your cmem.ai account. The hosted page is titles-only; the upload standing behind it is not. Don’t enable cloud sync if that content must stay on your machine.
One rendering difference. An observation with no title still appears on the LAN TV, which falls back to the subtitle. It does not appear on the hosted phone TV — that surface receives titles only, so it has no subtitle to fall back to.
Folder Context Files
Claude-mem can automatically generateCLAUDE.md files in your project folders with activity timelines. This feature is disabled by default.
Grok Bot live INDEX
The worker writes a growing observation INDEX into each Grok Bot seat’s Memory mid-attach file (agents/<uuid>/memory/log/zz-claude-mem-inject.md). See Grok Bot Integration.
See Folder Context Files for full documentation on how this feature works, configuration options, and git integration recommendations.
Context Injection Configuration
Claude-Mem injects past observations into each new session, giving Claude awareness of recent work. You can configure exactly what gets injected using the Context Settings Modal.Context Settings Modal
Access the settings modal from the web viewer. The worker prints its URL on startup; the port comes fromCLAUDE_MEM_WORKER_PORT.
- Click the gear icon in the header
- Adjust settings in the right panel
- See changes reflected live in the Terminal Preview on the left
- Click Save to keep your changes
Loading Settings
Control how many observations are injected:
Considerations:
- Higher values = More context but slower SessionStart and more tokens used
- Lower values = Faster SessionStart but less historical awareness
- Default of 50 observations from 10 sessions balances context richness with performance
Filter Settings
Control which observation types and concepts are included: Types (select any combination):bugfix- Bug fixes and error resolutionsfeature- New functionality additionsrefactor- Code restructuringdiscovery- Learnings about how code worksdecision- Architectural or design decisionschange- General code changes
how-it-works- System behavior explanationswhy-it-exists- Rationale for code/designwhat-changed- Change summariesproblem-solution- Problem/solution pairsgotcha- Edge cases and pitfallspattern- Recurring patternstrade-off- Design trade-offs
Display Settings
Control how observations appear in the context: Full Observations:
The most recent N observations (set by Count) show their full narrative or facts. Remaining observations show only title, type, and token counts in a compact table format.
Token Economics (toggles):
Token economics help you understand the value of cached observations vs. re-reading files.
Advanced Settings
Manual Configuration
Settings are stored in~/.claude-mem/settings.json:
Customization
Settings can be customized in~/.claude-mem/settings.json.
Custom Data Directory
Edit~/.claude-mem/settings.json:
Custom Worker Port
Edit~/.claude-mem/settings.json:
Custom Model
Edit~/.claude-mem/settings.json:
Custom Skip Tools
Control which tools are excluded from observations. Edit~/.claude-mem/settings.json:
ListMcpResourcesToolSlashCommandSkillTodoWriteAskUserQuestion
- Include TodoWrite: Remove from skip list to track task planning
- Include AskUserQuestion: Remove to capture decision-making conversations
- Skip additional tools: Add tool names to reduce observation noise
Advanced Configuration
Hook Timeouts
Hook timeouts are set inplugin/hooks/hooks.json. The current defaults match the shape of the workload at each lifecycle stage:
- Setup (
version-check.js,claude --init/--maintenanceonly): 300s ceiling; fast when the plugin’s dependencies are complete, up to 120s when it has to runbun install - SessionStart (worker-start + context): 60s
- SessionStart (ensure-launcher, startup only, synchronous): 180s, enough to compile the launcher
- UserPromptSubmit: 15s
- PreToolUse (file-context, Read matcher): 15s, synchronous so the File Read Gate can block a Read; its worker lookup gives up after 3s
- PostToolUse (observation): 120s
- Stop (summary): 120s
npx claude-mem install / npx claude-mem repair install the runtime (Bun, uv, bun install) outside the session lifecycle. The Setup hook only runs bun install when the loaded plugin’s dependencies are missing — typically a plugin-marketplace install or claude plugin update — and writes the .install-version marker once they are complete. Claude Code does not fire Setup on plugin install or update, so run claude --init-only or npx claude-mem install to trigger that repair.
Worker Memory Limit
The worker service is managed by Bun and will automatically restart if it encounters issues. Memory usage is typically low (~100-200MB).Logging Verbosity
Enable debug logging:Configuration Best Practices
- Use defaults: Default configuration works for most use cases
- Override selectively: Only change what you need
- Document changes: Keep track of custom configurations
- Test after changes: Verify worker restarts successfully
- Monitor logs: Check worker logs after configuration changes
Troubleshooting Configuration
Configuration Not Applied
-
Restart worker after changes:
-
Verify environment variables:
-
Check worker logs:
Invalid Model Name
If you specify an invalid Claude model name, the worker logs a warning and uses the default. Valid Claude models forCLAUDE_MEM_MODEL:
haiku(default, the newest Haiku)sonnet(the newest Sonnet)opus(the newest Opus)- a full model ID, such as
claude-sonnet-5, to pin one version
Port Already in Use
The default worker port is37700 + (uid % 100), so different OS users on the same machine get different ports automatically. If you still hit a collision (e.g. running multiple profiles as the same UID), set a fixed port:
-
Set custom port:
-
Restart worker:
-
Verify new port:
Next Steps
- Architecture Overview - Understand the system
- Troubleshooting - Common issues
- Development - Building from source

