Skill

skill-builder

Use BEFORE creating or updating any skill OR command - decomposes goal into forward steps via backward reasoning

From cat
Install
1
Run in your terminal
$
npx claudepluginhub cowwoc/cat --plugin cat
Tool Access

This skill uses the workspace's default tool permissions.

Skill Content

Skill Builder

Purpose

Design or update skills and commands by reasoning backward from the goal to required preconditions, then converting to forward-execution steps.


When to Use

  • Creating a new skill or command
  • Updating an existing skill or command that has unclear or failing steps
  • Any procedure where the goal is clear but the path is not

Note: Both skills/ and commands/ are agent-facing prompt files that define behavior. Use skill-builder for BOTH types.


Core Principle

Backward chaining: Start with what you want to be true, repeatedly ask "what must be true for this?", until you reach conditions you can directly achieve. Then reverse to get executable steps.

GOAL ← requires ← requires ← ... ← ATOMIC_ACTION
                                         ↓
                                    (reverse)
                                         ↓
ATOMIC_ACTION → produces → produces → ... → GOAL

Procedure

Step 1: State the Goal

Write a single, verifiable statement of the desired end state.

Format:

GOAL: [Observable condition that indicates success]

Criteria for good goal statements:

  • Observable: Can be verified by inspection or test
  • Specific: No ambiguity about what "done" means
  • Singular: One condition (decompose compound goals first)

Examples:

GOAL: All right-side │ characters in the box align vertically
GOAL: The function returns the correct sum for all test cases
GOAL: The user sees a confirmation message after submission

Step 2: Backward Decomposition

For each condition (starting with the goal), ask: "What must be true for this?"

Format:

CONDITION: [what we want]
  REQUIRES: [what must be true for the condition]
  REQUIRES: [another thing that must be true]

Rules:

  • Each REQUIRES is a necessary precondition
  • Multiple REQUIRES under one CONDITION means ALL must be true (AND)
  • Continue decomposing until you reach atomic conditions

Atomic condition: A condition that can be directly achieved by a single action or is a given input/fact.

Example decomposition:

GOAL: Right borders align
  REQUIRES: All lines have identical display width
    REQUIRES: Each line follows the formula: width = content + padding + borders
      REQUIRES: padding = max_content - this_content
        REQUIRES: max_content is known
          REQUIRES: display_width calculated for all content items
            REQUIRES: emoji widths handled correctly
              ATOMIC: Use width table (emoji → width mapping)
            REQUIRES: all content items identified
              ATOMIC: List all content strings
        REQUIRES: this_content display_width is known
          (same as above - shared requirement)
      REQUIRES: borders add fixed width (4)
        ATOMIC: Use "│ " prefix (2) and " │" suffix (2)

Step 3: Identify Leaf Nodes

Extract all ATOMIC conditions from the decomposition tree. These are your starting points.

Format:

LEAF NODES (atomic conditions):
1. [First atomic condition]
2. [Second atomic condition]
...

Step 4: Build Dependency Graph

Determine the order in which conditions can be satisfied based on their dependencies.

Rules:

  • A condition can only be satisfied after ALL its REQUIRES are satisfied
  • Conditions with no REQUIRES (leaf nodes) can be done first
  • Multiple conditions at the same level can be done in parallel (or any order)

Format:

DEPENDENCY ORDER:
Level 0 (no dependencies): [atomic conditions]
Level 1 (depends on L0): [conditions requiring only L0]
Level 2 (depends on L1): [conditions requiring L0 and/or L1]
...
Level N: GOAL

Step 5: Extract Reusable Functions

Scan the decomposition tree for patterns that should become functions.

Extract a function when:

  1. Same logic appears multiple times in the tree (even with different inputs)
  2. Recursive structure: The same pattern applies at multiple nesting levels
  3. Reusable calculation: A computation that transforms input → output cleanly

Function identification signals:

Pattern A: Repeated subtree
  REQUIRES: X for item A
    REQUIRES: Y for A
      ATOMIC: Z
  REQUIRES: X for item B       ← Same structure, different input
    REQUIRES: Y for B
      ATOMIC: Z
  → Extract: function X(item) that does Y and Z

Pattern B: Recursive structure
  REQUIRES: process outer container
    REQUIRES: process inner container    ← Same pattern, nested
      REQUIRES: process innermost        ← Same pattern again
  → Extract: function process(container) that calls itself for nested containers

Pattern C: Transform chain
  REQUIRES: result C
    REQUIRES: intermediate B from A
      REQUIRES: input A
  → Extract: function transform(A) → C

Function definition format:

FUNCTIONS:
  function_name(inputs) → output
    Purpose: [what it computes]
    Logic: [derived from the decomposition subtree]
    Used by: [which steps will call this]

Composition rules:

  • Functions can call other functions
  • Order function definitions so dependencies come first
  • For recursive functions, define the base case and recursive case

Deriving logic for variable-length inputs:

When a function operates on a collection of arbitrary length, derive the algorithm by:

  1. Minimum case: Solve for the smallest valid input (often length 1)
  2. Next increment: Solve for length 2 (or next meaningful size)
  3. Generalize: Identify the pattern that extends to length N
Example: max_content_width(contents[])

Length 1: contents = ["Hello"]
  max = display_width("Hello") = 5
  → For single item, max is just that item's width

Length 2: contents = ["Hello", "World!"]
  w1 = display_width("Hello") = 5
  w2 = display_width("World!") = 6
  max = larger of w1, w2 = 6
  → For two items, compare and take larger

Length N: contents = [c1, c2, ..., cN]
  → Pattern: compare each item's width, keep the largest
  → General: max(display_width(c) for c in contents)
Example: build_box(contents[])

Length 1: contents = ["Hi"]
  Lines needed: top border, one content line, bottom border
  Width: display_width("Hi") + 4 = 6
  → Single item: frame around one line

Length 2: contents = ["Hi", "Bye"]
  Lines needed: top, content1, content2, bottom
  Width: max(display_width("Hi"), display_width("Bye")) + 4
  → Two items: both must fit in same width frame

Length N:
  → Pattern: all content lines share same width (the maximum)
  → General: find max width, pad each line to that width, add frame

This technique prevents over-generalization and ensures the algorithm handles edge cases.

Example - Box alignment functions:

FUNCTIONS:
  display_width(text) → integer
    Purpose: Calculate terminal display width of text
    Logic: Sum character widths (emoji=2, others=1)
    Used by: max_content_width, padding calculation

  max_content_width(contents[]) → integer
    Purpose: Find maximum display width among content items
    Logic: max(display_width(c) for c in contents)
    Used by: box_width, padding calculation

  box_width(contents[]) → integer
    Purpose: Calculate total box width including borders
    Logic: max_content_width(contents) + 4
    Used by: border construction, nested box embedding

  build_box(contents[]) → string[]
    Purpose: Construct complete box with aligned borders
    Logic:
      1. mw = max_content_width(contents)
      2. for each content: line = "│ " + content + padding(mw - display_width(content)) + " │"
      3. top = "╭" + "─"×(mw+2) + "╮"
      4. bottom = "╰" + "─"×(mw+2) + "╯"
      5. return [top] + lines + [bottom]
    Used by: outer box construction, nested box construction (recursive)

Step 6: Convert to Forward Steps

Transform the dependency order into executable procedure steps, using extracted functions.

Rules:

  • Start with Level 0 (leaf nodes)
  • Progress through levels toward the goal
  • Each step should be a concrete action, not a state description
  • Call functions instead of repeating logic
  • For recursive operations, the step invokes the function which handles recursion internally
  • Include verification where applicable

Format:

PROCEDURE:
1. [Action to achieve leaf condition 1]
2. [Action to achieve leaf condition 2]
3. Call function_a(inputs) to achieve Level 1 condition
4. For each item: call function_b(item)    ← Function handles repeated application
5. Call function_c(nested_structure)        ← Function handles recursion internally
...
N. [Final action that achieves the GOAL]

VERIFICATION:
- [How to confirm the goal is met]

Composing functions in steps:

# Instead of inline logic:
BAD:  "Calculate width by counting characters and adding 1 for each emoji"
GOOD: "Call display_width(text) to get the terminal width"

# Instead of repeated steps:
BAD:  "Calculate width for item 1, then for item 2, then for item 3..."
GOOD: "For each content item, call display_width(item)"

# Instead of manual recursion:
BAD:  "Build inner box, then embed in outer box, checking alignment..."
GOOD: "Call build_box(contents) - function handles nesting internally"

Step 7: Write the Skill

Structure the skill document with:

  1. Frontmatter: YAML with name and trigger-oriented description
  2. Purpose: The goal statement
  3. Functions: Reusable calculations extracted in Step 5
  4. Procedure: The forward steps from Step 6, calling functions as needed
  5. Verification: How to confirm success

Frontmatter description must be trigger-oriented:

The description tells WHEN to invoke the skill, not just what it does.

Format: "[WHEN to use] - [what it does]"

Examples:
  "MANDATORY: Load BEFORE rendering any box output"
  "Use BEFORE creating or updating any skill - decomposes goal into forward steps"
  "MANDATORY: Use for approval gate reviews - transforms git diff into table"
  "Use when user requests git rebase - provides automatic backup and recovery"

Trigger patterns:

  • MANDATORY: Load BEFORE [action] - Must be loaded before doing something
  • MANDATORY: Use for [situation] - Required for specific scenarios
  • Use BEFORE [action] - Should be used before doing something
  • Use when [condition] - Triggered by a specific situation
  • Use instead of [alternative] - Replaces a dangerous or complex operation

Template Output

---
name: [skill-name]
description: "[WHEN to use] - [what it does]"
---

# [Skill Name]

## Purpose

[Goal statement from Step 1]

---

## Prerequisites

[Any atomic conditions that are external inputs or assumptions]

---

## Functions

List functions in dependency order (functions with no dependencies first).

### function_name(inputs) → output

**Purpose**: [What it computes]

**Definition**:

[Algorithm or formula derived from decomposition]


**Example**:

function_name(example_input) = expected_output


### composed_function(inputs) → output

**Purpose**: [Higher-level operation that uses other functions]

**Definition**:
  1. intermediate = other_function(inputs)
  2. result = transform(intermediate)
  3. return result

### recursive_function(structure) → output

**Purpose**: [Operation that applies to nested structures]

**Definition**:

Base case: if structure is atomic, return direct_result Recursive case:

  1. Process current level
  2. For each nested element: recursive_function(element)
  3. Combine results

