Obsidian Integration (Tutorial + Toolkit)
Overview
This skill turns an Obsidian vault into an addressable, automatable service. Two community
plugins provide complementary capabilities:
- Local REST API — a secure HTTPS REST interface for file operations (read, write,
create, delete, search notes). It does NOT execute plugin commands. - Advanced URI — extends the
obsidian://protocol so external callers can trigger any
Obsidian command (including community-plugin commands such as posting a tweet).
Together they let WorkBuddy: save bookmarks/notes into the vault, read/analyze notes, and fire
in-Obsidian actions (e.g. the notetweet plugin's "post file as thread" command).
> The combination is the answer to "Local REST API can't run commands" — Advanced URI supplies
> exactly the command-execution piece that Local REST API is missing.
When To Use
- User says "connect Obsidian", "save this to my vault", "read my Obsidian notes", etc.
- User wants to trigger an Obsidian plugin command from outside the app.
- User wants to automate posting to X/Twitter from notes (notetweet / x-post-saver plugins).
Prerequisites (one-time, inside Obsidian)
- Install Local REST API — Settings → Community plugins → Browse → "Local REST API".
Enable it, then open its settings and click Generate Token. Note the token and the port
(default 27123, but the real port is often different — see Step 1). - Install Advanced URI — same browse flow, search "Advanced URI", enable it.
- (Optional, for posting) Install notetweet or x-post-saver and configure X API keys
in their settings (stored in Obsidian's encrypted Secret Storage).
Obsidian must be running for both the REST API and URI commands to work.
Step 1 — Discover the real API port
The default port (27123) is frequently occupied, and Obsidian picks another on launch. Find it:
netstat -ano | grep -E "2712[0-9]"
# Example output: TCP 127.0.0.1:27124 0.0.0.0:0 LISTENING 34448
Use whichever port is LISTENING (here 27124). Store it as BASE in scripts.
Step 2 — Authenticate
The token from Local REST API settings is used as a Bearer token on every HTTPS request:
Authorization: Bearer <token>
The API serves over HTTPS with a self-signed certificate — clients must disable cert
verification (curl --insecure, or ssl.CERT_NONE in Python). Plain HTTP returns HTTP 000.
Step 3 — Verify the connection
Read any existing note (URL-encode the filename):
curl -s -H "Authorization: Bearer <token>" \
"https://127.0.0.1:27124/vault/%E6%AC%A2%E8%BF%8E.md" --insecure
HTTP 200 with note body = success.
Core Capability A — File operations (Local REST API)
| Action | Method + Path | Notes |
|---|---|---|
| Read note | GET /vault/<file> |
URL-encode filename |
| Write/create note | PUT /vault/<file> |
Body = markdown, Content-Type: text/markdown |
| Append | POST /vault/<file> |
|
| Delete | DELETE /vault/<file> |
|
| List vault | GET /vault/ |
Returns JSON {"files":[...]} |
| Search | GET /search/?query=<q> |
Full-text |
See scripts/obsidian_helper.py for a ready-to-run client.
Core Capability B — Trigger commands (Advanced URI)
Format (note the adv-uri host, not obsidian):
obsidian://adv-uri?vault=<vault>&filepath=<file>&commandid=<command-id>
commandidis recommended overcommandname(stable). Find a plugin's command id in its
sourcemanifest.json/ command registration.- Optional
confirm=trueauto-clicks the first modal button. - Opening a file + running a command: include
filepathso the command targets that note.
Windows launch gotcha: PowerShell blocks URIs containing %VAR%-style segments (URL-encoded
non-ASCII like %E6%AC%A2). Pass the raw (un-encoded) filename instead:
Start-Process "obsidian://adv-uri?vault=test1&filepath=欢迎.md&commandid=editor:save-file"
From Bash/Git Bash use cmd /c start "" "<uri>" or call PowerShell as above.
Common Workflows
Save arbitrary content into the vault
Write a note via PUT /vault/<filename> (Capability A). Filename from title/source; append
metadata (source, timestamp, tags) as YAML frontmatter or a --- footer.
Read & analyze a note
GET /vault/<file>, then summarize / extract / cross-link as requested.
Post a tweet/thread from a note
- Write the note with
THREAD START/THREAD ENDmarkers (notetweet format). - Trigger the plugin command via Advanced URI, e.g.
commandid=<notetweet-post-file-as-thread-id>. - Always confirm with the user before any real external post — it is a public action.
Troubleshooting
| Symptom | Cause / Fix |
|---|---|
HTTP 000 on HTTPS |
Wrong port, or Obsidian not running. Re-check netstat. |
HTTP 000 on HTTP |
API is HTTPS-only. Use https:// + --insecure. |
401 |
Bad/expired token. Regenerate in plugin settings. |
| PowerShell refuses URI | %-encoded non-ASCII in URI. Use raw Chinese filename. |
| Command did nothing | Obsidian not focused/running, or wrong commandid. Verify plugin installed. |
Resources
scripts/obsidian_helper.py— runnable client:read,write,search,list,cmd.references/api_reference.md— endpoint details and Python/PowerShell snippets.