--- name: bm-setup description: Set up the Basic Memory plugin for this project — a short guided interview that configures the project mapping, seeds note schemas, learns or suggests placement conventions, and enables capture reflexes. Use when the user runs /basic-memory:bm-setup, says "set up basic memory", or asks to configure/bootstrap the plugin. argument-hint: (no arguments — runs an interactive interview) --- # Basic Memory setup Run a short, adaptive interview (~2-3 minutes) and then write the configuration. Be conversational and **skip questions whose answer is already obvious** from context (e.g. if `list_memory_projects` shows a single local project and no cloud workspaces, don't ask about cloud/teams — just confirm). Suggest a sensible default for every question so the user can accept with one word. Don't do any writes until the interview is done and you've confirmed the plan. ## Prerequisite check First confirm the **Basic Memory MCP server is connected** — call `list_memory_projects`. If that tool isn't available or errors, Basic Memory isn't wired into Claude Code yet. **Stop and walk the user through it first** (everything below depends on it): 1. Install it: `uv tool install basic-memory --prerelease=allow` (or `pip install basic-memory`), version `>= 0.19.0`. Keep `--prerelease=allow` with uv: published releases pin a FastMCP pre-release, and without the flag uv silently installs an older Basic Memory release. 2. Connect it: `claude mcp add basic-memory -- uvx --prerelease=allow basic-memory mcp`, then restart the session so the MCP server loads. Re-check `list_memory_projects` before continuing — don't start the interview until it succeeds. ## Interview Ask only what you can't infer. Cover: 1. **Focus / how you'll use it.** "What will this project mostly be — code/dev, research, writing, knowledge capture, planning, or a mix?" This answer drives the folder structure you suggest (step 4) and is stored so the SessionStart brief can surface it. If you infer it instead of asking, state the use-case you assumed and the structure it implies so the user can correct it in one word. A code/dev answer makes this a **coding setup** (`sessionProfile: "coding"`): verify the directory is inside a Git repository, resolve a stable `repository` identifier such as `owner/name` from the origin remote or GitHub CLI, show it to the user, and ask for confirmation. Do not guess when the remote is missing or ambiguous, and do not infer `coding` merely because the current directory is a Git checkout — for mixed use, ask whether this repository should capture Git and pull-request context. The coding profile seeds the Coding Session schema so deliberate checkpoints carry required, queryable Git identity (repository, branch, SHA, and working directory), plus typed pull-request fields when a PR exists. 2. **Project mapping.** "Do you already have a Basic Memory project for this, or should I create one?" - Existing → show `list_memory_projects()` and let them pick. That name becomes `primaryProject`. - New → propose a name (default: this repo's directory name) and create it with `create_memory_project`. - *Local project* (default): path defaults to `~/basic-memory//`; any connected Basic Memory server can create it. - *Cloud project* (the user wants capture in a cloud workspace): pass the `workspace` selector (a slug from `list_workspaces`) and a cloud-style path like `/`, and create it with a **cloud-connected** MCP server. A purely local server (`uvx --prerelease=allow basic-memory mcp`) treats the path as a local directory and fails to create it (e.g. read-only `/`). When both a local and a cloud server are connected, route creation *and* the schema seeding through the cloud one, and pin `primaryProject` to the new project's `external_id` UUID (collision-proof across workspaces). 3. **Cloud / teams** (skip if there are no extra workspaces). Run `list_workspaces`. If the user belongs to more than one workspace, they likely have a **team** workspace alongside their personal/default one. Use `list_memory_projects` to see the projects in each (note: project names collide across workspaces, so always use the **workspace-qualified name**, e.g. `my-team-2/notes`, or the `external_id` UUID — never a bare name). - **Read from the team** (recommended): ask which team projects to pull into the session brief for recall. Store their qualified names in `secondaryProjects`. These are **read-only** — recall reads across them; nothing is written to them. **Cap:** the SessionStart brief reads only the first **6** shared projects per session (a latency/output bound), in list order. If the user wants more than six, order the most relevant first and tell them the rest are configured but not read each session. - **Share target** (optional): if the user wants a place to *publish* notes to the team via `/basic-memory:bm-share`, add it to `teamProjects` as `"": { "promoteFolder": "shared" }`. Sharing is always a manual gesture — auto-capture never writes to a team project. Keep `primaryProject` a project the user owns for their *own* capture; team projects are for reading and deliberate sharing only. 4. **Placement — learn or suggest** (depends on the project's state). The goal is a short `placementConventions` string (3-6 lines) telling you where new notes go. How you get it depends on whether the project already has notes: - **Existing project with notes** → *learn*. Inspect it: `list_directory` for the folder layout, sample a few notes per folder (and, where a folder holds recurring typed notes, you may run `schema_infer` to see their shape). Summarize the *real* conventions — folder-by-topic layout, naming style, the observation categories they favor. Infer from their actual notes; don't impose. - **New or empty project** → *suggest* (there's nothing to learn yet). Propose a **light** structure that fits the focus from step 1 — 3-5 optional top-level folders, no deep taxonomy — and be explicit that it's a starting point, not a scaffold: notes work fine without it and structure can stay emergent. Don't create empty folders; folders appear as notes land in them. Let the user edit or decline in one word. Either way, keep it short and store the result as `placementConventions`. The SessionStart brief surfaces it (alongside `captureFolder`), so this is what makes your captures land where the user expects — without it, placement is guesswork. 5. **Schemas.** "I'll add the session schema for this profile, plus decision and task schemas, so I can find them precisely later — okay?" (See "Seed the schemas" below.) 6. **Lifecycle-event capture.** "The plugin keeps a local trail of SessionStart and PreCompact events for diagnostics by default. Keep that on?" Default to **on**. Explain that the normal session brief and PreCompact checkpoint work either way; capture adds bounded lifecycle metadata to a local inbox until `bm hook flush` archives it locally. It never creates knowledge-graph notes. Persist the JSON boolean `false` only when the user opts out. - Capture stays local and personal. It never writes directly to team projects. 7. **How active should I be? (output style)** "Want me to proactively capture — search the graph before recalling, write material decisions as typed notes, and cite permalinks? Or keep it quiet (just the session brief, the PreCompact checkpoint, and `/basic-memory:bm-remember` on demand)?" Enabling it sets `outputStyle: "basic-memory"`. Default to enabled; leave it off for a recall-only, low-noise setup. (This is the single knob for how proactive the assistant is — the hooks always run regardless.) 8. **Shared skills** (optional, default yes). "Want the full Basic Memory toolkit — the shared `memory-*` skills (`memory-notes`, `memory-tasks`, `memory-research`, `memory-schema`, `memory-defrag`, …)? I can install them alongside this plugin." These are the canonical, framework-agnostic skills (the same set OpenClaw bundles). This plugin ships only the Claude-Code-specific glue and pulls the shared set on demand — it doesn't vendor its own copies. (See "Install the shared skills" below.) ## Apply (after confirming the plan) ### 1. Seed the schemas The plugin ships seed schemas at `/schemas/` — that's **two directories up from this skill's directory, then `schemas/`** (this skill is at `/skills/bm-setup/`). Read `coding-session.md` for a coding profile or `session.md` for a general profile, then read `decision.md` and `task.md`. These schemas cover notes the Claude integration writes directly. Lifecycle envelopes are not notes: `bm hook flush` archives that operational trace locally, so there is no projected session or tool-ledger schema to seed. For each one: - Check whether the chosen project already has a schema for that type (`search_notes` with `metadata_filters={"type": "schema"}`, or try `read_note("schemas/")`). **If it exists, skip it** — never overwrite a schema the user may have customized. - Otherwise write it with `write_note`, routed to `primaryProject` (pass it as `project`, or as `project_id` if it's an `external_id` UUID): - `directory="schemas"`, `note_type="schema"`, `title` = the schema's title (Session / Decision / Task). - `content` = the markdown **body only** — everything *after* the `---` frontmatter block (the `# Session` heading and the prose). - `metadata` = the schema's structured frontmatter as a **nested dict**: `entity`, `version`, the full `schema` map, and `settings` (keep its nested `frontmatter`, and pass enum values as JSON arrays, e.g. `["open","resumed","closed"]`). - **Do not** put the schema's `---` frontmatter inside `content`. On the cloud write path that nested YAML is silently coerced to the string `'[object Object]'` (basic-memory-cloud#1000), corrupting `schema`/`settings`. The `metadata` param round-trips correctly on both local and cloud. After seeding, verify one note with `read_note(..., output_format="json", include_frontmatter=true)` — `schema`/`settings` must come back as nested objects, not strings. - **Coding setup:** the selected `coding-session.md` schema's Git identity fields (`repository`, `repo_root`, `cwd`, `branch`, `git_sha`) are required by design. Required-and-proven fields are what make coding checkpoints queryable, so seed the schema unmodified instead of also seeding the general Session schema. ### 2. Install the shared skills (if the user opted in) **First, guard against clobbering a source checkout.** If `./skills` already exists, is tracked in git, and holds `memory-*` directories, you're inside the skills' own source repo (e.g. `basic-memory` itself) — the install would overwrite the working copy with published versions. In that case **skip the install** and tell the user the skills are already present as source; don't run the command. Quick check: ``` git ls-files skills/ | grep -q memory- && echo "source repo - skip install" ``` Otherwise, run from the project root: ``` npx skills add basicmachines-co/basic-memory/skills ``` This installs the canonical `memory-*` skills into the user's skills directory — the single source of truth, shared with OpenClaw. The plugin does **not** vendor copies; it relies on this shared set. If `npx` / the `skills` CLI isn't available, point the user at the manual install in the top-level [`skills/README.md`](../../../../skills/README.md). ### 3. Write settings Build the `basicMemory` block from the interview: ```json { "basicMemory": { "primaryProject": "", "secondaryProjects": [], "captureFolder": "sessions", "rememberFolder": "bm-remember", "recallTimeframe": "3d", "preCompactCapture": "extractive", "sessionProfile": "coding", "repository": "owner/name", "captureEvents": true, "placementConventions": "", "teamProjects": {} }, "outputStyle": "basic-memory" } ``` Persist `sessionProfile` explicitly. Persist `repository` only for the `coding` profile, after the user confirms it — a coding setup is incomplete without a repository identifier because the `coding_session` schema requires queryable Git identity fields. Omit both keys' example values for a `general` setup (`"sessionProfile": "general"`, no `repository`). Only include `outputStyle` if the user opted in. Ask whether this is a **team default** (write/merge into `.claude/settings.json`, suggest committing it) or **personal** (`.claude/settings.local.json`). **Merge** into any existing file — read it, add/replace only the keys above, preserve everything else. Use compact, valid JSON. Always persist `captureEvents` as a JSON boolean. Writing the `basicMemory` block is also what stops the SessionStart hook's first-run nudge — the config's presence is the signal that setup has run. ### 4. Smoke-test the wiring Before you close, prove recall actually resolves — this catches a misnamed project, missing cloud credentials, or a ref that doesn't route, while the user is still here to fix it. Run the same structured query the SessionStart hook runs, via the CLI it uses (`basic-memory` / `bm` / `uvx --prerelease=allow basic-memory`): - **Primary:** `… tool search-notes --type schema --page-size 10` against `primaryProject` — use `--project-id ` for a UUID, `--project ` otherwise. It should return the schemas you just seeded. For a coding setup, confirm the `Coding Session` schema is present. - **One shared project** (only if `secondaryProjects` is non-empty): a `--type decision --status open` query against the first ref. It just needs to return *cleanly* — `0 results` is fine; an **error** means the ref doesn't route. - **Hook health:** run `basic-memory hook status --harness claude --project-dir ` with the first available `basic-memory`, `bm`, or `uvx --prerelease=allow basic-memory` launcher. It must find the intended settings and report the selected project and capture state. Record the shared inbox depth and last-flush state in the setup summary; the counts include envelopes from every supported harness. If a query errors, or the primary returns nothing, surface it and fix the project ref before closing — don't let the next session's brief come up empty. ## Close Confirm what you did in a few lines: the project mapping, the session profile (and confirmed repository for a coding setup), which schemas were seeded vs. already present, whether placement was learned or suggested, the smoke-test result, whether lifecycle-event capture is enabled, the shared hook inbox/flush state, and whether the output style is on. Then handle activation based on the output style: - **Output style enabled** → it's fixed at session start, so the full capture reflexes only take effect next session. Prompt the user to **restart the session** (start a new Claude Code session) to activate them. Be precise so it doesn't read as "nothing works yet": recall is already live this session (the SessionStart hook's prompt ran), and the PreCompact checkpoint works now too — only the proactive-capture reflexes wait for the restart. - **Output style off** → no restart needed; the hooks already run. End with: *"Done — I'll use this from the next message. Run `/basic-memory:bm-status` anytime to see what I'm tracking."*