Software · In use
Stylewright
A dev-only Vite plugin. Click an element on the running page, edit its component's CSS with a live preview, and the change is written back into the .svelte source. It can hand the selected element to a coding agent over MCP, and from 0.2.0 it works in front of any server-rendered app.
Stylewright is a dev-only Vite plugin. I click an element on the running page, change a value in its component's CSS, and the change is written straight back into the <style> block of the .svelte file that owns it. I built it for the design work on the Paupack Hills website, where the alternative was tuning a value in DevTools and then copying it into the component by hand before a reload threw it away. This site uses it too.
Source and install on GitHub →
Why DevTools can't do this
DevTools can save a CSS edit back to disk, but only when the file is a whole stylesheet: a .css served by a <link>, or one a source map points at as a complete file. A Svelte <style> is a region of CSS inside a mixed file, so DevTools has nowhere to write it. Vite makes it worse in dev by serving every stylesheet as JavaScript that injects a <style> tag, which DevTools treats as read-only. So Stylewright owns the whole round trip itself: an overlay in the page captures the edit, and a dev-server-only endpoint patches the exact declaration back into the source.
How a save works
- Which element. Svelte's dev metadata records which component rendered each element. It's the same data the Svelte inspector uses, so pick mode can name the file before you commit to the click.
- Which rules. The dev server reads that component, finds its
<style>block, and parses it with PostCSS. By default the panel lists only the rules that style what you picked, including the@mediarules that apply to it, instead of the whole stylesheet. - The preview. Editing a value repaints the page as you type. A colour opens a picker seeded with the colours the component already uses.
- The write. Press Enter and the matched declaration is updated in the PostCSS tree, stringified, and spliced back at exact offsets with magic-string. Nothing else in the file moves: not the markup, not the script, not the CSS around it. Vite then repaints from source, so what's on screen is what's on disk.
Anything that could corrupt a file is refused rather than guessed. A save that would drop an at-rule from the source is refused. A payload containing </style> is refused, because that route splices text into the component verbatim and would otherwise be a way to inject source.
Handing an element to an agent
Some changes aren't a CSS value. "Make this a loading state" is markup, a state and a style. The Ask AI tab hands the selected element, its source file and its parsed rules to one coding agent session over MCP, and the agent makes the change under its own permission and diff flow. Claude Code, Cline, OpenCode and Kimi Code are supported.
Three rules keep this honest:
- The overlay never edits a file. It queues text. Every write is the agent's, under the agent's own approval.
- Nothing is pushed into a session. An MCP server can't make an idle agent start working, so you tell the agent once to watch for Stylewright edits, and from then on it asks for work. Until it does, the panel says so instead of queueing a request nobody will claim.
- Status is never invented. The panel shows only what the agent reported. There is no timer that decides it probably finished, and no file watcher that guesses. Done, needs input, and the list of changed files all come from the agent.
Each of the four agents registers an MCP server differently, and their tool timeouts don't agree: Cline counts in seconds, OpenCode and Kimi Code in milliseconds, and the defaults are far too short for an agent that is waiting for work. The setup screen writes the right registration for the agent you pick, with the path filled in for your install.
Apps that aren't Svelte
Version 0.2.0 added a mode for apps whose pages are built on the server: a Cloudflare Worker under wrangler dev, Express, Rails, anything that isn't Svelte on Vite. Nothing is installed in the app. The Stylewright MCP server puts the overlay in front of the app's dev server as a proxy and gives you a URL to open in place of the app's own. Your agent names the CSS sources the overlay may write, either .css files or a template literal in a JS file, and the same PostCSS patcher splices the changed bytes into them. A template literal with ${…} in it can't be a source at all, because its CSS is only known at runtime, and anything else the patcher can't do safely is refused with a message saying so.
Keeping it safe
The dev server writes to your source tree, and any page in your browser can reach localhost by URL. So the API is gated, not just obscure:
- Same-origin only, and only for a
Hostthat is an IP literal or*.localhost. That's what stops a DNS-rebinding attack from defeating the origin check. - Writes need a header no
<form>can set, so a cross-site POST can't rewrite a component. - Path containment is checked twice, lexically and again after resolving symlinks.
- The agent routes need a loopback socket and a token. The token lives under
~/.stylewright, deliberately outside the Vite root, because a credential inside the served tree is handed to any unauthenticated GET. - None of it exists in a production build. The plugin only applies while serving.
There is one outbound request, IBM Plex from Google Fonts for the overlay, and it can be turned off. There is no telemetry.
What's next
- A fallback for Svelte apps where the dev metadata isn't available. Plain-HTML mode already matches an element to rules without any metadata, and extending that to
.sveltefiles is what's left. - Inline
style=""attributes andhttps://targets in plain-HTML mode. - More than one
<style>block per component, and nested rules. - Bundling IBM Plex so the overlay makes no outbound request at all.
- Answering an agent's clarifying question from the overlay, which needs MCP elicitation.
- A light theme for the overlay.
How it's made
I'm building Stylewright with Claude, Anthropic's AI, as a team. I set the direction and judge the result by using it on real pages. Claude builds, tests and hardens. When a vendor's docs and its binary disagreed about a timeout, we measured the binary.

Pick mode names the element and the file that owns it before you click. 
The colour picker opens seeded with the colours the component already uses. 
Ask AI: the instruction typed, and the chip saying no session is linked yet. 
The setup screen generates the registration for your install. A checkout gets an absolute path instead of a package name. 
Dock the panel left, bottom, right or floating, and show only the rules that style what you picked.