obsidian-init
Bootstraps an Obsidian vault with CLAUDE.md, folders and schema. Use when the user wants a vault set up ("init vault", "bootstrap obsidian", "setup knowledge base", "create vault structure"). Not for
SKILL.mdplugins/mz-knowledge/skills/obsidian-init/SKILL.md
GitHubObsidian Init
Overview
Discipline skill that bootstraps a new Obsidian vault (or retrofits an existing one) with a CLAUDE.md governance file, PARA+Zettelkasten folder structure, .mz/vault-schema.yml, and starter templates. The output is a vault ready for all other mz-knowledge skills — process-notes, vault-ingest, vault-schema, vault-triage, vault-connect, etc.
When to Use
Setting up a new Obsidian vault from scratch for use with Claude Code, or retrofitting an existing vault that lacks CLAUDE.md or .mz/ structure.
When NOT to use
- Vault already has well-formed CLAUDE.md and
.mz/vault-schema.yml— edit directly. - Processing or ingesting notes — use
vault-ingest,process-notes. - Coding rules for a code repo rather than a vault — use
init-rules.
Constants
- SKILL_DIR:
${CLAUDE_SKILL_DIR}. Phase files write<SKILL_DIR>/...because files opened with Read get no variable substitution; expand it to this absolute path before reading a file, running a command, or passing a path to an agent. - PROJECT_ROOT: resolved once in setup with
echo "${MZ_MEMORY_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; expand<PROJECT_ROOT>to it in every command and agent prompt. - TASK_DIR:
<PROJECT_ROOT>/.mz/task/| SCHEMA_PATH:<vault>/.mz/vault-schema.yml| CLAUDE_MD_PATH:CLAUDE.md(vault root)
Core Process
Phase Overview
| Phase | Goal | Details |
|---|---|---|
| 0 | Setup + interview | Inline below |
| 0.5 | User approval — scaffold plan | Inline below |
| 1 | Scaffold vault | phases/scaffold_vault.md |
| 2 | Verify | Inline below |
Phase 0: Setup + Interview
- Resolve
PROJECT_ROOTwith the command in Constants, before anycdor worktree switch, and use it for every.mz/path below. - Parse
$ARGUMENTS. First argument is the vault path. If--minimalflag is present, skip interview and use defaults. - If the vault path is empty, ask via AskUserQuestion.
- Check whether the path exists. If it does, scan for existing
.obsidian/,CLAUDE.md,.mz/, and any folder structure. Record findings — the skill must not destroy existing content. - Derive
task_name = <YYYY_MM_DD>_obsidian-init_<slug>where<YYYY_MM_DD>is today's date (underscores) and<slug>is a snake_case summary of the vault directory name (max 20 chars); on same-day collision append_v2,_v3. CreateTASK_DIR<task_name>/. - Write
state.mdwithschema_version: 2,Status: running,Phase: 0,Started,Vault,ExistingCLAUDE: true|false,ExistingSchema: true|false,ExistingFolders: [list],phase_complete: false,what_remains: [].
Unless --minimal was passed, ask the user via AskUserQuestion (single question, all items):
- question:
Vault bootstrap interview for <vault path>. 1. Vault purpose — what kind of knowledge? (e.g., "personal second brain", "team engineering wiki", "research notes") 2. Primary topics — 3-5 top-level categories for permanent notes (e.g., AI, Engineering, Business) 3. Note types — which do you use? (permanent, fleeting, daily, moc, resource, project — all enabled by default) 4. Frontmatter style — minimal (created, type, tags) or extended (+ updated, status, source, epistemic_status)? 5. Tag taxonomy — flat (#ai, #engineering) or hierarchical (#ai/llm/claude, #status/draft)? Or choose one of the quick options below. - options:
- Defaults — accept all defaults (personal second brain, AI/Engineering/Business/Career topics, all six note types, extended frontmatter, hierarchical tags)
- Minimal — bare structure only, no interview answers applied
Record answers (or the chosen option) in state.md under VaultPurpose, PrimaryTopics, NoteTypes, FrontmatterStyle, TagStyle.
Phase 0.5: User Approval — Scaffold Plan
This orchestrator (not a subagent) presents this gate. This step is interactive and must not be delegated.
Build the plan from interview answers (or defaults). Write the scaffold plan to <PROJECT_ROOT>/.mz/task/<task_name>/scaffold_plan.md so it can be read and re-emitted on each loop iteration.
Pre-read: Read <PROJECT_ROOT>/.mz/task/<task_name>/scaffold_plan.md and capture the full contents into context.
State: write state.md with the artifact path and what_remains: [awaiting approval: scaffold plan gate]; Status stays running.
Surface 1 — emit the plan message. Output the scaffold plan verbatim as a normal markdown chat message:
## Scaffold plan ready for review — obsidian-init
Scaffold plan for <vault path>:
Folders to create:
<numbered list of folders with descriptions>
Files to write:
- CLAUDE.md — vault governance (~150 lines)
- .mz/vault-schema.yml — frontmatter schema for vault-schema skill
- .mz/memory/MEMORY.md — project memory index (empty)
- 99 - Meta/Templates/Permanent.md — starter template
- 99 - Meta/Templates/Fleeting.md — starter template
<if existing content detected>
Existing content preserved:
- <list of files/folders that will not be overwritten>
</if>
---
**Approve** → proceed to Phase 1, write all scaffolding files · **Reject** → abort the task, no files created · reply with feedback to revise
Emit the full verbatim contents of <PROJECT_ROOT>/.mz/task/<task_name>/scaffold_plan.md — do not substitute a path, summary, or placeholder.
Surface 2 — call AskUserQuestion. A short selector — do not re-embed the plan in the question body, it lives in the plan message above:
- question:
The scaffold plan above is ready for review. - header:
Scaffold - options:
- Approve — proceed to Phase 1 and write all scaffolding files
- Reject — abort the task, no files will be created
Response handling:
- Approve → add
- plan approved: .mz/task/<task_name>/scaffold_plan.mdunder## Decisionsinstate.md, remove theawaiting approvalentry, setPhase: plan_approved, and proceed to Phase 1. - Reject → update state to
aborted_by_userand stop. Do not proceed. - Any other reply (feedback) → adjust the plan, overwrite
<PROJECT_ROOT>/.mz/task/<task_name>/scaffold_plan.md, return to this gate, re-read the updated plan, and re-emit the entire plan message from scratch. This is a loop — repeat until the user explicitly approves. Never proceed to Phase 1 without explicit approval. - No answer → set
Status: blocked, keepawaiting approval: scaffold plan gate, stop. A missing answer is never approval.
Phase 1: Scaffold Vault
Create folders, write CLAUDE.md, schema, and templates. See phases/scaffold_vault.md.
Phase 2: Verify
- List
<vault>/**/*.mdand<vault>/.mz/**to confirm all planned files exist. - Read
CLAUDE.mdand verify it contains: Vault Context, Obsidian Syntax, Folder Layout, Note Conventions, Frontmatter, Compounding Wiki Principle, Don'ts sections. - Read
<vault>/.mz/vault-schema.ymland verify YAML parses withnote_types:key. - Confirm no existing files were overwritten (compare against Phase 0 scan).
Update state.md to terminal: Status: complete, Phase: 2, Completed: <ISO>.
Common Rationalizations
| Rationalization | Rebuttal |
|---|---|
| "Just copy the example CLAUDE.md verbatim — it's good enough." | "Every vault has different topics, note types, and conventions. A copied CLAUDE.md with someone else's topic hierarchy misleads every downstream skill that reads it." |
| "Skip the interview — defaults work for everyone." | "Defaults work for the author's vault. A team wiki needs different folder layout, frontmatter fields, and tag conventions. The interview costs 30 seconds and prevents hours of retrofitting." |
| "Overwrite the existing CLAUDE.md — ours is better." | "The existing CLAUDE.md may contain vault-specific rules accumulated over months. Merge, don't replace. If the user wants a clean slate, they say so explicitly." |
Red Flags
- Writing CLAUDE.md without checking whether one already exists.
- Creating folders for note types the user disabled.
- Hardcoding topic names from the example vault instead of using user's answers.
- Writing to
.obsidian/— that directory belongs to the Obsidian app.
Verification
Print this block before concluding:
obsidian-init verification:
[ ] Interview completed (or --minimal/defaults accepted)
[ ] Scaffold plan approved via AskUserQuestion before any writes
[ ] CLAUDE.md written with vault-specific content (not a generic copy)
[ ] .mz/vault-schema.yml written with note_types matching user's chosen types
[ ] Folder structure created matching approved plan
[ ] No existing files overwritten
[ ] state.md Status is `complete` with Completed timestamp
If any box is unchecked, report the failure explicitly.
References
${CLAUDE_SKILL_DIR}/references/claude-md-template.md: the CLAUDE.md template with{{PLACEHOLDER}}markers and a placeholder table. Read it in full in Phase 1, Step 2, whenExistingCLAUDEis false.
State Management
State persists to .mz/task/<task_name>/state.md under the project root, ${MZ_MEMORY_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}, resolved once at the start of the run. Schema is v2: line 1 is schema_version: 2; line 2 is Status: with one of pending, running, blocked, complete, aborted_by_user or failed, lowercase and unquoted; then Phase, Started, phase_complete (boolean) and what_remains (YAML list of strings), with skill-specific keys below them. Milestones go in Phase; the reason for blocked or failed goes in what_remains. Set phase_complete: false on phase entry and true once the phase's artifacts are written and its gates pass. Refresh what_remains on every phase transition; it is [] when Status is complete. Write the file after every phase and before every gate, and re-read it after compaction. Record decisions worth recalling under a heading that reads exactly ## Decisions, placed before ## Notes; mz-memory harvests them only once Status is complete. Under a heading that reads exactly ## Lessons, add one line whenever a review finding is accepted and fixed, a step fails, gate feedback corrects a mistake, or an approved approach is reversed, in the form - (review|failure|correction|change) WHEN <situation> → <what to do> — WHY <cause>, concrete and under about 40 words; mz-memory harvests lessons whatever the Status. Treat a legacy completed as complete. On reading a schema_version: 1 or unversioned file, put schema_version: 2 on line 1 and Status on line 2, add the missing keys, and log the upgrade. Leave a file with a higher schema_version untouched: ask whether to Restart (archive it), start New (_v2) or Abort, and stop if nobody can answer.