build-obsidian-vault
Skill2 starsChanged 4 months agoMITView on GitHub
Interview a user about knowledge-work goals and habits, then plan, create, or audit a maintainable local Obsidian vault made from ordinary Markdown, YAML properties, folders, and core-plugin-compatible templates. Use when a user asks to build, initialize, reorganize, or standardize an Obsidian knowledge base or vault. Prefer a new vault; extend an existing vault only after an explicit preview and never overwrite existing notes or settings.
In this repository4 other files it gives its agents.
- AGENTS.mdAGENTS.md
- download-videoSkill
- ingest-knowledgeSkill
- transcribe-mediaSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
20 rules. About 0 are common, 14 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈14
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Use Python 3.11–3.14 on macOS or Linux.
- Very specific: line 13
Before any mutating operation, the script requires fcntl, directory-FD operations, O_NOFOLLOW, O_DIRECTORY, directory fsync, atomic …
- Distinctive: line 16
Keep the skill independently runnable.
- Distinctive: line 20
Use short multi-turn questions.
- Distinctive: line 28
Read profiles.md after the first answer.
- Distinctive: line 32
Write one config JSON conforming to config-schema.md.
- Very specific: line 47
Read the plan_sha256 from the plan JSON.
- Very specific: line 64
Never reuse a digest after the config or observed vault contents change.
- Distinctive: line 65
Run the post-build audit and require the formal build receipt:
- Very specific: line 74
All lock-taking commands accept --lock-timeout.
- Distinctive: line 83
Before a new build, the script automatically finishes a provably matching pending build transaction.
- Distinctive: line 100
Keep source files portable: Markdown, ordinary attachments, and the skill-owned JSON receipt.
- Very specific: line 101
Create the .obsidian marker directory, but do not write undocumented .obsidian/*.json application settings.
- Distinctive: line 102
Use Obsidian properties as flat YAML.
- Distinctive: line 103
Prefer stable folder paths and links.
- Distinctive: line 104
Do not modify Obsidian's global vault registry or launch the GUI.
- Distinctive: line 105
Do not enable Sync, publish content, or copy settings from another vault.
- Very specific: line 108
Keep .awesome-capture, its lock, receipts, and journals private.
- Distinctive: line 109
Do not overwrite. A conflict must be resolved by the user or by generating a new path.
- Distinctive: line 110
Keep templates minimal; add automation only after the base vault works.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Build an Obsidian vault
Translate actual habits into a small, durable vault. Do not install community plugins or build an elaborate taxonomy before the user has demonstrated a need.
Runtime boundary
- Use Python 3.11–3.14 on macOS or Linux. The secure filesystem and locking guarantees are POSIX-only.
- Before any mutating operation, the script requires
fcntl, directory-FD operations,O_NOFOLLOW,O_DIRECTORY, directoryfsync, atomic no-replace rename, and atomic exchange rename. If the platform cannot provide them, stop withUNSUPPORTED_PLATFORM; do not substitute an unsafe implementation. - The script prints exactly one JSON object on stdout with empty stderr and exit 0 for success. An expected failure leaves stdout empty and prints exactly one redacted JSON error on stderr. Consume those objects rather than parsing prose.
- Repository-wide failure codes are: 2 for arguments, schemas, or unsafe inputs/paths; 3 for unavailable dependencies, models, or platform capabilities; 4 for locks, conflicts, recovery conflicts, or stale plans; 5 for external-tool, network, or runtime I/O failures; 7 for contract, identity, or file-evidence integrity failures; and 130 for interruption.
- Keep the skill independently runnable. It uses only its own vendored contracts and the Python standard library at runtime.
Interview
Use short multi-turn questions. Ask one coherent group at a time and accept “use defaults” at any point.
- Purpose and outputs: What should this vault help produce—learning, research, projects, content, decisions, or personal records? What are the two most common inputs and outputs?
- Capture and retrieval: Where should quick captures land? Does the user retrieve by search, links/maps, folders, dates, or a mix? How much weekly maintenance is realistic?
- Conventions and constraints: Preferred language, filename style, Wikilinks versus portable Markdown links, daily notes, attachment policy, sync/backup method, and target path.
Challenge contradictory requirements. For example, “zero maintenance” is incompatible with a deep manual taxonomy; choose a shallow inbox-plus-search workflow instead.
Read profiles.md after the first answer. Select the closest profile, then customize only what the user's answers justify.
Build workflow
- Write one config JSON conforming to config-schema.md. Keep it outside the target vault until validated.
For an existing vault, run the read-only audit before planning:
python3 scripts/vault_builder.py audit --vault "<absolute-vault-path>"An existing directory not previously built by this skill is reported with
managed_by_builder: false. That is not permission to modify it: inspect the plan and use--extend-existingonly after the user accepts every destination and conflict.Validate and preview:
python3 scripts/vault_builder.py validate-config "<config.json>" python3 scripts/vault_builder.py plan "<config.json>" --vault "<absolute-vault-path>"- Read the
plan_sha256from theplanJSON. Summarize the target path, folders, capture destination, source/attachment locations, templates, link style, unchanged files, and conflicts. Ask the user to confirm that exact plan because applying it creates local files. Apply the confirmed plan by passing its full digest:
python3 scripts/vault_builder.py build "<config.json>" \ --vault "<absolute-vault-path>" --apply \ --expected-plan-sha256 "<plan_sha256>"For an explicitly approved existing vault, add
--extend-existing:python3 scripts/vault_builder.py build "<config.json>" \ --vault "<absolute-vault-path>" --apply --extend-existing \ --expected-plan-sha256 "<plan_sha256>"Never reuse a digest after the config or observed vault contents change. The builder recomputes the plan while holding the exclusive vault lock and returns
STALE_PLANif it no longer matches. Runplanagain and obtain fresh confirmation.Run the post-build audit and require the formal build receipt:
python3 scripts/vault_builder.py audit \ --vault "<absolute-vault-path>" --require-build-receipt- Report the vault path, receipt, created/unchanged files, conflicts, and the one manual action: open that folder as a vault in Obsidian. If daily notes are enabled in the profile, explain that the builder creates the folder and template but does not toggle or configure the Obsidian core plugin.
All lock-taking commands accept --lock-timeout; the default is 30 seconds. A timeout returns VAULT_BUSY.
Contract, identity, and recovery
- The input remains
awesome-capture.vault-config/v1. - A successful build publishes
<vault>/.awesome-capture/vault-build.jsonlast. It is anawesome-capture.vault-build-receipt/v1object recording the config and contract digests, layout and link style, vault identity, confirmed plan digest, and relative managed paths with their initial hashes. - Generated Markdown and templates are independent of the execution date. Timestamps belong only in the receipt. Reapplying an identical config to intact managed content returns
unchanged; it does not create a cross-day diff. - Build files, the journal, and the receipt are published without clobbering existing paths and are synced with their parent directories. A conflicting destination is never overwritten.
- A build transaction uses an
awesome-capture.transaction/v1journal below<vault>/.awesome-capture/transactions/; the receipt is the final completion marker. Before a new build, the script automatically finishes a provably matching pending build transaction. To recover explicitly:
python3 scripts/vault_builder.py recover --vault "<absolute-vault-path>"Recovery only completes steps whose staged and published hashes agree. Unknown entries, unsafe paths, or mismatched content return
RECOVERY_CONFLICT; the script does not delete or overwrite them.
Locking and audit
- Vault build and knowledge ingest share the persistent
<vault>/.awesome-capture/vault.lock. Build and recovery take an exclusive lock; both audit commands take a shared lock. auditis read-only and never invokes recovery. It checks the formal build receipt, config identity, managed directories and templates, symlinks, hashes, and pending transactions.- Without
--require-build-receipt, an otherwise valid unowned vault reportsmanaged_by_builder: false. Post-build acceptance must use--require-build-receipt. - Any invalid or unknown receipt, missing or changed managed content, unsafe link, or pending transaction makes the required audit unhealthy. Run
recoveronly as an explicit mutating operation.
Guardrails
- Keep source files portable: Markdown, ordinary attachments, and the skill-owned JSON receipt.
- Create the
.obsidianmarker directory, but do not write undocumented.obsidian/*.jsonapplication settings. Obsidian may change those private formats. - Use Obsidian properties as flat YAML. Do not invent nested property schemas that the Properties UI does not support.
- Prefer stable folder paths and links. Avoid characters Obsidian documents as unsafe in links.
- Do not modify Obsidian's global vault registry or launch the GUI.
- Do not enable Sync, publish content, or copy settings from another vault.
- Reject filesystem roots, the user's home directory,
.obsidianitself, and a target nested inside another vault. - Reject parent traversal, symbolic-link path components, special files, hardlinked managed files, unsafe ownership, and directories writable by other users. Path display via
resolve()is not a security boundary. - Keep
.awesome-capture, its lock, receipts, and journals private. Ordinary vault Markdown remains readable as normal0644content. - Do not overwrite. A conflict must be resolved by the user or by generating a new path.
- Keep templates minimal; add automation only after the base vault works.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

