Skills use markdown files with YAML frontmatter following the agentskills.io specification:
---name: skill-namedescription: Brief description for discovery and trigger matching.allowed-tools: Read Grep Glob---[Prompt body - the actual instructions for Claude]
Explain what the agent receives and how to approach it:
## ScopeYou receive scoped code chunks from Warden's diff pipeline. Analyze eachchunk against the checks below. Only report findings you can prove from the code.
The core of the skill—specific patterns to detect:
## Checks### Check 1: SQL Injection**Red flags:**- String concatenation building SQL: `"SELECT * FROM users WHERE id = " + userId`- Template literals with user input: `SELECT * FROM ${table}`**Safe patterns:**- Parameterized queries: `db.query('SELECT * FROM users WHERE id = ?', [userId])`- Query builders: `knex('users').where('id', userId)`**Not a bug:**- Hardcoded SQL strings without user input- SQL in comments or logging---### Check 2: [Next Check]...
## Confidence Calibration| Level | Criteria | Action ||-------|----------|--------|| HIGH | Pattern traced to specific code, confirmed triggerable | Report || MEDIUM | Pattern present, context may mitigate | Read more, then decide || LOW | Vague resemblance | Do NOT report |When in doubt, read more files. Never guess.
## Report FormatFor each finding:- File path and line number- Which check it matches- One sentence: what is wrong- Why it matters (trigger condition)- Suggested fix (if obvious)### Zero findingsIf no checks fire, report nothing. Silence means the code is clean.
## Severity Levels- **critical**: Crash, data loss, or security breach in normal usage- **high**: Incorrect behavior in common scenarios- **medium**: Incorrect behavior in edge cases- **low**: Minor issues or style concernsDo NOT report low severity. If confidence is that low, don't report it.
For complex skills, split knowledge into reference files:
.agents/skills/agent-prompt/├── SKILL.md # Main entry point└── references/ # Supporting documentation ├── core-principles.md # Foundational rules ├── agentic-patterns.md # Tool-using patterns ├── anti-patterns.md # What to avoid └── context-design.md # Research notes
Reference files from the main skill:
SKILL.md
## Reference DocumentsRead the relevant reference files based on the user's question:| Document | Use When ||----------|----------|| `references/core-principles.md` | Writing any prompt || `references/agentic-patterns.md` | Building tool-using agents || `references/anti-patterns.md` | Reviewing for mistakes |
When Warden loads a skill, it sets the rootDir property to the directory containing SKILL.md. This allows reference files to be resolved relative to the skill:
// Internal loader behaviorconst skill = await loadSkillFromMarkdown(skillPath);// skill.rootDir === dirname(skillPath)// References in references/ are relative to rootDir
This enables skills to bundle supporting documentation and have it automatically discoverable.
Here’s a complete example with all best practices:
.agents/skills/check-sql-injection/SKILL.md
---name: check-sql-injectiondescription: "Detect SQL injection vulnerabilities from improper query construction"allowed-tools: Read Grep Globmetadata: category: security severity: critical---You are a security-focused code reviewer specialized in SQL injection detection.## ScopeAnalyze code for SQL injection vulnerabilities. Focus on database query construction.You receive code chunks from diffs—analyze each against the check below.## Check: SQL Injection via String Concatenation**Red flags:**- String concatenation building SQL with user input: `query = "SELECT * FROM users WHERE id = " + userId`- Template literals interpolating variables: `query = `SELECT * FROM ${table} WHERE id = ${id}``- `.format()` or f-strings building SQL- User-controlled values in WHERE/ORDER BY/LIMIT without parameterization**Safe patterns:**- Parameterized queries: `db.query('SELECT * FROM users WHERE id = ?', [userId])`- ORM methods: `User.findOne({ id: userId })`- Query builders: `knex('users').where('id', userId)`- Hardcoded SQL strings (no user input)**Not a bug:**- Concatenation of hardcoded SQL fragments (table/column names from constants)- SQL in logging or error messages (not executed)- SQL in comments or documentation## Confidence Calibration| Level | Criteria | Action ||-------|----------|--------|| HIGH | User input flows directly into concatenated SQL | Report as critical || MEDIUM | Indirect flow or partial sanitization | Report as high || LOW | No user input or fully parameterized | Do not report |Read more context if the data flow is unclear.## Report FormatFor each vulnerability:- File path and line number- The vulnerable code line- What user input flows into the query (trace the variable)- Why parameterization is needed (explain the attack vector)- How to fix (show parameterized version)### Zero findingsIf no vulnerabilities found, report nothing.## Severity Levels- **critical**: User input directly concatenated into executed SQL- **high**: Indirect flow without proper validation- **medium**: Sanitization present but insufficient (blocklist-based, etc.)