ai-visual-recap
SkillFiles & storageTurn a PR, branch, commit, or git diff into an interactive visual recap with diagrams, file maps, API/schema summaries, annotated diffs, and focused review notes. Trigger for "recap this PR", "summarize the change for review", "show me what this branch changed". In ai-engineering it runs when CLOSING a milestone (step 12), not on demand; the artifact lives at .ai-engineering/recap.html. Not for judging whether the work is any good — use /ai-verify.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the ai-visual-recap skill
What this skill tells your AI
The instructions your AI receives, as published by arcasilesgroup/ai-engineering in skills/ai-visual-recap/SKILL.md and read by ahel’s review.
ai-visual-recap creates a visual plan built from a diff, not toward one. It
is the reverse of forward planning: instead of describing the change you are
about to make, you describe the change that was just made, at a higher altitude
than line-by-line review. The same plan data model serves both directions —
schema, API, file, and architecture changes become the same data-model,
api-endpoint, file-tree, and diagram blocks a forward plan would use, only
now they summarize work that exists. A reviewer scans the shape of the change
before spending attention on the literal lines.
Publish As An Agent-Native Plan — Never Inline
The deliverable is ALWAYS a published Agent-Native Plan, created with
create-visual-recap on the Plan MCP connector — NEVER inline chat content (not
Markdown prose, an ASCII sketch, a table, a fenced "wireframe", or a "here's the
recap" summary). A recap's entire value is the hosted, interactive, annotatable
plan; an inline summary is not a degraded recap, it is the thing a recap
replaces. If the plan (or legacy agent-native-plans) tools are not visible,
discover them through the host's tool_search first; if they are still missing,
STOP and give the user the client-specific reconnect step rather than improvising
an inline recap. Before publishing, or whenever a connector or auth error
appears, READ references/connection.md in this skill directory — it is the
single source of truth for the never-inline rule, connector discovery, and the
per-client reconnect steps. Local-files privacy mode (below) is the one
exception.
Local-Files Privacy Mode — read references/local-files.md
When the user wants no hosted Plan database writes — no DB writes, no Plan MCP
publish, fully local/offline/private recaps, or AGENT_NATIVE_PLANS_MODE=local-files
— do not call any hosted Plan tool except the schema-only get-plan-blocks
catalog lookup. Read the diff with the local recap collect-diff / scan /
build-prompt --local-files helpers, author a local MDX folder (set
kind: "recap" and localOnly: true), and preview it with plan local check,
plan local serve --kind recap, and plan local verify --kind recap. Before
using local-files mode, READ references/local-files.md in this skill directory
— it is the single source of truth for the full contract.
When To Use
Build a recap when a PR or commit is large, multi-file, or touches schema, API contracts, or architecture, and a reviewer would benefit from seeing the change mapped to structured blocks before reading the raw diff. A GitHub Action can generate one automatically from a PR diff; an agent can generate one on request ("recap this PR", "show me what this branch changed"). Skip it for small, single-file, or obvious diffs — a recap is review overhead, and a tiny change reviews faster as plain diff.
Recap The Whole Work Unit
When ai-visual-recap is invoked in a chat thread after work has already happened, the default scope is the whole current work unit/thread, not only the most recent user message, tool action, or follow-up fix. Gather the thread-owned changes across the conversation: original implementation work, later bug fixes, UI follow-ups, tests, changesets, skill/instruction updates, generated plan/source artifacts, and any local import/linking fixes needed to make the recap open.
Use the current diff plus conversation context to separate thread-owned changes from unrelated dirty work that existed before the thread. Exclude unrelated pre-existing edits. If the scope is genuinely ambiguous and cannot be inferred, state the assumption or ask a concise question before publishing.
When updating an existing recap after feedback, revise the recap so it still covers the whole thread/work unit plus the new correction. Do not replace a broad recap with a narrow recap of only the latest feedback unless the user explicitly asks for that narrower scope.
Keep The Recap Body Lean
Do not add boilerplate intro, disclaimer, provenance, or summary prose blocks to
the generated plan body. In particular, do not create a rich-text block just to
say the recap is an aid, that the reviewer should still review the diff, how many
files changed, or which ref/working tree generated the recap. The plan title,
brief, and file-tree (which carries the per-file change stats) already carry
that context.
Only add prose blocks when they tell the reviewer something specific about the change that the structured blocks do not: the objective, a real compatibility risk, an important decision visible in the diff, or a grounded review note.
Recaps Must Be Substantial
Lean is not the same as thin. A recap is not a single wireframe plus one
sentence — that under-serves the reviewer as much as boilerplate prose over-serves
them. Alongside the visual/structural headline (wireframes, data-model,
api-endpoint, diagram), a substantial recap also carries the implementation
evidence:
- A short surface/state inventory before authoring: list the changed routes, components, popovers/dialogs, role/access states, empty/error states, and shared abstractions visible in the diff. The final recap must either represent each meaningful item with a block or intentionally omit it because it is tiny, redundant, or not user-visible.
- A
file-treeof the changed files with each entry'schangeflag, so the reviewer sees the footprint of the work at a glance. - The split
diffof the KEY changed files, grouped under a## Key changesrich-textheading in a single horizontaltabsblock (the default orientation, one file per tab), with a one-linesummaryand a fewannotationson each — so the reviewer can drop from the high-altitude shape straight into the load-bearing code. Use horizontal file tabs, not a vertical side rail, so the selected file has enough width for the side-by-side diff.
Skip the diff appendix only for a genuinely tiny change that reviews faster as plain diff (see "When To Use"); for any change worth recapping, the file-tree and key-change diffs belong in the plan.
Canonical Shape And Budgets
A strong recap follows one skeleton, top to bottom:
- UI-impact headline — wireframes first, when the diff changed rendered UI.
- Short outcome narrative (
rich-text): what changed and why, 1-3 paragraphs. data-model/api-endpointblocks for schema and contract changes.file-treeof the changed files withchangeflags.## Key changes— one horizontaltabsblock ofdiff/annotated-code, each excerpt carrying its language and coloured (see Code Is Colour, Never A Grey Block).
Budgets that keep the recap reviewable:
- 3-8 key-change tabs. Fewer than 3 on a large change under-serves the reviewer; more than 8 stops being a summary.
- Keep each diff/annotated-code excerpt focused — prefer under ~150 lines per tab; summarize or link the rest of a long file instead of dumping it.
- Title at most ~70 characters; brief 1-3 sentences.
These budgets are also the cost ceiling: do not exceed them in the name of thoroughness, and do not re-read the full diff after the initial sequential pass — work from the notes taken during that pass.
GOOD. A 25-file auth change: Before/After wireframes of the login surface,
a two-paragraph narrative, a diff-aware data-model of the sessions table, an
api-endpoint for the new refresh route, a file-tree with change flags, and
## Key changes with five focused tabs, each with a one-line summary and a
few annotations on the load-bearing hunks.
BAD. One giant unsegmented diff dump with no summaries or annotations; or a sparse three-block recap of a 40-file change (one wireframe, one sentence, one file list) that forces the reviewer back into the raw diff anyway.
Code Is Colour, Never A Grey Block
A reader skims a recap for the three lines that carry the change. A wall of grey monospace makes them find those three lines by reading everything, which is the one thing this artifact exists to spare them.
The cause is almost always a missing language. Code, AnnotatedCode, Diff,
each tabs child and every FileTree snippet accept a language prop, and a block
without one renders unhighlighted — the class the reader sees as no-highlight. The
schema read on 2026-09-11 (plan blocks --format schema, 20 blocks) lists language
as optional on all of them, so nothing forces you to pass it. Pass it on every excerpt
that is code:
<AnnotatedCode language="ts" filename="src/spec/index.ts" … />
<Diff language="ts" filename="src/commands/doctor.ts" mode="split" … />
Then, in order of how often each one is the actual problem:
-
No
languagemeans the content is text on purpose. A directory tree, a terminal transcript, a command's plain output — those read better monochrome and should say so. Everything else gets a language. -
Long excerpts collapse, they are not cut.
CodetakesmaxLines; use it instead of truncating by hand, so the reader can expand what they want. -
code-tabsis deprecated: use atabsblock withcodechildren, one per file. -
When the artifact is a self-contained HTML file instead of MDX — no renderer available — colour it yourself, with the highlighter bundled beside this skill:
bun assets/highlight.mjs --lang ts excerpt.ts # paste the HTML it printsGenerate the spans; never hand-annotate them. A missed string or a comment that swallows the next line is how a recap starts lying about its own code.
-
One token vocabulary across the whole family:
ccomment ·kkeyword ·sstring ·nnumber ·ttype ·fcall ·bstrong. These are the blueprint's own token classes (§22's stylesheet), so a recap and the design document read as one thing. -
The CSS travels with the artifact, so it renders identically in a browser, in a plan viewer and in a PDF export:
pre { background:#0E1830; border:1px solid rgba(0,212,170,.15); border-radius:10px; padding:14px 16px; overflow-x:auto; font-family:'SF Mono',ui-monospace,monospace; font-size:12.5px; line-height:1.65; color:#A9BBD0; } pre .c { color:#6b87a6 } pre .k { color:#00D4AA } pre .s { color:#22c55e } pre .n { color:#f97316 } pre .t { color:#a855f7 } pre .f { color:#7dd3fc } pre .b { color:#F8FAFB; font-weight:600 } -
Do not colour twice. If the renderer colours the block from
language, do not also pre-render spans into it: two colouring paths disagree the first time one changes, and the reader is the one who sees it.
UI Impact Needs Wireframes
When the diff changes rendered UI, layout, density, visual state, interaction affordances, navigation, controls, menus, dialogs, or design tokens, the recap MUST include one or more wireframes. Prose and file diffs are not a substitute for showing what changed visually.
Before choosing wireframes, make a UI coverage pass from the diff:
- Identify the entry surface where the change appears, such as a page header, list row, toolbar, route shell, or menu trigger.
- Identify the interaction surface that opens or changes, such as a popover, dialog, tab, sheet, dropdown, inline editor, or toast.
- Identify the resulting destination or persistent state, such as a public page, read-only view, empty state, error state, loading state, permission-denied state, or saved/shared state.
- Identify access or role variants when permissions change. Owner/admin/editor versus viewer/non-manager differences are visual behavior and need a compact matrix, paired wireframes, or clearly labeled state sequence.
For UI-heavy PRs, a single before/after of the entry surface is not enough. Show the changed entry point, the main changed interaction surface, and the resulting/destination state. Add more states when the diff adds tabs, role-based controls, public/private visibility, invite/manage flows, destructive controls, or empty/error branches.
Choose the smallest visual surface that makes the review clear:
- Use a
Before/Afterwireframe pair when the reviewer benefits from direct comparison, such as a removed or added control, a changed state, layout density, ordering, navigation, or a visible component replacement.references/wireframe.mdowns how to lay that pair out (columns vs. vertical stack by geometry). - Use an after-only wireframe when the change is purely additive or the "before" state would only show absence without adding review value.
- Use more than two wireframes when the UI change is flow-dependent, responsive, or stateful; show the meaningful states in order instead of forcing a single before/after pair.
- For tiny surfaces like menus, popovers, dialogs, toasts, or panels, use the
matching
surface(popover,panel, etc.) and show the focused sub-surface. Do not redraw a full page unless placement in the page is itself part of the change.
Ground each wireframe in the changed UI behavior, component names, file paths, and diff-visible labels/states. If exact pixels are inferred rather than captured, say so in the wireframe caption or a concise annotation. For local/manual recaps, import or update the plan source that holds the wireframes so the rendered recap opens with the UI visual available.
Wireframe Quality — read references/wireframe.md
UI recap/plan wireframes must meet a strict quality bar — full-width chrome,
pinned bottom bars, real product content, before/after comparability, the right
surface preset, --wf-* tokens instead of hex, and no <html>/<style>/font
tags. Before authoring ANY wireframe / <Screen> / WireframeBlock, READ
references/wireframe.md in this skill directory — it is the single source of
truth for HTML wireframe quality, shared word for word with the upstream
/visual-plan skill and with ai-visual-recap. Do not author wireframes from memory.
Use the standard WireframeBlock / <Screen> format so the Plan viewer owns the
surface frame, theme, and sketchy/clean toggle. HTML wireframes are appropriate
when placement precision matters, especially popovers, menus, dialogs, and dense
forms. For HTML
wireframes, keep renderMode unset or wireframe unless a design-only editable
mockup is explicitly required, because renderMode="design" disables the
sketchy rough overlay.
When a browser tool is available, render a UI-impact recap in the Plan viewer and visually inspect it at the current theme before sharing. If any label, annotation, toolbar, or wireframe content overlaps another element, fix the MDX and re-import before reporting the link. Limit this to one render-and-inspect pass plus at most one fix-and-re-render; do not keep iterating beyond that unless the user explicitly asks. A text-match screenshot is not enough; visually inspect the captured image. When no browser is available (for example a headless CI agent), state that in the recap handoff instead.
Top Canvas Recaps
When a recap includes a top canvas, storyboard, or flow view, apply the same
HTML wireframe rules as the document body (references/wireframe.md in this
skill directory) before authoring canvas.mdx. Recap
canvas artboards must use the same HTML wireframe path as good document-body
wireframes: <Screen surface="..." html={...} /> with a semantic HTML fragment.
Do not author fresh kit-tree children such as <FrameScreen>, <Card>,
<Row>, <Title>, or <Btn> inside canvas <Screen> tags. Those components
are legacy compatibility markup for old plans; in new canvas storyboards they
can produce cramped or overlapping layouts even when the inline body wireframe
looks good. If a canvas mockup looks worse than the same screen below the fold,
assume it used the legacy kit path and replace it with an HTML screen.
Open And Report The Recap
In local-files privacy mode, run plan local check first, then report the local
bridge URL from
npx @agent-native/core@latest plan local serve --dir <plan-dir> --kind recap --open
or from <plan-dir>/.plan-url. It opens the hosted Plan UI but reads from the
localhost bridge on this machine, so it is not shareable across machines. If the
Plan app itself is running locally with the same PLAN_LOCAL_DIR, the
/local-plans/<slug> route is also valid. Do not invent a hosted database URL
and do not publish just to get an absolute Plan link.
After creating the recap, link the reviewer to the rendered plan with an
absolute URL on the origin whose database actually holds the plan. That
origin is the Plan MCP server you just created the recap through — NOT whatever
dev server you happen to know is running. The create tool returns the correct
link; report THAT. Never make the primary link a local plan.mdx file, a local
mirror folder, or a relative path such as /plans/<id>.
When the recap is posted to a PR for a private repo, the plan link is not a public URL. Make the PR comment/handoff copy explicit: reviewers may need to sign in to Agent-Native Plans with an account that has access to the owning organization before the link loads. Use wording like: "Private repo recap: sign in with access to this org if the plan does not open." Do not imply the link is broken or public when access is gated by repo/org visibility.
A recap lives only in the database of the MCP that created it. A separately
running local dev server (e.g. http://localhost:8081) has its OWN database and
will NOT contain a recap created through the hosted MCP, so a hand-built
localhost link returns "Plan not found". This is the most common recap
mistake — do not guess an origin you have not confirmed shares the MCP's data.
Resolve the URL in this order:
- Use the absolute URL the create tool RETURNS —
openLink.webUrl, else thevisualUrlin the returnedplan.mdxfrontmatter, elseurl/pathresolved against the MCP server's own origin (for the hosted MCP that ishttps://plan.agent-native.com). This always points at the database that has the plan. - Use a
localhost/dev origin ONLY when the recap was created through a Plan MCP bound to that same origin — i.e. that MCP's url ishttp://localhost:<port>/mcp. Creating through the hosted MCP and linking to localhost is the exact mismatch that 404s. - If only a plan id is available, build the MCP origin's absolute URL
(hosted:
https://plan.agent-native.com/plans/<id>) and say it was inferred.
If the user wants to review on localhost but the recap was created through the
hosted MCP, say so plainly: the local dev server cannot see it. To view a recap
on localhost (e.g. to exercise un-deployed local renderer changes), they must
connect a LOCAL Plan MCP (http://localhost:<port>/mcp) and
re-create the recap through it so it lands in the local database; offer to do
that rather than handing over a localhost URL that will not resolve.
When running in Codex and the Browser/in-app side browser tools are available,
open the returned absolute recap URL there automatically after creation. Still
include the same absolute URL in the final response. Local mirror files like
plans/<slug>/plan.mdx may be mentioned only as secondary source-control
artifacts, not as the main way to open the recap.
Diff → Block Mapping
Map each kind of change to the block that carries it, derived mechanically from
the actual diff. The names below are the CONCEPTUAL block types, not the JSX
tags — resolve every conceptual name to its exact tag + prop schema with the
get-plan-blocks tool (see "Block reference" below) before authoring.
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 55
- Forks
- 3
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
ai-visual-recap- Source
- github.com/arcasilesgroup/ai-engineering