← Plugin catalog
Productivity

Basic Memory Cloud

Basic Memory v2.0.0

Is this plugin right for you?

Researched Oct 1, 2026

Keep reusable project knowledge available across AI conversations. [1]

Useful for individuals and teams maintaining shared knowledge. Our assessment from the available sources.

What you can do

  • Save decisions as linked notes [1]
  • Retrieve project context using semantic search [1]

What you need

  • A Basic Memory Cloud subscription after the trial [1] [2] [3]

Pricing

The cloud MCP requires a subscription. The free local edition is a different product option. [1] [2] [3]

USD 15.00 / seat/month

Connected service price; not a plugin installation fee.

Before you connect

  • The free local edition is separate from this cloud connector. [1] [2] [3]
Sources, unknowns & research method

We reviewed the saved listing and available official pages. Scenarios are our summaries of documented capabilities. This plugin has not been tested in a connected account. A missing price does not mean free access.

Still unknown

  • Publisher country has not been verified in this research pass.
  1. Saved marketplace listingchatgpt.com · Checked Oct 1, 2026 · Snapshot saved
  2. Official websitedocs.basicmemory.com · Checked Oct 1, 2026 · Snapshot saved
    You'll need an active subscription to use the MCP endpoint.
  3. Official websitebasicmemory.com · Checked Oct 1, 2026 · Snapshot saved
    $15 /seat/month
  4. Saved listing and package evidencecodex-plugin-stats.com · Checked Oct 1, 2026 · Snapshot saved
  5. Official websitebasicmemory.com · Checked Oct 1, 2026 · Snapshot saved
  6. Saved package manifestcodex-plugin-stats.com · Checked Sep 30, 2026 · Snapshot saved
Download structured report →

Publisher description

