一键导入
studio
Receives CSS and HTML changes made in CSS Studio via MCP and applies them to source code.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Receives CSS and HTML changes made in CSS Studio via MCP and applies them to source code.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Analyze the Secondlayer codebase and identify exactly ONE high-leverage, low-risk quality-of-life improvement. Use when: user runs "/quality-of-life", asks for "a quick win", "something to improve", "code quality check", or "what should I clean up next".
Run a production smoke sweep against secondlayer prod — container health, husk canaries, decoder lags, op queue budgets, public subgraph reads, balance conservation, known-bug regression probes. Use when the user runs "/prod-smoke", asks to "smoke test prod", "check prod health", "is everything running smoothly", or "verify the subgraphs".
Use Secondlayer to build on the Stacks blockchain — index on-chain activity into typed Postgres tables (subgraphs), stream raw and decoded events (Streams + Index), deliver row-level webhooks (subscriptions), and call Clarity contracts from a viem-style TypeScript SDK. Invoke this skill whenever the user mentions Secondlayer, `sl`, the `@secondlayer/*` packages, Stacks indexing, sBTC, BNS, PoX/stacking, Clarity contract reads/calls, post-conditions, webhook subscriptions on chain events, or asks how to query, watch, or react to anything happening on the Stacks chain — even if they don't name Secondlayer explicitly.
Analyze Stacks ecosystem signals and map them to high-value product, marketing, security, and onboarding opportunities buildable with secondlayer tools (Index, Subgraphs, Streams, CLI, SDK, @secondlayer/stacks, MCP). Use when the user pastes a Stacks Discord "this week in Stacks" announcement digest, or points at any single source — a Hiro GitHub issue, a forum/X thread, a dev complaint about the Hiro API or another service, a protocol launch, or a historical hack/exploit writeup — and wants it parsed, its links fetched and analyzed, and turned into ranked opportunities for product validation, developer onboarding, ecosystem/dev-need solutions, security tooling, or brand content. Triggers on "scout the announcements", "stacks opportunities", "what can we build from this", "analyze this for product opportunities", "ecosystem scan".
Create a changelog, launch, announcement, or milestone video for ANY repo / package / release using the cadence CLI. Use whenever someone wants a video, reel, teaser, or animated showcase for a software feature, release, PR, changeset, SDK/CLI update, or milestone — phrasings like "make a changelog video for <repo>", "announcement video for the v2 release", "showcase the new <feature>", "a reel for our latest npm release", "render a 9:16 of <project>'s changelog", "milestone video — 1M downloads". Point it at a local repo path or a GitHub repo. It reads the project, writes a small data file, and renders an MP4. Trigger even when the user doesn't say "Remotion", "beats", or "render".
| name | studio |
| description | Receives CSS and HTML changes made in CSS Studio via MCP and applies them to source code. |
| argument-hint | [wait for edits from CSS Studio] |
CSS Studio is a visual editor that lets users edit CSS properties, HTML attributes, text content, and CSS variables on a live page. When connected via MCP, edits made in the panel are sent as structured data describing the change.
Your first css-studio call must be announce:
css-studio({ action: "announce", capabilities: { subagent: true, backgroundSubagents: true, channelEvents: true, ask: true } })
subagent — true if you can spawn subagents via a Task/Agent tool.backgroundSubagents — true only if your host's subagent spawn is detached so your turn continues immediately while the subagent runs (e.g. a run_in_background: true flag or equivalent capability). This is what enables parallel tasks. If you have such a capability, announce true and use it; if your spawn primitive blocks the parent, announce false or omit — tasks then route in linear mode and the hub queues them FIFO on this thread. That's correct behaviour — just no parallelism.channelEvents — true if your environment delivers notifications/claude/channel notifications.ask — true if you can block on a user answer.Before entering the main loop, tell the user: "Starting CSS Studio in parallel mode." (you announced backgroundSubagents: true) or "Starting CSS Studio in linear mode." — then immediately make the first get call in the same turn.
Immediately after announce (and the one-line status message), call css-studio({ action: "get", timeout: 60000 }). Do not end the turn on a status message alone — the status line is not a tool call and the server cannot wake you without a pending get.
Then keep calling get in a loop forever:
get again.notifications/claude/channel) may arrive while a get is in flight — they unblock it early so the task is delivered without waiting out the poll. They do not replace the poll loop; the loop is mandatory.Every task arrives with a mode. The task carries a payload object — the canonical, deduped data the subagent needs (or you need, in linear mode).
mode: "orchestrator"Spawn one subagent per task — immediately, detached, with the shortest possible prompt. When a task arrives, your very next action is the sub-agent spawn call. Do not write preamble, commentary, or a status line first — any delay is user-visible.
The task carries subagentPromptPath: an absolute path to a file the hub has already written containing the full subagent instructions + payload. Your Task prompt is a single short directive pointing at that path — do not inline the header or the payload. Inlining them costs 25–60 seconds of token generation per task (measured); the file-based form takes ~1–2 seconds.
You MUST spawn in background mode. You only get mode: "orchestrator" tasks because you announced backgroundSubagents: true. Spawning blocking would serialise every incoming task behind this one and defeat the independent-chat architecture.
Spawn call shape:
Task({
subagent_type: "general-purpose",
description: "CSS Studio task",
prompt: "Read the file at " + task.subagentPromptPath + " and follow the instructions within. Do not narrate, summarise, or ask me questions — act on the instructions directly.",
run_in_background: true,
})
Use your host's detached/background spawn capability (run_in_background or equivalent) — if it's available, use it. The prompt shape stays the same. The hub already marks the task as responding on dispatch; you don't need to emit set-task-responding yourself.
After the spawn call returns (it returns immediately — the subagent runs in parallel), loop straight back to css-studio({ action: "get" }). When the backgrounded subagent eventually finishes you'll see a completion notification — ignore it. All progress, accept/revert, and final status were delivered directly to the server by the subagent's curl POSTs; the hub needs nothing from you.
mode: "linear"Handle the task inline. The payload has everything:
css-studio({ action: "claim-request", requestId: task.id }).css-studio({ action: "set-task-name", taskId: task.id, name: "…" }).css-studio({ action: "set-task-responding", taskId: task.id, active: true, verb: "Reading source" }).payload.edits in order, then implement payload.prompt. Target elements via payload.attachments[edit.attachment]. Read any images in payload.imageAttachments[] with your Read tool.
payload.messages already contains role: "agent" replies, the user sent follow-ups while you were working on an earlier turn. Respond to the newest user message(s) that came after your last agent reply — don't re-implement payload.prompt and don't re-apply edits you already applied.nextVerb describing what you're about to do next. Use fresh verbs — "Searching files", "Editing src/foo.tsx", "Running tests". Format text as markdown — backticks around filenames, selectors, CSS properties; **bold**; - lists.
css-studio({ action: "send-task-message", taskId: task.id, text: "Located the CTA in src/cta.tsx", nextVerb: "Editing styles" })
Post at least once per minute. The server reaps silent tasks as failed after ~15 minutes; if you're about to start a single long step (big grep, multi-file edit, test run), post a progress message first — the nextVerb alone keeps the task alive.css-studio({ action: "ask", taskId: task.id, question: "…", options: ["…"] }). Blocks until they answer.css-studio({ action: "complete-request", requestId: task.id, text: "summary" }). For kind: "variant", include result: { html: "<css-studio-variants>…" }.css-studio({ action: "describe-element", taskId: task.id }) to fetch live DOM info and retry.css-studio({ action: "panic", taskId: task.id, reason: "element_not_found", element: "…" }); clear with calm once fixed.css-studio({ action: "fail-request", requestId: task.id, error: "…" }).prompt — free-form instruction. Interpret and implement on the target element(s).variant — generate 3-5 design variants. Return a <css-studio-variants> wrapper in result.html — DO NOT edit source.
Apply variant "X" to …, Generate more variants based on "X", Retry applying variant "X" …) arrive as plain prompt tasks with no HTML in the text — the chosen variant's name is the only reference. Fetch the variant bundle HTML with css-studio({ action: "get", type: "variant", element: "<selector>" }) and pass it into the subagent's prompt so it can locate the chosen variant by data-name.responsive — add responsive styles (breakpoints / fluid values) for the element. The latest message's viewport is the current context.changes array — panel edits not wrapped in a task)Diff-style edits carry from and to as separate fields so the values can contain any characters (including arrows). Non-diff edits use value.
{ "changes": [ { "type": "style", "path": "main > section.hero", "element": "div.card:nth-of-type(2)", "name": "background-color", "from": "#fff", "to": "#f0f0f0" } ] }
| type | element | name | payload |
|---|---|---|---|
style | CSS selector | CSS property | from, to |
text | CSS selector | — | from, to |
attr | CSS selector | attribute name | from, to |
attr-delete | CSS selector | attribute name | — |
attr-rename | CSS selector | old attribute name | value = new name |
delete | CSS selector | — | — |
tag | CSS selector | — | from, to |
add-child / add-sibling | CSS selector | — | value = new tag |
duplicate | CSS selector | — | — |
token | — | CSS variable | from, to |
token-rename | — | old variable name | value = new name |
keyframe | — | @keyframes name | value = full CSS |
For text edits, each Change targets one block — a single <p>, heading (<h1>–<h6>), <li>, <blockquote>, <pre>, etc. The element selector (with :nth-of-type when needed) is the block itself, NOT a container like <article> or wrapping <div>. from and to carry the complete prior and new markdown of that block — inline formatting appears as **bold**, *italic*, \code`, label, strike; blocks as # heading, - list`. The strings are NOT stripped to a slice, so the full surrounding text is available as context.
To apply: locate the source element matching element (use from to disambiguate if multiple match within the scope) and replace its inner text with to, converting markdown formatting into whatever syntax the source uses — HTML tags for .html/.jsx/.tsx, literal markdown for .md/.mdx, etc. Do NOT touch sibling blocks; they emit their own Changes if they changed.
Agent notes in [[ … ]]. Any span the user wraps in double square brackets inside the new text is a note to you, not literal copy — interpret and act on it, don't transcribe it. Read the bracketed text as an instruction and replace the whole [[ … ]] span with content that satisfies it, using the surrounding text as context. The [[ ]] markers and their contents must never appear in the source you write. E.g. to: "Our beans are sourced from [[name three regions]]" → write the actual regions ("Ethiopia, Colombia, and Guatemala"); to: "[[make this punchier]] Welcome to our store" → rewrite the line per the note. This applies to any literal content the user types this way — text blocks and attr values alike (e.g. an alt/placeholder of "[[describe the photo]]").
A single inline-edit can produce multiple text Changes (one per modified block). Apply each independently in order. Special cases: from: "" means insert to as new text/block inside element (added paragraph, or loose text typed into a container). to: "" means remove the from text from element (deleted block) — element falls back to the editing root in this case, so use from as the find anchor. precedingText (when present on an insert or delete) carries the last few words of the preceding block in the original layout. Use it to locate the position in source: for inserts, place the new block immediately after the source block ending with those words; for deletes, remove the source block immediately after the one ending with those words (use from to confirm it's the right block).
Loose changes (no task wrapper) are keystroke edits. Apply them to source; don't claim a task.
css-studio tool returns an error, tell the user what failed — don't leave them waiting silently.in-progress, or the element stays visually locked in the panel.src/foo.css…".The CSS Studio MCP server is not installed. Install it with:
npx cssstudio install