Skip to content

Repository files navigation

visual-reply

Make Claude Code answer in visuals instead of paragraphs.

A Claude Code plugin (skill + output style + renderer). Instead of a wall of text, Claude writes a small JSON cardwhat changed, what's next, which option, is it working, how it flows — and a shared renderer draws it inline in the chat, in a side-panel file, or in your browser. In the Claude Desktop app the cards are interactive: a "Choose ↗" or "Run the tests ↗" button sends that request as your next message.

/visual on            → this session answers in cards until you say /visual off
/visual what changed  → one visual answer, mode stays as it was
outputStyle: visual-first  (settings)  → every new session starts in visual mode

Why: a card is read in two or three seconds, in any language, in any lighting. A paragraph is not.

This is a recap card — the answer to "what did you just do?" — as the renderer draws it (it follows your light/dark theme):

A recap card titled 'Seeding fix'. Three metric tiles (Tests: 14 passed, Startup time: 2.1 s to 0.3 s, Migration: needed), four file rows with added/modified/deleted badges and plus/minus line counts, a warning strip saying to run the migration before deploying, and two action buttons: 'Show the diff of seed.py' and 'Run the tests again'.

The eight cards

type Answers Shows
recap what did you just do? files with added/modified/deleted badges and ±lines, key numbers, warnings
steps what's the plan, where are we? stepper with done / current / next / blocked, "Do this ↗" buttons
decision which option? 2–4 option cards with pros, cons, cost; the recommended one outlined; "Choose ↗"
status is it working? metric tiles + pass/fail/warn/skip/running rows
flow how does it work? flowchart or sequence diagram (mermaid), clickable nodes
compare before vs after, A vs B three-column table with better/worse marks
flags what are the risks? danger / warning / info rows with file:line and "Fix ↗"
tree where does X live? annotated folder tree with change badges

Every card can carry a compact flags strip and up to four actions buttons. Full field reference: skills/visual/references/spec.md. One complete example per type: skills/visual/templates/.

One work session, card by card

The eight templates tell one continuous story — a seeding fix, from plan to risks. The recap above was the first card; here are the other seven, each answering its own question.

steps — what's the plan, where are we?

A steps card titled 'Migration plan', showing five steps: two done with green check marks, 'Add the migration' marked in progress, 'Run the full test suite' pending, and 'Deploy to staging' blocked, needing approval. The three open steps have 'Do this' buttons and there is a 'Skip to tests' action.

decision — which option?

A decision card asking 'Where should the cache live?'. Three option cards side by side: In-process dict, Redis (outlined and labelled Recommended), and SQLite table — each with pros, cons and a cost line such as '3 files, 1 new service', and a 'Choose' button. An info strip explains only Redis is shared between the 4 workers in production.

status — is it working?

A status card titled 'Build health' with four metric tiles (Tests 41 of 42 with 1 failing, Build ok, Lint 0 errors, Coverage 87% up 2%) and five check rows: unit tests pass, integration tests fail on test_reseed_twice, type check passes, E2E skipped, deploy preview running. A danger strip explains the failing test and there are 'Show the failing test' and 'Fix it' buttons.

flow — how does it work?

A flow card titled 'What happens on startup' showing a flowchart: App starts, then a decision 'Marker row exists?' — yes goes straight to Serve requests, no goes through Run seed script and Write marker row first. A button offers the sequence-diagram version.

compare — before vs after?

A compare card titled 'Before vs after the seeding fix': a three-column table where After wins on seed runs (once per environment instead of every request) and startup time (0.3 s instead of 2.1 s), with a warning mark on 'Needs migration: yes'. A 'Show the full diff' button sits below.

flags — what are the risks?

A flags card titled 'Risks found in the review' with four severity rows: a danger row about a committed API key with a file and line reference and a Fix button, warning rows about an unbounded cache and a flaky test, and an info row about out-of-date docs. A 'Fix all warnings' button sits below.

tree — where does X live?

A tree card titled 'Where the seeding code lives': an annotated folder tree of src/ with db/seed.py marked modified ('guarded seed script'), db/markers.py marked added ('marker table helper'), app.py annotated 'calls seed on startup' and cache.py highlighted as 'unbounded dict'. Two files have Open buttons.