Basic Memory gives you a persistent knowledge base: your notes, decisions, research, and project context, stored as plain Markdown files you own. Anything your AI saves to Basic Memory, you can open and edit. Anything you write, your AI can find and build on. Save what matters. "Save our pricing decision and link it to the roadmap." Notes you save in one conversation are available everywhere. Retrieve context from anywhere. "What did we decide about pricing? Check my notes first." Never re-explain a project. Search by meaning. Semantic and hybrid search across everything you and your AI have saved. Structured search. Filter by status, type, tags, or priority. "Show my open tasks, sorted by priority." Follow connections. Linked notes let your AI traverse related context and surface relationships in a living knowledge graph. Share a workspace with your team. Teammates and their AI tools read and write to one shared source of truth. Notes are stored as ordinary Markdown that you own. Any AI tool can use and build on it, so your shared context follows you across the assistants and agents you use. Subscription Required: This connector requires a Basic Memory Cloud account (7-day free trial, then from $15/seat/month at https://basicmemory.com. Use the Basic Memory Cloud app to view and edit your notes at: https://app.basicmemory.com

Language: English · Automatically detected from descriptions.

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package author
Basic Memory

Package observed Sep 30, 2026.

Files & skills

File archives

Plugin package37 files · 58.3 KBBrowse files →
Skill instructions
memory-capture11.2 KB

View saved version →

---
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.

Referenced files: 1

memory-ci-capture2.03 KB

View saved version →

---
name: memory-ci-capture
description: Synthesize GitHub delivery context into a concise Basic Memory project update. Use in CI after `bm ci collect` prepares a ProjectUpdateContext; return only structured AgentSynthesis JSON for `bm ci publish`.
---

# Memory CI Capture

Turn a meaningful GitHub delivery moment into project memory. GitHub records the
mechanics. Basic Memory remembers what changed and why.

## Inputs

Read the `ProjectUpdateContext` JSON produced by `bm ci collect` at
`.github/basic-memory/project-update-context.json`. Treat it as the immutable
source of truth for repository, event type, PR number, workflow run, SHA, source
URL, timestamps, and deployment environment.

Do not invent tests, deploy checks, linked issues, product impact, or decisions.
If evidence is absent, say so briefly in `verification` or leave the field empty.

## Output

Return only JSON matching the `AgentSynthesis` shape:

```json
{
  "summary": "What changed.",
  "why_it_matters": "Why this update matters for future humans and agents.",
  "user_facing_changes": [],
  "internal_changes": [],
  "verification": [],
  "follow_ups": [],
  "decision_candidates": [],
  "task_candidates": []
}
```

## Synthesis Rules

- Prefer a short explanation over a commit-by-commit changelog.
- Preserve intent, changed behavior, source links, verification evidence present
  in the context, and concrete follow-ups.
- Put explicit product or architecture decisions in `decision_candidates` only
  when the source context clearly contains them.
- Put future work in `task_candidates` only when it is concrete enough to act on.
- Keep the tone factual and useful. This is project memory, not marketing copy.

## Event Guidance

For merged pull requests, focus on why the PR existed, what area changed, what
issues it advanced or closed, and what verification evidence appears in the
context.

For production deploys, focus on what reached production, the deployed SHA,
environment, workflow run, and verification evidence. Do not overclaim success
beyond the workflow and source facts.

Referenced files: 1

memory-continue4.87 KB

View saved version →

---
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.

Referenced files: 1

memory-curate7.58 KB

View saved version →

---
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?"

Referenced files: 1

memory-defrag3.61 KB

View saved version →

---
name: memory-defrag
description: "Defragment and reorganize agent memory files: split bloated files, merge duplicates, remove stale information, and restructure the memory hierarchy. Use when memory files have grown unwieldy, contain redundancies, or need reorganization. Run periodically (weekly) or on demand."
---

# Memory Defrag

Reorganize memory files for clarity, efficiency, and relevance. Like filesystem defragmentation but for knowledge.

## When to Run

- **Periodic**: Weekly or biweekly via cron (recommended)
- **On demand**: User asks to clean up, reorganize, or defrag memory
- **Threshold**: When MEMORY.md exceeds ~500 lines or daily notes accumulate without consolidation

## Process

### 1. Audit Current State

Inventory all memory files:
```
MEMORY.md           — long-term memory
memory/             — daily notes, tasks, topical files
memory/tasks/       — active and completed tasks
```

For each file, note: line count, last modified, topic coverage, staleness.

### 2. Identify Problems

Look for these common issues:

| Problem | Signal | Fix |
|---------|--------|-----|
| **Bloated file** | >300 lines, covers many topics | Split into focused files |
| **Duplicate info** | Same fact in multiple places | Consolidate to one location |
| **Stale entries** | References to completed work, old dates, resolved issues | Remove or archive |
| **Orphan files** | Files in memory/ never referenced or updated | Review, merge, or remove |
| **Inconsistencies** | Contradictory information across files | Resolve to ground truth |
| **Poor organization** | Related info scattered across files | Restructure by topic |
| **Recursive nesting** | `memory/memory/memory/...` directories | Delete nested dirs (indexer bug artifact) |

### 3. Plan Changes

Before making edits, write a brief plan:
```markdown
## Defrag Plan
- [ ] Split MEMORY.md "Key People" section → memory/people.md
- [ ] Remove completed tasks older than 30 days from memory/tasks/
- [ ] Merge memory/bm-marketing-ideas.md into memory/competitive/
- [ ] Update stale project status entries in MEMORY.md
```

### 4. Execute

Apply changes one at a time:
- **Split**: Extract sections from large files into focused topical files
- **Merge**: Combine related small files into coherent documents
- **Prune**: Remove information that is no longer relevant or accurate
- **Restructure**: Move files to appropriate directories, rename for clarity
- **Update**: Fix outdated facts, dates, statuses

### 5. Verify & Log

After changes:
- Verify no information was lost (compare before/after)
- Update any cross-references between files
- Log what was done in today's daily note:

```markdown
## Memory Defrag (HH:MM)
- Files reviewed: N
- Split: [list]
- Merged: [list]
- Pruned: [list]
- Net result: X files, Y total lines (was Z lines)
```

## Guidelines

- **Preserve raw daily notes.** Don't delete or modify `memory/YYYY-MM-DD.md` files — they're the audit trail.
- **Target 15-25 focused files.** Too few means bloated files; too many means fragmentation. Aim for the sweet spot.
- **File names should be scannable.** Use descriptive names: `people.md`, `project-status.md`, `competitive-landscape.md` — not `notes-2.md`.
- **Don't over-organize.** One level of directories is usually enough. `memory/tasks/` and `memory/competitive/` are fine; `memory/work/projects/active/basic-memory/notes/` is not.
- **Completed tasks**: Tasks with `status: done` older than 14 days can be removed. Their insights should already be in MEMORY.md via reflection.
- **Ask before destructive changes.** If uncertain whether information is still relevant, keep it with a `(review needed)` tag rather than deleting.

Referenced files: 1

memory-ingest11.3 KB

View saved version →

---
name: memory-ingest
description: "Process unstructured external input (meeting transcripts, conversation logs, pasted documents) into structured Basic Memory entities. Extracts entities, searches for existing matches, proposes new entities with approval, creates notes with observations and relations, and captures action items."
---

# Memory Ingest

Turn raw, unstructured input into structured Basic Memory entities. Meeting transcripts, conversation logs, pasted documents, email threads — anything with information worth preserving gets parsed, cross-referenced against existing knowledge, and written as proper notes.

## When to Use

- User pastes a meeting transcript or conversation log
- User says "process these notes" or "add this to Basic Memory"
- User pastes a document, article, or email for knowledge extraction
- Any time raw external text needs to become structured knowledge

## Workflow Overview

```
1. Parse raw input           → identify structure, extract key info
2. Extract entities          → people, orgs, topics, action items
3. Search existing entities  → multi-variation queries
4. Research new entities     → optional web research (see memory-research)
5. Present entity proposal   → get approval before creating
6. Create source note        → verbatim content + observations + relations
7. Create approved entities  → structured notes for each new entity
8. Extract action items      → follow-ups and commitments
```

## Step 1: Parse Raw Input

Read the pasted content and identify its structure:

- **Format**: Meeting transcript, email thread, conversation log, article, freeform notes
- **Date**: When this happened (extract from content or ask)
- **Participants**: Who was involved (names, roles, organizations)
- **Sections**: Any existing structure (headings, speaker labels, timestamps)

Don't rewrite or summarize the source content. Preserve it verbatim in the note — you'll add structured observations alongside it.

## Step 2: Extract Entities

Scan the content for entities worth tracking in the knowledge graph:

| Entity Type | Signals |
|-------------|---------|
| **Person** | Names with roles, titles, or affiliations mentioned |
| **Organization** | Company names, agencies, institutions |
| **Topic/Concept** | Technical domains, methodologies, standards discussed substantively |
| **Action Item** | Commitments, deadlines, "I'll do X by Y" statements |

**Infer type from context.** If someone is introduced as "CTO of Acme Corp", that's both a Person and an Organization entity. If a technology is discussed in depth, it might warrant a Concept entity.

**Exclude noise.** Not every name mentioned is worth an entity. Filter for:
- People with substantive roles or interactions (not passing mentions)
- Organizations discussed in business/technical context
- Topics with enough detail to warrant their own note

## Step 3: Search Existing Entities

For each extracted entity, search Basic Memory with multiple query variations:

```python
# Person — try full name, last name
search_notes(query="Sarah Chen")
search_notes(query="Chen")

# Organization — try full name, abbreviation, acronym
search_notes(query="National Renewable Energy Laboratory")
search_notes(query="NREL")

# Topic — try the full term and keywords
search_notes(query="edge computing")
search_notes(query="edge inference")
```

Classify each entity as:
- **Existing** — found in Basic Memory. Will link to it with `[[wiki-link]]`.
- **Proposed** — not found. Will propose creation pending approval.

## Step 4: Research New Entities (Optional)

For proposed entities where more context would be valuable, do a brief web search (2-3 queries max per entity):

- **Organizations**: What they do, size, public/private, key products
- **People**: Current role, background, expertise
- **Topics**: Brief definition, relevance

Use hedging language ("appears to be", "estimated", "based on public information"). Never fabricate details.

This step is optional — skip it if the source material provides enough context, or if the user is in a hurry. See the **memory-research** skill for deeper research workflows.

## Step 5: Present Entity Proposal

Before creating anything, present what you found and what you'd like to create:

```
Entities found in Basic Memory:
  - [[Sarah Chen]] (Person — existing)
  - [[Acme Corp]] (Organization — existing)

Proposed new entities:
  - Jordan Rivera (Person — VP Engineering at NovaTech, mentioned as project lead)
  - NovaTech (Organization — SaaS platform, Series B, discussed as integration partner)
  - Federated Learning (Concept — core technical topic of the discussion)

Approve all / select individually / skip entity creation?
```

Include enough context with each proposed entity for the user to make a quick decision.

## Step 6: Create the Source Note

Create the primary note for the ingested content. This is the "record of what happened" — it preserves the raw material and adds structured metadata.

### Meeting / Conversation Note

```python
write_note(
  title="NovaTech Meeting - Jordan Rivera - Feb 22, 2026",
  directory="meetings/2026",
  note_type="meeting",
  tags=["meeting", "novatech", "federated-learning"],
  metadata={"date": "2026-02-22"},
  content="""
# NovaTech Meeting - Jordan Rivera - Feb 22, 2026

Brief one-sentence summary of what this meeting was about.

## Transcript
[Preserve all source content verbatim — do not summarize or rewrite]

## Observations
- [opportunity] NovaTech interested in integration partnership
- [insight] Their platform handles 10K concurrent sessions, relevant to our scale needs
- [next_step] Send technical spec document by Friday
- [sentiment] Strong enthusiasm from their engineering team
- [decision] Agreed to start with a proof-of-concept integration

## Relations
- attended [[Jordan Rivera]]
- with [[NovaTech]]
- discussed [[Federated Learning]]
- follow_up [[Send NovaTech Technical Spec]]
"""
)
```

### Document / Article Note

```python
write_note(
  title="Edge Computing Architecture Whitepaper",
  directory="references",
  note_type="reference",
  tags=["edge-computing", "architecture", "reference"],
  metadata={"source": "https://example.com/whitepaper.pdf", "date_ingested": "2026-02-22"},
  content="""
# Edge Computing Architecture Whitepaper

## Source Content
[Preserve relevant content — for long documents, include key sections rather than the entire text]

## Observations
- [key_finding] Latency drops 40% with edge inference vs cloud-only
- [technique] Model sharding across heterogeneous edge nodes
- [limitation] Requires minimum 8GB RAM per edge node

## Relations
- relates_to [[Edge Computing]]
- relates_to [[Model Optimization]]
"""
)
```

### Observation Categories

Use categories that capture the nature of the information. Common categories for ingested content:

| Category | Use For |
|----------|---------|
| `opportunity` | Business or collaboration opportunities identified |
| `decision` | Decisions made or agreed upon |
| `insight` | Non-obvious understanding gained |
| `next_step` | Concrete action items or follow-ups |
| `sentiment` | Enthusiasm, concerns, hesitations expressed |
| `risk` | Risks or concerns identified |
| `requirement` | Requirements or constraints discovered |
| `key_finding` | Important facts from reference material |
| `technique` | Methods, approaches, or patterns described |
| `context` | Background information that may be useful later |

Invent categories as needed — these are suggestions, not a fixed list.

## Step 7: Create Approved Entities

For each entity the user approved, create a structured note. Match the entity type to an appropriate template.

### Person

```python
write_note(
  title="Jordan Rivera",
  directory="people",
  note_type="person",
  tags=["person", "novatech", "engineering"],
  content="""
# Jordan Rivera

## Overview
VP of Engineering at NovaTech. Met during integration partnership discussion.

## Background
[Role, expertise, context from meeting + any web research]

## Observations
- [role] VP Engineering at NovaTech
- [expertise] Distributed systems, federated learning
- [met] 2026-02-22 during integration discussion

## Relations
- works_at [[NovaTech]]
- discussed_in [[NovaTech Meeting - Jordan Rivera - Feb 22, 2026]]
"""
)
```

### Organization

```python
write_note(
  title="NovaTech",
  directory="organizations",
  note_type="organization",
  tags=["organization", "saas", "integration-partner"],
  content="""
# NovaTech

## Overview
SaaS platform company. Series B stage.
[Additional context from meeting + web research]

## Products & Services
[What they offer, if discussed or researched]

## Observations
- [stage] Series B, ~200 employees
- [relevance] Potential integration partner for our platform
- [first_contact] 2026-02-22

## Relations
- employs [[Jordan Rivera]]
- discussed_in [[NovaTech Meeting - Jordan Rivera - Feb 22, 2026]]
"""
)
```

### Concept / Topic

```python
write_note(
  title="Federated Learning",
  directory="concepts",
  note_type="concept",
  tags=["concept", "machine-learning", "distributed-systems"],
  content="""
# Federated Learning

## Overview
[Brief description of the concept from the discussion context]

## Observations
- [definition] Machine learning approach where models train across decentralized data sources
- [relevance] Core technique discussed in NovaTech integration

## Relations
- discussed_in [[NovaTech Meeting - Jordan Rivera - Feb 22, 2026]]
"""
)
```

Adapt templates to your domain. The key elements are: type and tags as parameters, an overview section, observations with categories, and relations linking back to the source.

## Step 8: Extract Action Items

Review the source content for commitments and follow-ups:

```
Action Items:
  - Send NovaTech technical spec document by Friday (your commitment)
  - Jordan will share their API documentation by next week (their commitment)

Follow-Up Reminders:
  - 1 week: Check if Jordan sent API docs
  - 2 weeks: Schedule follow-up call to discuss POC scope
```

If using the **memory-tasks** skill, create Task notes for your action items. Otherwise, capture them as observations in the source note.

## Guidelines

- **Preserve source content verbatim.** The original text is the ground truth. Structure and observations are your interpretation layered on top.
- **Search before creating.** Always check if entities already exist (see memory-notes search-before-create pattern). Update existing entities with new information rather than creating duplicates.
- **Get approval for new entities.** Present proposed entities and let the user decide which to create. Don't silently populate the knowledge graph.
- **Infer, don't interrogate.** Extract entity types and relationships from context. Only ask the user when genuinely ambiguous.
- **Be selective about entities.** Not every name mentioned deserves its own note. Focus on entities the user will want to reference again.
- **Use hedging for researched info.** Web research supplements — don't present it as fact. "Appears to be", "estimated", "based on public information".
- **Link everything back.** Every created entity should relate back to the source note. The source note should link to all entities discussed.
- **Prose and observations together.** Notes work best with both narrative context and structured observations. Prose gives meaning and tells the story; observations make individual facts searchable. Use the body for context, then distill key facts into categorized observations.

Referenced files: 1

memory-lifecycle5.74 KB

View saved version →

---
name: memory-lifecycle
description: "Manage entity status transitions in Basic Memory: archive completed work, move notes between status folders, update frontmatter, and handle edge cases. Use when marking items complete, archiving old entities, or managing any folder-based status workflow."
---

# Memory Lifecycle

Manage how entities move through status stages in Basic Memory. The core principle: **archive, never delete.** Completed work is valuable context — move it out of the active view, but keep it in the knowledge graph.

## When to Use

- User says something is "done", "finished", "completed", "submitted", "missed", or "cancelled"
- Moving entities between status folders (active → archive, pipeline → active, etc.)
- Reverting a mistaken completion
- Periodic cleanup of stale active items

## Core Principle: Archive, Never Delete

Deleting a note removes it from the knowledge graph — all its observations, relations, and history disappear. Archiving preserves everything while signaling the entity is no longer active.

```
# Good — entity stays in the knowledge graph
move_note → active/ to archive/

# Bad — knowledge is lost
delete_note
```

The only exception: notes created by mistake (typos, true duplicates) can be deleted.

## Folder Conventions

Organize entities by status using folders. The exact folder names depend on your domain, but follow a consistent pattern:

```
entities/
  active/          # Currently relevant, in-progress
  archive/         # Completed, no longer active, but worth keeping
  pipeline/        # Future items, not yet started
```

For tasks specifically:

```
tasks/
  active/          # Work in progress
  completed/       # Finished work
```

For any entity type with a clear lifecycle:

```
[type]/
  active/          # Current
  [end-state]/     # Whatever "done" means for this type
```

Pick folder names that match your domain. The pattern matters more than the specific names.

## Status Detection

When the user mentions completion or status change, extract the intent:

| Signal | Status | Action |
|--------|--------|--------|
| "finished", "done", "completed", "shipped" | Complete | Move to archive/completed folder |
| "submitted", "sent", "delivered" | Complete | Move to archive/completed folder |
| "missed", "passed", "skipped", "expired" | Missed | Move to archive or missed folder |
| "cancelled", "abandoned", "killed" | Cancelled | Move to archive folder |
| "paused", "on hold", "deferred" | Paused | Update frontmatter status, keep in place |
| "restarting", "reopening", "reviving" | Reactivate | Move back to active folder |

## Workflow

### 1. Find the Entity

Search Basic Memory with multiple variations to locate the entity:

```python
search_notes(query="quarterly report")
search_notes(query="Q1 report")
```

If multiple matches come back, present options and ask which one.

If no match is found, ask for clarification — don't guess.

### 2. Move the File

Use `move_note` to relocate the entity to the appropriate status folder:

```python
move_note(
  identifier="tasks/active/quarterly-report",
  destination_path="tasks/completed/quarterly-report.md"
)
```

The permalink stays the same, so all existing `[[wiki-links]]` and `memory://` URLs continue to resolve.

### 3. Update Frontmatter

After moving, update the status in frontmatter to match:

```python
edit_note(
  identifier="quarterly-report",
  operation="find_replace",
  find_text="status: active",
  content="status: completed"
)
```

If there's a completion date field, set it:

```python
edit_note(
  identifier="quarterly-report",
  operation="find_replace",
  find_text="completed:",
  content="completed: 2026-02-22"
)
```

### 4. Confirm

Report what was done concisely:

```
Marked complete: Quarterly Report
  Moved to: tasks/completed/quarterly-report.md
  Status: completed
```

## Edge Cases

### Already Archived

If the entity is already in an archive/completed folder, notify the user:

> "Quarterly Report is already in tasks/completed/. Want me to update anything on it?"

### Partial Completion

Sometimes only part of an entity is done. Don't move it — instead, update observations or status notes within the entity to reflect partial progress.

### Revert / Reactivate

If something was archived by mistake, move it back:

```python
move_note(
  identifier="tasks/completed/quarterly-report",
  destination_path="tasks/active/quarterly-report.md"
)

edit_note(
  identifier="quarterly-report",
  operation="find_replace",
  find_text="status: completed",
  content="status: active"
)
```

### Status Without Movement

Some status changes don't require a folder move — "paused" or "blocked" items often stay in `active/` with just a frontmatter update. Reserve folder moves for terminal or major state transitions.

## Relationship to Other Skills

- **memory-tasks**: Tasks are a specific lifecycle case. This skill covers the general pattern; memory-tasks covers task-specific fields (steps, current_step, context).
- **memory-notes**: Use search-before-create (from memory-notes) to find the entity before transitioning it.
- **memory-defrag**: Periodic defrag can identify stale active items that should be archived.

## Guidelines

- **Archive, never delete.** The knowledge graph benefits from historical context.
- **Move first, then update frontmatter.** This order ensures the file is in the right place even if the edit step fails.
- **Permalinks survive moves.** Links to the entity keep working after a `move_note`.
- **Be concise in confirmations.** The user knows their system — just report what changed.
- **Ask when ambiguous.** If multiple entities match or the target folder isn't clear, ask rather than guess.
- **Batch operations are fine.** If the user says "archive all completed tasks", find them all, confirm the list, then move them in sequence.

Referenced files: 1

memory-literary-analysis17.9 KB

View saved version →

---
name: memory-literary-analysis
description: "Analyze a complete literary work into a structured Basic Memory knowledge graph. Covers schema design, entity seeding, chapter-by-chapter processing, cross-referencing, validation, and visualization."
---

# Memory Literary Analysis

Transform a complete literary work into a structured knowledge graph. Characters, themes, chapters, locations, symbols, and literary devices become interconnected notes — searchable, validatable, and visualizable.

## When to Use

- Analyzing a novel, play, poem, or non-fiction book end-to-end
- Building a teaching or study resource for a literary text
- Creating a book club companion knowledge base
- Research projects requiring structured close reading
- Stress-testing Basic Memory at scale (~200+ notes, 1000+ relations)

## Pipeline Overview

```
Phase 0: Setup         → project, schemas, directory structure
Phase 1: Seed          → stub notes for known major entities
Phase 2: Process       → chapter-by-chapter notes in batches
Phase 3: Cross-ref     → enrich arcs, add parallels, write analysis
Phase 4: Validate      → schema checks, drift detection, consistency
Phase 5: Visualize     → canvas files for character webs, timelines
```

## Phase 0: Setup

### Create the Project

```python
create_memory_project(name="<work-name>", path="~/basic-memory/<work-name>")
```

Use a kebab-case slug of the work's title (e.g., `great-gatsby`, `hamlet`, `beloved`).

### Define Schemas

Write 6 schema notes to `schema/`. Each schema defines the entity type's fields, observation categories, and relation types. Adapt fields to fit the work — the schemas below are starting points, not rigid templates.

#### Character Schema

```python
write_note(
  title="Character",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "Character",
    "version": 1,
    "schema": {
      "role(enum)": "[protagonist, antagonist, supporting, minor], character's narrative role",
      "description": "string, brief character description",
      "first_appearance?": "string, chapter or scene of first appearance",
      "status?(enum)": "[alive, dead, unknown, transformed], character status at end of work"
    },
    "settings": {"validation": "warn"}
  },
  content="""# Character

Schema for character entity notes.

## Observations
- [convention] Major characters in characters/major/, minor in characters/minor/
- [convention] Observation categories: trait, motivation, arc, quote, appearance, relationship, symbolism, fate
- [convention] Relations: appears_in, contrasts_with, allied_with, commands, symbolizes, associated_with"""
)
```

Add work-specific fields as needed — e.g., `rank` for military fiction, `house` for family sagas, `species` for fantasy.

#### Theme Schema

```python
write_note(
  title="Theme",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "Theme",
    "version": 1,
    "schema": {
      "description": "string, what this theme explores",
      "prevalence(enum)": "[major, minor], how central to the work",
      "first_introduced?": "string, where theme first appears"
    },
    "settings": {"validation": "warn"}
  },
  content="""# Theme

Schema for thematic analysis notes.

## Observations
- [convention] Observation categories: definition, manifestation, evolution, counterpoint, quote, interpretation
- [convention] Relations: embodied_by, contrasts_with, reinforced_by, explored_in, expressed_through"""
)
```

#### Chapter Schema

```python
write_note(
  title="Chapter",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "Chapter",
    "version": 1,
    "schema": {
      "chapter_number": "integer, sequential chapter number",
      "pov?": "string, point-of-view character or narrator mode",
      "setting?": "string, primary location",
      "narrative_mode?(enum)": "[dramatic, expository, reflective, epistolary, mixed], chapter's primary mode"
    },
    "settings": {"validation": "warn"}
  },
  content="""# Chapter

Schema for chapter-level analysis notes.

## Observations
- [convention] Chapters stored in chapters/ directory
- [convention] Observation categories: summary, event, tone, technique, quote, significance, foreshadowing
- [convention] Relations: features, set_in, explores, contains, employs, follows, precedes, parallels"""
)
```

#### Location Schema

```python
write_note(
  title="Location",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "Location",
    "version": 1,
    "schema": {
      "description": "string, what this place is",
      "location_type(enum)": "[city, building, landscape, body_of_water, region, fictional, vehicle], type of place",
      "real_or_fictional(enum)": "[real, fictional, both], whether the place exists"
    },
    "settings": {"validation": "warn"}
  },
  content="""# Location

Schema for location and setting notes.

## Observations
- [convention] Observation categories: description, atmosphere, symbolism, significance, geography
- [convention] Relations: setting_for, associated_with, symbolizes, contains, part_of"""
)
```

#### Symbol Schema

```python
write_note(
  title="Symbol",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "Symbol",
    "version": 1,
    "schema": {
      "description": "string, what the symbol is literally",
      "symbol_type(enum)": "[object, animal, color, action, natural_phenomenon, body_part], category of symbol",
      "primary_meaning": "string, most common interpretation"
    },
    "settings": {"validation": "warn"}
  },
  content="""# Symbol

Schema for symbolic element notes.

## Observations
- [convention] Observation categories: meaning, appearance, ambiguity, interpretation, quote, evolution
- [convention] Relations: represents, associated_with, appears_in, contrasts_with, located_at"""
)
```

#### LiteraryDevice Schema

```python
write_note(
  title="LiteraryDevice",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "LiteraryDevice",
    "version": 1,
    "schema": {
      "description": "string, what the device is",
      "device_type(enum)": "[rhetorical, structural, figurative, narrative, dramatic], category",
      "frequency(enum)": "[pervasive, frequent, occasional, rare], how often used"
    },
    "settings": {"validation": "warn"}
  },
  content="""# LiteraryDevice

Schema for literary technique and device notes.

## Observations
- [convention] Observation categories: definition, usage, effect, example, significance
- [convention] Relations: used_in, characterizes, expresses, related_to"""
)
```

### Directory Structure

```
<project>/
  schema/            # 6 schema definitions
  chapters/          # one note per chapter/section + prologue/epilogue
  characters/
    major/           # protagonist, antagonist, key supporting
    minor/           # named characters with limited roles
  themes/            # thematic analysis notes
  locations/         # settings and places
  symbols/           # symbolic elements
  literary-devices/  # techniques and devices
  analysis/          # cross-cutting synthesis
  tasks/             # processing tracker
```

## Phase 1: Seed Entities

Before processing chapters, create stub notes for major entities so `[[wiki-links]]` resolve from the start.

### Characters (major)

For each major character, create a stub with known metadata:

```python
write_note(
  title="<Character Name>",
  directory="characters/major",
  note_type="Character",
  tags=["character", "major", "<role>"],
  metadata={"role": "<role>", "description": "<brief description>"},
  content="""# <Character Name>

## Observations
- [role] <Character's role in the work>
- [appearance] <Key physical description>

## Relations
- associated_with [[<Related Character>]]
- appears_in [[<Key Location>]]"""
)
```

### Seed Checklist

Identify the work's major entities before you start reading. A good starting inventory:

| Type | Typical Count | What to Include |
|------|--------------|-----------------|
| Characters (major) | 8-20 | Protagonist, antagonist, key supporting cast |
| Themes | 5-12 | Central concerns the work explores |
| Locations | 4-10 | Primary settings, symbolically significant places |
| Symbols | 4-10 | Recurring objects, images, or motifs with layered meaning |

Stubs don't need to be complete — they give `[[wiki-link]]` targets and will be enriched during chapter processing.

## Phase 2: Chapter Processing

### Source Text Preparation

Obtain the full text and identify chapter/section boundaries. For public domain works, Project Gutenberg is a good source. For copyrighted works, work from a physical or licensed digital copy.

### Batching Strategy

Process ~10 chapters per batch to balance depth with progress. Group by narrative arc or thematic focus:

| Batch | Typical Content |
|-------|----------------|
| 1 | Opening: setting, character introductions, world-building |
| 2-3 | Rising action: conflicts established, relationships develop |
| 4-6 | Middle: complications, turning points, thematic deepening |
| 7-8 | Climax approach: escalation, revelations, crises |
| Final | Climax, resolution, epilogue |

Adjust batch size based on chapter length and density. Short, action-heavy chapters can be batched in larger groups; long, philosophically dense chapters may need smaller batches.

### Per-Chapter Workflow

For each chapter:

**1. Read the chapter carefully.** If working from a source text file, read the relevant section.

**2. Create the chapter note:**

```python
write_note(
  title="Chapter <N> - <Title>",
  directory="chapters",
  note_type="Chapter",
  tags=["chapter", "<arc-phase>"],
  metadata={
    "chapter_number": <N>,
    "pov": "<narrator or POV character>",
    "setting": "<primary location>",
    "narrative_mode": "<mode>"
  },
  content="""# Chapter <N> - <Title>

## Observations
- [summary] <1-2 sentence synopsis>
- [event] <Key plot events>
- [tone] <Emotional and stylistic atmosphere>
- [technique] <Notable narrative techniques>
- [quote] "<Significant passage>"
- [significance] <Why this chapter matters to the whole>
- [foreshadowing] <Hints at future events>

## Relations
- features [[<Character>]]
- set_in [[<Location>]]
- explores [[<Theme>]]
- contains [[<Symbol>]]
- employs [[<Literary Device>]]
- follows [[Chapter <N-1> - <Previous Title>]]
- precedes [[Chapter <N+1> - <Next Title>]]"""
)
```

**3. Enrich related entities:**

```python
edit_note(
  identifier="characters/major/<character-slug>",
  operation="append",
  heading="Observations",
  content="""- [arc] Ch.<N>: <What happens to this character>
- [quote] "<Attributed quote>" (Ch.<N>)"""
)
```

**4. Track progress** using the memory-tasks skill to create a processing task that survives context compaction.

### What to Capture Per Chapter

| Category | What to Look For |
|----------|-----------------|
| `[summary]` | 1-2 sentence chapter synopsis |
| `[event]` | Key plot events (actions, revelations, arrivals) |
| `[tone]` | Emotional and stylistic atmosphere |
| `[technique]` | Narrative innovations (POV shifts, structural experiments, genre blending) |
| `[quote]` | Memorable or thematically significant passages |
| `[significance]` | Why this chapter matters to the whole |
| `[foreshadowing]` | Hints at future events |

### Entity Enrichment Per Chapter

As each chapter is processed, append observations to relevant entities:
- **Characters**: `[arc]` moments, new `[trait]` revelations, `[quote]` attributions
- **Themes**: `[manifestation]` in this chapter, `[evolution]` shifts
- **Symbols**: `[appearance]` with context, new `[interpretation]` angles
- **Locations**: `[atmosphere]` as described, `[significance]` in scene
- **Literary devices**: `[example]` from this chapter

### Adding Prose and Interpretation

After the structured observations are in place, consider adding interpretive prose to major entity notes. Prepend 2-4 paragraphs of critical essay before the Observations section using `edit_note(operation="prepend")`. This prose should:

- Argue for a reading of the character, theme, or symbol — not just describe it
- Connect the entity to the work's larger concerns and to literary tradition
- Include subjective opinions clearly marked as such ("In my reading...", "I find...")
- Ground claims in textual evidence cited by chapter number

The prose adds the interpretive texture that structured observations alone cannot capture.

## Phase 3: Cross-Referencing

After all chapters are processed:

### Character Arcs
For each major character, write a full `[arc]` summary observation covering their trajectory across the work.

### Theme Evolution
For each theme, add `[evolution]` observations tracing how it develops from introduction to resolution.

### Chapter Parallels
Add `parallels` and `contrasts_with` relations between structurally similar chapters (e.g., mirrored scenes, repeated settings, thematic echoes).

### Analysis Notes
Create synthesis notes in `analysis/`:

```python
write_note(
  title="Narrative Structure",
  directory="analysis",
  note_type="note",
  tags=["analysis", "structure"],
  content="""# Narrative Structure

Analysis of the work's narrative architecture.

## Observations
- [structure] <Overall arc description>
- [technique] <Key narrative strategies>
...

## Relations
- analyzes [[<Protagonist>]]
- analyzes [[<Key Character>]]
- explores [[<Central Theme>]]
..."""
)
```

Recommended analysis notes:
- **Narrative Structure** — overall architecture and pacing
- **Work Overview** — synthesis of the complete work (summary, thesis, legacy)
- **Critical Reception** — historical and contemporary interpretations

### Discover Emergent Entities
During chapter processing, new minor characters, locations, and symbols will emerge. Create notes for any that appear in 3+ chapters or carry thematic weight.

## Phase 4: Validation

### Schema Validation

```python
# Validate each entity type
schema_validate(noteType="Character")
schema_validate(noteType="Theme")
schema_validate(noteType="Chapter")
schema_validate(noteType="Location")
schema_validate(noteType="Symbol")
schema_validate(noteType="LiteraryDevice")
```

### Drift Detection

```python
schema_diff(noteType="Character")
# ... for each type
```

Fix issues found — common fixes:
- Missing required observation categories → add them via `edit_note`
- Enum values outside allowed set → correct metadata
- Fields in notes but not schema → add as optional to schema if legitimate

### Relation Consistency
Spot-check bidirectional relations: if Chapter X `features [[Character]]`, does Character have observations referencing Chapter X? Fix gaps.

## Phase 5: Visualization

Generate canvas files for visual exploration:

```python
# Character relationship web
canvas(query="type:Character AND role:protagonist OR role:antagonist OR role:supporting")

# Theme connections
canvas(query="type:Theme")

# Chapter timeline with key events
canvas(query="type:Chapter", layout="timeline")
```

## Adapting to Other Genres

This pipeline works for any literary text. Adjust schemas for genre:

| Genre | Schema Adjustments |
|-------|-------------------|
| **Novel** | Base schemas work as-is; add genre-specific Character fields as needed |
| **Play** | Add `Act` and `Scene` schemas; Character gets `speaking_lines` field |
| **Poetry collection** | Replace Chapter with `Poem`; add `form`, `meter`, `rhyme_scheme` fields |
| **Non-fiction** | Replace Chapter with `Section`; add `Argument`, `Evidence` schemas |
| **Short story collection** | Add `Story` schema with `narrator`, `setting`, `word_count` |
| **Epic/myth** | Add `Deity`, `Prophecy` schemas; Location gets `mythological_significance` |
| **Memoir** | Character schema gets `relationship_to_narrator`; add `Memory` schema |

### Scaling Guidance

| Work Length | Batch Size | Estimated Notes |
|-------------|-----------|----------------|
| Novella (~40K words) | 5-10 chapters | ~50-80 |
| Novel (~80K words) | 8-12 chapters | ~100-150 |
| Long novel (~200K+ words) | 10-15 chapters | ~200-300 |
| Series (multiple volumes) | 1 volume at a time | ~200+ per volume |

## Related Skills

- **memory-schema** — Schema creation, validation, and drift detection
- **memory-tasks** — Track chapter processing progress across context compaction
- **memory-notes** — Note writing patterns, observation categories, wiki-links
- **memory-ingest** — Processing external input into structured entities
- **memory-metadata-search** — Querying notes by frontmatter fields
- **memory-lifecycle** — Archiving completed analysis phases

## Guidelines

- **Seed before processing.** Create entity stubs first so wiki-links resolve immediately during chapter processing.
- **Batch for sanity.** Processing ~10 chapters at a time balances depth with momentum. Track progress with a Task note.
- **Read the source text.** Don't rely on memory or summaries. Read (or re-read) the actual text for each batch before creating notes. Textual evidence is everything.
- **Observations are your index.** The knowledge graph's value comes from categorized observations. Be generous with categories and specific with content.
- **Relations are your web.** Every chapter should link to characters, themes, locations, and devices. Every entity should link back to chapters where it appears.
- **Enrich iteratively.** Entity notes grow richer with each chapter. Don't try to write the perfect character note upfront — append as you go.
- **Add prose for depth.** After structured data is in place, add interpretive essays to major notes. The prose captures what observations cannot: argument, nuance, opinion, and voice.
- **Validate periodically.** Run `schema_validate` after each batch, not just at the end. Catch drift early.
- **Quote generously.** Literary analysis lives on textual evidence. Include significant quotes as `[quote]` observations with chapter attribution.
- **Review and revise.** After completing all chapters, review the full graph from an external perspective. Look for thin notes, missing connections, and gaps in coverage. The first pass is never the last.
- **Analysis comes last.** Synthesis notes in `analysis/` should be written after all chapters are processed, when you have the full picture.

Referenced files: 1

memory-metadata-search6.38 KB

View saved version →

---
name: memory-metadata-search
description: "Structured metadata search for Basic Memory: query notes by custom frontmatter fields using equality, range, array, and nested filters. Use when finding notes by status, priority, confidence, or any custom YAML field rather than free-text content."
---

# Memory Metadata Search

Find notes by their structured frontmatter fields instead of (or in addition to) free-text content. Any custom YAML key in a note's frontmatter beyond the standard set (`title`, `type`, `tags`, `permalink`, `schema`) is automatically indexed as `entity_metadata` and becomes queryable.

## When to Use

- **Filtering by status or priority** — find all notes with `status: draft` or `priority: high`
- **Querying custom fields** — any frontmatter key you invent is searchable
- **Range queries** — find notes with `confidence > 0.7` or `score between 0.3 and 0.8`
- **Combining text + metadata** — narrow a text search with structured constraints
- **Tag-based filtering** — find notes tagged with specific frontmatter tags
- **Schema-aware queries** — filter by nested schema fields using dot notation

## The Tool

All metadata searching uses `search_notes`. Pass filters via `metadata_filters`, or use the `tags` and `status` convenience shortcuts. Omit `query` (or pass `None`) for filter-only searches.

## Filter Syntax

Filters are a JSON dictionary. Each key targets a frontmatter field; the value specifies the match condition. Multiple keys combine with **AND** logic.

### Equality

```json
{"status": "active"}
```

### Array Contains (all listed values must be present)

```json
{"tags": ["security", "oauth"]}
```

### `$in` (match any value in list)

```json
{"priority": {"$in": ["high", "critical"]}}
```

### Comparisons (`$gt`, `$gte`, `$lt`, `$lte`)

```json
{"confidence": {"$gt": 0.7}}
```

Numeric values use numeric comparison; strings use lexicographic comparison.

### `$between` (inclusive range)

```json
{"score": {"$between": [0.3, 0.8]}}
```

### Nested Access (dot notation)

```json
{"schema.version": "2"}
```

### Quick Reference

| Operator | Syntax | Example |
|----------|--------|---------|
| Equality | `{"field": "value"}` | `{"status": "active"}` |
| Array contains | `{"field": ["a", "b"]}` | `{"tags": ["security", "oauth"]}` |
| `$in` | `{"field": {"$in": [...]}}` | `{"priority": {"$in": ["high", "critical"]}}` |
| `$gt` / `$gte` | `{"field": {"$gt": N}}` | `{"confidence": {"$gt": 0.7}}` |
| `$lt` / `$lte` | `{"field": {"$lt": N}}` | `{"score": {"$lt": 0.5}}` |
| `$between` | `{"field": {"$between": [lo, hi]}}` | `{"score": {"$between": [0.3, 0.8]}}` |
| Nested | `{"a.b": "value"}` | `{"schema.version": "2"}` |

**Rules:**
- Keys must match `[A-Za-z0-9_-]+` (dots separate nesting levels)
- Operator dicts must contain exactly one operator
- `$in` and array-contains require non-empty lists
- `$between` requires exactly `[min, max]`

> **Warning:** Operators MUST include the `$` prefix — write `$gte`, not `gte`. Without the prefix the filter is treated as an exact-match key and will silently return no results. Correct: `{"confidence": {"$gte": 0.7}}`. Wrong: `{"confidence": {"gte": 0.7}}`.

## Using `search_notes` with Metadata

Pass `metadata_filters`, `tags`, or `status` to `search_notes`. Omit `query` for filter-only searches, or combine text and filters together.

```python
# Filter-only — find all notes with a given status
search_notes(metadata_filters={"status": "in-progress"})

# Filter-only — high-priority specs in a specific project
search_notes(
    metadata_filters={"type": "spec", "priority": {"$in": ["high", "critical"]}},
    project="research",
    page_size=10,
)

# Filter-only — notes with confidence above a threshold
search_notes(metadata_filters={"confidence": {"$gt": 0.7}})

# Convenience shortcuts for tags and status
search_notes(status="active")
search_notes(tags=["security", "oauth"])

# Text search narrowed by metadata
search_notes("authentication", metadata_filters={"status": "draft"})

# Mix text, tag shortcut, and advanced filter
search_notes(
    "oauth flow",
    tags=["security"],
    metadata_filters={"confidence": {"$gt": 0.7}},
)
```

**Merging rules:** `tags` and `status` are convenience shortcuts merged into `metadata_filters` via `setdefault`. If the same key exists in `metadata_filters`, the explicit filter wins.

## Tag Search Shorthand

The `tag:` prefix in a query converts to a tag filter automatically:

```python
# These are equivalent:
search_notes("tag:tier1")
search_notes("", tags=["tier1"])

# Multiple tags (comma or space separated) — all must match:
search_notes("tag:tier1,alpha")
```

## Example: Custom Frontmatter in Practice

A note with custom fields:

```markdown
---
title: Auth Design
type: spec
tags: [security, oauth]
status: in-progress
priority: high
confidence: 0.85
---

# Auth Design

## Observations
- [decision] Use OAuth 2.1 with PKCE for all client types #security
- [requirement] Token refresh must be transparent to the user

## Relations
- implements [[Security Requirements]]
```

Queries that find it:

```python
# By status and type
search_notes(metadata_filters={"status": "in-progress", "type": "spec"})

# By numeric threshold
search_notes(metadata_filters={"confidence": {"$gt": 0.7}})

# By priority set
search_notes(metadata_filters={"priority": {"$in": ["high", "critical"]}})

# By tag shorthand
search_notes("tag:security")

# Combined text + metadata
search_notes("OAuth", metadata_filters={"status": "in-progress"})
```

## Guidelines

- **Use metadata search for structured queries.** If you're looking for notes by a known field value (status, priority, type), metadata filters are more precise than text search.
- **Use text search for content queries.** If you're looking for notes *about* something, text search is better. Combine both when you need precision.
- **Custom fields are free.** Any YAML key you put in frontmatter becomes queryable — no schema or configuration required.
- **Multiple filters are AND.** `{"status": "active", "priority": "high"}` requires both conditions.
- **Omit `query` for filter-only searches.** `search_notes(metadata_filters={"status": "active"})` works without a text query.
- **Dot notation for nesting.** Access nested YAML structures with dots: `{"schema.version": "2"}` queries the `version` key inside a `schema` object.
- **Tags shortcut is convenient but limited.** `tags` and `status` are sugar for common fields. For anything else, use `metadata_filters` directly.

Referenced files: 1

memory-notes13.5 KB

View saved version →

---
name: memory-notes
description: "How to write well-structured Basic Memory notes: frontmatter, observations with semantic categories, relations with wiki-links, and best practices for building a rich knowledge graph. Use when creating or improving notes."
---

# Memory Notes

Write well-structured notes that Basic Memory can parse into a searchable knowledge graph. Every note is a markdown file with three key sections: frontmatter, observations, and relations.

## Note Anatomy

```markdown
---
title: API Design Decisions
tags: [api, architecture, decisions]
---

# API Design Decisions

The API team evaluated multiple approaches for the public API during Q1. After
prototyping both REST and GraphQL, the team chose REST due to broader ecosystem
support and simpler caching semantics. This note captures the key decisions and
their rationale, along with open questions still to resolve.

## Observations
- [decision] Use REST over GraphQL for simplicity #api
- [requirement] Must support versioning from day one
- [risk] Rate limiting needed for public endpoints

## Relations
- implements [[API Specification]]
- depends_on [[Authentication System]]
- relates_to [[Performance Requirements]]
```

### Frontmatter

Every note starts with YAML frontmatter:

```yaml
---
title: Note Title          # required — becomes the entity name in the knowledge graph
tags: [tag1, tag2]         # optional — for organization and filtering
type: note                 # optional — defaults to "note", use custom types with schemas
permalink: custom-path     # optional — auto-generated from title if omitted
---
```

- The `title` must match the `# Heading` in the body
- Tags are searchable and help with discovery
- Custom `type` values (Task, Meeting, Person, etc.) work with the schema system. See the **memory-schema** skill for defining schemas, validating notes against them, and detecting drift.
- The `permalink` is auto-generated from the `title` and `directory`. For example, title "API Design Decisions" in directory "specs" produces permalink `specs/api-design-decisions` and memory URL `memory://specs/api-design-decisions`. If no directory is specified, the permalink is just the kebab-cased title. Permalinks stay stable across file moves. You rarely need to set one manually.

> **Note:** When using `write_note`, you don't write frontmatter yourself. The `title`, `tags`, `note_type`, and `metadata` are separate parameters — Basic Memory generates the frontmatter automatically. Your `content` parameter is just the markdown body starting with `# Heading`.

### Body / Context

Free-form markdown between the heading and the Observations section. This is the heart of the note — write generously here:
- Background, motivation, and history
- Detailed explanation of what happened and why it matters
- Analysis, reasoning, and trade-offs considered
- Context that someone (or an AI) needs to understand this note later

Write complete, substantive prose. Basic Memory's search retrieves relevant chunks from note bodies, so longer, richer context makes notes more discoverable and more useful when found. Don't reduce everything to bullet points — tell the story.

## Observations

Observations are categorized facts — the atomic units of knowledge. Each one becomes a searchable entity in the knowledge graph.

### Syntax

```
- [category] Content of the observation #optional-tag
```

- **Square brackets** define the semantic category
- **Content** is the fact, decision, insight, or note
- **Hash tags** (optional) add extra metadata for filtering

### Categories Are Arbitrary

The category in brackets is free-form — use whatever label makes sense for the observation. There is no fixed list. The only rule is the `[category] content` syntax. Consistency within a project helps searchability, but invent categories freely.

A few examples to illustrate the range:

```
- [decision] Use PostgreSQL for primary data store
- [risk] Third-party API has no SLA guarantee
- [technique] Exponential backoff for retry logic #resilience
- [question] Should we support multi-tenancy at the DB level?
- [preference] Use Bun over Node for new projects
- [lesson] Always validate webhook signatures server-side
- [status] active
- [flavor] Ethiopian beans work best with lighter roasts
```

### Observation Tips

- **One fact per observation.** Don't pack multiple ideas into one line.
- **Be specific.** `[decision] Use JWT` is less useful than `[decision] Use JWT with 15-minute expiry for API auth`.
- **Use tags for cross-cutting concerns.** `[risk] Rate limiting needed #api #security` makes this findable under both topics.
- **Categories are queryable.** `search_notes("[decision]")` finds all decisions across your knowledge base.

## Relations

Relations create edges in the knowledge graph, linking notes to each other. They're how you build structure beyond individual notes.

### Syntax

```
- relation_type [[Target Note Title]]
```

- **relation_type** is a descriptive verb or phrase (snake_case by convention)
- **Double brackets** `[[...]]` identify the target note by title or permalink
- Relations are directional: this note → target note

### Relation Types

| Type | Purpose | Example |
|------|---------|---------|
| `implements` | One thing implements another | `- implements [[Auth Spec]]` |
| `requires` | Dependencies | `- requires [[Database Setup]]` |
| `relates_to` | General connection | `- relates_to [[Performance Notes]]` |
| `part_of` | Hierarchy/composition | `- part_of [[Backend Architecture]]` |
| `extends` | Enhancement or elaboration | `- extends [[Base Config]]` |
| `pairs_with` | Things that work together | `- pairs_with [[Frontend Client]]` |
| `inspired_by` | Source material | `- inspired_by [[CRDT Research Paper]]` |
| `replaces` | Supersedes another note | `- replaces [[Old Auth Design]]` |
| `depends_on` | Runtime/build dependency | `- depends_on [[MCP SDK]]` |
| `contrasts_with` | Alternative approaches | `- contrasts_with [[GraphQL Approach]]` |

### Inline Relations

Wiki-links anywhere in the note body — not just the Relations section — also create graph edges:

```markdown
We evaluated [[GraphQL Approach]] but decided against it because
the team has more experience with REST. See [[API Specification]]
for the full contract.
```

These create `references` relations automatically. Use the Relations section for explicit, typed relationships; use inline links for natural prose references.

### Relation Tips

- **Link liberally.** Relations are what turn isolated notes into a knowledge graph. When in doubt, add the link.
- **Create target notes if they don't exist yet.** `[[Future Topic]]` is valid — BM will resolve it when that note is created.
- **Use `build_context` to traverse.** `build_context(url="memory://note-title")` follows relations to gather connected knowledge.
- **Custom relation types are fine.** `taught_by`, `blocks`, `tested_in` — use whatever is descriptive.

## Memory URLs

Every note is addressable via a `memory://` URL, built from its permalink. These URLs are how you navigate the knowledge graph programmatically.

### URL Patterns

```
memory://api-design-decisions          # by permalink (title → kebab-case)
memory://docs/authentication           # by file path
memory://docs/authentication.md        # with extension (also works)
memory://auth*                         # wildcard prefix
memory://docs/*                        # wildcard suffix
memory://project/*/requirements        # path wildcards
```

### Project-Scoped URLs

In multi-project setups, prefix with the project name:

```
memory://main/specs/api-design         # "main" project, "specs/api-design" path
memory://research/papers/crdt          # "research" project
```

The first path segment is matched against known project names. If it matches, it's used as the project scope. Otherwise the URL resolves in the default project.

### Using Memory URLs

Memory URLs work with `build_context` to assemble related knowledge by traversing relations:

```python
# Get a note and its connected context
build_context(url="memory://api-design-decisions")

# Wildcard — gather all docs
build_context(url="memory://docs/*")

# Direct read by permalink
read_note(identifier="memory://api-design-decisions")
```

## Before Creating a Note

Always search Basic Memory before creating a new note. Duplicates fragment your knowledge graph — updating an existing note is almost always better than creating a second one.

### Search with Multiple Variations

A single search often misses. Try the full name, abbreviations, acronyms, and keywords:

```python
# Searching for an entity that might already exist
search_notes(query="Kubernetes Migration")
search_notes(query="k8s migration")
search_notes(query="container migration")
```

For people, try full name and last name. For organizations, try the full name and common abbreviations.

### Decision Tree

- **Entity exists** → Update it with `edit_note` (append observations, add relations, find-and-replace outdated info)
- **Entity doesn't exist** → Create it with `write_note`
- **Unsure if it's the same entity** → Read the existing note first, then decide

### Granular Updates with `edit_note`

When a note already exists, make targeted edits instead of rewriting the whole file:

```python
# Append a new observation to an existing note
edit_note(
  identifier="API Design Decisions",
  operation="append",
  section="Observations",
  content="- [decision] Switched to OpenAPI 3.1 for spec generation #api"
)

# Fix outdated information
edit_note(
  identifier="API Design Decisions",
  operation="find_replace",
  find_text="- [status] draft",
  content="- [status] approved"
)

# Add a new relation
edit_note(
  identifier="API Design Decisions",
  operation="append",
  section="Relations",
  content="- depends_on [[Rate Limiter]]"
)
```

This preserves existing content and keeps the edit history clean.

## Writing Notes with Tools

### Creating a Note

```python
write_note(
  title="API Design Decisions",
  directory="architecture",
  tags=["api", "architecture"],
  content="""# API Design Decisions

The API team evaluated REST and GraphQL during Q1 planning. After prototyping
both approaches, we chose REST for the public API — broader ecosystem support,
simpler caching with HTTP semantics, and a lower learning curve for external
consumers. GraphQL remains an option for internal services where query
flexibility matters more.

## Observations
- [decision] Use REST for public API #api
- [requirement] Support API versioning from v1

## Relations
- implements [[API Specification]]
- relates_to [[Backend Architecture]]"""
)
```

Basic Memory auto-generates frontmatter (including the permalink and memory URL) from the parameters. This note would get permalink `architecture/api-design-decisions` and be addressable at `memory://architecture/api-design-decisions`.

### Editing an Existing Note

Use `edit_note` to update a note in place — four operations:

```python
# 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"
)
edit_note(
  identifier="API Design Decisions",
  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:

```python
move_note(
  identifier="API Design Decisions",
  destination_path="archive/api-design-decisions.md"
)
```

The permalink stays the same after a move, so all `[[wiki-links]]` and `memory://` URLs continue to resolve.

## Best Practices

1. **Start with context.** Before listing observations, explain *why* this note exists. Future-you (or your AI collaborator) will thank you.

2. **Favor completeness.** Write rich, substantive notes. Basic Memory's search pulls relevant chunks from note bodies, so longer notes with more context are *more* discoverable, not less. Use prose in the body to tell the full story — the background, the reasoning, the nuance. Then distill key facts into `[category] content` observations for structured queries. Both matter: prose gives meaning, observations give precision.

3. **Build incrementally.** Add to existing notes rather than creating duplicates. Use `edit_note` to append new observations or relations as you learn more.

4. **Review AI-generated content.** When an AI writes notes for you, review them for accuracy. The AI captures structure well but may miss nuance.

5. **Use consistent titles.** Note titles are identifiers in the knowledge graph. `API Design Decisions` and `Api Design decisions` are different entities. Pick a convention and stick with it.

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.

Referenced files: 1

memory-onboarding13.8 KB

View saved version →

---
name: memory-onboarding
description: "Guide someone new to Basic Memory through designing and building a complete personal knowledge system — interview them about what they want to track, propose a structure, build it with schemas and instruction notes, teach them to use it, and set up their AI assistant to load it automatically. Use this skill whenever a user says they're new to Basic Memory, wants to 'get started', 'set up', or 'onboard' with Basic Memory, doesn't know what to use it for, asks how to organize their memory project or knowledge base, wants help designing folders/schemas/conventions, or asks how to make their assistant remember context between sessions. Also use it when a user has an empty or messy Basic Memory project and wants structure."
---

# Basic Memory Onboarding

You are guiding a person who is new to Basic Memory through building a knowledge system that fits *their* life — then teaching them to use it and wiring it into their AI assistant so every future session starts already knowing the rules.

This skill works with any LLM or assistant platform. Where platform-specific setup is needed (system prompts, project instructions), identify what YOUR environment supports and adapt the generic patterns in `references/assistant-setup.md`.

## Why this approach

Basic Memory is markdown files parsed into a knowledge graph. A pile of unstructured notes is barely better than a folder of text files. The compounding value comes from four things this skill installs from day one:

1. **Schemas** — note types with defined fields, so every task/contact/expense note looks the same and can be queried structurally.
2. **Observations and relations** — categorized facts (`- [status] active`) and typed links (`- depends_on [[Other Note]]`) that turn prose into a graph.
3. **Instruction notes** — the rules of the system live *inside* the system, as notes the assistant loads at session start. The knowledge base becomes self-describing.
4. **A startup router** — one small note that tells any assistant, on any platform, exactly what to load for each kind of task.

**Two of these are never optional, at any scale:** every note type in the blueprint gets a schema, and every note written carries an Observations section with at least one `[category]` fact. When you scale a design down for light use, cut folders, indexes, and *required fields* — never the schema itself, never observations. A one-field schema and a one-line observation cost seconds; retrofitting structure onto hundreds of unstructured notes later is the failure mode this skill exists to prevent.

## Speak Plainly — the User Doesn't Know the Jargon

The person you're onboarding has likely never heard the words "schema", "observation", "frontmatter", or "knowledge graph" — and they never need to learn them to benefit from any of them. The structure is for you; the conversation is for them.

- Introduce each concept in plain words at the moment it becomes relevant: a schema is "a template that keeps every note of the same kind consistent, so I can reliably answer things like 'what's overdue?'"; observations are "the key facts on a note, tagged so they're easy to find later"; relations are "links between notes, so one thing leads to the next".
- **The user never writes syntax.** You handle the `[category]` lines, wiki-links, and validation under the covers — they just talk. Say this explicitly; it's reassuring.
- One concept at a time, and only when it earns its place. If you catch yourself defining three terms in one breath, stop explaining and build something with their data instead — the example teaches better than the definition.

## Workflow overview

```
Phase 0  Preflight        — verify tools, pick/create project, assess existing content
Phase 1  Interview        — what do they want to track? (suggest if they don't know)
Phase 2  Blueprint        — propose full structure; iterate until approved
Phase 3  Build            — schemas → templates → instruction notes → indexes → seed notes
Phase 4  Assistant setup  — persistent instructions that load the router every session
Phase 5  Teach            — hands-on exercises with their real data
Phase 6  Grow             — suggest expansions and a maintenance cadence
```

Do not skip the approval gate between Phase 2 and Phase 3. Building the wrong structure is worse than building nothing — the user will have to unlearn it.

## Phase 0 — Preflight

Before asking the user anything:

1. Confirm Basic Memory tools are available (`write_note`, `read_note`, `search_notes`, `list_directory`, and ideally `schema_infer`/`schema_validate`). If they aren't, stop and help the user connect Basic Memory first.
2. List their projects (`list_memory_projects`). Ask which project to build in, or whether to create a fresh one. **Every subsequent call must pass this project explicitly** — mixed-project writes are one of the most common and painful setup errors.
3. Check for existing content (`list_directory` at root, depth 2). Three situations:
   - **Empty** — greenfield, proceed normally.
   - **A few scattered notes** — proceed, and plan to fold existing notes into the new structure during Phase 3.
   - **Substantial existing content** — this is a restructure, not an onboarding. Still use this skill, but Phase 1 becomes "what's working and what isn't", and Phase 2 must map old → new locations before anything moves.
4. **Check the live docs when unsure.** Basic Memory's documentation is agent-readable: fetch `https://docs.basicmemory.com/llms.txt` for an index, and any page as clean markdown via its `raw/....md` URL (e.g. `raw/reference/mcp-tools-reference.md`, `raw/concepts/schema-system.md`). Tool names and parameters evolve — when this skill and the docs disagree, the docs are canonical.

## Phase 1 — Interview

Ask **one question at a time**, conversationally. Never present a wall of questions. What you need to learn:

1. **Domains** — what do they want to keep track of? If they have ideas, dig into each: what specifically, how often, what does "done" look like?
2. **If they have no idea**, offer a concrete menu and ask what resonates (multi-select). Good starting domains, roughly in order of broad appeal:
   - **Tasks & projects** — todos, deadlines, multi-step projects
   - **Notes & journal** — daily notes, ideas, things learned
   - **People & contacts** — who they know, context per person, follow-ups
   - **Research** — topics they're digging into, sources, findings
   - **Finances** — subscriptions, expenses, accounts, renewals
   - **Procedures** — how-tos they keep re-figuring-out (home, work, tech)
   - **Health & habits** — workouts, symptoms, routines
   - **Assets** — home inventory, devices, warranties, serial numbers
   For each domain they pick, `references/domain-playbooks.md` has a starter kit: folders, a schema, naming conventions, and an example note. Read it before proposing the blueprint.
3. **Volume and cadence** — a system for 5 notes a week looks different from one for 50. Light use → fewer folders, fewer required fields.
4. **One real example per domain** — "tell me about a task on your plate right now" / "one subscription you pay for". These become the seed notes in Phase 3 and make every later phase concrete instead of hypothetical.
5. **What they've tried before** — if a previous system failed, find out why. Design against that failure.

Start with 2–3 domains even if they're excited about six. A small system that works grows; a sprawling empty scaffold dies. Note the deferred domains for Phase 6.

## Phase 2 — Blueprint

Read `references/conventions.md` and `references/schema-guide.md` now if you haven't. Then present ONE document (in chat, not yet written anywhere) containing:

1. **Folder tree** — the full proposed directory structure with one-line purpose per folder. Include `Schemas/`, `Templates/`, and an `Instructions/` (or `Meta/`) folder alongside the domain folders.
2. **Schemas table** — one row per note type: schema name, note_type, required observations, optional observations, status enum values.
3. **Naming conventions** — title format per note type, date formats, status vocabularies.
4. **Instruction notes** — the startup router plus one instruction note per domain (see `references/conventions.md` for anatomy).
5. **The discipline rules** they'll live by — search before create, exact-casing paths, changelog rows, index updates, bidirectional links — each with a one-line "why".

Walk through it, invite pushback, and iterate. Scale to their answers — but scaling means fewer folders, fewer indexes, and fewer *required* fields, never dropping schemas or observations (see the non-negotiables above). Get an explicit "yes, build it" before Phase 3.

## Phase 3 — Build

Build in this order — later items reference earlier ones:

1. **Schemas** → `Schemas/` folder, one note per type, `validation: warn`. Syntax in `references/schema-guide.md`.
2. **Templates** → `Templates/`, one per note type, matching the schema exactly.
3. **Instruction notes** → per-domain rules notes, then the **startup router** last (it links everything). Full anatomy and a worked example in `references/conventions.md`.
4. **Index notes** → one per domain that needs one (tables of contents; not every domain does).
5. **Migrate existing notes** *(restructure path)* → execute the approved old→new mapping from Phase 2 before seeding anything: move each existing note to its new home, set its note type, add the observations its schema requires, and update indexes as notes land. Archive what doesn't fit — never delete. Phase 3 is not done while anything still sits unorganized at the root.
6. **Seed notes** → 2–3 REAL notes per domain using the examples collected in Phase 1. Never seed with placeholder data — real notes teach the format and are immediately useful; fake ones are noise the user must delete.
7. **Validate** → run `schema_validate` on the seed notes AND any migrated notes; fix anything it flags. Read back the router and one instruction note to confirm links resolve.

Follow the write discipline in `references/conventions.md` throughout — most importantly: search before creating anything, use exact folder casing, and watch write results for duplicate-suffixed permalinks (`-1`, `-2`).

## Phase 4 — Assistant setup

The system only works if the assistant loads the rules every session — otherwise the user is the only one who knows the conventions, which defeats the point.

Read `references/assistant-setup.md` and set up (or hand the user exact text for) a **persistent instruction stub**: a short block in whatever always-loaded mechanism their platform provides (project instructions, custom instructions, system prompt, agent context file) that says, in essence: *"Before any knowledge-base work, read the startup router note in project X and follow its dispatch table."*

Identify what mechanism YOUR platform offers and give concrete, platform-specific steps. If you cannot determine the platform, present the generic stub and the common placements from the reference file. End Phase 4 with the verification test described there (simulate a fresh session; confirm the router gets loaded and followed).

## Phase 5 — Teach

Teach by doing, with their data — not by lecturing. Run short exercises:

1. **Capture** — "Tell me something that came up today" → create the note together, narrating the schema fields and observations as you fill them.
2. **Retrieve** — have them ask for something ("what's on my plate?", "what do I know about X?") → demonstrate `search_notes` and reading via `memory://` links; explain title-search vs semantic search for names.
3. **Update** — change a status, append an observation, add a changelog row — showing `edit_note` for targeted changes vs full overwrites.
4. **Connect** — add a relation between two of their notes; show how `build_context` walks the graph.

Then write a **cheat-sheet note** into their KB (`Instructions/` folder): the phrases they can say, what happens for each, and the core rules. This note is theirs — written for a human, not an assistant.

## Phase 6 — Grow

Close the onboarding by opening doors:

- **Suggest 2–3 specific expansions** drawn from their deferred Phase 1 domains or natural neighbors of what they built (built tasks → suggest meetings; built finances → suggest renewals calendar; built research → suggest a reading log). Frame each as "when you're ready" — never build unrequested.
- **Maintenance cadence** — suggest a periodic (weekly/monthly) review: `schema_diff` for drift, scan for duplicate or orphaned notes, prune stale statuses. If their platform supports scheduled/recurring tasks, offer to set this up.
- **Evolution rule** — when a convention starts to chafe, change the instruction note (with a changelog row), don't silently deviate. The system stays self-describing only if the rules in it stay true.

## Reference files

| File | Read when |
|:--|:--|
| `references/conventions.md` | Before Phase 2. Startup router anatomy, instruction notes, changelogs, indexes, linking, write discipline, failure modes. |
| `references/schema-guide.md` | Before Phase 2. Picoschema syntax, observations, relations, validation workflow. |
| `references/domain-playbooks.md` | Phase 1–2, for each domain the user picks. Starter folders, schemas, naming, example notes per domain. |
| `references/assistant-setup.md` | Phase 4. Persistent-instruction stub patterns per platform + verification test. |

## Related Skills

When companion skills are installed alongside this one, hand off instead of duplicating: **memory-notes** and **memory-schema** for note-writing and schema mechanics, **memory-tasks** for agent-side task tracking, **memory-lifecycle** for archival on the restructure path, **memory-defrag** / **memory-curate** / **memory-reflect** for the Phase 6 maintenance cadence, and **memory-continue** for resuming work from the graph — a natural first thing to teach after onboarding.

Referenced files: 6

memory-reflect3.17 KB

View saved version →

---
name: memory-reflect
description: "Sleep-time memory reflection: review recent conversations and daily notes, extract insights, and consolidate into long-term memory. Use when triggered by cron, heartbeat, or explicit request to reflect on recent activity. Runs as background processing to improve memory quality over time."
---

# Memory Reflect

Review recent activity and consolidate valuable insights into long-term memory.

Inspired by sleep-time compute — the idea that memory formation happens best *between* active sessions, not during them.

## When to Run

- **Cron/heartbeat**: Schedule as a periodic background task (recommended: 1-2x daily)
- **On demand**: User asks to reflect, consolidate, or review recent memory
- **Post-compaction**: After context window compaction events

## Process

### 1. Gather Recent Material

Find what changed recently, then read the relevant files:

```python
# Find recently modified notes — use json format for the complete list
# (text format truncates to ~5 items in the summary)
recent_activity(timeframe="2d", output_format="json")

# Read specific daily notes
read_note(identifier="memory/2026-02-27")
read_note(identifier="memory/2026-02-26")

# Check active tasks
search_notes(note_types=["task"], status="active")
```

### 2. Evaluate What Matters

For each piece of information, ask:
- Is this a **decision** that affects future work? → Keep
- Is this a **lesson learned** or mistake to avoid? → Keep
- Is this a **preference** or working style insight? → Keep
- Is this a **relationship** detail (who does what, contact info)? → Keep
- Is this **transient** (weather checked, heartbeat ran, routine task)? → Skip
- Is this **already captured** in MEMORY.md or another long-term file? → Skip

### 3. Update Long-Term Memory

Write consolidated insights to `MEMORY.md` following its existing structure:
- Add new sections or update existing ones
- Use concise, factual language
- Include dates for temporal context
- Remove or update outdated entries that the new information supersedes

### 4. Log the Reflection

Append a brief entry to today's daily note:
```markdown
## Reflection (HH:MM)
- Reviewed: [list of files reviewed]
- Added to MEMORY.md: [brief summary of what was consolidated]
- Removed/updated: [anything cleaned up]
```

## Guidelines

- **Be selective.** The goal is distillation, not duplication. MEMORY.md should be curated wisdom, not a copy of daily notes.
- **Preserve voice.** If the agent has a personality/soul file, reflections should match that voice.
- **Don't delete daily notes.** They're the raw record. Reflection extracts from them; it doesn't replace them.
- **Merge, don't append.** If MEMORY.md already has a section about a topic, update it in place rather than adding a duplicate entry.
- **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.

Referenced files: 1

memory-research7.54 KB

View saved version →

---
name: memory-research
description: "Research an external subject using web search, synthesize findings into a structured Basic Memory entity. Use when asked to research a company, person, technology, or topic — or when a bare name or URL is provided that implies a research request."
---

# Memory Research

Research an external subject, synthesize what you find, and create a structured Basic Memory entity — with the user's approval.

## When to Use

**Explicit triggers:**
- "Research [subject]"
- "Look up [subject]"
- "What do you know about [subject]?"
- "Evaluate [subject]"

**Implicit triggers (also activate this skill):**
- A bare name: "Terraform"
- A URL: "https://example.com"
- A name with context: "Acme Corp — saw them at the conference"

## Workflow

### Step 1: Web Research

Search for current information across multiple sources. Aim for 3-5 searches to build a well-rounded picture:

```
[subject name] site
[subject name] overview
[subject name] news [current year]
[subject name] [relevant domain keywords]
```

**What to gather by entity type:**

| Entity Type | Key Information |
|-------------|----------------|
| **Organization** | What they do, products/services, stage (startup/growth/public), funding, leadership, headquarters, employee count, notable partnerships or contracts |
| **Person** | Current role, organization, background, expertise, notable work, public presence |
| **Technology** | What it does, who maintains it, maturity, ecosystem, alternatives, adoption |
| **Topic/Domain** | Definition, current state, key players, trends, relevance to user's context |

### Step 2: Check Existing Knowledge

Before proposing a new entity, search Basic Memory:

```python
search_notes(query="Acme Corp")
search_notes(query="acme")
```

Try name variations — full name, abbreviation, acronym, domain name.

If the entity already exists:
- Report what you found in Basic Memory alongside your web research
- Offer to update the existing note with new information
- Use `edit_note` to append new observations or update outdated ones

If the entity doesn't exist, proceed to evaluation.

### Step 3: Evaluate and Summarize

Present your findings in a structured summary. Include all relevant information organized by section:

```markdown
## [Subject Name]

**Type:** [Organization / Person / Technology / Topic]

**Summary:** [2-4 sentences: what this is, why it matters, key distinguishing facts]

**Key Details:**
- [Organized by what's relevant for the entity type]
- [Stage, funding, leadership for orgs]
- [Role, expertise, affiliations for people]
- [Maturity, ecosystem, alternatives for tech]

**Relevance:** [Why this matters to the user — connection to their work, domain, or interests.
If no obvious connection: "No specific connection identified."]

**Sources:**
- [URLs of key sources consulted]
```

### Evaluation Guidelines

**Use hedging language.** Web research is a snapshot, not ground truth:
- "Appears to be", "Based on public information", "Estimated"
- "As of [date]", "According to [source]"
- Never state funding amounts, employee counts, or revenue as exact unless citing a primary source

**Don't fabricate.** If information isn't available, say so:
- "Leadership information not publicly available"
- "Funding details not disclosed"

**Let the user define relevance.** Don't impose a fixed evaluation framework. Instead, highlight facts and let the user draw conclusions. If the user has a specific evaluation rubric (strategic fit, buy/partner/compete, etc.), they'll tell you — apply it when asked.

### Step 4: Propose Entity Creation

After presenting the summary, ask for approval:

```
Create Basic Memory entity for [Subject]?
  Location: [suggested-folder]/[entity-name].md
  Type: [entity type]

  [yes / no / modify]
```

If the user provided context with their request ("saw them at the conference"), include that context in the proposed entity.

### Step 5: Create the Entity

After approval, create a structured note. Adapt the template to the entity type:

#### Organization

```python
write_note(
  title="Acme Corp",
  directory="organizations",
  note_type="organization",
  tags=["organization", "relevant-tags"],
  content="""# Acme Corp

## Overview
[2-3 sentence description from research]

## Products & Services
- [Key offerings discovered in research]

## Background
**Stage:** [Startup / Growth / Public]
**Headquarters:** [Location]
**Employees:** [Estimate, hedged]
**Leadership:** [Key people if found]
**Founded:** [Year if found]

## Observations
- [relevance] Why this entity matters in user's context
- [source] Researched on YYYY-MM-DD
- [additional observations from research findings]

## Relations
- [Link to related entities already in the knowledge graph]"""
)
```

#### Person

```python
write_note(
  title="Jane Smith",
  directory="people",
  note_type="person",
  tags=["person", "relevant-tags"],
  content="""# Jane Smith

## Overview
[Current role and affiliation. Brief background.]

## Background
**Role:** [Title at Organization]
**Expertise:** [Key domains]
**Notable:** [Publications, talks, projects if found]

## Observations
- [role] Title at Organization
- [expertise] Key technical or domain expertise
- [source] Researched on YYYY-MM-DD

## Relations
- works_at [[Organization]]"""
)
```

#### Technology

```python
write_note(
  title="Technology Name",
  directory="concepts",
  note_type="concept",
  tags=["concept", "technology", "relevant-tags"],
  content="""# Technology Name

## Overview
[What it is and what problem it solves]

## Key Details
**Maintained by:** [Organization or community]
**Maturity:** [Experimental / Stable / Mature]
**License:** [If applicable]
**Alternatives:** [Comparable tools or approaches]

## Observations
- [definition] What this technology does in one sentence
- [maturity] Current state and adoption level
- [source] Researched on YYYY-MM-DD

## Relations
- [Link to related concepts, tools, or projects in the knowledge graph]"""
)
```

Adapt these templates freely. The key elements are: note_type/tags parameters, an overview, structured details, observations with categories, and relations.

### Step 6: Store Source Context

If the user provided context with their request, capture it in the entity:

```python
# User said: "Acme Corp — saw their demo at the conference last week"
edit_note(
  identifier="Acme Corp",
  operation="append",
  section="Observations",
  content="- [context] Saw their demo at conference, week of 2026-02-17"
)
```

This context is often the most valuable part — it's the user's relationship to the entity, which web research can't provide.

## Guidelines

- **Always web search.** Don't rely on training data alone. Research should reflect current, verifiable information.
- **Search Basic Memory first.** Check for existing entities before creating new ones. Update rather than duplicate.
- **Hedge uncertain information.** Use qualifiers for estimates, unverified claims, and inferred details.
- **Store source URLs.** Include the URLs you consulted, either in observations or a Sources section. This enables the user to verify and dig deeper.
- **Get approval before creating.** Present your findings and let the user decide whether to create the entity and what to include.
- **Capture user context.** If the user told you *why* they're researching (met at a conference, evaluating as a vendor, etc.), that context belongs in the entity.
- **Don't over-research.** 3-5 web searches is usually enough. The goal is a useful knowledge graph entry, not an exhaustive report.
- **Link to existing knowledge.** Relate the new entity to things already in the knowledge graph. Connections compound value.

Referenced files: 1

memory-schema7.61 KB

View saved version →

---
name: memory-schema
description: "Schema lifecycle management for Basic Memory: discover unschemaed notes, infer schemas, create and edit schema definitions, validate notes, and detect drift. Use when working with structured note types (Task, Person, Meeting, etc.) to maintain consistency across the knowledge graph."
---

# Memory Schema

Manage structured note types using Basic Memory's Picoschema system. Schemas define what fields a note type should have, making notes uniform, queryable, and validatable.

## When to Use

- **New note type emerging** — you notice several notes share the same structure (meetings, people, decisions)
- **Validation check** — confirm existing notes conform to their schema
- **Schema drift** — detect fields that notes use but the schema doesn't define (or vice versa)
- **Schema evolution** — add/remove/change fields as requirements evolve
- **On demand** — user asks to create, check, or manage schemas

## Picoschema Syntax Reference

Schemas are defined in YAML frontmatter using Picoschema — a compact notation for describing note structure.

### Basic Types

```yaml
schema:
  name: string, person's full name
  age: integer, age in years
  score: number, floating-point rating
  active: boolean, whether currently active
```

Supported types: `string`, `integer`, `number`, `boolean`.

### Optional Fields

Append `?` to the field name:

```yaml
schema:
  title: string, required field
  subtitle?: string, optional field
```

### Enums

Use `(enum)` with a list of allowed values:

```yaml
schema:
  status(enum, current state): [active, blocked, done, abandoned]
```

Optional enum:

```yaml
schema:
  priority?(enum, task priority): [low, medium, high, critical]
```

### Arrays

Use `(array)` for list fields:

```yaml
schema:
  tags(array): string, categorization labels
  steps?(array): string, ordered steps to complete
```

### Relations

Reference other entity types directly:

```yaml
schema:
  parent_task?: Task, parent task if this is a subtask
  attendees?(array): Person, people who attended
```

Relations create edges in the knowledge graph, linking notes together.

### Validation Settings

```yaml
settings:
  validation: warn    # warn (log issues) or error (strict)
```

### Complete Example

```yaml
---
title: Meeting
type: schema
entity: Meeting
version: 1
schema:
  topic: string, what was discussed
  date: string, when it happened (YYYY-MM-DD)
  attendees?(array): Person, who attended
  decisions?(array): string, decisions made
  action_items?(array): string, follow-up tasks
  status?(enum, meeting state): [scheduled, completed, cancelled]
settings:
  validation: warn
---
```

## Discovering Unschemaed Notes

Look for clusters of notes that share structure but have no schema:

1. **Search by type**: `search_notes(query="type:Meeting")` — if many notes share a `type` but no `schema/Meeting.md` exists, it's a candidate.

2. **Infer a schema**: Use `schema_infer` to analyze existing notes and generate a suggested schema:
   ```python
   schema_infer(noteType="Meeting")
   schema_infer(noteType="Meeting", threshold=0.5)  # fields in 50%+ of notes
   ```
   The threshold (0.0–1.0) controls how common a field must be to be included. Default is usually fine; lower it to catch rarer fields.

3. **Review the suggestion** — the inferred schema shows field names, types, and frequency. Decide which fields to keep, make optional, or drop.

## Creating a Schema

Write the schema note to `schema/<EntityName>`:

```python
write_note(
  title="Meeting",
  directory="schema",
  note_type="schema",
  metadata={
    "entity": "Meeting",
    "version": 1,
    "schema": {
      "topic": "string, what was discussed",
      "date": "string, when it happened",
      "attendees?(array)": "Person, who attended",
      "decisions?(array)": "string, decisions made"
    },
    "settings": {"validation": "warn"}
  },
  content="""# Meeting

Schema for meeting notes.

## Observations
- [convention] Meeting notes live in memory/meetings/ or as daily entries
- [convention] Always include date and topic
- [convention] Action items should become tasks when complex"""
)
```

### Key Principles

- **Schema notes live in `schema/`** — one note per entity type
- **`note_type="schema"`** marks it as a schema definition
- **`entity: Meeting`** in metadata names the type it applies to
- **`version: 1`** in metadata — increment when making breaking changes
- **`settings.validation: warn`** is recommended to start — it logs issues without blocking writes

## Validating Notes

Check how well existing notes conform to their schema:

```python
# Validate all notes of a type
schema_validate(noteType="Meeting")

# Validate a single note
schema_validate(identifier="meetings/2026-02-10-standup")
```

**Important:** `schema_validate` checks for schema fields as **observation categories** in the note body — e.g., a `status` field expects `- [status] active` as an observation. Fields stored only in frontmatter metadata won't satisfy validation. To pass cleanly, include schema fields as both frontmatter values (for metadata search) and observations (for schema validation).

Validation reports:
- **Missing required fields** — the note lacks a field the schema requires (as an observation category)
- **Unknown fields** — the note has fields the schema doesn't define
- **Type mismatches** — a field value doesn't match the expected type
- **Invalid enum values** — a value isn't in the allowed set

### Handling Validation Results

- **`warn` mode**: Review warnings periodically. Fix notes that are clearly wrong; add optional fields to the schema for legitimate new patterns.
- **`error` mode**: Use for strict schemas where conformance matters (e.g., automated pipelines consuming notes).

## Detecting Drift

Over time, notes evolve and schemas lag behind. Use `schema_diff` to find divergence:

```python
schema_diff(noteType="Meeting")
```

Diff reports:
- **Fields in notes but not in schema** — candidates for adding to the schema (as optional)
- **Schema fields rarely used** — consider making optional or removing
- **Type inconsistencies** — fields used as different types across notes

## Schema Evolution

When note structure changes:

1. **Run diff** to see current state: `schema_diff(noteType="Meeting")`
2. **Update the schema note** via `edit_note`:
   ```python
   edit_note(
     identifier="schema/Meeting",
     operation="find_replace",
     find_text="version: 1",
     content="version: 2",
     expected_replacements=1
   )
   ```
3. **Add/remove/modify fields** in the `schema:` block
4. **Re-validate** to confirm existing notes still pass: `schema_validate(noteType="Meeting")`
5. **Fix outliers** — update notes that don't conform to the new schema

### Evolution Guidelines

- **Additive changes** (new optional fields) are safe — no version bump needed
- **Breaking changes** (new required fields, removed fields, type changes) should bump `version`
- **Prefer optional over required** — most fields should be optional to start
- **Don't over-constrain** — schemas should describe common structure, not enforce rigid templates
- **Schema as documentation** — even if validation is set to `warn`, the schema serves as living documentation for what notes of that type should contain

## Workflow Summary

```
1. Notice repeated note structure → infer schema (schema_infer)
2. Review + create schema note   → write to schema/ (write_note)
3. Validate existing notes       → check conformance (schema_validate)
4. Fix outliers                  → edit non-conforming notes (edit_note)
5. Periodically check drift      → detect divergence (schema_diff)
6. Evolve schema as needed       → update schema note (edit_note)
```

Referenced files: 1

memory-tasks5.48 KB

View saved version →

---
name: memory-tasks
description: "Task management via Basic Memory schemas: create, track, and resume structured tasks that survive context compaction. Uses BM's schema system for uniform notes queryable through the knowledge graph."
---

# Memory Tasks

Manage work-in-progress using Basic Memory's schema system. Tasks are just notes with `type: Task` — they live in the knowledge graph, validate against a schema, and survive context compaction.

## When to Use

- **Starting multi-step work** (3+ steps, or anything that might outlast the context window)
- **After compaction/restart** — search for active tasks to resume
- **Pre-compaction flush** — update all active tasks with current state
- **On demand** — user asks to create, check, or manage tasks

## Task Schema

Tasks use the BM schema system (SPEC-SCHEMA). The schema note lives at `memory/schema/Task.md`:

```yaml
---
title: Task
type: schema
entity: Task
version: 1
schema:
  description: string, what needs to be done
  status?(enum, current state): [active, blocked, done, abandoned]
  assigned_to?: string, who is working on this
  steps?(array): string, ordered steps to complete
  current_step?: integer, which step number we're on (1-indexed)
  context?: string, key context needed to resume after memory loss
  started?: string, when work began
  completed?: string, when work finished
  blockers?(array): string, what's preventing progress
  parent_task?: Task, parent task if this is a subtask
settings:
  validation: warn
---
```

## Creating a Task

When work qualifies, create a task note. Use `write_note` with `note_type="Task"` and put queryable fields in `metadata`:

```python
write_note(
  title="Descriptive task name",
  directory="tasks",
  note_type="Task",
  metadata={
    "status": "active",
    "priority": "high",
    "current_step": 1,
    "steps": ["First step", "Second step", "Third step"]
  },
  tags=["task"],
  content="""# Descriptive task name

## Observations
- [description] What needs to be done, concisely
- [status] active
- [assigned_to] claude
- [current_step] 1

## Steps
1. [ ] First concrete step
2. [ ] Second concrete step
3. [ ] Third concrete step

## Context
What future-you needs to pick up this work. Include:
- Key file paths and repos involved
- Decisions already made and why
- What was tried and what worked/didn't
- Where to look for related context"""
)
```

**Why both frontmatter and observations?** Fields in `metadata` (stored as frontmatter) power `search_notes` with `metadata_filters`. Fields as observations (`- [status] active`) power `schema_validate`. Include queryable fields in both places for full coverage.

### Key Principles

- **Steps are concrete and checkable** — "Implement X in file Y", not "figure out stuff"
- **Context is for post-amnesia resumption** — Write it as if explaining to a smart person who knows nothing about what you've been doing
- **Relations link to other entities** — `parent_task [[Other Task]]`, `related_to [[Some Note]]`
- **`note_types` is case-sensitive** — `write_note(note_type="Task")` stores the type as lowercase `task` in frontmatter. Use `note_types=["task"]` (lowercase) in search queries.

## Resuming After Compaction

On session start or after compaction:

1. **Search for active tasks:**
   ```python
   search_notes(note_types=["task"], status="active")
   ```

2. **Read the task note** to get full context

3. **Resume from `current_step`** using the `context` field

4. **Update as you progress** — increment `current_step`, update context, check off steps

## Updating Tasks

As work progresses, update the task note:

```markdown
## Steps
1. [x] First step — done, resulted in X
2. [x] Second step — done, changed approach because Y
3. [ ] Third step — next up

## Context
Updated context reflecting current state...
```

Update frontmatter too:
```yaml
current_step: 3
```

## Completing Tasks

When done:
```yaml
status: done
completed: YYYY-MM-DD
```

Add a brief summary of what was accomplished and any follow-up needed.

## Pre-Compaction Flush

When a compaction event is imminent:

1. Find all active tasks: `search_notes(note_types=["task"], status="active")`
2. For each, update:
   - `current_step` to reflect actual progress
   - `context` with everything needed to resume
   - Step checkboxes to show what's done
3. This is **critical** — context not written down is context lost

## Querying Tasks

With BM's schema system, tasks are fully queryable:

| Query | What it finds |
|-------|--------------|
| `search_notes(note_types=["task"])` | All tasks |
| `search_notes(note_types=["task"], status="active")` | Active tasks |
| `search_notes(note_types=["task"], status="blocked")` | Blocked tasks |
| `search_notes(note_types=["task"], metadata_filters={"assigned_to": "claude"})` | My tasks |
| `search_notes("blockers", note_types=["task"])` | Tasks with blockers |
| `schema_validate(noteType="Task")` | Validate all tasks against schema |
| `schema_diff(noteType="Task")` | Detect drift between schema and actual task notes |

## Guidelines

- **One task per unit of work** — Don't cram multiple projects into one task
- **Externalize early** — If you think "I should remember this", write it down NOW
- **Context > steps** — Steps tell you what to do; context tells you why and how
- **Close finished tasks** — Don't leave completed work as `active`
- **Link related tasks** — Use `parent_task [[X]]` or relations to connect related work
- **Schema validation is your friend** — Run `schema_validate(noteType="Task")` periodically to catch incomplete tasks

Referenced files: 1

Technical details
First seen
Sep 30, 2026 · 22:02 UTC
Last seen
Oct 1, 2026 · 12:00 UTC
Collection status
Collected

plugin_asdk_app_6a49590bf6348191a16c0b87ca6b01b4

Download listing JSON