OpenClaw plugin: Personal Brain Memory (v0.2.0).
A lightweight OpenClaw Gateway plugin that acts as a personal brain:
- Listens for inbound messages and captures likely-valuable notes based on configurable triggers.
- Stores everything locally in a JSONL file with optional secret redaction.
- Supports semantic-ish search via hash-based embeddings.
- Provides slash commands for manual CRUD operations.
- Enforces a configurable item cap (
maxItems) with oldest-first eviction.
clawhub install openclaw-memory-brainopenclaw plugins install -l ~/.openclaw/workspace/openclaw-memory-brain
openclaw gateway restartExplicitly save a personal brain memory item. Optionally add custom tags.
/remember-brain TypeScript 5.5 requires explicit return types on exported functions
/remember-brain Use Redis for session caching --tags arch,caching
Custom tags are merged with the configured defaultTags (duplicates are removed automatically). Returns a confirmation message. If redactSecrets is enabled (default), any detected secrets are automatically redacted before storage and the response notes it.
Search brain memory items by semantic similarity. Optionally filter by tags (AND logic - items must have ALL specified tags).
/search-brain TypeScript configuration
/search-brain architecture decisions 10
/search-brain caching strategy --tags arch
/search-brain API design --tags api,design 5
query- the search text (required)--tags tag1,tag2- filter by tags, comma-separated (optional, AND logic)limit- maximum number of results (optional, default 5, max 20)
The trailing argument is interpreted as a limit if it is a bare number and more than one argument is present. A sole numeric argument is treated as the query itself. Returns scored results sorted by relevance. Recently-accessed items receive a configurable recency boost (see search.recencyBoost). Each returned item's lastAccessedAt timestamp is updated.
List the most recent brain memory items. Optionally filter by tags (AND logic). Use --stale N to list items not accessed in N or more days.
/list-brain
/list-brain 20
/list-brain --tags arch
/list-brain --tags api,design 10
/list-brain --stale 30
/list-brain --tags arch --stale 60
--tags tag1,tag2- filter by tags, comma-separated (optional, AND logic)--stale days- show only items not accessed in N+ days (optional). Items without alastAccessedAtare treated as stale.limit- maximum number of items to return (optional, default 10, max 50)
Returns items in insertion order (oldest first), showing date and a truncated preview. Each returned item's lastAccessedAt timestamp is updated.
List all unique tags across all brain memory items, sorted alphabetically.
/tags-brain
Returns a comma-separated list of all tags with a count, e.g. Tags (4): api, arch, brain, design.
Export brain memory items as JSON or Markdown. Optionally filter by tags.
/export-brain
/export-brain --tags arch,design
/export-brain --format md
/export-brain --tags arch --format md
JSON format (default) - returns a JSON object with a version envelope:
{
"version": 1,
"exportedAt": "2026-02-27T10:30:00.000Z",
"count": 2,
"items": [...]
}The items array contains full MemoryItem objects with all fields preserved. Copy the output to a file for backup, or pass it to /import-brain on another instance.
Markdown format (--format md) - returns a human-readable document grouped by tags:
# Brain Memory Export - 2026-03-02
## arch
- [2026-02-27] Architecture decision about modules
## design
- [2026-02-28] Design pattern for servicesItems with multiple tags appear under each relevant tag heading. Items with no tags appear under ## (untagged). Tags are sorted alphabetically. The --tags filter is compatible with --format md.
Import brain memory items from a JSON export. Requires authentication. Accepts either:
- A JSON array of memory items
- An envelope object (as produced by
/export-brain) with anitemsarray
/import-brain [{"id":"...","kind":"note","text":"...","createdAt":"..."}]
/import-brain {"version":1,"items":[...]}
- Items that already exist (by ID) are skipped automatically
- Items missing an
idfield get a new UUID assigned - Items with an invalid or missing
kinddefault to"note" - Items without
tagsreceive the configureddefaultTags - Returns a summary:
Imported N items. X skipped (already exist). Y skipped (invalid format).
Delete brain memory items older than the configured retention period (retention.maxAgeDays). Requires authentication.
/purge-brain
/purge-brain --dry-run
- Returns
"Retention policy is not configured."ifmaxAgeDaysis 0 or unset. - Use
--dry-runto preview how many items would be deleted without actually removing them. - Returns a summary:
Purged N item(s) older than X day(s). M item(s) remaining.
When retention.maxAgeDays is configured, expired items are also automatically purged on plugin startup.
Delete a brain memory item by its unique ID. Requires authentication.
/forget-brain 550e8400-e29b-41d4-a716-446655440000
Returns a confirmation or a not-found message.
An AI-callable tool for searching brain memories programmatically. Supports optional tag-based filtering.
{
"query": "string (required) - the search text",
"limit": "number (optional, 1-20, default 5)",
"tags": "string[] (optional) - filter results to items that have ALL of these tags"
}{ "query": "Anthropic reset schedule", "limit": 5 }
{ "query": "caching strategy", "tags": ["arch", "caching"] }{
"hits": [
{
"score": 0.87,
"id": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2026-02-27T10:30:00.000Z",
"tags": ["brain"],
"text": "Remember: Anthropic resets usage limits on the 1st of each month."
}
]
}Returns an empty hits array when no results match.
The plugin listens on the message_received event and conditionally captures inbound messages as memory items.
A message is captured when all of the following are true:
- Message content is not empty
- Message length >=
minChars(default: 80 characters) - Channel is allowed by channel policy
- At least one of:
- The message contains an explicit trigger (e.g. "remember this", "keep this")
requireExplicitisfalseAND the message contains an auto-topic keyword (e.g. "decision")
- The message's confidence score >=
captureThreshold(default: 0.4) - The message is not a near-duplicate (when
dedupeThreshold> 0)
Convention: brain-memory should not silently store large amounts of chat. The recommended default is requireExplicit: true.
Each candidate message receives a 0-1 confidence score based on weighted signals:
| Signal | Weight | Condition |
|---|---|---|
| Explicit trigger | +0.4 | Message contains an explicit trigger keyword |
| Auto-topic | +0.2 | Message contains an auto-topic keyword |
| Substantive length | +0.2 | Message length >= 120 characters |
| Structural markers | +0.2 | Message contains code blocks, bullet lists, or numbered lists |
The score is capped at 1.0. Messages scoring below captureThreshold (default 0.4) are skipped. Explicit /remember-brain commands bypass scoring entirely.
The confidence score is stored in meta.capture.score on each auto-captured item for debugging. The /brain-status command shows the average score of the last 20 captured items.
- Case-insensitive substring matching (e.g. "merke dir" also matches "Merke dir:" naturally)
- Default explicit triggers:
merke dir,remember this,notiere,keep this - Default auto-topics:
entscheidung,decision
All configuration is provided via openclaw.plugin.json or the plugin config block.
{
"plugins": {
"entries": {
"openclaw-memory-brain": {
"enabled": true,
"config": {
"storePath": "~/.openclaw/workspace/memory/brain-memory.jsonl",
"dims": 256,
"redactSecrets": true,
"maxItems": 5000,
"capture": {
"minChars": 80,
"requireExplicit": true,
"captureThreshold": 0.4,
"explicitTriggers": ["merke dir", "remember this", "notiere", "keep this"],
"autoTopics": ["entscheidung", "decision"]
},
"defaultTags": ["brain"],
"search": {
"recencyBoost": 0.1
},
"retention": {
"maxAgeDays": 90
}
}
}
}
}
}| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | true |
Enable or disable the plugin entirely |
storePath |
string | ~/.openclaw/workspace/memory/brain-memory.jsonl |
Path to the JSONL storage file (must be inside home directory) |
dims |
number | 256 |
Embedding vector dimensions (32-2048) |
redactSecrets |
boolean | true |
Redact detected secrets (API keys, tokens, passwords) before storage |
maxItems |
number | 5000 |
Maximum number of memory items to keep (oldest are evicted, 100-100000) |
defaultTags |
string[] | ["brain"] |
Default tags applied to all captured items |
retention.maxAgeDays |
number | 0 |
Delete items older than this many days. 0 = disabled. Expired items are purged on startup and via /purge-brain. |
capture.minChars |
number | 80 |
Minimum message length for auto-capture (10+) |
capture.requireExplicit |
boolean | true |
When true, only explicit triggers cause capture (recommended) |
capture.explicitTriggers |
string[] | see above | Phrases that trigger explicit capture (substring match, case-insensitive) |
capture.captureThreshold |
number | 0.4 |
Minimum confidence score (0-1) for auto-capture. Messages below this are skipped. 0 = disabled. |
capture.autoTopics |
string[] | ["entscheidung", "decision"] |
Topic keywords that trigger capture when requireExplicit is false |
search.recencyBoost |
number | 0.1 |
Recency boost factor (0-1) for search scoring. Recently accessed items get a score boost proportional to how recently they were accessed (capped at 90 days). 0 = disabled. |
- The plugin redacts common secrets (API keys, tokens, passwords, private key blocks, JWTs, connection strings) before storage.
- Redaction uses pattern-based detection and never stores matched secret values - only the rule name and count.
- The store path is validated to stay inside the user's home directory (path traversal guard).
- PII is only stored locally on disk in the JSONL file - no external transmission.
npm install
npm run build # TypeScript type-check (noEmit, strict mode)
npm test # Run vitest test suite (244 tests)
npm run test:watch # Watch modeThe test suite covers all plugin functionality:
- Plugin registration (commands, tool, event handler, disabled state, invalid config)
/remember-brain(save, usage, empty args, secret redaction, source context, --tags flag, tag merging)/search-brain(query, usage, no-match, trailing limit, sole numeric arg, --tags filtering)/list-brain(empty store, populated listing, limit argument, default limit, --tags filtering)/forget-brain(usage, not-found, delete + verify, requireAuth)/tags-brain(empty store, unique tag listing, deduplication, alphabetical sort)/export-brain(empty store, JSON envelope format, MemoryItem fields, --tags filtering, valid JSON output)/import-brain(usage, invalid JSON, invalid structure, empty array, bare array import, envelope import, duplicate skipping, invalid entry skipping, default tags, kind preservation, kind defaulting, UUID generation, requireAuth)- Export/import round-trip (data preservation, idempotent re-import)
/purge-brain(not-configured, delete expired, no items to purge, --dry-run preview, requireAuth, metadata)- Retention startup cleanup (auto-purge on startup, logging, disabled when maxAgeDays=0, no log when nothing expired)
- Retention edge cases (invalid createdAt, empty store, purge all items)
brain_memory_searchtool (result shape, empty/undefined query, limit, schema, tags parameter)- Tag-based filtering (AND logic, single tag, multiple tags, no-match tag, empty tags, merged tags with defaults)
- Auto-capture (explicit trigger, auto-topic, short message rejection, no-trigger rejection, requireExplicit enforcement, empty content, case-insensitivity, secret redaction, error handling, custom minChars, custom triggers)
- Custom configuration (defaultTags, custom autoTopics, redactSecrets toggle)
- Output formatting (text truncation at 120 chars, ellipsis behavior)
- Edge cases (sole numeric arg, whitespace-only arg, limit clamping, multiple captures)
- Logger verification (startup info, capture info, error on invalid path)
- Command metadata (name, description, usage, requireAuth, acceptsArgs)
- Confidence scoring (
scoreCaptureunit tests, threshold boundary conditions, integration with auto-capture, meta.capture.score storage, /brain-status avg score display) - lastAccessedAt tracking (set on search/list results, not set on new items, updates on subsequent access)
- Recency boost (boost applied to recently accessed items, zero boost when disabled, default 0.1, clamped 0..1)
/list-brain --stale(stale item filtering, never-accessed items treated as stale, combined with --tags, limit support)- Backward compatibility (items without lastAccessedAt work in search, get zero recency boost)
- Runtime:
@elvatis_com/openclaw-memory-core(local linked package) - Dev:
typescript,vitest,@types/node
For automation that creates GitHub issues, use src/templates/github-issue-helper.ts.
It provides isValidIssueRepoSlug(), resolveIssueRepo(), and buildGhIssueCreateCommand().
MIT