Claude Cursor Skill

feature-radar-validate

Validate SKILL.md frontmatter and .feature-radar/ files against format rules. Runs validate.sh, reports errors/warnings, and auto-fixes issues. MUST use this skill after editing any SKILL.md or .feature-radar/ file, even if the user doesn't ask — catches format bugs like the Agen

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download runkids-my-skills-feature-radar_feature-radar-validate-7f33dbc.zip · 3 KB
Part of runkids/my-skills — 13 skills

Install

skills CLI npx skills add https://github.com/runkids/my-skills/tree/main/feature-radar/feature-radar-validate
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install runkids-my-skills@llmmart
Git git clone https://github.com/runkids/my-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole runkids/my-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Validate Feature Radar

Run skills/feature-radar-validate/scripts/validate.sh from the project root to check SKILL.md frontmatter and .feature-radar/ SPEC compliance, then fix any issues found.

Why This Matters

The description field in SKILL.md has a 1024-character limit in the Agent Skills spec (agentskills.io/specification, checked 2026-09-29). Agents that enforce the spec may reject a longer description; Claude Code instead truncates the skill listing at 1,536 characters, cutting off trigger text. Similarly, .feature-radar/ files must follow SPEC.md naming and metadata conventions or downstream tools can't parse them. This skill catches these issues before they cause problems.

Workflow

Step 1: Run Validation

bash skills/feature-radar-validate/scripts/validate.sh

Read the full output. Note the exit code:

  • Exit 0: all checks passed (may still have warnings)
  • Exit 1: errors found — must be fixed

Step 2: Report Results

Present the results clearly:

── Feature Radar: Validate ──

Errors:   {n}
Warnings: {n}

{List each error/warning with file path and issue}

If everything passes, say so and stop. No further action needed.

Step 3: Auto-Fix (if errors or warnings found)

For each issue, apply the appropriate fix:

Issue Fix Strategy
description > 1024 chars Trim to fit — cut the least essential trigger phrases or examples first, keep the core "what it does" and "Use when" intact. Show before/after char count.
description missing "Use when" Add a "Use when:" section based on the skill's purpose
name not kebab-case Rename to kebab-case
name missing Derive from directory name
name > 64 chars Propose a shorter name and ask user to confirm — the name is how the skill is invoked
name does not match directory Set name to the directory name; if the name is the intended one, ask user before renaming the directory (other skills reference it by path)
Body > 500 lines Flag for user — this requires judgment about what to extract into reference files
Filename not {nn}-{slug}.md Rename file to correct format
Missing **Status**: / **Impact**: / **Effort**: Add field with a placeholder value, ask user to confirm
base.md count mismatch Update the Tracking Summary table counts

After fixing, re-run bash skills/feature-radar-validate/scripts/validate.sh to confirm all errors are resolved.

Step 4: Completion Summary

── Feature Radar: Validate Complete ──

Files fixed:   ~ {path} ({what changed})
Errors fixed:  {n}
Warnings fixed: {n}
Remaining:     {n} (need user input)

Proactive Triggering

When you notice yourself editing skills/*/SKILL.md or .feature-radar/**/*.md, run validation afterward without being asked. A quick bash skills/feature-radar-validate/scripts/validate.sh check takes seconds and prevents silent breakage.

Files (my-skills)
  • scripts
    • validate.sh 5.4 KB
      #!/usr/bin/env bash
      # Feature Radar Validation Script
      # Validates SKILL.md frontmatter and .feature-radar/ SPEC.md compliance
      # Exit 0 = pass, Exit 1 = errors found
      set -euo pipefail
      
      RED='\033[0;31m'
      YLW='\033[0;33m'
      GRN='\033[0;32m'
      RST='\033[0m'
      
      errors=0
      warnings=0
      
      error() { echo -e "  ${RED}ERROR${RST}: $1"; errors=$((errors + 1)); }
      warn()  { echo -e "  ${YLW}WARN${RST}:  $1"; warnings=$((warnings + 1)); }
      pass()  { echo -e "  ${GRN}OK${RST}:    $1"; }
      
      # ─── Layer 1: SKILL.md Frontmatter ──────────────────────────────────────────
      
      echo ""
      echo "=== Layer 1: SKILL.md Frontmatter ==="
      echo ""
      
      for skill_file in skills/*/SKILL.md; do
        [ -f "$skill_file" ] || continue
        skill_dir=$(basename "$(dirname "$skill_file")")
        echo "[$skill_dir]"
      
        # Extract frontmatter (between first pair of ---)
        frontmatter=$(awk '/^---$/{n++; next} n==1' "$skill_file")
      
        # Check name field
        name=$(echo "$frontmatter" | grep -E '^name:' | head -1 | sed 's/^name:[[:space:]]*//')
        if [ -z "$name" ]; then
          error "missing 'name' field"
        elif ! echo "$name" | grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$'; then
          error "name '$name' is not kebab-case"
        elif [ "${#name}" -gt 64 ]; then
          error "name is ${#name} chars (max 64)"
        elif [ "$name" != "$skill_dir" ]; then
          error "name '$name' does not match directory '$skill_dir'"
        else
          pass "name: $name"
        fi
      
        # Extract description (handles multi-line | syntax)
        desc=$(awk '
          /^---$/ { n++; next }
          n != 1 { next }
          /^description:/ {
            # Check for inline value vs block scalar
            sub(/^description:[[:space:]]*/, "")
            if ($0 == "|" || $0 == ">") { capture = 1; next }
            if ($0 != "") { print; next }
            capture = 1; next
          }
          capture && /^[a-z]/ { capture = 0 }
          capture && /^[[:space:]]/ { sub(/^[[:space:]]+/, ""); print }
        ' "$skill_file")
      
        if [ -z "$desc" ]; then
          error "missing 'description' field"
        else
          desc_len=${#desc}
          if [ "$desc_len" -gt 1024 ]; then
            error "description is ${desc_len} chars (max 1024)"
          else
            pass "description: ${desc_len} chars"
          fi
      
          # Warning: description should contain "Use when" or "Trigger phrases"
          if ! echo "$desc" | grep -qiE 'Use when|Trigger phrases'; then
            warn "description lacks 'Use when' or 'Trigger phrases'"
          fi
        fi
      
        # Warning: body length (lines after frontmatter closing ---)
        body_lines=$(awk '/^---$/{n++; next} n>=2' "$skill_file" | wc -l | tr -d ' ')
        if [ "$body_lines" -gt 500 ]; then
          warn "body is ${body_lines} lines (recommended max 500)"
        fi
      
        echo ""
      done
      
      # ─── Layer 2: SPEC.md Compliance (.feature-radar/) ──────────────────────────
      
      if [ -d ".feature-radar" ]; then
        echo "=== Layer 2: .feature-radar/ SPEC Compliance ==="
        echo ""
      
        # Check archive/ and opportunities/ filename format: {nn}-{slug}.md
        for dir in archive opportunities; do
          dirpath=".feature-radar/$dir"
          [ -d "$dirpath" ] || continue
      
          for f in "$dirpath"/*.md; do
            [ -f "$f" ] || continue
            fname=$(basename "$f")
            echo "[$dir/$fname]"
      
            if ! echo "$fname" | grep -qE '^[0-9]{2}-[a-z0-9]+(-[a-z0-9]+)*\.md$'; then
              error "filename '$fname' does not match {nn}-{slug}.md format"
            else
              pass "filename format OK"
            fi
      
            # Check required fields based on directory
            content=$(cat "$f")
            if ! echo "$content" | grep -q '^\*\*Status\*\*:'; then
              error "missing **Status**: field"
            fi
      
            if [ "$dir" = "opportunities" ]; then
              for field in Impact Effort; do
                if ! echo "$content" | grep -q "^\*\*${field}\*\*:"; then
                  error "missing **${field}**: field"
                fi
              done
            fi
            echo ""
          done
        done
      
        # Warning: base.md Tracking Summary count reconciliation
        if [ -f ".feature-radar/base.md" ]; then
          echo "[base.md count reconciliation]"
          for dir in archive opportunities specs references; do
            dirpath=".feature-radar/$dir"
            if [ -d "$dirpath" ]; then
              actual=$(find "$dirpath" -name '*.md' -type f | wc -l | tr -d ' ')
            else
              actual=0
            fi
      
            # Extract count from base.md tracking table
            # Format: | archive/ | {n} | ...
            reported=$(grep -E "^\|[[:space:]]*${dir}/" ".feature-radar/base.md" 2>/dev/null \
              | head -1 \
              | awk -F'|' '{gsub(/[[:space:]]/, "", $3); print $3}')
      
            if [ -n "$reported" ] && [ "$reported" != "$actual" ]; then
              warn "${dir}/ count mismatch: base.md says ${reported}, actual ${actual}"
            elif [ -n "$reported" ]; then
              pass "${dir}/ count: ${actual}"
            fi
          done
          echo ""
        fi
      else
        echo ""
        echo "=== Layer 2: Skipped (.feature-radar/ not found) ==="
        echo ""
      fi
      
      # ─── Summary ────────────────────────────────────────────────────────────────
      
      echo "─────────────────────────────────────"
      if [ "$errors" -gt 0 ]; then
        echo -e "${RED}FAILED${RST}: ${errors} error(s), ${warnings} warning(s)"
        exit 1
      elif [ "$warnings" -gt 0 ]; then
        echo -e "${YLW}PASSED${RST}: 0 errors, ${warnings} warning(s)"
        exit 0
      else
        echo -e "${GRN}PASSED${RST}: all checks passed"
        exit 0
      fi
      
  • SKILL.md 3.5 KB
    ---
    name: feature-radar-validate
    description: |
      Validate SKILL.md frontmatter and .feature-radar/ files against format rules. Runs
      validate.sh, reports errors/warnings, and auto-fixes issues. MUST use this skill after
      editing any SKILL.md or .feature-radar/ file, even if the user doesn't ask — catches format
      bugs like the Agent Skills spec's 1024-char description limit before they break the skill.
      Use when the user asks to validate, lint, or verify skills or .feature-radar/ files, after
      editing either, or before committing changes that touch skills/ or .feature-radar/.
    ---
    
    # Validate Feature Radar
    
    Run `skills/feature-radar-validate/scripts/validate.sh` from the project root to check SKILL.md frontmatter and `.feature-radar/` SPEC compliance, then fix any issues found.
    
    ## Why This Matters
    
    The `description` field in SKILL.md has a 1024-character limit in the Agent Skills spec (agentskills.io/specification, checked 2026-09-29). Agents that enforce the spec may reject a longer description; Claude Code instead truncates the skill listing at 1,536 characters, cutting off trigger text. Similarly, `.feature-radar/` files must follow SPEC.md naming and metadata conventions or downstream tools can't parse them. This skill catches these issues before they cause problems.
    
    ## Workflow
    
    ### Step 1: Run Validation
    
    ```bash
    bash skills/feature-radar-validate/scripts/validate.sh
    ```
    
    Read the full output. Note the exit code:
    - **Exit 0**: all checks passed (may still have warnings)
    - **Exit 1**: errors found — must be fixed
    
    ### Step 2: Report Results
    
    Present the results clearly:
    
    ```
    ── Feature Radar: Validate ──
    
    Errors:   {n}
    Warnings: {n}
    
    {List each error/warning with file path and issue}
    ```
    
    If everything passes, say so and stop. No further action needed.
    
    ### Step 3: Auto-Fix (if errors or warnings found)
    
    For each issue, apply the appropriate fix:
    
    | Issue | Fix Strategy |
    |-------|-------------|
    | `description` > 1024 chars | Trim to fit — cut the least essential trigger phrases or examples first, keep the core "what it does" and "Use when" intact. Show before/after char count. |
    | `description` missing "Use when" | Add a "Use when:" section based on the skill's purpose |
    | `name` not kebab-case | Rename to kebab-case |
    | `name` missing | Derive from directory name |
    | `name` > 64 chars | Propose a shorter name and ask user to confirm — the name is how the skill is invoked |
    | `name` does not match directory | Set `name` to the directory name; if the `name` is the intended one, ask user before renaming the directory (other skills reference it by path) |
    | Body > 500 lines | Flag for user — this requires judgment about what to extract into reference files |
    | Filename not `{nn}-{slug}.md` | Rename file to correct format |
    | Missing `**Status**:` / `**Impact**:` / `**Effort**:` | Add field with a placeholder value, ask user to confirm |
    | `base.md` count mismatch | Update the Tracking Summary table counts |
    
    After fixing, re-run `bash skills/feature-radar-validate/scripts/validate.sh` to confirm all errors are resolved.
    
    ### Step 4: Completion Summary
    
    ```
    ── Feature Radar: Validate Complete ──
    
    Files fixed:   ~ {path} ({what changed})
    Errors fixed:  {n}
    Warnings fixed: {n}
    Remaining:     {n} (need user input)
    ```
    
    ## Proactive Triggering
    
    When you notice yourself editing `skills/*/SKILL.md` or `.feature-radar/**/*.md`, run validation afterward without being asked. A quick `bash skills/feature-radar-validate/scripts/validate.sh` check takes seconds and prevents silent breakage.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related