Turn Obsidian notes and AI session summaries into living concept maps.
Visual Notes watches configured markdown folders, asks Claude to extract the main concepts and relationships, writes a JSON graph sidecar, and renders an interactive Cytoscape.js graph directly inside Obsidian.
The markdown note stays the source of truth. Daily notes, AI session summaries, manual notes, mobile edits, Templater output, and synced changes all flow through the same plugin pipeline: if a watched note changes, it can be extracted and rendered.
- A visual daily recap: see the day's work, decisions, blockers, and cross-domain connections at a glance.
- Works with any note source: Claude Code, OpenCode, Copilot, manual typing, and mobile edits all become ordinary markdown input.
- No separate graph editor: edit the note; Visual Notes regenerates the graph sidecar.
- Useful for memory and navigation: nodes summarize important concepts; labeled edges explain why they matter.
flowchart TB
classDef input fill:#eef2ff,stroke:#4f46e5,stroke-width:2px,color:#111827
classDef plugin fill:#ecfeff,stroke:#0891b2,stroke-width:2px,color:#0f172a
classDef ai fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#111827
classDef data fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#052e16
classDef render fill:#fae8ff,stroke:#c026d3,stroke-width:2px,color:#111827
classDef optional fill:#fff7ed,stroke:#ea580c,stroke-width:2px,stroke-dasharray: 5,5,color:#111827
subgraph Vault["Obsidian vault"]
Note[("Any watched markdown note")]
Sidecar[("Sibling graph sidecar<br/>{note-basename}-overview.json")]
end
subgraph Plugin["Visual Notes Obsidian plugin"]
Watch["Watch + debounce"]
Source["Choose source<br/>raw note by default"]
Hash["Hash + skip unchanged"]
Extract["Extract graph with Claude"]
Validate["Validate schema"]
Render["Render inline"]
end
DailyContext["Optional Daily Context provider<br/>structured day sources"]
DateTags["Optional Date Tags provider<br/>date tag convention/API"]
Claude(("Anthropic Claude"))
Pane["Interactive Cytoscape visual<br/>inside the note"]
Note --> Watch
DateTags -. can feed .-> DailyContext
DailyContext -. optional source adapter .-> Source
Watch --> Source --> Hash --> Extract --> Claude
Claude --> Validate --> Sidecar --> Render --> Pane
Sidecar -. read by .-> Render
Pane -. rendered in .-> Note
class Note input
class Watch,Source,Hash,Extract,Validate,Render plugin
class Claude ai
class Sidecar data
class Pane render
class DateTags,DailyContext optional
Visual Notes is useful by itself: configure any folder of markdown notes, provide an Anthropic key, and it can extract/render a graph for those notes. Daily Context and Date Tags are optional providers/adapters, not required runtime dependencies.
| Component | Standalone responsibility | Optional integrations |
|---|---|---|
| Visual Notes plugin | Watches markdown, calls Claude, writes graph sidecars, renders Cytoscape inline. | Can consume Daily Context when present; can render explicit visual-notes blocks in templates. |
| Daily Context plugin | Exposes structured date-scoped source lists through a versioned Obsidian API. | Can use Date Tags as its date-tag provider; can be consumed by Visual Notes or any other plugin/automation. |
| Date Tags plugin | Maintains created/modified metadata and date tags. | Can provide tag-building semantics to Daily Context. |
| AI session summary skill/template | Not part of the public plugin core; an integration recipe that writes ordinary markdown notes Visual Notes can watch. | Useful for AI-client session logging, but Visual Notes does not require it. |
One useful composition is AI session logging. In that workflow an AI-client skill creates an ordinary markdown session note from a vault template, then Visual Notes treats it like any other watched note.
sequenceDiagram
participant User
participant Skill as obsidian-notes skill
participant Vault as Obsidian vault
participant VN as Visual Notes plugin
participant Claude as Anthropic Claude
User->>Skill: "make/end session summary"
Skill->>Vault: write AI session note from template
Vault-->>VN: watched session note modified
VN->>VN: raw-note extraction for non-date-named note
VN->>Claude: graph extraction request
Claude-->>VN: tool JSON graph
VN->>Vault: write session-overview.json
VN-->>User: render graph in visual-notes block
The template is an adapter detail, not a Visual Notes dependency. A good AI-session template can include:
> [!summary] Session Summary
> One-line summary.
## Session Visual
```visual-notes
```
## 2026-05-17If you also use Date Tags/Daily Context, associate the session with a day via an
explicit date/YYYY/MM/DD tag instead of adding a [[YYYYMMDD]] daily-note
wikilink in the body.
sequenceDiagram
participant Daily as Daily note
participant DC as Daily Context
participant DT as Date Tags
participant VN as Visual Notes
participant Claude as Anthropic Claude
DT-->>DC: date tag convention/API
Daily->>VN: watched daily note modified or manual extract
VN->>DC: getDailyContext(date, include sources)
DC-->>VN: daily sections + AI session sources
VN->>Claude: graph extraction request
Claude-->>VN: tool JSON graph
VN->>Daily: render daily overview sidecar inline
Visual Notes renders as a card at the top of the note in both reading and edit views. The graph is interactive; the note remains normal markdown underneath.
Feature overview:
- Watches one or more configured markdown folders, including daily-note folders and AI session folders.
- Debounces saves and skips unchanged content using a markdown hash.
- Sends structured Daily Context sources to the Anthropic Messages API for
date-named daily notes when the
daily-contextplugin is available, otherwise falls back to full note markdown. - Validates the returned graph against the shared sidecar schema.
- Writes
{note-basename}-overview.jsonnext to the note. - Renders the sidecar inline in reading/source views or in an explicit
visual-notescode block. - Supports pin/unpin/delete/regenerate commands for manual control.
- Shows extraction count and status in the Obsidian status bar.
- Tracks token usage and estimated cost metadata in the sidecar when the API response includes usage.
This repository contains two plugins and one shared schema:
| Piece | Purpose | Status |
|---|---|---|
plugins/obsidian-plugin |
Primary Obsidian plugin. Watches notes, calls Claude, writes sidecars, and renders Cytoscape inline. | MVP implementation in progress |
plugins/claude-code-plugin |
Optional companion for future agent-curated sidecars. Not required for automatic extraction. | Scaffolded; migration pending |
shared/schema.json |
JSON Schema contract for sidecar graph files. | Defined |
docs/design.md |
Living design document for open/future work. | Maintained as decisions evolve |
The Obsidian plugin is the standalone product. The Claude Code companion is an optional adapter: it can eventually pre-populate or pin curated sidecars, but Visual Notes does not depend on any AI-client plugin or skill.
Any watched folder/
├── note.md
└── note-overview.json
Daily folder example/
├── 20260517.md
└── 20260517-overview.json
AI session folder example/
└── 2026-05-17 plugin workflow/
├── 2026-05-17 plugin workflow.md
└── 2026-05-17 plugin workflow-overview.json
Obsidian plugin
├── settings tab # API key, watched folders, debounce, model, Daily Context
├── file watcher # configured markdown folders
├── extractor # requestUrl -> Anthropic Messages API
├── schema validation # Zod + shared/schema.json
└── renderer # Cytoscape in MarkdownRenderChild
Important invariants:
- The
.mdnote is the source of truth for extraction. - The sidecar JSON is the source of truth for rendered graph data.
_pinned: trueon a sidecar suppresses automatic re-extraction unless the user runs force regenerate.- The renderer tolerates unsupported future sidecar kinds by showing a placeholder instead of crashing.
- Daily Context integration is optional and applies automatically only to date-named daily notes. Other watched markdown files extract from their own content, so non-daily workflows stay standalone.
Until a release is published, use the development workflow:
pnpm install
pnpm --filter @visual-notes/obsidian-plugin buildThen copy or symlink plugins/obsidian-plugin into your vault's
.obsidian/plugins/visual-notes directory and enable Visual Notes in
Obsidian's Community plugins settings.
After enabling:
- Open Settings → Visual Notes.
- Paste an Anthropic API key.
- Add watched folders, such as
Daily Notes,Captains Log,0 AI Sessions, or0 Profisee/AI Sessions. - Choose a debounce and model, or keep the defaults.
- Save or manually extract a note with Visual Notes: Extract from current note.
See the plugin README for detailed Obsidian-specific instructions:
plugins/obsidian-plugin/README.md.
The Claude Code companion is scaffolded but not yet migrated from the original private workflow. Its intended install path is:
/plugin install bobthearsonist/visual-notes/plugins/claude-code-plugin
See plugins/claude-code-plugin/README.md.
The Obsidian command palette exposes:
- Visual Notes: Extract from current note — manually extract the active markdown file unless its sidecar is pinned.
- Visual Notes: Extract from current note using Daily Context — manually extract through the Daily Context provider and do not fall back to raw markdown if that provider is unavailable.
- Visual Notes: Regenerate (force) — bypasses cached hash and pin state, with a per-file cooldown.
- Visual Notes: Pin this overview — preserves the current sidecar from automatic replacement.
- Visual Notes: Unpin this overview — resumes automatic extraction.
- Visual Notes: Delete sidecar — removes the generated graph sidecar.
Visual Notes sends either the configured Daily Context sources or the active note markdown to the Anthropic API when extraction runs. Do not add folders or Daily Context sources containing notes you do not want sent to a third-party API.
Bring your own API key; this project does not proxy requests or aggregate usage. At the default Haiku model, a typical extraction is designed to cost only a few fractions of a cent, but actual spend depends on note length, model, save frequency, and retries. The plugin shows today's extraction count and stores usage metadata when available.
If you have a vault that already contains *-overview.html files
alongside their *-overview.json sidecars (typically under work
folders), those HTMLs were produced by a previous agent-curated
workflow and are not regenerated by the Obsidian plugin. The plugin
renders the same JSON inline; the legacy HTMLs are reference
artifacts only. See docs/design.md — Legacy hook artifacts vs.
plugin renderer
for the full story.
Requirements:
- Node.js 20+
- pnpm
Common commands:
pnpm install
pnpm build
pnpm typecheck
pnpm lintRepository layout:
visual-notes/
├── README.md # this file
├── LICENSE # MIT
├── manifest.json # marketplace metadata mirror
├── versions.json # marketplace compatibility mirror
├── docs/
│ ├── design.md
│ └── marketplace-readiness.md # release/submission checklist
├── scripts/
│ └── package-obsidian-plugin.mjs # builds release-ready Obsidian assets
├── shared/
│ ├── package.json
│ └── schema.json
└── plugins/
├── obsidian-plugin/
│ ├── README.md
│ ├── manifest.json
│ ├── prompts/extract-graph.md
│ └── src/
└── claude-code-plugin/
├── README.md
├── .claude-plugin/plugin.json
├── hooks/
└── skills/visual-notes/
- Obsidian plugin README
- Claude Code plugin README
- Living design document
- Marketplace readiness checklist
- Project issues
Marketplace readiness is tracked in
docs/marketplace-readiness.md. To produce
release-ready Obsidian assets, run pnpm package:obsidian from the repo root.
The root manifest.json/versions.json files are marketplace-facing mirrors of
the Obsidian plugin metadata under plugins/obsidian-plugin.
MIT — see LICENSE.