InSpec documentation

InSpec is a standalone CSS editor for live web pages. Click any element, dial in the styles with real visual editors, copy the result back out as paste-ready CSS — and the edits stick across reloads, automatically. Think of it as Chrome DevTools turned into the design tool it always wanted to be.

Installation

InSpec comes three ways. The direct download from bendansby.com/apps/inspec is a standard .dmg — drag InSpec.app into Applications. The Mac App Store version installs the usual way. The Setapp version is a one-time purchase, not part of a Setapp Membership subscription; it installs through the Setapp client, with no separate license key and no trial. Requires macOS 14 Sonoma or later; universal binary.

Your first edit

The five-second tour:

  1. Type a URL into the address bar (⌘L) and press ↩ — the page loads and takes the keyboard, so it scrolls and responds to keys straight away. Clicking the address selects it, ready to type over.
  2. Hover anything — InSpec outlines it in cyan and shows the box-model bands.
  3. Click to pin the element (outline turns amber).
  4. Edit any property in the sidebar — the page updates live.
  5. Reload. The edit re-applies automatically.

Click-to-pick

Inspect mode is on by default. As you move the cursor across the page, InSpec draws a cyan overlay around whatever's under the cursor, plus alignment guides extending to the page edges and box-model bands for margin (orange) and padding (green). A small badge shows the element's pixel dimensions and tag.

Hold ⌥ to toggle inspect mode off temporarily — useful for clicking through to a link or button without picking it.

Pinning an element

Click any element to pin it. The cyan hover outline becomes a persistent amber outline and the inspector populates with the element's CSS. The pin sticks through scroll, resize, and JavaScript-driven layout changes — InSpec re-resolves the element on every animation frame so the outline tracks it even as the page reflows.

Esc deselects. With nothing selected, Esc goes to the page, so a site's own dialogs and menus close with it. It never takes the window out of full screen.

Walking up the tree

The DOM list at the top of the inspector shows the pinned element's ancestor chain, its siblings and its children. Click any row to re-pin to that element — handy when you actually need to style the parent container, or a neighbour, instead of the leaf you clicked on.

The inspector

The right sidebar lists every CSS rule whose selector matches the pinned element, in cascade order, with the rule's declarations underneath as editable rows. Rules are read straight from the page's stylesheet source, so what you see is what the author wrote — no longhand expansion of font, background, or other shorthands. Declarations that another rule beats are shown struck through, each naming the rule that won, and every rule block shows its place in the cascade, its specificity and its @layer, if it has one. Toggle properties off with the checkbox; edit values inline; press ↩ to commit, Esc to revert (the element stays selected). ↑/↓ step the number under the caret by ±1, and ⇧↑/⇧↓ by ±10 — so in 8px 16px you can nudge either value. Long values wrap inside their field; a multi-line value is edited in its one-line form.

Each rule group carries its own + button to add a property to that rule, and an edit you make under a rule applies to every element that rule matches — not just the pinned one. To scope an edit to the selected element alone, use the Individual section (see Rule-wide & individual edits).

Variants

Above the rules pane, a strip lists every pseudo-class and @media context the page authors against the inspected element — :hover, :focus, :focus-visible, :active, :disabled, :checked, :hover @ (prefers-color-scheme: dark), print, and so on. Each row carries a glyph keyed to the variant type and a badge with the number of properties that variant changes.

Click a variant and InSpec promotes its declarations onto the live element with !important, so you can see and edit the hover state without holding the mouse there, the dark-mode variant without flipping system appearance, the print rule without opening print preview. The rules pane re-evaluates against the chip rather than the cursor's real-time state, so a :hover rule no longer flickers in just because your mouse drifted across the element.

Adding a variant

To style a state or breakpoint the page doesn't define for this element yet, click Add variant… at the end of the strip. Pick a state (:hover, :focus…) or one of the page's breakpoints, then check the Selector field: it starts as the pinned element's own selector, and you can edit it to broaden or narrow what the new rule targets. You can change it again later from the rule's header. Edits made while the variant is selected are scoped to it.

Variants you add are kept: they survive deselecting and reselecting the element, and edits you make while a variant is on show immediately.

The Variant rules only checkbox (on by default once a variant is active) narrows the rules pane to just the rules contributing to that variant. Turn it off to see the full cascade alongside.

Visual editors

