Obsidian Second Brain
Claude operates your Obsidian vault as a self-rewriting knowledge base. An evolution of Karpathy's LLM Wiki pattern: sources rewrite existing pages instead of just appending, contradictions reconcile automatically, and scheduled agents maintain the vault while you sleep. Everything worth remembering gets saved. Every update propagates everywhere it belongs.
Quick Start
0. Choose vault access method (in order of preference)
Try these methods in order. Use the first one available:
Method 0 - SessionStart hook (if configured):
If hooks/load_vault_context.py is wired as a SessionStart hook in ~/.claude/settings.json, _CLAUDE.md is injected into context automatically at session start. Skip step 1 below.
To wire it: bash scripts/setup.sh "/path/to/vault" or run /obsidian-setup.
Method A - Direct filesystem (default, always works): Use standard file tools (Read, Write, Edit, Glob) against the vault path. The vault is plain markdown, so every operation in this skill works this way with no setup. This is the normal path in Claude Code - the commands below use these tools directly.
Method B - MCP server (optional, mainly for non-Claude-Code clients):
This repo ships its own MCP server at integrations/obsidian-mcp-server/ that exposes the vault as tools (obsidian_search, obsidian_read_note, obsidian_save_note, obsidian_capture, plus curator tools). It exists so other MCP clients - Hermes Agent, Claude Desktop, Cursor - can use the vault as a knowledge layer; in Claude Code itself, Method A is simpler and preferred. If those obsidian_* tools happen to be available in your client, you may use them instead of raw file tools. Setup lives in integrations/obsidian-mcp-server/README.md (it is uv run --no-project --with 'mcp<2' python .../server.py with OBSIDIAN_VAULT_PATH set, not an npx package). Since the bookkeeping change, every write through the server also validates the note, adds the index entry, appends the operation-log line, and runs OBSIDIAN_POST_WRITE_CMD when set - see integrations/obsidian-mcp-server/README.md, "Bookkeeping after writes".
1. First time in a vault → read _CLAUDE.md
Before doing anything in a vault, check if _CLAUDE.md exists at the vault root and read it:
Read <vault>/_CLAUDE.md
If it exists: follow its rules exactly - they override the defaults in this skill. Where _CLAUDE.md is silent, fall back to the defaults below.
If it doesn't exist: use the defaults in this skill, then offer to create one.
If the SessionStart hook is active, _CLAUDE.md is already in context - skip this step.
2. First time with a new user → run discovery
Glob <vault>/**/*.md
Scan the structure to understand: folder names, template locations, naming conventions, frontmatter patterns. Then read 2-3 existing notes to calibrate writing style before creating anything new.
3. Bootstrap a new vault
If the user has no vault yet, run:
# One-line install + bootstrap (asks 3 questions: vault path, your name, preset)
curl -sL https://raw.githubusercontent.com/eugeniughelbur/obsidian-second-brain/main/scripts/quick-install.sh | bash
# Or manual:
python scripts/bootstrap_vault.py --path ~/path/to/vault --name "Your Name"
# With a preset:
python scripts/bootstrap_vault.py --path ~/my-vault --name "Your Name" --preset executive
python scripts/bootstrap_vault.py --path ~/my-vault --name "Your Name" --preset builder
python scripts/bootstrap_vault.py --path ~/my-vault --name "Your Name" --preset creator
python scripts/bootstrap_vault.py --path ~/my-vault --name "Your Name" --preset researcher
# With assistant mode (maintaining vault for someone else):
python scripts/bootstrap_vault.py --path ~/my-vault --name "Your Name" --mode assistant --subject "Boss Name"
Then just point the skill at the new vault path (Method A above). If you use the optional bundled MCP server, set OBSIDIAN_VAULT_PATH to the new path and restart the client.
Presets customize the vault for different use cases:
executive- Decisions, people, meetings, strategic planning. Kanban: OKRs, Quarterly, Weekly.builder- Projects, dev logs, architecture decisions, debugging. Kanban: Backlog, Sprint, Done.creator- Content calendar, ideas pipeline, audience notes, publishing. Kanban: Ideas, Drafts, Published.researcher- Sources, literature notes, hypotheses, methodology. Kanban: Reading, Processing, Synthesized.
Default (no preset) gives a general-purpose vault. All presets use wiki-style by default.
Assistant mode creates a _CLAUDE.md configured for operating a vault on behalf of someone else. See references/claude-md-assistant-template.md.
See references/vault-schema.md for full structural details.
Core Operating Principles
AI-first vault rule (applies to every note)
The vault is designed for future agent to read and reason over, not for human review. Every note Claude writes - across all 46 commands - must follow references/ai-first-rules.md:
- Self-contained context - each note explains itself; don't rely on backlinks alone
- "For future agent" preamble - 2-3 sentence summary so any compatible agent can decide relevance in 10 seconds
- Rich, consistent frontmatter -
type,date,tags,ai-first: true, plus type-specific fields (seeai-first-rules.mdfor schemas per note type) - Recency markers per claim - "Mem0 raised $24M (as of 2026-04, mem0.ai)" so future agent knows what to verify
- Sources preserved verbatim - every external claim has its source URL inline
- Cross-links mandatory - every person/project/idea/decision uses
[[wikilinks]] - Confidence levels -
stated | high | medium | speculationwhere applicable
This rule lives in _CLAUDE.md Section 0 of every vault using this skill, and in references/ai-first-rules.md (the canonical specification with frontmatter schemas + preamble templates per note type). That path is relative to the install root, which is load-bearing: if it does not resolve from your working directory, search upward for it, and if you still cannot read it, say so before writing rather than producing a note that silently skips the rule. The seven requirements above are the floor and apply whether or not the spec is reachable.
Never create in isolation
Every write operation must ask: where else does this belong?
| You create/update... | Also update... |
|---|---|
| A new project note | Kanban board (add to Backlog), today's daily note (link it) |
| A task completed | Kanban board (move to Done), project note (log it), daily note |
| A person note | Daily note (mention interaction), People index if it exists |
| A dev log | Daily note (link it), project note (Recent Activity) |
| A deal update | Side Biz / Deals kanban, Dashboard totals |
| A decision made | Project note (Key Decisions), daily note |
| A mention/shoutout | Mentions Log, person's note, daily note |
| A hook, contrarian angle, or content idea | social-media/ideas.md (if folder exists) |
| A specific reusable number or stat | social-media/data-points.md (if folder exists) |
| An external post that performed well + why | social-media/swipe-file.md (if folder exists) |
| Research findings worth keeping | social-media/research/YYYY-MM-DD - topic.md (if folder exists) |
| Any vault write | operation log (Logs/YYYY-MM-DD.md if Logs/ exists, else log.md), index.md (update if new note created) |
Always propagate. Never create a single orphaned note.
Bi-temporal facts - never overwrite, always append
When a fact changes (role, company, status, location, tool), NEVER delete the old value. Add a new entry to the timeline: frontmatter array with both event time AND transaction time:
timeline:
- fact: "CTO at Currentscale Labs"
from: 2024-01-01 # event time: when it was true
until: 2026-04-07
learned: 2026-02-23 # transaction time: when the vault learned it
source: "[[2026-02-23]]" # where from
- fact: "Architect at Currentscale Labs"
from: 2026-04-07
until: present
learned: 2026-04-07
source: "[[2026-04-07]]"
Top-level fields (role:, status:, company:) always reflect the CURRENT state. The timeline: preserves the full history with provenance.
This enables:
- Historical queries ("who was my manager in February?")
- Reflective thinking ("you believed X on Tuesday, then ingested Y on Wednesday and shifted to Z")
- Smart reconciliation (different facts at different times = not a contradiction)
- Full audit trail (when did the vault learn each fact, from what source?)
CRITICAL_FACTS.md - always loaded
A tiny file (~120 tokens) loaded alongside SOUL.md at L0 in every session. Contains facts needed in every conversation:
- Timezone
- Current manager
- Current location
- Current company and role
- Any other fact that's true RIGHT NOW and relevant to every interaction
Update this file whenever a critical fact changes. Keep it under 150 tokens.
Raw is immutable
In wiki-style vaults, the raw/ folder contains original sources (articles, transcripts, PDFs). Claude reads these but NEVER modifies them. They are the source of truth. If a wiki page gets corrupted, re-derive it from the raw source. When ingesting, always save the original to raw/ and the derived pages to wiki/.
Maintain index.md and log.md
Two structural files that keep the vault navigable and auditable:
index.md- A catalog of all vault pages organized by category. Claude reads this FIRST when navigating the vault instead of searching - faster and cheaper on tokens. Update it whenever a new note is created or deleted. Format:- [[Note Name]] - brief descriptiongrouped under folder headings.log.md- An append-only chronological log of every vault operation. Every save, ingest, health check, and structural change gets a timestamped entry. Never delete or rewrite entries - only append. Format:## [YYYY-MM-DD] action | Description
Per-day operation logs (modernized vaults)
Vaults initialized with /obsidian-init (v0.9+) use a split log structure instead of a monolithic log.md:
Logs/YYYY-MM-DD.md- one file per day, append-only. Format:**HH:MM** - action | descriptionlog.mdat vault root - pointer file only. Never write entries here; it explains the per-day structure and ships the entry template.
To migrate an existing monolithic log.md: run python scripts/migrate_log.py --vault <path>.
To refresh the stats block in index.md after bulk writes: run python scripts/vault_stats.py --vault <path>.
When writing operation log entries, check whether the vault uses the old (log.md) or new (Logs/YYYY-MM-DD.md) structure and write to the correct location.
The vault is a living system
The vault is not a filing cabinet. It is a living knowledge base that rewrites itself with every input. When new information enters:
- Existing pages get REWRITTEN with new context, not just appended to
- Contradictions between old and new claims get resolved or explicitly documented
- New patterns across multiple sources trigger automatic synthesis pages
- Stale claims get replaced with current information, with history preserved
The vault after an ingest should be DIFFERENT - not just bigger. If pages that existed before aren't smarter, more connected, and more current, the ingest wasn't deep enough.
Two-Output Rule
Every interaction that produces insight must generate two outputs:
- The answer - what the user sees in the conversation
- A vault update - the insight filed back into the relevant note(s)
This applies to all thinking tools and any query where Claude synthesizes information from the vault.
Synthesis Hook
When Claude notices a pattern during any operation (ingest, query, challenge, emerge), it should automatically create a synthesis page in wiki/concepts/. Patterns include:
- The same concept appearing in 3+ unrelated sources
- A claim being reinforced by multiple independent sources
- A trend emerging across time-sequenced notes
- Two entities sharing unexpected connections
Synthesis pages are the vault thinking for itself - connecting dots the user hasn't connected yet.
Reconciliation
The vault should never contain two pages that disagree without knowing they disagree. When contradictions are found (during ingest, health checks, or queries), either:
- Resolve them: rewrite the outdated page, preserve history
- Document them: create an explicit conflict page marked as an open question
Use /obsidian-reconcile for vault-wide truth maintenance.
Proactive save reminders
Unsaved conversations are lost knowledge. Claude should proactively remind the user to save:
- After 10+ exchanges: suggest "Want me to run /obsidian-save before we continue?"
- When the user signals wrap-up (e.g., "ok", "thanks", "done", "bye", "that's it"): suggest "Before you go - want me to /obsidian-save this conversation?"
- When a logical work block completes (feature shipped, decision made, problem solved): suggest saving
- Never skip the reminder. This is especially critical on Claude Desktop where there's no background agent.
Search before creating
Before creating any new note, search for an existing one:
search(query="keyword from title")
Duplicate notes are vault rot. Merge or update instead of creating new.
Never claim absence from memory, never fabricate
Two failure modes corrupt the vault silently:
- False absence (most common): never say "no note exists" or create a note on the assumption none exists without searching exhaustively first - by every plausible name, alias, and folder, listing and grepping, not from memory. When in doubt, over-include and label the uncertainty.
- Fabrication: never invent facts, entities, rates, dates, or relationships that were not actually stated. Mark unknowns as
TBD; an empty section is correct when nothing was said. External claims carry a source URL + recency marker; inferences carry a confidence level.
See the anti-fabrication and search-completeness hard rules in references/ai-first-rules.md.
Match the vault's voice
Read existing notes in the same folder before writing new ones. Match: frontmatter schema, heading style, list formatting, tone, emoji usage (or lack of it). Never introduce new conventions - extend what's already there.
Frontmatter is mandatory
Every note gets frontmatter. At minimum:
---
date: 2026-03-24
tags:
- <note-type>
---
See references/vault-schema.md for full frontmatter specs by note type.
Write Rules
See references/write-rules.md for the complete guide. Summary:
- Links: Use
[[Note Name]]for internal links. Always link to people, projects, and jobs mentioned in a note. - Dates: ISO format (
YYYY-MM-DD) in frontmatter. Human format (March 24) in body text. - Naming:
YYYY-MM-DD - Title.mdfor dated notes.Title.mdfor evergreen notes. No special characters except the ASCII hyphen-. Never an em dash (U+2014) or en dash (U+2013) in a filename: link matching compares stems literally, so2026-07-26 - Title.mdwill not resolve a[[2026-07-26 - Title]]link, producing an orphan and a dangling link in the same write. The write-time validator checks file CONTENT, not filenames, so nothing catches this for you. - Status values:
active/planning/completed/archived/on-holdfor projects.in-progress/done/waitingfor tasks. - Kanban: Items follow the format
- [ ] 🔴 **Title** · @{YYYY-MM-DD}\n\tDescription [[Link]]
The _CLAUDE.md File
This is the most important concept in this skill.
_CLAUDE.md lives at the vault root and persists Claude's operating rules across every session and every surface (Claude Desktop, Claude Code, VS Code, terminal). Without it, Claude has to re-learn your vault conventions every conversation.
Precedence rule: _CLAUDE.md wins on all vault-specific rules (folder names, naming conventions, frontmatter fields, auto-save behavior, private folders). The defaults in this skill file apply only where _CLAUDE.md is silent. Never let skill defaults override an explicit _CLAUDE.md rule.
What it contains:
- Your vault's folder map and what each folder is for
- Frontmatter schemas for your specific note types
- Naming conventions you use
- What to auto-save vs. what to ask first
- People and projects that need special handling
- Links to key files (boards, dashboard, templates)
To generate a _CLAUDE.md for an existing vault, run vault discovery then use the template in references/claude-md-template.md.
To install it: write the file to the vault root. Every Claude session that starts in that vault should read it first.
Common Operations
Save info from conversation
When a conversation produces something vault-worthy:
- Identify the note type (decision → project note, person met → People/, task → board + Tasks/, etc.)
- Check if a relevant note already exists
- Write or update - always frontmatter-first
- Propagate to boards, daily note, linked notes
Create today's daily note
date = today in YYYY-MM-DD format
path = Daily/{date}.md
Read Templates/Daily Note.md, fill in the date fields, create the file.
Then scan recent conversation for anything worth logging in today's sections.
Log a dev session
Read Templates/Dev Log.md. Fill: date, project name, what was worked on, problems solved, decisions made, next steps.
Save to Dev Logs/YYYY-MM-DD - Project Name.md.
Link from project note's Recent Activity section and today's daily note.
Update a kanban board
Boards use the kanban-plugin: board frontmatter.
Columns are ## Column Name headers.
Items are - [ ] **Title** · @{due-date}\n\tDescription [[Links]]
Completed items move to the ## ✅ Done column with a strikethrough: - [x] ~~**Title**~~ ✅ Date
Run vault health check
uv run --directory "SKILL_ROOT" scripts/vault_health.py --path ~/path/to/vault
Reports: duplicate notes, orphaned files (no incoming links), stale tasks (overdue), empty folders, broken links, notes missing frontmatter.
Proactively suggest running this when the user says the vault feels messy, notes are hard to find, they mention duplicates, or they haven't mentioned a health check in a long time. Offer: "Want me to run a vault health check?"
Commands
These slash commands can be used in any Claude surface. Each one is smart - it reads context, searches before writing, and propagates everywhere changes belong.
Name matching: If a name argument has a typo or is approximate, search the vault for the closest match, show what was found, and confirm with the user before proceeding. Never silently create a note with a misspelled name.
Command selection: the longest matching trigger wins. Several triggers are prefixes of longer, more specific ones, so a shorter match is not evidence that the shorter command is the right one. Always check whether a longer trigger also matches before choosing.
The five collisions that exist today, with the correct routing:
| The user says | Route to | Not to | Why it matters |
|---|---|---|---|
| "remind me every month...", "track a recurring..." | /obsidian-recurring |
/obsidian-task |
A one-shot card never recurs, which is the whole point of the request |
| "save this idea", "capture this" | /obsidian-capture |
/obsidian-save |
One small idea note, not a multi-subagent sweep across people, projects, tasks, decisions and boards |
| "save this person", "remember this person" | /obsidian-person |
/obsidian-save |
A person note, not a full conversation sweep |
| "synthesize what I know about X" | /vault-deep-synthesis |
/obsidian-synthesize |
One topic cross-referenced, not a whole-vault pattern scan |
| "find unnamed patterns" | /obsidian-emerge |
/obsidian-synthesize |
Surfaces patterns for the user, does not write synthesis pages unasked |
When two commands still look equally plausible after applying the rule, ask which one rather than guessing - the blast radii differ enormously, and /obsidian-save in particular writes across many files.
/obsidian-save
The master save command. Reads the entire conversation and extracts everything worth preserving.
Steps:
- Scan the conversation and identify all vault-worthy items: decisions, tasks, people mentioned, projects started, ideas, learnings, deals, mentions/shoutouts
- Group items by type: people, projects, tasks, decisions, ideas, deals
- Spawn parallel subagents - one per group - so all note types are handled simultaneously:
- People agent: search for each person, create or update notes, log interactions
- Projects agent: search for each project, create or update notes
- Tasks agent: parse tasks, add to the right kanban columns
- Decisions agent: find relevant project notes, append to Key Decisions sections
- Ideas agent: search Ideas/ for related notes, create or append
- After all agents complete: update today's daily note with links to everything saved
- Report back: a clean list of what was saved and where
Do not ask for guidance on where to save things - infer it. Only ask if something is genuinely ambiguous (e.g. a person mentioned with no context on who they are).
/obsidian-daily
Creates or updates today's daily note. Full steps in commands/obsidian-daily.md (the source of truth).
In short: resolves the daily folder per references/folder-map.md, creates today's note from the daily-note template if missing, then fills it from three inputs - the current conversation (tasks, people, decisions), the calendar (today's events when available), and the boards (due/overdue kanban items) - plus a short overnight-changes line when scheduled agents ran. Existing notes are injected into, never overwritten. Returns the note path.
/obsidian-calendar <mode>
One calendar command with four modes. Claude Code only (needs the Google Calendar MCP). The first word selects the mode; a bare range word defaults to agenda; no argument at all defaults to agenda today.
agenda [range]- reads the calendar and writes a re-derivable AI-first snapshot towiki/agenda/(type: agenda-snapshot). Range:today,tomorrow,week,next-week, a date, or a range. Cross-links attendees to[[Person]]notes; flags conflicts, 3+ back-to-back stretches, working-hours focus blocks, and externally-organized events. Read-only on the calendar; Google Calendar stays the source of truth.reconcile [window]- flags commitments the vault implies (projectnext_actions, due tasks, dated commitments in daily notes, fixed dates inCRITICAL_FACTS.md) that are NOT on the calendar, plus events with no vault context. Flag only - never adds or changes events.meeting [selector]- turns an event (last,next,today,event-id:<id>, or fuzzy title) into atype: meetingnote inwiki/meetings/with metadata pre-filled and empty Notes / Decisions / Action items sections (never fabricate meeting content). Cross-links attendees, backlinks any task whosecalendar-event-idmatches.schedule <args>- the only mode that writes to the calendar. Standalone ("<title>" <when> <duration>), from a task (task:<path>), or suggest-a-time (task:<...> suggest:<window>). Resolves attendee emails from person notes (never guesses), conflict-checks before writing, requests a Meet link when participants span domains, and writescalendar-event-idback into the task so a re-run reschedules rather than duplicating.
(Consolidated from the former /obsidian-agenda, /obsidian-reconcile-style calendar check, /obsidian-meeting, and /obsidian-schedule - same behaviors, one entry point. The natural-language triggers for all four still route here.)
/obsidian-recurring
Tracks a recurring obligation (payment, filing, ops) with a cadence and a computed next-due date.
State the obligation and cadence (e.g. "pay social benefits, monthly day 20"). Searches for an existing note first, then builds a type: recurring-task note with What / Cadence / Blockers / History sections and frontmatter (cadence, owner, blocker, next-due, optional amount). Adds a board card for the next occurrence; on each completion, appends a History row and advances next-due. Fills the gap that /obsidian-task (one-shot) leaves.
/obsidian-log
Logs a work or dev session to the vault. Full steps in commands/obsidian-log.md (the source of truth).
In short: infers the project from conversation, uses the dev-log template when one exists (inline structure otherwise), and saves YYYY-MM-DD - Project Name.md to the dev-log folder resolved per references/folder-map.md (wiki-style wiki/logs/, Obsidian-style Dev Logs/). Links are injected into the project note's Recent Activity and today's daily note.
/obsidian-task [description]
Adds a task to the vault and the right kanban board.
Steps:
- Parse the task from the argument or from recent conversation context if no argument given
- Infer: priority (🔴/🟡/🟢), due date, linked project, linked person
- Search for the right kanban board - use
_CLAUDE.mdboard list or searchBoards/ - Add the task card to the correct column (
📋 This Weekor📥 Backlogdepending on due date) - Create a task note in
Tasks/if the task is substantial (more than a one-liner) - Link the task from the relevant project note and today's daily note
/obsidian-person [name]
Creates or updates a person note.
Steps:
- Search the vault for an existing note matching the name (fuzzy - handle typos and partial names)
- If found: confirm with user, then update with new info from conversation
- If not found: create
People/Full Name.mdwith full frontmatter schema - Fill in everything inferable from the conversation: role, company, context, relationship strength, last interaction date
- Log the interaction in today's daily note
- If a People index file exists, add or update the entry there
/obsidian-capture [optional: idea text]
Quick idea capture with zero friction.
Steps:
- Take the argument as the idea, or pull the most recent idea/thought from the conversation
- Search
Ideas/for a related existing note - if found, append to it - If new: create
Ideas/Title.mdwith minimal frontmatter (date,tags: [idea]) - Write the idea with any supporting context from the conversation
- Add a brief mention in today's daily note under an Ideas or Captures section
/obsidian-catchup [today|week|all]
Process what the Telegram journal bot captured on the go. The laptop-side companion to the integrations/telegram-journal/ bot, which captures voice/text/image/PDF/link from your phone and appends each to a catchup.md queue in the vault.
Steps:
- Read
catchup.mdin the vault root - each unchecked- [ ]line is an unprocessed capture (date time | kind | summary | -> where). - Collect the unchecked items, applying the timeframe filter (
today/week/all, defaultall). If none, say so and stop. - Show them grouped by age (Today / This week / Older), flagging stale ones.
- Process WITH the user (not autonomously): open each linked note, propose integrate (fold into the right note per the AI-first rule) / keep / discard, confirm, then write.
- Check the item off (
- [x]+ processed date); never delete queue history.
Pull, not push: nothing is processed until you run this, so nothing surprises you. The phone is for fast dumb capture; this is where it becomes integrated knowledge.
/obsidian-find [query]
Smart vault search.
Steps:
- Run
search(query="...")with the provided query - Also try variations if results are sparse (synonyms, related terms)
- Return results with context: note title, folder, a relevant excerpt, and what type of note it is
- If results are ambiguous, group them by type (people, projects, tasks, etc.)
- Offer to open, update, or link any of the found notes
Do not just return filenames - return enough context for the user to act.
/obsidian-recap [today|week|month]
Summarizes a time period from the vault.
Steps:
- Determine the date range from the argument (default:
weekif not specified) - List all daily notes in the range with
list_files_in_dir("Daily/") - Spawn parallel subagents - one per daily note - to read and extract key points from each simultaneously
- Also spawn parallel agents to read dev logs and completed kanban tasks from the same period
- Synthesize all agent results: what was worked on, decisions made, people interacted with, tasks completed, ideas captured
- Present as a clean narrative summary - not a raw dump of note content
/obsidian-review
Generates a structured weekly or monthly review note. Full steps in commands/obsidian-review.md (the source of truth).
In short: reads the period's daily notes, dev logs, project changes, and completed board items; drafts from the review template when one exists (accomplishments, key decisions, people, learnings, carry-forward, plus the mandated "Suggested next week/month" section); saves YYYY-MM-DD - Weekly Review.md (or Monthly) to the reviews folder resolved per references/folder-map.md; links from the period's last daily note.
/obsidian-board [optional: board name]
Shows or updates a kanban board.
Steps:
- If a board name is given, search
Boards/for it (fuzzy match) - If no name given, list available boards and ask which one
- Read and display the current board state: columns, item counts, overdue items (past
@{date}) - Ask if the user wants to make updates - if yes, infer changes from conversation context
- Move completed items to ✅ Done with strikethrough, add new items in the right column
- Flag any items that are overdue or have been in the same column for more than a week
/obsidian-board-hygiene [optional: board name]
Bulk-triages a kanban board whose columns have gone stale. Where /obsidian-board only flags overdue items, this clears them.
Steps:
- Read
_CLAUDE.mdfor the boards folder and kanban convention (columns,@{date}format) - Read the target board (fuzzy-match; if none given, list boards and ask), parse every open item, compute age vs today
- Group items into overdue (
@{date}past), stale (older than N days, default 14), and undated; show counts per column so the bloat is visible - Propose ONE verdict per stale/overdue item with a one-line reason - done / reschedule / archive / keep - as a batch the user approves, edits, or overrides
- Apply approved verdicts in place (additive moves + strikethrough, never silent deletion), then report what moved and log it
/obsidian-project [name]
Creates or updates a project note.
Steps:
- Search the vault for an existing project matching the name (fuzzy - handle typos)
- If found: show what was found, confirm, then update with new info from conversation
- If not found: create
Projects/Project Name.mdwith full frontmatter schema (date,tags: [project],status: active,job) - Fill in everything inferable from the conversation: description, goals, key people, current status
- Add a card to the relevant kanban board in the
📥 Backlogor🔨 In Progresscolumn - Link from today's daily note
/obsidian-projects [optional: project name]
Live status overview across all tracked projects.
Reads _CLAUDE.md for the projects folder, then scans it for notes with type: project or a repo: field. For each project, spawns a parallel subagent that runs three checks: reads the vault note (status, last activity, next action, blockers), runs git log and git status if a repo: path is set, and looks for NOTES.md / TODO.md in the repo root. Merges the three into one status block (active / stalled / idle / blocked / archived inferred from activity recency), prints the full overview to the conversation ordered active-first, then injects a ## Last overview section into each project note.
If a project name argument is given, shows deep context for that one project only.
/obsidian-health
Runs a vault health check and summarizes findings.
Steps:
- Run:
uv run --directory "SKILL_ROOT" scripts/vault_health.py --path ~/path/to/vault --json - Parse the JSON output and split findings into categories
- Spawn parallel subagents to handle each category simultaneously:
- Links agent: verify broken links, attempt to resolve them
- Duplicates agent: confirm duplicates are truly the same concept, not just similar names
- Taxonomy agent: only fires when
<vault>/_meta/taxonomy.mdexists (format inreferences/taxonomy-format.md) - opt-in, zero findings without it.tag_synonym(a tag is a known synonym of a canonical tag) offers a per-note rename to the canonical form with confirmation;tag_not_in_taxonomy(a tag matches neither a canonical tag nor a synonym) is informational only, never auto-fixed - Frontmatter agent: identify notes missing required fields by type
- Staleness agent: check overdue tasks and unfilled template syntax
- Orphans agent: check orphaned notes and empty folders
- Contradictions agent: scan Key Decisions and Knowledge/ for claims that conflict or are superseded
- Concept gaps agent: find terms mentioned 3+ times without a dedicated page
- Stale claims agent: flag Knowledge/ notes older than 6 months on fast-moving topics
- Freshness agent: run
python scripts/freshness_lint.py --path <vault> --json- enforcesreferences/freshness-policy.md(every stored fact must be timeless, dated, or a pointer; fast facts carry anas ofstamp or link to their home system) - Typed-edge lint agent: run
python scripts/link_graph.py --path <vault> --lint- validates therelations:typed-edge graph (Rule 6 § Typed edges inreferences/ai-first-rules.md): contradiction cycles (critical), unknown types / dangling targets / self-edges (warning), missing inverse edges (info). Returns zero findings on vaults that use no typed edges yet
- Merge agent results and group by severity:
- 🔴 Critical: broken links, unfilled template syntax, contradictions, typed-edge contradiction cycles
- 🟡 Warning: duplicates, stale tasks, missing frontmatter, stale claims, concept gaps, typed-edge problems (unknown type, dangling target, self-edge), tag-synonym findings
- ⚪ Info: orphaned notes, empty folders, missing inverse edges, tags not in the taxonomy
- Present a clean summary with counts per category
- For safe fixes (missing frontmatter, obvious duplicates, creating pages for concept gaps), offer to fix them automatically
- For destructive fixes (archiving, merging, resolving contradictions), list them and ask for explicit confirmation before touching anything
- Append an operation-log entry with severity counts - if
Logs/exists write the entry toLogs/YYYY-MM-DD.md, otherwise append tolog.md(SKILL.md's own rule: the rootlog.mdis a pointer file in v0.9+ vaults, never an entry target)
/obsidian-reindex
Refreshes the semantic search index and makes its coverage visible. Full steps in commands/obsidian-reindex.md (the source of truth).
In short: reads the vault path from _CLAUDE.md, reports the current index_coverage, runs the existing incremental semantic_search.py --build, and reports coverage again with the builder's new, cached, excluded, degraded, and dropped counts. A backend failure stops the flow and is shown to the user; it is never presented as a successful refresh. The command updates only .obsidian-semantic-index.json, not Markdown notes.
/obsidian-retrieval-eval [optional: N to generate | report]
Measures how well vault search actually finds the right note - so improving retrieval is a number, not a hunch.
Hybrid command backed by scripts/eval/retrieval_eval.py, which reuses the REAL search engine (integrations/obsidian-mcp-server/vault_ops.py, the term-frequency, title-weighted ranking behind /obsidian-find and the MCP connector). It bootstraps its own eval set from the vault (an LLM writes a question per sampled note, avoiding the note's title words so it tests retrieval not string-match; the note is the gold answer), then scores recall@1/3/5/10 and MRR and lists the failures - misses and notes buried below #3, naming which note wrongly ranked #1. Claude interprets the numbers, turns failures into ranked retrieval fixes (each a hypothesis to re-measure on the same cases), and optionally writes an AI-first baseline note. Generated cases hold private note paths and are gitignored. The first run on a 1,000+ note vault scored 0% recall@10 on paraphrased questions (long raw/ transcripts and log.md dominate term-frequency ranking) - proving the cheap structural fixes (exclude raw/, weight by type:) should be measured before reaching for a vector index.
/obsidian-merge <canonical> <retired> | --from-health
Merges two near-duplicate notes that /obsidian-health found and stopped at. Dry run by default; the retired note becomes a redirect, never a deletion.
Health is read-only by contract, so the merge was the manual step everyone skipped and the same pairs came back every run. scripts/merge_notes.py does the mechanical half; you compose the merged body, because deciding what actually contradicts between two notes is judgment.
Steps:
- Resolve the pair: two paths from the user (first survives, second retires; confirm if the richer note is the second), or
--from-healthto list the 2-file duplicate groups from a livevault_health.check_duplicates()run. A group of 3+ is never auto-paired. - Read both notes in full. Compose the merged body per
references/ai-first-rules.md: one## For future agentpreamble naming both originals, both provenance trails kept, real contradictions listed with dates rather than resolved, every still-relevant[[wikilink]]from both sides carried over. Write it to a scratch file. - Dry run:
uv run --directory "SKILL_ROOT" scripts/merge_notes.py --path <vault> --canonical <a> --retire <b> --merged-body-file <scratch>. It prints the frontmatter conflicts (canonical wins, the retired value goes undermerged_from:; list fields such astagsandaliasesare unioned instead), the alias folded in, and the full text of both proposed notes. Show it verbatim. - Ask for explicit confirmation, then re-run the identical command with
--apply. Dry run and apply share onecompute_merge(), so what was previewed is what gets written. - Report which note survived, which became
type: redirect(schema inreferences/ai-first-rules.md, Documented exceptions), the conflicts, and the contradictions the body documents. Logmerge | <retired> -> <canonical>per the operation-log convention.
/obsidian-reconcile
Finds and resolves contradictions across the vault.
Steps:
- Read
index.mdto understand the full vault landscape - Spawn parallel subagents to find contradictions:
- Claims agent: scan
wiki/concepts/andwiki/projects/for conflicting factual claims - Entity agent: scan
wiki/entities/for outdated roles, companies, or descriptions - Decisions agent: scan
wiki/decisions/for reversed or superseded decisions never updated - Source freshness agent: compare
raw/dates againstwiki/pages for stale references
- Claims agent: scan
- For each contradiction, evaluate: which is newer, which i
…(truncated)