How it works
Deltaview has two halves. The skill is instructions Claude follows: resolve the ref, check it out, install, test, analyse the diff and anchor overlays in Chrome. The toolkit is a small Node CLI with no dependencies that parses the diff, validates the manifest, runs the proxy and posts the review. Deterministic work lives in the toolkit, so the review posts even if the Claude session is gone.
Items and tiers
Claude reads the full diff and the code around it, then groups hunks into items. Every hunk belongs to exactly one item; the toolkit refuses the item list until that holds. One file can be split across items when its hunks belong to different features.
Direct
The changed code renders something: a component, template, markup or styles. The overlay sits on that element.
Indirect
The changed code is non-visual (API handler, hook, service, util, store) but something on screen triggers it. Claude traces the chain from the trigger to the change by grepping callers, reading imports and using framework knowledge, then pins the overlay to the trigger. The overlay shows the chain as a breadcrumb, and the diff lists the item's hunks in chain order:
Save button › useSaveOrder() › POST /api/orders › orders.handler.tsBackstage
No path to the UI: migrations, CI, config, build files, docs, lockfiles, or UI that can't be anchored. These go to the Backstage drawer with the same diff, summary and decision controls, tagged not visually verified. UI that needs a manual interaction gets a howToReach note, e.g. “Open Settings, click Billing, then Edit”.
Grouping rules
- Test hunks attach to the item for the code they test, not to an item of their own.
- Shared code used by many elements is pinned to one representative element; the others are listed under Affects. When the instances on that page share a stable selector, it may match them all: the first is the anchor and the rest get dim outlines.
- Code with no UI path that nothing calls is flagged appears unused, checked with a grep across the worktree first. Dead code is a common smell in agent-written PRs.
- Each item gets a plain-language summary of what changed, its effect and any risks noticed.
Anchoring
With your dev server running, Claude opens a new Chrome tab, navigates to each item's route and finds its element. It checks that the selector matches exactly one element (or, for shared code, exactly the instances of the changed component) with a read-only document.querySelectorAll(selector).length. Selector preference:
data-testid,data-testordata-cy- An id
- ARIA and stable attributes:
[aria-label=…],a[href=…],button[name=…] - A short structural selector from stable attributes. Never nth-child or generated class names.
Anything that only appears after an interaction (a modal, a closed tab, a later form step) becomes a Backstage item with a howToReach note. The agent never clicks to get there.
The proxy
deltaview serve runs a plain Node HTTP server in front of your dev server, e.g. localhost:4500 → localhost:3000. HTTPS dev servers work too; self-signed certificates (mkcert, Vite's basic SSL) are accepted on loopback only. It:
- injects
<script type="module" src="/__deltaview/overlay.mjs">into every HTML response, and drops its CSP andX-Frame-Optionsheaders so the script can load and the page can be framed for the mobile and before/after views; - passes WebSocket upgrades through, so hot module reload keeps working;
- rewrites redirects and the Origin and Referer headers between the proxy and dev server origins;
- listens on the dev server's hostname (loopback only), so cookies, which are scoped per host and not per port, carry over and you stay logged in;
- serves the manifest and accepts decisions under
/__deltaview/. POSTs must beapplication/jsonand same-origin, which blocks cross-site requests.
The overlay lives in a Shadow DOM so its styles and your app's don't touch. Keystrokes inside it don't reach your app's hotkeys, and outlines re-attach when the DOM changes or an SPA navigates.
For the before/after view, a second proxy in the same process fronts the base version's dev server. It draws the same outlines but is read-only: it refuses decisions and Finish.
