▶️ LISTEN TO THIS ARTICLE

For six years, Obsidian has been the note-taking app that developers love precisely because it doesn't try to be clever. Plain markdown files in a local folder. No proprietary database. No cloud lock-in. Over 1.5 million active users built their knowledge systems on that simplicity.

But there was always a wall. If you wanted to script anything, query your vault programmatically, or wire it into an automated workflow, you were hacking around the app rather than working with it. Community plugins like Shell Commands and Local REST API filled parts of the gap, but they were duct tape over a missing feature. On February 10, 2026, Obsidian shipped the fix: version 1.12 includes an official command-line interface with over 100 commands. The tagline on the help docs is blunt: "Anything you can do in Obsidian you can do from the command line."

That claim is mostly true. I've spent the past week building automation around the CLI, and what follows is everything I've learned about what works, what breaks, and why this matters far beyond note-taking.

The $25 Unlock

There's a catch before you get started. The CLI shipped as an early access feature, which means you need a Catalyst license to use it today. Obsidian's Catalyst program has three tiers: Insider at $25, Supporter at $50, and VIP at $100. All three are one-time payments, not subscriptions, and all three unlock the same early access builds. The only differences are forum badges and how much you're tipping the 18-person team behind the app.

That $25 Insider tier is the minimum. You pay once, you get access to every pre-release build going forward, and the CLI will eventually roll out to the free tier once it leaves early access. For anyone running Obsidian as a daily driver for research, writing, or software development, $25 to turn your vault into a scriptable system is an easy call.