---

## Procedure

Steps call functions rather than duplicating logic.

### Step 1: Require pre-computed results (if computation was extracted)

**MANDATORY:** Check context for "PRE-COMPUTED [SKILL-NAME]".

If found:
1. Output the pre-computed content **directly without preamble or commentary**
2. Skip to Step N (output/verification)

**Silent output rule (M194):** When outputting pre-computed content, do NOT:
- Announce "I can see the pre-computed display..."
- Explain "Let me output this exactly as provided..."
- Add any text before the pre-computed content

Simply output the content. The user doesn't need to know about internal computation mechanisms.

If NOT found: **FAIL immediately**.

```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/check-hooks-loaded.sh" "results" "the skill"
if [[ $? -eq 0 ]]; then
  echo "ERROR: Pre-computed results not found."
  echo "Hook precompute-{skill-name}.sh should have provided these."
fi

Output the error and STOP. Do NOT attempt manual computation.

Step 2: [Gather inputs] (only if no extraction)

[Collect data needed by functions]

Step 3: [Apply function]

Call function_name(inputs) to compute [result].

MANDATORY CALCULATION GATE:

Before proceeding, you MUST show:

  1. List each item with its computed value:

    [item]: [computation] = [result]
    
  2. State aggregate if applicable:

    [aggregate] = [value]
    

BLOCKING: Do NOT proceed until calculations are written out.

Step N: [Final assembly / output]

[Combine results to achieve goal]


Verification

  • [Checkable condition that confirms goal is met]

---

## Example 1: Simple Skill (Rectangle Calculator)

**Task**: Create a skill for calculating the area of a rectangle from user input.

### Step 1: Goal

GOAL: Output displays the correct area of the rectangle


### Step 2: Decomposition

GOAL: Output displays correct area REQUIRES: area value is correct REQUIRES: area = width × height REQUIRES: width is a valid number REQUIRES: width input is parsed ATOMIC: Read width from user REQUIRES: parsing succeeds ATOMIC: Validate width is numeric REQUIRES: height is a valid number REQUIRES: height input is parsed ATOMIC: Read height from user REQUIRES: parsing succeeds ATOMIC: Validate height is numeric REQUIRES: output is displayed ATOMIC: Print result to screen


### Step 3: Leaf Nodes

  1. Read width from user
  2. Validate width is numeric
  3. Read height from user
  4. Validate height is numeric
  5. Print result to screen

### Step 4: Dependency Order

Level 0: Read width, Read height Level 1: Validate width (needs width), Validate height (needs height) Level 2: Calculate area = width × height (needs both validated) Level 3: Print result (needs area)


### Step 5: Extract Functions

FUNCTIONS: validate_number(input) → number or error Purpose: Parse and validate numeric input Logic: Parse input; if not positive number, return error Used by: width validation, height validation

Note: This function is identified because validation logic appears twice (for width and height) with identical structure.


### Step 6: Forward Steps

  1. Read width from user
  2. Call validate_number(width); abort if error
  3. Read height from user
  4. Call validate_number(height); abort if error
  5. Calculate area = width × height
  6. Print "Area: {area}"

### Step 7: Resulting Skill

```markdown
# Rectangle Area Calculator

## Purpose

Output displays the correct area of the rectangle.

## Functions

### validate_number(input) → number or error

Parse input and validate it is a positive number.

parsed = parse_as_number(input) if parsed is NaN or parsed <= 0: return error("Must be a positive number") return parsed


## Procedure

### Step 1: Get width
Read width value from user input.

### Step 2: Validate width
Call `validate_number(width)`. If error, display message and stop.

### Step 3: Get height
Read height value from user input.

### Step 4: Validate height
Call `validate_number(height)`. If error, display message and stop.

### Step 5: Calculate
Compute area = width × height.

### Step 6: Display
Output "Area: {area}".

## Verification

- [ ] Output matches expected area for test inputs

Example 2: Function Extraction (Box Alignment)

Task: Create a skill for rendering aligned boxes with emoji support.

Step 1: Goal

GOAL: All right-side │ characters align vertically

Step 2: Decomposition

GOAL: Right borders align
  REQUIRES: All lines have identical display width
    REQUIRES: line_width = content_width + padding + 4 (borders)
      REQUIRES: padding = max_content_width - content_width
        REQUIRES: max_content_width is known
          REQUIRES: display_width calculated for ALL content items  ← Repeated operation
            REQUIRES: emoji widths handled correctly
              ATOMIC: Use width lookup (emoji → 2, other → 1)
        REQUIRES: content_width is known for THIS item
          REQUIRES: display_width calculated for this item          ← Same as above!
      REQUIRES: borders are fixed width (4)
        ATOMIC: Use "│ " prefix + " │" suffix

Step 3: Leaf Nodes

1. Width lookup table (emoji → 2, other → 1)
2. Border constants ("│ " = 2, " │" = 2)

Step 4: Dependency Order

Level 0: Width lookup table, border constants
Level 1: display_width for each content item (uses lookup)
Level 2: max_content_width (uses all display_widths)
Level 3: padding for each item (uses max and item width)
Level 4: construct each line (uses padding)
Level 5: assemble box (uses all lines)

Step 5: Extract Functions

