> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Interactive graph (@graphview)

> Renders an interactive, Obsidian-style force-directed graph — draggable, with physics — to a self-contained HTML file opened in the browser. Unlike @diagram (a static image), the result stays alive: you drag the nodes, zoom, filter by type and click to focus. The physics engine is embedded JavaScript, no CDN, no network and no API key.

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`](/en/features/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.

<Tip>
  For a **deterministic diagram** of architecture/dependencies as an **image** (PNG/SVG), use [`@diagram`](/en/features/diagram). To **explore relationships interactively** — map the conversation, concepts, files, topics — and be able to **drag and focus**, use `@graphview`.
</Tip>

***

## Usage

```text theme={"system"}
<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](#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`](/en/features/knowledge-base) 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. |

<Tip>
  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`.
</Tip>

***

## 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

```text theme={"system"}
/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:

```text theme={"system"}
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.

<Tip>
  Combine it with [`@context`/`@knowledge`](/en/features/knowledge-base): 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`](/en/features/diagram).
</Tip>
