Aller au contenu
← Retour aux projets

Obsidian Notes Cli

Obsidian Notes CLI

#Obsidian Notes CLI

Buy Me A Coffee

Tests PHPStan Latest Release Packagist PHP 8.3+ License

CLI that writes structured Markdown notes into an Obsidian vault — built so Claude Code (or any script) can persist documentation/decisions as notes you can browse and search natively in Obsidian. No custom viewer, no lock-in: it's just Markdown files with frontmatter, in a folder Obsidian already understands.

Part of a 3-repo integration:

  • obsidian-notes-cli (this repo, PHP / Laravel Zero) — writes the notes. Works standalone — the other two repos are optional conveniences on top.
  • obsidian-claude-notes — Obsidian plugin: sidebar of Claude Code notes, command to trigger the CLI from inside Obsidian, live refresh.
  • claude-code-obsidian-notes — Claude Code plugin (skill + /obsidian-note command) that shells out to this CLI.

#Requirements

  • PHP >= 8.3 (only needed for the Composer install path — the .phar is self-contained)

#Install

#Composer (recommended)

composer global require jeffersongoncalves/obsidian-notes-cli

#PHAR

Download obsidian-notes.phar from the latest release, then:

chmod +x obsidian-notes.phar
mv obsidian-notes.phar /usr/local/bin/obsidian-notes

Every release after the first is built and attached by CI (.github/workflows/release.yml) — the binary that ships is exactly what git log for that tag shows, nothing built out-of-band.

#Commands

Command What it does
vault:init <path> Scaffolds .claude-notes.json and a Claude Notes/ folder in a vault, and saves it as the default vault. Safe to re-run — leaves an existing config file untouched. Pass --no-default to skip saving the default.
vault:config [path] Saves a default vault path (~/.obsidian-notes-cli/config.json) so --vault / OBSIDIAN_VAULT can be skipped. No path shows the current default.
note:create Writes a note. Body comes from stdin.
note:list Lists notes with source: claude-code frontmatter in a vault, optionally filtered by --project.
note:read <path> Prints a note's content with the YAML frontmatter block stripped — just the body.
self-update Replaces the running binary with the latest release's .phar (PHAR installs only — no-op for Composer installs, which update via composer global update).

#note:create options

Option Required Notes
--project= yes Groups the note in the folder structure and in the Obsidian plugin's sidebar.
--title= yes Used to build the filename slug and stored in frontmatter.
--tags= no Repeatable: --tags=architecture --tags=backend.
--vault= no* Vault path. *Falls back to OBSIDIAN_VAULT, then the vault:config default — one of the three must resolve.

#Usage

# One-time: scaffold .claude-notes.json + base folder in a vault
obsidian-notes vault:init /path/to/vault

# Write a note (body piped via stdin)
echo "We chose SQLite over Postgres for the CLI cache." \
  | obsidian-notes note:create --project=my-app --title="Decision: SQLite" --tags=architecture --vault=/path/to/vault

# List notes generated by Claude Code
obsidian-notes note:list --vault=/path/to/vault
obsidian-notes note:list --project=my-app --vault=/path/to/vault

# Read a note back as plain content (no frontmatter) — e.g. to feed another tool
obsidian-notes note:read /path/to/vault/Claude\ Notes/my-app/2026-09-10-decision-sqlite.md

# Update the CLI itself (PHAR installs)
obsidian-notes self-update

Set OBSIDIAN_VAULT to skip passing --vault every time:

export OBSIDIAN_VAULT=/path/to/vault

Or persist it once with vault:config (handy so Claude Code/scripts never need to know the path):

obsidian-notes vault:config /path/to/vault   # save
obsidian-notes vault:config                  # show current default

Resolution order: --vault > OBSIDIAN_VAULT > vault:config default.

#The .claude-notes.json contract

A vault's .claude-notes.json (created by vault:init, or hand-written) is the single source of truth shared with the Obsidian plugin — both read the same file, nothing is duplicated:

{
  "folderPattern": "Claude Notes/{project}/{date}-{slug}.md",
  "frontmatterDefaults": { "source": "claude-code", "tags": [] },
  "bridgePort": 27124
}
  • folderPattern — where notes land. Placeholders: {project}, {date} (YYYY-MM-DD), {slug} (from the title).
  • frontmatterDefaults — merged into every note's frontmatter before the CLI's own fields (project, title, tags, created, updated) are added. created is preserved across re-writes of the same path; updated always refreshes.
  • bridgePort — where the CLI tries to reach the Obsidian plugin's optional local bridge (see below).

If no .claude-notes.json exists, the CLI falls back to config/notes.php's defaults — same values as above.

#The bridge

After writing a file, the CLI makes a best-effort POST http://127.0.0.1:<bridgePort>/notes to the Obsidian plugin, so its sidebar refreshes instantly. If the bridge is off (it's opt-in on the plugin side) or Obsidian isn't running, the call is silently ignored — the file is already on disk, and Obsidian picks up external changes natively the next time it gains focus. The CLI never depends on the plugin being installed.

#Development

composer install
composer test       # Pest + Pint
composer phpstan
composer build       # produces builds/obsidian-notes locally (needs phar.readonly=Off)

#Windows note

Local PHAR builds (composer build / php obsidian-notes app:build) fail on a stock Herd/Windows PHP install because phar.readonly defaults to On. CI builds on Linux with phar.readonly=Off set explicitly, so releases are unaffected — this only blocks building a .phar on your own Windows machine.

#License

MIT.

Nouvelle version disponible.