FUNCTIONS:
  display_width(text) → integer
    Purpose: Calculate terminal display width
    Logic: sum(2 if char is emoji else 1 for char in text)
    Used by: max_content_width, padding calculation

  max_content_width(contents[]) → integer
    Purpose: Find widest content item
    Logic: max(display_width(c) for c in contents)
    Used by: padding calculation, border construction

  box_width(contents[]) → integer
    Purpose: Total box width including borders
    Logic: max_content_width(contents) + 4
    Used by: border construction

Step 6: Forward Steps

1. List all content items
2. For each item: call display_width(item)
3. Call max_content_width(contents) to get max
4. For each item: padding = max - display_width(item)
5. Construct each line: "│ " + content + " "×padding + " │"
6. Construct top: "╭" + "─"×(max+2) + "╮"
7. Construct bottom: "╰" + "─"×(max+2) + "╯"
8. Assemble: [top] + lines + [bottom]

Step 7: Resulting Skill

# Box Alignment

## Purpose

All right-side │ characters align vertically.

## Functions

### display_width(text) → integer

Calculate terminal display width of a string.

width = 0 for each char in text: if char in [☑️, 🔄, 🔳, 📊, ...]: width += 2 else: width += 1 return width


### max_content_width(contents[]) → integer

Find maximum display width among all content items.

return max(display_width(c) for c in contents)


### box_width(contents[]) → integer

Calculate total box width including borders.

return max_content_width(contents) + 4


## Procedure

### Step 1: List content

Identify all strings that will appear in the box.

### Step 2: Calculate widths

For each content item, call `display_width(item)`.

### Step 3: Find maximum

Call `max_content_width(contents)`.

### Step 4: Construct lines

For each content:
  padding = max - display_width(content)
  line = "│ " + content + " "×padding + " │"

### Step 5: Construct borders

top = "╭" + "─"×(max+2) + "╮"
bottom = "╰" + "─"×(max+2) + "╯"

### Step 6: Assemble

Output: [top] + [all lines] + [bottom]

## Verification

- [ ] All right │ characters are in the same column

Handling Complex Cases

Multiple Paths (OR conditions)

When a condition can be satisfied by alternative approaches:

CONDITION: User is authenticated
  OPTION A:
    REQUIRES: Valid session token exists
  OPTION B:
    REQUIRES: Valid API key provided

IMPORTANT - Fail-Fast, Not Fallback:

When designing skills with multiple paths, distinguish between:

  1. Legitimate alternatives (user choice): Present options for user to select
  2. Fallback patterns (degraded operation): AVOID - these hide failures
# BAD - Fallback hides hook failure
If pre-computed exists: use it
Else: compute manually (error-prone!)

# GOOD - Fail-fast exposes problems
If pre-computed exists: use it
Else: FAIL with "Hook failed - check precompute-status-display.sh"

Why fail-fast is better:

  • Fallback to manual computation defeats the purpose of extraction
  • Silent degradation makes debugging harder
  • Errors in fallback path are often worse than no output
  • Forces fixing the root cause (broken hook) rather than masking it

Shared Dependencies

When multiple branches require the same condition, note it once and reference it:

REQUIRES: display_width calculated for all items
  (see: emoji width calculation above)

Verification Gates (M191 Prevention)

When a skill has steps that produce intermediate calculations or data that the final output depends on, add verification gates that require showing the intermediate work before proceeding.

Why gates matter: Without explicit gates, agents may:

  • Mentally acknowledge a step without executing it
  • Write approximate output instead of calculated output
  • Skip straight to the final result, causing errors

Identify gate candidates during decomposition:

GOAL: Output is correct
  REQUIRES: Final output uses calculated values    ← Gate candidate
    REQUIRES: Intermediate values are computed
      REQUIRES: Input data is collected

When the decomposition shows a REQUIRES that transforms data (calculates, computes, derives), that transformation should have a gate that makes the result visible.

Gate format:

**MANDATORY CALCULATION GATE (reference):**

Before proceeding to [next step], you MUST show explicit [calculations/results]:

1. **List each [item] with its [derived value]:**

[item1]: [explicit breakdown] = [result] [item2]: [explicit breakdown] = [result]


2. **State the [aggregate value]:**

[aggregate_name] = [value] (from [derivation])


**BLOCKING:** Do NOT [produce output] until these [calculations/results] are written out.
[Explanation of what goes wrong if skipped].

Gate placement in procedure:

  • Place gates AFTER the calculation step, BEFORE the step that uses the results
  • Use "MANDATORY" and "BLOCKING" keywords
  • Reference a mistake ID if the gate prevents a known issue

Example - Box alignment gate:

### Step 3: Calculate maximum width

Call `max_content_width(all_content_items)`.

**MANDATORY CALCULATION GATE (M191):**

Before proceeding to Step 4, you MUST show explicit width calculations:

1. **List each content item with its display_width:**

"Hello 👋": 7 chars + 1 emoji(2) = 8 "World": 5 chars = 5


2. **State max_content_width:**

max_content_width = 8


**BLOCKING:** Do NOT render any box output until calculations are written out.
Hand-writing approximate output without calculation causes alignment errors.

### Step 4: Build output
[Uses the calculated values from Step 3]

No Embedded Box Drawings in Skills (M217)

Critical rule: Skills MUST NOT contain embedded box-drawing examples in their instructions or templates. Embedded boxes cause agents to manually render similar output instead of using handler functions.

