spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / plugins / plugin-dev / skills / agent-development / scripts / validate-agent.sh
217 lines · 5.7 KBRaw
1#!/bin/bash
2# Agent File Validator
3# Validates agent markdown files for correct structure and content
4
5set -euo pipefail
6
7# Usage
8if [ $# -eq 0 ]; then
9 echo "Usage: $0 <path/to/agent.md>"
10 echo ""
11 echo "Validates agent file for:"
12 echo " - YAML frontmatter structure"
13 echo " - Required fields (name, description, model, color)"
14 echo " - Field formats and constraints"
15 echo " - System prompt presence and length"
16 echo " - Example blocks in description"
17 exit 1
18fi
19
20AGENT_FILE="$1"
21
22echo "🔍 Validating agent file: $AGENT_FILE"
23echo ""
24
25# Check 1: File exists
26if [ ! -f "$AGENT_FILE" ]; then
27 echo "❌ File not found: $AGENT_FILE"
28 exit 1
29fi
30echo "✅ File exists"
31
32# Check 2: Starts with ---
33FIRST_LINE=$(head -1 "$AGENT_FILE")
34if [ "$FIRST_LINE" != "---" ]; then
35 echo "❌ File must start with YAML frontmatter (---)"
36 exit 1
37fi
38echo "✅ Starts with frontmatter"
39
40# Check 3: Has closing ---
41if ! tail -n +2 "$AGENT_FILE" | grep -q '^---$'; then
42 echo "❌ Frontmatter not closed (missing second ---)"
43 exit 1
44fi
45echo "✅ Frontmatter properly closed"
46
47# Extract frontmatter and system prompt
48FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$AGENT_FILE")
49SYSTEM_PROMPT=$(awk '/^---$/{i++; next} i>=2' "$AGENT_FILE")
50
51# Check 4: Required fields
52echo ""
53echo "Checking required fields..."
54
55error_count=0
56warning_count=0
57
58# Check name field
59NAME=$(echo "$FRONTMATTER" | grep '^name:' | sed 's/name: *//' | sed 's/^"\(.*\)"$/\1/')
60
61if [ -z "$NAME" ]; then
62 echo "❌ Missing required field: name"
63 ((error_count++))
64else
65 echo "✅ name: $NAME"
66
67 # Validate name format
68 if ! [[ "$NAME" =~ ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$ ]]; then
69 echo "❌ name must start/end with alphanumeric and contain only letters, numbers, hyphens"
70 ((error_count++))
71 fi
72
73 # Validate name length
74 name_length=${#NAME}
75 if [ $name_length -lt 3 ]; then
76 echo "❌ name too short (minimum 3 characters)"
77 ((error_count++))
78 elif [ $name_length -gt 50 ]; then
79 echo "❌ name too long (maximum 50 characters)"
80 ((error_count++))
81 fi
82
83 # Check for generic names
84 if [[ "$NAME" =~ ^(helper|assistant|agent|tool)$ ]]; then
85 echo "⚠️ name is too generic: $NAME"
86 ((warning_count++))
87 fi
88fi
89
90# Check description field
91DESCRIPTION=$(echo "$FRONTMATTER" | grep '^description:' | sed 's/description: *//')
92
93if [ -z "$DESCRIPTION" ]; then
94 echo "❌ Missing required field: description"
95 ((error_count++))
96else
97 desc_length=${#DESCRIPTION}
98 echo "✅ description: ${desc_length} characters"
99
100 if [ $desc_length -lt 10 ]; then
101 echo "⚠️ description too short (minimum 10 characters recommended)"
102 ((warning_count++))
103 elif [ $desc_length -gt 5000 ]; then
104 echo "⚠️ description very long (over 5000 characters)"
105 ((warning_count++))
106 fi
107
108 # Check for example blocks
109 if ! echo "$DESCRIPTION" | grep -q '<example>'; then
110 echo "⚠️ description should include <example> blocks for triggering"
111 ((warning_count++))
112 fi
113
114 # Check for "Use this agent when" pattern
115 if ! echo "$DESCRIPTION" | grep -qi 'use this agent when'; then
116 echo "⚠️ description should start with 'Use this agent when...'"
117 ((warning_count++))
118 fi
119fi
120
121# Check model field
122MODEL=$(echo "$FRONTMATTER" | grep '^model:' | sed 's/model: *//')
123
124if [ -z "$MODEL" ]; then
125 echo "❌ Missing required field: model"
126 ((error_count++))
127else
128 echo "✅ model: $MODEL"
129
130 case "$MODEL" in
131 inherit|sonnet|opus|haiku)
132 # Valid model
133 ;;
134 *)
135 echo "⚠️ Unknown model: $MODEL (valid: inherit, sonnet, opus, haiku)"
136 ((warning_count++))
137 ;;
138 esac
139fi
140
141# Check color field
142COLOR=$(echo "$FRONTMATTER" | grep '^color:' | sed 's/color: *//')
143
144if [ -z "$COLOR" ]; then
145 echo "❌ Missing required field: color"
146 ((error_count++))
147else
148 echo "✅ color: $COLOR"
149
150 case "$COLOR" in
151 blue|cyan|green|yellow|magenta|red)
152 # Valid color
153 ;;
154 *)
155 echo "⚠️ Unknown color: $COLOR (valid: blue, cyan, green, yellow, magenta, red)"
156 ((warning_count++))
157 ;;
158 esac
159fi
160
161# Check tools field (optional)
162TOOLS=$(echo "$FRONTMATTER" | grep '^tools:' | sed 's/tools: *//')
163
164if [ -n "$TOOLS" ]; then
165 echo "✅ tools: $TOOLS"
166else
167 echo "💡 tools: not specified (agent has access to all tools)"
168fi
169
170# Check 5: System prompt
171echo ""
172echo "Checking system prompt..."
173
174if [ -z "$SYSTEM_PROMPT" ]; then
175 echo "❌ System prompt is empty"
176 ((error_count++))
177else
178 prompt_length=${#SYSTEM_PROMPT}
179 echo "✅ System prompt: $prompt_length characters"
180
181 if [ $prompt_length -lt 20 ]; then
182 echo "❌ System prompt too short (minimum 20 characters)"
183 ((error_count++))
184 elif [ $prompt_length -gt 10000 ]; then
185 echo "⚠️ System prompt very long (over 10,000 characters)"
186 ((warning_count++))
187 fi
188
189 # Check for second person
190 if ! echo "$SYSTEM_PROMPT" | grep -q "You are\|You will\|Your"; then
191 echo "⚠️ System prompt should use second person (You are..., You will...)"
192 ((warning_count++))
193 fi
194
195 # Check for structure
196 if ! echo "$SYSTEM_PROMPT" | grep -qi "responsibilities\|process\|steps"; then
197 echo "💡 Consider adding clear responsibilities or process steps"
198 fi
199
200 if ! echo "$SYSTEM_PROMPT" | grep -qi "output"; then
201 echo "💡 Consider defining output format expectations"
202 fi
203fi
204
205echo ""
206echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
207
208if [ $error_count -eq 0 ] && [ $warning_count -eq 0 ]; then
209 echo "✅ All checks passed!"
210 exit 0
211elif [ $error_count -eq 0 ]; then
212 echo "⚠️ Validation passed with $warning_count warning(s)"
213 exit 0
214else
215 echo "❌ Validation failed with $error_count error(s) and $warning_count warning(s)"
216 exit 1
217fi