Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ All tools accept an optional `project` parameter for cross-project operations.

| Command | Description |
|---------|-------------|
| `/bm-setup` | Install or update the Basic Memory CLI |
| `/remember <text>` | Save a quick note |
| `/recall <query>` | Search the knowledge graph |
| `/tasks [args]` | Create, track, resume structured tasks |
Expand Down
32 changes: 32 additions & 0 deletions commands/slash.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
import { execSync } from "node:child_process"
import { dirname, resolve } from "node:path"
import { fileURLToPath } from "node:url"
import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
import type { BmClient } from "../bm-client.ts"
import { log } from "../logger.ts"

const __dirname = dirname(fileURLToPath(import.meta.url))

export function registerCommands(
api: OpenClawPluginApi,
client: BmClient,
): void {
api.registerCommand({
name: "bm-setup",
description: "Install or update the Basic Memory CLI (requires uv)",
requireAuth: true,
handler: async () => {
const scriptPath = resolve(__dirname, "..", "scripts", "setup-bm.sh")
log.info(`/bm-setup: running ${scriptPath}`)

try {
const output = execSync(`bash "${scriptPath}"`, {
encoding: "utf-8",
timeout: 180_000,
stdio: "pipe",
env: { ...process.env },
})
return { text: output.trim() }
} catch (err: unknown) {
const execErr = err as { stderr?: string; stdout?: string }
const detail = execErr.stderr || execErr.stdout || String(err)
log.error("/bm-setup failed", err)
return {
text: `Setup failed:\n${detail.trim()}`,
}
}
},
})

api.registerCommand({
name: "remember",
description: "Save something to the Basic Memory knowledge graph",
Expand Down
25 changes: 25 additions & 0 deletions skills/memory-notes/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,28 @@ edit_note(
6. **Link related concepts.** The value of a knowledge graph compounds with connections. A note with zero relations is an island — useful, but not as powerful as a connected one.

7. **Let the graph grow naturally.** Don't try to design a perfect taxonomy upfront. Write notes as you work, add relations as connections emerge, and periodically use `/reflect` or `/defrag` to consolidate.

## ⚠️ write_note vs edit_note — Avoiding Data Loss

**`write_note` is destructive.** If a note with the same title already exists, `write_note` silently replaces it. This will destroy accumulated content in daily notes, logs, or any file that grows over time.

### Rules

- **New notes**: Use `write_note` — it creates the file and frontmatter correctly.
- **Existing notes**: Use `edit_note` — it modifies without replacing.
- `operation: "append"` — add content to the end
- `operation: "prepend"` — add content to the beginning
- `operation: "find_replace"` — surgical text replacement
- `operation: "replace_section"` — replace a specific heading section

### Common Mistake

```
# ❌ WRONG — destroys existing daily note content
write_note(title="2026-02-26", folder="memory", content="## New Section\n...")

# ✅ RIGHT — appends to existing daily note
edit_note(identifier="2026-02-26", operation="append", content="\n## New Section\n...")
```

**When in doubt, use `edit_note`.** It's always safe. `write_note` is only safe when you're certain the note doesn't exist yet or you intentionally want to replace it entirely.
15 changes: 15 additions & 0 deletions skills/memory-reflect/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,18 @@ Append a brief entry to today's daily note:
- **Flag uncertainty.** If something seems important but you're not sure, add it with a note like "(needs confirmation)" rather than skipping it entirely.
- **Restructure over time.** If MEMORY.md is a chronological dump, restructure it into topical sections during reflection. Curated knowledge > raw logs.
- **Check for filesystem issues.** Look for recursive nesting (memory/memory/memory/...), orphaned files, or bloat while gathering material.

## ⚠️ Safe Writing Pattern

**Never use `write_note` on daily notes or MEMORY.md.** These files accumulate content throughout the day. `write_note` replaces the entire file — use `edit_note` instead:

```
# ✅ Update a section in MEMORY.md
edit_note(identifier="MEMORY", operation="replace_section", section="About Me", content="...")

# ✅ Append reflection log to today's daily note
edit_note(identifier="2026-02-26", operation="append", content="\n## Reflection (22:00)\n...")

# ❌ NEVER do this — destroys the existing file
write_note(title="2026-02-26", folder="memory", content="...")
```