diff --git a/README.md b/README.md index d493f17..7d49623 100644 --- a/README.md +++ b/README.md @@ -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 ` | Save a quick note | | `/recall ` | Search the knowledge graph | | `/tasks [args]` | Create, track, resume structured tasks | diff --git a/commands/slash.ts b/commands/slash.ts index 9ba21f8..4595fd2 100644 --- a/commands/slash.ts +++ b/commands/slash.ts @@ -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", diff --git a/skills/memory-notes/SKILL.md b/skills/memory-notes/SKILL.md index c5a4a3b..515e82f 100644 --- a/skills/memory-notes/SKILL.md +++ b/skills/memory-notes/SKILL.md @@ -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. diff --git a/skills/memory-reflect/SKILL.md b/skills/memory-reflect/SKILL.md index 0fb352c..b93d0fb 100644 --- a/skills/memory-reflect/SKILL.md +++ b/skills/memory-reflect/SKILL.md @@ -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="...") +```