/dial-inline
The full dial session: offer through teardown. Injection payloads (MEASURE, INJECT, TOGGLE, CLEAR) are defined in `${CLAUDE_PLUGIN_ROOT}/commands/references/dial-inject.md` - read it before Step 4 and hold it for the session.
$ npx -y skills add drobins25/craft --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/dial-inline
Context preview
What this command does when you run it.
The full dial session: offer through teardown. Injection payloads (MEASURE, INJECT, TOGGLE, CLEAR) are defined in `${CLAUDE_PLUGIN_ROOT}/commands/references/dial-inject.md` - read it before Step 4 and hold it for the session.
Command definition
dial-inline.mdDial Flow
The full dial session: offer through teardown. Injection payloads (MEASURE, INJECT, TOGGLE, CLEAR) are defined in `${CLAUDE_PLUGIN_ROOT}/commands/references/dial-inject.md` - read it before Step 4 and hold it for the session.
Two shapes, both first-class, neither the default:
- **Magnitude** - one property, different amounts. Ordered: current / conservative / reach. Spacing, size, weight, timing. ("The gaps are too loose.")
- **Approach** - one goal, different treatments. Unordered - there is no "more" between positions, and a position may ADD an element (a badge, an accent bar, a button) as long as the surface it lands on already renders. ("How should an invalid card read?")
The approach shape is the reason dial exists. Dial is not a tight/tighter widget, and the approach shape must not collapse into magnitude.
**No AskUserQuestion anywhere in this flow - never, at any step, including every exit.** Dial's entire conversation is inline prose and the user clicking letters in their own browser.
Step 0: The degradation ladder
Five rungs, checked in order. The session runs on the first rung that matches:
- **(a) No dev server and no discoverable way to start one** -> NO offer is made at all; the conversation continues normally. Dial without a live surface is a contradiction.
- **(b) Runnable but not running** -> starting it folds into the offer line itself ("I'll start the dev server and open it in a separate window") - never a separate question.
- **(c) Running** -> proceed.
- **(d) No `.craft/` directory** -> full dial, no detents: candidates come without token names, `dials-capture.sh` is NEVER called, and init is mentioned only after the user has landed on a choice - never before, never as a precondition.
- **(e) `.craft/` present but no visual values in `tokens.yaml`** -> candidates derive from live computed styles (Step 5's fallback), and the exit offers to write the implicit scale into `tokens.yaml`.
Step 1: The offer
The offer is ONE ignorable inline line, spoken only AFTER the substantive answer the user actually asked for. It names the candidates in dial's own idiom and carries the mechanics in the same breath:
> "I can dial that in live - gap-md, gap-lg, or gap-xl. I'll open it in a separate window - you may need to sign in there once. Otherwise moving on."
Rules:
- Answer first. "Why does that pill look so loud?" gets the mechanism explained, THEN the offer. An offer that preempts the reply makes the tool feel like it is hunting for reasons to run.
- An already-decided value ("make that gap 24") is a tweak, permanently - no dial offer at any point.
- The mechanics clause ("separate window... sign in once") is said BEFORE the browser opens, so the fresh-profile window and any login wall are expected beats, not surprises.
- Ignoring the offer is an answer. Continue the conversation; never re-offer the same dial.
Step 2: Open the surface
Open the surface in the dial browser (rung (b): start the server first, as promised in the offer). The browser craft drives is a fresh Chrome with its own profile - it carries none of the user's cookies.
Step 3: The login beat
On any surface behind auth, the fresh profile lands on a login screen. This is a NUMBERED STEP, not an error branch: detect it, name it plainly, and wait -
> "That's the login screen - sign in there and tell me when you're through."
The session persists for the rest of the dial, so this costs one login per session at most. Dial never requires a remote-debugging port or any browser setup from the user - one login is the whole price.
Step 4: Measure
Run CLEAR first, unconditionally - a stale dial from an earlier session may have left residue, and CLEAR is idempotent on a clean page. Then MEASURE the surface (both operations from `dial-inject.md`): current computed values for the property in question, bounding rect of the first visible match. The visibility rule applies - never read the hidden face of a responsive page.
Step 5: Derive the candidates
Read `.craft/design/tokens.yaml` when it exists and carries relevant visual values; positions that land on the scale get their token name as metadata. When tokens are absent or silent on this property (rungs (d)/(e)), derive from the live computed styles - the page itself is the scale.
**The candidate rules. These are the deliverable - state them to yourself and obey them:**
- **Never let every position be timid.** On a magnitude dial, the last position is a reach that COMMITS to the change rather than nudging it - moving margins AND shrinking the search field AND quieting the loud pill, not two margins moved by 4px. On an approach dial, at least one treatment is genuinely louder or more structural than the safe one - a ring plus a left bar next to a lone asterisk. A dial where every option is a small variation on the current state is the failure mode that makes the user pick nothing and feel the tool wasted their time.
- **The approach shape is first-class and must not collapse into magnitude.** "How should this read?" gets four different ideas, not four sizes of one idea.
- **A position is never blunted just to keep every value named.** On-scale or off-scale is downstream of what the position needs - the rule is deliberately NOT "always include an off-scale option," and never "trim the reach to the nearest token."
- **2-4 positions, letters running as far as they need.** Four is real - a four-treatment dial has shipped and the user chose D.
- **Letters are the handle; token names and pixels are metadata.** The user says "C, but a little looser" - nobody says "option gap-xl."
Per-position hierarchy, strongest to weakest: letter -> intent word -> token name -> measured px.
Step 6: Inject
Run INJECT from `dial-inject.md`: candidate CSS keyed off `html[data-craft-dial]`, the panel as body's last child, position A active. Tell the user ONCE, when the panel lands:
> "Changes are live in the page only - don't refresh until we're
Read more
Dial Flow
The full dial session: offer through teardown. Injection payloads (MEASURE, INJECT, TOGGLE, CLEAR) are defined in `${CLAUDE_PLUGIN_ROOT}/commands/references/dial-inject.md` - read it before Step 4 and hold it for the session.
Two shapes, both first-class, neither the default:
- **Magnitude** - one property, different amounts. Ordered: current / conservative / reach. Spacing, size, weight, timing. ("The gaps are too loose.")
- **Approach** - one goal, different treatments. Unordered - there is no "more" between positions, and a position may ADD an element (a badge, an accent bar, a button) as long as the surface it lands on already renders. ("How should an invalid card read?")
The approach shape is the reason dial exists. Dial is not a tight/tighter widget, and the approach shape must not collapse into magnitude.
**No AskUserQuestion anywhere in this flow - never, at any step, including every exit.** Dial's entire conversation is inline prose and the user clicking letters in their own browser.
Step 0: The degradation ladder
Five rungs, checked in order. The session runs on the first rung that matches:
- **(a) No dev server and no discoverable way to start one** -> NO offer is made at all; the conversation continues normally. Dial without a live surface is a contradiction.
- **(b) Runnable but not running** -> starting it folds into the offer line itself ("I'll start the dev server and open it in a separate window") - never a separate question.
- **(c) Running** -> proceed.
- **(d) No `.craft/` directory** -> full dial, no detents: candidates come without token names, `dials-capture.sh` is NEVER called, and init is mentioned only after the user has landed on a choice - never before, never as a precondition.
- **(e) `.craft/` present but no visual values in `tokens.yaml`** -> candidates derive from live computed styles (Step 5's fallback), and the exit offers to write the implicit scale into `tokens.yaml`.
Step 1: The offer
The offer is ONE ignorable inline line, spoken only AFTER the substantive answer the user actually asked for. It names the candidates in dial's own idiom and carries the mechanics in the same breath:
> "I can dial that in live - gap-md, gap-lg, or gap-xl. I'll open it in a separate window - you may need to sign in there once. Otherwise moving on."
Rules:
- Answer first. "Why does that pill look so loud?" gets the mechanism explained, THEN the offer. An offer that preempts the reply makes the tool feel like it is hunting for reasons to run.
- An already-decided value ("make that gap 24") is a tweak, permanently - no dial offer at any point.
- The mechanics clause ("separate window... sign in once") is said BEFORE the browser opens, so the fresh-profile window and any login wall are expected beats, not surprises.
- Ignoring the offer is an answer. Continue the conversation; never re-offer the same dial.
Step 2: Open the surface
Open the surface in the dial browser (rung (b): start the server first, as promised in the offer). The browser craft drives is a fresh Chrome with its own profile - it carries none of the user's cookies.
Step 3: The login beat
On any surface behind auth, the fresh profile lands on a login screen. This is a NUMBERED STEP, not an error branch: detect it, name it plainly, and wait -
> "That's the login screen - sign in there and tell me when you're through."
The session persists for the rest of the dial, so this costs one login per session at most. Dial never requires a remote-debugging port or any browser setup from the user - one login is the whole price.
Step 4: Measure
Run CLEAR first, unconditionally - a stale dial from an earlier session may have left residue, and CLEAR is idempotent on a clean page. Then MEASURE the surface (both operations from `dial-inject.md`): current computed values for the property in question, bounding rect of the first visible match. The visibility rule applies - never read the hidden face of a responsive page.
Step 5: Derive the candidates
Read `.craft/design/tokens.yaml` when it exists and carries relevant visual values; positions that land on the scale get their token name as metadata. When tokens are absent or silent on this property (rungs (d)/(e)), derive from the live computed styles - the page itself is the scale.
**The candidate rules. These are the deliverable - state them to yourself and obey them:**
- **Never let every position be timid.** On a magnitude dial, the last position is a reach that COMMITS to the change rather than nudging it - moving margins AND shrinking the search field AND quieting the loud pill, not two margins moved by 4px. On an approach dial, at least one treatment is genuinely louder or more structural than the safe one - a ring plus a left bar next to a lone asterisk. A dial where every option is a small variation on the current state is the failure mode that makes the user pick nothing and feel the tool wasted their time.
- **The approach shape is first-class and must not collapse into magnitude.** "How should this read?" gets four different ideas, not four sizes of one idea.
- **A position is never blunted just to keep every value named.** On-scale or off-scale is downstream of what the position needs - the rule is deliberately NOT "always include an off-scale option," and never "trim the reach to the nearest token."
- **2-4 positions, letters running as far as they need.** Four is real - a four-treatment dial has shipped and the user chose D.
- **Letters are the handle; token names and pixels are metadata.** The user says "C, but a little looser" - nobody says "option gap-xl."
Per-position hierarchy, strongest to weakest: letter -> intent word -> token name -> measured px.
Step 6: Inject
Run INJECT from `dial-inject.md`: candidate CSS keyed off `html[data-craft-dial]`, the panel as body's last child, position A active. Tell the user ONCE, when the panel lands:
> "Changes are live in the page only - don't refresh until we're
Stop Vibing. Start Crafting. Claude Code plugin: guided + controlled development orchestration harness with built-in workflow + state management, for designing + building durable, production-ready software through the entire product lifecycle - new projects
Repo: drobins25/craft
Other commands on craft.
- /craft-analyze
Post-cycle analysis — QA, UX, Creative, and Style audits using MCP browser tools.
Open command - /craft-ask
Consult a craft agent. Routes your question to the best mind in the workshop - not a menu, a recommendation.
Open command - /craft-become
Agent crystallization command. Studies a tool, role, or person and produces a portable 9-section agent that inhabits the domain - with beliefs, scar tissue, and instincts.
Open command - /craft-cycle-assign
Move a story from backlog to a cycle.
Open command - /craft-cycle-complete
Complete a cycle. Triggers reflection if pending learnings, then archives.
Open command - /craft-cycle-design
Design a cycle — create new cycles with planned stories, detail existing planning cycles, or quick-sketch a roadmap. Detects planning docs in .craft/planning/ and sources the cycle from them when relevant.
Open command

