
Meta Agent Creator
- 68 installs
- 14 repo stars
- Updated March 2, 2026
- oakoss/agent-skills
Helps with ai & agent building tasks during AI-assisted development.
About
meta-agent-creator is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- meta-agent-creator
- AI & Agent Building
- AI-coding skill
Meta Agent Creator by the numbers
- 68 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #5,828 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/oakoss/agent-skills --skill meta-agent-creatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 68 |
|---|---|
| repo stars | ★ 14 |
| Last updated | March 2, 2026 |
| Repository | oakoss/agent-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Custom Agent Creator
Overview
Subagents are specialized AI assistants defined as Markdown files with YAML frontmatter. Each subagent runs in its own context window with a custom system prompt, specific tool access, and independent permissions. When a task matches a subagent's description, the parent conversation delegates to it automatically, preserving main context while enforcing constraints.
When to use: Isolating high-volume operations (tests, logs), enforcing read-only access for reviewers, routing simple tasks to cheaper models, running parallel research, creating reusable team workflows.
When NOT to use: Tasks requiring frequent back-and-forth, quick targeted changes, workflows needing nested delegation (subagents cannot spawn subagents), latency-sensitive operations where fresh context gathering is costly.
Quick Reference
| Pattern | Configuration | Key Points |
|---|---|---|
| File location (project) | .claude/agents/name.md | Shared via version control, priority 2 |
| File location (user) | ~/.claude/agents/name.md | Available across all projects, priority 3 |
| Required fields | name, description | Only two fields are mandatory |
| Tool restriction | tools: Read, Grep, Glob | Allowlist; inherits all if omitted |
| Tool denial | disallowedTools: Write, Edit | Denylist; removed from inherited set |
| Model selection | model: haiku | Options: sonnet, opus, haiku, inherit (default) |
| Permission mode | permissionMode: dontAsk | Controls permission prompt behavior |
| Skill preloading | skills: [auth, api-patterns] | Injected at startup; no inheritance from parent |
| Lifecycle hooks | hooks: { PreToolUse: [...] } | Validate or block tool usage conditionally |
| CLI-defined agent | claude --agents '{...}' | Session-only, highest priority, JSON format |
| Interactive creation | /agents command | Guided setup with Claude generation |
| Proactive triggers | "Use proactively after..." | Include in description for auto-delegation |
Common Mistakes
| Mistake | Correct Pattern |
|---|---|
| Using opus for simple checklist reviews | Use haiku for read-only reviews and style checks |
| Omitting output format in system prompt | Include structured output template for consistent results |
| Listing tools explicitly when all are needed | Omit tools field to inherit all tools including MCP |
| Expecting skills from parent conversation | Explicitly list skills in the skills field |
| Generic description without triggers | Include specific trigger phrases like "Use proactively when..." |
| Giving a single agent too many responsibilities | Design focused agents with one clear purpose each |
Using bypassPermissions without caution | Prefer acceptEdits or dontAsk for safer automation |
| Creating deeply nested agent workflows | Chain subagents from main conversation; nesting is not supported |
Delegation
- Agent pattern discovery: Use
Exploreagent to find existing agents in.claude/agents/ - Interactive creation: Use
/agentscommand for guided setup with Claude generation - Code review of agent files: Use
Taskagent to validate system prompts and configuration
References
- Agent configuration: YAML fields, file locations, and priority order
- Tool selection: access patterns, common combinations, and model guide
- Templates: ready-to-use agent patterns for common workflows
Agent Configuration
File Structure
Subagent files use YAML frontmatter for configuration followed by the system prompt in Markdown:
---
name: code-reviewer
description: Reviews code for quality and best practices. Use proactively after code changes.
tools: Read, Glob, Grep
model: sonnet
---
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.The frontmatter defines metadata and configuration. The body becomes the system prompt. Subagents receive only this system prompt plus basic environment details, not the full parent system prompt.
File Locations and Priority
When multiple subagents share the same name, the higher-priority location wins.
| Location | Scope | Priority |
|---|---|---|
--agents CLI flag (JSON) | Current session only | 1 (highest) |
.claude/agents/ | Current project | 2 |
~/.claude/agents/ | All projects | 3 |
Plugin's agents/ directory | Where plugin is enabled | 4 (lowest) |
Project subagents in .claude/agents/ should be checked into version control for team sharing.
YAML Frontmatter Fields
Required Fields
| Field | Description |
|---|---|
name | Unique identifier using lowercase letters and hyphens |
description | When the parent should delegate to this subagent |
Optional Fields
| Field | Description | Default |
|---|---|---|
tools | Comma-separated allowlist of tools the subagent can use | Inherits all tools (including MCP) |
disallowedTools | Comma-separated denylist removed from inherited or specified set | None |
model | Model alias: sonnet, opus, haiku, or inherit | inherit |
permissionMode | How the subagent handles permission prompts | default |
skills | Skills to inject into the subagent's context at startup | None (no inheritance from parent) |
hooks | Lifecycle hooks scoped to this subagent | None |
Permission Modes
The permissionMode field controls how the subagent handles permission prompts. Subagents inherit the permission context from the main conversation but can override the mode.
---
name: auto-fixer
description: Automatically fix lint errors. Use proactively after lint failures.
tools: Read, Edit, Grep, Glob
permissionMode: acceptEdits
---| Mode | Behavior |
|---|---|
default | Standard permission checking with prompts |
acceptEdits | Auto-accept file edits |
dontAsk | Auto-deny permission prompts (explicitly allowed tools still work) |
bypassPermissions | Skip all permission checks (use with caution) |
plan | Plan mode (read-only exploration) |
If the parent uses bypassPermissions, it takes precedence and cannot be overridden by the subagent.
Skill Preloading
Use the skills field to inject skill content into a subagent's context at startup. Subagents do not inherit skills from the parent conversation.
---
name: api-developer
description: Implement API endpoints following team conventions
skills:
- api-conventions
- error-handling-patterns
---
Implement API endpoints. Follow the conventions and patterns from the preloaded skills.The full content of each skill is injected into the subagent's context, not just made available for invocation.
Lifecycle Hooks
Define hooks directly in the subagent's frontmatter. These hooks only run while that specific subagent is active.
| Event | Matcher Input | When It Fires |
|---|---|---|
PreToolUse | Tool name | Before the subagent uses a tool |
PostToolUse | Tool name | After the subagent uses a tool |
Stop | (none) | When the subagent finishes (converted to SubagentStop at runtime) |
---
name: safe-editor
description: Edit files with automatic linting after changes
tools: Read, Edit, Grep, Glob
hooks:
PostToolUse:
- matcher: 'Edit|Write'
hooks:
- type: command
command: './scripts/run-linter.sh'
---Project-Level Hooks
Configure hooks in settings.json that respond to subagent lifecycle events in the main session:
{
"hooks": {
"SubagentStart": [
{
"matcher": "db-agent",
"hooks": [
{ "type": "command", "command": "./scripts/setup-db-connection.sh" }
]
}
],
"SubagentStop": [
{
"hooks": [{ "type": "command", "command": "./scripts/cleanup.sh" }]
}
]
}
}SubagentStart supports matchers to target specific agent types. SubagentStop fires for all subagent completions regardless of matcher values.
CLI-Defined Agents
Pass subagent definitions as JSON via the --agents flag for session-only agents:
claude --agents '{
"code-reviewer": {
"description": "Expert code reviewer. Use proactively after code changes.",
"prompt": "You are a senior code reviewer...",
"tools": ["Read", "Grep", "Glob", "Bash"],
"model": "sonnet"
}
}'The JSON format uses prompt for the system prompt (equivalent to the markdown body in file-based agents). CLI-defined agents have the highest priority and are not saved to disk.
Built-in Agents
Claude Code includes several built-in subagents that are used automatically:
| Agent | Model | Tools | Purpose |
|---|---|---|---|
| Explore | Haiku | Read-only (no Write/Edit) | Fast codebase search and analysis |
| Plan | Inherits | Read-only (no Write/Edit) | Research for plan mode |
| general-purpose | Inherits | All tools | Complex multi-step tasks |
| Bash | Inherits | Terminal commands | Running commands in separate context |
Explore Thoroughness Levels
When invoking Explore, specify a thoroughness level: quick for targeted lookups, medium for balanced exploration, or very thorough for deep analysis.
Foreground vs Background Execution
- Foreground: Blocks main conversation until complete. Permission prompts pass through to the user.
- Background: Runs concurrently. Permissions are pre-approved before launch; unapproved prompts are auto-denied. MCP tools are not available in background subagents.
Press Ctrl+B to background a running task, or ask to "run this in the background."
Resuming Agents
Each subagent invocation creates a new instance with fresh context. To continue a previous subagent's work, ask to resume it. Resumed subagents retain their full conversation history.
Transcripts are stored at ~/.claude/projects/{project}/{sessionId}/subagents/agent-{agentId}.jsonl.
Disabling Agents
Prevent specific subagents from being used via permission rules:
{
"permissions": {
"deny": ["Task(Explore)", "Task(my-custom-agent)"]
}
}Or via CLI:
claude --disallowedTools "Task(Explore)"Agent Templates
Code Reviewer
A read-only subagent that reviews code without modifying it. Uses restricted tools (no Edit or Write) and a structured output format.
---
name: code-reviewer
description: Expert code review specialist. Proactively reviews code for quality, security, and maintainability. Use immediately after writing or modifying code.
tools: Read, Grep, Glob, Bash
model: inherit
---
You are a senior code reviewer ensuring high standards of code quality and security.
When invoked:
1. Run git diff to see recent changes
2. Focus on modified files
3. Begin review immediately
Review checklist:
- Code is clear and readable
- Functions and variables are well-named
- No duplicated code
- Proper error handling
- No exposed secrets or API keys
- Input validation implemented
- Good test coverage
- Performance considerations addressed
Provide feedback organized by priority:
- Critical issues (must fix)
- Warnings (should fix)
- Suggestions (consider improving)
Include specific examples of how to fix issues.Debugger
A subagent that can analyze and fix issues. Includes Edit for modifying code with a clear workflow from diagnosis to verification.
---
name: debugger
description: Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues.
tools: Read, Edit, Bash, Grep, Glob
---
You are an expert debugger specializing in root cause analysis.
When invoked:
1. Capture error message and stack trace
2. Identify reproduction steps
3. Isolate the failure location
4. Implement minimal fix
5. Verify solution works
Debugging process:
- Analyze error messages and logs
- Check recent code changes
- Form and test hypotheses
- Add strategic debug logging
- Inspect variable states
For each issue, provide:
- Root cause explanation
- Evidence supporting the diagnosis
- Specific code fix
- Testing approach
- Prevention recommendations
Focus on fixing the underlying issue, not the symptoms.Research Agent
A read-only agent with web access for gathering external information and documentation.
---
name: researcher
description: Research specialist for documentation lookup, API exploration, and gathering external information. Use when needing external context or documentation.
tools: Read, Grep, Glob, WebFetch, WebSearch
model: haiku
---
You are a research specialist. Gather information from codebases and external sources to answer questions thoroughly.
When invoked:
1. Understand the research question
2. Search the codebase for relevant context
3. Fetch external documentation if needed
4. Synthesize findings into a clear summary
Present findings as:
- Key facts and answers
- Relevant code locations
- External documentation links
- Recommendations based on findings
Be thorough but concise. Focus on actionable information.Test Runner
A subagent focused on running and analyzing test results. Isolates verbose test output from the main conversation.
---
name: test-runner
description: Run tests and analyze failures. Use proactively after code changes to verify correctness.
tools: Read, Grep, Glob, Bash
model: haiku
---
You are a test execution specialist. Run tests, analyze failures, and report results concisely.
When invoked:
1. Identify which tests to run based on the request
2. Execute the test suite
3. Analyze any failures
4. Report results in structured format
Output format:
## Test Results
**Status**: PASS / FAIL
**Total**: X tests, Y passed, Z failed
## Failures (if any)
1. **test-name**: Brief description of failure
- Expected: ...
- Actual: ...
- File: path/to/test:line
## Recommendations
- Suggested fixes for failuresSecurity Auditor
A focused auditor with sonnet for deeper reasoning about security patterns.
---
name: security-auditor
description: Audit code for security vulnerabilities and best practices. Use proactively before releases or when reviewing authentication, authorization, or data handling code.
tools: Read, Grep, Glob, Bash
model: sonnet
---
You are a security auditor. Analyze code for vulnerabilities and security best practices.
When invoked:
1. Identify the scope of the audit
2. Search for common vulnerability patterns
3. Check authentication and authorization logic
4. Review data handling and input validation
5. Assess dependency security
Check for:
- SQL injection, XSS, CSRF
- Hardcoded secrets or API keys
- Missing input validation
- Insecure authentication patterns
- Improper error handling that leaks information
- Unsafe dependency versions
- Missing rate limiting
- Insecure data storage
Report format:
## Security Audit
### Critical (must fix before release)
1. [Finding]: [Location] - [Description and fix]
### High (fix soon)
1. [Finding]: [Location] - [Description and fix]
### Medium (address in next sprint)
1. [Finding]: [Location] - [Description and fix]
### Recommendations
- General security improvementsExploration Agent
A lightweight read-only agent for discovering and documenting patterns in the codebase.
---
name: <domain>-explorer
description: Explore and understand <domain> patterns in the codebase. Use when researching existing implementations or understanding architecture.
tools: Read, Grep, Glob
model: haiku
---
# <Domain> Exploration Specialist
You explore and document <domain> patterns in this codebase.
## Exploration Process
1. **Scope** - Identify relevant directories and file patterns
2. **Discover** - Find implementations using Grep and Glob
3. **Analyze** - Read and understand patterns
4. **Document** - Summarize findings
## Key Patterns to Look For
- <Pattern 1>
- <Pattern 2>
- <Pattern 3>
## Output Format
\`\`\`markdown
## <Domain> Exploration Results
### Files Found
| File | Purpose |
| ---- | ------- |
| ... | ... |
### Patterns Identified
#### <Pattern Name>
[Description and examples]
### Recommendations
[How to apply these patterns]
\`\`\`Data Scientist
A domain-specific subagent for data analysis with explicit model selection for capable analysis.
---
name: data-scientist
description: Data analysis expert for SQL queries, BigQuery operations, and data insights. Use proactively for data analysis tasks and queries.
tools: Bash, Read, Write
model: sonnet
---
You are a data scientist specializing in SQL and BigQuery analysis.
When invoked:
1. Understand the data analysis requirement
2. Write efficient SQL queries
3. Use BigQuery command line tools (bq) when appropriate
4. Analyze and summarize results
5. Present findings clearly
Key practices:
- Write optimized SQL queries with proper filters
- Use appropriate aggregations and joins
- Include comments explaining complex logic
- Format results for readability
- Provide data-driven recommendations
For each analysis:
- Explain the query approach
- Document any assumptions
- Highlight key findings
- Suggest next steps based on data
Always ensure queries are efficient and cost-effective.Database Query Validator
Demonstrates using PreToolUse hooks for conditional tool validation. Allows Bash but blocks write SQL operations.
---
name: db-reader
description: Execute read-only database queries. Use when analyzing data or generating reports.
tools: Bash
hooks:
PreToolUse:
- matcher: 'Bash'
hooks:
- type: command
command: './scripts/validate-readonly-query.sh'
---
You are a database analyst with read-only access. Execute SELECT queries to answer questions about the data.
When asked to analyze data:
1. Identify which tables contain the relevant data
2. Write efficient SELECT queries with appropriate filters
3. Present results clearly with context
You cannot modify data. If asked to INSERT, UPDATE, DELETE, or modify schema, explain that you only have read access.The validation script for the hook:
#!/bin/bash
# ./scripts/validate-readonly-query.sh
# Blocks SQL write operations, allows SELECT queries
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if [ -z "$COMMAND" ]; then
exit 0
fi
if echo "$COMMAND" | grep -iE '\b(INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|TRUNCATE|REPLACE|MERGE)\b' > /dev/null; then
echo "Blocked: Write operations not allowed. Use SELECT queries only." >&2
exit 2
fi
exit 0Best Practices for Agent Design
1. Start with `/agents` command to generate an initial agent with Claude, then customize 2. One clear purpose per agent with a focused system prompt 3. Include trigger phrases in description ("Use proactively when...", "Use immediately after...") 4. Limit tool access to only what the agent needs 5. Include structured output formats for consistent results 6. Route simple tasks to haiku and complex analysis to sonnet or opus 7. Check project agents into version control for team sharing 8. Test and iterate on system prompts for better results
Role Description Best Practices
Be Specific
# Good - specific to project
You are a senior code reviewer for a TanStack Start + Better Auth project.
# Bad - too generic
You are a helpful assistant.Include Context
# Good - includes key conventions
Review code for:
- File naming: kebab-case
- Imports: Use @/ alias
- Types: Use `type` not `interface`
# Bad - no context
Review the code.Reference Skills
## Skill References
| Area | Skill |
| -------- | --------------- |
| Forms | `tanstack-form` |
| Auth | `auth` |
| Database | `database` |Use Proactive Triggers
Include trigger phrases in descriptions:
- "Use proactively after..."
- "MUST BE USED when..."
- "Use when encountering..."
These help Claude know when to automatically invoke the agent.
Output Format Examples
Structured Review
## Summary
Brief overall assessment in 1-2 sentences.
## Issues Found
1. **[Category]**: [File:line] - [Description]
- Fix: [Suggested fix]
## Recommendations
- [Optional improvements not blocking approval]
## Verdict
APPROVE / REQUEST CHANGES / NEEDS DISCUSSIONInvestigation Report
## Analysis
**Error**: Exact error message
**Location**: src/module/file.ts:123
**Type**: Runtime / Type / Build
## Root Cause
Explanation of why this happened.
## Evidence
- src/file1.ts:45 - Finding description
- src/file2.ts:78 - Related finding
## Fix
Specific code changes needed.
## Verification
Steps to confirm the fix works.Exploration Summary
## Exploration Results
### Files Found
| File | Purpose |
| ---------------------- | ------------------ |
| src/auth/index.ts | Auth configuration |
| src/auth/middleware.ts | Route protection |
### Patterns Identified
#### Pattern Name
Description with code examples.
### Recommendations
How to apply these patterns in new code.Tool Selection
Available Tools
Subagents can use any of Claude Code's internal tools. By default, subagents inherit all tools from the main conversation, including MCP tools.
| Tool | Purpose | Include When |
|---|---|---|
Read | Read file contents | Always (basic exploration) |
Grep | Search content by pattern | Pattern matching needed |
Glob | Find files by name | File discovery needed |
Bash | Run shell commands | Diagnostics, tests, builds |
Write | Create new files | Agent creates artifacts |
Edit | Modify existing files | Agent makes code changes |
WebFetch | Fetch web content | Documentation lookup |
WebSearch | Search the web | Research tasks |
Tool Access Control
Allowlist with tools
Restrict a subagent to specific tools only:
---
name: read-only-reviewer
description: Reviews code without modifications. Use proactively after code changes.
tools: Read, Grep, Glob
---When tools is specified, the subagent can only use those tools. Omit the field entirely to inherit all tools from the parent conversation (including MCP tools).
Denylist with disallowedTools
Remove specific tools from the inherited set:
---
name: safe-researcher
description: Research agent that cannot modify files
disallowedTools: Write, Edit
---This inherits all tools except Write and Edit. Use disallowedTools when you want most tools but need to block a few.
Combining Both
You can use both fields together. The disallowedTools removes tools from the tools allowlist:
---
name: restricted-bash
description: Run diagnostics without file modifications
tools: Read, Grep, Glob, Bash
disallowedTools: Write, Edit
---Common Tool Combinations
Read-Only Reviewer
tools: Read, Grep, GlobFor code review, style checking, and analysis tasks. Cannot modify files or run commands.
Investigator with Diagnostics
tools: Read, Grep, Glob, BashFor debugging, test execution, and system diagnostics. Can run commands but cannot modify source files directly.
Agent That Can Fix Issues
tools: Read, Grep, Glob, EditFor automated fixes like lint corrections or refactoring. Can modify existing files but cannot create new ones or run commands.
Full Modification Agent
tools: Read, Grep, Glob, Edit, Write, BashFor implementation tasks that require creating files, editing code, and running builds/tests.
Research Agent
tools: Read, Grep, Glob, WebFetch, WebSearchFor documentation lookup, API research, and gathering external information.
All Tools (Default)
# Omit the tools field entirelyInherits everything from the parent conversation, including MCP tools. Use when the agent needs full capabilities.
Conditional Tool Validation with Hooks
For finer control than allowlist/denylist, use PreToolUse hooks to validate specific operations:
---
name: db-reader
description: Execute read-only database queries
tools: Bash
hooks:
PreToolUse:
- matcher: 'Bash'
hooks:
- type: command
command: './scripts/validate-readonly-query.sh'
---The hook script receives JSON via stdin with the tool input in tool_input. Exit code 0 allows the operation, exit code 2 blocks it and feeds the stderr message back to the agent.
Model Selection Guide
| Model | Cost | Speed | Best For |
|---|---|---|---|
haiku | Low | Fast | Code review, style checks, simple validation, codebase search |
sonnet | Medium | Medium | Debugging, security analysis, implementation, complex reasoning |
opus | High | Slow | Architecture decisions, multi-system analysis, nuanced judgment |
inherit | Same as parent | Same as parent | When cost/speed should match the main conversation |
Decision Tree
Is this a simple checklist or search task?
Yes -> haiku
No -> Does it require modifying code or deep reasoning?
Yes -> sonnet
No -> Does it involve architecture or cross-system decisions?
Yes -> opus
No -> sonnet (safe default)Model Configuration
---
name: fast-reviewer
model: haiku
---- Model alias:
sonnet,opus, orhaiku - `inherit`: Uses the same model as the main conversation
- Omitted: Defaults to
inherit
Cost Optimization Patterns
Route simple tasks to haiku to reduce costs:
---
name: style-checker
description: Check code style and formatting. Use proactively after file edits.
tools: Read, Grep, Glob
model: haiku
---Reserve sonnet or opus for tasks requiring deeper analysis:
---
name: security-auditor
description: Audit code for security vulnerabilities. Use proactively before releases.
tools: Read, Grep, Glob, Bash
model: sonnet
---#!/usr/bin/env -S uv run --quiet --script
# /// script
# requires-python = ">=3.11"
# ///
"""
Validate Claude Code agent structure against best practices.
Usage:
uv run scripts/validate-agent.py <path> # Single file or directory
uv run scripts/validate-agent.py <glob-pattern> # Multiple agents
uv run scripts/validate-agent.py .claude/agents/ # All agents in directory
Examples:
uv run scripts/validate-agent.py .claude/agents/my-agent.md
uv run scripts/validate-agent.py .claude/agents/
uv run scripts/validate-agent.py ".claude/agents/*.md"
"""
import glob
import sys
from pathlib import Path
def parse_frontmatter(content: str) -> tuple[dict[str, str] | None, str | None]:
"""Parse YAML frontmatter from content."""
if not content.startswith("---"):
return None, "YAML frontmatter must start with --- on line 1"
lines = content.split("\n")
end_idx = None
for i, line in enumerate(lines[1:], 1):
if line.strip() == "---":
end_idx = i
break
if end_idx is None:
return None, "Invalid YAML frontmatter: missing closing ---"
frontmatter = {}
for line in lines[1:end_idx]:
line = line.strip()
if not line or line.startswith("#"):
continue
if ":" in line:
key, _, value = line.partition(":")
frontmatter[key.strip()] = value.strip().strip('"').strip("'")
return frontmatter, None
def resolve_agent_paths(path_arg: str) -> tuple[list[Path], str | None]:
"""
Resolve a path argument to a list of agent .md files.
Handles:
- Direct file path: .claude/agents/my-agent.md
- Directory path: .claude/agents/ (finds all .md files)
- Glob pattern: .claude/agents/*.md
Returns:
Tuple of (list of Path objects, error message if any)
"""
path = Path(path_arg)
# Case 1: Direct file path
if path.is_file():
if not path.suffix == ".md":
return [], f"Expected .md file, got: {path.name}"
return [path], None
# Case 2: Directory - find all .md files
if path.is_dir():
agent_files = [f for f in path.glob("*.md") if f.name != "README.md"]
if agent_files:
return sorted(agent_files), None
return [], f"No agent .md files found in: {path}"
# Case 3: Glob pattern
if "*" in path_arg or "?" in path_arg:
matches = glob.glob(path_arg, recursive=True)
agent_files = [Path(m) for m in matches if m.endswith(".md") and not m.endswith("README.md")]
if agent_files:
return sorted(agent_files), None
return [], f"No agent files match pattern: {path_arg}"
# Path doesn't exist
return [], f"Path not found: {path_arg}"
def validate_agent(path: Path) -> tuple[list[str], list[str]]:
"""Validate an agent .md file."""
errors: list[str] = []
warnings: list[str] = []
try:
content = path.read_text()
except PermissionError:
return [f"Permission denied: {path}"], []
except OSError as e:
return [f"Cannot read file: {e}"], []
lines = content.split("\n")
# Frontmatter validation
frontmatter, fm_error = parse_frontmatter(content)
if fm_error:
errors.append(fm_error)
elif frontmatter:
# Required fields
if "name" not in frontmatter:
errors.append("Missing required field: 'name'")
if "description" not in frontmatter:
errors.append("Missing required field: 'description'")
else:
desc = frontmatter["description"].lower()
if "proactively" not in desc and "use when" not in desc:
warnings.append("Description should include trigger phrases ('Use proactively' or 'Use when')")
# Optional but recommended
if "tools" not in frontmatter:
warnings.append("Consider adding 'tools' to restrict agent capabilities (omit to inherit all)")
# Validate model if present
if "model" in frontmatter:
valid_models = ["haiku", "sonnet", "opus", "inherit"]
if frontmatter["model"] not in valid_models:
warnings.append(f"Model '{frontmatter['model']}' - expected: {valid_models}")
# Line count
line_count = len(lines)
if line_count > 500:
errors.append(f"Agent file is {line_count} lines (max 500)")
elif line_count > 300:
warnings.append(f"Agent file is {line_count} lines (consider splitting)")
# Code block language specifiers
in_code = False
for i, line in enumerate(lines, 1):
if line.strip().startswith("```"):
if not in_code and line.strip() == "```":
errors.append(f"Line {i}: Code block missing language specifier (MD040)")
in_code = not in_code
# Check for output format section (good practice for reviewers)
content_lower = content.lower()
if "## output" not in content_lower:
warnings.append("Consider adding '## Output Format' section")
return errors, warnings
def print_result(path: Path, errors: list[str], warnings: list[str], verbose: bool = True) -> None:
"""Print validation results for a single agent."""
agent_name = path.stem
if errors:
print(f"❌ {agent_name}: FAILED")
if verbose:
for error in errors:
print(f" ✗ {error}")
elif warnings:
print(f"✓ {agent_name}: valid (with {len(warnings)} warning(s))")
if verbose:
for warning in warnings:
print(f" ⚠ {warning}")
else:
print(f"✓ {agent_name}: passed")
def main() -> int:
"""Main entry point."""
if len(sys.argv) < 2:
print("Usage: uv run scripts/validate-agent.py <path>")
print()
print("Accepts:")
print(" - File path: .claude/agents/my-agent.md")
print(" - Directory: .claude/agents/")
print(" - Glob pattern: '.claude/agents/*.md'")
print()
print("Examples:")
print(" uv run scripts/validate-agent.py .claude/agents/code-reviewer.md")
print(" uv run scripts/validate-agent.py .claude/agents/")
return 1
path_arg = sys.argv[1]
agent_paths, error = resolve_agent_paths(path_arg)
if error:
print(f"❌ Error: {error}")
return 1
if not agent_paths:
print("❌ No agents found to validate")
return 1
# Validate all agents
total_errors = 0
total_warnings = 0
failed_agents = []
# Single agent - verbose output
if len(agent_paths) == 1:
path = agent_paths[0]
errors, warnings = validate_agent(path)
if errors:
print("❌ Agent validation FAILED\n")
print("Errors:")
for error in errors:
print(f" ✗ {error}")
print()
if warnings:
print("Warnings:")
for warning in warnings:
print(f" ⚠ {warning}")
print()
if not errors and not warnings:
print("✓ Agent validation passed")
elif not errors:
print("✓ Agent valid (with warnings)")
return 1 if errors else 0
# Multiple agents - summary output
print(f"Validating {len(agent_paths)} agent(s)...\n")
for path in agent_paths:
errors, warnings = validate_agent(path)
total_errors += len(errors)
total_warnings += len(warnings)
if errors:
failed_agents.append(path.stem)
print_result(path, errors, warnings, verbose=bool(errors))
# Summary
print()
if failed_agents:
print(f"❌ {len(failed_agents)} agent(s) failed: {', '.join(failed_agents)}")
else:
print(f"✓ All {len(agent_paths)} agent(s) passed")
if total_warnings:
print(f" {total_warnings} total warning(s)")
return 1 if failed_agents else 0
if __name__ == "__main__":
sys.exit(main())