@graphview tool renders an interactive, Obsidian-style graph — force-directed, with physics — to a self-contained HTML file that opens in the browser. You drag nodes and the rest reacts, zoom/pan, search, filter by type and click to focus on a region.
Unlike @diagram, which produces a static image (PNG/SVG), the output here is a living graph: the physics engine is pure JavaScript running on a <canvas>, embedded in the binary via go:embed. No CDN, no network and no API key — it works offline from the first run, the same self-contained DNA as the embedded Graphviz, the embedded TTS/STT and the pure-Go voice notes.
Usage
@graphview itself. It works in agent, coder and chat (see Availability).
Data sources (source)
The source argument decides where the nodes and edges come from:
Arguments
Tolerated input aliases (in case the model varies the shape): a node accepts
title/name as label and type/group as kind; an edge accepts from/to as source/target. Duplicate nodes are deduplicated by id and dangling edges/self-loops are dropped, so the graph is always well-formed.
The interactive experience
The generated HTML is a complete visualization app — all client-side, no network:- Drag + physics — drag any node; the force-directed simulation (repulsion + springs + gravity + damping) re-settles the rest. Double-click pins/unpins a node.
- Zoom & pan — scroll/trackpad to zoom; drag the background to move. On touch, pinch to zoom and two fingers to pan.
- Click to focus (expand) — click/tap a node to select it: the neighborhood is highlighted, the rest dims, a detail panel opens (type, title, summary, connections) and the camera glides and zooms to frame the node and its neighbors. Click an edge to highlight it and see the weight. Click empty space to clear.
- Search — the search box highlights matching nodes and dims the rest.
- Filter by type — click a type in the legend to show/hide that
kind. Each type has its own color; node size reflects degree + weight. - Theme — toggle dark/light with the
◐button. - Fit / Reheat —
Fitre-frames the graph (and resumes auto-framing);Reheatre-heats the simulation.
Responsive
The page is genuinely responsive: the<canvas> fills the whole window and re-frames on resize/maximize. Interactions use Pointer Events (mouse, trackpad and touch unified), and on narrow screens the layout reflows — the toolbar wraps, the search expands and the legend becomes a scrollable strip at the bottom. It works on desktop and on phone/tablet.
Availability
@graphview works on demand across all three modes:
- Agent / Coder — it joins the tool catalog automatically; the model invokes it when you ask for a visualization.
- Chat — chat is tool-less by design, so
@graphviewis a sanctioned exception (the third, alongsideask_userand read-only knowledge retrieval): when you ask for a graph, the model may call it once in that turn. It is gated byCHATCLI_CHAT_GRAPHVIEW(on by default) and flippable at runtime with/config chat graphview on|off.
Configuration
The per-call
open argument overrides CHATCLI_GRAPHVIEW_OPEN. Opening the browser is TTY-gated: running without a terminal (gateway/daemon or piped output) writes the file but does not open a window.
Output
The tool writes the.html (to output or a temp file), opens it in the browser when a terminal is present, and returns a summary:
Notes
- Read-only from the workspace’s point of view: the tool only visualizes data into a fresh HTML file and opens a viewer — it never mutates your files — so it asks for no security confirmation in the agent. It is not concurrency-safe (it writes a file and may open the browser), so it doesn’t join parallel batches.
- Truly self-contained: the physics engine is embedded JavaScript on a
<canvas>, no CDN, no network and no API key. The.htmlworks offline forever. - Node ceiling: the simulation is O(n²) per frame, so the graph is capped at a couple thousand nodes to keep dragging smooth; beyond that, reduce the set or render a sub-graph.