Workshop Studio
participantPublic visitor

Skills

Skills are the unified extension system in Claude Code, following the open Agent Skills standard (agentskills.io). They replace the older "commands" system and serve a dual purpose: they are both reusable knowledge patterns that Claude auto-discovers when relevant, and user-invocable slash commands that developers trigger explicitly with /<name>. A single skill can serve both roles, or specialize in one.

Each skill lives in a directory under .claude/skills/ with a SKILL.md entrypoint file. The directory-based structure is intentional — a skill can bundle supporting files (templates, schemas, reference docs) alongside its instructions, keeping everything self-contained and portable.

Claude Code ships with five bundled skills that are available in every project without any configuration:

IconSkillDescription
📦/batchProcess multiple files or operations in a single pass.
🔌/claude-apiGenerate code that calls the Anthropic API.
🐛/debugSystematic debugging workflow with root cause analysis.
🔄/loopIterative refinement loop — repeat until quality criteria met.
✂️/simplifyReduce complexity — fewer lines, clearer logic, less indirection.

These bundled skills demonstrate the patterns you should follow when building your own. They use frontmatter fields, $ARGUMENTS substitution, and context forking — all features available to custom skills.

A SKILL.md file has YAML frontmatter that controls how and when the skill activates, followed by markdown instructions that Claude follows when the skill is invoked:

.claude/skills/tdd-workflow/SKILL.md

---
name: tdd-workflow
description: "Test-Driven Development workflow: Red → Green → Refactor"
user-invocable: true
argument-hint: "<file-path>"
allowed-tools:
  - Read
  - Edit
  - Write
  - Bash
---

Follow the TDD workflow strictly:

## Step 1: Red
Write a failing test first. Run it to confirm it fails.
Command: `npm test -- --testPathPattern=$ARGUMENTS`

## Step 2: Green
Write the minimum code to make the test pass. No more.

## Step 3: Refactor
Clean up both test and implementation. Run tests again.

## Rules
- NEVER write implementation before the test exists
- Each test should test ONE behavior
- Test file must exist before source file

Key frontmatter fields control the skill's behavior:

FieldPurposeExample
nameSkill identifier (used as /name for slash commands)tdd-workflow
descriptionWhen to trigger — Claude uses this for auto-discovery"TDD workflow for test-first development"
user-invocableIf true, appears as a slash command (/tdd-workflow)true | false
argument-hintHint text shown after /name in autocomplete"<file-path>"
allowed-toolsRestrict which tools the skill can use[Read, Edit, Bash]
modelOverride the model for this skill executionhaiku, sonnet, opus
context: forkRun the skill in an isolated context (like a sub-agent)fork
disable-model-invocationIf true, skill only provides context — no AI reasoningtrue
$ARGUMENTS / $1 $2Special variables — replaced with user input after /name"src/routes/tasks.js"

Skills activate in two distinct ways, and understanding the difference is key to designing effective skills:

Auto-Discovered (Passive)User-Invoked (Active)
Claude reads the skill's description fieldDeveloper types /skill-name to trigger explicitly
When working context matches, skill loads automaticallyuser-invocable: true must be set in frontmatter
No user action required — seamless$ARGUMENTS captures text after the command name
Good for: conventions, standards, patternsGood for: workflows, multi-step processes, reports
Example: OWASP checklist loads when editing auth codeExample: /tdd-workflow src/routes/tasks.js

Many skills work in both modes. A tdd-workflow skill can auto-discover when Claude notices you are writing tests, and also be explicitly invoked with /tdd-workflow when you want to force the workflow for a specific file.

Skills can inject dynamic information into their instructions with the !command! syntax — for example, embedding !git diff --stat! inside a review skill runs the command at skill-load time and substitutes the output inline before Claude reasons over it. This makes skills adaptive to the current project state. Bangs run with your shell permissions and are not sandboxed — only use trusted commands, never user-controlled input.

Skills are directory-based packages, not just prompt files. The SKILL.md is the entrypoint, but the directory can contain anything the skill needs — scripts, templates, reference documents, schemas, example files:

<repo root>/
└── .claude/
    └── skills/
        └── generate-api/
            ├── SKILL.md              # Entrypoint — instructions + frontmatter
            ├── route-template.js     # Template Claude uses as a starting point
            ├── openapi-schema.yaml   # Reference schema Claude checks against
            ├── validate.sh           # Script invoked via !bash validate.sh!
            └── examples/
                ├── good-route.js     # Well-structured route
                └── bad-route.js      # Anti-pattern for Claude to avoid

Claude can read any file in the skill directory. This means you can package complex workflows — a code generator with templates, a review checklist with reference examples, a migration tool with schema definitions — as self-contained, portable units. Copy the directory to another project and the skill works.

This is what makes skills more powerful than just a well-crafted prompt. A prompt is instructions. A skill is instructions plus reference materials plus scripts plus templates — everything Claude needs to execute a workflow reliably.

Skills can live in three places, and the location determines who gets them:

LocationScopeUse for
.claude/skills/ (repo root)Team-shared, committed to gitProject-specific workflows — /validate-route referencing this API's conventions, /design-review against this project's ADRs
~/.claude/skills/Personal, machine-globalYour individual habits across every project — preferred commit-message style, personal explainer formats
Bundled (ship with Claude Code)Available everywhere, no setupThe five shown at the top of this page — /batch, /claude-api, /debug, /loop, /simplify

Rule of thumb: if another teammate on this repo would want the same slash command, commit it under .claude/skills/. If it is idiosyncratic to how you personally work, put it in ~/.claude/skills/. All TRY IT exercises in this workshop create project-level skills because they reference project-specific standards — making them personal would mean duplicating those standards for every project you touch.

The EPCC Workflow Plugin  is an open-source collection of skills for a full development workflow:

SkillPurpose
/prdGenerate a Product Requirements Document
/trdGenerate a Technical Requirements Document
/epcc-exploreMap the codebase — code archaeologist
/epcc-planDesign an implementation plan
/epcc-codeImplement with auto-validation
/epcc-commitRun tests and commit
/epcc-resumeResume interrupted work

Additional skill libraries:

  • mattpocock/skills — Small, composable engineering and productivity skills built for practical software-development workflows.
  • addyosmani/agent-skills — Production-grade skills that encode development workflows, quality gates, and engineering best practices across the software lifecycle.

Browse the source — each .md file is a skill you can read to see how production teams structure their workflow prompts. In the SDLC phases of this workshop, you will build your own skills (/validate-spec, /design-review, /self-review) following the same patterns.

Build a skill that validates a specific route file when invoked, demonstrating the $ARGUMENTS variable and dynamic context features.

Step 1 — Create the skill: Create the skill directory and SKILL.md:

Run in terminal:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mkdir -p .claude/skills/validate-route && cat > .claude/skills/validate-route/SKILL.md << 'SKILLEOF'
---
name: validate-route
description: "Validate an API route file against project conventions"
user-invocable: true
argument-hint: "<route-file-path>"
---

Validate the route file: $ARGUMENTS

Check against these standards:
1. All handlers validate input before processing
2. Error responses use { error: "message" } format
3. Correct HTTP status codes (201 create, 204 delete)
4. No direct file I/O — must use store.js functions
5. All async operations have error handling

Current project test status:
!npm test -- --watchAll=false 2>&1 | tail -5!
SKILLEOF

Observe: The skill is now available as /validate-route. The $ARGUMENTS variable will be replaced with whatever file path the developer specifies.

Step 2 — Start Claude Code: Start a Claude Code session:

Run in terminal:

1
claude

Step 3 — Test the skill: Invoke the skill:

Tell Claude:

/validate-route src/routes/tasks.js

Observe: Claude loads the skill, replaces $ARGUMENTS with src/routes/tasks.js, executes the npm test command for dynamic context, and then validates the route file against the listed standards. Skills bridge the gap between reusable conventions (auto-discovered) and team workflows (user-invoked) — the $ARGUMENTS and !command! features make them dynamic and context-aware, far more powerful than static documentation.

You may have noticed that the validate-route skill contains API standards (error format, status codes, store.js usage) that also appear in CLAUDE.md, @imported docs, and .claude/rules/. This overlap is intentional — each location serves a different purpose based on when Claude needs the information:

LocationWhen It LoadsUse ForContext Cost
CLAUDE.md / @importsEvery session, always in contextThings Claude should know no matter what it is doing — project overview, key commands, universal conventionsAlways paid
.claude/rules/ with globsWhen Claude touches matching filesStandards for a category of files — "when editing route files, always validate input"Paid only when relevant files are open
SkillsOnly when invoked or auto-discoveredActive workflows that produce output — "validate this file against our checklist and report findings"Zero until invoked

The key distinction: rules are passive context — Claude knows about them while working on matching files (progressive disclosure). A skill is an active workflow that uses standards to produce a structured output. The validate-route skill is not just "here are our API standards" — it is "run this checklist against a specific file and tell me what is wrong."

The anti-pattern is putting standards only in a skill. Then Claude would not know about them during normal coding — it would only apply them when you explicitly invoke the validation. You want the knowledge ambient (.claude/rules/ with globs) and the workflow on-demand (skills).