Skip to main content

Configuration

Settings File

Settings are managed in ~/.claude-mem/settings.json. The file is auto-created with defaults on first run.

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_type values. The two settings combine as a union: a subagent observation is skipped if the global toggle is on or its agent_type is 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

Run codex 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

For CLAUDE_MEM_PROVIDER=openai-compatible: any endpoint that speaks /chat/completions, hosted or local. See OpenAI-Compatible Provider for presets and setup.

Quota Fallback Settings

See Quota Fallback for how the fallback starts and ends.

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 of CLAUDE_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.

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.

System Configuration

Grok Bot Brainbeat Webhook

Optional. Set CLAUDE_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:
POSTs are sent concurrently and each times out after 5 seconds. Redirects are refused, so the shared secret and the observation only ever go to the configured URL; put the receiver’s final address in the setting. A failure is logged with the receiver’s origin and a short reason only (never the full URL) and never blocks observation storage or other notifications.

Near-Duplicate Deduplication

Opt-in (off by default) dedup of observations whose titles describe the same recurring work but are worded slightly differently, so content_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_count is 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 by POST /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-api vs rdlp-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>.

Model Configuration

Configure which Claude model compresses your observations (only applies when CLAUDE_MEM_PROVIDER=claude).

Available Models

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:

Mode Configuration

Configure the active workflow mode and language.

Settings

Examples

Spanish Code Mode:
Email Investigation 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-remote a repository that has an origin remote is named by its org/repo slug 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 own origin). 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 usable origin (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-project file (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/acme as acme, 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, run npx 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.

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 in plugin/hooks/hooks.json. The current shape uses a single dispatcher (worker-service.cjs hook claude-code <event>) launched through bun-runner.js, plus a fast Setup-phase version-check.js. The events wired up are:
  • Setup → version-check.js (installs missing plugin dependencies, records .install-version)
  • SessionStart → start the worker, then hook claude-code context (context injection)
  • UserPromptSubmit → hook claude-code session-init
  • PreToolUse (matcher Read) → hook claude-code file-context
  • PostToolUse (matcher *) → hook claude-code observation
  • Stop → hook claude-code summarize
The exact hooks.json entries are written by the installer; do not hand-edit them in the marketplace copy unless you know what you’re doing.

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, so these switches turn off claude-mem’s per-tool work, not the hook process itself.

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 to 127.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:
The host setting and the token work as a pair: 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:
  1. GET /api/observations returns 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 with offset.
  2. /stream is unfiltered. It carries every observation for every project on the box, plus the project catalog and processing status. There is no per-client filtering.
  3. No rate limiting. A token holder can hammer GET /api/observations freely.
  4. The token is readable on loopback via GET /api/settings, exactly like your provider API keys are today. It is deliberately not writable through POST /api/settings (that route is unauthenticated), so it can only be set by someone with filesystem or environment access.
  5. /stream is not side-effect-free. Every new connection triggers an initial_load broadcast 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:
Then restart the worker:

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: open https://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 generate CLAUDE.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 from CLAUDE_MEM_WORKER_PORT.
  1. Click the gear icon in the header
  2. Adjust settings in the right panel
  3. See changes reflected live in the Terminal Preview on the left
  4. Settings auto-save as you change them
The Terminal Preview shows the selected project and source. Select All sources to preview a combined SessionStart context.

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 resolutions
  • feature - New functionality additions
  • refactor - Code restructuring
  • discovery - Learnings about how code works
  • decision - Architectural or design decisions
  • change - General code changes
Concepts (select any combination):
  • how-it-works - System behavior explanations
  • why-it-exists - Rationale for code/design
  • what-changed - Change summaries
  • problem-solution - Problem/solution pairs
  • gotcha - Edge cases and pitfalls
  • pattern - Recurring patterns
  • trade-off - Design trade-offs
Use “All” or “None” buttons to quickly select/deselect all options.

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:
Note: The Context Settings Modal (in the web viewer) is the recommended way to configure these settings, as it provides live preview of changes.

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:
Then restart the worker:

Custom Model

Edit ~/.claude-mem/settings.json:
Then restart the worker:

Custom Skip Tools

Control which tools are excluded from observations. Edit ~/.claude-mem/settings.json:
Default excluded tools:
  • ListMcpResourcesTool
  • SlashCommand
  • Skill
  • TodoWrite
  • AskUserQuestion
Common customizations:
  • 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
Changes take effect on the next tool execution (no worker restart needed).

Advanced Configuration

Hook Timeouts

Hook timeouts are written into plugin/hooks/hooks.json by the installer. The current defaults match the shape of the workload at each lifecycle stage:
  • Setup (version-check.js): 300s ceiling; fast when the plugin’s dependencies are complete, up to 120s when it has to run bun install
  • SessionStart (worker-start + context): 60s
  • UserPromptSubmit: 60s
  • PreToolUse (file-context, Read matcher): 60s
  • 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.

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

  1. Use defaults: Default configuration works for most use cases
  2. Override selectively: Only change what you need
  3. Document changes: Keep track of custom configurations
  4. Test after changes: Verify worker restarts successfully
  5. Monitor logs: Check worker logs after configuration changes

Troubleshooting Configuration

Configuration Not Applied

  1. Restart worker after changes:
  2. Verify environment variables:
  3. 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 for CLAUDE_MEM_MODEL:
  • claude-haiku-4-5-20251001 (default)
  • claude-sonnet-5
  • claude-opus-4-8

Port Already in Use

The default worker port is 37700 + (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:
  1. Set custom port:
  2. Restart worker:
  3. Verify new port:

Next Steps