Render this whole gallery yourself, light and dark, with the command below.

See them all at once (opens in your browser, light and dark):

python skills/visual/scripts/render.py skills/visual/templates/*.json --open

Install

As a plugin (recommended — gets the skill, the output style and the hook together):

/plugin marketplace add omar1001/visual-reply
/plugin install visual-reply@visual-reply

As a plain skill (skill + scripts only, no output style): copy skills/visual/ to ~/.claude/skills/visual/.

For development: clone the repo and point a personal-skills entry at it — on Windows mklink /J "%USERPROFILE%\.claude\skills\visual-reply" "C:\path\to\visual-reply", on macOS/Linux ln -s /path/to/visual-reply ~/.claude/skills/visual-reply. Because the folder has .claude-plugin/plugin.json, Claude Code loads it as the plugin visual-reply@skills-dir. Run /reload-plugins after changing hooks or output styles.

Requirements: Python 3.8+ on PATH (scripts use only the standard library). The inline widget needs the Claude Desktop app; the terminal CLI gets the browser + text fallback. /visual graph additionally needs halal-graphify (uv tool install "halal-graphify[godot]").

Use

You type What happens
/visual or /visual on visual mode ON for this session. A tiny hook reminds Claude every turn; nothing else changes.
/visual off back to normal replies
/visual status · /visual history current mode · list of cards rendered to files (re-open any with render.py <path> --open)
/visual <anything> — e.g. /visual the plan, /visual options for caching one visual answer; mode unchanged
/visual graph · /visual graph open opens the project's code graph: refreshes it for free if the code moved on, then an index page linking the force graph, the folder tree and the call-flow diagrams (needs halal-graphify)
/visual graph map · area <path> · file <path> · node <name> · impact <name> · trace <a> <b> · flaws · stats the same graph answered as cards in the chat: the area map, what an area/file contains, a symbol's neighbours, what breaks if a symbol changes (ring by ring), the path from A to B, cycles/god-objects/orphans, graph health — one script, no LLM
"show me visually", "as a card", "draw the flow" Claude picks the skill by itself

Always on: put "outputStyle": "visual-first" in ~/.claude/settings.json (every project) or a project's .claude/settings.local.json. Takes effect in the next session. In the terminal, /config → Output style also lists it.

What a visual reply looks like

  1. One lead sentence with the result.
  2. One to three cards.
  3. A short text ## Summary — one bullet per card, plus ⚠️ FLAGS / ❓ NEEDS YOU / ➡️ NEXT.

The card part, exactly as the Claude Desktop app drew it inline in a real chat — this very card is the reply that closed this repo's own publish work, and clicking its button sent the next user message:

A recap card rendered inside the Claude Desktop chat widget, inside the app's rounded widget container: title 'Publish polish - visual-reply', three green metric tiles (Screenshots 11 saved, README +58 lines, Profile pinned), three file rows, a warning strip saying the repo changes are still local, and a 'Shoot it and push' action button.

The Summary stays on purpose: it is the searchable record, it keeps every number and risk even if a card drops it, and it survives a widget outage. Prefer visuals only? ~/.visual-reply/config.json{"summary": false}.

Small answers stay small: a yes/no or a single fact is a sentence, never a card.

Graph view — see the code's structure without the model drawing it

The force-graph page for a real project: 1,541 nodes in community colours clustered by module on a dark canvas, with a sidebar listing the communities (LinkSession, LevelMeter, JitterBuffer, AudioCaptureManager and more) with per-community node counts, checkbox filters and a node search box.

If the project has been indexed by halal-graphify (graphify-out/graph.json: files, classes, functions and the calls/imports/references between them), /visual graph open runs one script and no LLM:

  1. finds graphify-out/ from wherever you are in the project;
  2. checks whether the code moved on since the graph was built (deleted or modified indexed files, commits since the build, new files) and, if so, runs halal-graphify update . — local AST re-extraction, about 5–7 s on a 100-file project — printing how long it took (--no-update to skip, --force-update to accept a smaller graph);
  3. regenerates the folder tree and call-flow pages and writes graphify-out/INDEX.html: node/edge/file counts, build commit vs HEAD, links to every page, edges by relation, the ten most connected symbols;
  4. opens it — side panel in the Desktop app, default browser in the terminal (--open).

No graph yet? The script says so and prints the free build command (halal-graphify extract . --code-only).

The INDEX.html page for a project called bro mic: stat tiles for 1,541 nodes, 2,433 edges, 101 files, 115 communities and the build commit, then a Pages list linking the force graph, the collapsible tree, the call-flow diagrams and the plain-language report, with the not-yet-built Explorer greyed out.

Graph cards (/visual graph map|area|file|node|impact|trace|flaws|stats) turn the same graph into chat cards: impact ConnectionManager answers "what breaks if I change this" as a status row plus a ring-by-ring tree; flaws lists cycles (danger), overloaded hubs (warning) and orphan files (info); an ambiguous name becomes a decision card whose buttons re-run with the exact symbol picked. Oversized results are truncated to the card caps and say so, pointing at the full pages. Planned next: a zoomable explorer page — see docs/PLAN-graph-view.md.

How it works

Claude writes a JSON card  ──►  renderer draws it  ──►  where you are
   ~150–350 tokens             renderer/renderer.js      1. chat widget (Desktop)      interactive
                               loaded from jsDelivr,     2. side-panel HTML file        clipboard buttons
                               never re-emitted          3. browser (terminal CLI)      clipboard buttons
                                                         4. Unicode card in the reply   text
  • renderer/renderer.js — zero-dependency vanilla JS; draws all eight types; uses the host's CSS variables in the widget and its own light/dark palette standalone; sendPrompt() when the host provides it, clipboard otherwise.
  • skills/visual/scripts/render.py — validates a spec (precise error messages), writes a self-contained HTML page, prints the widget fragment, or prints a Unicode text card; logs specs for /visual history.
  • skills/visual/scripts/state.py + hook_reminder.py — per-session on/off state and the per-turn reminder.
  • skills/visual/scripts/graph_open.py/visual graph open: staleness check, free halal-graphify update, page regeneration, INDEX.html. Shells out to the halal-graphify CLI; never imports it, never calls an LLM.
  • skills/visual/SKILL.md — the protocol Claude follows: which card for what, the surface ladder, the reply format.
  • output-styles/visual-first.md — the same protocol as a system-prompt style for always-on use.

Cost, honestly

A card costs about the same output tokens as the paragraphs it replaces (the renderer is fetched from a CDN, not generated). The skill loads ~1.5k tokens once per session; the reminder hook is ~40 tokens per turn. Hand-drawn SVG diagrams cost 3–10× more, so the skill reserves them for one-off explanations.

Known limits

  • The inline widget exists in the Claude Desktop app only; the terminal gets the browser + text card.
  • Flow diagrams load mermaid from a CDN; offline they degrade to a numbered list.
  • Widget renders are not logged to ~/.visual-reply/log/ (only file/terminal renders are); the text Summary is the record.
  • Output style changes apply from the next session; /visual on|off is the mid-session switch.

Extend

Add a card type in three places: a branch in renderer.js (R.<type>), validation + text fallback in render.py, and a row in references/spec.md plus a template in templates/. Keep the design rules in references/style.md (flat, two weights, colour = meaning, CSS variables only).

Develop / test

python skills/visual/scripts/render.py --validate skills/visual/templates/*.json      # all specs valid
python skills/visual/scripts/render.py skills/visual/templates/*.json --open           # every card in the browser
python skills/visual/scripts/render.py skills/visual/templates/steps.json --format ansi # terminal card
python skills/visual/scripts/render.py skills/visual/templates/steps.json --format widget --inline  # widget fragment, renderer embedded
python skills/visual/scripts/graph_open.py <project> --no-update                        # graph index for an indexed project
claude plugin validate .                                                               # manifests

License

MIT — see LICENSE. Icons are from Tabler Icons (MIT). Flow diagrams use mermaid (MIT) at runtime.

About

Answer in visuals instead of paragraphs — a Claude Code plugin: JSON cards (recap, steps, decision, status, flow, compare, flags, tree) drawn inline in chat, in a side panel, or in the browser

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages