obsidian-cli
Section titled “obsidian-cli”Obsidian’s built-in CLI (enabled 2026-08-20, Settings → General → Command line interface), used as a headless render-verification harness from WSL — eval runs JS inside the running app, dev:screenshot grabs a PNG. Lets an agent confirm a Dataview/dataviewjs render matches expected output without asking Talbot to look.
Invocation from WSL
Section titled “Invocation from WSL”- PATH is stale in an already-open WSL/terminal session — the registry
UserPATH gets the entry the moment the toggle is flipped, but a shell whose ancestor process launched before that won’t see it until a fresh top-level process. Don’t fight it — call the exe directly:C:\Users\Admin\AppData\Local\Programs\Obsidian\Obsidian.exe - Route through PowerShell, not
cmd.exe(quoting is far less fragile):Terminal window /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile -Command "& \"C:\Users\Admin\AppData\Local\Programs\Obsidian\Obsidian.exe\" eval \"code=<js>\"" - Quoting rule that matters: wrap the whole
-Commandin double quotes, then wrapcode=<js>in double quotes too, and write the JS itself using single-quote strings only. PowerShell single-quoted strings don’t process\"escapes — a\"meant for a JS string literal survives as a literal backslash and breaks the JS parser (Error: Unexpected token '.'with no other clue). A base64-encode-then-decode-in-a-.ps1-file workaround was tried and abandoned — same failure, not worth the extra layer. evalawaits a returned Promise and prints the resolved value — async IIFEs work fine ((async()=>{...})()).- No
vault=needed when exactly one vault is open (this machine:D:\FSS\KB, registered in%APPDATA%\Obsidian\obsidian.json). setTimeoutinsideevalcode silently kills the response — the CLI’s IPC round-trip never returns (no output, no error, not even the=>prefix), tested at both 500ms and 1500ms. Needing to wait for a render (setState({mode:'preview'})) means splitting into two separateevalcalls: one that awaitssetStatealone (resolves fast, no timer), and a second call afterward that reads the DOM — the gap between two separate CLI invocations is real wall-clock delay without ever usingsetTimeout.
Confirmed working (2026-08-20)
Section titled “Confirmed working (2026-08-20)”Used to verify Focus/scripts/ecco-view.js’s render (ecco-notepads-build Phase 0/1): opened Focus/proofs/ecco-view-engine-proof.md, forced the active leaf to reading mode, read back .block-language-dataviewjs elements’ innerText, and confirmed it matched the algorithm’s expected output exactly — no manual look-and-confirm needed.
Scope / gotchas
Section titled “Scope / gotchas”Obsidian.exe --helpalso prints “installer out of date” every call — harmless, ignore (the running app is 1.13.7 regardless of what the installer stub reports; see AGENTS.md’s installer-version-lies rule).- Multiple leaves/tabs open on the same file render the same query more than once in the DOM — dedupe by content when reading back, don’t assume one block per query.