---
name: obsidian-cli
component: obsidian
description: >-
  Patterns for using Obsidian CLI and file-based vault operations.
  Covers official CLI commands, running-state detection, and graceful
  degradation to direct file operations when Obsidian is not running.
type: utility
trigger-patterns:
  - vault operations
  - obsidian commands
  - note management
category: tooling
tags:
  - obsidian
  - cli
  - vault
  - file-operations
---

# Obsidian CLI

Patterns for interacting with Obsidian vaults. The **primary write path is direct file I/O** (`fs.writeFileSync`) — Obsidian auto-detects disk writes via its file watcher. CLI invocation is **optional** and only useful for rare cases where you want Obsidian to open a file or trigger Obsidian-side behavior.

> **Foot-gun warning:** The Obsidian CLI uses `key=value` argument syntax. Positional arguments are **silently ignored** — `obsidian create "path/to/note.md"` does NOT create a note at that path. It creates `Untitled N.md` at the vault root instead. Always use `path=<path>` kwarg form if you invoke the CLI at all. See `.planning/debug/phase25-untitled-vault-spam.md` for the production bug this caused.

## Obsidian Running-State Detection

**Status: TBD / open problem.**

There is no reliable way to detect whether Obsidian is running from the shell. The previously-documented `obsidian status` probe does **not** exist as a subcommand — it exits 0 with an error message on stdout, which makes it indistinguishable from success. Until a reliable mechanism exists (lockfile check, IPC probe, platform-specific window enumeration), callers should:

- Treat Obsidian as potentially-absent
- Write notes directly to disk with `fs.writeFileSync` (see below)
- Trust Obsidian's file watcher to pick up new/modified files when it later runs

Do **not** gate vault writes on a running-state check.

## Official Obsidian CLI Commands

The CLI uses **key=value** argument syntax. Positional args are silently ignored.

| Command                                         | Purpose                                                                                         |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `obsidian daily`                                | Open or create today's daily note                                                               |
| `obsidian search query=<text> format=<text\|json>` | Search vault content — use key=value syntax                                                  |
| `obsidian create path=<path>`                   | Create a new note at `<path>` — **uses key=value syntax, NOT positional args**                  |
| `obsidian tags`                                 | List all tags in the vault                                                                      |

### Creating Notes via CLI (optional)

If you specifically need Obsidian to open a file or trigger Obsidian-side behavior on note creation, use the kwarg form:

```bash
obsidian create path="Projects/MyProject/note-name.md" content="Initial body"
```

> **Warning:** Positional arguments (e.g. `obsidian create "Projects/MyProject/note-name.md"`) are silently ignored by the CLI — the file is created as `Untitled N.md` at the vault root instead.

In most cases you do **not** need to invoke the CLI at all. Just write the file directly (next section); Obsidian's file watcher will index it.

## Writing Notes — Direct Vault File I/O

Direct filesystem writes are the **primary** path for all programmatic vault operations:

```javascript
const fs = require('fs');
const path = require('path');

// Write a note directly
fs.mkdirSync(path.dirname(notePath), { recursive: true });
fs.writeFileSync(notePath, content, 'utf8');
```

Key points for file-based operations:
- Create parent directories recursively before writing
- Use UTF-8 encoding for all markdown files
- Obsidian indexes new/modified files automatically via its file watcher (when running) or on next launch
- Frontmatter must be valid YAML between `---` delimiters

## Writing Notes — Recommended Pattern

The one-stage direct-write pattern. Do not pre-invoke the CLI:

```javascript
const fs = require('fs');
const path = require('path');

function writeNote(destPath, content) {
  // Obsidian auto-detects disk writes via its file watcher — no CLI invocation needed.
  // This is both simpler and correct. The prior "try obsidian create first, fall back
  // to file write" pattern caused silent Untitled-file spam at the vault root because
  // the CLI uses key=value syntax, not positional arguments
  // (see .planning/debug/phase25-untitled-vault-spam.md).
  fs.mkdirSync(path.dirname(destPath), { recursive: true });
  fs.writeFileSync(destPath, content, 'utf8');
}
```

This replaces the previous two-stage "try CLI, fall back to file" pattern. There is no CLI step — writing to disk is sufficient.

## Platform-Specific Notes

### Windows
- Vault paths use backslashes internally but Obsidian normalizes to forward slashes
- Default vault location: `%APPDATA%/obsidian/` for config, vault can be anywhere
- Use `path.resolve()` to normalize paths

### Unix (macOS/Linux)
- Default vault location: `~/.obsidian/` for config, vault can be anywhere
- File permissions: ensure notes are readable (644)

## When to Use This Skill

- Syncing artifacts from `.planning/` to an Obsidian vault
- Creating or updating vault notes programmatically
- Building tools that integrate with Obsidian
- Any operation that reads from or writes to a vault directory
