Agent skill

decide

Generate an interactive decision configurator from research or plan analysis. Presents options as explorable cards with trade-offs, costs, and filtering. Integrates with Planner to collect DEC-ID decisions.

Stars 173
Forks 28

Install this agent skill to your Project

npx add-skill https://github.com/juanandresgs/claude-ctrl/tree/main/skills/decide

SKILL.md

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:

  1. 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
  2. MASTER_PLAN.md context/decide plan

    • Extracts decision points from "Architectural Decisions" section
    • Pulls requirements from "Requirements" section
    • Associates DEC-IDs with plan phases
  3. 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:

  1. 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
  2. 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)
  3. 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) or visibleWhen (state-based)
  4. Cost tracking — Live impact bar

    • Price-based: monitors ($799 × quantity) + arms ($398) + cables ($30 × quantity)
  5. 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:

  1. 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
  2. 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:

  1. Start from one of the fixture examples as a template
  2. Replace domain-specific data (monitors → auth methods, prices → your domain)
  3. Preserve the structure: meta, steps, impactBar, summary, research (if applicable)
  4. 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.

bash
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:

  1. Validate config
  2. Build HTML with config injected
  3. Start HTTP server on a random port (localhost only)
  4. Open http://localhost:{port}/ in browser
  5. Print Decisions will be saved to: {cwd}/decisions.json
  6. Wait for the user to click Confirm
  7. When Confirm is clicked, write decisions.json and 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)

bash
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__*):

javascript
// 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:

json
{
  "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:

  1. Write each decision into ### Planned Decisions in MASTER_PLAN.md:
    - DEC-AUTH-001: JWT + PKCE Flow — Stateless, scales horizontally — Addresses: REQ-P0-001
    
  2. Populate phase **Decision IDs:** fields with the confirmed DEC-IDs
  3. 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:

  1. Show what was chosen — summarize each decision with DEC-ID, selection, and rationale
  2. If MASTER_PLAN.md exists — offer to update it:
    • Read the existing plan
    • Find the ### Planned Decisions sections
    • Replace or append the confirmed decisions using the DEC-ID as the key
    • Write the updated plan
  3. 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
  4. 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:

  1. Present the final shopping list with prices and buy links
  2. Offer: "Want me to open the buy links in your browser?"
  3. Save the decisions to {cwd}/decisions.json for reference

Always end with forward motion — never leave decisions hanging without a next action.

Refinement workflow: If the user wants to adjust after confirming:

  1. User requests change: "Add a fourth option" or "change the auth recommendation"
  2. Read and update decision-config.json
  3. Re-run python3 ~/.claude/skills/decide/scripts/build.py decision-config.json --output configurator.html --open
  4. User re-confirms in the refreshed configurator
  5. 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

json
{
  "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

json
{
  "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:

markdown
### 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

json
{
  "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:

bash
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.

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results