Memory system for claws
/install claw-mem2db
claw-mem2db — persistent semantic memory for agents
A standalone, plug-in memory layer for OpenClaw agents. claw-mem2db turns every conversation and every tool call into a queryable history — automatic capture, local SQLite + FTS5 storage, hybrid recall on the next prompt. Use it on its own for long-lived agent memory; pair it with coc-soul for on-chain backup, DID identity, P2P storage, and cross-device recovery — i.e. digital / silicon-based persistence.
Naming note. This ClawHub skill is published as
claw-mem2dbbecause the bareclaw-memslug was taken. The underlying artifacts keep the original names:
- npm package:
@chainofclaw/claw-mem- OpenClaw plugin id:
claw-mem(auto-loaded afteropenclaw plugins install)- Standalone CLI binary:
claw-mem— only present if you separately rannpm i -g @chainofclaw/claw-mem.openclaw plugins installdoes not put it on your PATH.Inside OpenClaw, you don't need the standalone bin. Use the agent tools or
openclaw mem …(covered below).
Install
The plugin ships on npm as @chainofclaw/claw-mem. The full real-world install command is:
openclaw plugins install @chainofclaw/claw-mem --dangerously-force-unsafe-install --force
Two flags are needed in practice — neither is "skip safety checks for fun":
--dangerously-force-unsafe-install— claw-mem legitimately useschild_process(theopenclawsummarizer mode spawnsopenclaw infer model run; bootstrap helpers shell out). OpenClaw's static scan flags any plugin that importschild_process, so this flag is required to whitelist a known-safe consumer. It is not disabling sandboxing of the running plugin.--force— allows reinstalling/upgrading over an existing extension directory without the "already installed" abort.
If openclaw plugins install itself errors out (npm cache EACCES, registry timeout, etc.), fall back to the in-place tarball install — see the appendix in references/cli.md.
After install: writable data dir
claw-mem opens its SQLite DB on first activation. The data dir auto-resolves (1.1.17+):
config.dataDir(per-instance plugin config — set this when the defaults below don't work)$CLAW_MEM_DATA_DIR(operator env override)$OPENCLAW_STATE_DIR/claw-mem(OpenClaw's standard sandboxed state-dir)~/.claw-mem(standalone default)
The first writable candidate wins. If every candidate fails, the plugin throws an actionable error — it does not silently fall back to /tmp.
Sandboxed hosts (Docker, restricted-uid runners) commonly hit EACCES on ~/.claw-mem because $HOME is read-only or owned by a different uid. The fix is to point claw-mem at an explicitly-writable directory in ~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"claw-mem": {
"config": {
"dataDir": "/home/node/.openclaw/state/claw-mem"
}
}
}
}
}
Use whatever absolute path is writable in your environment (~/.openclaw/state/claw-mem is a good default since OpenClaw already owns that tree). Restart the gateway after editing. Verify with openclaw mem status — if it returns counts (even 0/0/0), the DB opened successfully.
Zero-config (after the install + dataDir step)
No further setup needed. No chain interaction, no external services, no required env vars beyond the dataDir override above (and only when the default isn't writable).
- Session hooks auto-register: every tool call becomes a candidate observation; sessions are summarized on close.
- Reads work immediately once any observations have been captured.
CLAW_MEM_DATA_DIRis the only env knob and it has a sensible default.
Memory-only mode is expected, not a degradation. The gateway log line [claw-mem] Loaded (memory layer only) is intentional — claw-mem deliberately owns only the memory layer. If you've also installed coc-node and/or coc-soul, each registers its own commands/tools under its own root, so the three plugins cleanly compose without stepping on each other.
Session summaries default to openclaw mode when loaded inside OpenClaw (1.1.16+). Each session-end summary is generated by spawning openclaw infer model run --json — the summarizer reuses whatever inference provider the host's OpenClaw agent is already authenticated for. No claw-mem-specific API key, no extra env var, no model picker. If the spawn fails (openclaw not on PATH, no provider auth) the summarizer falls back to a heuristic stringifier so observations still get summaries. Override with summarizer.mode: "heuristic" to skip LLM calls entirely, or summarizer.mode: "llm" + summarizer.llm.apiKey (or ANTHROPIC_API_KEY env) to talk to Anthropic directly via the bundled SDK.
Mental model
Two streams feed the same store:
- Chat — every user message (and optionally every assistant message) is run through a lightweight extractor that flags explicit cues (e.g. "remember this", "note this", "for the record" — full bilingual EN + zh-CN dictionary in the cue config) as
decisionobservations and preference cues (e.g. "I prefer", "from now on", "always use") aslearning. Plain chat lands as a low-signaldiscovery. - Tool calls — every tool the agent runs becomes a typed observation (discovery / decision / pattern / learning / issue / change / explanation), capturing what was read, edited, searched, or executed.
Both streams write into a single local SQLite database with FTS5 full-text search. On each new prompt, claw-mem assembles a token-budgeted memory context via hybrid recall — an FTS5 search on the latest user message merged with the recent tail — and injects it into the next prompt. Sessions are summarized on close (the host's OpenClaw inference provider does the summarization, no extra API key needed).
What the agent gets in return:
- No more "I forgot what we were doing" between sessions or after compaction
- Searchable history of decisions, preferences, and the rationale behind them
- Explicit "remember this" cues in chat reliably stick as
decisionobservations (bilingual EN + zh-CN cue dictionaries built in) - All memory stays local by default — no network, no chain, no external service
Optional companions: from local memory to digital immortality
claw-mem2db is complete on its own. It needs nothing else to capture, search, or inject memory. But two adjacent skills extend the agent in directions claw-mem deliberately doesn't:
| Skill | What it adds on top of claw-mem | When to install |
|---|---|---|
| coc-soul | On-chain memory snapshots, DID identity, P2P / IPFS-backed storage, cross-device recovery & resurrection | When you want the agent to survive a host dying, a disk failing, or a move to a different machine — i.e. digital / silicon-based persistence |
| coc-node | Running a COC blockchain node so the agent participates in the network instead of just consuming it | When you want the agent to be a first-class peer rather than a guest |
The plugins are fully decoupled: claw-mem doesn't know whether coc-soul is installed, and works the same way either way. Installing coc-soul alongside claw-mem creates the immortality story (memory captured locally → snapshotted to chain + IPFS → recoverable from a fresh host using the agent's DID), but you can adopt it later without changing anything in claw-mem.
How to use it
From inside an agent loop (preferred)
The plugin registers three agent-callable tools. Use these — not shell commands — when you're an agent answering the user. No PATH lookup, no plugin discovery, no shell context required.
| Tool | Parameters | Returns |
|---|---|---|
mem-search |
query (required), limit?, type? (discovery | decision | pattern | learning | issue | change | explanation) |
Matching observations from FTS5 index |
mem-status |
none | Stats: observation/summary/session counts, agents, DB path, tokenBudget |
mem-forget |
sessionId (required) |
Confirms deletion of that session's observations |
Typical agent-side patterns:
- Before deciding how to approach a familiar-feeling task, call
mem-searchwith the topic — past decisions and their rationale will surface. - Before claiming "I'm not sure about X," call
mem-searchfor X. - When the user says "forget that whole session" or you notice a session is polluting search results, call
mem-forgetwith the session id frommem-status.
From a human shell (CLI)
When operating from a terminal — install/upgrade scripts, ops checks, manual cleanup — use the OpenClaw CLI namespace. Every memory operation is reachable as openclaw mem \x3Csubcommand>.
openclaw mem search "checkpoint" # FTS5 keyword/phrase search
openclaw mem search "..." --type decision --limit 20 --json
openclaw mem status # DB stats; --json for machine output
openclaw mem peek # preview the context that would be injected
openclaw mem forget \x3CsessionId> # delete one session's observations
openclaw mem prune --older-than 90 # drop observations older than 90 days
openclaw mem prune --before 2025-01-01 # explicit cutoff
openclaw mem export memory.json # dump observations to JSON
openclaw mem import memory.json # restore from JSON
Sibling subtrees:
openclaw mem config get|set|list|path # plugin config (persisted to ~/.claw-mem/config.json)
openclaw mem db vacuum|migrate-status|size # SQLite maintenance
openclaw mem version # plugin version
Configuration knobs worth knowing
tokenBudget(default 8000) — how much of the next prompt goes to memory contextmaxObservations/maxSummaries(50 / 10) — hard caps on what's considered for injectionskipTools— tools the observer skips entirely (defaults excludeTodoWrite,AskUserQuestion,Skillbecause they're usually noisy meta-tools)dedupWindowMs(30000) — de-duplicate observations with the same content hash within this windowsummarizer.mode—openclaw(default inside OpenClaw — spawnsopenclaw infer model run),heuristic(no LLM), orllm(direct Anthropic SDK with own apiKey)summarizer.openclaw.model— pin a specific provider/model for summary calls (default: let OpenClaw pick);summarizer.openclaw.timeoutMsdefaults to 60000ms
Chat compaction (2.3.0+) — automatic summarization & space reclamation
By default, chat capture writes one observation per message. Over time the chat tail grows and the agent's tokenBudget gets eaten by raw chitchat. v2.3.0 adds a compactor that rolls batches of chat observations into a single chat_compaction summary, and (optionally) hard-deletes low-importance originals to reclaim space.
Pipeline:
- Capture-time denoising — emoji-only / pictograph-only turns are dropped entirely (don't even reach the DB). Each captured row gets a heuristic
importancescore (0.0–1.0) computed from cue match, presence of dates / URLs / code / numbers, length, role, and chitchat-token detection. - Trigger — every
chatMemory.compaction.triggerEverychat captures (default 10) the compactor runs in the background. It also fires opportunistically onagent_end. - Roll-up — the compactor pulls uncompacted chat rows (skipping the most-recent
keepRecentRaw, default 20), passes the batch through the configured summarizer (openclawmode by default — same auth path as session summaries), writes a singlechat_compactionobservation taggedtool_name="chat_compaction"withimportance=0.9, then marks the originalscompacted=1, compacted_into=\x3Cid>. - Prune — when
deleteCompactedLowValue=true(default), compacted rows whoseimportance \x3C minImportanceToKeep(default 0.7) are hard-deleted. The most-recentkeepRecentRaware always retained regardless of importance. - Recall —
before_prompt_buildandmem-searchexcludecompacted=1rows by default, so the agent reads the compaction summary + the recent tail instead of seeing the same content twice.
Schema (migration v3, additive — safe on existing DBs):
| Column | Type | Default | Meaning |
|---|---|---|---|
compacted |
INTEGER | 0 |
1 = rolled into a chat_compaction; hidden from default recall / search |
importance |
REAL | 0.5 |
heuristic score; higher = more worth keeping |
compacted_into |
INTEGER | NULL | id of the chat_compaction observation that this row was rolled into (audit trail) |
Config (under chatMemory.compaction):
enabled(defaulttrue)triggerEvery(default10) — run a pass every N captureskeepRecentRaw(default20) — never compact the most-recent NdeleteCompactedLowValue(defaulttrue) — hard-delete after compactionminImportanceToKeep(default0.7) — prune thresholdidleMs(default120000) — reserved for future idle-based trigger
Set chatMemory.compaction.enabled = false to keep raw chat rows forever (audit-heavy use). Set deleteCompactedLowValue = false to keep all originals on disk but still benefit from cleaner recall (the compaction summary stays small).
Chat memory (2.1.0+ / renamed knobs in 2.2.0)
Pure chat sessions used to slip past the observer because capture only fired on after_tool_call. v2.1.0 added message_received / message_sent capture so spoken-only conversations build up memory too. v2.2.0 also exposes the schema in openclaw.plugin.json so openclaw plugins inspect claw-mem shows both hooks and config keys, and renames the knobs to match the OpenClaw operator-side conventions (breaking — see migration table below). Defaults are conservative: user messages are captured, assistant messages are not.
chatMemory.enabled(defaulttrue) — master switch for chat capturechatMemory.explicitOnly(defaultfalse) — only capture when the message contains an explicit cue ("remember this", "note this", "for the record", "save this", and the equivalent zh-CN tokens shipped in the default cue dictionary); silences everything elsechatMemory.minChars(default8) — drop shorter messages as chitchatchatMemory.maxNarrativeChars(default500) — truncate the captured narrative body at this many characterschatMemory.cues.explicit/chatMemory.cues.preference— override the cue dictionaries (defaults ship bilingual EN + zh-CN); preference cues ("I prefer", "from now on", "always use" + zh-CN equivalents) becomelearningobservations. To inspect or override the actual default tokens, runopenclaw mem config get chatMemory.cueschatMemory.captureAssistant(defaultfalse) — also capture assistant messages viamessage_sent(use sparingly — high noise)
Chat observations now carry toolName: "message_received" (user) or toolName: "message_sent" (assistant) — a 1:1 mapping with the originating hook so downstream filters can write tool_name IN ('message_received','message_sent') for "all chat" or pull just one direction. Still no schema migration; the existing tool_name column carries the value.
2.1.0 → 2.2.0 migration (config keys):
| Old (2.1.0) | New (2.2.0) |
|---|---|
chatMemory.minLen |
chatMemory.minChars |
chatMemory.captureAssistantPromises |
chatMemory.captureAssistant |
| (hard-coded 500) | chatMemory.maxNarrativeChars |
chat observations had tool_name: "chat" |
now "message_received" / "message_sent" |
Context recall
How before_prompt_build picks observations to inject:
contextRecall.mode(defaulthybrid) —recentkeeps the chronological tail;hybridruns an FTS5 search on the latest user message and merges the hits with the recent tail (deduped by id). Hybrid surfaces topical past memories instead of always showing the last N regardless of relevance.contextRecall.searchLimitRatio(default0.5) — fraction ofmaxObservationsreserved for search hits in hybrid mode; the rest is filled with recent.
Hybrid mode falls back transparently to recent-only if the search throws or no user-message text is available.
Edit any knob with openclaw mem config set \x3Cpath> \x3Cvalue>.
Hardening (opt-outs)
Default behavior: claw-mem auto-injects a memory context block into every prompt (via before_prompt_build) and exposes mem-search / mem-status / mem-forget to the agent. That's the right default for "give the agent persistent memory and let it use it."
If your deployment wants memory to be query-only — captured in the background, but never auto-injected and never callable from inside the agent loop — the gateway provides two host-side switches in ~/.openclaw/openclaw.json:
{
"plugins": {
"entries": {
"claw-mem": {
"hooks": {
// Block claw-mem's before_prompt_build hook from stuffing context
// into the next prompt. Observation capture (after_tool_call) and
// session summarization (session_end) still fire — only the
// prompt-side injection is suppressed.
"allowPromptInjection": false
}
}
}
},
// Host-level filter: hide these tools from the agent's tool list entirely.
// Useful for tightening the agent's surface (e.g. blocking exec/process)
// and/or making memory access human-only via the CLI.
"skipTools": ["exec", "process", "mem-search"]
}
Pick what fits your threat model:
- Capture but don't inject — set
allowPromptInjection: false. Observations still accumulate; you read them viaopenclaw mem searchwhen needed. - CLI-only memory — also add
mem-search(and optionallymem-status/mem-forget) to the host'sskipTools. The agent can no longer query memory; only humans can viaopenclaw mem …. - Default ("memory just works") — leave both unset.
Note: the plugin-config knob skipTools (under plugins.entries.claw-mem.config.skipTools, listed above) is a different filter. It controls which observed tool calls the observer records, not which tools the agent can see. The host-level skipTools at the top of openclaw.json is what gates agent visibility.
Verification (post-install smoke test)
After openclaw plugins install @chainofclaw/claw-mem (or an in-place upgrade), restart the gateway and run:
openclaw mem status # proves the plugin is loaded; shows 0/0/0 on a fresh DB
openclaw mem peek # context that would inject on the next prompt
openclaw mem db migrate-status # confirms schema is current; 0 pending migrations
All three should succeed without errors. Common failure modes:
unknown command 'mem'— the plugin failed to load. Checkplugins.allowin~/.openclaw/openclaw.jsonand the gateway startup logs for[claw-mem] Loaded(or a[claw-mem] Bootstrap failed:line).Bootstrap failed: ... EACCES ... /home/.../.claw-mem— the default~/.claw-memisn't writable on this host. Apply the explicitdataDiroverride from the Install section.mem search/mem-searchagent tool returns "tool not found" — check whether the host hasmem-searchinskipTools(see Hardening). If yes, that's intentional; query via the CLI or remove the entry.
When NOT to use this skill
- You want ephemeral agent sessions with no persistent history — don't install claw-mem; OpenClaw's in-session context is enough.
- You want memory-like search only for code — tools like grep / ripgrep /
codebase_searchserve that need without the persistence overhead. - You want on-chain / cross-device backup — add coc-soul on top; claw-mem only persists locally.
Reference
references/cli.md— everyopenclaw mem|config|dbsubcommand, plus the standalone-bin appendixreferences/config.md— complete config schemareferences/observer.md— how observations are extracted, when hooks firereferences/programmatic-api.md— usingDatabase/ObservationStore/SearchEngineas a library
Source and issue tracker: \x3Chttps://github.com/NGPlateform/claw-mem>.
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install claw-mem2db - After installation, invoke the skill by name or use
/claw-mem2db - Provide required inputs per the skill's parameter spec and get structured output
What is Memory system for claws?
Give an AI agent persistent semantic memory that survives restarts and compaction. Captures structured observations from tool calls, summarizes sessions (LLM... It is an AI Agent Skill for Claude Code / OpenClaw, with 182 downloads so far.
How do I install Memory system for claws?
Run "/install claw-mem2db" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Memory system for claws free?
Yes, Memory system for claws is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Memory system for claws support?
Memory system for claws is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Memory system for claws?
It is built and maintained by Meshes & Parallels (@ngplateform); the current version is v2.3.1.