Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10c02c785b | |||
| 8fc3803385 | |||
| 0e524848b7 | |||
| 1e6f0a6b6b | |||
| 69c42bfb92 | |||
| cdb3bd2209 | |||
| 6f5ed7c70e | |||
| 7d20d45a71 | |||
| ec070a1371 | |||
| 1ab03980b9 | |||
| d7d115781e | |||
| a882e74591 | |||
| de356e8396 | |||
| c7b35b314d | |||
| b116ad4abf | |||
| 536320574b | |||
| a5a0d10d35 | |||
| 986ff986d2 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "obsidian-cli",
|
||||
"description": "Interact with Obsidian vaults using the official Obsidian CLI (v1.12+). Read, create, append, search, and manage notes, daily notes, properties, tags, tasks, bookmarks, templates, themes, sync, plugins, and links — all from the terminal.",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"author": {
|
||||
"name": "pablo-mano"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review, reopened]
|
||||
# Optional: Only run on specific file changes
|
||||
# paths:
|
||||
# - "src/**/*.ts"
|
||||
# - "src/**/*.tsx"
|
||||
# - "src/**/*.js"
|
||||
# - "src/**/*.jsx"
|
||||
|
||||
jobs:
|
||||
claude-review:
|
||||
# Optional: Filter by PR author
|
||||
# if: |
|
||||
# github.event.pull_request.user.login == 'external-contributor' ||
|
||||
# github.event.pull_request.user.login == 'new-developer' ||
|
||||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code Review
|
||||
id: claude-review
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
||||
plugins: 'code-review@claude-code-plugins'
|
||||
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Claude Code
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
claude:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
actions: read # Required for Claude to read CI results on PRs
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
|
||||
# This is an optional setting that allows Claude to read CI results on PRs
|
||||
additional_permissions: |
|
||||
actions: read
|
||||
|
||||
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
||||
# prompt: 'Update the pull request description to include a summary of changes.'
|
||||
|
||||
# Optional: Add claude_args to customize behavior and configuration
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
A skill for AI coding agents that enables full control of [Obsidian](https://obsidian.md) vaults from the terminal using the official **Obsidian CLI** (v1.12+).
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -12,22 +13,44 @@ A skill for AI coding agents that enables full control of [Obsidian](https://obs
|
||||
|
||||
Once installed, your AI agent will know how to interact with Obsidian vaults through the official CLI — reading, creating, and editing notes; managing daily notes; running full-text search; querying tasks, tags, links, and properties; managing plugins and sync; and running developer tools.
|
||||
|
||||
Covers **100+ commands** across all major areas:
|
||||
Covers **130+ commands** across all major areas:
|
||||
|
||||
| Area | Commands |
|
||||
|---|---|
|
||||
| **Files** | `read`, `create`, `append`, `prepend`, `move`, `delete`, `files`, `folders` |
|
||||
| **Daily Notes** | `daily`, `daily:read`, `daily:append`, `daily:prepend` |
|
||||
| **Search** | `search` with scoping, limits, JSON output |
|
||||
| **Properties** | `properties`, `property:read`, `property:set`, `property:remove` |
|
||||
| **Files** | `read`, `create`, `append`, `prepend`, `move`, `rename`, `delete`, `files`, `folders`, `file`, `random` |
|
||||
| **Daily Notes** | `daily`, `daily:read`, `daily:append`, `daily:prepend`, `daily:path` |
|
||||
| **Search** | `search`, `search:context` with scoping, limits, JSON output |
|
||||
| **Properties** | `properties`, `property:read`, `property:set`, `property:remove`, `aliases` |
|
||||
| **Tags** | `tags`, `tag` with counts and filtering |
|
||||
| **Tasks** | `tasks`, `task` — query, filter, toggle |
|
||||
| **Links** | `backlinks`, `links`, `unresolved`, `orphans`, `deadends` |
|
||||
| **Bookmarks** | `bookmarks`, `bookmark` |
|
||||
| **Templates** | `templates`, `template:read`, `template:insert` |
|
||||
| **Plugins** | `plugins`, `plugin:enable/disable/install/reload` |
|
||||
| **Sync** | `sync`, `sync:status`, `sync:history`, `sync:restore` |
|
||||
| **Developer** | `eval`, `dev:screenshot`, `dev:console`, `dev:errors` |
|
||||
| **Vault** | `vault`, `vaults`, `version`, `recents`, `outline`, `wordcount` |
|
||||
| **Plugins** | `plugins`, `plugin`, `plugin:enable/disable/install/uninstall`, `plugins:restrict` |
|
||||
| **Sync** | `sync`, `sync:status`, `sync:history`, `sync:read`, `sync:restore`, `sync:deleted` |
|
||||
| **Themes** | `themes`, `theme`, `theme:set`, `theme:install/uninstall` |
|
||||
| **Snippets** | `snippets`, `snippets:enabled`, `snippet:enable/disable` |
|
||||
| **Commands** | `commands`, `command`, `hotkeys`, `hotkey` |
|
||||
| **Bases** | `bases`, `base:query`, `base:views`, `base:create` |
|
||||
| **History** | `history`, `history:list`, `history:read`, `history:restore` |
|
||||
| **Workspace** | `workspace`, `tabs`, `tab:open` |
|
||||
| **Diff** | `diff` |
|
||||
| **Developer** | `eval`, `dev:screenshot`, `dev:debug`, `dev:console`, `dev:errors`, `dev:css`, `dev:dom`, `dev:mobile`, `devtools` |
|
||||
| **Vault** | `vault`, `vaults`, `version`, `reload`, `restart`, `recents`, `outline`, `wordcount` |
|
||||
|
||||
---
|
||||
|
||||
## Invoking the Skill
|
||||
|
||||
The skill activates automatically when your request clearly involves Obsidian vault operations. For casual phrasing, you may need to invoke it explicitly:
|
||||
|
||||
| Method | Example |
|
||||
|---|---|
|
||||
| **Natural language** (usually works) | *"add this to my daily note: …"*, *"search my vault for X"* |
|
||||
| **Explicit prefix** (always works) | `$obsidian-cli append to today's daily note: "…"` |
|
||||
| **Strict mode** (always active) | Enable in Claude Code settings so the skill is always loaded |
|
||||
|
||||
If Claude tries to answer a vault request without executing any commands, just say `use obsidian-cli` and it will retry with the skill active.
|
||||
|
||||
---
|
||||
|
||||
@@ -60,7 +83,7 @@ Covers **100+ commands** across all major areas:
|
||||
/plugin install obsidian-cli
|
||||
```
|
||||
|
||||
Done — the skill auto-triggers when you ask Claude to interact with Obsidian.
|
||||
Done — see [Invoking the Skill](#invoking-the-skill) above for how to activate it.
|
||||
|
||||
**Option B — Direct plugin load:**
|
||||
|
||||
@@ -107,6 +130,60 @@ Cursor picks it up automatically — no restart needed.
|
||||
|
||||
---
|
||||
|
||||
### Cortex Code
|
||||
|
||||
**Option A — Remote install (recommended)**
|
||||
|
||||
In a Cortex Code session, run:
|
||||
|
||||
```
|
||||
/skill add https://github.com/pablo-mano/Obsidian-CLI-skill.git
|
||||
```
|
||||
|
||||
Cortex Code clones the repo and caches the skill. Use `/skill sync obsidian-cli` to pull
|
||||
updates later.
|
||||
|
||||
**Option B — Project-local install**
|
||||
|
||||
```bash
|
||||
mkdir -p .cortex/skills/obsidian-cli
|
||||
curl -sSL https://raw.githubusercontent.com/pablo-mano/Obsidian-CLI-skill/main/skills/obsidian-cli/SKILL.md \
|
||||
-o .cortex/skills/obsidian-cli/SKILL.md
|
||||
```
|
||||
|
||||
Or clone the repo and copy:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/pablo-mano/Obsidian-CLI-skill.git /tmp/obsidian-cli-skill
|
||||
cp -r /tmp/obsidian-cli-skill/skills/obsidian-cli .cortex/skills/
|
||||
```
|
||||
|
||||
**Option C — User-level install**
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.snowflake/cortex/skills/obsidian-cli
|
||||
cp skills/obsidian-cli/SKILL.md ~/.snowflake/cortex/skills/obsidian-cli/
|
||||
```
|
||||
|
||||
**Verify**
|
||||
|
||||
```
|
||||
/skill list
|
||||
```
|
||||
|
||||
You should see `obsidian-cli` in the output.
|
||||
|
||||
**Invoke**
|
||||
|
||||
Prefix requests with `$obsidian-cli` or just describe what you want — Cortex Code activates
|
||||
the skill automatically when the context matches:
|
||||
|
||||
```
|
||||
$obsidian-cli append to today's daily note: "Reviewed Snowflake PR #42"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GitHub Copilot (VS Code)
|
||||
|
||||
Copilot supports [custom instructions](https://docs.github.com/en/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot) via repository files:
|
||||
@@ -223,6 +300,10 @@ See [`skills/obsidian-cli/references/command-reference.md`](skills/obsidian-cli/
|
||||
| Wrong vault targeted | Multi-vault ambiguity | Pass vault name as the first argument: `obsidian "My Vault" ...` |
|
||||
| IPC socket not found (Linux) | `PrivateTmp=true` in systemd unit | Set `PrivateTmp=false` |
|
||||
| Snap confinement errors | Snap restricts IPC | Use the `.deb` package instead |
|
||||
| Multi-vault `"Name" command` fails | Vault name matching issue | Omit vault name; switch vault manually in Obsidian UI |
|
||||
| `property:set` list value is a string | CLI stores value as-is | Edit frontmatter directly or use `eval` to call Obsidian API |
|
||||
| Colon+params exit 127 (missing `.com`) | Outdated installer — `Obsidian.com` absent | Reinstall from [obsidian.md/download](https://obsidian.md/download) |
|
||||
| Colon+params exit 127 (Git Bash / MSYS2) | Bash resolves `obsidian` to `.exe` not `.com` | Create `~/bin/obsidian` wrapper: `#!/bin/bash` + `/c/path/to/Obsidian.com "$@"`, add `export PATH="$HOME/bin:$PATH"` to `~/.bashrc` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Eval Set Review - obsidian-cli v2</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@500;600&family=Lora:wght@400;500&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: 'Lora', Georgia, serif; background: #faf9f5; padding: 2rem; color: #141413; }
|
||||
h1 { font-family: 'Poppins', sans-serif; margin-bottom: 0.5rem; font-size: 1.5rem; }
|
||||
.description { color: #b0aea5; margin-bottom: 1.5rem; font-style: italic; max-width: 900px; }
|
||||
.controls { margin-bottom: 1rem; display: flex; gap: 0.5rem; }
|
||||
.btn { font-family: 'Poppins', sans-serif; padding: 0.5rem 1rem; border: none; border-radius: 6px; cursor: pointer; font-size: 0.875rem; font-weight: 500; }
|
||||
.btn-add { background: #6a9bcc; color: white; }
|
||||
.btn-add:hover { background: #5889b8; }
|
||||
.btn-export { background: #d97757; color: white; }
|
||||
.btn-export:hover { background: #c4613f; }
|
||||
table { width: 100%; max-width: 1100px; border-collapse: collapse; background: white; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
|
||||
th { font-family: 'Poppins', sans-serif; background: #141413; color: #faf9f5; padding: 0.75rem 1rem; text-align: left; font-size: 0.875rem; }
|
||||
td { padding: 0.75rem 1rem; border-bottom: 1px solid #e8e6dc; vertical-align: top; }
|
||||
tr:nth-child(even) td { background: #faf9f5; }
|
||||
tr:hover td { background: #f3f1ea; }
|
||||
.section-header td { background: #e8e6dc; font-family: 'Poppins', sans-serif; font-weight: 500; font-size: 0.8rem; color: #141413; text-transform: uppercase; letter-spacing: 0.05em; }
|
||||
.query-input { width: 100%; padding: 0.4rem; border: 1px solid #e8e6dc; border-radius: 4px; font-size: 0.875rem; font-family: 'Lora', Georgia, serif; resize: vertical; min-height: 60px; }
|
||||
.query-input:focus { outline: none; border-color: #d97757; box-shadow: 0 0 0 2px rgba(217,119,87,0.15); }
|
||||
.toggle { position: relative; display: inline-block; width: 44px; height: 24px; }
|
||||
.toggle input { opacity: 0; width: 0; height: 0; }
|
||||
.toggle .slider { position: absolute; inset: 0; background: #b0aea5; border-radius: 24px; cursor: pointer; transition: 0.2s; }
|
||||
.toggle .slider::before { content: ""; position: absolute; width: 18px; height: 18px; left: 3px; bottom: 3px; background: white; border-radius: 50%; transition: 0.2s; }
|
||||
.toggle input:checked + .slider { background: #d97757; }
|
||||
.toggle input:checked + .slider::before { transform: translateX(20px); }
|
||||
.btn-delete { background: #c44; color: white; padding: 0.3rem 0.6rem; border: none; border-radius: 4px; cursor: pointer; font-size: 0.75rem; font-family: 'Poppins', sans-serif; }
|
||||
.btn-delete:hover { background: #a33; }
|
||||
.summary { margin-top: 1rem; color: #b0aea5; font-size: 0.875rem; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Eval Set Review: <span id="skill-name">obsidian-cli</span></h1>
|
||||
<p class="description">Current description: <span id="skill-desc">Use this skill whenever the user wants Claude to interact with their Obsidian vault — reading notes, creating or appending content, searching, managing tasks, tags, properties, daily notes, bookmarks, templates, sync, plugins, or links. The underlying mechanism is the official Obsidian CLI (v1.12+), but trigger even when the user doesn't mention the CLI — phrases like "add this to my daily note", "search my vault", "create a note from template", or "what tasks do I have open?" all apply. Also trigger for explicit CLI usage: running obsidian subcommands from a shell, scripting or automating vault operations, scheduling via cron, debugging IPC/headless Linux setups, or building programmatic wrappers. Skip only for pure GUI questions (Obsidian settings navigation, theme/plugin installation via UI) or iCloud sync configuration that has nothing to do with vault content.</span></p>
|
||||
|
||||
<div class="controls">
|
||||
<button class="btn btn-add" onclick="addRow()">+ Add Query</button>
|
||||
<button class="btn btn-export" onclick="exportEvalSet()">Export Eval Set</button>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:65%">Query</th>
|
||||
<th style="width:18%">Should Trigger</th>
|
||||
<th style="width:10%">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="eval-body"></tbody>
|
||||
</table>
|
||||
|
||||
<p class="summary" id="summary"></p>
|
||||
|
||||
<script>
|
||||
const EVAL_DATA = [
|
||||
{
|
||||
"query": "add this to my daily note: 'reviewed the Q1 roadmap with sarah, she wants the mockups by friday'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "search my vault for everything i've written about the Henderson project, i need to prep for a call",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "what open tasks do i have in obsidian? just the incomplete ones",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "create a new note from my meeting-notes template and call it 'Standup 2026-03-04'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "append '- [ ] follow up with the design team about the nav bar' to my projects/mobile-redesign.md",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "how many notes are in my vault right now? also which ones have no links pointing to them?",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "read me today's daily note",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "set the status property on projects/q2-launch.md to 'in-review'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "i want to write a script that pulls all notes tagged #meeting from the past week and summarizes them",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "move everything in my Inbox/ folder to Archive/2026/ and update the daily note with a log entry",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "how do i change the accent color in obsidian? i want something more muted than the default purple",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i can't figure out how to enable community plugins in obsidian — the toggle is greyed out in safe mode",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "does obsidian have a built-in kanban view or do i need a plugin for that?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "my icloud sync for obsidian keeps conflicting with files on my ipad — how do i resolve this without losing data?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "how do i set up the obsidian git plugin to auto-commit my vault every hour?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i use notion for my notes but i'm thinking of switching to obsidian — what's the best way to export from notion and import into obsidian?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "in the dataview plugin, how do i write a query that shows all notes with a due-date property before today?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i want to customize the obsidian theme with css — how do i target the sidebar background color specifically?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "what's the keyboard shortcut to open the command palette in obsidian on mac?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i'm writing a python script to parse markdown files from my notes folder and extract all the headings into a CSV — what's the best library for this?",
|
||||
"should_trigger": false
|
||||
}
|
||||
];
|
||||
|
||||
let evalItems = [...EVAL_DATA];
|
||||
|
||||
function render() {
|
||||
const tbody = document.getElementById('eval-body');
|
||||
tbody.innerHTML = '';
|
||||
const sorted = evalItems
|
||||
.map((item, origIdx) => ({ ...item, origIdx }))
|
||||
.sort((a, b) => (b.should_trigger ? 1 : 0) - (a.should_trigger ? 1 : 0));
|
||||
let lastGroup = null;
|
||||
sorted.forEach(item => {
|
||||
const group = item.should_trigger ? 'trigger' : 'no-trigger';
|
||||
if (group !== lastGroup) {
|
||||
const headerRow = document.createElement('tr');
|
||||
headerRow.className = 'section-header';
|
||||
headerRow.innerHTML = `<td colspan="3">${item.should_trigger ? 'Should Trigger' : 'Should NOT Trigger'}</td>`;
|
||||
tbody.appendChild(headerRow);
|
||||
lastGroup = group;
|
||||
}
|
||||
const idx = item.origIdx;
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td><textarea class="query-input" onchange="updateQuery(${idx}, this.value)">${escapeHtml(item.query)}</textarea></td>
|
||||
<td>
|
||||
<label class="toggle">
|
||||
<input type="checkbox" ${item.should_trigger ? 'checked' : ''} onchange="updateTrigger(${idx}, this.checked)">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span style="margin-left:8px;font-size:0.8rem;color:#b0aea5">${item.should_trigger ? 'Yes' : 'No'}</span>
|
||||
</td>
|
||||
<td><button class="btn-delete" onclick="deleteRow(${idx})">Delete</button></td>
|
||||
`;
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function updateQuery(idx, value) { evalItems[idx].query = value; updateSummary(); }
|
||||
function updateTrigger(idx, value) { evalItems[idx].should_trigger = value; render(); }
|
||||
function deleteRow(idx) { evalItems.splice(idx, 1); render(); }
|
||||
function addRow() {
|
||||
evalItems.push({ query: '', should_trigger: true });
|
||||
render();
|
||||
const inputs = document.querySelectorAll('.query-input');
|
||||
inputs[inputs.length - 1].focus();
|
||||
}
|
||||
function updateSummary() {
|
||||
const trigger = evalItems.filter(i => i.should_trigger).length;
|
||||
const noTrigger = evalItems.filter(i => !i.should_trigger).length;
|
||||
document.getElementById('summary').textContent =
|
||||
`${evalItems.length} queries total: ${trigger} should trigger, ${noTrigger} should not trigger`;
|
||||
}
|
||||
function exportEvalSet() {
|
||||
const valid = evalItems.filter(i => i.query.trim() !== '');
|
||||
const data = valid.map(i => ({ query: i.query.trim(), should_trigger: i.should_trigger }));
|
||||
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'eval_set.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
render();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,142 @@
|
||||
[
|
||||
{
|
||||
"query": "add this to my daily note: 'reviewed the Q1 roadmap with sarah, she wants the mockups by friday'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "search my vault for everything i've written about the Henderson project, i need to prep for a call",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "what open tasks do i have in obsidian? just the incomplete ones",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "create a new note from my meeting-notes template and call it 'Standup 2026-03-04'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "append '- [ ] follow up with the design team about the nav bar' to my projects/mobile-redesign.md",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "how many notes are in my vault right now? also which ones have no links pointing to them?",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "read me today's daily note",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "set the status property on projects/q2-launch.md to 'in-review'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "i want to write a script that pulls all notes tagged #meeting from the past week and summarizes them",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "move everything in my Inbox/ folder to Archive/2026/ and update the daily note with a log entry",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "check the sync history for my important.md and restore the version from two days ago",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "list all my bookmarks in obsidian",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "run obsidian eval to count how many markdown files have a 'status' property set to 'done'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "find all notes in my vault that link to projects/q1-review.md",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "take a screenshot of my current obsidian view and save it to screenshots/",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "show me all tags in my vault sorted by how often they're used",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "query my Obsidian Bases 'Tasks' view and show all entries where priority is high",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "what notes have i opened recently in obsidian?",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "delete my scratch/temp-ideas.md note permanently",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "rename my 'Meeting 2026-02-28.md' note to 'Sprint Retro 2026-02-28.md'",
|
||||
"should_trigger": true
|
||||
},
|
||||
{
|
||||
"query": "how do i change the accent color in obsidian? i want something more muted than the default purple",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i can't figure out how to enable community plugins in obsidian — the toggle is greyed out in safe mode",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "does obsidian have a built-in kanban view or do i need a plugin for that?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "my icloud sync for obsidian keeps conflicting with files on my ipad — how do i resolve this without losing data?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "how do i set up the obsidian git plugin to auto-commit my vault every hour?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i use notion for my notes but i'm thinking of switching to obsidian — what's the best way to export from notion and import into obsidian?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "in the dataview plugin, how do i write a query that shows all notes with a due-date property before today?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i want to customize the obsidian theme with css — how do i target the sidebar background color specifically?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "what's the keyboard shortcut to open the command palette in obsidian on mac?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "i'm writing a python script to parse markdown files from my notes folder and extract all the headings into a CSV — what's the best library for this?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "how does obsidian's graph view work? i want to understand what the clusters represent",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "is there a way to publish my obsidian vault publicly? what are the options?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "how do i configure a hotkey in obsidian to run a specific command from the command palette?",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "explain what the 'unresolved links' section in obsidian's graph view means",
|
||||
"should_trigger": false
|
||||
},
|
||||
{
|
||||
"query": "how do i use templater plugin variables like {{date}} in obsidian?",
|
||||
"should_trigger": false
|
||||
}
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "obsidian-cli",
|
||||
"description": "Interact with Obsidian vaults using the official Obsidian CLI (v1.12+). Read, create, append, search, and manage notes, daily notes, properties, tags, tasks, bookmarks, templates, themes, sync, plugins, and links — all from the terminal.",
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"author": {
|
||||
"name": "pablo-mano"
|
||||
},
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
---
|
||||
name: obsidian-cli
|
||||
description: >
|
||||
Interact with Obsidian vaults using the official Obsidian CLI (v1.12+).
|
||||
Read, create, append, search, and manage notes, daily notes, properties, tags,
|
||||
tasks, bookmarks, templates, themes, sync, plugins, and links — all from the terminal.
|
||||
Use this skill whenever the user mentions Obsidian CLI, wants to automate Obsidian
|
||||
vault operations, manage notes programmatically, script daily note workflows,
|
||||
query vault metadata, or integrate Obsidian with AI agents or automation pipelines.
|
||||
Also trigger when the user asks about controlling Obsidian from the command line,
|
||||
building scripts around their knowledge base, or running headless Obsidian setups.
|
||||
Even if the user just says "add something to my daily note" or "search my vault"
|
||||
in a CLI/scripting context, this skill applies.
|
||||
Use this skill whenever the user wants Claude to directly interact with their
|
||||
Obsidian vault — reading a note or daily note, writing or appending content,
|
||||
searching vault contents, counting or listing notes, managing tasks, moving or
|
||||
renaming files, finding orphaned notes or broken links. Without this skill, Claude
|
||||
has no way to access vault data or execute vault operations. Treat any request that
|
||||
implies "go into my vault and do X" as a trigger — the user is asking Claude to act,
|
||||
not to explain. Also trigger for vault automation, CLI scripting, or cron-based
|
||||
workflows involving Obsidian. Skip for pure conceptual questions: how Obsidian's GUI
|
||||
works, navigating settings menus, theme or plugin installation via the UI, or general
|
||||
Dataview query syntax — anything where the user needs an explanation rather than
|
||||
Claude performing a vault operation.
|
||||
---
|
||||
|
||||
# Obsidian CLI
|
||||
|
||||
The official Obsidian CLI (released in v1.12, February 2026) lets you control every aspect of Obsidian from the terminal. It communicates with a running Obsidian desktop instance via IPC.
|
||||
|
||||
> For the full command reference with all subcommands, flags and examples, read
|
||||
> `references/command-reference.md` in this skill folder.
|
||||
> Read `references/command-reference.md` when you need specific flags, output formats, or
|
||||
> subcommands for any command group. It covers all 130+ commands with full parameter tables
|
||||
> and has a table of contents at the top.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -32,6 +34,8 @@ The official Obsidian CLI (released in v1.12, February 2026) lets you control ev
|
||||
|
||||
- **macOS / Linux**: The `obsidian` binary is registered in PATH automatically when you enable CLI in settings.
|
||||
- **Windows**: Requires an `Obsidian.com` redirector file placed alongside `Obsidian.exe`. **Must run with normal user privileges** — admin terminals produce silent failures.
|
||||
- If colon subcommands (`property:set`, `daily:append`, etc.) with parameters return exit 127, check that `Obsidian.com` exists alongside `Obsidian.exe`. If missing, you have an outdated installer — download the latest from [obsidian.md/download](https://obsidian.md/download) and reinstall.
|
||||
- **Git Bash / MSYS2 users**: Bash resolves `obsidian` to `Obsidian.exe` (GUI) instead of `Obsidian.com` (CLI), causing colon+params to fail with exit 127 even when `Obsidian.com` is present. Create a wrapper script — see Troubleshooting.
|
||||
- **Headless Linux**: Use the `.deb` package (not snap). Run under `xvfb`. Prefix commands with `DISPLAY=:5` (or your xvfb display number). Ensure `PrivateTmp=false` if running as a service.
|
||||
|
||||
## Syntax
|
||||
@@ -77,7 +81,7 @@ The CLI provides **130+ commands** across these groups:
|
||||
| **history** | `history`, `history:list`, `history:read`, `history:restore` | File version recovery (File Recovery plugin) |
|
||||
| **workspace** | `workspace`, `tabs`, `tab:open` | Workspace layout and tab management |
|
||||
| **diff** | `diff` | Compare local vs sync file versions |
|
||||
| **dev** | `eval`, `dev:screenshot`, `dev:debug`, `dev:console`, `dev:errors`, `dev:css`, `dev:dom`, `devtools` | Developer/debugging tools |
|
||||
| **dev** | `eval`, `dev:screenshot`, `dev:debug`, `dev:console`, `dev:errors`, `dev:css`, `dev:dom`, `dev:mobile`, `devtools` | Developer/debugging tools |
|
||||
| **vault** | `vault`, `vaults`, `version`, `reload`, `restart` | Vault info and app control |
|
||||
| **other** | `outline`, `wordcount`, `recents` | Utility commands |
|
||||
|
||||
@@ -229,6 +233,17 @@ obsidian command id="dataview:dataview-force-refresh-views"
|
||||
7. **`daily:prepend`** inserts content after frontmatter, not at byte 0.
|
||||
8. **Use `eval`** to run arbitrary JavaScript against the Obsidian API (`app.*`).
|
||||
9. **`template:insert`** inserts into the currently active file in the Obsidian UI — it does not accept a `path=` parameter. If no file is open, it returns `Error: No active editor. Open a file first.` To create a file from a template via CLI, use `obsidian create path="..." template="..."` instead.
|
||||
10. **`property:set` stores list values as strings** — `value="tag1, tag2"` writes a literal comma-separated string, not a YAML array. For proper array fields, edit the note's frontmatter directly (e.g. via `read` → modify → `create --force`) or use `eval` to call the Obsidian API.
|
||||
11. **`eval` requires single-line JavaScript** — multiline JS passed inline fails with a token error. Write the script to a temp file instead:
|
||||
```bash
|
||||
cat > /tmp/obs.js << 'JS'
|
||||
var files = app.vault.getMarkdownFiles();
|
||||
files.length;
|
||||
JS
|
||||
obsidian eval code="$(cat /tmp/obs.js)"
|
||||
```
|
||||
12. **Multi-vault targeting may not work in all environments** — `obsidian "My Vault" command` can return `Error: Command "My Vault" not found` on some setups. If this happens, omit the vault name (CLI targets the most recently active vault) and switch vaults manually in the Obsidian UI.
|
||||
13. **When colon subcommands are unavailable** (e.g. Windows Git Bash without wrapper), prefer non-colon alternatives: use `properties` instead of `property:read`, and `obsidian daily:path` + `append` instead of `daily:append`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -240,3 +255,7 @@ obsidian command id="dataview:dataview-force-refresh-views"
|
||||
| Wrong vault targeted | Multi-vault ambiguity | Pass vault name as first arg |
|
||||
| IPC socket not found (Linux) | `PrivateTmp=true` in systemd | Set `PrivateTmp=false` |
|
||||
| Snap confinement issues | Snap restricts IPC | Use `.deb` package instead |
|
||||
| Multi-vault `"Name" command` fails | Vault name matching issue | Omit vault name; target most recent vault |
|
||||
| `property:set` list value is a string | CLI stores value as-is | Edit frontmatter directly or use `eval` |
|
||||
| Colon+params exit 127 (missing `.com`) | Outdated installer — `Obsidian.com` absent | Reinstall from [obsidian.md/download](https://obsidian.md/download) |
|
||||
| Colon+params exit 127 (Git Bash / MSYS2) | Bash resolves `obsidian` to `.exe` not `.com` | Create `~/bin/obsidian` wrapper: `#!/bin/bash` / `/c/path/to/Obsidian.com "$@"` and add `export PATH="$HOME/bin:$PATH"` to `~/.bashrc` |
|
||||
|
||||
@@ -196,6 +196,10 @@ obsidian property:set path="note.md" name="tags" value="[project, alpha]"
|
||||
obsidian property:set path="note.md" name="date" value="2026-02-27"
|
||||
```
|
||||
|
||||
> **Note:** `property:set` always stores `value=` as a string. Passing `value="[project, alpha]"` writes
|
||||
> the literal string `[project, alpha]`, not a YAML array. For true array-typed properties (e.g. `tags`),
|
||||
> edit the note's frontmatter directly or use `eval` with the Obsidian API.
|
||||
|
||||
### Remove Property
|
||||
|
||||
```bash
|
||||
@@ -487,6 +491,17 @@ obsidian eval code="app.vault.getMarkdownFiles().map(f => f.path).join('\n')"
|
||||
|
||||
Executes arbitrary JavaScript in the Obsidian app context. Has access to the full Obsidian API (`app`, `app.vault`, `app.workspace`, `app.metadataCache`, etc.).
|
||||
|
||||
> **Multiline scripts:** Passing multiline JavaScript inline fails with "Invalid or unexpected token".
|
||||
> Write the code to a temp file and use command substitution instead:
|
||||
>
|
||||
> ```bash
|
||||
> cat > /tmp/obs.js << 'JS'
|
||||
> var files = app.vault.getMarkdownFiles();
|
||||
> files.map(f => f.path).join('\n');
|
||||
> JS
|
||||
> obsidian eval code="$(cat /tmp/obs.js)"
|
||||
> ```
|
||||
|
||||
### Console & Errors
|
||||
|
||||
```bash
|
||||
@@ -611,6 +626,11 @@ obsidian "Archive" files total
|
||||
|
||||
If the vault name contains spaces, quote it. The vault name must match what's shown in `obsidian vaults`.
|
||||
|
||||
> **Compatibility note:** On some environments, `obsidian "My Vault" command` returns
|
||||
> `Error: Command "My Vault" not found`. If this occurs, omit the vault name — the CLI will target
|
||||
> the most recently active vault. Switch vaults in the Obsidian UI before running CLI commands
|
||||
> when targeting a specific vault.
|
||||
|
||||
---
|
||||
|
||||
## Headless / Server Setup (Linux)
|
||||
|
||||
@@ -1,30 +1,60 @@
|
||||
---
|
||||
name: obsidian-cli
|
||||
version: "1.3.0"
|
||||
description: >
|
||||
Interact with Obsidian vaults using the official Obsidian CLI (v1.12+).
|
||||
Read, create, append, search, and manage notes, daily notes, properties, tags,
|
||||
tasks, bookmarks, templates, themes, sync, plugins, and links — all from the terminal.
|
||||
Use this skill whenever the user mentions Obsidian CLI, wants to automate Obsidian
|
||||
vault operations, manage notes programmatically, script daily note workflows,
|
||||
query vault metadata, or integrate Obsidian with AI agents or automation pipelines.
|
||||
Also trigger when the user asks about controlling Obsidian from the command line,
|
||||
building scripts around their knowledge base, or running headless Obsidian setups.
|
||||
Even if the user just says "add something to my daily note" or "search my vault"
|
||||
in a CLI/scripting context, this skill applies.
|
||||
Use this skill whenever the user wants Claude to directly interact with their
|
||||
Obsidian vault — reading a note or daily note, writing or appending content,
|
||||
searching vault contents, counting or listing notes, managing tasks, moving or
|
||||
renaming files, finding orphaned notes or broken links. Without this skill, Claude
|
||||
has no way to access vault data or execute vault operations. Treat any request that
|
||||
implies "go into my vault and do X" as a trigger — the user is asking Claude to act,
|
||||
not to explain. Also trigger for vault automation, CLI scripting, or cron-based
|
||||
workflows involving Obsidian, managing sync history, querying Bases, restoring file
|
||||
versions via history, managing bookmarks, or running JavaScript against the Obsidian
|
||||
API. Skip for pure conceptual questions: how Obsidian's GUI works, navigating settings
|
||||
menus, theme or plugin installation via the UI, iCloud/third-party sync conflicts,
|
||||
general Dataview query syntax, keyboard shortcuts, or parsing vault files with external
|
||||
scripts — anything where the user needs an explanation rather than Claude performing a
|
||||
vault operation.
|
||||
triggers:
|
||||
- "obsidian"
|
||||
- "vault"
|
||||
- "daily note"
|
||||
- "obsidian cli"
|
||||
- "note"
|
||||
- "append to"
|
||||
- "prepend to"
|
||||
- "search my vault"
|
||||
- "create a note"
|
||||
- "read note"
|
||||
- "move note"
|
||||
- "rename note"
|
||||
- "delete note"
|
||||
- "tasks in obsidian"
|
||||
- "open tasks"
|
||||
- "backlinks"
|
||||
- "orphaned notes"
|
||||
- "broken links"
|
||||
- "frontmatter"
|
||||
- "properties"
|
||||
- "sync history"
|
||||
- "obsidian bases"
|
||||
- "file history"
|
||||
---
|
||||
|
||||
# Obsidian CLI
|
||||
|
||||
The official Obsidian CLI (released in v1.12, February 2026) lets you control every aspect of Obsidian from the terminal. It communicates with a running Obsidian desktop instance via IPC.
|
||||
|
||||
> For the full command reference with all subcommands, flags and examples, read
|
||||
> `references/command-reference.md` in this skill folder.
|
||||
> Read `references/command-reference.md` when you need specific flags, output formats, or
|
||||
> subcommands for any command group. It covers all 130+ commands with full parameter tables
|
||||
> and has a table of contents at the top.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| Requirement | Details |
|
||||
|---|---|
|
||||
| Obsidian Desktop | **v1.12.0+** |
|
||||
| Obsidian Desktop | **v1.12.4+** (recommended; CLI introduced in v1.12.0) |
|
||||
| CLI enabled | Settings → Command line interface → Toggle ON |
|
||||
| Obsidian running | The desktop app **must be running** for CLI to work (IPC) |
|
||||
|
||||
@@ -32,6 +62,8 @@ The official Obsidian CLI (released in v1.12, February 2026) lets you control ev
|
||||
|
||||
- **macOS / Linux**: The `obsidian` binary is registered in PATH automatically when you enable CLI in settings.
|
||||
- **Windows**: Requires an `Obsidian.com` redirector file placed alongside `Obsidian.exe`. **Must run with normal user privileges** — admin terminals produce silent failures.
|
||||
- If colon subcommands (`property:set`, `daily:append`, etc.) with parameters return exit 127, check that `Obsidian.com` exists alongside `Obsidian.exe`. If missing, you have an outdated installer — download the latest from [obsidian.md/download](https://obsidian.md/download) and reinstall.
|
||||
- **Git Bash / MSYS2 users**: Bash resolves `obsidian` to `Obsidian.exe` (GUI) instead of `Obsidian.com` (CLI), causing colon+params to fail with exit 127 even when `Obsidian.com` is present. Create a wrapper script — see Troubleshooting.
|
||||
- **Headless Linux**: Use the `.deb` package (not snap). Run under `xvfb`. Prefix commands with `DISPLAY=:5` (or your xvfb display number). Ensure `PrivateTmp=false` if running as a service.
|
||||
|
||||
## Syntax
|
||||
@@ -77,7 +109,7 @@ The CLI provides **130+ commands** across these groups:
|
||||
| **history** | `history`, `history:list`, `history:read`, `history:restore` | File version recovery (File Recovery plugin) |
|
||||
| **workspace** | `workspace`, `tabs`, `tab:open` | Workspace layout and tab management |
|
||||
| **diff** | `diff` | Compare local vs sync file versions |
|
||||
| **dev** | `eval`, `dev:screenshot`, `dev:debug`, `dev:console`, `dev:errors`, `dev:css`, `dev:dom`, `devtools` | Developer/debugging tools |
|
||||
| **dev** | `eval`, `dev:screenshot`, `dev:debug`, `dev:console`, `dev:errors`, `dev:css`, `dev:dom`, `dev:mobile`, `devtools` | Developer/debugging tools |
|
||||
| **vault** | `vault`, `vaults`, `version`, `reload`, `restart` | Vault info and app control |
|
||||
| **other** | `outline`, `wordcount`, `recents` | Utility commands |
|
||||
|
||||
@@ -229,6 +261,17 @@ obsidian command id="dataview:dataview-force-refresh-views"
|
||||
7. **`daily:prepend`** inserts content after frontmatter, not at byte 0.
|
||||
8. **Use `eval`** to run arbitrary JavaScript against the Obsidian API (`app.*`).
|
||||
9. **`template:insert`** inserts into the currently active file in the Obsidian UI — it does not accept a `path=` parameter. If no file is open, it returns `Error: No active editor. Open a file first.` To create a file from a template via CLI, use `obsidian create path="..." template="..."` instead.
|
||||
10. **`property:set` stores list values as strings** — `value="tag1, tag2"` writes a literal comma-separated string, not a YAML array. For proper array fields, edit the note's frontmatter directly (e.g. via `read` → modify → `create --force`) or use `eval` to call the Obsidian API.
|
||||
11. **`eval` requires single-line JavaScript** — multiline JS passed inline fails with a token error. Write the script to a temp file instead:
|
||||
```bash
|
||||
cat > /tmp/obs.js << 'JS'
|
||||
var files = app.vault.getMarkdownFiles();
|
||||
files.length;
|
||||
JS
|
||||
obsidian eval code="$(cat /tmp/obs.js)"
|
||||
```
|
||||
12. **Multi-vault targeting may not work in all environments** — `obsidian "My Vault" command` can return `Error: Command "My Vault" not found` on some setups. If this happens, omit the vault name (CLI targets the most recently active vault) and switch vaults manually in the Obsidian UI.
|
||||
13. **When colon subcommands are unavailable** (e.g. Windows Git Bash without wrapper), prefer non-colon alternatives: use `properties` instead of `property:read`, and `obsidian daily:path` + `append` instead of `daily:append`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -240,3 +283,7 @@ obsidian command id="dataview:dataview-force-refresh-views"
|
||||
| Wrong vault targeted | Multi-vault ambiguity | Pass vault name as first arg |
|
||||
| IPC socket not found (Linux) | `PrivateTmp=true` in systemd | Set `PrivateTmp=false` |
|
||||
| Snap confinement issues | Snap restricts IPC | Use `.deb` package instead |
|
||||
| Multi-vault `"Name" command` fails | Vault name matching issue | Omit vault name; target most recent vault |
|
||||
| `property:set` list value is a string | CLI stores value as-is | Edit frontmatter directly or use `eval` |
|
||||
| Colon+params exit 127 (missing `.com`) | Outdated installer — `Obsidian.com` absent | Reinstall from [obsidian.md/download](https://obsidian.md/download) |
|
||||
| Colon+params exit 127 (Git Bash / MSYS2) | Bash resolves `obsidian` to `.exe` not `.com` | Create `~/bin/obsidian` wrapper: `#!/bin/bash` / `/c/path/to/Obsidian.com "$@"` and add `export PATH="$HOME/bin:$PATH"` to `~/.bashrc` |
|
||||
|
||||
@@ -196,6 +196,10 @@ obsidian property:set path="note.md" name="tags" value="[project, alpha]"
|
||||
obsidian property:set path="note.md" name="date" value="2026-02-27"
|
||||
```
|
||||
|
||||
> **Note:** `property:set` always stores `value=` as a string. Passing `value="[project, alpha]"` writes
|
||||
> the literal string `[project, alpha]`, not a YAML array. For true array-typed properties (e.g. `tags`),
|
||||
> edit the note's frontmatter directly or use `eval` with the Obsidian API.
|
||||
|
||||
### Remove Property
|
||||
|
||||
```bash
|
||||
@@ -487,6 +491,17 @@ obsidian eval code="app.vault.getMarkdownFiles().map(f => f.path).join('\n')"
|
||||
|
||||
Executes arbitrary JavaScript in the Obsidian app context. Has access to the full Obsidian API (`app`, `app.vault`, `app.workspace`, `app.metadataCache`, etc.).
|
||||
|
||||
> **Multiline scripts:** Passing multiline JavaScript inline fails with "Invalid or unexpected token".
|
||||
> Write the code to a temp file and use command substitution instead:
|
||||
>
|
||||
> ```bash
|
||||
> cat > /tmp/obs.js << 'JS'
|
||||
> var files = app.vault.getMarkdownFiles();
|
||||
> files.map(f => f.path).join('\n');
|
||||
> JS
|
||||
> obsidian eval code="$(cat /tmp/obs.js)"
|
||||
> ```
|
||||
|
||||
### Console & Errors
|
||||
|
||||
```bash
|
||||
@@ -611,6 +626,11 @@ obsidian "Archive" files total
|
||||
|
||||
If the vault name contains spaces, quote it. The vault name must match what's shown in `obsidian vaults`.
|
||||
|
||||
> **Compatibility note:** On some environments, `obsidian "My Vault" command` returns
|
||||
> `Error: Command "My Vault" not found`. If this occurs, omit the vault name — the CLI will target
|
||||
> the most recently active vault. Switch vaults in the Obsidian UI before running CLI commands
|
||||
> when targeting a specific vault.
|
||||
|
||||
---
|
||||
|
||||
## Headless / Server Setup (Linux)
|
||||
|
||||
Reference in New Issue
Block a user