Support stdin pipe for obsidian CLI

Use case or problem

I want to provide larger chunks of content to various Obsidian CLI commands. For example, larger multiline scripts for eval, or larger multi-line content chunks for ‘append’.

Proposed solution

Use nix-style ‘-’ to mean ‘stdin’, e.g.:
echo “helloWorld()” | obsidian eval code=-
echo “Hello World” | obsidian append file=Inbox content=-

Current workaround (optional)

Probably something like:
echo <<-EOF > script.js
helloWorld()
EOF
obsidian eval code=“$(<script.js)”
But this is likely to be full of annoying quote problems.

Related feature requests (optional)

2 Likes

Use case or problem

I’m using the Obsidian 1.12 CLI extensively with AI assistants (Claude + Desktop Commander MCP) to manage my vault programmatically. The CLI works brilliantly for read, search, append, prepend, and property:set.

However, create path="..." content="..." overwrite silently fails when the content contains multiline text passed via shell variables or command substitution. This is because shell argument expansion breaks on special characters (quotes, newlines, brackets, etc.) in longer content.

What works:


# Single-line content — works fine

obsidian create path="test.md" content="Hello World" overwrite

# Append — works fine

obsidian append path="notes.md" content="A new line"

# Read — works perfectly

obsidian read path="notes.md"

What fails silently:


# Multiline content via variable — fails silently (no error, no update)

CONTENT=$(obsidian read path="myfile.md" | sed 's/old/new/')

obsidian create path="myfile.md" content="$CONTENT" overwrite

# Command substitution — same issue

obsidian create path="myfile.md" content="$(cat /tmp/updated.md)" overwrite

The command produces no output and no error, but the file remains unchanged. This makes it impossible to do programmatic find-and-replace or full file rewrites through the CLI alone.

Proposed solution

Support stdin input for the create command, similar to how many Unix tools work:


# Read from stdin via pipe

cat /tmp/updated-file.md | obsidian create path="myfile.md" overwrite --stdin

# Or via heredoc

obsidian create path="myfile.md" overwrite --stdin << 'EOF'

---

title: My Note

---

# Heading

Content with "quotes", (parens), and $pecial chars.

EOF

Alternatively or additionally, support a file source parameter:


# Read content from a file

obsidian create path="myfile.md" overwrite --from-file="/tmp/updated.md"

Both approaches would bypass shell argument escaping issues entirely.

Current workaround

Write the content to /tmp/file.md and use cp to overwrite the vault file directly:


cat > /tmp/myfile.md << 'EOF'

...content...

EOF

cp /tmp/myfile.md "/path/to/vault/myfile.md"

This works but bypasses Obsidian’s internal indexing, meaning links, backlinks, tags, and search may not update immediately until Obsidian detects the filesystem change.

Context

The native CLI is a game-changer for AI-assisted vault management. With read, search, append, and property:set, it covers 90% of use cases perfectly. Adding stdin/file support for create would close the last significant gap and make the CLI a complete solution for programmatic vault operations — no more falling back to direct filesystem writes.

Environment:

  • Obsidian 1.12.1 (macOS, Apple Silicon)

  • Using CLI via MCP server (Desktop Commander) with Claude AI

  • Vault synced via Google Drive

8 Likes

I am experiencing the exact same issue on Windows. Both the create and append commands ought to support STDIN.

Obsidian CLI - Obsidian Help says:
For multiline content use \n for newline. Use \t for tab.

obsidian create name=Note content="# Title\n\nBody text"

That works, but via the TUI, one has to say:

create name=Note content="# Title\\n\\nBody text"

So I suppose the expectation is for user text to modified to escape newlines…

Somewhat Related BR