Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>CSS Inspector MiniNew to Visual Studio Code? Get it now.
CSS Inspector Mini

CSS Inspector Mini

Aviran Revach

|
2 installs
| (0) | Free
Click an element on any web page and get a chat-ready description of it for Claude Code, Cursor, or any coding agent.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

CSS Inspector Mini

Click an element on any web page and get a chat-ready description of it in Claude Code or any other coding agent.

Let's talk about this element `a.dsnav-top-link:nth-child(3)` (a):

No more describing a button in prose, or hunting for the selector by hand. Point the extension at a running page, click the thing you mean, paste.

  • Works on any HTTP or HTTPS page — your dev server, a staging link, a public site
  • Never modifies your files
  • The page opens inside the editor, so your app and the chat sit side by side
  • Collect several elements and send them as one message
  • Five wordings, from a discussion opener to a numbered feedback list

Contents

  • How it works
  • Getting started
  • The panel
  • Single and multi-select
  • Wordings
  • Choosing what to inspect
  • In the page
  • Commands
  • Settings
  • Known limitations
  • Troubleshooting
  • Development

How it works

The extension runs a small local server and proxies the page you want to inspect. It fetches the page server-side, strips the headers that block embedding (X-Frame-Options, frame-busting CSP), injects a picker overlay, and serves the result back on loopback.

┌─ your editor ──────────────────────────────────────────────┐
│                                                            │
│  ┌─ Inspector panel ─┐   ┌─ the page, proxied ──────────┐  │
│  │ target, selection │   │  …your app, with a picker…    │  │
│  │ wording, actions  │   │                        [Pick] │  │
│  └───────────────────┘   └──────────────────────────────┘  │
│           ▲                            │                   │
│           └────── WebSocket ───────────┘                   │
└────────────────────────────────────────────────────────────┘

Because the overlay is served from the same origin as the proxied page, the picker attaches to anything reachable — including sites that refuse to be put in an iframe. The server listens on the first free port in 53110–53199 and stops when the editor closes.


Getting started

  1. Start your app however you normally do.
  2. Open the CSS Inspector icon in the activity bar (the cursor-in-a-box).
  3. The panel shows a detected dev server. Ports 3000, 4200, 5173 and 8080 are probed automatically — if yours isn't there, paste a URL into the field in the switcher and press Enter.
  4. Click Pick an element. The page opens in the editor with the picker already armed.
  5. Click any element. The selector lands on your clipboard and the chat takes focus.
  6. Paste, add your question, send.

Nothing to arm, no mode to enter. Clicking Pick an element is the whole gesture.


The panel

The panel shows only what's true at the moment, so it changes shape as you work.

Idle — the current target, and one framed block holding the action and its destination: Pick an element with on localhost:4321 beneath it, plus a live dot so you can see the server is up. The label says what the button does, the line says where it goes, and the frame says they belong together. A ⌄ on the button opens the three things you can do with that address — copy the inspect link, copy the original address, or open it in your own browser.

Picking — an indicator with a live count and an ✕ to cancel. Esc works too.

Captured — what you picked, the wording pills, a preview of the exact text, and the action.

The preview is the text itself, character for character — what you read is what gets pasted.


Single and multi-select

A Multi-select switch sits under the primary button.

Off (default) On
One click Captures and copies Adds to a selection
After a pick Picking ends, page usable again Stays armed, keeps collecting
Clipboard Immediate Nothing until you press the button
Clicking a picked element again Replaces it Removes it from the selection

With Multi-select on, picked elements get a green outline and a numbered badge in the page, matching their row in the panel — so you can tell which element note 2 refers to.

Turning it back off keeps your most recent pick and drops the rest.


Wordings

Five ways to frame the same selection. Switching re-copies immediately, so you can pick once and try wordings until one reads right. Your choice is remembered per workspace.

Discuss (default)

Let's talk about this element `.hero-title` (h1):

Restyle

Update the styles for these 3 elements: `.hero-title`, `.cta`, `footer .legal`:

Debug

Something looks wrong with this element `.hero-title` (h1). Here's what I'm seeing:

Selector — just the selector, nothing else. Good for pasting into code.

.hero-title

Feedback — a numbered scaffold you fill in after pasting.

Feedback on these 3 elements:

1. `.hero-title` (h1) - 
2. `a.dsnav-top-link:nth-child(3)` (a) - 
3. `footer .legal` (span) - 

Containers read area rather than element, so a wrapper doesn't get described as a widget.


Choosing what to inspect

Click the target line at the top of the panel to open the switcher.

DETECTED
  ● localhost:3000    Acme Admin · Dashboard      ⧉  ↗
  ● localhost:5173    Acme Marketing Site      ✓  ⧉  ↗
  ● localhost:8080    Storybook                   ⧉  ↗
RECENT
  ○ staging.acme.io                               ⧉  ↗
  ─────────────────────────────────────────
  [ Paste any URL, press Enter          ]
  • Detected servers were found listening. Recent are URLs you've opened before. They're separate groups, so a server you've never opened is never described as recent.
  • Page titles are fetched when you open the menu — a port number can't tell an admin app from Storybook. Nothing is fetched at startup.
  • Clicking a row switches the target. Clicking its ↗ doesn't — that opens the URL in your own browser and leaves the target where it was. Useful for checking which server is which, and the only way to see a signed-in page as yourself: the proxy forwards no cookies, so a webview inside the editor would show you the same signed-out page.
  • ⧉ copies the plain address to your clipboard, with no wording applied and without touching the chat — for dropping somewhere yourself.
  • Paste a URL and press Enter to go straight there. A rejected URL keeps its text and says why, in place.
  • Recents are stored per workspace, so each project keeps its own list.

In the page

The proxied page carries a small Pick pill at the bottom right. You normally won't need it — arriving from the panel means the picker is already armed — but it toggles picking on and off if you want to browse first.

  • Hover highlights the element under the cursor
  • Click captures it
  • Esc steps out of picking so the page behaves normally

A snackbar confirms each pick. In multi-select it reports Added / Removed with a running count, and tells you the elements are waiting in the panel rather than claiming they're on your clipboard.

About the selectors

Selectors prefer an id, then a unique class, and fall back to a positional path anchored on the nearest ancestor id.

Two kinds of name are deliberately skipped, because a selector containing them is wrong tomorrow:

  • Machine-generated names — CSS-module hashes, styled-components and emotion classes, React useId values, anything with a random alphanumeric tail. Both of these are real, from one page: Primer_Brand__FormControl-module__FormControl___xyCI6 and FormControl--_R_9l8l_. This applies to ids as much as classes; a framework-minted id is no more durable than a hashed class, and it's tempting precisely because ids normally are reliable.
  • Runtime state — is-active, open, selected and friends. Unique right now, pointing at a different element the moment the user clicks something else.

A third case gets qualified rather than dropped. A class with no letters in it describes nothing — Webflow prefixes numeric class names with an underscore, so a heading arrives as ._2. That's unique and stable but unreadable, so it borrows its parent for context: section.hero-section > h2._2.

Two rules keep paths short. Each step carries at most one class, and :nth-child is added only where a step is genuinely ambiguous among its siblings — an index on an element its class already identifies says nothing and breaks the moment anything is inserted above it.

A positional fallback is uglier than a hash but survives a rebuild, which is the trade being made.


Commands

Command What it does
CSS Inspector Mini: Pick element Asks which URL, then opens it with the picker armed
CSS Inspector Mini: Pick element on current target Skips the question and reuses the known target
CSS Inspector Mini: Stop inspecting Removes the picker from every open page and closes the editor's browser panel

A Pick element item also sits in the status bar. The inspector server keeps running either way — there's nothing to start or stop by hand.


Settings

cssInspectorMini.browserMode

"embedded" | "external" — default "embedded"

Where the page opens. embedded keeps it in the editor beside your chat. external uses your default browser; the picker still attaches, because the page comes through the proxy either way.

cssInspectorMini.chatInsertMode

"replace" | "append" — default "replace"

append prefixes the copied text with a newline, so it drops cleanly below something you've already typed in the chat.

cssInspectorMini.defaultFraming

"discuss" | "restyle" | "debug" | "selector" | "feedback" — default "discuss"

Which wording to start from. Once you pick a different one in the panel, that choice is remembered per workspace and takes precedence over this.

cssInspectorMini.recentUrlsLimit

number, 1–50 — default 10

How many recent URLs to keep. Stored per workspace.


Known limitations

Signed-in pages render signed out. The proxy fetches server-side and forwards no cookies. Use the ↗ in the switcher to open the page in your own browser — you'll see it as yourself, though the picker won't attach there.

Single-page apps may have broken API calls. Relative URLs resolve through an injected <base href>, which covers images, stylesheets and scripts but not fetch('/api/…') calls made from JavaScript.

Clicking a link inside a proxied page navigates out of the proxy. Use the panel to switch pages.

Non-HTML responses pass through untouched, so no picker appears on them.


Troubleshooting

The page opened in an external browser instead of the editor.Some editors — Cursor among them — don't ship VS Code's Simple Browser. The extension tries the known editor browsers and then falls back to rendering the page in its own panel, so this should be rare. If it happens anyway, the page still works and the picker still attaches.

No Pick pill on the page.The response probably wasn't HTML. Non-HTML content is proxied unchanged and gets no overlay.

The panel says not responding.The extension couldn't open a TCP connection to that host and port. If it says not checked, it simply hasn't looked yet — it won't claim a server is down without evidence.

Nothing happens when I click an element.Check the pill reads Picking…. If it says Pick, picking was cancelled — click it, or run Pick element again.


Development

npm install        # dependencies
npm run compile    # type-check and build to out/
npm run watch      # rebuild on change
npm test           # vitest
npm run package    # build a .vsix

Press F5 to launch an Extension Development Host. It compiles first, so you're never debugging a stale build. A new activity bar icon only appears in a freshly launched host — reloading an existing one won't pick up manifest changes.

Layout

Path Responsibility
src/extension.ts Activation, commands, status bar, opening the browser
src/inspector-server.ts The HTTP + WebSocket server, proxying and messaging
src/proxy-transform.ts Pure HTML transform: base href, CSP strip, overlay injection
src/sidebar-view.ts The panel
src/target-state.ts Pure view-model: which targets to offer and how to group them
src/framings.ts Pure: how a selection is worded
src/page-titles.ts Fetches page titles for the switcher
src/workspace-probe.ts Port probing and reachability
src/recent-urls.ts Per-workspace recent URL store
src/overlay/overlay.js The in-page picker

The pure modules carry the test suite; the server and the panel are verified by the manual matrix in SMOKE.md, since neither can run outside an editor host.

Design notes and implementation plans live in docs/superpowers/.

A note on the overlay script URL

proxy-transform must emit an absolute <script src> for the overlay. The <base href> it injects points at the inspected site, so a root-relative src would make the browser fetch overlay.js from that origin and the picker would never load. This shipped broken in v0.2.0 and v0.2.1; two regression tests now guard it.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft