@basicmemory/openclaw-basic-memory 0.1.0-alpha.8 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,134 +1,66 @@
1
1
  # openclaw-basic-memory
2
2
 
3
- Local-first knowledge graph plugin for OpenClaw — persistent memory with graph search and composited memory search. Everything works locally with no cloud account required.
3
+ Give your OpenClaw agent persistent, searchable memory — in plain text files you can read and edit.
4
4
 
5
- ## What this plugin does
6
-
7
- The `openclaw-basic-memory` plugin integrates [Basic Memory](https://github.com/basicmachines-co/basic-memory) with OpenClaw to provide:
5
+ ## What is Basic Memory?
8
6
 
9
- - **Composited `memory_search`** — queries MEMORY.md, the BM knowledge graph, and active tasks in parallel
10
- - **Persistent MCP stdio session** — keeps a single `bm mcp --transport stdio --project <name>` process alive
11
- - **Auto-recall** — injects active tasks and recent activity as context at session start
12
- - **Auto-capture** — records agent conversations as structured daily notes
13
- - **Graph tools** — search, read, write, edit, delete, move, and navigate notes via `memory://` URLs
14
- - **Skill workflows** — `/tasks`, `/reflect`, `/defrag`, `/schema` slash commands for guided memory management
7
+ [Basic Memory](https://basicmemory.com) stores AI knowledge in local Markdown files and indexes them into a semantic knowledge graph. Your agent writes notes. You can open them in any editor, read them, change them, and the changes sync back automatically. No black box. No proprietary format. Just files.
15
8
 
16
- All data stays on your machine as markdown files indexed locally with SQLite. Cloud sync is available but entirely optional — see [BASIC_MEMORY.md](./BASIC_MEMORY.md) for cloud setup.
9
+ It does three things that work together:
17
10
 
18
- For a practical runbook, see [Memory + Task Flow](./MEMORY_TASK_FLOW.md).
11
+ - **Stores knowledge in plain Markdown** — everything lives in plain text files on your computer, not locked inside a database you can't read
12
+ - **Creates connections automatically** — notes link to each other through a searchable, traversable knowledge graph
13
+ - **Searches by meaning, not just keywords** — vector search finds relevant context even when the exact words don't match
14
+ - **Keeps notes consistent** — dynamic schemas and validation ensure your knowledge base stays structured and useful as it grows
15
+ - **Enables two-way collaboration** — both you and the AI read and write the same files
19
16
 
20
- ## Requirements
17
+ Over time, your agent builds a knowledge base that grows with you. Context that survives across sessions. Memory that belongs to you.
21
18
 
22
- 1. **[uv](https://docs.astral.sh/uv/)** — Python package manager used to install Basic Memory CLI
23
- ```bash
24
- # macOS
25
- brew install uv
19
+ Learn more: [basicmemory.com](https://basicmemory.com) · [GitHub](https://github.com/basicmachines-co/basic-memory) · [Docs](https://docs.basicmemory.com)
26
20
 
27
- # macOS / Linux
28
- curl -LsSf https://astral.sh/uv/install.sh | sh
29
- ```
21
+ ## What this plugin does
30
22
 
31
- 2. **[OpenClaw](https://docs.openclaw.ai)** with plugin support
23
+ This plugin connects Basic Memory to OpenClaw so your agent can:
32
24
 
33
- ## Installation
25
+ - **Remember across sessions** — search and recall past conversations, decisions, and context
26
+ - **Track work in progress** — structured tasks that survive context compaction
27
+ - **Build knowledge over time** — notes, observations, and relations that grow into a connected graph
28
+ - **Search intelligently** — composited search across working memory, the knowledge graph, and active tasks in parallel
34
29
 
35
- ```bash
36
- # Install the plugin (automatically installs the bm CLI via uv)
37
- openclaw plugins install @basicmemory/openclaw-basic-memory
30
+ All data stays on your machine as Markdown files indexed locally with SQLite. Cloud sync is available but entirely optional.
38
31
 
39
- # Enable and assign to the memory slot
40
- openclaw plugins enable openclaw-basic-memory --slot memory
32
+ ## Install
41
33
 
42
- # Restart the gateway
43
- openclaw gateway restart
44
- ```
34
+ **Prerequisite:** [uv](https://docs.astral.sh/uv/) (Python package manager) — used to install the Basic Memory CLI.
45
35
 
46
- Verify:
47
36
  ```bash
48
- openclaw plugins list
49
- openclaw plugins info openclaw-basic-memory
50
- ```
51
-
52
- If `uv` is not installed, the `bm` CLI setup is skipped gracefully during install. Install `uv` first, then re-run the postinstall script:
37
+ # macOS
38
+ brew install uv
53
39
 
54
- ```bash
55
- bash ~/.openclaw/extensions/openclaw-basic-memory/scripts/setup-bm.sh
40
+ # macOS / Linux
41
+ curl -LsSf https://astral.sh/uv/install.sh | sh
56
42
  ```
57
43
 
58
- ### Basic Memory Cloud
59
-
60
- Everything works locally — cloud adds cross-device, team, and production capabilities:
61
-
62
- - **Your agent's memory travels with you** — same knowledge graph on laptop, desktop, and hosted environments
63
- - **Team knowledge sharing** — org workspaces let multiple agents and team members build on a shared knowledge base
64
- - **Durable memory for production agents** — persistent memory that survives CI teardowns and container restarts
65
- - **Multi-agent coordination** — multiple agents can read and write to the same graph
66
-
67
- Cloud extends local-first — still plain markdown, still yours. Start with a [7-day free trial](https://basicmemory.com) and use code `BMCLAW` for 20% off for 3 months. See [BASIC_MEMORY.md](./BASIC_MEMORY.md) for cloud setup.
68
-
69
- ### Development (local directory)
70
-
71
- For plugin development, clone and link locally:
44
+ Then install the plugin:
72
45
 
73
46
  ```bash
74
- git clone https://github.com/basicmachines-co/openclaw-basic-memory.git
75
- cd openclaw-basic-memory
76
- bun install
77
- openclaw plugins install -l "$PWD"
78
- openclaw plugins enable openclaw-basic-memory --slot memory
47
+ openclaw plugins install @basicmemory/openclaw-basic-memory
79
48
  openclaw gateway restart
80
49
  ```
81
50
 
82
- Or load directly from a path in your OpenClaw config:
51
+ That's it. The plugin auto-installs the `bm` CLI on first startup if it's not already on your PATH. See [SECURITY.md](./SECURITY.md) for details on how this works.
83
52
 
84
- ```json5
85
- {
86
- plugins: {
87
- load: {
88
- paths: ["~/dev/openclaw-basic-memory"]
89
- },
90
- entries: {
91
- "openclaw-basic-memory": {
92
- enabled: true
93
- }
94
- },
95
- slots: {
96
- memory: "openclaw-basic-memory"
97
- }
98
- }
99
- }
100
- ```
101
-
102
- ### Bundled Skills
103
-
104
- This plugin ships with six skills that are automatically available when the plugin is enabled — no manual installation needed:
105
-
106
- - **`memory-tasks`** — structured task tracking that survives context compaction
107
- - **`memory-reflect`** — periodic consolidation of recent notes into durable memory
108
- - **`memory-defrag`** — periodic cleanup/reorganization of memory files
109
- - **`memory-schema`** — schema lifecycle management (infer, create, validate, diff, evolve)
110
- - **`memory-metadata-search`** — structured metadata search by custom frontmatter fields (status, priority, etc.)
111
- - **`memory-notes`** — guidance for writing well-structured notes with observations and relations
112
-
113
- Skills are loaded from the plugin's `skills/` directory. See the upstream source at [`basic-memory-skills`](https://github.com/basicmachines-co/basic-memory-skills).
114
-
115
- #### Updating or adding skills with `npx skills`
116
-
117
- You can update bundled skills or install new ones as they become available using the [Skills CLI](https://github.com/vercel-labs/skills):
53
+ Verify:
118
54
 
119
55
  ```bash
120
- # Update all basic-memory skills to latest
121
- npx skills add basicmachines-co/basic-memory-skills --agent openclaw
122
-
123
- # Install a specific skill
124
- npx skills add basicmachines-co/basic-memory-skills --name memory-tasks --agent openclaw
56
+ openclaw plugins list
57
+ openclaw plugins info openclaw-basic-memory
125
58
  ```
126
59
 
127
- This installs to the same `skills/` directory the plugin reads from, so updated skills take effect on the next session.
128
-
129
60
  ## Configuration
130
61
 
131
- ### Minimal (zero-config)
62
+ ### Zero-config (recommended)
63
+
132
64
  ```json5
133
65
  {
134
66
  "openclaw-basic-memory": {
@@ -137,440 +69,180 @@ This installs to the same `skills/` directory the plugin reads from, so updated
137
69
  }
138
70
  ```
139
71
 
140
- This uses sensible defaults: auto-generated project name, maps Basic Memory to your workspace `memory/` directory, and captures conversations.
72
+ This uses sensible defaults: auto-generated project name, maps to your workspace root, captures conversations, and recalls active tasks on session start.
73
+
74
+ ### Full options
141
75
 
142
- ### Full configuration
143
76
  ```json5
144
77
  {
145
78
  "openclaw-basic-memory": {
146
79
  enabled: true,
147
80
  config: {
148
- project: "my-agent", // BM project name (default: "openclaw-{hostname}")
149
- bmPath: "bm", // Path to BM CLI binary
150
- projectPath: "~/.openclaw/workspace/memory/", // Optional override; supports absolute, ~/..., or workspace-relative paths
151
- memoryDir: "memory/", // Relative memory dir for task scanning
152
- memoryFile: "MEMORY.md", // Working memory file for grep search
153
- autoCapture: true, // Index conversations automatically
154
- captureMinChars: 10, // Min chars to trigger auto-capture
155
- autoRecall: true, // Inject active tasks + recent activity at session start
156
- recallPrompt: "Check for active tasks and recent activity. Summarize anything relevant to the current session.",
157
- debug: false, // Verbose logging
81
+ project: "my-agent", // BM project name (default: "openclaw-{hostname}")
82
+ projectPath: ".", // Project directory (default: workspace root)
83
+ memoryDir: "memory/", // Where task notes live
84
+ memoryFile: "MEMORY.md", // Working memory file
85
+ autoCapture: true, // Record conversations as daily notes
86
+ autoRecall: true, // Inject active tasks + recent activity at session start
87
+ debug: false // Verbose logging
158
88
  }
159
89
  }
160
90
  }
161
91
  ```
162
92
 
163
- ### Configuration Options
93
+ | Option | Default | Description |
94
+ |--------|---------|-------------|
95
+ | `project` | `"openclaw-{hostname}"` | Basic Memory project name |
96
+ | `bmPath` | `"bm"` | Path to BM CLI binary |
97
+ | `projectPath` | `"."` | Project data directory |
98
+ | `memoryDir` | `"memory/"` | Relative path for task scanning |
99
+ | `memoryFile` | `"MEMORY.md"` | Working memory file for text search |
100
+ | `autoCapture` | `true` | Auto-index agent conversations |
101
+ | `captureMinChars` | `10` | Min chars to trigger capture |
102
+ | `autoRecall` | `true` | Inject context at session start |
103
+ | `recallPrompt` | *(default)* | Instruction appended to recalled context |
104
+ | `debug` | `false` | Verbose logs |
164
105
 
165
- | Option | Type | Default | Description |
166
- |--------|------|---------|-------------|
167
- | `project` | string | `"openclaw-{hostname}"` | Basic Memory project name |
168
- | `bmPath` | string | `"bm"` | Path to Basic Memory CLI binary |
169
- | `projectPath` | string | `"memory/"` | Directory for BM project data (resolved from workspace unless absolute) |
170
- | `memoryDir` | string | `"memory/"` | Relative path for task scanning |
171
- | `memoryFile` | string | `"MEMORY.md"` | Working memory file (grep-searched) |
172
- | `autoCapture` | boolean | `true` | Auto-index agent conversations |
173
- | `captureMinChars` | number | `10` | Minimum character threshold for auto-capture (both messages must be shorter to skip) |
174
- | `autoRecall` | boolean | `true` | Inject active tasks and recent activity as context at session start |
175
- | `recallPrompt` | string | *(see above)* | Instruction appended to recalled context — customize to change what the agent focuses on |
176
- | `debug` | boolean | `false` | Enable verbose debug logs |
106
+ ## How it works
177
107
 
178
- Snake_case aliases (`memory_dir`, `memory_file`, `auto_recall`, `recall_prompt`, `capture_min_chars`) are also supported.
108
+ ### Memory search
179
109
 
180
- Cloud sync is optional — see [BASIC_MEMORY.md](./BASIC_MEMORY.md) for cloud configuration.
110
+ When your agent calls `memory_search`, three sources are queried in parallel:
181
111
 
182
- On startup, the plugin ensures the configured BM project exists at `projectPath` via MCP `create_memory_project` in idempotent mode.
112
+ 1. **MEMORY.md** — text search with surrounding context
113
+ 2. **Knowledge Graph** — hybrid full-text + vector search across all indexed notes
114
+ 3. **Active Tasks** — scans `memory/tasks/` for in-progress work
183
115
 
184
- ## How It Works
116
+ Results come back in clear sections so the agent knows where each piece of context came from.
185
117
 
186
- ### MCP Session Lifecycle
187
- On startup, the plugin starts one persistent MCP stdio session:
188
- 1. Spawns `bm mcp --transport stdio --project <name>`
189
- 2. Verifies required MCP tool capabilities at connect time
190
- 3. Uses bounded reconnect attempts (`500ms`, `1000ms`, `2000ms`) when the session drops
118
+ ### Auto-recall
191
119
 
192
- Basic Memory MCP lifecycle handles sync and watch behavior for the project.
120
+ On each session start, the plugin loads active tasks and recently modified notes, giving the agent immediate awareness of ongoing work without being asked.
193
121
 
194
- ### Composited `memory_search`
195
- When the agent calls `memory_search`, three sources are queried in parallel:
122
+ ### Auto-capture
196
123
 
197
- 1. **MEMORY.md** — grep/text search with ±1 line context
198
- 2. **BM Knowledge Graph** — hybrid FTS + vector search (top 5 results with scores)
199
- 3. **Active Tasks** — scans `memory/tasks/` for non-done tasks
124
+ After each conversation turn, the plugin records the exchange as a timestamped entry in a daily note. This builds a searchable history of everything your agent has discussed.
200
125
 
201
- Results are formatted into clear sections:
202
- ```
203
- ## MEMORY.md
204
- - matching lines with context...
205
-
206
- ## Knowledge Graph (memory/)
207
- - note-title (0.85)
208
- > preview of content...
209
-
210
- ## Active Tasks
211
- - **Task Name** (status: active, step: 3)
212
- context snippet...
213
- ```
214
-
215
- ### Memory + Task Management Flow
216
-
217
- This plugin works best if you treat memory as three lanes:
218
-
219
- 1. **Working memory (`MEMORY.md`)** — short-horizon context and current focus.
220
- 2. **Knowledge graph (`memory/**/*.md`)** — long-term notes indexed by Basic Memory.
221
- 3. **Task notes (`memory/tasks/*.md`)** — active execution state for in-flight work.
222
-
223
- > **Note:** OpenClaw's default convention treats `MEMORY.md` as [long-term curated memory](https://docs.openclaw.ai/concepts/memory). This plugin flips that role — the BM knowledge graph handles durable storage, so `MEMORY.md` serves as short-horizon working memory. See [MEMORY_TASK_FLOW.md](./MEMORY_TASK_FLOW.md) for details.
224
-
225
- Typical loop:
226
-
227
- 1. Capture or update notes/tasks with `write_note` / `edit_note`.
228
- 2. The persistent BM MCP process syncs markdown updates into the BM project index.
229
- 3. `memory_search` queries:
230
- - `MEMORY.md` text snippets
231
- - BM search results (semantic + FTS)
232
- - active tasks
233
- 4. Drill into one result with `memory_get` or `read_note`.
234
- 5. Advance tasks by updating `current_step`, checkboxes, and context.
235
- 6. Complete tasks by setting `status: done` (done tasks are excluded from active task results).
236
-
237
- ```mermaid
238
- flowchart LR
239
- A["Write/Update notes"] --> B["BM MCP indexes changes"]
240
- B --> C["memory_search(query)"]
241
- C --> D["MEMORY.md"]
242
- C --> E["Knowledge Graph"]
243
- C --> F["Active Tasks"]
244
- D --> G["Composited result"]
245
- E --> G
246
- F --> G
247
- G --> H["memory_get / read_note"]
248
- H --> A
249
- ```
250
-
251
- ### Task Note Shape (Recommended)
252
-
253
- `memory_search` task extraction is strongest when task notes include:
254
-
255
- - file location: `memory/tasks/*.md`
256
- - frontmatter fields: `status:` and `current_step:`
257
- - a `## Context` section for preview snippets
258
-
259
- Example:
260
-
261
- ```markdown
262
- ---
263
- title: auth-middleware-rollout
264
- type: Task
265
- status: active
266
- current_step: 2
267
- ---
268
-
269
- ## Context
270
- Rolling JWT middleware to all API routes. Staging verification is in progress.
271
-
272
- ## Plan
273
- - [x] Implement middleware
274
- - [x] Add refresh-token validation
275
- - [ ] Roll out to staging
276
- - [ ] Verify logs and error rates
277
- ```
126
+ ### Persistent connection
278
127
 
279
- To mark complete, update:
280
-
281
- ```yaml
282
- status: done
283
- ```
128
+ The plugin keeps a long-lived Basic Memory process running over standard I/O. No cold starts per tool call. The connection auto-reconnects if it drops.
284
129
 
285
- Done tasks are filtered out of the `Active Tasks` section in composited `memory_search`.
130
+ ## Agent tools
286
131
 
287
- ### Auto-Recall
288
- On each `agent_start` event (when `autoRecall: true`), the plugin:
289
- 1. Queries the knowledge graph for active tasks (`type: Task`, `status: active`, up to 5)
290
- 2. Fetches notes modified in the last 24 hours
291
- 3. Formats both into structured context and returns it to the agent
132
+ All tools accept an optional `project` parameter for cross-project operations.
292
133
 
293
- This gives the agent immediate awareness of ongoing work and recent changes without the user needing to ask. The `recallPrompt` config field controls the instruction appended to the context — customize it to steer what the agent prioritizes.
134
+ | Tool | Description |
135
+ |------|-------------|
136
+ | `memory_search` | Composited search across all memory sources |
137
+ | `memory_get` | Read a specific note by title or path |
138
+ | `search_notes` | Search the knowledge graph directly |
139
+ | `read_note` | Read a note by title, permalink, or `memory://` URL |
140
+ | `write_note` | Create or update a note |
141
+ | `edit_note` | Append, prepend, find/replace, or replace a section |
142
+ | `delete_note` | Delete a note |
143
+ | `move_note` | Move a note to a different folder |
144
+ | `build_context` | Navigate the knowledge graph — follow relations and connections |
145
+ | `list_memory_projects` | List accessible projects |
146
+ | `list_workspaces` | List workspaces (personal and org) |
147
+ | `schema_validate` | Validate notes against Picoschema definitions |
148
+ | `schema_infer` | Analyze notes and suggest a schema |
149
+ | `schema_diff` | Detect drift between schema and actual usage |
294
150
 
295
- ### Auto-Capture
296
- After each agent turn (when `autoCapture: true`), the plugin:
297
- 1. Extracts the last user + assistant messages
298
- 2. Appends them as timestamped entries to a daily conversation note (`conversations-YYYY-MM-DD`)
299
- 3. Skips very short exchanges (< `captureMinChars` chars each, default 10)
300
-
301
- ## Agent Tools
302
-
303
- All content tools accept an optional `project` parameter to operate on a different project than the default (cross-project operations).
304
-
305
- ### `list_workspaces`
306
- List all workspaces (personal and organization) accessible to this user.
307
- ```
308
- list_workspaces()
309
- ```
310
-
311
- ### `list_memory_projects`
312
- List all projects, optionally filtered by workspace.
313
- ```
314
- list_memory_projects()
315
- list_memory_projects(workspace="my-org")
316
- ```
317
-
318
- ### `search_notes`
319
- Search the knowledge graph.
320
- ```
321
- search_notes(query="API design", limit=5)
322
- search_notes(query="API design", project="other-project") # cross-project
323
- ```
324
-
325
- ### `read_note`
326
- Read a note by title, permalink, or `memory://` URL.
327
- ```
328
- read_note(identifier="memory://projects/api-redesign")
329
- read_note(identifier="memory://projects/api-redesign", include_frontmatter=true) # raw markdown + YAML
330
- read_note(identifier="notes/readme", project="docs") # cross-project
331
- ```
332
-
333
- ### `write_note`
334
- Create a new note.
335
- ```
336
- write_note(title="Auth Strategy", content="## Overview\n...", folder="decisions")
337
- write_note(title="Shared Note", content="...", folder="shared", project="team") # cross-project
338
- ```
339
-
340
- ### `edit_note`
341
- Edit an existing note (`append`, `prepend`, `find_replace`, `replace_section`).
342
- ```
343
- edit_note(identifier="weekly-review", operation="append", content="\n## Update\nDone.")
344
- edit_note(
345
- identifier="weekly-review",
346
- operation="find_replace",
347
- find_text="status: active",
348
- content="status: done",
349
- expected_replacements=1,
350
- )
351
- edit_note(
352
- identifier="weekly-review",
353
- operation="replace_section",
354
- section="## This Week",
355
- content="- Done\n- Next",
356
- )
357
- ```
358
-
359
- ### `delete_note`
360
- Delete a note.
361
- ```
362
- delete_note(identifier="notes/old-draft")
363
- delete_note(identifier="notes/old-draft", project="archive") # cross-project
364
- ```
365
-
366
- ### `move_note`
367
- Move a note to a different folder.
368
- ```
369
- move_note(identifier="notes/my-note", newFolder="archive")
370
- ```
371
-
372
- ### `build_context`
373
- Navigate the knowledge graph — get a note with its observations and relations.
374
- ```
375
- build_context(url="memory://projects/api-redesign", depth=2)
376
- build_context(url="memory://decisions", depth=1, project="team") # cross-project
377
- ```
378
-
379
- ### `schema_validate`
380
- Validate notes against their Picoschema definitions.
381
- ```
382
- schema_validate(noteType="person")
383
- schema_validate(identifier="notes/john-doe")
384
- schema_validate(noteType="person", project="contacts") # cross-project
385
- ```
386
-
387
- ### `schema_infer`
388
- Analyze existing notes and suggest a Picoschema definition.
389
- ```
390
- schema_infer(noteType="meeting")
391
- schema_infer(noteType="person", threshold=0.5)
392
- ```
393
-
394
- ### `schema_diff`
395
- Detect drift between a schema definition and actual note usage.
396
- ```
397
- schema_diff(noteType="person")
398
- ```
399
-
400
- ## Slash Commands
401
-
402
- ### Memory
403
- - **`/remember <text>`** — Save a quick note to the knowledge graph
404
- - **`/recall <query>`** — Search the knowledge graph (top 5 results)
405
-
406
- ### Skill workflows
407
- These inject step-by-step instructions from the bundled skill files. Each accepts optional arguments for context.
151
+ ## Slash commands
408
152
 
409
153
  | Command | Description |
410
154
  |---------|-------------|
411
- | `/tasks [args]` | Task management — create, track, resume structured tasks |
412
- | `/reflect [args]` | Memory reflection — consolidate recent activity into long-term memory |
413
- | `/defrag [args]` | Memory defrag — reorganize, split, prune memory files |
414
- | `/schema [args]` | Schema management — infer, create, validate, evolve Picoschema definitions |
155
+ | `/remember <text>` | Save a quick note |
156
+ | `/recall <query>` | Search the knowledge graph |
157
+ | `/tasks [args]` | Create, track, resume structured tasks |
158
+ | `/reflect [args]` | Consolidate recent notes into long-term memory |
159
+ | `/defrag [args]` | Reorganize and clean up memory files |
160
+ | `/schema [args]` | Manage Picoschema definitions |
415
161
 
416
- Examples:
417
- ```
418
- /tasks create a task for the API migration
419
- /reflect
420
- /defrag clean up completed tasks older than 2 weeks
421
- /schema infer a schema for Meeting notes
422
- ```
423
-
424
- ## CLI Commands
162
+ ## CLI
425
163
 
426
164
  ```bash
427
165
  openclaw basic-memory search "auth patterns" --limit 5
428
166
  openclaw basic-memory read "projects/api-redesign"
429
- openclaw basic-memory read "projects/api-redesign" --raw
430
- openclaw basic-memory edit "projects/api-redesign" --operation append --content $'\n## Update\nDone.'
431
167
  openclaw basic-memory context "memory://projects/api-redesign" --depth 2
432
168
  openclaw basic-memory recent --timeframe 24h
433
169
  openclaw basic-memory status
434
170
  ```
435
171
 
436
- ## Troubleshooting
437
-
438
- ### `bm` command not found
439
- ```bash
440
- which bm # Check if installed
441
- bm --version # Check version
442
- bm mcp --help # Verify MCP server command exists
443
- ```
444
- If `bm mcp` doesn't exist, update Basic Memory to a newer version.
445
-
446
- ### `edit_note` says `edit-note` is required
447
- Your installed `basic-memory` version is missing native `tool edit-note`.
448
- Upgrade `basic-memory` and rerun.
449
-
450
- ### Jiti cache issues
451
- ```bash
452
- rm -rf /tmp/jiti/ "$TMPDIR/jiti/"
453
- openclaw gateway stop && openclaw gateway start
454
- ```
455
-
456
- ### Search returns no results
457
- 1. Check that the MCP session is connected (look for `connected to BM MCP stdio` in logs)
458
- 2. Verify files exist in the project directory
459
- 3. Try `bm mcp --transport stdio --project <name>` and run `search_notes` through an MCP inspector/client
460
- 4. Check project status: `bm project list`
461
-
462
- ## Integration Tests
463
-
464
- This repo includes real end-to-end integration tests for `BmClient` in:
172
+ ## Bundled skills
465
173
 
466
- - `integration/bm-client.integration.test.ts`
174
+ Six skills ship with the plugin — no installation needed:
467
175
 
468
- These tests launch a real `bm mcp --transport stdio --project <name>` process,
469
- run write/read/edit/search/context/move/delete calls, and assert actual filesystem/index results.
176
+ - **memory-tasks** — structured task tracking that survives context compaction
177
+ - **memory-reflect** — periodic consolidation of recent notes into durable memory
178
+ - **memory-defrag** — cleanup and reorganization of memory files
179
+ - **memory-schema** — schema lifecycle (infer, create, validate, diff)
180
+ - **memory-metadata-search** — query notes by frontmatter fields
181
+ - **memory-notes** — guidance for writing well-structured notes
470
182
 
471
- Run integration tests:
183
+ ### Updating skills
472
184
 
473
185
  ```bash
474
- bun run test:int
186
+ npx skills add basicmachines-co/basic-memory-skills --agent openclaw
475
187
  ```
476
188
 
477
- By default this uses `./scripts/bm-local.sh`, which runs BM from a sibling
478
- `../basic-memory` checkout via `uv run --project ...` when present, and falls
479
- back to `bm` on `PATH` otherwise.
189
+ ## Task notes
480
190
 
481
- Optional overrides:
191
+ The plugin works well with structured task notes in `memory/tasks/`:
482
192
 
483
- ```bash
484
- # Use a non-default bm binary
485
- BM_BIN=/absolute/path/to/bm bun run test:int
486
-
487
- # Use a specific basic-memory source checkout
488
- BASIC_MEMORY_REPO=/absolute/path/to/basic-memory bun run test:int
489
- ```
193
+ ```markdown
194
+ ---
195
+ title: auth-middleware-rollout
196
+ type: Task
197
+ status: active
198
+ current_step: 2
199
+ ---
490
200
 
491
- ## Development
201
+ ## Context
202
+ Rolling JWT middleware to all API routes.
492
203
 
493
- ```bash
494
- bun run check-types # Type checking
495
- bun run lint # Linting
496
- bun test # Run tests (156 tests)
497
- bun run test:int # Real BM MCP integration tests
204
+ ## Plan
205
+ - [x] Implement middleware
206
+ - [x] Add refresh-token validation
207
+ - [ ] Roll out to staging
208
+ - [ ] Verify logs and error rates
498
209
  ```
499
210
 
500
- ## Publish to npm
211
+ Set `status: done` to mark complete. Done tasks are filtered out of active task results.
501
212
 
502
- This package is published as `@basicmemory/openclaw-basic-memory`.
213
+ ## Basic Memory Cloud
503
214
 
504
- ```bash
505
- # 1) Verify release readiness (types + tests + npm pack dry run)
506
- just release-check
215
+ Everything works locally. Cloud adds cross-device sync, team workspaces, and persistent memory for hosted agents.
507
216
 
508
- # 2) Inspect publish payload
509
- just release-pack
217
+ - Same knowledge graph on laptop, desktop, and CI
218
+ - Shared workspaces for teams
219
+ - Durable memory for production agents
510
220
 
511
- # 3) Authenticate once (if needed)
512
- npm login
513
-
514
- # 4) Publish current version from package.json
515
- just release-publish
516
- ```
221
+ Cloud extends local-first — still plain Markdown, still yours. [Start a free trial](https://basicmemory.com) and use code `BMCLAW` for 20% off for 3 months. See [BASIC_MEMORY.md](./BASIC_MEMORY.md) for setup.
517
222
 
518
- For a full release (version bump + publish + push tag):
223
+ ## Troubleshooting
519
224
 
520
- ```bash
521
- just release patch # or: minor, major, 0.2.0, etc.
522
- ```
225
+ **`bm` not found** — Install uv, then restart the gateway. Or install manually: `uv tool install basic-memory`
523
226
 
524
- ### GitHub Actions CI/CD
227
+ **Search returns nothing** — Check that Basic Memory connected (look for `connected to BM` in logs). Verify files exist in the project directory.
525
228
 
526
- - CI workflow: `.github/workflows/ci.yml` runs on PRs and `main` pushes.
527
- - Release workflow: `.github/workflows/release.yml` runs manually (`workflow_dispatch`) and will:
528
- 1. run release checks
529
- 2. bump version and create a git tag
530
- 3. push commit + tag
531
- 4. publish to npm
532
- 5. create a GitHub release
229
+ **Jiti cache issues** — `rm -rf /tmp/jiti/ "$TMPDIR/jiti/"` then restart the gateway.
533
230
 
534
- Repository secret required:
231
+ **Disable semantic search** — Set `BASIC_MEMORY_SEMANTIC_SEARCH_ENABLED=false` to fall back to full-text only.
535
232
 
536
- - `NPM_TOKEN` (npm publish token with package publish permissions)
233
+ ## More
537
234
 
538
- ### Project Structure
539
- ```
540
- openclaw-basic-memory/
541
- ├── index.ts # Plugin entry — manages MCP lifecycle, registers tools
542
- ├── config.ts # Configuration parsing
543
- ├── bm-client.ts # Persistent Basic Memory MCP stdio client
544
- ├── tools/ # Agent tools
545
- │ ├── search-notes.ts # search_notes
546
- │ ├── read-note.ts # read_note
547
- │ ├── write-note.ts # write_note
548
- │ ├── edit-note.ts # edit_note
549
- │ ├── delete-note.ts # delete_note
550
- │ ├── move-note.ts # move_note
551
- │ ├── build-context.ts # build_context
552
- │ ├── list-memory-projects.ts # list_memory_projects
553
- │ ├── list-workspaces.ts # list_workspaces
554
- │ ├── schema-validate.ts # schema_validate
555
- │ ├── schema-infer.ts # schema_infer
556
- │ ├── schema-diff.ts # schema_diff
557
- │ └── memory-provider.ts # Composited memory_search + memory_get
558
- ├── commands/
559
- │ ├── slash.ts # /remember, /recall
560
- │ ├── skills.ts # /tasks, /reflect, /defrag, /schema
561
- │ └── cli.ts # openclaw basic-memory CLI
562
- └── hooks/
563
- ├── capture.ts # Auto-capture conversations
564
- └── recall.ts # Auto-recall (active tasks + recent activity)
565
- ```
235
+ - [Memory + Task Flow](./MEMORY_TASK_FLOW.md) — practical runbook
236
+ - [Cloud Setup](./BASIC_MEMORY.md) — configure Basic Memory Cloud
237
+ - [Security](./SECURITY.md) — how auto-installation and data handling work
238
+ - [Development](./DEVELOPMENT.md) — contributing, tests, publishing
239
+ - [Basic Memory docs](https://docs.basicmemory.com)
240
+ - [Issues](https://github.com/basicmachines-co/openclaw-basic-memory/issues)
566
241
 
567
- ## License
242
+ ## Telemetry
568
243
 
569
- MIT — see LICENSE file.
244
+ This plugin does not collect telemetry. The Basic Memory CLI may send anonymous usage analytics — see the [Basic Memory docs](https://github.com/basicmachines-co/basic-memory) for opt-out instructions.
570
245
 
571
- ## Links
246
+ ## License
572
247
 
573
- - [Basic Memory](https://github.com/basicmachines-co/basic-memory)
574
- - [Basic Memory Skills](https://github.com/basicmachines-co/basic-memory-skills)
575
- - [OpenClaw](https://docs.openclaw.ai)
576
- - [Issues](https://github.com/basicmachines-co/openclaw-basic-memory/issues)
248
+ MIT
package/bm-client.ts CHANGED
@@ -196,7 +196,7 @@ function isRecoverableConnectionError(err: unknown): boolean {
196
196
  )
197
197
  }
198
198
 
199
- function isNoteNotFoundError(err: unknown): boolean {
199
+ function _isNoteNotFoundError(err: unknown): boolean {
200
200
  const msg = getErrorMessage(err).toLowerCase()
201
201
  return (
202
202
  msg.includes("entity not found") ||
@@ -659,11 +659,12 @@ export class BmClient {
659
659
  identifier,
660
660
  operation,
661
661
  content,
662
- find_text: options.find_text,
663
- section: options.section,
664
- expected_replacements: options.expected_replacements,
665
662
  output_format: "json",
666
663
  }
664
+ if (options.find_text) args.find_text = options.find_text
665
+ if (options.section) args.section = options.section
666
+ if (options.expected_replacements != null)
667
+ args.expected_replacements = options.expected_replacements
667
668
  if (project) args.project = project
668
669
 
669
670
  const payload = await this.callTool("edit_note", args)
@@ -829,10 +830,6 @@ export class BmClient {
829
830
  return payload as unknown as MetadataSearchResult
830
831
  }
831
832
 
832
- private isNoteNotFoundError(err: unknown): boolean {
833
- return isNoteNotFoundError(err)
834
- }
835
-
836
833
  async indexConversation(
837
834
  userMessage: string,
838
835
  assistantResponse: string,
@@ -854,22 +851,33 @@ export class BmClient {
854
851
  "---",
855
852
  ].join("\n")
856
853
 
854
+ // Try append first — if it fails for ANY reason, fall through to create
857
855
  try {
858
856
  await this.editNote(title, "append", entry)
859
857
  log.debug(`appended conversation to: ${title}`)
858
+ return
860
859
  } catch (err) {
861
- if (!this.isNoteNotFoundError(err)) {
862
- log.error("conversation append failed", err)
863
- return
864
- }
860
+ log.debug(`append failed, will create: ${getErrorMessage(err)}`)
861
+ }
865
862
 
866
- const content = [`# Conversations ${dateStr}`, "", entry].join("\n")
867
- try {
868
- await this.writeNote(title, content, "conversations")
869
- log.debug(`created conversation note: ${title}`)
870
- } catch (createErr) {
871
- log.error("conversation index failed", createErr)
872
- }
863
+ // Create the note with frontmatter and first entry
864
+ const content = [
865
+ "---",
866
+ `title: Conversations ${dateStr}`,
867
+ "type: Conversation",
868
+ `date: "${dateStr}"`,
869
+ "---",
870
+ "",
871
+ `# Conversations ${dateStr}`,
872
+ "",
873
+ entry,
874
+ ].join("\n")
875
+
876
+ try {
877
+ await this.writeNote(title, content, "conversations")
878
+ log.debug(`created conversation note: ${title}`)
879
+ } catch (err) {
880
+ log.error("conversation index failed", err)
873
881
  }
874
882
  }
875
883
 
package/config.ts CHANGED
@@ -6,11 +6,6 @@ export type CloudConfig = {
6
6
  api_key: string
7
7
  }
8
8
 
9
- export type DashboardConfig = {
10
- enabled: boolean
11
- port: number
12
- }
13
-
14
9
  export type BasicMemoryConfig = {
15
10
  project: string
16
11
  bmPath: string
@@ -23,7 +18,6 @@ export type BasicMemoryConfig = {
23
18
  recallPrompt: string
24
19
  debug: boolean
25
20
  cloud?: CloudConfig
26
- dashboard: DashboardConfig
27
21
  }
28
22
 
29
23
  const ALLOWED_KEYS = [
@@ -43,7 +37,6 @@ const ALLOWED_KEYS = [
43
37
  "recall_prompt",
44
38
  "debug",
45
39
  "cloud",
46
- "dashboard",
47
40
  ]
48
41
 
49
42
  function assertAllowedKeys(
@@ -113,22 +106,6 @@ export function parseConfig(raw: unknown): BasicMemoryConfig {
113
106
  }
114
107
  }
115
108
 
116
- let dashboard: DashboardConfig = { enabled: false, port: 3838 }
117
- if (
118
- cfg.dashboard &&
119
- typeof cfg.dashboard === "object" &&
120
- !Array.isArray(cfg.dashboard)
121
- ) {
122
- const d = cfg.dashboard as Record<string, unknown>
123
- dashboard = {
124
- enabled: typeof d.enabled === "boolean" ? d.enabled : false,
125
- port:
126
- typeof d.port === "number" && d.port > 0 && d.port < 65536
127
- ? d.port
128
- : 3838,
129
- }
130
- }
131
-
132
109
  return {
133
110
  project:
134
111
  typeof cfg.project === "string" && cfg.project.length > 0
@@ -137,7 +114,7 @@ export function parseConfig(raw: unknown): BasicMemoryConfig {
137
114
  projectPath:
138
115
  typeof cfg.projectPath === "string" && cfg.projectPath.length > 0
139
116
  ? cfg.projectPath
140
- : memoryDir,
117
+ : ".",
141
118
  bmPath:
142
119
  typeof cfg.bmPath === "string" && cfg.bmPath.length > 0
143
120
  ? cfg.bmPath
@@ -167,7 +144,6 @@ export function parseConfig(raw: unknown): BasicMemoryConfig {
167
144
  : "Check for active tasks and recent activity. Summarize anything relevant to the current session.",
168
145
  debug: typeof cfg.debug === "boolean" ? cfg.debug : false,
169
146
  cloud,
170
- dashboard,
171
147
  }
172
148
  }
173
149
 
package/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { Server } from "node:http"
1
+ import { execSync } from "node:child_process"
2
+
2
3
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
3
4
  import { BmClient } from "./bm-client.ts"
4
5
  import { registerCli } from "./commands/cli.ts"
@@ -9,10 +10,11 @@ import {
9
10
  parseConfig,
10
11
  resolveProjectPath,
11
12
  } from "./config.ts"
12
- import { createDashboardServer } from "./dashboard/server.ts"
13
+
13
14
  import { buildCaptureHandler } from "./hooks/capture.ts"
14
15
  import { buildRecallHandler } from "./hooks/recall.ts"
15
16
  import { initLogger, log } from "./logger.ts"
17
+ import { CONVERSATION_SCHEMA_CONTENT } from "./schema/conversation-schema.ts"
16
18
  import { TASK_SCHEMA_CONTENT } from "./schema/task-schema.ts"
17
19
  import { registerContextTool } from "./tools/build-context.ts"
18
20
  import { registerDeleteTool } from "./tools/delete-note.ts"
@@ -82,13 +84,47 @@ export default {
82
84
  registerCli(api, client, cfg)
83
85
 
84
86
  // --- Service lifecycle ---
85
- let dashboardServer: Server | undefined
86
-
87
87
  api.registerService({
88
88
  id: "openclaw-basic-memory",
89
89
  start: async (ctx: { config?: unknown; workspaceDir?: string }) => {
90
90
  log.info("starting...")
91
91
 
92
+ // Auto-install bm CLI if not found
93
+ const bmBin = cfg.bmPath || "bm"
94
+ try {
95
+ execSync(`command -v ${bmBin}`, { stdio: "ignore" })
96
+ } catch {
97
+ log.info("bm CLI not found on PATH — attempting auto-install...")
98
+ try {
99
+ execSync("command -v uv", { stdio: "ignore" })
100
+ log.info(
101
+ "installing basic-memory via uv (this may take a minute)...",
102
+ )
103
+ const result = execSync(
104
+ 'uv tool install "basic-memory @ git+https://github.com/basicmachines-co/basic-memory.git@main" --force',
105
+ { encoding: "utf-8", timeout: 120_000, stdio: "pipe" },
106
+ )
107
+ log.info(
108
+ `basic-memory installed: ${result.trim().split("\n").pop()}`,
109
+ )
110
+ // Verify it worked
111
+ try {
112
+ execSync(`command -v ${bmBin}`, { stdio: "ignore" })
113
+ log.info("bm CLI now available on PATH")
114
+ } catch {
115
+ log.error(
116
+ "bm installed but not found on PATH. You may need to add uv's bin directory to your PATH (typically ~/.local/bin).",
117
+ )
118
+ }
119
+ } catch (_uvErr) {
120
+ log.error(
121
+ "Cannot auto-install basic-memory: uv not found. " +
122
+ "Install uv first (brew install uv, or curl -LsSf https://astral.sh/uv/install.sh | sh), " +
123
+ "then restart the gateway.",
124
+ )
125
+ }
126
+ }
127
+
92
128
  const workspace = ctx.workspaceDir ?? process.cwd()
93
129
  const projectPath = resolveProjectPath(cfg.projectPath, workspace)
94
130
  cfg.projectPath = projectPath
@@ -97,45 +133,30 @@ export default {
97
133
  await client.ensureProject(projectPath)
98
134
  log.debug(`project "${cfg.project}" at ${projectPath}`)
99
135
 
100
- // Seed Task schema if not already present
101
- try {
102
- await client.readNote("schema/Task")
103
- log.debug("Task schema already exists, skipping seed")
104
- } catch {
136
+ // Seed schemas if not already present
137
+ for (const [name, content] of [
138
+ ["Task", TASK_SCHEMA_CONTENT],
139
+ ["Conversation", CONVERSATION_SCHEMA_CONTENT],
140
+ ] as const) {
105
141
  try {
106
- await client.writeNote("Task", TASK_SCHEMA_CONTENT, "schema")
107
- log.debug("seeded Task schema note")
108
- } catch (err) {
109
- log.debug("Task schema seed failed (non-fatal)", err)
142
+ await client.readNote(`schema/${name}`)
143
+ log.debug(`${name} schema already exists, skipping seed`)
144
+ } catch {
145
+ try {
146
+ await client.writeNote(name, content, "schema")
147
+ log.debug(`seeded ${name} schema note`)
148
+ } catch (err) {
149
+ log.debug(`${name} schema seed failed (non-fatal)`, err)
150
+ }
110
151
  }
111
152
  }
112
153
 
113
154
  setWorkspaceDir(workspace)
114
155
 
115
- // Start dashboard if enabled
116
- if (cfg.dashboard.enabled) {
117
- dashboardServer = createDashboardServer({
118
- port: cfg.dashboard.port,
119
- client,
120
- })
121
- dashboardServer.listen(cfg.dashboard.port, () => {
122
- log.info(
123
- `dashboard running at http://localhost:${cfg.dashboard.port}`,
124
- )
125
- })
126
- }
127
-
128
156
  log.info("connected — BM MCP stdio session running")
129
157
  },
130
158
  stop: async () => {
131
159
  log.info("stopping BM MCP session...")
132
- if (dashboardServer) {
133
- await new Promise<void>((resolve) =>
134
- dashboardServer?.close(() => resolve()),
135
- )
136
- dashboardServer = undefined
137
- log.info("dashboard stopped")
138
- }
139
160
  await client.stop()
140
161
  log.info("stopped")
141
162
  },
@@ -48,19 +48,14 @@
48
48
  },
49
49
  "projectPath": {
50
50
  "label": "Project Path",
51
- "placeholder": "~/.openclaw/workspace/memory/",
52
- "help": "Filesystem path for Basic Memory project data (relative paths resolve from workspace); created automatically if missing",
51
+ "placeholder": ".",
52
+ "help": "Filesystem path for Basic Memory project data (defaults to workspace root; relative paths resolve from workspace)",
53
53
  "advanced": true
54
54
  },
55
55
  "cloud": {
56
56
  "label": "Cloud Backend",
57
57
  "help": "Optional cloud backend config (url + api_key). If present, uses cloud instead of local BM.",
58
58
  "advanced": true
59
- },
60
- "dashboard": {
61
- "label": "Dashboard",
62
- "help": "Web dashboard for visualizing the knowledge graph (enabled, port)",
63
- "advanced": true
64
59
  }
65
60
  },
66
61
  "configSchema": {
@@ -81,13 +76,6 @@
81
76
  "url": { "type": "string" },
82
77
  "api_key": { "type": "string" }
83
78
  }
84
- },
85
- "dashboard": {
86
- "type": "object",
87
- "properties": {
88
- "enabled": { "type": "boolean" },
89
- "port": { "type": "number", "minimum": 1, "maximum": 65535 }
90
- }
91
79
  }
92
80
  },
93
81
  "required": []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basicmemory/openclaw-basic-memory",
3
- "version": "0.1.0-alpha.8",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Basic Memory plugin for OpenClaw — local-first knowledge graph for agent memory",
6
6
  "license": "MIT",
@@ -33,6 +33,7 @@
33
33
  "tools/write-note.ts",
34
34
  "types/openclaw.d.ts",
35
35
  "schema/task-schema.ts",
36
+ "schema/conversation-schema.ts",
36
37
  "skills/",
37
38
  "scripts/setup-bm.sh",
38
39
  "openclaw.plugin.json",
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Canonical Conversation schema note content, seeded into new projects on first startup.
3
+ * If the schema already exists (user may have customized it), seeding is skipped.
4
+ */
5
+ export const CONVERSATION_SCHEMA_CONTENT = `---
6
+ title: Conversation
7
+ type: schema
8
+ entity: Conversation
9
+ version: 1
10
+ schema:
11
+ date: "string, ISO date YYYY-MM-DD"
12
+ session_id?: "string, unique session identifier"
13
+ channel?: "string, where the conversation happened (webchat, telegram, discord, etc)"
14
+ participants?: "array, who was in the conversation"
15
+ topic?: "string, brief description of main topic"
16
+ summary?: "string, one-paragraph summary of key points"
17
+ key_decisions?: "array, decisions made during conversation"
18
+ action_items?: "array, things to do as a result"
19
+ settings:
20
+ validation: warn
21
+ ---
22
+
23
+ # Conversation
24
+
25
+ A record of a conversation session between the agent and user(s).
26
+
27
+ ## Observations
28
+ - [convention] Conversation files live in memory/conversations/ with format conversations-YYYY-MM-DD.md
29
+ - [convention] Messages are appended as the conversation progresses
30
+ - [convention] Summary and key_decisions populated at session end or by memory-reflect
31
+ - [convention] Skip routine greetings, heartbeat acks, and tool call details
32
+ - [convention] Focus on decisions, actions taken, and key context needed for continuity
33
+ `
@@ -15,11 +15,10 @@ if ! command -v uv >/dev/null 2>&1; then
15
15
  exit 0
16
16
  fi
17
17
 
18
- # ── install basic-memory[semantic] ────────────────────────────────
18
+ # ── install basic-memory ────────────────────────────────
19
19
  echo "Installing basic-memory from ${BM_REPO}@${BM_REF} ..."
20
20
  uv tool install \
21
- "basic-memory[semantic] @ git+${BM_REPO}@${BM_REF}" \
22
- --with 'onnxruntime<1.24; platform_system == "Darwin" and platform_machine == "x86_64"' \
21
+ "basic-memory @ git+${BM_REPO}@${BM_REF}" \
23
22
  --force
24
23
 
25
24
  # ── verify ────────────────────────────────────────────────────────