Imported from csansoon/skillset (
skills/brain/SKILL.md). Install upstream withnpx skills add csansoon/skillset --skill brain. Copyright stays with the author.
SKILL: brain
The BRAIN is a personal wiki about the user's life, organized as a folder of interconnected Markdown files. You use your file read/write tools to navigate and update it. This skill tells you everything you need to know: how it is structured, how to read it, how to write to it, and what scripts are available to query it efficiently.
0. Quick lookup (most common operation)
Most of the time, you just need to check what you know about someone or something:
- Read
brain/_INDEX.md— get the lay of the land, find top-level entities - If you need a specific type, read
brain/<type>/_INDEX.md— key entities and tags for that type - Read the entity file — get full context
- Done
For cross-cutting queries (searching across all files, listing by tag, etc.), use the
scripts in section 10. All scripts run from the workspace root as
python3 skills/brain/<script>.py.
The golden rule: Never answer a question about a person, place, or project from pure recall if a BRAIN file exists. Always check.
Silent writes: Update the brain (and daily memory when you log alongside it) whenever it helps — but do not tell the user you're saving, filing, or taking notes unless they explicitly asked for confirmation or you need permission for sensitive or ambiguous facts. Your reply should be substance (answer, question, reaction), not commentary on the write operation.
1. Location and structure
The BRAIN lives at brain/ inside your workspace (default script path: ./brain from cwd, or set BRAIN_ROOT / OPENCLAW_WORKSPACE).
brain/
├── _INDEX.md ← Global overview: type directory, top key entities
├── people/
│ ├── _INDEX.md ← Key people + people-specific tags
│ ├── john-doe.md
│ └── ...
├── events/
│ ├── _INDEX.md ← Key events + event-specific tags
│ └── ...
├── places/
│ ├── _INDEX.md
│ └── ...
├── projects/
│ ├── _INDEX.md
│ └── ...
├── topics/
│ ├── _INDEX.md
│ └── ...
└── <new-type>/
├── _INDEX.md ← Every type folder gets its own index
└── ...
These are the starting types. If something doesn't fit — create a new folder and type. A recipe collection, a media list, a health log — whatever makes sense.
Folder names vs type: values
Folder names are plural (people/, events/), but the type: field in frontmatter
is singular (person, event). This is intentional — folders name collections,
types describe what an entity is.
All scripts accept either form with --type: --type people and --type person both
work. For custom types, keep the same convention: plural folder (recipes/), singular
type (recipe).
The golden rule of folders
Folders categorize by what a note is (its type), not by who mentioned it or
what context it came up in. A recipe a friend taught the user goes in recipes/, not
people/. A trip to Rome goes in events/, not people/. Sue's file in people/
links to both via wikilinks — that's how connections work.
2. Finding things: the two-tier index model
The brain uses a two-tier index system:
Global index: brain/_INDEX.md
Your starting point. Contains:
- A type directory — what each type folder holds and when to use it
- The most important entities overall — the handful of pages that matter across the whole brain (e.g., the owner's own page)
- How to navigate further
This is NOT an exhaustive list. It only lists entities that are globally significant.
Per-type index: brain/<type>/_INDEX.md
Each type folder has its own index. Contains:
- Key entities in that type — the most important pages, not all of them
- Tags used within that type — with short descriptions of what each tag means
Example format for a per-type index:
# People Index
## Key people
- [[people/john-doe]] — placeholder self-page (example only)
- [[people/jordan-lee]] — partner
## Tags
| Tag | Meaning |
|---|---|
| `family` | Blood relatives or family-by-choice |
| `close` | People the user has a close personal relationship with |
When to use what
| Need | Action |
|---|---|
| Starting a session | Read brain/_INDEX.md |
| Looking up a specific type | Read brain/<type>/_INDEX.md |
| Finding a specific entity by name | Use search.py |
| Listing all entities of a type | Use list.py --type <type> |
| Listing entities by tag | Use list.py --tag <tag> |
| Finding the most connected entities | Use list.py --sort backlinks |
If an entity is not in any index, it may still exist — use the scripts to search.
3. File format
Every BRAIN file follows this structure:
--- ← YAML frontmatter (always present)
type: person ← Required: singular form (person, event, place...)
aliases: [Sue, Sue Smith] ← All names this entity is known by
tags: [family] ← For filtering and categorization (don't repeat the type here)
[extra fields as needed] ← See section 4
updated: YYYY-MM-DD ← Date of last modification
---
# Full Name / Title ← H1: canonical name
## Section heading ← Sections vary by type (see section 5)
Content with [[wikilinks]] ← Every entity reference is a wikilink
## Another section
More content...
Wikilink format
- In body text:
[[people/sue-smith|Sue]](path | display alias) - In frontmatter:
"[[places/barcelona]]"(quoted string) - Bare name when unambiguous and a redirect exists:
[[Sue]] - Never write a person's name or place name as plain text when a file exists for them
4. Frontmatter
Every file has YAML frontmatter. Four fields are always required:
type: <type> # singular form: person, event, place, project, topic, or custom
aliases: [Name, Nickname] # all names this entity is known by
tags: [attribute, ...] # categorization tags — do NOT include the type (see section 5)
updated: YYYY-MM-DD # last modification date
Beyond those four, add whatever fields make sense for the entity. Think about what would be useful to query or filter on later.
Built-in types and their common fields
These are the starting types. Their extra fields are suggestions, not requirements — use what applies, skip what doesn't, add what's missing.
| Type | Common extra fields |
|---|---|
person |
name, relation, birthday, location (wikilink) |
event |
date-start, date-end, location (wikilink), people (wikilink list) |
place |
country |
project |
status (active/paused/completed/abandoned), started |
topic |
(none beyond the required three) |
Custom types
When something doesn't fit the built-in types, create a new type:
- Create the folder:
brain/<type-name>/ - Create
brain/<type-name>/_INDEX.mdwith key entities and type-specific tags - Use
type: <type-name>in frontmatter - Add whatever extra fields make sense for that type
- Add the new type to the global
brain/_INDEX.mdtype directory
Examples of custom types that might emerge organically: recipes, media,
health, finance, gear, subscription. Let them appear when the need is real — don't
pre-create categories.
Subscription notes
Use subscription for recurring paid services or memberships the user keeps over time. A subscription file should capture the stable description: service name, plan, billing cadence, usual price, status, notes on whether they use it, and any other context that would help future reviews.
Default assumptions are fine when the user already implied them. For example, if they say all subscriptions normally charge the main account, you can set paid-from to that default without re-asking every time. Tags and category-like labels can be inferred from the known service, asked directly, or looked up when helpful.
Boundary with finances: the subscription file is the inventory and description. Actual charges, refunds, and price changes observed in real money movement belong in finances/.
5. Tags
Tags handle cross-cutting attributes that folders can't. Folders force one category;
tags allow many. A person can be family and close. A place can be favorite and
food. An event can be travel and memorable. This is how you build queryable
dimensions across the BRAIN.
How to tag
- Do NOT include the entity type as a tag — the
type:field already handles that, and--typefiltering uses it. Addingpersonas a tag on a person is pure redundancy. - Only add tags that provide additional categorization beyond the type
- Tags are lowercase, no spaces, and as specific as useful
- It is perfectly fine for an entity to have
tags: []if no cross-cutting attribute applies
What to tag
Think about future queries. If you'd ever want to ask "show me all X," there should
be a tag for X. Tags are type-specific — each type's _INDEX.md lists the tags used
within that type and their meaning. When you create a new tag, add it to the relevant
type's _INDEX.md tag table.
Don't create tags for things that only apply to one entity — that information belongs in the entity's file and its relationships, not in a tag. Tags are for grouping multiple entities together.
Tags vs folders
- Folders answer "what is this?" → one answer per entity (person, place, event...)
- Tags answer "what is this like?" → many answers per entity
A restaurant the user loves: folder is places/, tags are [favorite, food].
Their sister: folder is people/, tags are [family, close].
A random conference contact: folder is people/, tags are [coworker].
Someone the user just met: folder is people/, tags are [] — and that's fine.
Querying by tag
python skills/brain/list.py --tag close # all close people/entities
python skills/brain/list.py --tag family # all family members
python skills/brain/list.py --tag favorite # all favorites across types
6. How to structure a file's body
There are no fixed templates. Every file is different — structure should emerge from the content, not from a checklist. Think like a wiki editor: a page about the user's mother looks nothing like a page about a coworker he met once at a conference.
Hard requirements
- H1 title — the canonical name of the entity
- At least one content section (
## Something) with actual information
Everything else is up to you.
Principles
- Only create sections you can fill. If you only know someone's name and how the user
met them, write one
## Contextsection. Don't scaffold six empty headings. - Sections should describe what they contain, not follow a formula. A close family
member might need
## Relationship,## Shared memories,## Contact. A professional acquaintance might just need## How they know the user. - Let structure grow with content. When new information arrives that doesn't fit existing sections, create a new section with a clear heading. When a section gets too long, split it.
- Use subsections (
###) when a section has natural subdivisions. A project with multiple phases, a person with distinct life chapters, a place with different contexts. - Keep a
## Personal notessection (or similar) for subjective impressions, opinions, and provisional observations. When notes become confirmed facts, promote them into the relevant body section.
Examples of how the same type can look completely different
A close family member (people/mary-williams.md):
# Mary Williams
## Who she is
The user's mother. Lives in [[places/springfield]].
## Family
- Married to [[people/sam-williams|Sam]]
- Mother of [[people/john-doe]] and [[people/sue-smith|Sue]]
## Her cooking
The user considers her lasagna top tier. Also known for...
## Personal notes
Always calls on Sunday evenings. Worries about them eating well.
A brief professional contact (people/john-doe.md):
# John Doe
## Context
Backend engineer at Vercel. The user met him at KubeCon 2025. They talked
about [[topics/opentelemetry]] instrumentation for serverless functions.
Exchanged LinkedIn contacts. (mentioned 2025-06-14)
A city the user visited once (places/rome.md):
# Rome
## Overview
Capital of Italy. Visited for [[events/2025-rome-trip]].
A city the user lives in (places/barcelona.md):
# Barcelona
## Overview
Home city since 2018. Lives in the 08013 area.
## Daily life
Works at the [[projects/acme-corp]] office in 08019. Commutes by metro.
## Favorite spots
- Harbor Bistro — seafood, goes with friends
- Green Bowl Cafe — healthy lunch near the office
## Visits
- [[events/2025-rome-trip]] — departed from BCN airport
Notice: same type (place), completely different depth and structure. The content
dictates the shape, not the type.
7. Formatting
Use markdown formatting to make pages scannable and readable. A well-formatted page is easier to skim and update than a wall of plain text. Don't over-format — let the content guide when formatting helps.
When to use what
| Format | Use for | Example |
|---|---|---|
| Bold | Key facts that should jump out when scanning | Backend engineer at Acme Corp |
| Italics | Subjective impressions, provisional info, soft context | Seems interested in Rust, mentioned it twice |
> blockquote |
Direct quotes from the user about someone/something | > "Best apple pie I've ever had" |
| Bullet lists | Enumerating connections, preferences, related items | - [[people/sue-smith]], - [[people/sam-williams]] |
| Tables | Structured comparisons, timelines, multi-field data | Career history, project milestones |
> [!NOTE] |
Important context that applies broadly to the entity | A note about someone's communication style |
> [!TIP] |
Practical reminders for future interactions | Best time to call, gift preferences |
> [!WARNING] |
Sensitive context to be careful with | Sore topics, things not to bring up |
Callout syntax
> [!NOTE]
> Sue prefers SMS over email for quick questions. Message her there.
> [!TIP]
> The user's mom loves flowers — good gift idea for her birthday.
> [!WARNING]
> Don't mention the 2024 incident — it's a sore topic.
Guiding principle
Format to improve scannability. Bold the facts you'd want to find quickly. Use lists when there are multiple items. Use tables when data has parallel structure. Use callouts when context is important enough to stand out visually. If plain text reads fine, leave it plain.
8. Writing protocol: what to do when you receive new information
Step 1 — Identify all affected entities
Given any new information, ask:
- What is the primary entity? (the main subject)
- What other entities are mentioned or affected?
- A person →
people/ - A place →
places/ - An event →
events/ - A project →
projects/ - A topic →
topics/ - Something else → existing custom type, or create a new one if it makes sense
- A person →
Step 2 — Determine which section in each file
Use the section structure above. Every piece of information has exactly one right section in its primary file, and relevant cross-links in other files.
Step 3 — Check if files exist
Read _INDEX.md. For any entity not listed:
- Create the file with the correct frontmatter schema
- Add it to
_INDEX.md
Step 4 — Write, with links
Write the information in the correct section. Every entity name in body text
must be a [[wikilink]]. Never write names as plain text when files exist.
Step 5 — Update all affected files
After writing the primary file, update every other file that was identified in Step 1. Add cross-links in the appropriate sections.
Step 6 — Update frontmatter
Update the updated: YYYY-MM-DD field in every file you touched.
Step 7 — Maintain the indices
After writing, maintain the index structure:
Per-type index (brain/<type>/_INDEX.md):
- If you created a new entity that is important or frequently referenced, add it to the type's key entities list
- If you used a new tag that doesn't appear in the type's tag table, add it with a short description
- Not every entity goes in the index — only key ones. Ask: "Would the agent need to find this without searching?" If yes, add it. Minor or one-off entities are discoverable via scripts.
Global index (brain/_INDEX.md):
- Only update when a new type folder is created (add to the type directory)
- Or when a new entity is so important it belongs in the global key entities (rare — think "owner" level of importance)
How to judge "key entity" status
An entity is key if:
- It has many backlinks (connected to lots of other entities)
- It is referenced frequently in conversations
- It represents a core relationship (family, close friends, main projects)
- The agent would always want to know where it is without needing to search
When in doubt, leave it out of the index. The scripts can always find it.
Fan-out example
The user says: "I'm planning a trip to Rome in June with my sister Sue."
| File | Action | Section |
|---|---|---|
events/2025-rome-trip.md |
CREATE | Overview, People |
people/sue-smith.md |
UPDATE | Events — add [[events/2025-rome-trip]] |
places/rome.md |
UPDATE or CREATE | Visits — add link + date |
people/john-doe.md |
UPDATE | Events — add link |
_INDEX.md |
UPDATE | Add 2025-rome-trip → events/2025-rome-trip.md |
9. Improvement protocol: how files grow over time
Files are never "done." Every new piece of information should make existing files richer.
Confirming existing content
If new information confirms what is already written, enrich the existing sentence:
- Before:
The user's sister. Lives in [[places/springfield]]. - After:
The user's sister. Lives in [[places/springfield]]. Recently promoted at [company], Jan 2025.
Updating stale content
If new information replaces old content, update in place and note the change:
- Before:
Works at [[projects/old-company]]. - After:
Works at [[projects/acme-corp]] (previously [[projects/old-company]]).
Adding new content
Append to the relevant section. Never duplicate facts that are already there.
Consolidation rule
When ## Personal notes accumulates facts that have become stable and confirmed,
move them into ## Basic information. The notes section should capture provisional
or personal impressions; confirmed facts belong in the body.
Never do this
- Don't add duplicate bullet points when a fact is already present
- Don't leave stale data alongside updated data without noting the change
- Don't write plain text entity names when a wikilink file exists
- Don't create a new file for a one-off mention with no meaningful context
Stubs for unknown entities
When the agent encounters an entity it doesn't recognize (a name in an email, a calendar
event, a conversation), asks the user about it, and the user doesn't know either, the
agent should create a stub — a minimal file tagged unknown:
---
type: person
aliases: []
tags: [unknown]
updated: 2025-03-25
---
## Context
- Seen in calendar event "Dinner with Morgan" on 2025-03-25
- Asked the user — they don't know who this is
Why stubs exist:
- Prevent the agent from asking about the same entity again
- Accumulate context if the entity reappears (another email, another event)
- Allow the user to later ask "who is this?" and get a history of sightings
When to create a stub:
- The entity has a concrete touchpoint (email, calendar, message) that could recur
- The user was asked and said they don't know
When NOT to create a stub:
- Purely hypothetical or transient mentions (a delivery driver, a one-time customer service rep)
- The entity is clearly identifiable from context and doesn't need tracking
Graduating a stub: When real information arrives later, remove the unknown tag,
add proper content, and treat it like any other entity file.
10. Available scripts
All scripts live in the skill directory (skills/brain/). They output JSON and
run with Python 3. The --brain flag defaults to the workspace BRAIN path, so
you usually don't need to specify it.
list — enumerate pages
python skills/brain/list.py [PATTERN] [--type TYPE] [--tag TAG] [--sort FIELD] [--regex]
Returns metadata (path, title, type, tags, aliases, description, updated, backlinks) for all pages matching the pattern. Pattern is a case-insensitive substring of the file path.
Sort options: backlinks (most linked first), updated (most recent), title (default).
Examples:
python skills/brain/list.py people/ # all people
python skills/brain/list.py --type event # all events
python skills/brain/list.py --tag family # all family-tagged notes
python skills/brain/list.py 2025 --type event # 2025 events
python skills/brain/list.py --sort backlinks # most connected entities first
python skills/brain/list.py --type person --sort backlinks # most connected people
search — find by content
python skills/brain/search.py QUERY [--type TYPE] [--content] [--exact] [--limit N]
Searches title, aliases, tags, description. Use --content to also search body text.
Results are ranked by relevance. Each result includes score, matched_in, and backlinks fields.
Examples:
python skills/brain/search.py "Sue" # find Sue in titles/aliases
python skills/brain/search.py "promoted" --content # full-text search
python skills/brain/search.py "rome" --type event # events mentioning Rome
links — outgoing links from a file
python skills/brain/links.py FILE [--raw]
Returns all pages that FILE links to, with full metadata. FILE can be a path,
stem, or alias. Use --raw for just the link target strings.
Examples:
python skills/brain/links.py people/sue-smith.md # what does Sue's file link to?
python skills/brain/links.py "Rome Trip 2025" # links from event (by alias)
backlinks — incoming links to a file
python skills/brain/backlinks.py FILE [--type TYPE]
Returns all pages that link TO the given file, with full metadata and linking_via
showing which link strings matched. Useful for understanding a note's connections.
Examples:
python skills/brain/backlinks.py people/sue-smith.md # who links to Sue?
python skills/brain/backlinks.py places/barcelona.md # what mentions Barcelona?
python skills/brain/backlinks.py john-doe --type event # events linking to John Doe's page
orphans — find disconnected pages
python skills/brain/orphans.py [--type TYPE] [--exclude-index]
Lists pages with no incoming wikilinks. Use this to discover connection opportunities: pages that could be linked from related files to strengthen the knowledge graph. Orphans aren't bad — but connections are always good.
Examples:
python skills/brain/orphans.py # all orphaned pages
python skills/brain/orphans.py --type person # people nobody links to
move — rename or relocate a file
python skills/brain/move.py <FROM> <TO> [--dry-run]
Moves a file to a new path and rewrites every wikilink that pointed to the old
location across all brain files and indices. Also updates type: in frontmatter
if the file moves to a different type folder. Use --dry-run to preview changes.
FROM can be a path, stem, or alias. TO must be a relative path ending in .md.
Examples:
python skills/brain/move.py people/sue.md people/sue-jones.md # rename
python skills/brain/move.py "Sue" people/sue-jones.md # same, by alias
python skills/brain/move.py people/cooking.md topics/cooking.md # change type
python skills/brain/move.py topics/fitness.md topics/fitness.md --dry-run # preview
validate — check structural integrity
python skills/brain/validate.py [--fix-index]
Runs integrity checks: dead _INDEX.md entries, files missing from index,
broken wikilinks, missing frontmatter fields, duplicate aliases. Use --fix-index
to auto-append missing files to _INDEX.md.
Run this after any large batch of writes, or periodically for maintenance.
11. Naming conventions
- File names: lowercase, hyphen-separated, no spaces.
sue-smith.md,rome-trip-2025.md - Event slugs:
YYYY-[descriptive-name].md.2025-rome-trip.md,2024-job-start-acme.md - Topic slugs: short, descriptive.
llm-observability.md,cooking.md - Tags: lowercase, no spaces. Multiple tags are fine. Prefer specific (
family) over vague (people) - Dates in frontmatter: always
YYYY-MM-DD
12. Source annotations
When writing facts you're less than certain about, annotate inline:
(mentioned YYYY-MM-DD)— date the info was captured(unconfirmed)— inferred or from a single mention(per user)— the user explicitly stated this
This helps future-you evaluate stale or uncertain data.
13. What does NOT belong in BRAIN
The BRAIN stores structured knowledge about entities — people, places, projects, events, topics. It does NOT replace other memory systems:
| Information type | Where it goes |
|---|---|
| Facts about people, places, projects | BRAIN |
| Operational rules and preferences | MEMORY.md |
| Session logs, raw event capture | memory/YYYY-MM-DD.md |
| Transient state (monitor JSON, heartbeat tracking) | memory/ |
| Agent behavioral learnings | AGENTS.md or MEMORY.md |
| One-off mentions with no recurring context | Don't create a file — embed in the primary file or daily log |
When both apply: If the user tells you a fact about a person AND it's an event worth logging, write to both: update the person's BRAIN file AND log the raw event in daily memory.
14. When in doubt
- Ambiguous category: use the most specific entity as the primary file, cross-link to others
- Don't know which section: write under a new heading with a clear label; the section can be normalized later
- Entity doesn't fit any type: create a new type with its own folder, or use
topicas a lightweight catch-all if the entity is minor - Something is both a place and an event (e.g. "home office"): primary in
places/, link fromevents/orprojects/as needed - Unsure if an entity deserves its own file: ask whether it might be mentioned again. If yes, create it. If it is a one-off, embed in the primary file and don't create a page for it.