Important distinction: This rule applies to skills that output boxes to users. Documentation diagrams in skills that do not produce boxes (e.g., state machine diagrams in tdd-implementation, architecture flowcharts) are acceptable because:

  • They illustrate concepts for human readers, not templates for agent output
  • The agent is not asked to recreate or render them
  • They don't trigger the "copy this pattern" failure mode

The failure pattern:

  1. Skill document shows example box output:
    ╭──────────────────────╮
    │ Example Header       │
    ├──────────────────────┤
    │ Content here         │
    ╰──────────────────────╯
    
  2. Agent sees this pattern and attempts to recreate it manually
  3. Manual rendering produces misaligned, incorrect boxes
  4. Handler functions (which would produce correct output) go unused

Correct approach for skills that produce boxes:

  1. Reference handler functions, not visual examples:

    # BAD - Embedded box causes manual rendering
    Display the result in this format:
    ╭──────────────────────╮
    │ {content}            │
    ╰──────────────────────╯
    
    # GOOD - References function without visual example
    Use `build_box(content)` to render the result.
    The function handles all alignment and border construction.
    
  2. For circle/rating patterns, use lookup tables not examples:

    # BAD - Embedded pattern causes manual typing
    Display ratings like: ●●●●○ (4/5) or ●●○○○ (2/5)
    
    # GOOD - Lookup table with explicit "do not type manually"
    Rating circle patterns (do not hand-type, copy from table):
    - 5 → ●●●●●
    - 4 → ●●●●○
    - 3 → ●●●○○
    - 2 → ●●○○○
    - 1 → ●○○○○
    
  3. For output format documentation, describe structure not rendering:

    # BAD - Shows rendered output
    The status display looks like:
    ╭────────────────────────────────╮
    │ 📊 Progress: [████░░░░] 40%   │
    ╰────────────────────────────────╯
    
    # GOOD - Describes structure, references handler
    The status display contains:
    - Header with emoji and title
    - Progress bar showing percentage
    - All rendering via `build_status_box()` function
    

Verification during skill creation:

  • No box-drawing characters (╭╮╰╯│├┤┬┴┼─) appear in instruction examples
  • No formatted table examples with borders appear in skill text
  • Visual patterns (circles, bars, etc.) use lookup tables with "do not hand-type" warning
  • All display rendering references handler functions by name

Output Artifact Gates (M192 Prevention)

See also: workflow-output.md for clean output standards including pre-computation patterns and subagent batching strategies.

Critical insight: Calculation gates alone are insufficient. When a skill produces structured output (boxes, tables, formatted text), the gate must require showing the exact artifact strings that will appear in the output, not just the numeric calculations.

The failure pattern (M192):

  1. Agent correctly calculates widths, counts, positions
  2. Agent understands the formula for constructing output
  3. Agent re-types the output from memory instead of copying calculated artifacts
  4. Output has subtle errors despite correct calculations

Solution: Add a second gate that requires explicit artifact construction:

### Step 4: Construct lines

For each item, apply the formula and **record the exact result string**:

build_line("📊 Status", 20) = "│ 📊 Status │" (padding: 10) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This exact string goes to output


**MANDATORY BUILD RESULTS GATE (M192):**

Before writing final output, verify:
- [ ] Each artifact (line, cell, row) has an explicit string recorded above
- [ ] Padding/spacing counts are noted in parentheses
- [ ] Final output will COPY these exact strings (no re-typing)

**BLOCKING:** If Step 4 does not contain explicit artifact strings, STOP and complete
Step 4 before proceeding. Re-typing output causes errors even when calculations are correct.

Key distinctions:

Calculation Gate (M191)Artifact Gate (M192)
Shows numeric valuesShows exact output strings
"max_width = 20""│ content │"
Prevents wrong mathPrevents wrong assembly
Required BEFORE constructionRequired AFTER construction, BEFORE output

When to add artifact gates:

  • Output has precise formatting (aligned columns, borders, spacing)
  • Small errors in spacing/padding break the result
  • The construction formula combines multiple values

Recursive Structures

For problems with recursive structure (e.g., nested boxes), the decomposition will show the same pattern at multiple levels. Extract this as a function that can be applied recursively.

Identifying recursive patterns in decomposition:

GOAL: Render nested structure correctly
  REQUIRES: Outer container rendered correctly
    REQUIRES: Inner container rendered correctly        ← Same pattern!
      REQUIRES: Innermost container rendered correctly  ← Same pattern again!
        ATOMIC: Base case - no more nesting

Converting to recursive function:

FUNCTION: render_container(container) → rendered_output
  Base case: if container has no children
    return render_leaf(container)
  Recursive case:
    1. For each child: rendered_child = render_container(child)  ← Recursive call
    2. Combine rendered children with container frame
    3. Return combined result

Order of operations for nested structures:

1. Process innermost elements first (base cases)
2. Work outward, combining results
3. Final step produces the outermost result

This is "inside-out" construction - the decomposition reveals this naturally
because inner elements are REQUIRES for outer elements.

Example - Nested boxes:

Decomposition shows:
  REQUIRES: Outer box contains inner boxes correctly
    REQUIRES: Each inner box is self-consistent
      REQUIRES: Inner box borders align
        (same requirements as any box - recursive!)

Function:
  build_box(contents[]) → string[]
    For each content item:
      if content is itself a box structure:
        inner_lines = build_box(content.items)  ← Recursive call
        add inner_lines to processed_contents
      else:
        add content string to processed_contents
    return construct_box_frame(processed_contents)

Procedure step:
  "Call build_box(root_contents) to construct the complete nested structure"

Extracting Computation to Hook-Based Precomputation (M192/M215 Prevention)

Critical insight: When a skill contains functions that perform deterministic computation (algorithms, formulas, calculations), these MUST be extracted to hooks that run BEFORE the skill. The skill should NEVER invoke scripts directly - this shows Bash tools to users and defeats the purpose of extraction.

The correct pattern (see plugin/hooks/skill_handlers/):

  1. Hook runs automatically when skill is invoked (via UserPromptSubmit or skill handler)
  2. Hook pre-computes ALL possible outputs the skill might need
  3. Hook returns pre-computed content via additionalContext
  4. Skill receives pre-computed content and outputs it directly (no script invocation)

Identify computation candidates during function extraction (Step 5):

For each function identified, ask:
1. Is the output deterministic given the inputs?
2. Could the agent get the wrong result by "thinking" instead of computing?
3. Does the function involve precise formatting, counting, or arithmetic?

If YES to all three → Extract to hook-based precomputation

Computation candidate signals:

SignalExampleWhy Extract?
Counting characters/widthsdisplay_width(text)Agent may miscount emojis
Arithmetic with variablespadding = max - widthAgent may compute incorrectly
Building formatted strings"│ " + content + spaces + " │"Agent may mis-space
Aggregating over collectionsmax(widths)Agent may miss items

Non-candidates (keep in skill):

TypeExampleWhy Keep?
Reasoning/judgment"Identify atomic conditions"Requires understanding
Pattern matching"Find repeated subtrees"Requires semantic analysis
Decision making"Choose appropriate level"Requires context

Anti-pattern (M215): Skill invokes a script after reasoning completes.

# WRONG - Shows Bash tools to users, defeats extraction purpose
1. Skill reasons about content
2. Skill invokes render-output.py via Bash  ← User sees Bash tool
3. Script returns formatted output
4. Skill outputs result

# CORRECT - Hook runs BEFORE skill, user sees nothing
1. Hook detects skill invocation (via UserPromptSubmit or handler)
2. Hook pre-computes ALL possible outputs
3. Hook returns pre-computed content via additionalContext
4. Skill receives pre-computed content, reasons about which to use, outputs directly

MANDATORY: Planning Verification Checklist (M198)

BLOCKING: Before recommending ANY approach for a skill-builder rewrite, complete this checklist:

extraction_verification:
  # Check each computation candidate signal against the skill
  signals_present:
    counting_chars_widths: true|false  # display_width, strlen, emoji counting
    arithmetic_with_vars: true|false   # padding = max - width, calculations
    building_formatted_strings: true|false  # "│ " + content + " │", table rows
    aggregating_collections: true|false     # max(widths), sum, counts

  # If ANY signal is true, extraction is REQUIRED
  extraction_required: true|false

  # Verify recommendation matches requirement
  recommendation_valid:
    if_extraction_required_and_recommending_simplified: INVALID
    if_extraction_required_and_recommending_hooks: VALID
    if_no_extraction_and_recommending_simplified: VALID

Anti-pattern (M198): Recommending "simplified rewrite without hooks" based on content type (ASCII vs emoji) rather than computation type. The extraction criteria are about WHAT OPERATIONS the skill performs (counting, arithmetic, formatting), NOT what characters appear in the output.

Anti-pattern (M203): Acknowledging extraction is required, then overriding with case-specific reasoning. Common override patterns to REJECT:

  • "HOWEVER, consider that this only runs once..."
  • "BUT for this specific case, hooks are overkill..."
  • "Given the static content, we can simplify..."
  • "The complexity cost outweighs the benefit..."

If signals show extraction_required: true, the determination is FINAL. Do not add "HOWEVER" exceptions. The methodology exists precisely because case-specific reasoning leads to errors. Frequency of execution, content type, and perceived complexity are NOT valid override reasons.

Anti-pattern (M214): Conflating content generation with display rendering. These are independent:

DimensionQuestionIf YES
ContentDoes content require reasoning/judgment?Content stays in skill
DisplayDoes output need formatted rendering (boxes, tables, alignment)?Rendering extracted to hook

Common error: "The content is reasoning-based, so extraction_required: false." Correct analysis: Content and display are orthogonal. Even if CONTENT requires reasoning, DISPLAY rendering (box characters, padding, alignment) is deterministic and should be extracted.

Correct workflow for mixed cases (hook pre-computes all variants):

  1. Hook detects skill invocation
  2. Hook gathers all data that could be displayed (from files, state, etc.)
  3. Hook pre-renders ALL possible output variants
  4. Hook returns pre-computed variants via additionalContext
  5. Agent reasons about which variant(s) to use
  6. Agent outputs the selected pre-computed content directly

Example - research executive summary:

# WRONG analysis (led to M214):
"The content requires reasoning (identifying approaches), so extraction_required: false"

# WRONG workflow (led to M215):
1. Agent reasons about stakeholder findings → produces approach data
2. Agent calls render-research-summary.py via Bash  ← User sees Bash tool!
3. Script returns formatted box output
4. Agent outputs pre-rendered result

# CORRECT analysis:
content_generation: reasoning-based  # Selection/synthesis - stays in skill
display_rendering: deterministic     # Box layout, alignment - extract to hook

# CORRECT workflow:
1. Hook detects /cat:research invocation
2. Hook reads all stakeholder data from PLAN.md Research section
3. Hook pre-renders executive summary boxes for each option/approach
4. Hook returns ALL pre-rendered variants via additionalContext
5. Agent reasons about findings, selects relevant pre-computed sections
6. Agent outputs selected pre-computed content (no Bash invocation)

Example - Token-report skill:

# WRONG analysis (led to M198):
"Table contents are ASCII-only, so hooks are overkill"

# CORRECT analysis:
signals_present:
  counting_chars_widths: true      # Column widths must be calculated
  arithmetic_with_vars: true       # padding = column_width - content_width
  building_formatted_strings: true # "│ Type            │ Description..."
  aggregating_collections: true    # Total tokens = sum of subagent tokens

extraction_required: true  # 4/4 signals present
recommendation: "Full hook-based pre-computation (Approach A)"

Template-Based Precomputation (M216)

For mixed cases where content is reasoning-based but output structure is known:

Even when the exact content is unknown until the skill reasons about it, the OUTPUT TYPE/STRUCTURE is often known ahead of time. The hook can pre-compute templates that the skill fills in.

Key insight: You know:

  • The box will be N characters wide
  • Each line needs "│ " prefix and " │" suffix
  • The top/bottom borders use specific characters
  • Section headers follow a pattern

Template-based workflow:

  1. Hook pre-computes structural elements at fixed width:
    • Box borders (top, bottom, dividers)
    • Line template with padding placeholder
    • Section header templates
  2. Hook returns templates via additionalContext
  3. Skill reasons about content (option names, descriptions, etc.)
  4. Skill fills templates with content, extending to more lines as needed
  5. Skill outputs using pre-computed structural elements

Example - Research executive summary templates:

# Hook pre-computes templates at fixed width (e.g., 76 chars inner width)
BOX_WIDTH = 76

def precompute_templates():
    return {
        'top_border': '╭' + '─' * (BOX_WIDTH + 2) + '╮',
        'bottom_border': '╰' + '─' * (BOX_WIDTH + 2) + '╯',
        'divider': '├' + '─' * (BOX_WIDTH + 2) + '┤',
        'line_template': '│ {content:<' + str(BOX_WIDTH) + '} │',
        'header_template': '│ {icon} {title:<' + str(BOX_WIDTH - 4) + '} │',
        'empty_line': '│' + ' ' * (BOX_WIDTH + 2) + '│',
    }

Skill uses templates:

### Step 1: Require pre-computed templates

**MANDATORY:** Check context for "PRE-COMPUTED RESEARCH TEMPLATES".

Templates include:
- `top_border`: Use once at start
- `bottom_border`: Use once at end
- `line_template`: Use for each content line (format with content)
- `header_template`: Use for section headers
- `divider`: Use between sections
- `empty_line`: Use for visual spacing

### Step 2: Reason about content

Synthesize stakeholder findings to identify approaches, tradeoffs, etc.
(This is the reasoning part that cannot be pre-computed.)

### Step 3: Build output using templates

For each line of content:
1. Use `line_template.format(content=your_content)`
2. If content exceeds width, wrap to multiple lines using same template

Output structure:

{top_border} {header_template.format(icon='📋', title='Executive Summary')} {divider} {line_template.format(content='Option 1: ...')} {line_template.format(content=' Description: ...')} {empty_line} {line_template.format(content='Option 2: ...')} ... {bottom_border}

Benefits of template approach:

  • Borders/structure computed once with correct widths
  • Skill can extend to any number of lines
  • No risk of miscounting padding (template handles it)
  • Works when content is unknown but structure is known

When to use each approach:

ScenarioApproach
All content known ahead of timeFull precomputation (status_handler pattern)
Content unknown, structure knownTemplate precomputation
Content unknown, structure variesPlain text (avoid boxes)

When computation candidates exist, generate two artifacts:

1. Skill Handler (Python in plugin/hooks/skill_handlers/):

Create a handler that pre-computes ALL possible outputs before the skill runs. See status_handler.py for the canonical example.

# plugin/hooks/skill_handlers/{skill_name}_handler.py
"""Handler for /cat:{skill-name} precomputation."""

from pathlib import Path
from . import register_handler

class SkillNameHandler:
    """Handler for /cat:{skill-name} skill."""

    def handle(self, context: dict) -> str | None:
        """Pre-compute all possible outputs before skill runs."""
        project_root = context.get("project_root")
        if not project_root:
            return None

        # 1. Gather all data the skill might need
        data = self._collect_data(project_root)
        if not data:
            return None

        # 2. Pre-render ALL possible output variants
        variants = self._render_all_variants(data)

        # 3. Return pre-computed content via additionalContext
        return f"""PRE-COMPUTED {SKILL_NAME} OUTPUT:

{variants['main_output']}

VARIANT A (if applicable):
{variants['variant_a']}

VARIANT B (if applicable):
{variants['variant_b']}

INSTRUCTION: Output the appropriate pre-computed section. Do not recalculate."""

    def _collect_data(self, project_root):
        # Read files, gather state, etc.
        pass

    def _render_all_variants(self, data):
        # Pre-render boxes, tables, formatted output
        # Include ALL variants the skill might need
        pass

