Command-line interface for inspecting, resolving, and provisioning Obsidian vault resources. Provides diagnostics and automation for vault content, skills, and agents.
Run directly via npx (no install required):
npx @obsidian-vfs/cli --help
npx @obsidian-vfs/cli inspect "@obs:architect" --body
npx @obsidian-vfs/cli provision-skillsOr install globally:
npm install -g @obsidian-vfs/cli
obsidian-vfs --helpFrom the workspace root (after building):
pnpm build
pnpm cli --help| Flag | Description |
|---|---|
--json |
Machine-readable JSON output |
--verbose, -v |
Timing diagnostics |
--description |
Show descriptions (list-skills, list-agents) |
--user |
Provision to ~/.claude/ (user-global) instead of .claude/ (project-level) |
--help, -h |
Show usage information |
Resolve a wikilink, vault-relative path, or /obs: skill to its vault path.
npx @obsidian-vfs/cli resolve "Project Plan"
npx @obsidian-vfs/cli resolve "[[Project Plan]]"
npx @obsidian-vfs/cli resolve "/obs:obsidian"
npx @obsidian-vfs/cli resolve "Note" --jsonUses the Obsidian CLI's search with file:<name> to find candidates, then picks the exact basename match. When multiple files share the same basename, the shortest vault-relative path wins. This differs from the raw search order — Obsidian's search returns results in its own relevance ranking, which may place partial matches before exact ones.
Inspect a mention — shows resolved path, target type, and content.
npx @obsidian-vfs/cli inspect "architect"
npx @obsidian-vfs/cli inspect "10-projects/plan.md#Architecture"
npx @obsidian-vfs/cli inspect "obs://vault/path/to/note#section"
npx @obsidian-vfs/cli inspect "/obs:obsidian"| Flag | Description |
|---|---|
--body |
Output only the raw content body (no metadata headers, no truncation) |
--full |
Show full content without truncation |
The plugin's obs-read bin script calls inspect --body internally for hook-triggered reads. inspect is the general-purpose CLI command; obs-read is a thin entry point used by plugin hooks at runtime.
Enumerate all skills discovered from the vault's skills directories (see Vault Configuration).
npx @obsidian-vfs/cli list-skills
npx @obsidian-vfs/cli list-skills --description
npx @obsidian-vfs/cli list-skills --jsonOutput is compact by default (name and vault-relative path only). Pass --description to include the description column.
Enumerate all agents discovered from the vault's agents directories.
npx @obsidian-vfs/cli list-agents
npx @obsidian-vfs/cli list-agents --description
npx @obsidian-vfs/cli list-agents --jsonOutput is compact by default (name and vault-relative path only). Pass --description to include the description column.
Generate thin proxy files under .claude/skills/ that Claude Code treats as native skills. Each proxy contains a !command`` directive that fetches live content from the vault at invocation time.
npx @obsidian-vfs/cli provision-skills
npx @obsidian-vfs/cli provision-skills --dry-run
npx @obsidian-vfs/cli provision-skills --include deploy --include review
npx @obsidian-vfs/cli provision-skills --exclude "draft-*"
npx @obsidian-vfs/cli provision-skills --pin
npx @obsidian-vfs/cli provision-skills --user
npx @obsidian-vfs/cli provision-skills --json
npx @obsidian-vfs/cli provision-skills --set model=opus
npx @obsidian-vfs/cli provision-skills --set model=claude-sonnet-4-6 --set allowed-tools=Bash
npx @obsidian-vfs/cli provision-skills --unset argument-hint
npx @obsidian-vfs/cli provision-skills --set model=opus --unset argument-hint| Flag | Description |
|---|---|
--dry-run |
Preview without writing |
--include <glob> |
Only provision matching skills (repeatable) |
--exclude <glob> |
Skip matching skills (repeatable) |
--pin |
Pin generated commands to the current CLI version |
--user |
Provision to ~/.claude/skills/ and ~/.claude/settings.json instead of project-level |
--set <key=value> |
Override a frontmatter attribute (repeatable) |
--unset <key> |
Remove a frontmatter attribute (repeatable) |
Obsidian vault skills live outside the project directory. Claude Code only discovers skills from .claude/skills/ (project-level), ~/.claude/skills/ (personal), or a plugin's skills/ directory — it has no mechanism to reach into an arbitrary vault path, and there is no API for dynamically registering skills at runtime.
The Claude plugin's @obs: hook can inject vault content via additionalContext, but content delivered this way is treated as passive context, not as an actionable skill. It lacks the full native skill lifecycle:
| Feature | Native skill | additionalContext |
|---|---|---|
/ autocomplete |
Listed with description | Not listed |
$ARGUMENTS substitution |
Automatic | Not available |
context: fork (subagent isolation) |
Supported | Not available |
| Compaction survival | Re-attached (5K tokens each, 25K budget) | Dropped |
allowed-tools (pre-authorized permissions) |
Supported | Not available |
| Model/effort override | Via frontmatter or --set/--unset |
Not available |
| Live change detection | Watched directories | N/A |
Provisioning bridges this gap: it generates thin proxy files that Claude Code discovers natively, while the actual content is fetched live from the vault.
Each proxy contains a !command`` directive that fetches live vault content:
---
name: deploy
description: Deploy helper
---
!`npx --yes @obsidian-vfs/cli inspect --body "/obs:deploy"`The proxy lives at .claude/skills/deploy/SKILL.md. When invoked, the !command`` preprocessor runs the CLI's inspect --body, which bootstraps the core tracker, resolves the skill from the vault, and outputs content to stdout. Claude receives this as the skill body with full native lifecycle: frontmatter metadata, autocomplete, forked context, compaction survival.
By default, generated commands reference the package name without a version (@obsidian-vfs/cli), so they always resolve to the latest published version. Pass --pin to pin commands to the currently running CLI version (@obsidian-vfs/cli@0.1.0).
When OBSIDIAN_VFS_PROJECT_DIR is set, provisioning emits ./bin/obs-read instead (see Environment Variables).
Provisioning adds a single generic allow rule to .claude/settings.local.json:
Bash(npx --yes @obsidian-vfs/cli inspect --body *)
When --pin is passed, the rule pins to the current CLI version:
Bash(npx --yes @obsidian-vfs/cli@0.1.0 inspect --body *)
When OBSIDIAN_VFS_PROJECT_DIR is set, the rule uses the local path instead: Bash(./bin/obs-read *).
- Enumerates every
skillsdirectory from the vault config, finds subdirectories containingSKILL.md, extracts frontmatter, and writes proxy files. - Writes are idempotent — identical proxies are skipped.
- Skill names validated against
/^[a-zA-Z0-9._-]+$/; shell metacharacters rejected. - When multiple
skillsdirectories contain a skill with the same name, the first directory wins. - Add-only — never removes proxy files or permission rules. Delete
.claude/skills/<name>/and the corresponding rule from.claude/settings.local.jsonmanually. - When a filter is active (
--include/--exclude), unmatched skills appear asskippedbut existing proxies are never removed.
Generate proxy agent files under .claude/agents/.
Unlike skill proxies, agent proxies write the full vault content at provisioning time. This is a Claude Code platform constraint: the !commandpreprocessing that enables live content loading is a `SKILL.md`-only feature — it does not work in agent files. An agent file containing !command `` produces the literal text, not the command output.
Two workarounds exist for dynamic content in agents:
- Write full content at generation time (what this command does) —
[[wikilinks]]are scrubbed toobs://URIs so Claude can follow them viaobs-readat runtime. - Preload a skill via the
skillsfrontmatter field — the skill can use!command``, and its rendered content is injected into the agent's context at startup.
npx @obsidian-vfs/cli provision-agents
npx @obsidian-vfs/cli provision-agents --dry-run
npx @obsidian-vfs/cli provision-agents --include architect --include reviewer
npx @obsidian-vfs/cli provision-agents --exclude "draft-*"
npx @obsidian-vfs/cli provision-agents --pin
npx @obsidian-vfs/cli provision-agents --user
npx @obsidian-vfs/cli provision-agents --json
npx @obsidian-vfs/cli provision-agents --set model=opus
npx @obsidian-vfs/cli provision-agents --set model=haiku --set allowed-tools="Bash, Read"
npx @obsidian-vfs/cli provision-agents --unset allowed-tools
npx @obsidian-vfs/cli provision-agents --set model=opus --unset argument-hint| Flag | Description |
|---|---|
--dry-run |
Preview without writing |
--include <glob> |
Only provision matching agents (repeatable) |
--exclude <glob> |
Skip matching agents (repeatable) |
--pin |
Pin generated commands to the current CLI version |
--user |
Provision to ~/.claude/agents/ and ~/.claude/settings.json instead of project-level |
--set <key=value> |
Override a frontmatter attribute (repeatable) |
--unset <key> |
Remove a frontmatter attribute (repeatable) |
| Aspect | provision-skills |
provision-agents |
|---|---|---|
| Output format | .claude/skills/<name>/SKILL.md (directory) |
.claude/agents/<name>.md (flat file) |
| Body mechanism | !command`` loads fresh content per session |
Full content written at provisioning time |
| Frontmatter | Minimal (name + description), overridable via --set/--unset |
All fields forwarded from vault, overridable via --set/--unset |
| Wikilink scrubbing | At runtime by obs-read |
At provisioning time by CLI |
| Permissions | Single generic Bash(npx ... inspect --body *) |
Same generic rule |
| Content freshness | Always current | Stale until re-provisioned |
Same add-only behavior as skills. Delete .claude/agents/<name>.md manually to remove a deprovisioned agent.
Provisioning automatically remaps non-Claude model: values in vault frontmatter to the closest Claude equivalent. Claude model names (haiku, sonnet, opus) pass through unchanged.
| Vault model | Maps to | Tier |
|---|---|---|
gemini-*flash-lite* |
haiku |
Lightweight |
gpt-4o-mini* |
haiku |
Lightweight |
gpt-3.5* |
haiku |
Lightweight |
gemini-*flash* |
sonnet |
Balanced |
gemini-*pro* |
sonnet |
Balanced |
gpt-4o |
sonnet |
Balanced |
gpt-4-turbo* |
sonnet |
Balanced |
gemini-*ultra* |
opus |
Most capable |
gpt-4.5* |
opus |
Most capable |
o1* |
opus |
Most capable |
o3* |
opus |
Most capable |
| (unrecognized) | sonnet |
Default fallback |
Mapping runs during provisioning only — vault source notes are never modified. Mapping runs during provisioning inside buildFrontmatter for both skills and agents, before --set/--unset overrides are applied. --set model=opus always writes the value verbatim regardless of the vault source model.
By default, provisioning writes to the project directory:
| Target | Path |
|---|---|
| Skills | .claude/skills/ |
| Agents | .claude/agents/ |
| Permissions | .claude/settings.local.json |
With --user, provisioning writes to the user-global directory:
| Target | Path |
|---|---|
| Skills | ~/.claude/skills/ |
| Agents | ~/.claude/agents/ |
| Permissions | ~/.claude/settings.json |
User-global agents and skills are available across all Claude Code sessions without per-project provisioning. Project-level resources take priority when both exist.
Known limitation: --user combined with OBSIDIAN_VFS_PROJECT_DIR produces project-relative ./bin/obs-read paths in global proxies, which may not resolve correctly from other directories. Avoid combining the two.
| Variable | Purpose | Default |
|---|---|---|
OBSIDIAN_VFS_CLI_PATH |
Path to the Obsidian CLI binary | "obsidian" |
OBSIDIAN_VFS_TIMEOUT_MS |
CLI operation timeout in milliseconds | 10000 |
OBSIDIAN_VFS_PROJECT_DIR |
Local project dir for provisioning (emits ./bin/obs-read instead of npx) |
unset |
Controls how provisioning emits !command`` directives and permission rules:
| Value | !command output (unpinned) |
!command output (--pin) |
Use case |
|---|---|---|---|
| Unset | npx --yes @obsidian-vfs/cli inspect --body "/obs:skill" |
npx --yes @obsidian-vfs/cli@0.1.0 inspect --body "/obs:skill" |
Production — end users |
. |
./bin/obs-read "/obs:skill" |
./bin/obs-read "/obs:skill" |
Developing inside the repo |
/path/to/obsidian-vfs |
/path/to/obsidian-vfs/bin/obs-read "/obs:skill" |
/path/to/obsidian-vfs/bin/obs-read "/obs:skill" |
Local checkout from another project |
Only affects provisioning output. Does not change runtime behavior of obs-read, inspect, or hook resolution.
export OBSIDIAN_VFS_PROJECT_DIR=.
npx @obsidian-vfs/cli provision-skills # emits ./bin/obs-read in proxiesFor upstream Claude Code documentation on skills, agents, hooks, and plugins, see the Claude plugin README.