Whenever a property has a richer affordance than a text field, InSpec shows it. Click the swatch / chip next to the value to pop the editor:

The box model button in the inspector header opens a DevTools-style margin / border / padding / content diagram for the pinned element. Every edge is editable in place: drag across a field to scrub, or use ↑/↓ (±1), ⇧↑/⇧↓ (±10) and ⌥↑/⌥↓ (±0.1). Bare numbers get px; empty a field to clear that side's override.

CSS variables

InSpec extracts every --name: value declaration from the page's stylesheets and offers them in autocomplete whenever you're editing a compatible property — colour vars in colour fields, length vars in length fields, etc.

Each var() in a value shows as a pill carrying its resolved value, so you can see what the variable actually is at a glance. Click a pill to pick a different variable for just that part of the value — the rest of the value is left alone. (Toggle the pill view off in Preferences if you prefer raw var() syntax.)

Adding a property

Every group has its own + button. Add from a rule heading to add a property to that rule (it applies to all matching elements); add from the Individual section heading to add a property to just the pinned element. Either way the Add property modal opens — type a property name (with autocomplete) and a value. For an individual add you also pick a save target: Inline (element.style), the <style> block in <head>, or any of the page's attached stylesheets. The target rides along with the override so Save to source and Copy CSS by stylesheet route it correctly the first time, and you can retarget any edit later via the chip on its row in the overrides sheet.

Rule-wide & individual edits

An edit you make under a stylesheet rule is rule-wide: InSpec injects it as a selector { … } rule, so it changes every element that selector matches, present and future. That's the right default for restyling a component — edit .card once and every card follows.

When you want an edit to touch only the element you pinned, move it to the Individual section at the top of the panel. Two ways:

InSpec drops the rule-wide override and re-applies the same value as an inline style on just that element. The Individual section also has its own + for adding element-only properties from scratch, and lists every element-scoped edit you've made (it never shows values that merely changed because of a rule-wide edit elsewhere).

Overrides across reloads

Every edit you make is an "override" — a small record of selector + property + value. Overrides persist to UserDefaults keyed by the page's URL (scheme, host, path). On the next reload InSpec re-injects them as a stylesheet before the page paints, so your edits are already in place by the time you see the page.

Two overrides for the same selector + property update in place (no duplicates). A toggle next to each override lets you A/B-compare without deleting.

Pinning an override

Pin an override to keep it when you clear the rest: right-click its row and choose Pin override, or click the pin button on its row in the overrides sheet. A pinned override shows a pin icon; click it to unpin. Pinned overrides survive Clear All, so a fix you're still testing stays put while you clear the experiments around it.

The All Overrides modal

From the inspector's … menu, Show All Overrides opens a sheet listing every override for the current page. Filter by source stylesheet, enable / disable individually, delete individually, or select-and-copy as a single CSS block.

Clearing overrides

The nuclear option: View → Clear Overrides on Page deletes every override for the current URL — text edits included — and reloads. Useful for resetting your work to compare with the original, or starting fresh on a section you've been over-iterating. Pinned overrides are kept, and the confirmation says how many.

Importing & exporting overrides

File → Export Overrides saves the current page's overrides in one of two formats:

File → Import Overrides… reads either format and merges it onto the current page, applying it live — so you can move a set of edits to another URL, hand it to a teammate, or keep a known-good version. A CSS import makes every rule a rule-wide override. The overrides sheet has the same Export… menu and an Import… button.

Viewport presets

The viewport picker offers seven sizes:

Switching a viewport resizes the webview in place — no reload flash, JS state preserved. Once the page reflows, the selected element is scrolled back to the centre so it stays in view.

Per-breakpoint overrides

An override can be scoped to a single @media query. When you make an edit while a narrow viewport is active, the inspector pre-checks the matching breakpoint so the override only fires there. The copy-out wraps the rule in the right @media automatically.

Page modes

The page-modes button in the toolbar lists the @media features the page authors against — prefers-color-scheme, prefers-contrast, prefers-reduced-motion, print and the like. Pick one to force those rules on and see the page the way those visitors do; pick it again, or Live state, to go back. A rule is forced only when its whole query holds, so turning on prefers-contrast: more doesn't also apply a rule written for contrast and dark mode to a light page.

When your Mac is in dark mode, the list also offers prefers-color-scheme: light, which shows the page as light-mode visitors see it — its dark-mode rules stop applying.

Annotations

Annotations are review markup, separate from your CSS edits. With an element pinned, the annotation bar under the inspector header offers three marks:

Each element carries one mark at a time: click another to replace it, click the active one again (or Clear) to remove it. A matching badge appears on the element in the page and follows it as the page scrolls and reflows. Annotations are keyed to the page's URL and the element's selector, and persist across reloads and relaunches.

With nothing selected, the sidebar lists every annotation on the page, notes included. Click a row to re-select that element, its trash button to clear that annotation, or Clear all to remove every one.

Annotations never appear in the Source view, copied CSS or Save to source. They do appear in captures: when a page has annotations, the capture sheet shows an Include annotations switch, on by default — handy for sending a reviewed page to a stakeholder or a coding agent.

Copy as paste-ready CSS

Every override has a Copy button. The copied text is a complete CSS rule formatted to drop straight into your source stylesheet — selector, properties, and a wrapping @media query if the override targeted a breakpoint. Multi-select overrides in the All Overrides modal to copy a group as a single block.

To copy an element's CSS as a whole, use the copy menu in the inspector header: Copy styles copies the element's matched rules as the sidebar shows them — with your edits and media queries, in cascade order — and Copy all computed properties copies the full resolved set.

Overrides that change a property the original stylesheet doesn't set (e.g. an inherited or UA-default value) are flagged "needs new rule" and copied as a fresh declaration rather than as an override to a non-existent property.

Save to source

For a local page, Save to source in the overrides sheet writes your overrides back into its files — either editing each declaration in place or appending a fenced /* InSpec overrides */ block. When you're editing an HTML page, a change to a rule in the page's own <style> block rewrites that declaration in place rather than adding an override block at the end. Edits that apply to one element only are still added as a rule of their own.

Before anything is written, the confirmation sheet previews each affected rule in full, the way it reads in your file — every existing declaration in context, with the ones InSpec is about to change highlighted — so you can see exactly what will change before you save.

Screenshot capture

The camera button in the toolbar is a menu: Copy Image puts a picture of the page on the clipboard in one step, and Capture… opens the capture sheet (also File → Capture…, ⇧⌘S). In the sheet, pick visible viewport or full-page, tick which viewports to render, and InSpec renders each one off-screen with your overrides applied, keeping the page's layout and form state, and saves the images to a folder.

To capture just one element, use the camera menu in the inspector header: Copy Image puts a picture of the pinned element on the clipboard, and Save Image… saves it as a PNG.

Tabs & sessions

InSpec is multi-tab. ⌘T opens a blank tab; drag to reorder; ⌘W closes (flips to Close Window when the last tab is gone). ⌘-click a link in the page to open it in a new tab instead of navigating the current one. As you type in the address bar, a dropdown suggests matching pages from your history by URL or title — ↑/↓ to move through it, ↩ or a click to go. Each tab's overrides, scroll position, and inspection selection persist independently. Restore Session in Preferences brings every window's tab state back on next launch.

Freeze the page

View → Freeze Page (⌥⌘F) suspends JavaScript on the active tab — animations stop, scroll-driven effects pause, modal popups don't re-trigger. Useful when you're trying to inspect something that won't sit still. Toggle off to thaw.

Alignment guides

View → Show Alignment Guides (⇧⌘G) extends the hover overlay's vertical and horizontal lines to the full page width and height, so you can eyeball how the pinned element lines up with everything else. Global toggle — applies in every window.

Preferences

Keyboard shortcuts

ShortcutAction
⌘LFocus address bar
⌘TNew tab
⌘WClose tab (or window when empty)
⇧⌘WClose window
⌘-clickOpen link in a new tab
⌘RReload page
⌘OOpen local file
⇧⌘SOpen capture sheet
⌥⌘SShow / hide sidebar
⌥⌘FFreeze / unfreeze page
⇧⌘GShow / hide alignment guides
↩ in the address barLoad the page and give it the keyboard
EscDeselect pinned element (with nothing selected, goes to the page)
⌥ (hold)Suspend inspect mode while held
↑ / ↓±1 on the number under the caret
⇧↑ / ⇧↓±10 on the number under the caret

License & trial

Three distribution paths:

Unlicensed direct-download copies show a one-screen reminder roughly every tenth CSS-edit batch after a 7-day grace window. No features are locked, no overrides are deleted — the reminder offers Buy, Enter License, or Maybe Later.