agentsclimarketplace

Obsidian

Skill lx-wnk/skills/skills/obsidian

Portable Agent Skills for AI coding agents (Claude Code, Codex, Cursor, Gemini) — agentskills.io-conformant, versioned, installable via skills.sh

Install
npx -y skills add lx-wnk/skills --skill obsidian

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Obsidian vault access via Local REST API using curl — read, search, create, or update notes in the knowledge base. Trigger on ANY of these: user mentions "obsidian", "vault", "knowledge base", "my notes", or "note" in a save/lookup context; user asks to "save", "persist", "document", "note down", or "look up" information; phrases like "note this down", "add this to my knowledge base", "search my notes", "check if I have notes on X", "create a note"; CLAUDE.md says to search or store in Obsidian before/after tasks — do it proactively; starting a task where prior context might exist → search first; mid-task discovery of a non-obvious insight, gotcha, root cause, or workaround → save it; finishing a task with decisions or learnings worth remembering → persist it; something written to CLAUDE.md or project docs → also save it for cross-project search.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.2 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Obsidian Knowledge Base – curl API Reference

When to use this skill

There are three natural moments to reach for Obsidian:

  1. Before a task — search for existing context so you don't repeat research or contradict prior decisions
  2. Mid-task — when you discover something non-obvious (a hidden bug cause, a framework gotcha, an architecture constraint, a deliberate tradeoff) that would cost future-you to rediscover
  3. After a task — persist new learnings, updated project status, or decisions made during the session

If something gets written to CLAUDE.md or project documentation, consider whether it also belongs in Obsidian — CLAUDE.md is project-scoped, Obsidian is cross-project and searchable.


Base Config

  • URL: $OBSIDIAN_BASE_URL
  • Auth: $OBSIDIAN_API_KEY
  • Root folder: $OBSIDIAN_ROOT (default: claude-memory)
  • SSL: self-signed cert → always use curl -sk
  • Default subfolders: private/, work/, misc/

Setup: Add these vars to ~/.claude/settings.json under the "env" key — not to ~/.claude/settings.local.json (that path is not a recognized Claude Code settings scope and is silently ignored):

{ "env": { "OBSIDIAN_BASE_URL": "https://127.0.0.1:27124", "OBSIDIAN_API_KEY": "your-key" } }

Helper alias (reduces repetition)

obs() { curl -sk -H "Authorization: Bearer $OBSIDIAN_API_KEY" "$@"; }
ROOT="${OBSIDIAN_ROOT:-claude-memory}"

Note: Each Bash tool call runs in a fresh shell — obs() and ROOT do not persist between invocations. Redefine both at the top of each command, or inline the full curl -sk -H "Authorization: Bearer $OBSIDIAN_API_KEY" directly.


Search

Uses Obsidian's built-in index — fast even on large vaults.

obs -X POST "$OBSIDIAN_BASE_URL/search/simple/?query=KEYWORD" \
  | python3 -c "import sys,json; [print(r['filename']) for r in json.load(sys.stdin)]"

Use specific keywords that likely appear in note filenames (e.g. auth, docker, deployment).


Read a note

obs "$OBSIDIAN_BASE_URL/vault/${ROOT}/work/My-Note.md"

URL-encode spaces as %20. For complex paths:

python3 -c "import urllib.parse; print(urllib.parse.quote('PATH/WITH SPACES'))"

Create or update a note (PUT = upsert)

obs -X PUT \
  -H "Content-Type: text/markdown" \
  --data-binary "# Title

Content here." \
  "$OBSIDIAN_BASE_URL/vault/${ROOT}/work/My-Note.md"

Append to an existing note

obs -X POST \
  -H "Content-Type: text/markdown" \
  --data-binary "

## New Section
Content." \
  "$OBSIDIAN_BASE_URL/vault/${ROOT}/work/My-Note.md"

Delete a note

obs -X DELETE "$OBSIDIAN_BASE_URL/vault/${ROOT}/work/My-Note.md"

List folder contents

obs "$OBSIDIAN_BASE_URL/vault/${ROOT}/work/"

Note naming conventions

  • One topic per note — no catch-all files
  • Filename = searchable keyword (Docker-Port-Conflicts.md, Auth-JWT-Setup.md)
  • Path: $OBSIDIAN_ROOT/{private|work|misc}/{Topic}.md
    • work/ — project notes, architecture decisions, tickets, bug findings
    • private/ — personal projects and private insights
    • misc/ — tools, plugins, general knowledge that doesn't fit elsewhere

Error codes

CodeMeaning
200/204OK
401Wrong or missing API key
404Note/path doesn't exist
0 / refusedObsidian not running or plugin disabled

One-time Migration (old → new folder structure)

If your vault still uses a legacy structure (e.g. Claude Code/{Allgemein,Privat,Arbeit}/), run this script to move all notes into the new $OBSIDIAN_ROOT/{misc,private,work}/ layout:

python3 - <<'EOF'
import subprocess, json, urllib.parse, os, sys

BASE = os.environ["OBSIDIAN_BASE_URL"]
KEY  = os.environ["OBSIDIAN_API_KEY"]
ROOT = os.environ.get("OBSIDIAN_ROOT", "claude-memory")

FOLDER_MAP = {
    "Claude Code/Allgemein": f"{ROOT}/misc",
    "Claude Code/Privat":    f"{ROOT}/private",
    "Claude Code/Arbeit":    f"{ROOT}/work",
}

def api(method, path, **kwargs):
    url = f"{BASE}/vault/{urllib.parse.quote(path, safe='/')}"
    cmd = ["curl", "-sk", "-X", method, "-H", f"Authorization: Bearer {KEY}"]
    if "data" in kwargs:
        cmd += ["-H", "Content-Type: text/markdown", "--data-binary", kwargs["data"]]
    cmd.append(url)
    r = subprocess.run(cmd, capture_output=True, text=True)
    return r.stdout

for old_folder, new_folder in FOLDER_MAP.items():
    listing = api("GET", old_folder + "/")
    try:
        files = json.loads(listing).get("files", [])
    except Exception:
        print(f"Skip {old_folder} — not found or empty")
        continue
    for f in files:
        if not f.endswith(".md"):
            continue
        old_path = f"{old_folder}/{f}"
        new_path = f"{new_folder}/{f}"
        content = api("GET", old_path)
        api("PUT", new_path, data=content)
        api("DELETE", old_path)
        print(f"Moved: {old_path} → {new_path}")

print("Migration complete.")
EOF

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.