agentleFS
cyberpinkmancyberpinkman/awesome-capture/skills/build-obsidian-vault/SKILL.md

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.

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
  1. Distinctive:

    Use Python 3.11–3.14 on macOS or Linux.

    line 12
  2. Very specific:

    Before any mutating operation, the script requires fcntl, directory-FD operations, O_NOFOLLOW, O_DIRECTORY, directory fsync, atomic …

    line 13
  3. Distinctive:

    Keep the skill independently runnable.

    line 16
  4. Distinctive:

    Use short multi-turn questions.

    line 20
  5. Distinctive:

    Read profiles.md after the first answer.

    line 28
  6. Distinctive:

    Write one config JSON conforming to config-schema.md.

    line 32
  7. Very specific:

    Read the plan_sha256 from the plan JSON.

    line 47
  8. Very specific:

    Never reuse a digest after the config or observed vault contents change.

    line 64
  9. Distinctive:

    Run the post-build audit and require the formal build receipt:

    line 65
  10. Very specific:

    All lock-taking commands accept --lock-timeout.

    line 74
  11. Distinctive:

    Before a new build, the script automatically finishes a provably matching pending build transaction.

    line 83
  12. Distinctive:

    Keep source files portable: Markdown, ordinary attachments, and the skill-owned JSON receipt.

    line 100
  13. Very specific:

    Create the .obsidian marker directory, but do not write undocumented .obsidian/*.json application settings.

    line 101
  14. Distinctive:

    Use Obsidian properties as flat YAML.

    line 102
  15. Distinctive:

    Prefer stable folder paths and links.

    line 103
  16. Distinctive:

    Do not modify Obsidian's global vault registry or launch the GUI.

    line 104
  17. Distinctive:

    Do not enable Sync, publish content, or copy settings from another vault.

    line 105
  18. Very specific:

    Keep .awesome-capture, its lock, receipts, and journals private.

    line 108
  19. Distinctive:

    Do not overwrite. A conflict must be resolved by the user or by generating a new path.

    line 109
  20. Distinctive:

    Keep templates minimal; add automation only after the base vault works.

    line 110

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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, directory fsync, atomic no-replace rename, and atomic exchange rename. If the platform cannot provide them, stop with UNSUPPORTED_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.

  1. 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?
  2. 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?
  3. 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

  1. Write one config JSON conforming to config-schema.md. Keep it outside the target vault until validated.
  2. 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-existing only after the user accepts every destination and conflict.

  3. Validate and preview:

    python3 scripts/vault_builder.py validate-config "<config.json>"
    python3 scripts/vault_builder.py plan "<config.json>" --vault "<absolute-vault-path>"
  4. Read the plan_sha256 from the plan JSON. 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.
  5. 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_PLAN if it no longer matches. Run plan again and obtain fresh confirmation.

  6. Run the post-build audit and require the formal build receipt:

    python3 scripts/vault_builder.py audit \
      --vault "<absolute-vault-path>" --require-build-receipt
  7. 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.json last. It is an awesome-capture.vault-build-receipt/v1 object 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/v1 journal 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.
  • audit is 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 reports managed_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 recover only as an explicit mutating operation.

Guardrails

  • Keep source files portable: Markdown, ordinary attachments, and the skill-owned JSON receipt.
  • Create the .obsidian marker directory, but do not write undocumented .obsidian/*.json application 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, .obsidian itself, 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 normal 0644 content.
  • 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.