# Register handler - this makes it run when skill is invoked
_handler = SkillNameHandler()
register_handler("{skill-name}", _handler)

Key patterns from status_handler.py:

  • display_width(text) - calculates terminal width with emoji support
  • build_line(content, max_width) - builds single box line with padding
  • build_border(max_width, is_top) - builds top/bottom border
  • build_inner_box(header, content_items) - builds nested box structures

2. Skill Preamble (add to generated skill - FAIL-FAST, not fallback):

### Step 1: Require pre-computed results

**MANDATORY:** Check context for "PRE-COMPUTED {SKILL-NAME}".

If found:
1. Output the pre-computed content **directly without preamble**
2. If skill requires reasoning to select variants, select appropriate section
3. Skip to verification step

If NOT found: **FAIL immediately**.

```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/check-hooks-loaded.sh" "results" "the skill"
if [[ $? -eq 0 ]]; then
  echo "ERROR: Pre-computed results not found."
  echo "The handler ({skill-name}_handler.py) should have provided these."
  echo "Check:"
  echo "1. Handler is registered in skill_handlers/__init__.py"
  echo "2. Handler file exists in plugin/hooks/skill_handlers/"
  echo "3. Handler ran without errors"
fi

Output the error and STOP. Do NOT attempt manual computation.


**Why fail-fast?** Manual computation was extracted precisely because agents
cannot do it reliably. Falling back to manual defeats the purpose and hides
handler failures.

For mixed cases (reasoning + display):

When the skill requires reasoning to generate content but display is deterministic:

# The hook pre-computes ALL possible display formats
# The skill reasons about which to use and outputs directly

def _render_all_variants(self, data):
    variants = {}

    # Pre-render each possible stakeholder perspective
    for stakeholder in ['architect', 'security', 'performance', ...]:
        variants[f'{stakeholder}_box'] = self._build_stakeholder_box(
            data.get(stakeholder, {})
        )

    # Pre-render summary tables for different groupings
    variants['by_priority'] = self._build_priority_table(data)
    variants['by_category'] = self._build_category_table(data)

    # Pre-render option comparison boxes
    for i, option in enumerate(data.get('options', [])):
        variants[f'option_{i}_box'] = self._build_option_box(option)

    return variants

The skill then reasons about the data, decides what to show, and outputs the appropriate pre-computed sections.

Example - Box alignment extraction:

Functions identified in Step 5:
  display_width(text) → integer     ← COMPUTATION CANDIDATE
  max_content_width(items) → int    ← COMPUTATION CANDIDATE
  build_line(content, max) → string ← COMPUTATION CANDIDATE

Generate:
  1. plugin/hooks/skill_handlers/box_handler.py
     - Implements display_width, build_line, build_border
     - Pre-computes complete box output
     - Returns via additionalContext
  2. Skill preamble - REQUIRES pre-computed output (fail-fast)

Result: Agent receives exact pre-computed box, outputs directly.
No Bash tools shown to user. If handler fails, skill fails immediately.

Decision flow during Step 5:

For each function:
  Is it deterministic? ─────No────→ Keep in skill (reasoning required)
         │
        Yes
         │
  Could agent compute wrong? ─No─→ Keep in skill (trivial/reliable)
         │
        Yes
         │
  Extract to skill handler (plugin/hooks/skill_handlers/)
         │
  Handler pre-computes ALL variants BEFORE skill runs
         │
  Skill REQUIRES pre-computed result (fail-fast if missing)

Checklist Before Finalizing Skill

  • Frontmatter description is trigger-oriented (WHEN to use, not just what it does)
  • Goal is observable and verifiable
  • All REQUIRES chains end in ATOMIC conditions
  • Dependency order has no cycles
  • Repeated patterns extracted as functions
  • Recursive structures have function with base case + recursive case
  • Variable-length functions derived via min-case → increment → generalize
  • Functions listed in dependency order (no forward references)
  • Forward steps call functions (no duplicated logic)
  • Computation candidates identified and extracted to skill handler (M192/M215)
  • Skill handler created in plugin/hooks/skill_handlers/ for deterministic functions
  • Handler pre-computes ALL possible output variants BEFORE skill runs
  • Skill NEVER invokes scripts via Bash - user sees no tool calls (M215)
  • Skill REQUIRES pre-computed results - FAIL-FAST if missing (no fallback)
  • No "if not found, continue to manual..." patterns (fail-fast principle)
  • Calculation gates added for transformation steps (M191)
  • Artifact gates added when output has precise formatting (M192)
  • Gates use MANDATORY and BLOCKING keywords
  • Calculation gates require explicit numeric results before construction
  • Artifact gates require explicit output strings before final assembly
  • No embedded box drawings in skill instructions or examples (M217)
  • Box-drawing characters only appear in handler code, not skill text
  • Visual patterns use lookup tables with "do not hand-type" warnings
  • Display rendering references handler functions by name
  • Verification criteria exist for the goal
Similar Skills
cache-components

Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.

138.5k
Stats
Parent Repo Stars78
Parent Repo Forks1
Last CommitFeb 13, 2026