The @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.
For a deterministic diagram of architecture/dependencies as an image (PNG/SVG), use @diagram. To explore relationships interactively — map the conversation, concepts, files, topics — and be able to drag and focus, use @graphview.
Usage
<tool_call name="@graphview" args='{"title":"Our chat","nodes":[{"id":"cli","label":"ChatCLI","kind":"project"},{"id":"oauth","label":"OAuth login","kind":"topic"},{"id":"token","label":"Token exchange","kind":"topic"}],"edges":[{"source":"cli","target":"oauth"},{"source":"oauth","target":"token","weight":2}]}' />
<tool_call name="@graphview" args='{"source":"knowledge"}' />
<tool_call name="@graphview" args='{"source":"conversation"}' />
In practice you don’t write this by hand: just ask in natural language — “draw an interactive graph of what we discussed” — and the model builds the nodes and edges and calls @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:
| Source | What it renders |
|---|
json (default) | The nodes/edges you (the model) supply in nodes/edges. This is how “map the conversation” works: the model already has the context and emits the semantic graph. It also accepts a JSON file via file. |
knowledge | The in-core knowledge graph (memory, skills, topics, projects, tags) — the same substrate as the /graph command, but interactive. |
conversation | Everything in the current session in one graph: the conversation thread (turns by role) + the tools it invoked + every context attached with /context (including its files) + the attached knowledge bases — all hanging off a session root node. |
Want a thematic/semantic graph of what was discussed? Let the model extract the entities and relations and pass them as nodes/edges (source=json). Want a structural graph of what’s in the session and attached? Use source=conversation.
Arguments
| Argument | Description | Default |
|---|
source | json | knowledge | conversation | json |
nodes | source=json: array of {id, label, kind?, summary?, weight?}. kind drives the node color (e.g. topic, project, file, person, entity). | (json) |
edges | source=json: array of {source, target, weight?} between node ids. weight thickens the edge. | (json) |
file | Path to a JSON file {"nodes":[...],"edges":[...]} — for large graphs, instead of inline. | — |
title | Title shown in the toolbar. | (“Graph”) |
theme | dark | light | dark |
output | Path of the .html to write. Omitted, writes a temp file and returns the path. | (temp) |
open | Open the result in the default browser. | true |
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 —
Fit re-frames the graph (and resumes auto-framing); Reheat re-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
@graphview is a sanctioned exception (the third, alongside ask_user and read-only knowledge retrieval): when you ask for a graph, the model may call it once in that turn. It is gated by CHATCLI_CHAT_GRAPHVIEW (on by default) and flippable at runtime with /config chat graphview on|off.
Configuration
/config graphview # panorama: theme, auto-open and the chat exception
/config chat graphview on|off # enable/disable graph rendering in chat
Environment variables (process-wide; read on every call/turn):
| Variable | Values | Default | Effect |
|---|
CHATCLI_GRAPHVIEW_THEME | dark | light | dark | Default graph theme. |
CHATCLI_GRAPHVIEW_OPEN | true | false | true | Whether to open the HTML in the browser after rendering. |
CHATCLI_CHAT_GRAPHVIEW | true | false | true | Enables the @graphview exception in chat. |
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:
Interactive graph rendered → /tmp/chatcli-graph-1234.html (12 nodes, 18 edges)
Opened in your default browser. Drag nodes, scroll to zoom, drag the background to pan, click a type in the legend to filter.
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 .html works 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.
Combine it with @context/@knowledge: attach a project knowledge base and ask for source=conversation — the graph shows the conversation, the tools used and the attached base with its files in one place. For a static architecture diagram, use @diagram.