2026-08-18 — setting up Claude Code for the vault

First session. Goal: make Claude Code usable against this vault through the official Obsidian CLI, and encode the conventions so an agent writes notes that fit.

What was found

A six-way parallel survey of the vault and the Quartz repo. The findings that changed decisions:

Publishing is opt-out, not opt-in. publish ?? true — a note with no publish key goes live. At the time, 303 of 325 public notes were public purely by default. This became the organising fact of the whole setup. Details in publishing.md.

The Assets emitter has no publish filter. assets.ts globs every non-markdown file and copies it out without consulting shouldPublish. Verified by reading the source. Reviewed and accepted as-is.

The CLI’s daily:* commands pointed at the wrong folder. The CLI reads the core daily-notes plugin; this vault uses the periodic-notes community plugin, and core had never been configured. obsidian daily:path returned Inbox/2026-08-18.md instead of Journal/2026/08/2026-08-18.md. Every daily command would have written to the wrong place.

The weekly note is the live ritual, not the daily. Weeklies are filled in every week; dailies are sporadic, with a seven-month gap in the recent record. Any workflow that assumes a daily note exists is built on sand.

A user-level monthly-report skill targets a different vault. Both vaults use an identical Journal/YYYY/MM/YYYY-MM-DD.md layout, so they look interchangeable. This one has no ## Doing sections at all. Running it here would produce an empty report and write into the wrong tree.

Decisions

Daily notes: configure core to match, rather than ban the commands. The rejected alternative was to forbid daily:* in the agent instructions and compute paths by hand. That leaves the CLI half-broken for interactive use too. Writing .obsidian/daily-notes.json to mirror periodic-notes fixes it for both. Verified both plugins now resolve the same path.

Weekly notes have no core equivalent, so they go through obsidian command id="periodic-notes:open-weekly-note" — the same code path the Calendar plugin uses. Notes are never created by writing a file.

Setup lives at the repo root, not in the vault. CLAUDE.md and .claude/skills/ sit outside digital-garden/, so the build cannot publish them by accident. (Claude/ itself is a later, deliberate exception — it is published on purpose.)

Read-only CLI commands were allowlisted; eval was not. obsidian eval runs arbitrary JavaScript in the app and can mutate the vault, so it still prompts.

What was built

  • CLAUDE.md at the repo root — the always-loaded safety rules, pointing here.
  • .claude/skills/garden-capture, garden-inbox, garden-journal, garden-publish-check.
  • .claude/skills/garden-publish-check/scripts/publish_audit.py — replicates the real pipeline (glob → ignorePatterns → RemoveDrafts → ExplicitPublish) plus the unfiltered Assets emitter. Exits 1 on a high-severity finding so it can gate a push.
  • .claude/settings.json — allowlist for read-only obsidian commands.

The audit script’s highest-value check is the YAML one: under yaml.JSON_SCHEMA, only a bare false is a boolean, so publish: "false", publish: no and publish: False all publish. Tested against a scratch vault built for the purpose.

The frontmatter cleanup

A single pass over the 373 publishable notes (325 public + 48 in Inbox/), changing 354 of them:

ActionNotes
publish: true added (already-public)303
Created: … body line removed267
title: added204
H1 removed (matched filename/title)68
publish: false added (Inbox/)28
H1 removed, text promoted to title:8
Frontmatter block created from scratch7
H1 demoted to a plain link line2
published: typo replaced with publish:1

The invariant: membership of the public set had to be identical before and after. It was — 325 both sides — while “public by default” went 303 → 0. Silence no longer publishes anything.

Removing 78 H1s could have orphaned [[Note#heading|Heading]] anchor links, so the audit was also run against a clean git archive of HEAD and compared: broken links 44 before, 44 after. Frontmatter was then re-parsed with Quartz’s own gray-matter + js-yaml at JSON_SCHEMA — 781 files, 0 errors.

Three judgment calls worth keeping:

  • Ten Books/Can't Hurt Me/ notes have an H1 of the form # Challenge #5. That is content, not a title. Left intact.
  • Where an H1 was a reworded or shortened filename, its text was promoted to title: rather than discarded. This is how 00 12 Rules for Life.md got title: 12 Rules for Life, and how one book index note recovered a colon a filename cannot hold.
  • Two MoC notes had an H1 wrapping the title in the project’s official URL. The heading was demoted to a plain markdown link so the URL survived.

Created: matching skipped fenced code blocks, so no code sample lost a line.

Corrections — claims that were wrong

Recorded because they were believed and acted on before being checked.

The CLI was reported as “not installed”. It was installed and working the whole time; which obsidian resolves through the app bundle.

Obsidian Sync was reported as “not configured”. It is on, under the vault name “Digital Garden”. The absence of a sync.json was read as absence of sync.

Four CLI commands were documented as permanently broken on the outdated installer — search, help, commands, version. Re-testing showed all four work. The real behaviour is intermittent empty output when the app is cold, which makes an empty result untrustworthy rather than impossible. The instruction that replaced it — empty output is not a result, re-run before concluding — is the more useful rule anyway, because a false “nothing found” is what creates a duplicate note.

A weekly-alias mismatch count was stated as 33, then 35. Recomputed: 37, and not confined to 2021–22 as claimed — one each in 2025 and 2026. So it is a live mistake to guard against, not a historical artefact.

The pattern in all four: a plausible reading of indirect evidence, stated with more confidence than the evidence carried. Cheap to check, and each check took under a minute.

Side effects

A subagent ran periodic-notes:open-daily-note while verifying commands, which created that day’s daily note and left it staged. Unstaged and reported rather than quietly deleted — it is the author’s file, and an empty daily note in the right place is not damage.

Left undone

  • The Assets emitter still copies non-markdown files with no publish filter. Reviewed and accepted; the fix would be patching assets.ts.
  • Research/Research.canvas and publish.css publish verbatim. Both expected.
  • Broken links inside published notes render as dead text on the site. Not touched — fixing them is editorial.
  • One published book index note is entirely a Dataview query, which Quartz cannot render, leaving its chapter notes unreachable from the site.