senna-lang80 downloadsClaude Code's /ide, with your knowledge graph attached. Select text and it's pushed to Claude with the graph expanded: embeds inlined, linked notes summarized, heading path and backlinks.
Claude Code IDE integration for Obsidian — with your knowledge graph attached.
This plugin makes Obsidian show up in Claude Code's /ide picker (the same lock-file +
localhost WebSocket + MCP protocol that the VS Code and JetBrains extensions use), so Claude
Code automatically sees the note you're editing and the text you've selected.
On top of that base IDE integration, it adds the thing that makes Obsidian different from a
code editor: expanded graph context. When you select text, the plugin doesn't just send the
raw markdown with opaque [[links]] — it resolves and inlines the surrounding knowledge graph
and ships it in a single payload:
![[embeds]] → the linked note's actual content, inlined[[wikilinks]] → a short summary (frontmatter + first paragraph) of each target## Section > ### Subsection)No extra MCP server, no multi-step tool calls — it arrives with the selection.
Every other Obsidian ↔ Claude Code integration (and every generic Obsidian MCP server) reaches
linked content the same way: Claude pulls it, link by link, in multiple round-trips. Claude
sees [[Some Note]] as opaque text, has to decide to resolve it, calls a resolve/read tool, gets
raw markdown back (with more [[links]] inside), and repeats — N links means N×2 tool calls.
Servers that run outside Obsidian even re-implement Obsidian's link resolution themselves, which
can diverge from how Obsidian actually resolves links.
This plugin instead does the resolution server-side, inside Obsidian, using Obsidian's own
metadataCache link resolver, expands the content once, and pushes it with the selection.
| Typical plugins / MCP servers | Graph Context for Claude Code | |
|---|---|---|
| Link content delivery | Claude pulls, N round-trips | Pushed once with the selection |
[[link]] content |
Raw / not expanded | Embeds inlined, links summarized |
| Link resolution | Claude-driven or re-implemented | Obsidian's own resolver |
| Heading path / backlinks | Separate tool calls (if any) | Included in the payload |
It is not that other tools can't get this context — it's that they make Claude fetch it, link by link, after the fact. Here it's automatic, resolved correctly, and zero round-trips.
isDesktopOnly — it runs a Node WebSocket server).npm install && npm run buildmain.js and manifest.json into your vault at
<vault>/.obsidian/plugins/graph-context-for-claude-code/You should see a notice: Graph Context for Claude Code: ready on port <PORT>.
claude, then type /ide and pick Obsidian.Select a few lines in a note that contains links/embeds, then ask e.g. "summarize what I've selected and how it connects to the linked notes" — Claude already has the expanded context.
Base IDE tools: getCurrentSelection, getLatestSelection, getWorkspaceFolders,
getOpenEditors, openFile, openDiff.
Graph-context tools:
getSelectionWithContext — current selection + EnrichedContext (heading path, frontmatter,
expanded embeds, wikilink summaries, backlinks).getNoteExpanded { path } — any vault note, expanded the same way (path-guarded to the vault).
Loads the note on demand if it isn't already cached, so it works on notes you haven't opened.The standard selection_changed notification is also enriched with a context field, so the
context follows your selection automatically.
0 for a random ephemeral port (recommended), or set a fixed port.127.0.0.1, writes a lock file to
~/.config/claude/ide/<port>.lock (and ~/.claude/ide/<port>.lock) containing the port, the
vault path, and a per-session auth token, and cleans it up on unload/exit.selectionchange).src/context/) is pure and Obsidian-free: it takes an injected
VaultPort (backed by metadataCache / vault.cachedRead) so the link-expansion, summary,
heading-path and size-capping logic is fully unit-tested.![[note#heading]] embeds expand to just that section; ![[note#^block]] to just that block.truncated flags — never silently dropped.getNoteExpanded sidesteps this by loading on demand.selection_changed is debounced (~150 ms) so a drag-select doesn't flood the connection. Graph
context is attached only to non-empty selections; a bare cursor move sends just the standard
selection fields. Note-level context (frontmatter, links, backlinks) is memoized per note, so
moving the cursor within a note only recomputes the heading path.getSelectionWithContext, getNoteExpanded) always return full context on demand,
regardless of the above push-side optimizations.The WebSocket server binds to 127.0.0.1 only and rejects any connection whose
x-claude-code-ide-authorization header doesn't match the per-session token in the lock file.
File-opening / diff tools are guarded to the vault root.
Automated review flags this plugin for using Node's fs module outside the Obsidian vault API.
This is required by the Claude Code IDE protocol and is the plugin's core function: Claude Code
discovers an IDE by reading a lock file that the IDE writes under the user's config directory
(~/.config/claude/ide/<port>.lock and ~/.claude/ide/<port>.lock). Those paths are outside the
vault, so the Obsidian vault API cannot reach them — fs is the only option, and it's the same
mechanism the official VS Code / JetBrains extensions use.
The fs usage is intentionally confined to lock files: every write/delete is guarded by
isLockFilePath(), which permits only paths of the form …/ide/<port>.lock. The plugin does not
read or write any other file on disk; all note access goes through the Obsidian vault API.
This is an independent, unofficial integration. "Claude Code" is a product of Anthropic; this plugin is not affiliated with or endorsed by Anthropic.
MIT © 2026 senna-lang