claude-obsidian
CLI ToolAgriciDaniel/claude-obsidian
AI self-organizing knowledge base for Obsidian and Claude Code.
Overview
A local-first system that turns source material into linked, cited Obsidian notes. Provides 15 agent skills for capture, query, linting, research, and canvas mapping. Keeps the vault as plain Markdown files you own.
README Preview
\n \n\n\nclaude-obsidian\n\n\n Build an Obsidian knowledge base that becomes more useful every time you use it.\n Capture sources, create connected notes, retrieve grounded answers, and keep the vault healthy—without giving up ownership of your files.\n\n\n\n \n \n \n \n\n\n\n See the workflow ·\n Quick start ·\n Explore the skills ·\n Installation guide ·\n Windows & WSL\n\n\nclaude-obsidian is a local-first knowledge system for Claude Code and compatible\n[Agent Skills](https://agentskills.io) hosts. It turns source material into\nlinked, source-cited Obsidian pages; answers from the evidence already in the\nvault; and provides explicit workflows for research, retrieval, maintenance,\nand visual mapping.\n\nYour vault remains a normal directory of Markdown, JSON, and source files. It is\nnot hidden in a plugin cache, locked in a cloud database, or silently uploaded\nto a model.\n\n## From source to living knowledge\n\nMost AI note workflows stop after saving text. claude-obsidian is organized\naround a repeatable loop: retain the source, ground the claims, connect the\nknowledge, then put it back to work.\n\n\n\n- **Capture with context.** Bring local sources through a visible inbox and\n preserve immutable, content-addressed copies before synthesis.\n- **Ground every important claim.** Source and claim ledgers retain authority,\n freshness, support, contradiction, confidence, and review state.\n- **Connect what you learn.** Build linked pages, indexes, Maps of Content,\n methodology-aware structures, and Obsidian Canvas views.\n- **Use the vault again.** Query, research, retrieve, lint, and fold what is\n already known instead of starting every conversation from zero.\n\n## See the vault\n\nThe output is meant to remain useful with or without an agent: plain Markdown\nfor portability, Obsidian for navigation and visual exploration.\n\n\n \n \n\n\n\n Linked knowledge in Graph view · A visual knowledge map in Obsidian Canvas\n\n\n## Why it fe
FAQ (5)
TroubleshootingHow do I fix checkpoint COMMITTED_MODE_MISMATCH in a Windows-created Git repo used from WSL?
Upgrade to claude-obsidian v2.2.0 or later. PR #177 makes checkpoint honor core.filemode=false, so it no longer requires Git mode 100755 when the persisted transaction result contains an executable POSIX mode. After upgrading, rerun checkpoint for the failed operation. Verify the repository setting with git config --get core.filemode; false is expected for repos created or cloned by native Windows Git. Do not edit changed-paths.json or use git update-index --chmod=+x, as those falsify provenance or create staged state that checkpoint rejects.
TroubleshootingWhy does stop_status report completed transaction journals over 64 KiB as unreadable, and why doesn't `transaction recover` clear the warning?
This is a false positive caused by a 64 KiB read limit in stop_status. Journals larger than that were truncated before JSON parsing, so valid journals with "state": "complete" were counted as unreadable. The recommended claude-obsidian transaction recover does not clear them because it only handles prepared, applying, and rollback-failed journals; completed journals are intentionally skipped.
Fix: upgrade to claude-obsidian v2.2.0 or newer. PR #177 raises the journal read bound to 8 MiB.
Temporary verification on older versions:
import json
raw = open(journal_path, "rb").read()
print(len(raw), json.loads(raw)["state"])
If the output ends with complete, the warning can be ignored until the upgrade. Running transaction recover is a no-op for these journals.
TroubleshootingHow do I fix false ambiguous-target lint findings caused by the `.raw/` archive in claude-obsidian?
In claude_obsidian/lint_engine.py, add .raw to _IGNORED_WALK_DIRS:
_IGNORED_WALK_DIRS = {
".git",
".obsidian",
".vault-meta",
".cache",
".pytest_cache",
"__pycache__",
"node_modules",
".raw",
}
Then rerun:
python scripts/claude-obsidian.py lint --vault "$VAULT" --format markdown
This prevents archived captures from being treated as Obsidian link-resolution candidates. Obsidian ignores dot-prefixed folders, so files under .raw/ should not compete with pages under wiki/sources/. The narrow fix also removes related false stale_index_entries and orphans findings. Provenance validation is unaffected because it reads the ledger directly instead of using _walk_files().
A broader alternative is to skip every dot-prefixed directory, matching Obsidian’s behavior for all hidden folders, but that is a wider behavior change. Reported in claude-obsidian 2.1.0 with engine 1.1.1.
TroubleshootingHow do I fix the Claude Code hook error "NameError: name 'false' is not defined"?
In Claude Code 2.1.49, command hooks do not support the separate args field in hooks/hooks.json. A hook defined with "command": "python3" plus args runs only python3, causing Python to read the hook's JSON payload from stdin and fail on lowercase false.
Edit hooks/hooks.json, remove the args array, and use a single command string:
SessionStart:"command": "python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/claude-obsidian.py\" hook session-start"
Stop:"command": "python3 \"${CLAUDE_PLUGIN_ROOT}/scripts/claude-obsidian.py\" hook stop"
Keep the same "type": "command" and "timeout" values, then restart Claude Code or reload the plugin. The adapter should then receive the JSON payload and exit with status 0. Although the traceback is non-blocking, the lifecycle hooks do not run until this change is made.
TroubleshootingWhy does claude-obsidian lint report a false dead link for paths with %23 (encoded #) in the filename?
This false positive was a bug in lint engine versions before 3.0.0: _parse_links() URL-decoded the destination before splitting off the # fragment, so an encoded %23 in a filename was misread as a fragment delimiter and the truncated path lookup failed. Fix: upgrade to claude-obsidian v3.0.0 or later (https://github.com/AgriciDaniel/claude-obsidian/releases/tag/v3.0.0). The fix splits the fragment from the still-encoded destination and decodes the path only once, so links like [doc](../some%20folder%20%231/file.md) resolve to the real file and no dead link is reported. No changes to your Markdown are needed — the percent-encoding per RFC 3986 was already correct.