Local-first knowledge graph plugin for OpenClaw β persistent memory with graph search and composited memory search.
The openclaw-basic-memory plugin integrates Basic Memory with OpenClaw to provide:
- Composited
memory_searchβ queries MEMORY.md, the BM knowledge graph, and active tasks in parallel - Persistent MCP stdio session β keeps a single
bm mcp --transport stdio --project <name>process alive - Auto-capture β records agent conversations as structured daily notes
- Graph tools β search, read, write, edit, delete, move, and navigate notes via
memory://URLs
For a practical runbook, see Memory + Task Flow.
-
Basic Memory CLI (
bm) with MCP server support:bm mcp --transport stdio --project <name>- MCP tools with JSON output mode:
read_note,write_note,edit_note,recent_activity,list_memory_projects,create_memory_project,delete_note,move_note - Structured MCP tools:
search_notes,build_context
uv tool install 'basic-memory[semantic] @ git+https://github.com/basicmachines-co/basic-memory.git@f2683291e478568cdf1676759ed98c70d7cfdac3' --with 'onnxruntime<1.24; platform_system == "Darwin" and platform_machine == "x86_64"' # Alternative (inside an existing Python environment): uv pip install 'basic-memory[semantic] @ git+https://github.com/basicmachines-co/basic-memory.git@f2683291e478568cdf1676759ed98c70d7cfdac3' 'onnxruntime<1.24; platform_system == "Darwin" and platform_machine == "x86_64"'
-
OpenClaw with plugin support
git clone https://github.com/basicmachines-co/openclaw-basic-memory.git
cd openclaw-basic-memory
bun install
openclaw plugins install -l "$PWD"Then set this plugin as the memory slot owner in your OpenClaw config:
{
plugins: {
entries: {
"basic-memory": {
enabled: true
}
},
slots: {
memory: "basic-memory"
}
}
}Restart OpenClaw gateway after install/config changes, then verify:
openclaw plugins list
openclaw plugins info basic-memoryIf you prefer loading directly from a path in config instead of plugins install:
{
plugins: {
load: {
paths: ["~/dev/openclaw-basic-memory"]
},
entries: {
"basic-memory": {
enabled: true
}
},
slots: {
memory: "basic-memory"
}
}
}You can pair this plugin with skills from
basic-memory-skills:
memory-tasksβ structured task tracking that survives compactionmemory-reflectβ periodic consolidation of recent notes into durable memorymemory-defragβ periodic cleanup/reorganization of memory files
Install (workspace-local):
git clone https://github.com/basicmachines-co/basic-memory-skills.git
cp -r basic-memory-skills/memory-tasks ~/.openclaw/workspace/skills/
cp -r basic-memory-skills/memory-reflect ~/.openclaw/workspace/skills/
cp -r basic-memory-skills/memory-defrag ~/.openclaw/workspace/skills/If you want these skills available to multiple workspaces/agents on the same machine,
install to ~/.openclaw/skills/ instead.
After installation, start a new OpenClaw session so the refreshed skill set is loaded.
{
"basic-memory": {
enabled: true
}
}This uses sensible defaults: auto-generated project name, maps Basic Memory to your workspace memory/ directory, and captures conversations.
{
"basic-memory": {
enabled: true,
config: {
project: "my-agent", // BM project name (default: "openclaw-{hostname}")
bmPath: "bm", // Path to BM CLI binary
projectPath: "~/.openclaw/workspace/memory/", // Optional override; supports absolute, ~/..., or workspace-relative paths
memoryDir: "memory/", // Relative memory dir for task scanning
memoryFile: "MEMORY.md", // Working memory file for grep search
autoCapture: true, // Index conversations automatically
debug: false, // Verbose logging
cloud: { // Optional cloud sync
url: "https://cloud.basicmemory.com",
api_key: "your-key"
}
}
}
}| Option | Type | Default | Description |
|---|---|---|---|
project |
string | "openclaw-{hostname}" |
Basic Memory project name |
bmPath |
string | "bm" |
Path to Basic Memory CLI binary |
projectPath |
string | "memory/" |
Directory for BM project data (resolved from workspace unless absolute) |
memoryDir |
string | "memory/" |
Relative path for task scanning |
memoryFile |
string | "MEMORY.md" |
Working memory file (grep-searched) |
autoCapture |
boolean | true |
Auto-index agent conversations |
debug |
boolean | false |
Enable verbose debug logs |
cloud |
object | β | Optional cloud sync config (url + api_key) |
Snake_case aliases (memory_dir, memory_file) are also supported.
On startup, the plugin ensures the configured BM project exists at projectPath via MCP create_memory_project in idempotent mode.
On startup, the plugin starts one persistent MCP stdio session:
- Spawns
bm mcp --transport stdio --project <name> - Verifies required MCP tool capabilities at connect time
- Uses bounded reconnect attempts (
500ms,1000ms,2000ms) when the session drops
Basic Memory MCP lifecycle handles sync and watch behavior for the project.
When the agent calls memory_search, three sources are queried in parallel:
- MEMORY.md β grep/text search with Β±1 line context
- BM Knowledge Graph β hybrid FTS + vector search (top 5 results with scores)
- Active Tasks β scans
memory/tasks/for non-done tasks
Results are formatted into clear sections:
## MEMORY.md
- matching lines with context...
## Knowledge Graph (memory/)
- note-title (0.85)
> preview of content...
## Active Tasks
- **Task Name** (status: active, step: 3)
context snippet...
This plugin works best if you treat memory as three lanes:
- Working memory (
MEMORY.md) β short-horizon context and current focus. - Knowledge graph (
memory/**/*.md) β long-term notes indexed by Basic Memory. - Task notes (
memory/tasks/*.md) β active execution state for in-flight work.
Typical loop:
- Capture or update notes/tasks with
bm_write/bm_edit. - The persistent BM MCP process syncs markdown updates into the BM project index.
memory_searchqueries:MEMORY.mdtext snippets- BM search results (semantic + FTS)
- active tasks
- Drill into one result with
memory_getorbm_read. - Advance tasks by updating
current_step, checkboxes, and context. - Complete tasks by setting
status: done(done tasks are excluded from active task results).
flowchart LR
A["Write/Update notes"] --> B["BM MCP indexes changes"]
B --> C["memory_search(query)"]
C --> D["MEMORY.md"]
C --> E["Knowledge Graph"]
C --> F["Active Tasks"]
D --> G["Composited result"]
E --> G
F --> G
G --> H["memory_get / bm_read"]
H --> A
memory_search task extraction is strongest when task notes include:
- file location:
memory/tasks/*.md - frontmatter fields:
status:andcurrent_step: - a
## Contextsection for preview snippets
Example:
---
title: auth-middleware-rollout
type: Task
status: active
current_step: 2
---
## Context
Rolling JWT middleware to all API routes. Staging verification is in progress.
## Plan
- [x] Implement middleware
- [x] Add refresh-token validation
- [ ] Roll out to staging
- [ ] Verify logs and error ratesTo mark complete, update:
status: doneDone tasks are filtered out of the Active Tasks section in composited memory_search.
After each agent turn (when autoCapture: true), the plugin:
- Extracts the last user + assistant messages
- Appends them as timestamped entries to a daily conversation note (
conversations-YYYY-MM-DD) - Skips very short exchanges (< 10 chars each)
Search the knowledge graph.
bm_search({ query: "API design", limit: 5 })Read a note by title, permalink, or memory:// URL.
bm_read({ identifier: "memory://projects/api-redesign" })
bm_read({ identifier: "memory://projects/api-redesign", include_frontmatter: true }) // raw markdown + YAMLCreate a new note.
bm_write({ title: "Auth Strategy", content: "## Overview\n...", folder: "decisions" })Edit an existing note (append, prepend, find_replace, replace_section).
bm_edit({ identifier: "weekly-review", operation: "append", content: "\n## Update\nDone." })
bm_edit({
identifier: "weekly-review",
operation: "find_replace",
find_text: "status: active",
content: "status: done",
expected_replacements: 1,
})
bm_edit({
identifier: "weekly-review",
operation: "replace_section",
section: "## This Week",
content: "- β
Done\n- π Next",
})Delete a note.
bm_delete({ identifier: "notes/old-draft" })Move a note to a different folder.
bm_move({ identifier: "notes/my-note", newFolder: "archive" })Navigate the knowledge graph β get a note with its observations and relations.
bm_context({ url: "memory://projects/api-redesign", depth: 2 })/remember <text>β Save a quick note/recall <query>β Search the knowledge graph
openclaw basic-memory search "auth patterns" --limit 5
openclaw basic-memory read "projects/api-redesign"
openclaw basic-memory read "projects/api-redesign" --raw
openclaw basic-memory edit "projects/api-redesign" --operation append --content $'\n## Update\nDone.'
openclaw basic-memory context "memory://projects/api-redesign" --depth 2
openclaw basic-memory recent --timeframe 24h
openclaw basic-memory statuswhich bm # Check if installed
bm --version # Check version
bm mcp --help # Verify MCP server command existsIf bm mcp doesn't exist, update Basic Memory to a newer version.
Your installed basic-memory version is missing native tool edit-note.
Upgrade basic-memory and rerun.
rm -rf /tmp/jiti/ "$TMPDIR/jiti/"
openclaw gateway stop && openclaw gateway start- Check that the MCP session is connected (look for
connected to BM MCP stdioin logs) - Verify files exist in the project directory
- Try
bm mcp --transport stdio --project <name>and runsearch_notesthrough an MCP inspector/client - Check project status:
bm project list
This repo includes real end-to-end integration tests for BmClient in:
/Users/phernandez/dev/basicmachines/openclaw-basic-memory/integration/bm-client.integration.test.ts
These tests launch a real bm mcp --transport stdio --project <name> process,
run write/read/edit/search/context/move/delete calls, and assert actual filesystem/index results.
Run integration tests:
bun run test:intBy default this uses ./scripts/bm-local.sh, which runs BM from a sibling
../basic-memory checkout via uv run --project ... when present, and falls
back to bm on PATH otherwise.
Optional overrides:
# Use a non-default bm binary
BM_BIN=/absolute/path/to/bm bun run test:int
# Use a specific basic-memory source checkout
BASIC_MEMORY_REPO=/absolute/path/to/basic-memory bun run test:intbun run check-types # Type checking
bun run lint # Linting
bun test # Run tests (156 tests)
bun run test:int # Real BM MCP integration testsThis package is published as @openclaw/basic-memory.
# 1) Verify release readiness (types + tests + npm pack dry run)
just release-check
# 2) Inspect publish payload
just release-pack
# 3) Authenticate once (if needed)
npm login
# 4) Publish current version from package.json
just release-publishFor a full release (version bump + publish + push tag):
just release patch # or: minor, major, 0.2.0, etc.- CI workflow:
.github/workflows/ci.ymlruns on PRs andmainpushes. - Release workflow:
.github/workflows/release.ymlruns manually (workflow_dispatch) and will:- run release checks
- bump version and create a git tag
- push commit + tag
- publish to npm
- create a GitHub release
Repository secret required:
NPM_TOKEN(npm publish token with package publish permissions)
openclaw-basic-memory/
βββ index.ts # Plugin entry β manages MCP lifecycle, registers tools
βββ config.ts # Configuration parsing
βββ bm-client.ts # Persistent Basic Memory MCP stdio client
βββ tools/ # Agent tools
β βββ search.ts # bm_search
β βββ read.ts # bm_read
β βββ write.ts # bm_write
β βββ edit.ts # bm_edit
β βββ delete.ts # bm_delete
β βββ move.ts # bm_move
β βββ context.ts # bm_context
β βββ memory-provider.ts # Composited memory_search + memory_get
βββ commands/
β βββ slash.ts # /remember, /recall
β βββ cli.ts # openclaw basic-memory CLI
βββ hooks/
βββ capture.ts # Auto-capture conversations
MIT β see LICENSE file.