--- name: wiki-cli description: "Default vault-mutation transport for claude-obsidian v1.7+. Wraps the Obsidian CLI (Obsidian 1.12+) as the preferred way to read, write, search, and modify vault notes from Claude — no MCP server, no REST API plugin, no TLS workarounds. Falls back to direct filesystem Read/Write/Edit when the CLI is unavailable. Triggers on: wiki-cli, obsidian cli, obsidian read, obsidian write, obsidian search, daily note, obsidian create, obsidian append, vault transport, which transport, transport detection, obsidian command line." allowed-tools: Read Bash --- # wiki-cli: Default Transport Layer claude-obsidian v1.7+ standardizes on the **Obsidian CLI** (shipped with Obsidian 1.12) as the preferred transport for all vault mutations on desktop. This skill is the recipe reference for using it. **Substrate preference (v1.7+)**: This skill is a self-contained fallback. **Prefer `kepano/obsidian-skills`** (by Steph Ango, Obsidian CEO) as the authoritative substrate — its `obsidian-cli` skill is the canonical CLI reference for any Agent-Skills runtime. If you see an `obsidian-cli` skill available without the `claude-obsidian:` namespace, that is kepano's version: use it. The recipes below are provided so claude-obsidian remains functional when kepano's marketplace is not installed. Install kepano: `claude plugin marketplace add kepano/obsidian-skills`. --- ## Why CLI over MCP | Concern | MCP (Options A/B) | Obsidian CLI | |---|---|---| | Install | Local REST API plugin + MCP server config | Built into Obsidian 1.12+ | | Auth | API key + TLS bypass (`NODE_TLS_REJECT_UNAUTHORIZED=0`) | None — direct subprocess | | Latency | HTTP round-trip per call | In-process binary | | Failure mode | Plugin disabled → silent breakage | Binary missing → loud `command -v` failure | | Reentrancy | Self-MCP-calls inside Claude session can deadlock | Pure subprocess, safe | | Mobile / headless | Limited | Limited (CLI is desktop-only too) | CLI loses to MCP on exactly one axis: it only works on machines where Obsidian itself is installed. For headless servers and mobile, fall through to the next transport in the chain. --- ## Detection At session start (or vault setup), run: ```bash bash scripts/detect-transport.sh ``` This writes `.vault-meta/transport.json` with the schema: ```json { "preferred": "cli", "fallback_chain": ["cli", "filesystem"], "available": { "cli": {"present": true, "binary": "obsidian-cli", "version_string": "..."}, "filesystem": {"present": true}, "mcp_obsidian": {"present": null, "detection": "deferred"}, "mcpvault": {"present": null, "detection": "deferred"} } } ``` **Read this file before any non-trivial vault mutation.** Skills that need to read or write should consult `preferred` and pick the corresponding transport. The decision tree lives at `wiki/references/transport-fallback.md`. Refresh detection with `--force` after installing/removing the Obsidian CLI: ```bash bash scripts/detect-transport.sh --force ``` --- ## Recipes (CLI-first; fallback noted inline) Each recipe shows the CLI form first. If the CLI is unavailable per the detection snapshot, fall through to the noted fallback. Variable substitution: `$VAULT` is the absolute vault root; `$NOTE` is a vault-relative path like `wiki/concepts/Foo.md`. ### Read a note ```bash # CLI obsidian-cli read "$VAULT" "$NOTE" # Fallback: Claude's Read tool with absolute path # Read $VAULT/$NOTE ``` ### Create or overwrite a note ```bash # CLI obsidian-cli write "$VAULT" "$NOTE" < /path/to/content.md # Fallback: Claude's Write tool with absolute path # Write $VAULT/$NOTE with the desired content string ``` ### Append to a note ```bash # CLI echo "additional content" | obsidian-cli append "$VAULT" "$NOTE" # Fallback: Read $VAULT/$NOTE, append manually, Write back ``` ### Search note content (CLI uses Obsidian's own search ranking) ```bash # CLI obsidian-cli search "$VAULT" "" # Fallback: ripgrep rg --type=md "" "$VAULT/wiki/" ``` ### Today's daily note (if Daily Notes plugin is enabled) ```bash # CLI obsidian-cli daily:today "$VAULT" obsidian-cli daily:append "$VAULT" "captured at $(date)" # Fallback: compute path manually NOTE="$VAULT/wiki/daily/$(date +%Y-%m-%d).md" ``` ### Patch a frontmatter property ```bash # CLI obsidian-cli property:set "$VAULT" "$NOTE" status "evergreen" # Fallback: read frontmatter, parse, mutate, rewrite (use mcp__obsidian-vault__update_frontmatter if MCP is configured) ``` ### List backlinks for a page ```bash # CLI obsidian-cli backlinks "$VAULT" "$NOTE" # Fallback: ripgrep for wikilink references rg --type=md "\[\[$(basename "$NOTE" .md)" "$VAULT/wiki/" ``` ### Open a Bases (.base) file's resolved view ```bash # CLI obsidian-cli bases "$VAULT" "$NOTE" # (returns the resolved row list; supplements obsidian-bases skill which handles the .base file's YAML) # Fallback: read the .base file directly; no resolved-view available without Obsidian itself ``` ### Tags + bookmarks ```bash obsidian-cli tags "$VAULT" obsidian-cli bookmarks "$VAULT" ``` --- ## When CLI is NOT the right choice - **Mobile (iOS Share extension)**: filesystem write into `.raw/` is the only path; CLI is desktop-only. - **CI / headless ingest jobs**: filesystem with manual frontmatter parsing. - **Cross-vault operations**: CLI binds to one vault root per invocation; for federation, fall back to filesystem walks. - **Live edits while Obsidian is mid-save**: rare race; CLI handles it correctly but in pathological cases the v1.7 `wiki-lock.sh` advisory locks (see [skills/wiki-fold/](../wiki-fold/SKILL.md) and `agents/wiki-ingest.md`) should be acquired first. --- ## Cross-reference - Decision tree: [`wiki/references/transport-fallback.md`](../../wiki/references/transport-fallback.md) - Legacy MCP options (A/B/C/D): [`skills/wiki/references/mcp-setup.md`](../wiki/references/mcp-setup.md) - Concurrency policy (v1.7+): [`skills/wiki-ingest/SKILL.md`](../wiki-ingest/SKILL.md) §Concurrency - Detection script: [`scripts/detect-transport.sh`](../../scripts/detect-transport.sh) --- ## How to think (10-principle mapping) When working on this skill, apply the 10-principle loop. See [`skills/think/SKILL.md`](../think/SKILL.md) for the canonical framework. | # | Principle | Application here | |---|-----------|-------------------| | 1 | OBSERVE (ext) | Detect which Obsidian CLI binaries are installed; check if Obsidian app is running. Read `.vault-meta/transport.json` if it exists. | | 2 | OBSERVE (int) | Don't be biased toward filesystem fallback when CLI is actually available — verify auto-detection caught what's installed. | | 3 | LISTEN | If `manual_override: true` is set in transport.json, the user has spoken — preserve their `preferred` and `fallback_chain`. | | 4 | THINK | Compute the right fallback chain for this environment. CLI > MCP > filesystem; freshness check before recomputing. | | 5 | CONNECT (lat) | How does this transport choice affect every other skill's write? Six downstream skills depend on this snapshot. | | 6 | CONNECT (sys) | Schema stability of transport.json matters more than feature richness — consumers parse the JSON via simple shell idioms. | | 7 | FEEL | Error message when no transport works should tell the user EXACTLY what to do (install CLI, configure MCP, etc.). | | 8 | ACCEPT | Filesystem fallback is fine. Admit when CLI doesn't exist; don't fabricate a binary that isn't there. | | 9 | CREATE | Write transport.json atomically (temp + rename). Round-trip `manual_override` every cycle. | | 10 | GROW | As MCP support matures, auto-detection should cover the deferred tiers. Track that as v1.7.x scope. |