feat(skills): port useful retired plugin skills into the shared memory-* set

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) <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
phernandez
2026-05-28 22:55:31 -05:00
committed by Paul Hernandez
parent fc8ac86fa1
commit 877e52fd73
6 changed files with 695 additions and 7 deletions
+3
View File
@@ -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`
+3
View File
@@ -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
+275
View File
@@ -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="<topic>")`), 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": "<thread-id>"},
project="<project>"
)
```
- Without one, search by topic and identify the note this thread already produced:
```python
search_notes(query="<thread topic>", project="<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": "<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: <descriptive title for the thread>
type: note
thread_id: <thread-id, if your agent exposes one>
tags:
- relevant
- tags
---
# <Title>
## 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.
+148
View File
@@ -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.
+243
View File
@@ -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?"
+23 -7
View File
@@ -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: