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:
- 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.
- Hover anything — InSpec outlines it in cyan and shows the box-model bands.
- Click to pin the element (outline turns amber).
- Edit any property in the sidebar — the page updates live.
- 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:
- Color — system colour picker for any colour-typed property.
- Box shadow / text shadow — drag-based offset, blur, and spread; inset toggle (shadows only).
- Border radius — visual four-corner dial.
- Filter / backdrop-filter — chain of nine functions (blur, brightness, contrast, grayscale, hue-rotate, invert, opacity, saturate, sepia) with per-function sliders.
- Flex — picker for direction, justify, align, gap, wrap.
- Grid — template-columns / template-rows builder.
- Background image — gradient and image-URL composer.
- Cubic bezier — visual curve editor for transition / animation timing.
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:
- Drag the edit's row onto the Individual section.
- Right-click the row and choose Make individual (this element only).
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:
- As JSON… — full fidelity: enabled state, rule-wide vs individual, original values and save targets all round-trip.
- As CSS… — portable: plain
selector { … }rules carrying just the applied styles.
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:
- Fill — match the InSpec window width.
- Desktop — 1440 px.
- Laptop — 1280 px.
- Tablet landscape — 1024 px.
- Tablet — 768 px.
- Phone large — 414 px.
- Phone — 375 px.
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:
- Approved (green check) — this element is good.
- Needs change (red ✕) — this element needs work.
- Note (yellow) — opens a field for a written note; it grows as you type, and ↩ finishes.
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.
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
- Restore Session — re-open last window state on launch. Default on.
- Show Color Swatches — render a tiny colour pill next to colour-typed properties in the inspector. Default on.
- Show Node Styling — paint annotation badges on the live page. Default on.
- Show Resolved Variables — render
var(--name)references as a pill showing the computed value. Off shows the rawvar()text instead. Default on.
Keyboard shortcuts
| Shortcut | Action |
|---|---|
| ⌘L | Focus address bar |
| ⌘T | New tab |
| ⌘W | Close tab (or window when empty) |
| ⇧⌘W | Close window |
| ⌘-click | Open link in a new tab |
| ⌘R | Reload page |
| ⌘O | Open local file |
| ⇧⌘S | Open capture sheet |
| ⌥⌘S | Show / hide sidebar |
| ⌥⌘F | Freeze / unfreeze page |
| ⇧⌘G | Show / hide alignment guides |
| ↩ in the address bar | Load the page and give it the keyboard |
| Esc | Deselect 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:
- Mac App Store — purchase and updates handled by Apple. No license keys.
- Direct download — licensed via Lemon Squeezy. InSpec → Buy License… opens checkout, Enter License… activates the key from the purchase email. Activation is online; cached locally for up to 7 days offline.
- Setapp. A one-time purchase through Setapp — bought outright, not part of a Setapp Membership subscription. No separate license key; Setapp handles the purchase and delivers updates automatically. The app runs through the Setapp client, so keep it installed and your Setapp account active.
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.