← Claude Code & Certification

Introduction to Agent Skills — Study Notes

Introduction to Agent Skills — Study Notes

Comprehensive exam preparation for the Anthropic “Introduction to Agent Skills” (Claude Code) course. These notes synthesize the official curriculum with real-world examples from the claude-distribution repository.


Module 1: What Are Skills?

Key Notes

Core Definition

  • Skills are reusable, triggered workflows that encapsulate complex agent behaviors
  • A skill is NOT a prompt instruction, rule, or hook — it’s a discrete, invokable command
  • Each skill has its own system prompt, tool restrictions, and context isolation
  • Skills exist in /skills/{skillname}/SKILL.md within the .claude/ distribution folder

Why Skills Matter

  • Consistency — Same workflow runs the same way every time, not subject to prompt variability
  • Reusability — Define once, invoke in many projects (via submodule or symlink)
  • Context Isolation — A skill’s exploratory reading doesn’t pollute the main session’s context window
  • Team Alignment — Everyone uses the same skill definition; no drift in how tasks are approached
  • Delegation — Skills enable subagent specialization (read-only scouts, safety auditors, code reviewers)

Skill vs. Instruction File (CLAUDE.md)

  • CLAUDE.md — Project-specific rules, conventions, and environment setup (checked into git, per-project)
  • Skill — Reusable action that can be invoked manually or embedded in workflows; shareable across projects
  • CLAUDE.md sets up the context; skills define behaviors

Skill Trigger Mechanism

  • User types /skillname (slash notation) to invoke
  • System detects the trigger and spawns the skill’s logic
  • Skill runs with its declared system prompt, tool permissions, and agent type
  • Returns final output; main context absorbs only the result

When to Use Skills

  • Repetitive processes you want identical every time (deployments, audits, reviews)
  • Exploratory tasks where you want context isolation (research, code scouting)
  • Multi-phase workflows with specialized tool restrictions (safety gates, read-only verification)
  • Processes that need subagent specialization (let one agent verify, another implement)
  • Shareable templates across multiple projects (testing pattern, CI analysis, documentation generator)

Best Practices

  • Atomic scope — A skill solves ONE well-defined problem (not ten loosely related things)
  • Clear trigger — The /skillname should intuitively match what it does (not cryptic abbreviations)
  • Constrain tools — List only the tools the skill actually needs (fail-safe defaults to read-only)
  • Progressive disclosure — Large skills should have internal phases; show results incrementally, not a wall of output
  • Output clarity — Skill’s final output format should be actionable for the user (reports, diffs, checklists)
  • Avoid duplication — If CLAUDE.md already defines a behavior, don’t replicate it in a skill
  • Version explicitly — Each SKILL.md includes a version: field for tracking breaking changes

Module 2: Creating Your First Skill

Key Notes

SKILL.md Frontmatter (YAML metadata at top)

---
name: skillname                    # kebab-case identifier; becomes /skillname trigger
version: 1.0.0                     # semver for tracking breaking changes
description: |                     # Multi-line string describing what the skill does
  One sentence user value.
  When to use it (trigger phrases).
argument-hint: "[optional-arg]"    # Hint for what user can pass; e.g., "[url]", "[feature-name]"
agent: Explore                     # Agent type: Explore, Verification, Plan, General, etc.
context: fork                      # Context mode: default (inherit), fork (new clean context)
preamble-tier: 2                   # How much preamble injected (0=none, 1=minimal, 2=standard)
allowed-tools:                     # Whitelist of tools available to this skill
  - Bash
  - Read
  - Write
  - Edit
  - Glob
  - Grep
  - AskUserQuestion
sensitive: true                    # If true, skill is marked sensitive (privacy, security)
hooks:
  PreToolUse:                      # Optional inline hooks triggered during skill execution
    - matcher: "Bash"
      hooks:
        - type: command
          command: "bash path/to/check.sh"
---

Agent Types (determines system prompt specialty)

  • Explore — Read-only codebase explorer; finds information, produces reports
  • Verification — Adversarial tester; tries to break code, checks security
  • Plan — Architect mode; discusses approach before building
  • General — Full capabilities; for complex workflows
  • Claude Code Guide — Answers questions about the tool itself

Context Modes

  • default (inherit) — Runs with main session’s context history; good for continuation
  • fork — Runs with clean context; good for isolated research, prevents pollution

Tool Allowlist (security + focus)

  • List only tools the skill needs
  • Omit tools = fail-safe (agent can’t use them)
  • Common safe tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
  • Common restricted tools: Task (for subagent spawning; needs explicit approval), WebFetch (external data)

Body Structure (Markdown after frontmatter)

  1. Preamble section — Auto-injected context about Claude Code capabilities (if preamble-tier > 0)
  2. User-facing heading/skillname — Description
  3. Core workflow — Numbered steps, code blocks, examples
  4. Output format — Where results go, what format to use
  5. Important rules — Gates (e.g., “DO NOT fix code, only report”) and constraints

Template Variables (auto-substituted)

  • {{PREAMBLE}} — System context about Claude Code (preamble-tier 1–2)
  • {{SLUG_SETUP}} — Code to compute project slug for storing state
  • {{SNAPSHOT_FLAGS}} — Documented flags for a specific tool
  • {{COMMAND_REFERENCE}} — Reference table for a tool’s command set

Example

Real-world example from the distribution: /browse skill for QA testing.

---
name: browse
version: 1.1.0
description: |
  Fast headless browser for QA testing and site dogfooding. Navigate any URL, interact with
  elements, verify page state, diff before/after actions, take annotated screenshots, check
  responsive layouts, test forms and uploads, handle dialogs, and assert element states.
  ~100ms per command. Use when you need to test a feature, verify a deployment, dogfood a
  user flow, or file a bug with evidence. Use when asked to "open in browser", "test the
  site", "take a screenshot", or "dogfood this".  
argument-hint: "[url]"
allowed-tools:
  - Bash
  - Read
  - AskUserQuestion
---

{{PREAMBLE}}

# browse: QA Testing & Dogfooding

Persistent headless Chromium. First call auto-starts (~3s), then ~100ms per command.
State persists between calls (cookies, tabs, login sessions).

{{BROWSE_SETUP}}

## Core QA Patterns

### 1. Verify a page loads correctly
\`\`\`bash
$B goto https://yourapp.com
$B text                          # content loads?
$B console                       # JS errors?
$B network                       # failed requests?
$B is visible ".main-content"    # key elements present?
\`\`\`

### 2. Test a user flow
\`\`\`bash
$B goto https://app.com/login
$B snapshot -i                   # see all interactive elements
$B fill @e3 "user@test.com"
$B fill @e4 "password"
$B click @e5                     # submit
$B snapshot -D                   # diff: what changed after submit?
$B is visible ".dashboard"       # success state present?
\`\`\`

## Important Rules

1. **Always read screenshots** — After taking a screenshot, use the Read tool so the user can see it
2. **Persistent state** — Browser cookies, localStorage, and tabs persist across commands
3. **Handoff to user** — If stuck on CAPTCHA, OAuth, or MFA, use `$B handoff` to open visible Chrome

Key Design Points from This Example

  • Atomic focus — One skill does browser testing, nothing else
  • Constrained tools — Only Bash, Read, AskUserQuestion (no file edits)
  • Clear patterns — Step-by-step examples show typical workflows
  • Hard gate// Always read screenshots ensures user visibility
  • Progressive disclosure — Each command is small and fast (~100ms); user can verify state incrementally

Module 3: Configuration and Multi-File Skills

Key Notes

Multi-File Skill Structure

A skill can span multiple files for modularity:

skills/
└── entropy/
    ├── SKILL.md                          # Frontmatter + main logic
    ├── lib/                              # Shared code libraries
    │   ├── patterns.js                   # Dead code patterns
    │   └── analysis.js                   # Scoring logic
    ├── bin/                              # Executable scripts
    │   └── scan.sh                       # Main scanning loop
    └── data/                             # Data templates
        └── report-template.md            # Report structure

File Organization Patterns

  • SKILL.md — Only for metadata and user-facing instructions (keep lean; under 200 lines of actual instructions)
  • lib/{name}.js — Reusable code for analysis, formatting, state management
  • bin/{name}.sh — External scripts invoked by the skill (keeps SKILL.md readable)
  • data/{name} — Templates, configs, data definitions
  • .env — Environment variables for API keys, rate limits (gitignored)

Loading Multi-File Content

Skills reference external files via environment variables:

  • $CLAUDE_SKILL_DIR — Path to the skill’s directory (e.g., /path/to/.claude/skills/entropy/)
  • $CLAUDE_PROJECT_DIR — Path to the target project root

Example from /entropy skill:

# In SKILL.md
{{PREAMBLE}}

# /entropy — Codebase Health Scan

To detect dead code:
\`\`\`bash
node $CLAUDE_SKILL_DIR/lib/patterns.js --mode deadcode --cwd $CLAUDE_PROJECT_DIR
\`\`\`

Settings-Driven Configuration

Skills can register hooks in settings.json to auto-trigger on certain events:

{
  "skills": {
    "careful": {
      "enabled": true,
      "hooks": {
        "PreToolUse": {
          "matcher": "Bash",
          "command": "bash ${CLAUDE_SKILL_DIR}/bin/check-careful.sh"
        }
      }
    }
  }
}

The /careful skill hooks every bash command to warn about destructive patterns (rm -rf, DROP TABLE, git push --force, etc.) before execution.

Progressive Disclosure Pattern

For large skills, output results in phases to avoid overwhelming the user:

# Phase 1: Quick Summary (1 minute)
- {N} issues found
- Top 3 recommendations

# Phase 2: Detailed Report (2 minutes)
- Full issue list with files and line numbers
- Severity breakdown
- Suggested fixes

# Phase 3: Implementation Support (on demand)
- "Shall I fix these automatically? [yes/no]"

State Management Across Invocations

Skills can store state in ~/.gstack/projects/{project_slug}/:

# In skill, compute slug
SLUG=$(git rev-parse --show-toplevel | md5sum | cut -d' ' -f1)
mkdir -p ~/.gstack/projects/$SLUG

# Store data
echo '{"ts":"2026-04-24T...","score":9.1}' >> ~/.gstack/projects/$SLUG/health-history.jsonl

# Retrieve history
tail -10 ~/.gstack/projects/$SLUG/health-history.jsonl

This lets skills track trends over time (e.g., /health skill tracks code quality scores across runs).

Best Practices

  • DRY across skills — If two skills need the same analysis, extract to lib/shared.js
  • Fail gracefully — If an external script doesn’t exist, inject a helpful error message
  • Document file layout — Add a # Files section to SKILL.md explaining what each file does
  • Version external deps — If a skill calls external CLIs (node, python, bash), document version requirements
  • Keep SKILL.md scannable — Max 200 lines of instructional content; delegate to external files
  • Use sensible defaults — If config is missing, apply safe defaults (e.g., read-only mode)
  • Atomic lib functions — Each lib file exports one focused function or set of related functions

Example: Multi-File Skill Structure

From /health skill (code quality dashboard):

SKILL.md (70 lines of user instructions + frontmatter)

  • Frontmatter declares tools, agent type, tiers
  • Step-by-step workflow
  • Output format
  • Hard gate: “DO NOT fix issues, only report”

lib/scoring.js (score calculation)

function scoreTypeCheck(toolOutput) {
  const errors = (toolOutput.match(/error TS/g) || []).length;
  if (errors === 0) return 10;
  if (errors < 10) return 7;
  if (errors < 50) return 4;
  return 0;
}

bin/detect-tools.sh (auto-detect available tools)

# Detects tsc, biome, jest, knip, shellcheck
# Returns list of available tools in "TOOL:command" format

data/report-template.md (dashboard template)

CODE HEALTH DASHBOARD
=====================
Project: {project_name}
Branch: {branch}
Date: {date}

Category | Score | Status
---------|-------|--------

Module 4: Skills vs. Other Claude Code Features

Key Notes

The Four Tools of the Harness

Claude Code provides four tools for automating agent behavior. They exist on a spectrum from “context pollution” (high) to “reusability” (high).

FeatureScopeReusabilityContext CostExecutionBest For
CLAUDE.mdPer-projectLow (project-specific)High (always loaded)Passive (read by agent)Project setup, conventions, environment
HooksSystem-wideHigh (across all projects)Low (injected on-demand)Deterministic (system runs them)Invariants, safety gates, auto-triggers
Rules (rules/)System-wideHigh (across all projects)Medium (auto-loaded, lean)Passive (read by agent)Behavioral guidance, principles
SkillsSystem-wideHigh (across all projects)None (isolated context)Active (user invokes)Reusable workflows, delegation, specialization

Detailed Comparison

CLAUDE.md

  • Scope — Everything in a project directory and below
  • Triggered — Auto-loaded every session; agent always sees it
  • Format — Markdown with structured sections (Health Stack, Project Rules, Interfaces, Tools)
  • Context cost — Adds to every LLM call (includes in main context window)
  • Reusability — Low; each project has its own CLAUDE.md
  • Use when — You need project-specific context (e.g., “this project uses Biome, not ESLint”)
  • ExampleCLAUDE.md describes the project’s architecture, coding standards, and how to run tests

Hooks

  • Scope — System-wide; defined in .claude/settings.json
  • Triggered — Automatically at specific lifecycle points (SessionStart, PreToolUse, PostToolUse, Stop, etc.)
  • Format — Shell commands (.cjs CommonJS scripts) that run outside the LLM’s context
  • Context cost — Low (runs in the system, not in the model’s context window, though output can be injected)
  • Reusability — Very high; hooks apply to all projects using that .claude/ distribution
  • Use when — You need deterministic enforcement (e.g., “always run type-check before accepting a commit”)
  • Example/loop-detection hook watches for repeated edits to the same file and blocks if threshold exceeded

Rules (auto-loaded markdown files in rules/)

  • Scope — System-wide
  • Triggered — Auto-loaded at session start; injected into system prompt
  • Format — Markdown with principles, guidelines, conventions
  • Context cost — Medium (every line uses tokens; competes with code, docs, conversation)
  • Reusability — Very high; apply to all projects
  • Use when — You have behavioral principles to teach the agent (e.g., “always follow KISS and YAGNI”)
  • Exampledevelopment-rules.md teaches the agent to split files > 200 lines, use try-catch, avoid code duplication

Skills

  • Scope — System-wide; invoked on-demand by the user
  • Triggered — User types /skillname (opt-in, not automatic)
  • Format — SKILL.md with frontmatter, optional multi-file support
  • Context cost — Zero for main session (runs in isolated context)
  • Reusability — Very high; share skills across projects
  • Use when — You have a repeatable workflow that should be isolated (research, audits, code review, testing)
  • Example/browse skill runs a headless browser for QA testing; its context doesn’t pollute the main session

Comparison Table: When to Use Which

ScenarioUseReason
“This project uses Biome, not ESLint”CLAUDE.mdProject-specific context that agents need on every call
“Always check for merge conflicts before pushing”Hook (PreToolUse on Bash, matching push pattern)Deterministic enforcement; runs automatically
“Never repeat yourself; extract common patterns”Rule (development-rules.md)Behavioral principle; teaches the agent culture
“I want a specialist agent to run tests in isolation”Skill (/test)Spawns a focused agent; context doesn’t pollute main session
“Block high-risk git commands; warn on rm -rfHook (PreToolUse on Bash)Deterministic; user can’t forget the warning
“Test coverage should be >80% before merge”Skill (/health or /verify)Complex logic; easier as a skill than a rule
“All Python files should follow PEP-8”CLAUDE.md or RuleGuidance; agent should check every Python file
“Log all tool calls to ~/.gstack/ for analytics”Hook (PreToolUse on *)Deterministic; happens every time, no prompt needed

Examples from Real Skills

/entropy — Codebase Health Scan

  • Uses agent: Explore (read-only specialist)
  • Context mode fork (clean context, no pollution)
  • Allowed tools: Bash, Read, Grep, Glob, AskUserQuestion
  • Produces a report; doesn’t modify code
  • Could be a rule, but benefits from focused tools + isolated context

/health — Code Quality Dashboard

  • Uses agent: Explore
  • Wraps existing tools (tsc, biome, jest, knip)
  • Scores categories, tracks trends in ~/.gstack/
  • Too complex for CLAUDE.md; too workflow-heavy to be just a rule

/decompose — Feature Spec Generator

  • Uses default context (inherits main session)
  • Asks clarifying questions; produces feature specs
  • Could be a rule (“always decompose features”), but skill isolates the analysis

/careful — Destructive Command Safety

  • Uses a Hook (PreToolUse on Bash)
  • Checks every bash command before execution
  • Deterministic (system runs it, not prompt)
  • Can’t be a skill (needs to trigger automatically)

Module 5: Sharing Skills

Key Notes

Distribution via Claude Distribution

Skills are shared via the claude-distribution repository (.claude/ in target projects):

# In a project, add the distribution as a submodule
git submodule add https://github.com/org/claude-distribution .claude

# Update to latest skills, hooks, rules, config
git submodule update --remote .claude

# Or symlink to a local copy (development)
ln -s ~/claude-distribution /path/to/project/.claude

Folder Structure

.claude/
├── skills/
│   ├── browse/
│   │   ├── SKILL.md
│   │   ├── bin/
│   │   └── lib/
│   ├── entropy/
│   ├── decompose/
│   └── ...
├── hooks/
│   ├── session-init.cjs
│   ├── loop-detection.cjs
│   └── lib/
├── rules/
│   ├── development-rules.md
│   ├── git-safety.md
│   └── ...
├── settings.json
└── docs/
    ├── system-architecture.md
    └── code-standards.md

Skill Discovery

Claude Code automatically discovers all skills in {project}/.claude/skills/:

  • User types / and sees autocomplete list
  • Matches trigger names from name: field in SKILL.md
  • Filters by description to help user find relevant skills

Versioning and Breaking Changes

Each skill includes a version: field (semver):

---
name: health
version: 1.2.1
description: |
  Code quality dashboard. (No breaking changes in 1.x)  
---

Releasing Breaking Changes

If a skill’s interface changes incompatibly:

version: 2.0.0
description: |
  BREAKING: Output format changed from CSV to JSON (v1.x users: see migration guide)  

Consumers must explicitly acknowledge the breaking change.

Enterprise Distribution

For organizations:

  1. Fork claude-distribution (or create a custom distribution)
  2. Add your organization’s skills to skills/
  3. Distribute via internal git server or package registry
  4. Projects add via: git submodule add https://internal-git/claude-dist .claude

Documentation for Shared Skills

Every skill distributed should include:

  1. SKILL.md preamble — What it does, when to use it
  2. Usage examples — How to invoke it and typical workflows
  3. Output format — What to expect from the skill
  4. Tool requirements — Does it need special permissions?
  5. Limitations — What it can’t do
  6. Troubleshooting — Common issues and fixes

Plugin Ecosystem (Future)

Claude Code is designed for a skill marketplace:

  • Users can publish skills to a registry
  • Community skills can be installed with a single command
  • Versioning prevents breakage across organizations
  • All skills run in the same sandboxed environment

Best Practices

  • Name skills intuitively/browse is clear; /agg-qa-analysis-tool is not
  • Document prerequisites — If a skill needs specific tools (Node.js 18+, Python 3.10+), say so
  • Keep skills backward compatible — If you must break the interface, bump major version
  • Test across projects — A skill should work in multiple projects, not one specific context
  • Minimize external dependencies — Prefer built-in tools (Bash, Node.js) over CLI packages
  • Provide a quick-start — First paragraph of SKILL.md should show the simplest use case

Module 6: Troubleshooting Skills

Key Notes

Skill Doesn’t Trigger

Symptom: User types /skillname but nothing happens.

Causes and Fixes:

  1. Skill file not in .claude/skills/{name}/SKILL.md

    • Verify folder structure: ls -la .claude/skills/skillname/SKILL.md
    • Ensure SKILL.md exists and is readable
  2. Syntax error in frontmatter

    • YAML parsing fails silently
    • Fix: Validate YAML syntax (use an online YAML linter)
    • Common: missing quotes in multiline strings
    description: |
      Multi-line strings need the pipe (|) operator
      and proper indentation  
    
  3. Skill name mismatch

    • SKILL.md has name: foo but user types /bar
    • Fix: Verify name: field in frontmatter matches the folder name
  4. Settings disable the skill

    • In settings.json, a skill might be disabled
    • Fix: Check settings.json for "enabled": false on the skill

Skill Starts but Exits Immediately

Symptom: Skill runs, but finishes in <1 second with no output.

Causes and Fixes:

  1. Missing template variable

    • SKILL.md references {{UNKNOWN_VARIABLE}} that doesn’t exist
    • System fails to substitute and exits
    • Fix: Remove unknown variables or define them in a hook
  2. Context fork failed

    • Skill declares context: fork but fork creation failed
    • Fix: Check git worktree status: git worktree list
    • Ensure .claude/hooks/ has worktree-init.cjs (manages worktrees)
  3. Agent type not recognized

    • agent: InvalidType — must be one of: Explore, Verification, Plan, General, Claude Code Guide
    • Fix: Use a valid agent type
  4. Tool whitelist too restrictive

    • Skill declares allowed-tools: [Read] but the code needs Write
    • Agent fails silently when it tries to use unavailable tool
    • Fix: Add missing tools to allowed-tools:

Skill Starts but Agent Refuses to Work

Symptom: Skill context loads, but agent says “I don’t have permission” or “Tool not available.”

Causes and Fixes:

  1. Tool not in whitelist

    • Agent needs Write but allowed-tools: [Read, Bash]
    • Fix: Add the tool to allowed-tools:
    allowed-tools:
      - Read
      - Write
      - Bash
    
  2. Permission not granted

    • Skill declares allowed-tools: [Bash], but settings.json restricts Bash execution
    • Fix: Add permission to settings.json or project’s .claude/settings.local.json
    {
      "permissions": {
        "Bash": ["allow"]
      }
    }
    
  3. Subagent not allowed

    • Skill tries to spawn a subagent (Task tool) but it’s not whitelisted
    • Fix: Add Task to allowed-tools and ensure it’s permitted in settings

Skill Output is Garbled or Wrong Format

Symptom: Skill produces output but it’s not in the expected format.

Causes and Fixes:

  1. Wrong preamble-tier

    • preamble-tier: 2 injects extra context that interferes with output
    • Fix: Lower tier if output is polluted: preamble-tier: 0 or 1
  2. Template variable not substituted

    • {{PREAMBLE}} or {{BROWSE_SETUP}} appears in output instead of being filled
    • Fix: These are special variables. If custom, define in a hook or validate they exist
  3. Agent ignoring output format instructions

    • SKILL.md says “output as JSON” but agent produces markdown
    • Fix: Make the output instruction a hard gate:
    # HARD GATE: Output format
    
    ALWAYS produce output as valid JSON. NO markdown wrappers. NO explanatory text.
    
    \`\`\`json
    { "results": [...] }
    \`\`\`
    
  4. External script returning unexpected data

    • Skill calls bash $CLAUDE_SKILL_DIR/bin/analyze.sh but the script produces errors
    • Fix: Test the script independently first:
    bash path/to/.claude/skills/skillname/bin/analyze.sh
    # Check exit code: echo $?
    # Should exit 0 on success
    

Skill Errors Out During Execution

Symptom: Skill runs, but fails partway through with an error.

Causes and Fixes:

  1. Path not found

    • Script tries to read $CLAUDE_PROJECT_DIR/nonexistent/file.txt
    • Fix: Use absolute paths; verify paths exist before reading:
    [ -f "$CLAUDE_PROJECT_DIR/file.txt" ] || echo "File not found"
    
  2. Tool permission denied

    • Agent tries to Write but permission denied
    • Fix: Add permission or use a tool that’s allowed
  3. Script timeout

    • External script takes too long (e.g., large repo scan)
    • Fix: Add timeout handling in the hook:
    hooks:
      PreToolUse:
        - command: "bash $CLAUDE_SKILL_DIR/bin/analyze.sh"
          timeout: 60
    
  4. Dependency not installed

    • Script calls node or python but not in PATH
    • Fix: Check if tool is available; provide fallback:
    command -v node >/dev/null 2>&1 || { echo "Node.js not found"; exit 1; }
    

Skill Output Doesn’t Match User Expectations

Symptom: Skill technically works, but the output isn’t useful.

Causes and Fixes:

  1. Output too verbose

    • Skill produces 50 lines when user expected 5
    • Fix: Add progressive disclosure (quick summary first, detailed on request)
  2. Output too terse

    • Skill produces “Done” when user wanted details
    • Fix: Structure output with headings, tables, bullet points
  3. Missing context for user action

    • Skill reports 10 issues but doesn’t say how to fix them
    • Fix: Add recommendations section with actionable next steps

Skills Not Updating After Changes

Symptom: User edits SKILL.md but changes don’t take effect.

Causes and Fixes:

  1. Submodule not updated

    • User edited the skill in .claude/ submodule but never committed
    • Fix: Changes in submodules don’t auto-sync; must commit and push:
    cd .claude/skills/myskill
    git add SKILL.md
    git commit -m "Update myskill description"
    git push origin main
    cd ../..
    git add .claude
    git commit -m "Update .claude submodule"
    
  2. Local override not applied

    • Skill exists in .claude/ but user created a local copy in project
    • Claude Code finds the local copy first and ignores the distribution
    • Fix: Remove local copy and use the distribution’s version
  3. Session cache not cleared

    • Claude Code caches the skill definition for the session
    • Fix: Restart the session (or use /clear to reset context)

Common Issues & Fixes Table

IssueCheckFix
Skill doesn’t appear in / autocompleteSKILL.md exists in .claude/skills/{name}/Restart session, check YAML syntax
Skill runs but does nothingallowed-tools includes what agent needsAdd missing tool to whitelist
Agent says “I don’t have permission”Check settings.json and project .claude/settings.local.jsonAdd permission or allow tool
Output format is wrongRead SKILL.md “Output” sectionMake format constraint a HARD GATE
External script failsTest script independently: bash path/to/script.shFix script, check return code, verify paths
Changes to SKILL.md don’t take effectCheck if in submodule; commit changes if soPush changes, restart session
Subagent (Task tool) failsAgent type and allowed-tools include TaskEnsure Task permission in settings.json
Skill is too slowCheck for unnecessary file reads or API callsAdd caching, parallelize, use streaming output

Quick Reference

SKILL.md Template (Minimal)

---
name: myskill
version: 1.0.0
description: |
  One sentence of user value.
  Trigger phrases: when asked to "...", use when "..."  
argument-hint: "[optional-arg]"
allowed-tools:
  - Bash
  - Read
  - Grep
  - AskUserQuestion
---

# /myskill — Description

{{ PREAMBLE }}

## Step 1: Gather input

Ask the user or read context.

## Step 2: Process

Analyze, compute, search.

## Step 3: Output

Present results in clear format.

## Important Rules

- HARD GATE: Never modify code without user consent
- ALWAYS output as markdown table

Frontmatter Quick Lookup

FieldTypeRequiredDefaultExamples
namestring (kebab-case)browse, entropy, health
versionsemver1.0.0, 2.1.3
descriptionmultiline stringFast headless browser...
argument-hintstring""[url], [feature-name]
agentstringGeneralExplore, Verification, Plan
contextstringdefaultdefault, fork
preamble-tier0, 1, 210 (none), 2 (full)
allowed-toolsarray of strings[][Bash, Read, Write, Task]
sensitivebooleanfalsetrue (for privacy-sensitive)
hooksobject{}PreToolUse, PostToolUse

When to Use Which Agent Type

AgentUse forToolsTypical Output
ExploreCodebase scanning, research, auditsRead, Bash, GrepReports, findings
VerificationSecurity checks, adversarial testingRead, BashPass/fail verdict
PlanArchitecture design, approach discussionRead, AskUserQuestionDesign doc, recommendations
GeneralComplex workflows, multi-phase tasksAll toolsDepends on task
Claude Code GuideAnswer questions about the tool itselfRead, AskUserQuestionExplanations, examples

Tools Whitelist Quick Reference

Safe (read-only): Read, Grep, Glob Write-capable: Write, Edit, MultiEdit Execution: Bash Delegation: Task (spawns subagents) Interaction: AskUserQuestion External: WebFetch (requires permission) Browser: (part of browse skill; not a general tool)

Hard Gates (Critical Rules)

A HARD GATE is a non-negotiable rule that overrides agent discretion:

# HARD GATE: No code changes

This skill ONLY reports issues. It DOES NOT modify code.
If you're tempted to fix an issue, ask the user first.

Effective hard gates:

  • Explicitly say what NOT to do
  • Give the reason (why it matters)
  • Suggest the alternative (ask user, report only, etc.)

Template Variables

VariableValueUse in
{{PREAMBLE}}System context about Claude CodeSKILL.md body (if preamble-tier > 0)
$CLAUDE_SKILL_DIRPath to skill’s folderScripts, external tools
$CLAUDE_PROJECT_DIRPath to project rootScripts, relative paths
{{SLUG_SETUP}}Code to compute project slugState persistence (analytics, history)

Debugging Checklist

  • SKILL.md exists at .claude/skills/{name}/SKILL.md
  • YAML frontmatter is valid (test with online validator)
  • name: matches folder name
  • allowed-tools includes all tools the agent will need
  • Paths use $CLAUDE_SKILL_DIR and $CLAUDE_PROJECT_DIR
  • External scripts exist and are executable
  • External scripts return exit code 0 on success
  • Output format matches what’s documented
  • Hard gates are clear and explicit
  • No references to unknown template variables

Key Takeaways

Skills are the foundation of reusable, isolated automation in Claude Code:

  1. One slash, one purpose/skillname should do exactly one thing, consistently
  2. Context isolation — Skills don’t pollute the main session’s context window
  3. Tool whitelisting — Be explicit about what tools a skill needs (fail-safe defaults)
  4. Reusable across projects — Skills live in .claude/ (via submodule) and work everywhere
  5. Complementary to other tools — Use CLAUDE.md for project setup, rules for principles, hooks for invariants, skills for workflows
  6. Versionable and shareable — Skills follow semver; breaking changes bump major version
  7. Progressive disclosure — Show results incrementally; don’t overwhelm the user with output
  8. Hard gates enforce critical constraints — Use them to prevent mistakes the agent might make under pressure
  9. Multi-file skills for complexity — Keep SKILL.md lean; delegate analysis to lib/ and bin/
  10. Test, document, share — Skills in the distribution are community assets; document well and test across projects

Study tip: Re-read the real skill examples from the distribution (browse, entropy, decompose, careful, health, checkpoint). Each demonstrates different patterns. Master one skill per week, then create your own.