Decide: Structured Decision Configurator
Generate interactive decision configurators that transform complex trade-off analysis into explorable interfaces. Presents options as cards with visual hierarchy, automatic filtering, cascading dependencies, and live cost tracking.
When to Use /decide
Use this skill when decisions have:
- •3+ options with meaningful trade-offs
- •Dollar amounts to compare
- •Cascading dependencies (choice A eliminates options in choice B)
- •Multiple dimensions to evaluate (cost, quality, risk)
Don't use for:
- •Binary yes/no decisions → use AskUserQuestion
- •Simple 2-option choices → use AskUserQuestion
- •Decisions already made → just document them
Decision Sources
The skill can extract decision points from three sources:
- •
Research directories —
/decide .claude/research/DeepResearch_Auth_2026-02-11- •Parses provider reports (openai.md, perplexity.md, gemini.md)
- •Extracts competing approaches and trade-offs
- •Links to cited sources
- •
MASTER_PLAN.md context —
/decide plan- •Extracts decision points from "Architectural Decisions" section
- •Pulls requirements from "Requirements" section
- •Associates DEC-IDs with plan phases
- •
Conversation context —
/decide monitor purchase decision- •Analyzes recent conversation history
- •Identifies options, constraints, and trade-offs discussed
- •Generates from requirements stated in conversation
Implementation Phases
Phase 1: Identify Decision Source
If argument is a filesystem path:
- •Check if it's a research directory (.claude/research/DeepResearch_*)
- •Look for report.md, openai.md, perplexity.md, gemini.md
- •Extract decision points from research findings
If argument is "plan":
- •Read {project_root}/MASTER_PLAN.md
- •Extract from "Architectural Decisions" section
- •Map DEC-IDs to options
- •Pull constraints from Requirements section
If argument is topic/question:
- •Analyze recent conversation (last 5-10 messages)
- •Identify options mentioned, trade-offs discussed
- •Extract constraints and requirements from conversation
If no source is clear:
- •Ask user: "I found these potential decision sources: [list]. Which should I use?"
Phase 2: Decompose Decisions
For each decision source, identify:
- •
Steps — Sequential decision points (e.g., "Choose auth method" → "Choose database" → "Choose deployment")
- •Each step has: title, subtitle, DEC-ID (if from plan), info box (optional context)
- •Steps should flow logically — dependencies become filters
- •
Options — Alternatives within each step
- •Each option has: title, badge, price, specs (pros/cons), tags, links
- •Mark recommended option (if clear from research/plan)
- •Mark eliminated options (if constraints rule them out)
- •
Filtering logic — Cascading constraints
- •"If user picks 5K resolution, hide 4K monitors"
- •"If user picks quantity=3, show triple-arm option"
- •Document as
filterBy(data-based) orvisibleWhen(state-based)
- •
Cost tracking — Live impact bar
- •Price-based: monitors ($799 × quantity) + arms ($398) + cables ($30 × quantity)
- •
Summary & Export — Final output
- •Grid items: "Your monitor: ASUS ProArt PA27JCV", "Total cost: ~$2,795"
- •Action items: setup instructions, next steps
- •Export: JSON blob with DEC-IDs and selected options
Phase 3: Generate Config JSON
Write decision-config.json following the schema. The config is the single source of truth for the configurator. The build script injects it verbatim into the HTML template.
Reference the fixtures as examples:
- •
Purchase decision pattern — See
fixtures/monitor-setup.json:- •
meta.type: "purchase" - •Price-based options with dollar amounts
- •Impact bar with price × quantity math
- •Buy links in summary
- •Info boxes with domain-specific guidance
- •
- •
Technical decision pattern — See
fixtures/tech-stack.json:- •
meta.type: "technical" - •Documentation links instead of buy links
- •Export enabled with DEC-IDs
- •
Key config patterns:
- •
filterBy: Filter options in step B based on data field from selected option in step A
json{ "id": "monitor", "filterBy": { "dataField": "tier", "matchStep": "priority" } }Meaning: "Show only monitors where option.data.tier matches the selected priority option's ID"
- •
visibleWhen: Show/hide option based on exact state match
json{ "id": "triple-arm", "visibleWhen": { "step": "quantity", "equals": "qty-3" } }Meaning: "Show this arm option only when step 'quantity' has option 'qty-3' selected"
- •
impactBar.items: Dynamic cost calculation
json{ "label": "Monitors", "fromStep": "monitor", "multiplyByStep": "quantity" }Meaning: "Get price from selected monitor, multiply by quantity value"
When generating config:
- •Start from one of the fixture examples as a template
- •Replace domain-specific data (monitors → auth methods, prices → your domain)
- •Preserve the structure: meta, steps, impactBar, summary, research (if applicable)
- •Validate against schema mentally before writing
Write the config to decision-config.json in the working directory (or user-specified path).
Phase 4: Build and Serve
Run the build script with --serve to start a local server. This is required — the Confirm button POSTs decisions back to the server, which writes them to decisions.json on disk.
python3 ~/.claude/skills/decide/scripts/build.py decision-config.json --serve
CRITICAL: Run this with run_in_background: true so you can continue operating while the user interacts with the configurator. Set timeout: 600000 (10 minutes).
The script will:
- •Validate config
- •Build HTML with config injected
- •Start HTTP server on a random port (localhost only)
- •Open
http://localhost:{port}/in browser - •Print
Decisions will be saved to: {cwd}/decisions.json - •Wait for the user to click Confirm
- •When Confirm is clicked, write
decisions.jsonand print>>> DECISIONS CONFIRMED
Flags:
- •
--serve— start local server (primary mode, enables auto-submit) - •
--open— open as file:// (fallback, clipboard-only, no auto-submit) - •
--decisions-out PATH— custom path for decisions.json output
Phase 5: Report Back & Wait for Decisions
Tell the user:
Generated decision configurator — opening in browser.
Server running at http://localhost:{port}/
The configurator presents {N} decision steps with {M} total options.
Make your selections, then click "Confirm Decisions" — your choices will be submitted automatically.
Then wait for the user to say they're done (or check the background task for the >>> DECISIONS CONFIRMED message).
Phase 6: Read Confirmed Decisions
When the user confirms, the server writes decisions.json to disk. Read it directly.
Method 1: Read from file (primary — works with --serve)
cat decisions.json
Or use the Read tool on the decisions.json path that the server printed at startup. This is the default path — {cwd}/decisions.json unless --decisions-out was specified.
Check the background task output for the >>> DECISIONS CONFIRMED line to know when the file is ready. If the user says "done" but the file doesn't exist yet, tell them: "Please click the green 'Confirm Decisions' button in the configurator first."
Method 2: Chrome extension (if available)
If browser automation tools are available (mcp__claude-in-chrome__*):
// Via javascript_tool on the configurator tab: JSON.stringify(window.__DECISIONS__)
Method 3: User pastes from clipboard
Fallback for --open (file://) mode where the server isn't running. The Confirm button copies JSON to clipboard.
Phase 7: Integrate Decisions
Once you have the decisions JSON, parse it and take concrete action. The JSON looks like:
{
"decisions": {
"auth-method": {
"decId": "DEC-AUTH-001",
"selected": "jwt-pkce",
"title": "JWT + PKCE Flow",
"rationale": "Stateless, scales horizontally"
}
},
"timestamp": "2026-02-11T14:30:00Z"
}
Action depends on the invoking context:
7a. Invoked from Planner (most common)
Return the parsed decisions to the calling Planner agent. The Planner will:
- •Write each decision into
### Planned Decisionsin MASTER_PLAN.md:code- DEC-AUTH-001: JWT + PKCE Flow — Stateless, scales horizontally — Addresses: REQ-P0-001
- •Populate phase
**Decision IDs:**fields with the confirmed DEC-IDs - •Continue to Phase 3 (Issue Decomposition) with user-validated decisions
To enable this, output the decisions as a structured block the Planner can parse:
CONFIRMED DECISIONS:
- DEC-AUTH-001 (auth-method): JWT + PKCE Flow — "Stateless, scales horizontally"
- DEC-DATA-001 (database): PostgreSQL + Prisma — "Type-safe queries with Prisma Client"
- DEC-DEPLOY-001 (deployment): Docker + Fly.io — "Full control over runtime environment"
SOURCE: configurator confirmed at {timestamp}
7b. Invoked standalone
Present the decisions and take the next step:
- •Show what was chosen — summarize each decision with DEC-ID, selection, and rationale
- •If MASTER_PLAN.md exists — offer to update it:
- •Read the existing plan
- •Find the
### Planned Decisionssections - •Replace or append the confirmed decisions using the DEC-ID as the key
- •Write the updated plan
- •If no plan exists — offer to:
- •Create a new MASTER_PLAN.md with these decisions as the Architectural Decisions section
- •Start implementation directly based on the choices
- •If this was a purchase decision — compile the buy list with links and totals from the selected options
7c. Invoked for purchase decisions (no plan context)
For purchase decisions (meta.type = "purchase"), skip plan integration. Instead:
- •Present the final shopping list with prices and buy links
- •Offer: "Want me to open the buy links in your browser?"
- •Save the decisions to
{cwd}/decisions.jsonfor reference
Always end with forward motion — never leave decisions hanging without a next action.
Refinement workflow: If the user wants to adjust after confirming:
- •User requests change: "Add a fourth option" or "change the auth recommendation"
- •Read and update decision-config.json
- •Re-run
python3 ~/.claude/skills/decide/scripts/build.py decision-config.json --output configurator.html --open - •User re-confirms in the refreshed configurator
- •Re-read decisions (Phase 6) and re-integrate (Phase 7)
Config JSON Schema Reference
The schema is defined in schema/decision-config.schema.json. Key fields:
meta (required)
- •
title(string, required) — Configurator title - •
subtitle(string, optional) — Subtitle/description - •
type(enum, required) — "purchase" | "technical" | "implementation" | "configuration"- •Controls theme color (indigo/purple/teal/blue)
- •
researchDir(string, optional) — Path to research directory - •
planContext(object, optional) — { masterPlan, phase, requirements[] }
steps[] (required, min 1)
- •
id(string, required) — Unique step identifier - •
title(string, required) — Step title - •
subtitle(string, optional) — Step subtitle - •
decId(string, optional) — DEC-ID from MASTER_PLAN.md - •
filterBy(object, optional) — { dataField, matchStep } - •
infoBox(object, optional) — { html, variant: "default" | "critical" | "warning" } - •
options[](array, required, min 1) — Options for this step
options[] (within steps)
- •
id(string, required) — Unique option identifier - •
title(string, required) — Option title - •
badge(object, optional) — { text, color } - •
recommended(bool, default false) — Show "RECOMMENDED" ribbon - •
eliminated(bool, default false) — Gray out and disable - •
price(object, optional) — { amount: number, label: string } - •
specs[](array, optional) — Bullet points- •Each spec: { text, type: "highlight" | "warning" | "neutral" }
- •
tags[](array, optional) — Tags with ok/not-ok states- •Each tag: { text, ok: bool }
- •
links[](array, optional) — Resource links- •Each link: { label, url, detail }
- •
data(object, optional) — Arbitrary data for filtering - •
visibleWhen(object, optional) — { step, equals }
impactBar (optional)
- •
items[](array, required if impactBar present)- •Each item: { label, fromStep?, multiplyByStep?, perUnit?, approximate: bool }
- •
totalLabel(string, optional, default "Total") - •
prefix(string, optional, default "$")
summary (optional)
- •
title(string, required if summary present) - •
gridItems[](array, optional) — Summary grid- •Each item: { label, template, highlight: bool }
- •Templates use {stepId.field} syntax: {monitor.title}, {total}
- •
actions[](array, optional) — Action items- •Each action: { text, critical: bool, condition?: string }
- •
footer(object, optional) — { html } - •
export(object, optional) — { enabled: bool, filename, includeDecIds: bool }
research (optional)
- •
summary(string, optional) — Executive summary from research - •
sources[](array, optional) — Research sources- •Each source: { provider, title, content, citations[] }
Fixture Examples (Inline Reference)
1. Purchase Decision: Monitor Setup
{
"meta": {
"title": "Monitor Setup Configurator",
"subtitle": "Triple-checked buying guide for Mac workstation",
"type": "purchase"
},
"steps": [
{
"id": "priority",
"title": "What matters most?",
"subtitle": "This determines your resolution tier",
"options": [
{
"id": "5k",
"title": "Maximum Text Crispness",
"badge": { "text": "218 PPI", "color": "green" },
"recommended": true,
"price": { "amount": 0, "label": "5K Resolution" },
"specs": [
{ "text": "218 PPI — native 2x Retina on macOS", "type": "highlight" },
{ "text": "Zero interpolation, zero scaling artifacts", "type": "highlight" }
],
"data": { "tier": "5k" }
},
{
"id": "4k",
"title": "Good Text, Great Value",
"badge": { "text": "163 PPI", "color": "amber" },
"price": { "amount": 0, "label": "4K Resolution" },
"specs": [
{ "text": "163 PPI — requires fractional macOS scaling", "type": "neutral" },
{ "text": "Subtle font softness possible", "type": "warning" }
],
"data": { "tier": "4k" }
}
],
"infoBox": {
"html": "<strong>For astigmatism:</strong> 5K is dramatically crisper.",
"variant": "critical"
}
},
{
"id": "monitor",
"title": "Choose your monitor",
"filterBy": { "dataField": "tier", "matchStep": "priority" },
"options": [
{
"id": "asus-5k",
"title": "ASUS ProArt PA27JCV",
"badge": { "text": "5K • BEST VALUE", "color": "green" },
"recommended": true,
"price": { "amount": 799, "label": "per monitor" },
"specs": [
{ "text": "5120 x 2880 — 218 PPI", "type": "highlight" },
{ "text": "99% DCI-P3, Delta E < 2", "type": "highlight" }
],
"links": [
{ "label": "Amazon", "url": "https://amazon.com/...", "detail": "Ships to 20002" }
],
"data": { "tier": "5k" }
}
]
}
],
"impactBar": {
"items": [
{ "label": "Monitors", "fromStep": "monitor", "multiplyByStep": "quantity" },
{ "label": "Arms", "fromStep": "arms" },
{ "label": "Cables", "perUnit": 30, "multiplyByStep": "quantity", "approximate": true }
],
"totalLabel": "Total Setup Cost",
"prefix": "$"
},
"summary": {
"title": "Your Setup — Ready to Buy",
"gridItems": [
{ "label": "Monitors", "template": "{quantity.value}x {monitor.title}", "highlight": false },
{ "label": "Total Cost", "template": "${total}", "highlight": true }
],
"export": { "enabled": false }
}
}
2. Technical Decision: Tech Stack
{
"meta": {
"title": "Authentication & Database Decisions",
"subtitle": "Choose your tech stack for the auth microservice",
"type": "technical",
"planContext": {
"masterPlan": "MASTER_PLAN.md",
"phase": "Phase 1: Core Authentication",
"requirements": ["REQ-P0-001", "REQ-P0-002"]
}
},
"steps": [
{
"id": "auth-method",
"title": "Choose authentication method",
"decId": "DEC-AUTH-001",
"options": [
{
"id": "jwt-pkce",
"title": "JWT + PKCE Flow",
"badge": { "text": "Modern", "color": "purple" },
"recommended": true,
"specs": [
{ "text": "Stateless, scales horizontally", "type": "highlight" },
{ "text": "No server-side session storage needed", "type": "highlight" },
{ "text": "Requires careful token rotation strategy", "type": "warning" }
],
"links": [
{ "label": "RFC 7636 (PKCE)", "url": "https://...", "detail": "OAuth 2.0 extension" }
]
},
{
"id": "session-based",
"title": "Session-Based Auth",
"badge": { "text": "Traditional", "color": "blue" },
"specs": [
{ "text": "Simple to implement", "type": "highlight" },
{ "text": "Requires sticky sessions or shared state", "type": "warning" }
]
}
]
},
{
"id": "database",
"title": "Choose database",
"decId": "DEC-DATA-001",
"options": [
{
"id": "postgres-prisma",
"title": "PostgreSQL + Prisma",
"recommended": true,
"specs": [
{ "text": "Type-safe queries with Prisma Client", "type": "highlight" },
{ "text": "Built-in migration system", "type": "highlight" }
]
}
]
}
],
"impactBar": {
"items": [
{ "label": "Auth", "fromStep": "auth-method" },
{ "label": "Database", "fromStep": "database" }
],
"totalLabel": "Total",
"prefix": ""
},
"summary": {
"title": "Your Tech Stack",
"gridItems": [
{ "label": "Auth Method", "template": "{auth-method.title}", "highlight": false },
{ "label": "Database", "template": "{database.title}", "highlight": false },
{ "label": "Total", "template": "{total}", "highlight": true }
],
"export": {
"enabled": true,
"filename": "tech-decisions.json",
"includeDecIds": true
}
}
}
Integration with Planner
The /decide skill is invoked by the Planner during Phase 2 (Architecture Design). The full round-trip:
Step 1: Planner invokes /decide
Planner Phase 2, Step 2 (Research Gate): → Identifies 3+ decisions with trade-offs → Invokes: /decide plan → Skill generates configurator, opens in browser → Skill tells user to click "Confirm Decisions" when done → Skill WAITS for user to return
Step 2: User interacts in browser
User explores options, sees trade-offs, makes selections, clicks "Confirm Decisions".
- •Decisions stored in
window.__DECISIONS__(for Chrome extension) - •Decisions auto-copied to clipboard (for paste fallback)
- •Green banner tells user to return to Claude Code
Step 3: Skill reads decisions back (Phase 6)
User says "done" or "confirmed" → Skill reads window.__DECISIONS__ via Chrome extension → OR asks user to paste from clipboard → Parses the decisions JSON
Step 4: Skill outputs structured block (Phase 7a)
CONFIRMED DECISIONS: - DEC-AUTH-001 (auth-method): JWT + PKCE Flow — "Stateless, scales horizontally" - DEC-DATA-001 (database): PostgreSQL + Prisma — "Type-safe queries with Prisma Client" - DEC-DEPLOY-001 (deployment): Docker + Fly.io — "Full control over runtime environment" SOURCE: configurator confirmed at 2026-02-11T14:30:00Z
Step 5: Planner writes decisions into MASTER_PLAN.md
The Planner receives the structured block and writes each decision into the plan:
### Planned Decisions - DEC-AUTH-001: JWT + PKCE Flow — Stateless, scales horizontally — Addresses: REQ-P0-001, REQ-P0-003 - DEC-DATA-001: PostgreSQL + Prisma — Type-safe queries with Prisma Client — Addresses: REQ-P0-002 - DEC-DEPLOY-001: Docker + Fly.io — Full control over runtime environment — Addresses: REQ-P0-004
The Addresses: field comes from the config's meta.planContext.requirements array, mapped by the Planner based on which requirements each decision satisfies.
Decisions JSON format
{
"decisions": {
"auth-method": {
"decId": "DEC-AUTH-001",
"selected": "jwt-pkce",
"title": "JWT + PKCE Flow",
"rationale": "Stateless, scales horizontally"
},
"database": {
"decId": "DEC-DATA-001",
"selected": "postgres-prisma",
"title": "PostgreSQL + Prisma",
"rationale": "Type-safe queries with Prisma Client"
}
},
"timestamp": "2026-02-11T14:23:45Z"
}
What happens after
The Planner proceeds to Phase 2 Step 3 (Finalize decisions) with the user's confirmed selections, then Phase 3 (Issue Decomposition) and Phase 4 (MASTER_PLAN.md generation). The DEC-IDs from /decide carry through to @decision annotations in code, creating full traceability: User selection → DEC-ID in plan → @decision in code.
Error Handling
Config validation fails:
- •Show validation error with specific field missing
- •Point to schema file and fixture examples
- •Offer to fix automatically if error is clear
Build script not found:
- •Check ~/.claude/skills/decide/scripts/build.py exists
- •If missing, tell user to complete /decide skill installation
No decision source found:
- •"I couldn't find decisions in [source]. Can you point me to: (1) research directory, (2) MASTER_PLAN.md with decisions section, or (3) describe the decision in chat?"
Research directory exists but no reports:
- •"Research directory exists but I found no reports. Expected report.md, openai.md, perplexity.md, or gemini.md. Should I skip research context?"
Example Invocations
/decide .claude/research/DeepResearch_Auth_2026-02-11 → Generates configurator from deep research findings on auth methods /decide plan → Generates configurator from current MASTER_PLAN.md architectural decisions /decide monitor purchase decision → Analyzes recent conversation about monitor purchasing, generates configurator /decide "nextjs vs remix" after research → Looks for recent research on Next.js vs Remix, generates framework comparison configurator
Write Context Summary (MANDATORY — do this LAST)
Write a compact result summary so the parent session receives key findings:
cat > .claude/.skill-result.md << 'SKILLEOF' ## Decision Configurator Result **Decisions made:** [n] **Confirmed DEC-IDs:** [DEC-XXX-001, DEC-XXX-002, ...] ### Decisions Summary 1. [DEC-ID]: [Choice made] — [1-line rationale] 2. [DEC-ID]: [Choice made] — [1-line rationale] ### Pending - [Any decisions deferred or needing follow-up] SKILLEOF
Keep under 2000 characters. This is consumed by a hook — the parent session will see it automatically.
Notes
- •The configurator is a single HTML file — no build tools, no npm, no server
- •It works offline after generation
- •Users can save and share the HTML file
- •The config JSON is embedded directly in the HTML (view source to see it)
- •All styling is scoped within the file — no external CSS
- •JavaScript is vanilla ES6 — no frameworks
This skill enables the Planner to present complex trade-off analysis as explorable interfaces, making architectural decisions tangible and user-driven.