From 877e52fd73d1ea20d51ae791f4c3103c779c84a0 Mon Sep 17 00:00:00 2001 From: phernandez Date: Thu, 28 May 2026 22:55:31 -0500 Subject: [PATCH] feat(skills): port useful retired plugin skills into the shared memory-* set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following the evaluation on #866, the genuinely-useful behavior from the deleted Claude Code plugin skills is preserved as framework-agnostic shared skills (usable by any MCP agent — Claude Desktop, OpenClaw, etc.), instead of being lost in the v0.4 clean-break. The Claude Code plugin itself is unchanged — it deliberately relies on hooks + the output style for capture/recall and pulls these shared skills via /basic-memory:setup. New shared skills (ported from the deleted set, CC-specific glue stripped): - memory-curate (from knowledge-organize) — the real coverage gap: knowledge-GRAPH curation (orphan notes, relation suggestion, duplicate merge, tag/folder audit, hub notes, sparse-note enrichment). Distinct from memory-defrag, which is agent-memory-FILE hygiene. - memory-continue (from continue-conversation) — resume prior work by rebuilding context from the graph (build_context / recent_activity / search), timeframe table, resume playbooks. - memory-capture (from knowledge-capture) — synthesize a thread's current state into one note, rewriting in place via a thread_id key. The Claude-Code-specific session UUID is generalized to "any stable thread id your host exposes." Also completed memory-notes' edit reference (added prepend / replace_section to the two existing operations). Updated skills/README.md and skills/CLAUDE.md. `just package-check-skills` validates 13 skills. NOTE: skills/skills-lock.json is a generated artifact of the `npx skills` CLI (not used by Claude Code or OpenClaw) and should be regenerated once the set is final — not hand-edited here. Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: phernandez --- skills/CLAUDE.md | 3 + skills/README.md | 3 + skills/memory-capture/SKILL.md | 275 ++++++++++++++++++++++++++++++++ skills/memory-continue/SKILL.md | 148 +++++++++++++++++ skills/memory-curate/SKILL.md | 243 ++++++++++++++++++++++++++++ skills/memory-notes/SKILL.md | 30 +++- 6 files changed, 695 insertions(+), 7 deletions(-) create mode 100644 skills/memory-capture/SKILL.md create mode 100644 skills/memory-continue/SKILL.md create mode 100644 skills/memory-curate/SKILL.md diff --git a/skills/CLAUDE.md b/skills/CLAUDE.md index f034b7a4..e57f54f1 100644 --- a/skills/CLAUDE.md +++ b/skills/CLAUDE.md @@ -23,6 +23,9 @@ memory-lifecycle/SKILL.md # Entity status transitions and folder-based arc memory-ingest/SKILL.md # Process external input into structured entities memory-research/SKILL.md # Web research synthesized into Basic Memory entities memory-literary-analysis/SKILL.md # Literary analysis knowledge graph pipeline +memory-curate/SKILL.md # Knowledge-graph curation: orphans, relations, tags, hub notes +memory-continue/SKILL.md # Resume prior work by rebuilding context from the graph +memory-capture/SKILL.md # Capture a thread's current state into one coherent note ``` There is no code to compile — this is a pure markdown project. Run `just check` diff --git a/skills/README.md b/skills/README.md index d8d4e549..a43ca858 100644 --- a/skills/README.md +++ b/skills/README.md @@ -17,13 +17,16 @@ Basic Memory provides the MCP server — tools like `write_note`, `search_notes` | **memory-tasks** | Structured task tracking that survives context compaction. Creates typed `Task` notes with steps, status, and context. | Multi-step work (3+ steps), anything that might outlast a context window, or after compaction to resume. | | **memory-schema** | Schema lifecycle management — discover unschemaed notes, infer schemas, create/edit definitions, validate, and detect drift. | When structured note types emerge (Task, Person, Meeting, etc.) and you want consistency. | | **memory-reflect** | Sleep-time memory reflection. Reviews recent conversations and daily notes, extracts insights, consolidates into long-term memory. Inspired by [sleep-time compute](https://www.letta.com/blog/sleep-time-compute). | Schedule via cron (1-2x daily), trigger from heartbeat, or run on demand. | +| **memory-capture** | Capture the current state of a working thread into a single coherent note — synthesize where it landed, not an append-log. Re-captures rewrite the same note in place via a `thread_id` key. | Mid-thread or end-of-thread, when decisions, insights, or context are worth preserving. | | **memory-notes** | How to write well-structured notes — frontmatter, observations with semantic categories, relations with wiki-links, and best practices. | When creating or improving notes, or when you need a reference for the note format. | | **memory-metadata-search** | Structured metadata search — query notes by custom frontmatter fields using equality, range, array, and nested filters. | When finding notes by status, priority, confidence, or any custom YAML field. | | **memory-defrag** | Memory defragmentation — split bloated files, merge duplicates, remove stale information, restructure the hierarchy. | Run weekly/biweekly via cron, or on demand when memory feels messy. | +| **memory-curate** | Knowledge-graph curation — find orphan notes and suggest links, propose typed relations, merge duplicates, audit tags and folders, build hub notes. | When organizing, connecting, or improving a knowledge base as notes accumulate. | | **memory-lifecycle** | Entity lifecycle management — status transitions through folder-based organization, archiving completed work. Core principle: archive, never delete. | When marking items complete, archiving old entities, or managing folder-based status workflows. | | **memory-ingest** | Process unstructured external input into structured entities. Parses meeting transcripts, conversation logs, and pasted documents. | When pasting a transcript, conversation log, or external document that should become structured knowledge. | | **memory-research** | Web research synthesized into Basic Memory entities. Researches a subject, checks for existing knowledge, presents findings, and creates entity notes. | When asked to research a company, person, technology, or topic. | | **memory-literary-analysis** | Analyze a complete literary work into a structured knowledge graph — characters, themes, chapters, locations, symbols, and literary devices. | Full-text literary analysis, book club companions, teaching resources, or research projects. | +| **memory-continue** | Resume prior work by rebuilding context from the knowledge graph — `build_context` via `memory://` URLs, recent activity, and search, then read the key notes. | Starting a session, or when the user says "continue with...", "back to...", or "where were we?" | ## Basic Memory Cloud diff --git a/skills/memory-capture/SKILL.md b/skills/memory-capture/SKILL.md new file mode 100644 index 00000000..8912aea8 --- /dev/null +++ b/skills/memory-capture/SKILL.md @@ -0,0 +1,275 @@ +--- +name: memory-capture +description: "Capture the current state of a working thread or conversation into a single coherent Basic Memory note — synthesize where it landed, don't append a log. On re-capture, rewrite the same note in place instead of duplicating. Use mid-thread or end-of-thread when decisions, insights, or context are worth preserving." +--- + +# Memory Capture + +Capture the gist of a working thread — the decisions made, insights surfaced, and context built — into a single coherent Basic Memory note that reflects where the thread has landed. + +## Purpose + +A thread has a beginning, middle, and end. Things change as the conversation progresses: an early decision gets revised, a problem looks different in light of new information, a trade-off is settled differently than it first seemed. When this skill is invoked, capture the **current state of understanding**, not the history of how it got there. + +If the skill is invoked more than once in the same thread, the **same note is rewritten** so it stays coherent — not appended to. The result should read top-to-bottom as a single document about the thread's outcome, with brief prose where a meaningful change is worth acknowledging. + +## When to Use + +Typical timing is **mid-thread or end-of-thread**, after enough has been settled to be worth preserving. + +Use this skill when: +- Key decisions have been made and shouldn't evaporate when the thread closes +- A design, debugging, or planning discussion has produced something concrete +- The user explicitly asks to capture, save, or remember what's been discussed +- Toward the end of a session, to summarize the outcome + +It is fine — and expected — to invoke this skill multiple times in the same thread as the conversation evolves. + +## Same-Thread Detection + +To rewrite the same note on re-capture instead of duplicating, key the note to a stable `thread_id` in its frontmatter. + +**If your agent exposes a stable session or thread id**, store it as `thread_id` so subsequent captures within the same thread find and rewrite the same note. Any value that stays constant for the duration of the thread works — a session UUID, a conversation id, a ticket number the work is scoped to. + +> **Example (hosts with a JSONL transcript):** some agents write a per-session transcript whose filename is a stable session UUID. If yours does, you can derive the id from the most-recently-modified transcript file and use it as `thread_id`. This is optional — only do it if your host actually exposes such a transcript. + +**If no stable id is available**, match the existing note by title/topic instead: search for a note covering the same thread (`search_notes(query="")`), and if you find the one this thread already produced, rewrite it. Omit `thread_id` and rely on a consistent title. + +## Decision Flow + +1. **Determine the thread key.** Use a stable session/thread id if your agent exposes one; otherwise plan to match by title/topic. +2. **Search Basic Memory** for the existing thread note. + - With a thread id, use `metadata_filters` (not `query`) — full-text query doesn't reliably match YAML frontmatter custom fields: + ```python + search_notes( + metadata_filters={"thread_id": ""}, + project="" + ) + ``` + - Without one, search by topic and identify the note this thread already produced: + ```python + search_notes(query="", project="") + ``` +3. **If a match is found:** + - Read the existing note (use the full permalink returned by search) + - Synthesize a new version that integrates the latest understanding from the conversation + - Overwrite via `write_note` with `overwrite=True` (same title, same `thread_id` if used, same directory) +4. **If no match is found:** + - Synthesize the note from the conversation + - If you have a thread id, pass `metadata={"thread_id": ""}` to `write_note` (it surfaces as a custom frontmatter field) + - Save it + +## Synthesis Rules + +When updating an existing thread note, **synthesize, don't append**: + +- Decisions that are still current → keep, possibly refined +- Decisions that have been superseded → replaced inline (the new one goes where the old one was) +- Significant revisions that deserve explanation → a sentence woven into the relevant section, *not* an appended changelog +- Outdated context → removed + +Goal: the note reads top-to-bottom as a single coherent document. A reader who never saw the conversation should still understand the outcome from the note alone. There is no `## Changes` section at the bottom; revisions live in the prose where they're relevant. + +## Escape Hatch + +If the user explicitly asks for a separate note (e.g., "capture this as a new note, don't merge with the existing thread note"), skip the same-thread lookup and create a fresh note without setting `thread_id`. This is rare; the default is to update. + +## Note Structure + +```markdown +--- +title: +type: note +thread_id: +tags: +- relevant +- tags +--- + +# + +## Context + +What this thread is about — the situation, problem, or topic being explored. + +## <One or more topical sections> + +The actual content. Could be decisions, a design rationale, an investigation summary, etc. + +## Observations + +- [decision] What was decided #tag +- [insight] Key understanding gained #tag +- [tradeoff] Option A chosen over B because... #tag + +## Relations + +- relates_to [[Related Concept]] +- implements [[Parent Spec]] +``` + +## Common Observation Categories + +- `[decision]` — choices made +- `[insight]` — understanding gained +- `[pattern]` — reusable approaches +- `[learning]` — lessons learned +- `[tradeoff]` — options weighed +- `[problem]` — issues identified +- `[solution]` — fixes applied + +## Title + +The title should reflect the thread's topic. On update, the title can be refined if the topic has clarified — but it should still describe the same thread. Don't drift to a wholly new topic; if that's needed, use the escape hatch and create a new note. + +## MCP Tools Used + +```python +# Find existing thread note by thread id (use metadata_filters, not query) +search_notes( + metadata_filters={"thread_id": "<thread-id>"}, + project="<project>" +) + +# Or, without a thread id, find it by topic +search_notes(query="<thread topic>", project="<project>") + +# Read existing thread note (use the full permalink from search results) +read_note( + identifier="<full-permalink>", + project="<project>" +) + +# Create +write_note( + title="<title>", + content="<markdown body — frontmatter is generated from title/tags/metadata>", + directory="<folder>", + tags=["..."], + metadata={"thread_id": "<thread-id>"}, # omit if no stable id + project="<project>" +) + +# Overwrite an existing note (same path) +write_note( + title="<same title>", + content="<new content>", + directory="<same folder>", + tags=["..."], + metadata={"thread_id": "<same thread-id>"}, # omit if no stable id + overwrite=True, + project="<project>" +) +``` + +## Examples + +### Example 1 — First capture during a brand design conversation + +**Preceding conversation:** The user has been working through visual identity decisions for a new product. They settled on a deep navy primary (`#2B3651`), explored accent options and chose orange (`#F26B3A`) for warmth, and picked Inter as the body font with Helvetica Neue as the display font. + +**User asks to capture.** + +**Result — note created:** + +```markdown +--- +title: Visual identity — initial decisions +type: note +thread_id: 7c1d4a2e-3b5f-4d8a-9e1c-2f6b8a4d7c39 +tags: +- branding +- design +--- + +# Visual identity — initial decisions + +## Context + +Working through the visual identity for the new product. This thread covers the initial palette and typography pass — a starting point that will likely be refined. + +## Color palette + +- Primary: deep navy `#2B3651` — calm and professional +- Accent: warm orange `#F26B3A` — energy and warmth as a complement to the navy + +## Typography + +- Body: Inter — neutral, readable at small sizes +- Display: Helvetica Neue — strong presence for headings without being heavy + +## Observations + +- [decision] Primary color is navy `#2B3651` #branding +- [decision] Accent color is orange `#F26B3A` #branding +- [decision] Inter for body, Helvetica Neue for display #typography +- [tradeoff] Considered teal as accent; orange tested better for warmth #branding + +## Relations + +- relates_to [[Brand Strategy]] +``` + +### Example 2 — Update capture later in the same thread + +**Preceding conversation (continued):** After the initial decisions above, the conversation continued. The orange accent felt too aggressive in mock-ups, so we tested a coral (`#E89B7A`) which read warmer and more refined. The body font also shifted: Geist felt slightly tighter and more modern than Inter. Helvetica Neue for display stayed. + +**User asks to capture again — same thread.** + +**Result — same note rewritten (note the same `thread_id`):** + +```markdown +--- +title: Visual identity — initial decisions +type: note +thread_id: 7c1d4a2e-3b5f-4d8a-9e1c-2f6b8a4d7c39 +tags: +- branding +- design +--- + +# Visual identity — initial decisions + +## Context + +Working through the visual identity for the new product. This thread settled on a navy + coral palette and a Geist/Helvetica typography pairing after a round of refinement. + +## Color palette + +- Primary: deep navy `#2B3651` — calm and professional +- Accent: coral `#E89B7A` — warm and refined + +The accent went through a round of revision: an initial orange (`#F26B3A`) felt too aggressive in mock-ups, so we shifted to a coral that reads warmer and more refined while keeping the energy. + +## Typography + +- Body: Geist — slightly tighter and more modern than Inter, which we tried first +- Display: Helvetica Neue — strong presence for headings without being heavy + +## Observations + +- [decision] Primary color is navy `#2B3651` #branding +- [decision] Accent color is coral `#E89B7A` — warmer and more refined than the originally-chosen orange #branding +- [decision] Geist for body, Helvetica Neue for display #typography +- [tradeoff] Inter felt neutral but Geist edged it for spacing and modernity #typography +- [tradeoff] Orange accent rejected as too aggressive; coral preferred #branding + +## Relations + +- relates_to [[Brand Strategy]] +``` + +Notice that: +- The orange and Inter decisions are **no longer the primary content** — they're acknowledged in prose ("which we tried first," "originally-chosen orange") and in tradeoff observations +- There is **no "Changes" section** at the bottom — revisions are integrated where they belong +- The note still reads top-to-bottom as a single coherent document +- The `thread_id` is unchanged, so the note was updated in place rather than duplicated + +## Best Practices + +1. **Capture the current state, not the history.** The note represents where the thread has landed. +2. **Synthesize, don't log.** Each invocation produces a coherent document, not an accumulating record. +3. **Brief prose for revisions.** A sentence in the section that changed is enough — don't add a changelog. +4. **Always run the same-thread lookup** before deciding to create or update. +5. **Use observations for the structured layer.** Decisions, insights, tradeoffs go in `## Observations` so they're searchable. +6. **Link relations liberally.** Notes the user might want to reach from this one. diff --git a/skills/memory-continue/SKILL.md b/skills/memory-continue/SKILL.md new file mode 100644 index 00000000..0274d192 --- /dev/null +++ b/skills/memory-continue/SKILL.md @@ -0,0 +1,148 @@ +--- +name: memory-continue +description: "Resume prior work by rebuilding context from the Basic Memory knowledge graph — pick up where you left off using memory:// URLs, recent activity, and search. Use when starting a session or when the user says 'continue with...', 'back to...', or 'where were we?'" +--- + +# Memory Continue + +Resume previous work by reconstructing context from the Basic Memory knowledge graph, so the assistant can pick up across sessions instead of starting cold. + +## When to Use + +- Starting a new session and you need to pick up where you left off +- The user references earlier work: "continue with...", "back to...", "where were we on...?" +- You need context about an ongoing project or spec +- The user asks about something discussed in a previous conversation +- You're working on a task that spans multiple sessions + +## Building Context + +### 1. Identify What to Continue + +If it's unclear, ask: +- What topic or project should you resume? +- What timeframe matters? +- Any specific aspect to focus on? + +### 2. Gather Context with MCP Tools + +**Known topic — use `build_context`.** Navigate the graph from a starting point, following relations outward: + +```python +build_context( + url="memory://topic-or-note-name", + depth=2, # how many relation hops to follow + timeframe="7d", # bias toward recent changes +) +``` + +**No clear starting point — use `recent_activity`.** See what's changed and let it surface the thread: + +```python +recent_activity(timeframe="3d", depth=1) +``` + +**Looking for something specific — use `search_notes`.** Find candidate notes by keyword: + +```python +search_notes(query="async client refactor", page_size=10) +``` + +### 3. Read the Key Notes + +Once you've identified the relevant notes, read them in full: + +```python +read_note(identifier="note-title-or-permalink") +``` + +### 4. Present Context to the User + +Summarize what you found, incrementally: +- Current state of the work +- Recent changes or progress +- Open items and next steps +- Related context that might help + +## Memory URL Reference + +`build_context` and `read_note` both accept `memory://` URLs, which address notes by permalink and support wildcards for gathering groups of notes. + +``` +memory://note-title # a single note by permalink +memory://folder/* # all notes in a folder +memory://specs/SPEC-24* # pattern / prefix match +memory://project/*/requirements # path wildcards +``` + +Use a specific note URL to anchor on one starting point; use a wildcard to pull in a whole folder or family of related notes at once. + +## Timeframe Reference + +`build_context` and `recent_activity` accept natural-language timeframes: + +| Timeframe | Meaning | +|-----------|---------| +| `"today"` | Current day | +| `"yesterday"` | Previous day | +| `"3d"` or `"3 days"` | Last 3 days | +| `"1 week"` or `"7d"` | Last week | +| `"2 weeks"` | Last 2 weeks | +| `"1 month"` | Last month | + +## Scenario Playbooks + +### Resuming a Spec or Project + +```python +# 1. Read the spec / project note +read_note(identifier="SPEC-24: Postgres Database Migration") + +# 2. Pull in related context and recent changes via the graph +build_context(url="memory://SPEC-24*", timeframe="7d") +``` + +Then summarize: the goals, what's completed, what's pending, and any blockers or open decisions. + +### Continuing General Work + +```python +# 1. Check recent activity +recent_activity(timeframe="3d") + +# 2. Read notes from the recent sessions it surfaces +read_note(identifier="relevant-note") +``` + +Then list the modified notes with brief descriptions and ask which thread to dive into. + +### Following Up on a Topic + +```python +# 1. Find the topic +search_notes(query="topic keywords") + +# 2. Build context from the best match, following its relations +build_context(url="memory://found-note-permalink", depth=2) +``` + +Then present the full picture — the note plus its connected context. + +## Project Discovery + +Project names are user-specific. To discover what's available before scoping a search or `memory://` URL: + +```python +list_memory_projects() +``` + +In multi-project setups, prefix a `memory://` URL with the project name (e.g. `memory://research/papers/crdt`) to scope it. + +## Guidelines + +1. **Start broad, then narrow.** Get an overview with `recent_activity` or a wildcard `build_context`, then drill into specific notes. +2. **Present incrementally.** Share what you find as you go rather than holding everything until the end. +3. **Follow relations.** The graph's connections are the point — `build_context` with `depth` surfaces context you wouldn't find by reading one note. +4. **Check multiple projects.** Specs may live separately from implementation notes; discover projects with `list_memory_projects`. +5. **Confirm understanding.** Verify the reconstructed context is what the user actually needs before acting on it. +6. **Capture new progress.** As the resumed work advances, write it back to the graph (see the **memory-notes** skill) so the next session can continue too. diff --git a/skills/memory-curate/SKILL.md b/skills/memory-curate/SKILL.md new file mode 100644 index 00000000..c046c072 --- /dev/null +++ b/skills/memory-curate/SKILL.md @@ -0,0 +1,243 @@ +--- +name: memory-curate +description: "Curate the Basic Memory knowledge graph: find orphan notes and suggest links, propose typed relations, merge duplicates, audit tags and folders, and build hub notes. Use to organize, connect, and improve a knowledge base as notes accumulate." +--- + +# Memory Curate + +Maintain a healthy, well-connected knowledge graph. As notes accumulate, it pays to periodically organize, link, and curate the knowledge base so isolated notes become a connected graph. + +This skill curates the **knowledge graph** — the notes, relations, and tags that make up the knowledge base. (For hygiene on an agent's own memory *files* — splitting bloated files, pruning stale entries — see **memory-defrag**.) + +## When to Use + +- Asked to organize, clean up, or improve the knowledge base +- Asked to find connections between notes, or what isn't linked yet +- Orphan or unlinked notes are mentioned +- Asked about duplicate or similar notes +- Asked for help with folder organization or tag consistency +- Phrases like "help me organize", "find related notes", "what's not linked", "clean up my notes" + +## Curation Capabilities + +### 1. Find Orphan Notes + +Orphans have no relations to other notes — they're islands in the graph. + +```python +# List notes, then read each to inspect its Relations section +search_notes(query="*", page_size=50) +read_note(identifier="note-to-check") +# Orphans have an empty (or missing) Relations section +``` + +**What to do with orphans:** +- Suggest relations based on content similarity +- Ask whether they should connect to existing topics +- Propose hub notes to gather related orphans (see capability 6) + +### 2. Suggest Typed Relations + +Analyze a note's content and propose meaningful connections. + +```python +read_note(identifier="note-to-analyze") +# Pull out key terms, then search for related notes +search_notes(query="key terms from the note") +``` + +Suggest relations based on shared topics, complementary content (problem/solution, +question/answer), sequence (part 1 → part 2), or hierarchy (parent concept → detail). + +**Relation-type vocabulary:** +- `relates_to` — general topical connection +- `extends` — builds upon or elaborates +- `implements` — realizes a concept or spec +- `depends_on` — requires understanding of +- `part_of` — hierarchy or composition +- `contrasts_with` — presents an alternative view +- `inspired_by` — source of insight +- `enables` — makes something possible + +Custom relation types are fine — use whatever verb is descriptive. + +Add a confirmed relation with `edit_note`: + +```python +edit_note( + identifier="API Design Decisions", + operation="append", + section="Relations", + content="- depends_on [[Rate Limiter]]", +) +``` + +### 3. Identify Similar / Duplicate Notes + +Find notes that may cover the same ground. + +```python +search_notes(query="topic keywords") +# Compare results for: similar titles, overlapping observations, +# shared tags, close-together timestamps +``` + +**Actions for duplicates:** +- **Merge** into a single comprehensive note, then redirect the loser with a relation +- Link with `supersedes` / `updates` when one revises the other +- **Differentiate** by adding context that clarifies each note's distinct focus + +```python +# Point an older note at the one that replaces it +edit_note( + identifier="DB Schema v1", + operation="append", + section="Relations", + content="- updates [[DB Schema v2]]", +) +``` + +### 4. Folder Organization Review + +```python +list_directory(dir_name="/", depth=3) +``` + +Look for overcrowded folders, single-note folders, inconsistent naming, and notes +that belong elsewhere. Suggest grouping related notes into topic folders, adding +subfolders for large categories, and a consistent naming convention. Move misplaced +notes with `move_note` — the permalink stays stable, so wiki-links keep resolving. + +```python +move_note( + identifier="API Design Decisions", + destination_path="architecture/api-design-decisions.md", +) +``` + +### 5. Tag Consistency + +```python +search_notes(query="*", page_size=100) +# Inspect tag patterns across results +``` + +Look for: +- **Variant tags** — `architecture` vs `arch`; pick one and standardize +- **Unused tags** — present on a single note, no longer carrying weight +- **Over-used generic tags** — so broad they don't aid discovery +- **Missing tags** — relevant notes lacking an obvious tag + +### 6. Create Index / Hub Notes + +After finding a cluster of related notes, build a navigation hub. + +```python +write_note( + title="Architecture Decisions Index", + directory="indexes", + tags=["architecture", "index"], + note_type="index", + content="""# Architecture Decisions Index + +A hub linking architecture-related decisions and patterns. + +## Decisions +- [[Database Selection Decision]] +- [[API Design Patterns]] +- [[Authentication Architecture]] + +## Patterns +- [[Repository Pattern]] +- [[Async Client Pattern]] + +## Observations +- [index] Central hub for architecture knowledge #navigation + +## Relations +- indexes [[Architecture]]""", +) +``` + +### 7. Enrich Sparse Notes + +Find notes lacking structure and fill them in. + +```python +read_note(identifier="sparse-note") +``` + +If the note is missing an Observations section, suggest categories. If it has no +Relations, suggest links. If it has no tags, suggest relevant ones. If it lacks +context, suggest adding background. Apply with `edit_note`. + +## Curation Workflows + +### Quick Health Check + +A fast overview of knowledge base status: + +1. Count total notes +2. Identify orphan count +3. List recently modified (`recent_activity`) +4. Check for obvious duplicates +5. Report folder distribution + +### Deep Organization Session + +Thorough review and improvement: + +1. **Audit** — catalog all notes, identify issues +2. **Orphans** — address unlinked notes +3. **Relations** — suggest new connections +4. **Duplicates** — merge or differentiate similar notes +5. **Structure** — reorganize folders if needed +6. **Index** — create hub notes for major topics + +### Topic-Focused Organization + +Organize around a specific subject: + +1. Find all notes related to the topic (`search_notes`) +2. Map existing relations with `build_context(url="memory://...")` +3. Identify gaps in the topic graph +4. Suggest new notes to fill them +5. Create a topic index note + +## Best Practices + +1. **Work incrementally.** Don't reorganize everything at once. +2. **Confirm before changing.** Always ask before moving, merging, or editing notes. +3. **Preserve permalinks.** Moving a note is fine; changing its permalink breaks inbound links. +4. **Explain suggestions.** Say *why* a relation or merge makes sense. +5. **Respect the existing system.** Enhance the user's organization — don't impose a new taxonomy. +6. **Show the graph.** Use `build_context` to help the user see how notes connect. + +## Example Conversations + +**User:** "Help me organize my notes" + +The assistant: +1. Runs a health check on the knowledge base +2. Reports: "You have 47 notes. I found 12 orphans and 3 potential duplicates." +3. Asks: "Want to start by connecting the orphans, or review the duplicates first?" + +**User:** "Find notes that should link to my API design note" + +The assistant: +1. Reads the API design note +2. Searches for related content +3. Suggests: "5 notes could relate — + - 'REST Best Practices' → `relates_to` + - 'Authentication Flow' → `implements` + - 'Rate Limiting Decision' → `extends` + Should I add any of these relations?" + +**User:** "Are there notes on similar topics?" + +The assistant: +1. Analyzes titles and content for clusters +2. Reports: "Possible overlaps — + - 'Auth Flow' and 'Authentication Design' cover similar ground + - 'DB Schema v1' and 'DB Schema v2' likely want a `supersedes` relation + Want to review either?" diff --git a/skills/memory-notes/SKILL.md b/skills/memory-notes/SKILL.md index 8c57caba..b0c3ce3b 100644 --- a/skills/memory-notes/SKILL.md +++ b/skills/memory-notes/SKILL.md @@ -276,26 +276,42 @@ Basic Memory auto-generates frontmatter (including the permalink and memory URL) ### Editing an Existing Note -Use `edit_note` to append, prepend, or find-and-replace within a note: +Use `edit_note` to update a note in place — four operations: ```python -# Append new observations +# append / prepend — add to the end or start (use for time-ordered logs) edit_note( identifier="API Design Decisions", operation="append", section="Observations", content="- [decision] Use OpenAPI 3.1 for spec generation #api" ) - -# Add a new relation edit_note( identifier="API Design Decisions", - operation="append", - section="Relations", - content="- depends_on [[Rate Limiter]]" + operation="prepend", + content="> Updated 2026-05-28: auth approach finalized.\n" +) + +# replace_section — rewrite a named section (use for living content that stays current) +edit_note( + identifier="API Design Decisions", + operation="replace_section", + section="Summary", + content="Concise, current summary of the decision and its rationale." +) + +# find_replace — swap specific text +edit_note( + identifier="API Design Decisions", + operation="find_replace", + find_text="OpenAPI 3.0", + content="OpenAPI 3.1" ) ``` +When an edit is destructive (`replace_section`, `find_replace`), it's good practice to +read the note first and confirm the change before applying it. + ### Moving a Note Use `move_note` to reorganize notes into different directories: