pi-obsidian-cli

Dynamic pi extension wrapping the official Obsidian CLI with fixed permission gating, 52 typed read-only catalog tools, audited fixed-purpose wrappers, and an interactive TUI browser

Packages

Package details

extension

Install pi-obsidian-cli from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-obsidian-cli
Package
pi-obsidian-cli
Version
0.8.3
Published
Aug 22, 2026
Downloads
626/mo · 626/wk
Author
frnn
License
MIT
Types
extension
Size
1.5 MB
Dependencies
0 dependencies · 5 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ],
  "image": "./docs/preview.png"
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-obsidian-cli

npm version npm downloads License

Dynamic pi extension wrapping the official Obsidian CLI (v1.13+) with fixed permission gating, 52 typed read-only catalog tools, audited fixed-purpose wrappers, prompt guidelines, and an interactive TUI browser.

Talks directly to the obsidian binary — no MCP server or Obsidian plugin dependency, with no extra setup beyond enabling the CLI in Obsidian.

Read the project story and design rationale: Safe Obsidian tools for Pi agents.

pi-obsidian-cli preview

Safety Defaults

  • Read-only permissions are enabled by default.
  • No write-capable profiles are registered by default.
  • Generic eval is disabled by default.
  • DataviewJS requires explicit opt-in and confirmation.
  • Fixed-purpose wrappers are audited separately from generic evaluation.

Quick Start

Install from npm (recommended)

pi install npm:pi-obsidian-cli

Install from git

pi install git:github.com/frNNcs/pi-obsidian-cli

Install from local clone (development)

git clone https://github.com/frNNcs/pi-obsidian-cli
cd pi-obsidian-cli
npm ci

Then install from the local path (run these from your terminal, not inside a pi session):

# Project-local (writes .pi/settings.json in the current project; the local path
# is referenced as-is — no copy, no symlink — and takes effect after /reload):
pi install -l /absolute/path/to/pi-obsidian-cli

# Global (writes pi's global settings.json; same no-copy behaviour):
pi install /absolute/path/to/pi-obsidian-cli

Note: Use absolute paths with pi install. Relative paths may not resolve correctly inside pi's runtime. If pi asks for trust, run /trust in a pi session or pass --approve on the CLI.

After installing, configure your vault in pi's settings.json:

{
  "obsidianCli": {
    "vault": "my-vault",
    "permissionMode": "read-only"
  }
}

Reload with /reload and you're done.

Prerequisites

  • Node.js >= 22.19.0
  • Obsidian 1.13+ running
  • CLI enabled: Settings → General → Advanced → Command line interface
  • obsidian binary on your PATH

Development

See docs/development.md for the full step-by-step circuit: clone → npm ci → typecheck → test → install locally → release.

Quick reference:

npm ci                    # clean install from lockfile
npm run check             # TypeScript type-check (tsc --noEmit)
npm run pack:dry          # validate packaging integrity

# Test with pi — loads ONLY this extension, no duplicates:
pi --no-extensions -e ./index.ts

What You Get

52 Typed Read-Only Catalog Tools

The current Obsidian CLI catalog exposes 52 read-only commands as dedicated tools with typed parameters, structured JSON/TSV output, and contextual defaults (active file, vault):

Category Tools
Files & Folders obsidian_read, obsidian_files, obsidian_folders, obsidian_file, obsidian_folder, obsidian_outline
Search obsidian_search, obsidian_search_context
Tasks & Tags obsidian_tasks, obsidian_tags, obsidian_tag
Properties obsidian_properties, obsidian_property_read
Links & Graph obsidian_links, obsidian_backlinks, obsidian_orphans, obsidian_deadends, obsidian_unresolved
Bases obsidian_bases, obsidian_base_query, obsidian_base_views
Daily Notes obsidian_daily, obsidian_daily_path
Sync obsidian_sync_status, obsidian_sync_history, obsidian_sync_read, obsidian_sync_deleted
History obsidian_history, obsidian_history_list, obsidian_history_read
Plugins & Themes obsidian_plugins, obsidian_plugin, obsidian_themes, obsidian_theme
Workspace obsidian_workspace, obsidian_tabs, obsidian_recents
Special obsidian_active_file, obsidian_resolve_link

Audited Fixed-Purpose Wrappers

These wrappers are separate from the read-only catalog and can be enabled without enabling generic eval:

  • obsidian_excalidraw_export
  • obsidian_excalidraw_mermaid
  • obsidian_active_file
  • obsidian_resolve_link
  • obsidian_dataview_query
  • obsidian_tasks_query
  • obsidian_daily creation

obsidian_dataviewjs_run remains separate and opt-in because it evaluates user-supplied JavaScript and always requires confirmation.

Permission Gating (Fixed by Code, Not Prompt)

Three modes with risk classification (read / write / danger):

{
  "obsidianCli": {
    "permissionMode": "read-only",
    "exclude": ["eval", "command", "dev:*", "restart", "reload"],
    "confirmDestructive": true
  }
}
  • read-only — only read commands (default, safe)
  • all — everything minus exclude
  • custom — only commands matching include (minus exclude)

Blocked commands fail with an explanation of exactly which setting to change — the policy cannot be negotiated from the prompt.

Fixed-script tools and confirmation. Audited fixed-purpose wrappers run when allowFixedScripts is enabled (the default) without enabling generic eval. Fixed wrappers do not prompt themselves; write-capable operations use the central confirmation path. The general obsidian tool and arbitrary eval commands remain governed by permission mode and exclude.

Interactive TUI Browser

Run /obsidian to open the browser:

  • Filter with / + Tab autocomplete (longest common prefix, cycles with Tab/Shift+Tab)
  • Risk badges (◦ read · ● write · ▲ danger)
  • Argument editor with inline flag reference
  • Scrollable output with TSV column alignment
  • m cycle permission mode (session-only)
  • v set vault · r rediscover catalog

Inline mode: /obsidian read path=Notes/hello.md runs directly.

Prompt Guidelines

Dedicated tools carry concise usage guidance (promptGuidelines) telling the LLM to use them instead of built-in read/bash/grep/ls/find for vault operations.


Configuration Reference

Key Default Description
binary "obsidian" Path to the CLI binary
autoLaunch false Allow the CLI to launch the Obsidian GUI when the app is not running. Disabled by default; keep Obsidian open before using obsidian_* tools.
vault (active) Default vault name or id
permissionMode "read-only" "read-only" / "all" / "custom"
include [] Patterns for custom mode ("read", "base:*")
exclude ["eval","command","dev:cdp","dev:debug","restart","reload","plugin:install","plugin:uninstall","theme:install","theme:uninstall"] Always-blocked patterns
exposeReadOnlyTools true Register typed tools per command
promptSnippets true Show tools in system prompt "Available tools"
confirmDestructive true Confirm write/danger in TUI; reject them without a UI
timeoutMs 30000 Per-invocation timeout
maxOutputBytes 51200 Output returned to LLM
statusBar true Footer: vault · mode · catalog
preferJson true Request format=json where supported
contextMode "active-tab" "active-tab"/"manual" — default file/folder from active tab
resolveWikilinks true Resolve [[wikilinks]] to vault paths
allowFixedScripts true Enable audited wrappers without enabling generic eval
allowDataviewJs false Opt in to user-supplied DataviewJS execution; requires confirmation
toolProfiles {} Optional named profiles; write-capable profiles are never registered by default

Settings live under "obsidianCli" in pi's main settings.json.

By default, the extension performs a process pre-flight and fails fast when Obsidian is not running, so calling a tool never opens the GUI unexpectedly. Set "autoLaunch": true only if you explicitly want the CLI to retain its automatic app-launch behavior.

Config file locations (pi's search order):

  • Global: ~/.config/pi/agent/settings.json (or ~/.pi/agent/settings.json if configured)
  • Project: .pi/settings.json (relative to the project root)

When the project is trusted, project settings override global values for keys such as permissionMode and include; exclude entries are always additive. Treat trusted project settings as permission-bearing configuration and review them before enabling trust.


Architecture

pi-obsidian-cli architecture

The editable Excalidraw source is available at docs/architecture.excalidraw.

Catalog Discovery

obsidian __completions returns a JSON map of every command, including usage, description, and flags. The catalog varies per vault because plugins can add namespaces such as sync:* and base:*; discovery falls back to fallback-catalog.json when the app is unreachable.


Dependencies

Zero runtime dependencies. All pi packages and typebox are peerDependencies — they are provided by the pi runtime at execution time, not bundled with this extension.

Dependency Role Provided by
@earendil-works/pi-coding-agent Extension API, events, types pi runtime
@earendil-works/pi-agent-core Core SDK types pi runtime
@earendil-works/pi-ai AI provider interface pi runtime
@earendil-works/pi-tui TUI key bindings, text utils pi runtime
typebox Tool parameter schemas pi runtime

In devDependencies (for tsc --noEmit only):

  • @types/node — Node.js type definitions
  • typescript — the type checker itself
  • All five peer packages at the pinned versions used to develop against

Troubleshooting

"Extension not trusted" / tools don't appear

Run /trust in pi to trust the extension. If running from the CLI with --no-extensions -e, use:

pi --no-extensions -e ./index.ts --approve

Duplicate tools after installing from local path

If you previously had a manual copy in ~/.config/pi/agent/extensions/obsidian-cli/, pi will load both. Remove the manual copy:

rm -rf ~/.config/pi/agent/extensions/obsidian-cli
# or, if your pi uses ~/.pi:
rm -rf ~/.pi/agent/extensions/obsidian-cli

Then /reload in pi. Verify with /tools — you should see each obsidian_* tool exactly once.

"pi: command not found" or "pi install not recognized"

Ensure @earendil-works/pi-coding-agent is installed globally:

npm install -g @earendil-works/pi-coding-agent

Obsidian CLI connection errors

  • Make sure Obsidian is running before invoking any tool
  • Check that Command line interface is enabled in Obsidian settings
  • Verify the obsidian binary is on your PATH: which obsidian
  • If the binary has a different name/path, set obsidianCli.binary in settings

Local path install doesn't pick up changes

pi install -l /path registers the local path in pi's settings (.pi/settings.json for project-local, or global settings.json). The path is referenced as-is — files are neither copied nor symlinked into pi's extension directory. Changes to the source files should be picked up after /reload. If not:

  1. Verify the path is recorded correctly: check extensions in your .pi/settings.json or global settings.json
  2. Force a reload: /reload
  3. If all else fails, reinstall: pi install -l /absolute/path/to/pi-obsidian-cli

Known Quirks

  • daily:path double-slash: The upstream Obsidian CLI returns paths like Daily//2026/07-julio/2026-07-31.md. obsidian_daily fixes this; regular daily:path shows the raw value.
  • create exits 0 on error: The CLI always exits 0. Errors are detected from output text patterns.
  • Catalog drift: Regenerate fallback-catalog.json after Obsidian updates: obsidian __completions > fallback-catalog.json

Release Checklist

  1. npm run check passes on main
  2. npm run pack:dry shows correct file list
  3. Manual smoke test: pi --no-extensions -e ./index.ts
  4. Bump version in package.json (semver)
  5. Commit and tag: git tag vX.Y.Z && git push origin main --tags
  6. Verify install from git: pi install git:github.com/frNNcs/pi-obsidian-cli
  7. (Optional) Publish to npm: npm publishpi install npm:pi-obsidian-cli

License

MIT