| name | amvcp-show |
| description | Smart router for the AI Maestro Visual Communicator plugin. Use when the user wants to view, comment on, or interact with ANY input (file path, URL, plain text, or skill+args) — the router classifies by extension + content sniff and dispatches to the right sub-skill. Always uses iTerm split-pane when detected. Preserves markdown reports verbatim (routes to /amvcp-interactive-report). Trigger with /amvcp-show, 'show this', 'visualize this report', 'open this in the viewer', 'route this'. |
| license | MIT |
| compatibility | macOS + iTerm2 for split-pane; Python 3.12+; Chromium fallback when iTerm not detected. |
| metadata | {"author":"Emasoft"} |
amvcp-show — Smart Router
Overview
One entry point for any content the user wants to view or comment on. The router classifies the input (markdown, HTML, code, image, CSV/JSON, Mermaid, regex, LaTeX, diff, slides, plain text, URL, or explicit skill+args form), dispatches to the right sub-skill or command, always uses iTerm split-pane when iTerm is detected, and always preserves source content verbatim for markdown reports — no reinterpretation, no cherry-picking.
Prerequisites
- Python 3.12+
- iTerm2 on macOS for the split-pane preview (Chromium fallback otherwise)
- The plugin's runtime + renderer scripts (
scripts/amvcp-show-launcher.py, scripts/render-interactive-report.py) co-located in the plugin root
Instructions
- Run
python3 $CLAUDE_PLUGIN_ROOT/skills/amvcp-show/scripts/dispatch.py <input> with the user's argument as a single string.
- Parse the JSON action plan printed to stdout.
- Follow the
action field per the contract in "Output" below.
The dispatcher handles the markdown and HTML paths itself (renders + launches via the iTerm-first launcher). For every other content type it returns a structured invoke_skill / invoke_command instruction telling the orchestrator which slash command to invoke next.
Routing matrix
| Input shape | Detection cue | Routes to | Why |
|---|
.md / .markdown | extension + slides-marker check | /amvcp-interactive-report | Preserves every word; adds per-finding 3-state + textarea |
.html / .htm | extension | iTerm launcher directly | Already a rendered page |
.py / .ts / .js / .go / .rs / .java / .cpp / .sh / .yaml / etc. | code extension | amvcp-prose-pages (data-ve-code blocks) | Syntax highlight + line-level commenting |
.svg / .png / .jpg / .webp / .gif | image extension | amvcp-prose-pages (image wrapper + hotspot) | Visual annotation |
.csv / .tsv / .json array-of-objects | extension + JSON sniff (top-level [) | amvcp-charts-and-dashboards | Auto-chart appropriate type |
.json non-array | extension + JSON sniff | amvcp-prose-pages (pretty-printed JSON block) | Read-only inspection |
.diff / .patch | extension | /amvcp-diff-review | Side-by-side diff |
.mmd or content graph TD, sequenceDiagram, flowchart | extension OR first non-blank line | amvcp-graph-diagrams | Diagram render |
.tex or content documentclass, begin{...} | extension OR LaTeX markers | amvcp-math-and-latex | KaTeX/TikZ |
.md with two or more --- separators | own-line --- count >= 2 | /amvcp-generate-slides | Slide deck |
Single-line /.../flags regex | content sniff | amvcp-regex-vis | Visualizer |
URL (http(s)://...) | starts with http | /amvcp-fact-check (fetch + inspect) | Treat as remote file |
| Plain text idea (not a path) | not a filesystem path | amvcp-visual-communication (coordinator) | Author from scratch |
amvcp-<skill> pipe-separated <args> two-token form | starts with amvcp- + contains a pipe | call that sub-skill directly | Power-user escape hatch |
When no rule matches a file's content the router defaults to treating it as code (the safest "preserve verbatim + add commenting" path).
Output
The dispatcher writes ONE JSON object to stdout. Five action shapes are possible:
action: "rendered" — Markdown was rendered to HTML and the iTerm launcher returned the user's submission payload. The user already saw the page and clicked Submit (or Exit / timed out). The payload.selections[] array contains finding-reply entries with findingId, text, and decision (skip / approve / reject). Process each entry: re-read the original finding from the source markdown, take decision + text, and write a per-finding response into <report>.replies.json.
action: "passthrough" — An HTML file was opened directly via the launcher; payload carries the launcher's stdout (same shape as rendered, kind html).
action: "invoke_command" — A slash command should be invoked, e.g. {"command": "amvcp-diff-review", "args": ["/path/to/file.diff"]}. The downstream command handles its own rendering + launching.
action: "invoke_skill" — A skill should be activated, e.g. {"skill": "amvcp-charts-and-dashboards", "args": ["/path/to/data.csv"]}. After authoring, always launch the resulting HTML via scripts/amvcp-show-launcher.py (NOT amvcp-select.py directly) so the iTerm split-pane fires when iTerm is present.
action: "explicit_skill" — The user used the power-user pipe-separated form. Same handling as invoke_skill.
action: "error" — Classification or rendering failed; surface reason to the user and ask for clarification.
Error Handling
- Input not found on disk and not a URL or plain text —
{"action": "error", "reason": "file not found"}. Ask the user to confirm the path.
render-interactive-report.py exits non-zero — {"action": "error", "reason": "..."} with the script's stderr trimmed to 400 chars. Most common cause: invalid markdown syntax.
amvcp-show-launcher.py fails to find the plugin scripts — the launcher resolves the plugin root via $CLAUDE_PLUGIN_ROOT, then the repo checkout, then ~/.claude/plugins/cache/...; if all three miss it raises FileNotFoundError and the launcher reports the missing path.
- iTerm AppleScript fails — the page is still being served on localhost; the launcher prints the URL and the user can open it manually.
Examples
Markdown report (most common case):
/amvcp-show /path/to/audit-report.md
Renders + opens in iTerm split-pane; user clicks Submit; payload returns inline with per-finding decisions and textarea replies.
HTML page already rendered:
/amvcp-show /path/to/page.html
Opens directly in iTerm split-pane.
CSV that should become a chart:
/amvcp-show /path/to/sales.csv
Returns {"action":"invoke_skill","skill":"amvcp-charts-and-dashboards","args":["/path/to/sales.csv"]}. Orchestrator follows the chart skill's authoring workflow.
Plain text idea:
/amvcp-show "draw a flowchart of the deployment process"
Returns {"action":"invoke_skill","skill":"amvcp-visual-communication","args":["draw a flowchart..."]}. Coordinator picks a representation.
Power-user form — bypass classification:
/amvcp-show "amvcp-graph-diagrams|sequenceDiagram: client -> server -> db"
Returns {"action":"explicit_skill","skill":"amvcp-graph-diagrams","args":["sequenceDiagram: ..."]}.
Resources
- dispatch.py — classifier + action-plan emitter (13 input shapes recognised)
Companion plugin scripts (resolved at runtime via $CLAUDE_PLUGIN_ROOT):
scripts/amvcp-show-launcher.py — iTerm-first wrapper around amvcp-select.py; owns iTerm detection (without isatty) and the AppleScript split-pane dispatch
scripts/render-interactive-report.py — markdown to interactive HTML with per-finding 3-state controls
scripts/amvcp-runtime.js — owns R29 selection visuals, decision-state Map, per-finding-reply enrichment of submit payload
Sibling skills the router dispatches to (loaded via the plugin's skill index — not direct file links from here per CPV self-containment rule):
amvcp-interactive-report — for .md inputs
amvcp-prose-pages — for code and image inputs
amvcp-charts-and-dashboards — for tabular data
amvcp-graph-diagrams — for Mermaid sources
amvcp-regex-vis — for regex sources
amvcp-math-and-latex — for LaTeX sources
amvcp-visual-communication — coordinator for plain text
Six contracts the router upholds
These contracts (per TRDD-4c300620) are non-negotiable:
- Content preservation — markdown reports round-trip every paragraph, list, table, and code block from the source verbatim. Augmentation permitted; reinterpretation not.
- Hover glow — the runtime's R29 selection visual is owned exclusively by
amvcp-runtime.js. Page-CSS :hover rules on selectable atoms violate that contract and have been stripped.
- Corner buttons visible — the four corner buttons use DESIGN.md surface tokens (not hardcoded white) plus strong shadow + backdrop-filter blur so they always read against the page background.
- iTerm split-pane — when
$TERM_PROGRAM=iTerm.app, the router invokes amvcp-show-launcher.py which sets VE_SELECT_NO_BROWSER=1 VE_SELECT_NO_ITERM=1 on amvcp-select.py and triggers open_preview.applescript directly. Never spawns Safari / Chromium when iTerm is detected.
- Polished theme — the
product-dashboard preset uses IBM Plex Sans + warm-cream canvas + navy accent.
- Per-finding 3-state — every
## Finding heading in the rendered page carries a fieldset.ve-decision with three segments (Skip / Approve / Reject); the submit payload's selections[i].decision carries the current decision alongside the reply text.
Out of scope
- Authoring new sub-skills (the router only calls existing ones).
- Replacing
amvcp-select.py (the iTerm-first launcher wraps it).
- Multi-round response loop for
amvcp-interactive-report (the responder is /amvcp-respond-to-comment; the router only fires the first round).
Modes
Not applicable in the runtime sense — amvcp-show does not emit DOM, so it has no data-ve-mode host. It is a dispatch skill: it classifies an input and either renders + launches it directly (markdown / HTML paths) or returns a JSON instruction telling the orchestrator which downstream skill to invoke. The downstream skills (amvcp-interactive-report, amvcp-prose-pages, amvcp-charts-and-dashboards, etc.) own their own data-ve-mode declarations per R23.
Composability
Compatible with every visual-communicator sub-skill — by design. The router's job is to compose them, not interfere with them. It never mutates a rendered page, never overrides a sub-skill's runtime initialisation, and never assigns data-ve-id values itself (per R22). When dispatching to a downstream skill the router passes the input verbatim and stays out of the way.
Specific composability guarantees:
- Does NOT race any other skill on
data-ve-id namespaces — emits no DOM.
- Does NOT mount any runtime —
amvcp-runtime.js is loaded only by the rendered HTML the downstream skill emits.
- Always invokes the iTerm-first launcher (
scripts/amvcp-show-launcher.py) so the iTerm split-pane / Chromium fallback decision is made in exactly one place, regardless of which downstream skill rendered the HTML (per R33 corner buttons always present + the launcher's iTerm contract).
- Compatible with
/amvcp-respond-to-comment for the multi-round response loop on markdown reports — the router only fires round 1; the responder picks up subsequent rounds.