Skill instructions
basic-memory5.29 KB
View saved version →
---
name: basic-memory
description: "Use the user's Basic Memory knowledge base: find notes for context, save linked notes, resume work, run Memory Quest. Use when a task needs prior notes, should be remembered, or mentions Memory Quest."
---
# Basic Memory
Basic Memory is the user's knowledge base: plain Markdown notes that you read and
write through the Basic Memory tools. Notes carry categorized observations and link
to each other through relations, so they form a graph that outlasts any one
conversation. What one session learns, the next one can find.
## Core habits
- **Search before you write.** Call `bm_search` before creating a note, and update
the note you find instead of starting a duplicate.
- **Load context on purpose.** Use `bm_read` for a note you know, and
`bm_context` with a `memory://` URL to pull in a note with its related notes.
- **Write connected notes.** Give each note observations (`- [decision] ...`) and
relations (`- relates_to [[Other Note]]`) so it joins the graph.
- **Ask before saving.** Say what you would save and where, and write only after the
user agrees, unless they have told you otherwise.
- **Don't overwrite by accident.** Pass `overwrite: false` to `bm_write` unless you
are deliberately replacing a note you have read in full.
- **Name the project.** Discover projects with `bm_project(command="list")` when
needed, then pass `project` on every note, folder, context and schema call and
on recent activity. A project name, `workspace/project`, or external ID works;
a qualified path does not replace it. Search requires `project`, `projects`, or
`all_projects=True`. Discovery and bundled manuals need no scope.
## Routing
For these requests, read the listed file in full before acting, then follow it.
Paths are relative to this skill's folder.
| Request | Read in full first |
|---|---|
| Create, run, and check Basic Memory Cloud agents: notes with type agent whose text is instructions. Use when asked to automate work on notes, run an agent, or see how a run went. | `references/memory-agents.md` |
| Capture a working thread's current state into one coherent Basic Memory note; on re-capture, rewrite it in place. Use mid- or end-of-thread when decisions, insights, or context are worth keeping. | `references/memory-capture.md` |
| Write Basic Memory notes that render as charts, tables, boards, and live views with `::bm-*` Comark components. Use when a note reads better as a figure or board, or already has `::bm-*` directives. | `references/memory-comark.md` |
| Resume prior work by rebuilding context from the Basic Memory graph via memory:// URLs, recent activity, and search. Use at session start or on 'continue with...', 'back to...', 'where were we?' | `references/memory-continue.md` |
| Curate the Basic Memory graph: link orphan notes, propose typed relations, merge duplicates, audit tags and folders, build hub notes. Use to organize and connect a knowledge base as notes accumulate. | `references/memory-curate.md` |
| Check local Basic Memory projects with bm doctor, explain the findings, and run the suggested fixes once the user agrees. Use when search misses or repeats notes, or a save looks lost. | `references/memory-doctor.md` |
| Turn meeting transcripts, conversation logs, or pasted documents into structured Basic Memory notes: match existing entities, propose new ones with approval, and capture action items. | `references/memory-ingest.md` |
| Manage note status transitions in Basic Memory: archive completed work, move notes between status folders, update frontmatter. Use when marking items complete or archiving entities. | `references/memory-lifecycle.md` |
| Search Basic Memory notes by custom frontmatter fields with equality, range, array, and nested filters. Use when finding notes by status, priority, confidence, or any YAML field, not free text. | `references/memory-metadata-search.md` |
| How to write well-structured Basic Memory notes: frontmatter, categorized ob
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 22 — file references are metadata, not package contents.
memory-agents7.33 KB
View saved version →
---
name: memory-agents
description: "Create, run, and check Basic Memory Cloud agents: notes with type agent whose text is instructions. Use when asked to automate work on notes, run an agent, or see how a run went."
---
# Memory Agents
A Basic Memory Cloud agent is a note. Its frontmatter says `type: agent`, and its
body is the instructions. Running it on another note (the target) starts a
short-lived agent in Cloud that reads the target, works through the Basic Memory
tools, and changes notes as its instructions say.
Agents run in Basic Memory Cloud only, on plans that include them. A local
Basic Memory has no agent tools. Confirm the connected server exposes `bm_agent_list` and `bm_agent_run`
before starting this workflow.
## When to Use
- The user wants recurring work on their notes done for them: follow up on
meetings, link new notes, tidy a folder, write a weekly digest
- Asked to create, change, run, or turn off an agent
- Asked how an agent run went, what it changed, or why it did not run
## Tools
| Tool | Does |
|---|---|
| `bm_agent_list()` | The project's agents and how their recent runs went |
| `bm_agent_run()` | Starts an agent on a note; returns the run id |
| `bm_agent_get()` | One run: status, notes changed, and the agent's last reply |
| `bm_agent_runs()` | Recent runs, newest first, optionally for one agent |
| `bm_agent_mark()` | Mark a run `kept` or `dismissed` with `run_id` and `decision` |
Create agents with `bm_write`; edit existing agents with the exposed `bm_edit_*` tools. Read the note first and pass its checksum as `expected_checksum`. There is no separate
agent tool for that.
## Write an Agent
```markdown
---
title: Meeting follow-up
type: agent
enabled: true
watch:
paths:
- meetings/
---
Load the memory-ingest and memory-tasks skills before you start.
Read the meeting note you run on.
- For each action item, create a task note in `tasks/` with its owner and a
relation back to the meeting note. Check `tasks/` first and link an existing
task instead of making a duplicate.
- Add a `## Summary` section to the meeting note. If it has one, leave it.
Reply with the tasks you created or linked.
```
Frontmatter:
| Field | Required | Meaning |
|---|---|---|
| `type` | yes | `agent` |
| `title` | yes | The agent's name |
| `enabled` | yes | `false` keeps it from running, by hand or by watch |
| `watch` | no | Starts the agent when a person creates a note under these paths |
| `description` | no | One line shown with the agent |
`watch.paths` takes folders (`meetings/`) or globs over the file path
(`meetings/*.md`), at most 20, all inside the project. `watch.events` defaults
to `[create]`, the only event so far. Do not write `on:` for events: YAML reads
that key as `true`.
Agents always write: their output is notes, and every change they make is a
note version you can revert. An agent changes notes only in its own project, and
it runs only if both the person who last edited the agent note and the person the
run is for can edit that project. An agent note last edited by another agent
cannot run. An old `access` key in an agent note is ignored.
### Instructions that work
- **Scope to the target note.** The agent starts from the note it runs on. Say
what that note is (a meeting note, a hub note, any note) and how far to look
from it.
- **Name the skills to load.** Agents can load the Basic Memory skills, for
example `Load the memory-curate skill before you start.`
- **Say where new notes go** and how to avoid duplicates: check the folder first,
link what exists.
- **Keep existing content.** Ask the agent to read each note before changing it.
Cloud already refuses an edit that does not name the revision it read.
- **Ask for a reply.** The last reply is the run's summary: what it created,
linked, or left alone, and anything it was unsure about.
- **Keep each run small.** A run has about seven minutes, including startup.
Split large jobs across several agents or severaPreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 uPreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 — file references are metadata, not package contents.
memory-comark8.78 KB
View saved version →
---
name: memory-comark
description: "Write Basic Memory notes that render as charts, tables, boards, and live views with `::bm-*` Comark components. Use when a note reads better as a figure or board, or already has `::bm-*` directives."
---
# Memory Comark
Basic Memory notes can carry small, safe components written as Comark block
directives (`::bm-bars{...}` … `::`). Basic Memory Cloud draws them in Notes, the
Wiki, and shared pages. Everywhere else (a local editor, GitHub, an agent's raw
read) the same Markdown still reads as an ordinary list, table, or paragraph, so
a component never hides content.
Use a component when its shape says more than a sentence or a list would. Keep
prose primary: one figure per idea, at most two per section, with a sentence
between them that says what the figure shows.
The full vocabulary, every prop, and every data grammar are in
[references/components.md](references/components.md). Read it before using a
component you have not used before.
## Pick a component
Most notes need only these. The reference has the rest (39 in total).
| You want to show | Use |
| --- | --- |
| One or a few headline numbers | `bm-stat` |
| A comparison of a few values | `bm-bars` |
| A short ranked list | `bm-rank` |
| A small data table | `bm-table` |
| Progress toward a whole | `bm-meter` |
| A trend without axes | `bm-spark` |
| Steps that drop off | `bm-funnel` |
| A task list | `bm-check` |
| Work in lanes (now, next, later) | `bm-kanban` |
| Events in order | `bm-timeline` |
| A framed claim or summary | `bm-frame` |
| A short path (`a → b → c`) | `bm-flow` |
| A real graph, sequence, or state machine | a fenced ```mermaid block (not a component) |
If nothing fits, write prose or a plain Markdown table. Never invent a
component: an unknown name such as `::bm-pie` is not drawn and shows as raw text.
## Write a component
Every component opens with `::bm-name{attributes}` on its own line and closes
with `::` on its own line.
```markdown
The queue rewrite more than doubled steady-state throughput.
::bm-bars{title="Throughput" caption="Before and after the queue rewrite"}
- Before: 42/s
- **After: 96/s**
::
```
Rules that matter:
- **Data goes in the body as Markdown**, not in an attribute: `- label: value`
rows, a table for grids. **Bold** marks the current or chosen row, *italic*
recedes, ` — note` adds a side note.
- **Attribute values are double-quoted and cannot contain `"`.** There is no
escape. Inside a `query`, quote phrases with single quotes:
`query="search 'queue rewrite'"`.
- **Task state stays in Markdown.** Use `- [ ]` and `- [x]` inside `bm-check` and
`bm-kanban`; people can tick boxes from the rendered note.
- **Never put HTML, scripts, styles, or classes in a note**, and never wrap a
component in a code fence (a fenced block stays literal code).
- **Use only registered props.** An unknown attribute produces `prop-unknown`
in a warning frame with the original source and registered props; it is never
silently dropped.
A checklist and a board:
```markdown
::bm-check{title="Launch"}
- [x] Freeze the schema
- [ ] Write the migration note — due Friday
::
::bm-kanban{title="Roadmap"}
### Now
- **Billing page**
- [ ] Usage emails
### Next
- *Partner portal*
::
```
## Live views over the knowledge base
A component with a `query` attribute shows current data from the project it
lives in. Prefer a live view to a hand-copied number when the note describes its
own knowledge base, because copied counts go stale.
```markdown
::bm-stat{label="Open decisions" query="notes | where type == decision and status == open | count"}
::
::bm-bars{title="Open decisions by owner" query="notes | where type == decision and status != done | group owner | sort count desc"}
::
::bm-table{title="Due soon" query="notes | where tags contains infra and due < 2026-10-15 | fields title, owner, due | sort due"}
::
::bm-timeline{title="Recent edits" query="activity 7d"}
::
::bm-rank{title="Related noPreview of the first 4,000 characters. Read full instructions →
Referenced files: 2 — file references are metadata, not package contents.
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:
`Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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="Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 — file references are metadata, not package contents.
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 Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 t
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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="""#Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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"Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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]
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 not
Preview of the first 4,000 characters. Read full instructions →
Referenced files: 6 — file references are metadata, not package contents.
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 — file references are metadata, not package contents.
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. AdapPreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 mePreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.
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 anPreview of the first 4,000 characters. Read full instructions →
Referenced files: 1 — file references are metadata, not package contents.