Agent skill

Visual View Diff

by rajbos in rajbos/ai-engineering-fluency

Render the VS Code extension's webview panels headlessly and detect which ones changed visually, producing before/after/diff screenshots for review.

MITAuto-check passedDevelopment

Install Visual View Diff

skills CLI
$ npx skills add rajbos/ai-engineering-fluency --skill visual-view-diff -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install rajbos/ai-engineering-fluency visual-view-diff --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/rajbos/ai-engineering-fluency.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/visual-view-diff .claude/skills/visual-view-diff && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
visual-view-diff
GitHub stars
115
Token cost
~3.1k tokens
SKILL.md length
1,636 words
Files
1
Skills in repo
22
Repo updated
First seen
Licence
MIT

At a glance

Render the VS Code extension's webview panels headlessly and detect which ones changed visually, producing before/after/diff screenshots for review.

  • Works in 4 steps: Find the view's HTML shell in… → Add an entry to views.config.json — id,… → Write fixtures/.json with that payload. → …
  • A change touches webview UI (src/webview/
  • SKILL.md covers When to use it, Why this exists (and why it…, Usage and Reading the result, plus 4 more sections
  • Calls node, npm and gh

What it does

Visual View Diff is an agent skill from rajbos/ai-engineering-fluency. Render the VS Code extension's webview panels headlessly and detect which ones changed visually, producing before/after/diff screenshots for review. Use when a change touches webview UI (src/webview/, view HTML in extension.ts, shared CSS) and you want to see and show what it looks like, or to check that a refactor changed nothing visually.

Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Refactoring. It works with Visual Studio Code. The repository describes itself as: Extension that shows information about the estimated token usage and more of AI in editors/CLI's. The licence is MIT.

When your agent uses it

  • A change touches webview UI (src/webview/
  • View HTML in extension.ts
  • Shared CSS) and you want to see and show what it looks like
  • Check that a refactor changed nothing visually

Example prompts

  • “/visual-view-diff”

Requirements

  • Node.js

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Find the view's HTML shell in extension.ts (getHtml) and note the
  2. Add an entry to views.config.json — id, bundle (its esbuild entry point
  3. Write fixtures/.json with that payload.
  4. Check it renders: node render-views.js --view --out /tmp/check.

What it can do on your machine

Read from SKILL.md and the folder at commit 6933e2a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • node
    • npm
    • gh
    • git
    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npm, gh, git and npx, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Visual View Diff loads about 3.1k tokens when it runs. Until then it costs about 90 tokens; SKILL.md has 1,636 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~90
When it runs · the whole SKILL.md, loaded when a task matches
~3.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from rajbos/ai-engineering-fluency at commit 6933e2a, republished under its MIT licence (© rajbos). 1,636 words, ~3,082 tokens.

Download SKILL.mdSave it as .claude/skills/visual-view-diff/SKILL.md (or your agent's skills folder).
name
visual-view-diff
description
Render the VS Code extension's webview panels headlessly and detect which ones changed visually, producing before/after/diff screenshots for review. Use when a change touches webview UI (src/webview/**, view HTML in extension.ts, shared CSS) and you want to see and show what it looks like, or to check that a refactor changed nothing visually.

Visual View Diff Skill

Renders the extension's webview panels headlessly, screenshots them, and reports which views changed compared to a baseline commit.

The screenshots are the deliverable. Posting them anywhere — a PR comment, a job summary, an artifact upload — is deliberately not part of this skill. It answers exactly one question: what changed visually, and what does it look like? Whoever wants to publish that answer reads report.md and the PNGs.

The publisher for pull requests is the ui-checks job in .github/workflows/ci.yml: it runs this diff against the PR's merge base and posts the before/after/diff images as one comment on the PR (replaced on every push) through gh pr comment --attach, rendered by .github/workflows/scripts/visual-diff-comment.js. An agent opening a UI PR does not have to attach screenshots by hand — it has to make sure the change is visible to this harness (see "States" below) and say in the PR body which views it expects to change.

When to use it

  • A change touches vscode-extension/src/webview/**, the shared webview CSS, or a get*Html method in extension.ts.
  • A refactor is supposed to be visually neutral and you want proof.
  • You want before/after images of a UI change for a human to look at.

Why this exists (and why it does not open VS Code)

The repo forbids agents from launching a real editor window — see "Never Launch a Real Editor/IDE Instance" in .github/copilot-instructions.md. That rules out the Extension Development Host, and with it the existing aiEngineeringFluency.runLocalViewRegression command, which only a human can run and which checks DOM metrics (node counts, text length) rather than appearance.

This skill covers the gap: it renders the real webview bundles outside VS Code. Every panel's HTML shell in extension.ts is the same four ingredients — a <div id="root">, a window.__INITIAL_<VIEW>__ payload, the shared JSON config globals, and <script src="dist/webview/<view>.js">. The harness reproduces that shell around a committed fixture and supplies the --vscode-* theme tokens VS Code would normally inject, then lets the real bundle render.

Nothing about the views is re-implemented, which is what makes the screenshots trustworthy: if rendering code changes, the screenshot changes with it.

Usage

Everything runs from the repo root. Bundles must be built first (cd vscode-extension && npm install && node esbuild.js).

Compare against the baseline commit (the usual case)
bash
node .github/skills/visual-view-diff/visual-diff.js
# or, from vscode-extension/:  npm run visual:diff

This builds the webviews at the merge base with origin/main in a temporary git worktree, builds the working tree, renders both, and compares. Your checkout is never touched — no stashing, no branch switching.

bash
# Compare against something else, or render both themes
node .github/skills/visual-view-diff/visual-diff.js --base origin/main --theme both
node .github/skills/visual-view-diff/visual-diff.js --view details,chart

Output lands in visual-output/ (git-ignored):

visual-output/
├── baseline/   <view>.<theme>.png     — before
├── current/    <view>.<theme>.png     — after
└── diff/       <view>.<theme>.diff.png, report.md, report.json

A view rendered in one of its declared states (a tab, a mode) is named <view>--<state>.<theme>.png, e.g. usage--tools.dark.png.

Just screenshot the current state
bash
node .github/skills/visual-view-diff/render-views.js --out visual-output/current --theme both
# or, from vscode-extension/:  npm run visual:render -- --theme both
Compare two directories you already have
bash
node .github/skills/visual-view-diff/diff-screenshots.js \
  --baseline visual-output/baseline --current visual-output/current --out visual-output/diff

Reading the result

diff/report.md is a Markdown summary — a table of every view with its status (changed / unchanged / added / removed), how many pixels moved, and the image size. report.json is the same data for scripting.

Diff images paint changed pixels magenta over a dimmed copy of the new screenshot, so a change is easy to locate in context.

A changed view is not automatically a problem. Read the diff image and decide: intended restyle, or accidental regression? The tool reports; you judge.

Requirements

  • Playwright with Chromium. Intentionally not a dependency of the extension — this is developer/CI tooling, not shipped code. lib/browser.js finds a local or global install, or the pinned one CI uses under .github/workflows/dependencies/playwright; if none exists: npm install -g playwright && npx playwright install chromium. The Copilot coding agent gets that pinned install from copilot-setup-steps.yml, and Claude Code's cloud environment ships a global Playwright, so in both an agent can run this skill as-is.
  • Built webview bundles in vscode-extension/dist/webview/.
  • vscode-extension/node_modules — the baseline worktree symlinks it rather than running a second npm install.

Fixtures

Each view renders from a committed JSON fixture in fixtures/, holding exactly the payload extension.ts passes to that view. Fixtures use fixed timestamps and synthetic numbers so two runs of the same code produce byte-identical screenshots — a Date.now() anywhere would make every view diff against itself.

A fixture can reference a repo data file instead of copying it:

json
{ "categories": { "$fromRepoJson": "src/fluencyLevelData.json" } }

That keeps the fixture small and means editing the source file shows up as the visual change it really is.

Adding a view
  1. Find the view's HTML shell in extension.ts (get<Name>Html) and note the window.__INITIAL_*__ global it assigns.
  2. Add an entry to views.config.json — id, bundle (its esbuild entry point name in esbuild.js), global, and fixture.
  3. Write fixtures/<id>.json with that payload.
  4. Check it renders: node render-views.js --view <id> --out /tmp/check.

A view whose #root comes out empty is reported as an error, not silently screenshotted blank — a fixture missing a required field would otherwise pass as "no visual change" forever.

dashboard is enabled with synthetic Azure rollups and an additional __DASHBOARD_CONFIG__ global declared in the registry's globals field. Both backend tabs render without contacting a live backend. The in-editor regression runner still skips it because that runner needs a configured live backend. When enabling a previously disabled view, the visual baseline uses the new fixture on both bundles to compare layouts rather than a loading screen against data.

Show full SKILL.md (792 more words)Show less
States — tabs and modes

A view is screenshotted in its initial render and in every state it declares. This matters more than it sounds: the usage panel opens on "My Activity", so a whole new section added to its Tools tab once diffed as "20 unchanged" — the harness never looked at that tab. A state is a few click/select steps replayed on a fresh page before the screenshot:

json
{
  "id": "tools",
  "title": "Tools & Integrations tab",
  "steps": [{ "click": ".tab-button[data-tab=\"tools\"]" }],
  "expect": "#tab-panel-tools"
}
  • steps use the same click / select (+ optional value) vocabulary as interaction-smoke scenarios, plus post: a message delivered to the view as if the extension host sent it. A tab that asks the host for data when it opens (Repository PRs, Cloud Agent) would otherwise only ever screenshot its loading placeholder, so its state declares the answer. Keep that answer deterministic — fixed dates, no fetchedAt — or the screenshot diffs against itself.
  • expect (required) is what the state must be showing afterwards. If it is not, the render is an error, not a screenshot of the previous tab that would pass as "unchanged" forever; a state without it is refused when the registry loads.
  • settleMs overrides the wait after the steps for a tab that lazily loads a chart library and animates in (the efficiency Models tab needs ~3s).
  • noiseFloorPixels gives a canvas-drawing state its own tolerance, so the view's DOM-rendered initial state can stay compared exactly.

Adding a tab to a view means adding a state for it here, or the visual diff will never see what you built. Reach a nested tab by clicking its group first (the diagnostics Research and Settings groups do this).

The baseline is rendered from the base commit's own views.config.json — its definitions, steps, fixtures and bundles — plus every view and state only the current registry declares. So a state (or a whole view) this branch introduced is attempted on the old bundle and, where it cannot render there, skipped by --allow-missing and reported as added; a state or view this branch removed or renamed still renders on the baseline side and is reported as removed, rather than vanishing from both sides as "no change"; and a state whose selector or fixture this branch changed is still driven the old way on the old bundle, so the comparison shows the real before and after. --allow-missing skips only those current-only targets: a view both sides declare that fails on the base bundle is an error, never a silent "added". The current-tree render stays strict too. View and state ids are file names, so the registry refuses anything but letters, digits, _ and single dashes, and duplicates.

Determinism

Two runs of unchanged code produce identical screenshots. That is load-bearing — without it every run reports spurious changes. It is achieved by pinning the locale to en-US and the timezone to UTC, freezing the page clock (FROZEN_NOW in render-views.js, the fixtures' shared "today"), disabling CSS animations and transitions, hiding carets, waiting for fonts to settle, and keeping all time-dependent values out of the fixtures.

The frozen clock matters because views read new Date() themselves: the chart draws a projected bar for the rest of the current period sized by the minute of the day, so an unfrozen clock made the chart diff against itself whenever the baseline and current renders straddled a minute boundary. The constant lives in the harness rather than the registry because the baseline render uses the base commit's registry, and both sides must see the same time.

The viewport is grown to the page's full height before the screenshot rather than letting the full-page capture do it: that capture-time resize made every responsive <canvas> (Chart.js) redraw mid-capture, and the efficiency Models tab diffed against itself by 2.6% on every other run.

The views that draw to a <canvas> (chart, maturity, the efficiency chart tabs) can still differ by a handful of anti-aliased pixels, so they carry a small noiseFloorPixels tolerance in views.config.json. Every other view is compared exactly — a global tolerance would hide small real changes, such as a restyled badge that moves fewer than 200 pixels.

Limits

  • Not a substitute for looking at the real extension. The harness supplies VS Code's theme tokens from lib/theme-dark.css / lib/theme-light.css, which track Dark Modern and Light Modern. A user's custom theme, high-contrast mode, or a token these files do not define will look different in practice. When a webview starts using a new --vscode-* token, add it to both files.
  • Fixtures are hand-authored, so they can drift from the real payload shape. Drift shows up as a render error or a visibly wrong view, not as a silent pass.
  • Only declared states are covered — each view is screenshotted in its initial render plus the tabs and modes listed under states in views.config.json. Hover, transient dialogs and click sequences beyond those are out of scope.

© rajbos, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/visual-view-diff of rajbos/ai-engineering-fluency.

Open the folder on GitHubat commit 6933e2a

Compare with similar skills

Visual View Diff next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Visual View Diff compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Visual View Diff this skillrajbos/ai-engineering-fluency115—~3.1kAutomated safety check: PassMIT
Omni DevGulajavaMinistudio/Mayukai-Theme139—~736Automated safety check: PassMIT
Trust Test AuthoringjohannesPettersson80/trust-platform221—~939Automated safety check: PassApache-2.0
Vibe CodingOfficeDev/microsoft-365-agents-toolkit781—~5.5kAutomated safety check: PassCustom licence
Expert Code ReviewerGulajavaMinistudio/Mayukai-Theme139—~1.4kAutomated safety check: PassMIT
Guidelinesakash-network/node1.1k22 repos~577Automated safety check: PassMIT

Similar skills

  • Omni Dev

    GulajavaMinistudio/Mayukai-Theme

    Omni-expert principal software architect. An agent skill from GulajavaMinistudio/Mayukai-Theme.

    139 GitHub stars~736 tokensUpdated 3 mo ago
    DevelopmentAuto-check passed
  • Trust Test Authoring

    johannesPettersson80/trust-platform

    A skill your agent uses for every trust-platform behavior change, bug fix, refactor, malformed input, runtime safety, VS Code, hardware, docs, or supply-chain task that requires a written…

    221 GitHub stars~939 tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Vibe Coding

    OfficeDev/microsoft-365-agents-toolkit

    End-to-end workflow for agent-driven changes that add or modify behavior in the toolkit packages.

    781 GitHub stars~5.5k tokensUpdated today
    DevelopmentAuto-check passed
  • Expert Code Reviewer

    GulajavaMinistudio/Mayukai-Theme

    Language-agnostic workflow for code reviews and security audits against Clean Code/SOLID principles, generating formal refactoring plans.

    139 GitHub stars~1.4k tokensUpdated 3 mo ago
    DevelopmentAuto-check passed
  • Guidelines

    akash-network/node

    Behavioral guidelines to reduce common LLM coding mistakes. An agent skill from akash-network/node.

    1.1k GitHub starsUsed in 22 repos~577 tokens
    DevelopmentAuto-check passed
  • Component Refactoring

    langflow-ai/langflow

    Refactor high-complexity React components in Langflow frontend.

    156k GitHub stars~3.5k tokensUpdated today
    DevelopmentAuto-check passed

More from rajbos/ai-engineering-fluency

All 22 skills in this repo
  • Check Urls

    rajbos/ai-engineering-fluency

    Find all hardcoded URLs in TypeScript source files and verify they resolve (return HTTP 2xx/3xx).

    115 GitHub stars~662 tokensUpdated yesterday
    Auto-check passed
  • Create Issue

    rajbos/ai-engineering-fluency

    Create a well-scoped GitHub issue in this repo. An agent skill from rajbos/ai-engineering-fluency.

    115 GitHub stars~2k tokensUpdated yesterday
    Auto-check passed
  • Deduplicate Code

    rajbos/ai-engineering-fluency

    Detect copy-pasted code blocks across the shared source (vscode-extension/src, the repo-root src/, cli/src) with the dependency-free check-code-duplication.js detector, then pick one duplicate group…

    115 GitHub stars~2.4k tokensUpdated yesterday
    Auto-check passed
  • Improve Tool Families

    rajbos/ai-engineering-fluency

    Analyze coverage of the vscode-extension's tool-family definitions (DEFAULTTOOLFAMILIES in vscode-extension/src/toolFamilies.ts) against the canonical tool-name list in src/toolNames.json and/or a…

    115 GitHub stars~1.3k tokensUpdated yesterday
    Auto-check passed
  • Load Cache Data

    rajbos/ai-engineering-fluency

    Load and display the last 10 cache entries as raw JSON output.

    115 GitHub stars~3.2k tokensUpdated yesterday
    Auto-check passed
  • PR Risk Review

    rajbos/ai-engineering-fluency

    Assess the risk of a changeset (a PR, a branch, or the working tree) and classify it as low, medium, or high with a written rationale.

    115 GitHub stars~2.6k tokensUpdated yesterday
    Auto-check passed

Categories

Questions about Visual View Diff

What does Visual View Diff do?

Render the VS Code extension's webview panels headlessly and detect which ones changed visually, producing before/after/diff screenshots for review. Visual View Diff is an agent skill from rajbos/ai-engineering-fluency. Render the VS Code extension's webview panels headlessly and detect which ones changed visually, producing before/after/diff screenshots for review.

When should I use Visual View Diff?

Visual View Diff fits situations like: A change touches webview UI (src/webview/; view HTML in extension.ts; shared CSS) and you want to see and show what it looks like; check that a refactor changed nothing visually.

How do I install Visual View Diff in Claude Code?

Run `npx skills add rajbos/ai-engineering-fluency --skill visual-view-diff -a claude-code`. Or copy the skill folder (.claude/skills/visual-view-diff in rajbos/ai-engineering-fluency) into .claude/skills/visual-view-diff in your project. Claude Code loads it when a task matches its description.

How do I install Visual View Diff in Codex?

Run `npx skills add rajbos/ai-engineering-fluency --skill visual-view-diff -a codex`. Or copy the skill folder (.claude/skills/visual-view-diff in rajbos/ai-engineering-fluency) into .agents/skills/visual-view-diff in your project. Codex loads it when a task matches its description.

Can I use Visual View Diff in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add rajbos/ai-engineering-fluency --skill visual-view-diff -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/visual-view-diff, .gemini/skills/visual-view-diff, .github/skills/visual-view-diff and .opencode/skills/visual-view-diff in your project.

What does Visual View Diff need to run?

Going by SKILL.md and its folder, Visual View Diff needs the command-line tools its instructions call (node, npm, gh, git and npx). Our summary lists: Node.js.

Does Visual View Diff access the network?

SKILL.md contains no URLs. Its commands use npm, gh, git and npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Visual View Diff safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Visual View Diff use?

Visual View Diff is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Visual View Diff use?

About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Visual View Diff?

Skills that share tags, products or a category with Visual View Diff: Omni Dev (GulajavaMinistudio/Mayukai-Theme, 139 stars), Trust Test Authoring (johannesPettersson80/trust-platform, 221 stars), Vibe Coding (OfficeDev/microsoft-365-agents-toolkit, 781 stars) and Expert Code Reviewer (GulajavaMinistudio/Mayukai-Theme, 139 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Visual View Diff?

rajbos (a GitHub user) maintains it in rajbos/ai-engineering-fluency, which has 115 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 6, 2026.

Source: rajbos/ai-engineering-fluency on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.