To activate the CLI after purchasing Catalyst: open Obsidian, go to Settings, then General, scroll to the Advanced section, and enable the Command Line Interface toggle. On Linux, this creates a symlink at /usr/local/bin/obsidian (or ~/.local/bin/obsidian if you don't have sudo). On macOS, it modifies ~/.zprofile to add Obsidian to your PATH. Windows users need to download a separate Obsidian.com terminal redirector from the Discord channel.

How It Actually Works Under the Hood

The CLI isn't a standalone tool that parses your markdown files. It's a client that talks to a running Obsidian instance. When you type obsidian files total, the CLI binary sends that command to the Obsidian desktop app over a local protocol, the app executes it, and the result comes back to your terminal. If Obsidian isn't running, the first command you issue will launch it automatically.

This architecture matters because the CLI has access to everything the app knows. Not just raw markdown, but the full link graph, resolved backlinks, plugin data, Dataview indices, Canvas relationships, and even the internal app context via JavaScript evaluation. A file parser could give you text. This gives you the app's brain.

Two execution modes exist. Single command mode runs one command and returns output: obsidian read file="Daily Note". Interactive TUI mode drops you into a persistent terminal interface with tab completion, command history, reverse search via Ctrl+R, and multi-line editing. The TUI is genuinely good. It feels like a REPL for your knowledge base.

The Commands Worth Knowing

With 100+ commands across 12 categories, I won't catalog every one. Here are the ones that changed my workflow.

Search and Discovery

The link graph is where Obsidian's CLI pulls ahead of anything you could build with grep and find. Four commands expose the structure of your vault:

  • obsidian backlinks file="Project Notes" shows every file that links to a given note
  • obsidian orphans lists notes with zero incoming links, the forgotten corners of your vault
  • obsidian unresolved finds all [[wikilinks]] that point to notes that don't exist yet
  • obsidian links file="Research Log" shows all outgoing links from a specific note

Run obsidian orphans on a vault you've been using for six months. The number of abandoned notes will be uncomfortable. That's useful discomfort. Those orphans are either things you should connect or things you should delete.

One caveat: in version 1.12.2, the search command returns empty output for some queries. The workaround is search:open, which sends the query to Obsidian's built-in search panel. Not ideal for scripting, but it works for interactive use.

Daily Notes on Autopilot

If you run a daily journal, the daily notes commands save you from ever opening the GUI just to jot something down:

obsidian daily read
obsidian daily:append content="- Met with design team about v2 wireframes"
obsidian daily:prepend content="## Morning Review\nEnergy: 7/10"
obsidian daily:path

That daily:append command is the one I use most. Quick capture from the terminal without context-switching. The \n escape creates actual newlines, which means you can append structured content, not just flat text.

Task Management Without Leaving the Terminal

obsidian tasks
obsidian tasks status=incomplete
obsidian tasks file="Sprint Planning"
obsidian task toggle file="Sprint Planning" line=14

The tasks command surfaces every - [ ] and - [x] checkbox in your vault (or a specific file). Filter by completion status. Toggle individual tasks by line number. If you're someone who tracks tasks in markdown files rather than a dedicated app, this is the first time you can manage them from a script.

Metadata and Frontmatter

obsidian properties file="Research Paper"
obsidian property:set file="Research Paper" property=status value=reviewed
obsidian tags
obsidian tag tag="ai-agents"

The tags command without arguments lists every tag in your vault with a count. The tag command filters to show all files with a specific tag. Combined with the properties commands for YAML frontmatter, you can build tag-based workflows entirely from the terminal. Tag a note as "needs-review" from a script, then query for all unreviewed notes later.

The Power Move: eval

The eval command is the sleeper feature. It executes arbitrary JavaScript inside the running Obsidian instance, with full access to the app object that plugins use.

obsidian eval code="app.vault.getFiles().length"
obsidian eval code="app.vault.getMarkdownFiles().filter(function(f){ return f.stat.size > 10000 }).length"
obsidian eval code="Object.keys(app.plugins.plugins).join(', ')"

That first command returns the total file count in your vault. The second counts markdown files over 10KB. The third lists every installed plugin by name.

One syntax gotcha: use function() syntax, never arrow functions. Shell quoting mangles the => in arrow functions, and you'll get cryptic parse errors. function(f){ return f.stat.size > 10000 } works. f => f.stat.size > 10000 doesn't.

The eval command turns your vault into a queryable database with zero setup. Any property the Obsidian API exposes is available. File metadata, plugin state, workspace layout, the link resolution cache, all of it. For developers who already know the Obsidian plugin API, the CLI just made the REPL-debug-iterate cycle instant.

Database Queries with Bases

Obsidian's Bases feature (their structured data layer, similar to Notion databases) has CLI support via base:query:

obsidian bases
obsidian base:query base="Reading List" format=json
obsidian base:query base="Reading List" format=csv

Output formats include JSON, TSV, CSV, and markdown. There's a significant gotcha here: base:query only works when the base is the active tab in Obsidian. You need to open the base first, wait a couple of seconds for it to render, then query. Not great for fully automated scripts, but workable for interactive use.

Why AI Developers Should Pay Attention

Here's where it gets interesting for the AI agent crowd. The Obsidian CLI solves a problem that the Model Context Protocol and tool-calling frameworks have been circling: how do you give an AI assistant structured access to a human's accumulated knowledge?

Before the CLI, wiring Claude or GPT into an Obsidian vault meant one of three approaches. You could use the Local REST API plugin, which requires the plugin to be installed and configured. You could read the raw markdown files from disk, which gives you text but not the link graph, resolved backlinks, or plugin-computed metadata. Or you could build an MCP server that wraps file system operations. All three worked. None of them felt native.

The CLI changes the integration story. An AI assistant with shell access (Claude Code, OpenAI Codex CLI, Gemini CLI) can now query your vault the same way you would. obsidian search query="project deadline". obsidian backlinks file="Architecture Decision". obsidian tags. The commands return structured output in JSON, CSV, or plain text. No MCP server to configure, no plugin dependencies, no API keys.

The Read/Write Architecture

The most useful pattern I've found is treating the CLI as a read layer for a two-component system. The CLI reads: it queries notes, discovers connections, pulls metadata, runs vault analytics. A separate write layer handles knowledge capture, whether that's a shell script appending to daily notes, an MCP-based memory system, or Claude Code writing markdown files directly.

This separation matters because reading knowledge and writing knowledge have different trust requirements. You want your AI assistant to freely query your vault for context. You might want more guardrails around what it writes. The CLI's read commands are naturally safe, they don't modify anything. The write commands (create, append, delete) exist but can be gated separately.

Natural Language to CLI Translation

AI assistants are already good at translating natural language into shell commands. "What notes mention the project deadline?" becomes obsidian search query="project deadline". "Show me notes I haven't linked to anything" becomes obsidian orphans. "What tags do I use most?" becomes obsidian tags.

The command syntax is simple enough that current-generation models handle the translation without fine-tuning. The output formats (JSON especially) are easy for models to parse and reason over. This is the kind of tool integration that just works, no complex schema definitions or function-calling boilerplate required.

For anyone building AI agents that need persistent knowledge, this is significant. The biggest complaint about agent memory systems is that they're separate from where humans actually store knowledge. Your agent has its vector database; you have your Obsidian vault. The CLI closes that gap. The agent can query the same knowledge store you maintain by hand, and it gets the same rich structure (links, tags, backlinks, properties) that makes Obsidian useful in the first place.

What the Competition Doesn't Have

Notion added an API in 2021, but it requires OAuth tokens, runs through their cloud, and only works if your data lives on their servers. Logseq is open-source and file-based like Obsidian, but has no official CLI. Roam Research is browser-only with no terminal interface at all.

The closest comparison is the community of third-party tools that have tried to fill this gap. Yakitrak's notesmd-cli can operate on vault files without Obsidian running, but it only handles basic file operations, not the link graph or plugin data. David Pereira's obsidian-cli adds AI-optimized operations with REST API integration, but it's a separate tool you have to install and configure.

Obsidian's official CLI has an advantage none of these can match: it runs inside the app. When you query backlinks, you get the same results the GUI shows. When you run eval, you get the same JavaScript context that plugins use. There's no synchronization gap between what the CLI reports and what you see on screen.

For knowledge management tools, this is a first. The tool where you think now has a programmatic interface that doesn't sacrifice any fidelity.

The Gotchas Nobody Warns You About

After a week of daily use, here's what the documentation glosses over.

Search is broken in 1.12.2. The search and search:context commands return empty output for most queries. This is an early access build, so bugs are expected, but search is a core command. The workaround is search:open which opens the search pane in the GUI, useful for interactive work but useless for scripts. Expect a fix in a point release.

Linux AppImage needs --no-sandbox. If you installed Obsidian as an AppImage (the most common Linux method), you may need to add the --no-sandbox flag to your launch script. Without it, Electron's sandbox can interfere with the CLI's ability to connect to the running instance. A simple wrapper script at ~/.local/bin/obsidian-launch handles this.

The "Loading updated app package" noise. Every CLI invocation may print Loading updated app package... to stderr. It's harmless but will pollute your script output. Redirect stderr or filter it out in your automation.

base:query requires the active tab. As mentioned above, Bases queries only work when the target base is the active tab. For scripting, you need to obsidian open path="Reading List.base", sleep for 2 seconds, then run the query. Fragile, but functional.

Arrow functions break in eval. Shell quoting corrupts the => syntax. Always use function() notation. This isn't documented anywhere.

The CLI needs the app running. Unlike git or rg, you can't just point the Obsidian CLI at a directory and get results. The desktop app must be running. If your workflow involves headless servers or CI pipelines, this is a significant limitation. For workstation use, it's fine since most Obsidian users have the app open all day anyway.

Where This Goes Next

The Obsidian team has built something that matters beyond their own user base. The idea that a personal knowledge management tool should have a first-class programmatic interface is overdue. We treat code as something that naturally lives in the terminal. We treat notes as something trapped in GUIs. That distinction made sense when notes were documents. It stops making sense when notes are the knowledge substrate for AI systems.

The context window problem for AI agents isn't just about how much text fits in a prompt. It's about whether the agent can reach the right knowledge at the right time. A CLI that exposes a human-curated knowledge graph, with tags, links, properties, and full-text search, gives agents a retrieval system that humans have already organized. That's not a vector embedding of your notes. It's the actual structure you built because you understood the connections.

I expect two things to happen fast. First, MCP servers wrapping the Obsidian CLI will proliferate. It's a natural fit. Claude Desktop, Claude Code, and any MCP-compatible agent would get Obsidian vault access through a standardized protocol. Second, other knowledge tools will face pressure to ship their own CLIs. If Obsidian proves that a terminal interface drives adoption among developers and AI practitioners, Logseq and the rest won't be able to ignore it.

For now, $25 and 10 minutes of setup gets you a knowledge base that your AI tools can actually use. Given how much time developers spend building brittle integrations between their notes and their agents, that's a solid trade.

Sources

Official Documentation:

Community & Commentary:

Market & Usage Data:

Related Swarm Signal Coverage: