../

Agent skills

How to turn a workflow you repeat into a skill: a folder of instructions, scripts and reference files that an agent loads only when a task calls for it. Written for Claude Code first, where skills do the most, with the Claude apps, the Claude API, the Agent SDK and the open Agent Skills format covered after. A skill's instructions are a prompt you write once, so everything in Prompting fundamentals applies inside it.

The short version

A skill is one folder with one required file. This one is complete and works as is in Claude Code (~/.claude/skills/ makes it available in every project):

~/.claude/skills/
writing-release-notes/SKILL.md
writing-release-notes/SKILL.md
---
name: writing-release-notes
description: Writes user-facing release notes from merged pull requests and commits. Use when the user asks for release notes, a changelog entry, or what changed between two versions or dates.
---
 
# Writing release notes
 
1. Get the changes: `git log --merges --oneline <from>..<to>`
   (ask for the two tags or dates if the user didn't give them).
2. Group them under Breaking, Added, Changed, Fixed. Drop
   chores, CI and dependency bumps unless they change behavior.
3. Write one line per change for users: what they can do now,
   not which file changed.
 
Before answering, check: every line traces to a commit, no
internal ticket numbers, and breaking changes come first.
 
Output: Markdown, one heading per version, newest first.

Ask "write the release notes for v2.4" and the agent picks the skill up by itself; type /writing-release-notes to call it directly. Five things decide whether a skill works:

RuleWhy
The description is the triggerit's the only part the agent sees before deciding to use the skill: say what it does and when, in the words you'd type
One job per skilla skill that reviews code and writes docs triggers at the wrong times and does both badly
Write only what the agent doesn't knowyour steps, defaults, conventions and quality bar; not how to write Markdown or use git
Keep SKILL.md short, push detail outlong references go in files it reads on demand; exact operations go in scripts it runs
Test on real requestsdoes it trigger on three phrasings and not on a near miss, and does the output pass your checks?

What a skill is

A skill is a directory whose SKILL.md starts with YAML frontmatter (at least name and description) followed by Markdown instructions, optionally with scripts/, references/ and assets/. The agent loads it in three levels, so an installed skill costs almost nothing until it's used. This is progressive disclosure:

LevelWhatLoadedCost
1. Metadataname + descriptionat session start, for every installed skillabout 100 tokens per skill
2. Instructionsthe body of SKILL.mdwhen a request matches the description, or you type /namekeep under about 5,000 tokens (500 lines)
3. Resourcesfiles in the folderonly when a step needs one; scripts run, and only their output enters the contexteffectively unlimited
reviewing-pull-requests/ SKILL.md --- name: reviewing-pull-requests description: Reviews a pull request… --- ## Steps 1. Run scripts/diff_stats.sh 2. Read references/checklist.md ## Checklist - tests cover the change ## Output Fill in assets/review-template.md references/checklist.md scripts/diff_stats.sh assets/review-template.md always in context: loaded when the skill is used: read only when a step says to run, not read: copied into the output ~100 tokens per skill keep it under 500 lines (~5k tokens) only their output enters context (templates, images)
What loads when: one skill folder, part by part
context window installed skills free space names + descriptions ≈100 tokens per skill you: "review PR 142" SKILL.md body steps, checklist, output script output its code stays out references/checklist.md reviewing-pull-requests/ SKILL.md: name, description SKILL.md: body references/checklist.md scripts/diff_stats.sh loaded matches read read run writing-release-notes/ SKILL.md: name, description SKILL.md: body assets/template.md loaded no match

1/4

Session starts: only each skill's name and description enter the context, about 100 tokens apiece.

Progressive disclosure during one request

The consequence for your workflows: you can install a skill for every one of them. Twenty idle skills cost about as much context as a paragraph, and only the one that fits the task gets read.

When to use a skill

A skill is one of several places to put knowledge for an agent. Pick by when the knowledge must apply:

MechanismLoadedUse it forNot for
CLAUDE.md / AGENTS.mdevery session, in fullfacts every task needs: build and test commands, layout, conventionsprocedures used now and then: they cost context every session
Skillwhen relevant, or on /namerepeatable procedures and know-how: review a PR, write the weekly report, apply the house stylerules that must hold every time
Hookon an event (before a tool runs, after an edit), every timedeterministic actions: format after edits, block a dangerous command, notifyanything that needs judgment
MCP serverits tools are always availablelive access to outside systems: issue trackers, databases, APIshow and when to use those tools (write a skill for that)
Subagentin its own context windowlarge searches or side tasks whose details would clutter your sessionshort procedures (a skill with context: fork runs in a subagent)
Plugininstalled as a bundlesharing skills, subagents, hooks and MCP settings togethera single personal skill
Plain promptthis turn onlyone-off tasksanything you'll explain twice
Must it apply to every task in this project? Should it run automatically on an event, every time, no judgment? Does it need a live connection to an outside system? Is it a procedure or know-how the agent should pull in when relevant? Just this once? yes yes yes yes yes no no no no CLAUDE.md / AGENTS.md Hook MCP server Skill Plain prompt (always loaded) (deterministic) (tools) (loaded on demand) (nothing saved) plus a skill that teaches how to use them add context: fork to run it in a subagent Ship several of these together → Plugin
Where should this workflow knowledge live?

Rule of thumb: the second time you paste the same instructions into a chat, make them a skill.

Turn a workflow into a skill

  1. Pick a workflow

    Something you do at least weekly, that has a clear "done", and that you explain to the agent every time. Start with one; good first candidates are reports, reviews, release chores and anything with a checklist.

  2. Do it once without a skill

    Run the workflow with the agent in a normal session and keep notes of every correction you make and every fact you have to supply. That list, not your memory of the process, is the skill's content.

  3. Write the description first

    Name the job and the moments it applies, in the words you'd actually type. If you can't write it in two sentences, the skill does too much: split it.

  4. Write the body

    Inputs, numbered steps each with a "done when", the checks to run before answering, and the exact output format. Leave out what a capable model already knows.

  5. Move the bulk out

    Long reference material goes to references/, exact or fragile operations to scripts/, templates to assets/. SKILL.md says when to read or run each one.

  6. Test it

    Three requests that should trigger it, two near misses that shouldn't, and one real task run with and without the skill. Use a fresh session, so the agent isn't helped by the conversation where you wrote it.

  7. Iterate, then share

    Fix what you saw go wrong, one change at a time. When it works for you, commit it to the project or package it as a plugin.

WorkflowSkill shapeHow it's invoked
Weekly status reporttemplate filled with live data (commits, PRs, issues)/weekly-report, by you only
Code reviewchecklist + quality bar, references for securityautomatically, when you ask for a review
Deploy to stagingexact commands and verification stepsby you only (disable-model-invocation: true)
House writing stylereference knowledgeautomatically; hidden from the / menu (user-invocable: false)
Research a library or codebase areainstructions run in a subagentcontext: fork
Clean and validate data filesscripts + a validator loopautomatically, when the file type comes up
Meeting notes to taskstemplate + rules for owners and datesautomatically, when you paste notes

Have the agent draft it

Give the agent the notes from step 2 and let it write the first version. The prompt uses the structure from Prompting fundamentals:

<materials>
[paste the transcript or your notes from doing the workflow once,
including every correction you made]
</materials>
 
<context>
I want a reusable Agent Skill for this workflow. It will run in
[surface: Claude Code | the Claude apps | the Claude API | another agent].
</context>
 
<task>
Draft the skill: SKILL.md (frontmatter and body) and any scripts/,
references/ or assets/ files it needs.
</task>
 
<requirements>
- name: lowercase letters, numbers and hyphens, at most 64 characters,
  one job, e.g. reviewing-pull-requests
- description: third person, what it does and when to use it, with the
  words I'd type; under 1,024 characters
- body under 200 lines: inputs, numbered steps with "done when", checks
  before answering, output format; only what a capable model wouldn't know
- exact or fragile operations go in scripts that handle their own errors;
  long reference material goes in references/
- Never invent commands, flags or file paths: write [NEEDS SOURCE]
  where you're unsure.
</requirements>
 
<quality_bar>
Before answering, check your draft against:
- Would the description trigger on three different phrasings of the
  request, and not on a near miss?
- Does every step say exactly what to do and how to know it's done?
- Is there one default for each choice, not a menu of options?
</quality_bar>
 
<output_format>
The folder tree, then each file in its own code block, then 3 requests
that should trigger it and 2 that shouldn't.
</output_format>
 
<process>
Ask me up to 3 questions first if anything missing would change the
skill. End with a list of the assumptions you made.
</process>

Anatomy of a skill folder

a complete skill
reviewing-pull-requests/SKILL.md                # required: frontmatter + bodyreferences/checklist.md        # read when a step says sosecurity.mdscripts/diff_stats.sh       # run; only output enters contextassets/review-template.md  # copied into the output
PartHoldsRules
SKILL.mdfrontmatter, then instructionsrequired; the folder name must equal name
references/documentation the agent reads when needed: schemas, policies, long examplesone level deep from SKILL.md (no reference that points to another); a table of contents at the top of files over about 100 lines
scripts/code the agent runs: validators, converters, API callshandle errors and print short, clear output; only the output costs context
assets/files used in the output: templates, images, fontsnever read into context unless a step says so

Paths inside a skill use forward slashes and are relative to the skill folder (references/checklist.md), also on Windows. In Claude Code, ${CLAUDE_SKILL_DIR} expands to the folder's absolute path, for commands that run from another working directory.

Frontmatter

These fields come from the open Agent Skills specification (opens in a new tab), so a skill that uses only them works wherever skills do:

FieldRequiredRules
nameyes1–64 characters; lowercase letters, digits and hyphens; no leading, trailing or double hyphen; equals the folder name
descriptionyes1–1,024 characters; what the skill does and when to use it
licensenoa license name, or the name of a license file in the folder
compatibilitynoup to 500 characters on what the environment needs: tools, network, operating system
metadatanoa map of string keys to string values: version, owner, anything your own tooling reads
allowed-toolsnotools the skill may use without asking, space-separated, e.g. Bash(git:*) Read; experimental in the spec
frontmatter using only portable fields
---
name: reviewing-pull-requests
description: Reviews a pull request for correctness, test coverage and security issues. Use when the user asks to review a PR, a diff or a branch before merging.
license: MIT
compatibility: Needs git and the GitHub CLI (gh), with network access.
metadata:
  version: "1.2.0"
  owner: platform-team
---
SurfaceExtra rules
Claude API and Claude appsname can't contain "anthropic" or "claude"; neither field may contain XML tags
Claude apps (claude.ai upload)only the six fields above are accepted; any other field is an error, so keep Claude Code-only fields out of skills you upload there
Claude Codename defaults to the folder name; frontmatter must start on line 1; unknown fields are ignored; adds the fields in Claude Code features

Keep description on one line. The YAML spec allows multi-line values, but one line is the form every tool reads.

Writing the description

The agent decides whether to use a skill from its description alone, so a skill that never triggers almost always has a description problem.

  • Third person, present tense: "Reviews pull requests…", not "I review…" or "Use this to review…".
  • What, then when: the first sentence says what it does, the second when to use it ("Use when…").
  • The words you'd type: nouns and verbs from real requests, file types and tool names ("PR", "diff", "code review", ".xlsx", "Grafana").
  • Specific beats broad: a description that could fit ten skills triggers for none of them reliably.
  • Say when not, if two skills are close: "Not for writing new tests; see writing-tests."
WeakStrong
"Helps with documents.""Extracts text and tables from PDF files, fills PDF forms and merges PDFs. Use when the user mentions PDFs, forms or document extraction."
"Code review skill.""Reviews a pull request for bugs, missing tests and security issues, and writes the review as inline comments. Use when asked to review a PR, a diff or a branch."
"Use this for reports.""Writes the weekly engineering status report from this week's commits, merged PRs and closed issues. Use when the user asks for the weekly report or a status update."

In Claude Code the skill list in context gets about 1% of the model's context window, and each entry (description plus the optional when_to_use field) is cut at 1,536 characters. With many skills, long descriptions get shortened: /doctor estimates the listing's cost and /skill-doctor reports how your skills are used.

Writing the instructions

The body is a prompt the agent reads at the moment it needs it, so the rules of a good prompt apply, plus a few that come from being read again and again:

  • Concise: the agent is already capable. Explain your conventions, defaults and decisions, not general skills.
  • Imperative and ordered: numbered steps, each with how to know it's done.
  • Defaults, not menus: "Use pdfplumber; for scanned PDFs use OCR" beats a list of five libraries.
  • One term per thing: if it's a "release" in step 1, don't call it a "version" in step 4.
  • Nothing time-sensitive: no "as of this year". Put superseded behavior under an "Old patterns" heading.
  • Under 500 lines: past that, split into reference files the body points to.
  • Read vs run, said explicitly: "Run scripts/validate.py report.json" (execute it) and "See references/schema.md" (read it) are different instructions.

Match how tightly you specify a step to how fragile it is. These are the degrees of freedom:

FreedomUse whenWrite
Highmany approaches are fine and judgment mattersgoals and heuristics: "Keep each commit to one change; explain why in the message."
Mediumthere's a preferred pattern with some variationa template or pseudocode with parameters
Lowthe operation is fragile, exact or destructivethe exact command, and "Run exactly this; don't change the flags."

A body that follows the same structure as a good prompt:

# Reviewing pull requests
 
## Inputs
- The PR number or branch. If none is given, ask for it.
 
## Steps
1. Get the diff: `gh pr diff <number>`. Done when you have it.
2. Run `scripts/diff_stats.sh <number>` for size and touched areas.
3. Review against references/checklist.md, file by file.
4. If auth, payments or user data are touched, also apply
   references/security.md.
 
## Checks before answering
- Every finding names a file and line and says why it matters.
- Findings are ranked: blocking, should fix, nit.
- No finding is about style the linter already enforces.
 
## Output
Use assets/review-template.md. Blocking findings first.
 
## Edge cases
- Diff over 1,000 lines: review the riskiest files first and
  say which files you skipped.

Checklists and feedback loops

For long workflows, give the agent a checklist to copy into its answer and tick off, so steps don't get skipped. For anything with a validator (a schema, a linter, a test suite, a script you wrote), make the loop explicit: run it, fix what it reports, run it again, and only continue when it passes.

Do the step Run the validator Errors? Fix what it reports Next step Repeat until the validator passes scripts/validate.py yes no 3 errors 1 error 0 errors

Repeat until the validator passes

For risky batch work (renaming hundreds of files, bulk edits through an API), add a plan step: the agent writes the plan to a file (changes.json), a script validates it, and only then does it execute. Mistakes surface in the plan, where they're cheap.

Scripts and bundled files

Put a step in a script when it must be exact, when it's long or fragile, or when the agent would otherwise write the same code every time. The agent runs the script and sees only its output, so a 300-line script costs a few lines of context.

  • Solve, don't defer: handle missing files, bad input and network errors in the script, and print a message that says what to do.
  • No unexplained constants: TIMEOUT = 30 # the API's limit is 30 s instead of a bare 30.
  • Short, structured output: a summary and the problems found, not a log. Exit non-zero on failure so the agent knows to stop.
  • Declare dependencies: say what must be installed (in compatibility and in the step), and don't assume a package exists.
  • Prefer reading data over hard-coding it: a script that reads references/rules.json is easier to update than one with the rules inside.
scripts/validate.py
"""Check a report JSON file; exit 1 listing problems."""
import json
import sys
 
REQUIRED = ["title", "period", "highlights", "risks"]
 
 
def main(path: str) -> int:
    try:
        with open(path, encoding="utf-8") as file:
            data = json.load(file)
    except (OSError, json.JSONDecodeError) as err:
        print(f"Cannot read {path}: {err}")
        return 1
    missing = [key for key in REQUIRED if not data.get(key)]
    if missing:
        print("Missing or empty: " + ", ".join(missing))
        return 1
    print(f"OK, highlights: {len(data['highlights'])}")
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main(sys.argv[1]))

Where a skill runs decides what its scripts can do:

SurfaceNetworkPackages
Claude Codeyour machine's network, like any program you runwhatever is installed; don't have a skill install packages globally
Claude appsfull, partial or none, set by you and your admincan install from npm and PyPI when the network allows
Claude APInoneonly what the code execution environment has preinstalled

Claude Code features

Where skills live

LocationPathApplies to
Enterpriseset through managed settingseveryone in the organization
Personal~/.claude/skills/<name>/SKILL.mdall your projects
Project.claude/skills/<name>/SKILL.mdeveryone working in the repository (commit it)
Nested<subdirectory>/.claude/skills/<name>/SKILL.mdloaded once the agent reads or edits a file in that subdirectory
Plugin<plugin>/skills/<name>/SKILL.mdwherever the plugin is installed, as /plugin-name:skill-name

On a name clash, enterprise beats personal, which beats project; plugin skills are namespaced, so they never clash. Custom commands are now skills: .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy, old command files keep working, and the skill wins if both exist.

Invoking and arguments

The agent uses a skill when a request matches its description; you call one by starting a message with /name, followed by any arguments: /fix-issue 123. In the body:

PlaceholderBecomes
$ARGUMENTSeverything after the name (if the body has no placeholder, the arguments are appended as ARGUMENTS: …)
$0, $1 or $ARGUMENTS[0]one argument by position, counting from 0
$namea named argument declared in arguments
${CLAUDE_SKILL_DIR}the skill folder's absolute path
${CLAUDE_PROJECT_DIR}the project root

Controlling behavior

FieldEffectTypical use
disable-model-invocation: trueonly you can run it, with /name; its description leaves the context, and /loop and scheduled tasks can't run itdeploys, sends, anything with side effects
user-invocable: falsehidden from the / menu; the agent still uses itbackground knowledge: house style, domain rules
when_to_useextra trigger text appended to the descriptionlonger "use when" guidance
argument-hintthe hint shown while typing, e.g. "[issue-number]" (quote it: unquoted brackets are a YAML list)skills you call with arguments
argumentsnames for positional arguments, used as $namereadable bodies
allowed-toolstools it may use without asking, for the turn that invoked it: Bash(gh *) Reada report skill that runs git log
disallowed-toolstools removed while it's activea read-only review skill
model, effortthe model or effort level for that turna cheap model for a mechanical skill
context: forkruns in a subagent with its own context; agent picks its type (default general-purpose, or e.g. Explore), background whether it runs in the background (default true)research whose details would clutter your session
pathsglobs (a comma-separated string or a YAML list) that limit when it loads automaticallya skill for one part of a monorepo
hookshooks registered while it's activea format-on-save rule during a refactor skill

Live data in the instructions

A placeholder !`command` (at the start of a line or after a space) runs before the agent sees the skill and is replaced by the command's output, so the instructions arrive with current data. Its output isn't scanned again for placeholders. A fenced block opened with ```! runs several lines. If a command fails, the skill doesn't run. Administrators can turn this off with the disableSkillShellExecution setting.

Managing skills

CommandDoes
/skillslists loaded skills
/contextshows how much context the skill list uses
/skill-doctorreports how your skills are used and what they cost
/reload-skillspicks up a newly created top-level skills folder (edits to existing skills load without it)
claude plugin validate .claude/skillschecks frontmatter before you share

Loops, goals and long runs

Some of the most useful skills aren't run once: they're run until something is true, or every few minutes while something changes. Claude Code has commands for both, and a skill is the natural thing to put inside them.

CommandDoesWith a skill
/loop [interval] [prompt]runs the prompt again every interval (5m, 2h; at least 1 minute); with no interval Claude picks each wait itself, 1 minute to 1 hour; with no prompt it tends the branch's PR or follows .claude/loop.md/loop 15m /babysitting-pull-requests, or /loop /babysitting-pull-requests to let it pace itself
/goal [condition]after every turn a small model checks the condition against the conversation; while it isn't met, Claude starts another turn; /goal clear ends itrun a skill, then hold it to a finish line: /goal every check in the skill's report passes; or stop after 20 turns
/schedule [description]cloud scheduled tasks that run on Anthropic's servers, even with your machine offa daily or weekly skill: the Monday report, a nightly dependency audit
/batch <instruction>splits a large change into 5–30 units and runs one background subagent per unit, each in its own worktree, each opening a PRa migration your skill describes, applied everywhere at once
claude --bg "<prompt>", /tasksa session that keeps working in the background; list and manage background worka long skill you don't want to watch
Stop hookruns when Claude finishes responding and can block stopping (exit code 2)enforce "don't stop until the validator passes" as code, not instructions
/goal [condition] you, once Claude works a turn a small model reads the conversation met? no: another turn yes the goal clears and control returns to you also ends if the checker judges it impossible, or a turn fails on an error

/goal: another turn until the condition holds

Writing skills that repeat

  • Idempotent: every step checks before it acts ("if this comment already has a reply, skip it"), so the tenth run doesn't redo the first.
  • Standing instructions: Claude Code doesn't re-read SKILL.md on later turns, so write rules that apply for the whole run as rules ("never force-push"), not as one-time steps.
  • One status line: end every run with a fixed line (STATUS: checks pass · comments 0 · action none). The /goal checker can only judge what's printed, and an unchanged line tells you nothing needs attention.
  • Quiet when nothing changed: print only the status line.
  • State in a file: record what's been handled in a file the next run reads, because long sessions get summarized and details drop out of the conversation.
  • A stop rule: "If the PR is merged or closed, say so and end the loop", or "stop once two rounds in a row find nothing new".
  • Bounded: put a turn limit in every goal ("or stop after 20 turns"), and in scripts cap runs with claude -p --max-turns 30 --max-budget-usd 5.
.claude/skills/babysitting-pull-requests/SKILL.md
---
name: babysitting-pull-requests
description: Checks this branch's pull request for failing CI, new review comments and merge conflicts, and fixes what it safely can. Use when asked to watch, babysit or tend a PR, or when run by /loop.
allowed-tools: Bash(gh pr *) Bash(gh run *) Bash(git status *) Bash(git diff *) Bash(git add *) Bash(git commit *) Bash(git push)
---
 
# Babysitting a pull request
 
Safe to run again and again. Never force-push; never merge the PR.
 
1. Read the state: `gh pr view --json number,state,mergeable,statusCheckRollup,reviewDecision`.
   If the PR is merged or closed, print "PR closed: stopping" and end the loop.
2. Read .claude/pr-babysit.md (create it if missing): the comments and runs already handled.
3. Failing checks not yet handled: read the log (`gh run view <run-id> --log-failed`), fix the cause, commit, push once.
4. Review comments not yet handled: address each in code or reply, push once, and list them in .claude/pr-babysit.md.
5. Merge conflicts: report them; don't resolve conflicts in files this PR didn't change.
 
## Every run ends with exactly one line
STATUS: checks <pass|fail> · new comments <n> · conflicts <yes|no> · action <what you did|none>
 
If nothing changed since the last run, print only that line.

Run it with /loop /babysitting-pull-requests and stop it with Esc, or set a fixed interval (/loop 15m /babysitting-pull-requests) and ask Claude to cancel it when you're done. Loops run only while Claude Code is open and idle, and recurring ones expire after seven days.

Other places skills run

Claude apps

Turn on code execution (Settings, Capabilities), then add the skill under Customize, Skills: "+", "Create skill", "Upload a skill". Zip the skill folder itself, so the archive's top level is that folder (house-style/SKILL.md), not a parent folder around it, and name the folder like the skill. Only the six portable frontmatter fields are accepted. Team and Enterprise owners can provision skills for the whole organization, and Enterprise can scan uploaded skills for malicious content. Skills you add in the apps can sync one way into Claude Code when you sign in with the same account. Plan availability changes: check the help center.

Claude API

Upload a skill to your workspace with POST /v1/skills (multipart files, or a zip under 30 MB). Each new version is a complete snapshot. Attach skills to a request through the container, with the code execution tool enabled:

{
  "model": "[model id]",
  "max_tokens": 4096,
  "container": {
    "skills": [
      { "type": "anthropic", "skill_id": "xlsx",
        "version": "latest" },
      { "type": "custom", "skill_id": "skill_01...",
        "version": "latest" }
    ]
  },
  "tools": [
    { "type": "code_execution_20250825",
      "name": "code_execution" }
  ],
  "messages": [
    { "role": "user",
      "content": "Build the Q3 budget workbook." }
  ]
}
  • Up to 20 skills per request. Anthropic's prebuilt skills are pptx, xlsx, docx and pdf.
  • The container has no network access, and only preinstalled packages: bundle what the skill needs.
  • Custom skills belong to the whole workspace: any API key with access can use or delete them. Use a separate workspace per customer if you serve several.
  • Headers and versions change: copy them from the current skills guide (opens in a new tab).

Agent SDK

Skills are files on disk, found in the same places as in Claude Code. Load the user and project sources and enable them:

from claude_agent_sdk import ClaudeAgentOptions
 
options = ClaudeAgentOptions(
    setting_sources=["user", "project"],
    skills="all",
    allowed_tools=["Read", "Grep", "Bash"],
)

Setting skills adds the Skill tool automatically; if you pass an explicit tools list, include "Skill". The session's init message lists the skills that loaded.

Other agents

Anthropic published Agent Skills as an open standard in December 2025, with the specification at agentskills.io (opens in a new tab). The portable core is the folder layout and the six frontmatter fields; Claude Code's extras (arguments, !`command`, invocation control, context: fork) are not part of it. For a skill meant to work in other agents, stick to the core, check each agent's docs for where it looks for skills, and validate with the reference tool: skills-ref validate ./my-skill.

Patterns for workflows

PatternShapeExample
Checkliststeps the agent copies and ticks offonboarding a new service, a release
Validator loopdo, validate with a script, fix, repeatdata files, generated configs, docs that must build
Template fillan asset with the exact output formatstatus reports, incident summaries, RFCs
Routera short SKILL.md that points to one reference per casean API with many endpoints, a style guide by document type
Knowledge packconventions and decisions, user-invocable: falsehouse writing style, naming rules, domain glossary
Tool wrapperscripts around a CLI or API, with when-to-use rulesa reporting API, an internal deploy tool
Manual actionexact steps, disable-model-invocation: truedeploys, data migrations, sending email
Plan, validate, executewrite a plan file, check it, then actbulk renames, mass edits, migrations
Forked researchercontext: fork, results summarized back"investigate how auth works in this repo"
Polling loopan idempotent skill with one status line, run by /looptending a PR, watching a deploy, triaging new issues
Goal-drivena skill whose checks print evidence, finished with /goal"fix until the test suite passes", "fill every section of the template"

Example skills

Weekly report: called by you, with live data

.claude/skills/weekly-report/SKILL.md
---
name: weekly-report
description: Writes the weekly engineering status report from this week's commits, merged pull requests and closed issues. Use when the user asks for the weekly report or a status update.
disable-model-invocation: true
argument-hint: "[team name]"
allowed-tools: Bash(git log *) Bash(gh pr list *) Bash(gh issue list *)
---
 
# Weekly report for $ARGUMENTS
 
## This week's data
Commits: !`git log --since="7 days ago" --oneline --no-merges`
Merged PRs: !`gh pr list --state merged --limit 50 --json number,title,mergedAt`
Closed issues: !`gh issue list --state closed --limit 50 --json number,title,closedAt`
 
## Steps
1. Keep only PRs and issues closed in the last 7 days.
2. Group by theme (feature, fix, infrastructure), not by person.
3. Write 3–5 highlights in plain language: what users or the team can now do.
4. List risks and blockers only if the data or the user names them.
 
## Checks before answering
- Every highlight traces to a PR, issue or commit above.
- No highlight invented to fill space: fewer is fine.
 
## Output
Use assets/template.md exactly. End with the PR and issue numbers used.

Code review: picked up automatically

.claude/skills/reviewing-pull-requests/SKILL.md
---
name: reviewing-pull-requests
description: Reviews a pull request for bugs, missing tests and security issues and reports ranked findings. Use when the user asks to review a PR, a diff or a branch before merging.
---
 
# Reviewing pull requests
 
## Steps
1. Get the diff: `gh pr diff <number>` (ask for the number if missing).
2. Run `bash ${CLAUDE_SKILL_DIR}/scripts/diff_stats.sh <number>`.
3. Review each file against references/checklist.md.
4. If authentication, payments or personal data are touched, also apply
   references/security.md.
 
## Checks before answering
- Each finding: file, line, what's wrong, why it matters, a fix.
- Ranked: blocking, should fix, nit. At most 5 nits.
- Nothing the linter or formatter already catches.
 
## Output
A summary line, then the findings table from assets/review-template.md.
If there are no blocking findings, say so first.

House style: background knowledge

.claude/skills/house-style/SKILL.md
---
name: house-style
description: The company's writing style for docs, release notes, emails and UI text: voice, terminology, formatting. Use when writing or editing any user-facing text.
user-invocable: false
---
 
# House style
 
- Voice: plain and direct; second person ("you"); no exclamation marks.
- Terms: see references/glossary.md and use those exact spellings.
- Headings: sentence case. Lists: no ending periods unless full sentences.
- Numbers: digits for 10 and above, and for all units ("5 GB").
- Never: "simply", "just", "easy", or blame on the user in error messages.
 
For error messages and empty states, see references/ui-text.md.

Deploy to staging: manual only, exact steps

.claude/skills/deploy-staging/SKILL.md
---
name: deploy-staging
description: Deploys the current branch to the staging environment and verifies it. Use only when the user runs /deploy-staging.
disable-model-invocation: true
---
 
# Deploy to staging
 
Run each command exactly as written; stop at the first failure and
report its output.
 
1. `git status --porcelain`: must print nothing. If it does, stop
   and ask the user to commit or stash.
2. `make test`: must pass.
3. `make deploy ENV=staging`
4. `curl -fsS https://staging.example.com/health`: must print "ok".
 
Report: the commit deployed (`git rev-parse --short HEAD`), the
health check result, and the time.

Test and evaluate

Test the two things that can fail separately: triggering (does the agent pick the skill up at the right moments) and outcome (is the result good when it does).

TestHowPass
Should triggerthree different phrasings of a real request, in a fresh sessionthe skill is used each time
Should not triggertwo near misses ("review this essay" for a code review skill)it isn't used
Baselinethe same real task with the skill removedthe skill's version is clearly better; if not, the skill isn't earning its place
Outcomethree real tasks, checked against the skill's own checksevery check passes
Navigationwatch which files the agent opensit reads what each step points to, and nothing it doesn't need
Modelsrun the outcome tests on every model you'll usesmaller models follow it too; they need more explicit steps

Iterate with two sessions: in one you write and revise the skill with the agent ("Claude A"); a fresh one uses the skill on real tasks ("Claude B"). Bring what B got wrong back to A, change one thing, and test again. Fresh sessions matter because the authoring session already knows everything the skill fails to say.

Share and maintain

ScopeHow
Just you~/.claude/skills/
A repository's teamcommit .claude/skills/; review changes like code
Several repositories or teamsa plugin with a skills/ folder, published through a plugin marketplace
An organization in the Claude appsan owner provisions it in the organization settings
An API productupload to the workspace; pin version in requests and bump it deliberately
  • Keep a version in metadata and a short changelog at the bottom of SKILL.md.
  • Anthropic's example skills are in the anthropics/skills (opens in a new tab) repository, which is also a plugin marketplace: /plugin marketplace add anthropics/skills.
  • Revisit a skill when its workflow changes; a stale skill is worse than none, because it's followed confidently.

Security

A skill can run code and steer an agent that has your permissions, so treat installing one like installing software.

  • Install skills only from sources you trust, and read every file first: SKILL.md, scripts and anything they download.
  • Be wary of skills that fetch URLs or tell the agent to send data anywhere: that's how prompt injection and data exfiltration happen.
  • Never put secrets in a skill. Read them from the environment or a secrets manager at run time.
  • Scope allowed-tools narrowly (Bash(git log *), not Bash), and use disable-model-invocation: true for anything with side effects.
  • In the API, any key in the workspace can use and delete its custom skills; separate workspaces separate tenants.

Troubleshooting

SymptomLikely causeFix
Never triggersthe description doesn't use the words of the request, or is too broadadd the nouns and verbs you actually type; test three phrasings
Triggers at the wrong timesthe description overlaps another skill or is genericnarrow it and add "Not for …"
Doesn't appear at allfrontmatter not on line 1, the folder name differs from name, or a new top-level folderfix the file; run /reload-skills; check /skills
Upload rejected in the Claude appsa Claude Code-only field, a reserved word, or the zip's root isn't the skill folderkeep only the six portable fields; re-zip from inside the parent folder
Follows some steps, skips otherssteps without a "done when", or a body that's too longnumber the steps, add a checklist, move detail to references
Reads every reference fileSKILL.md doesn't say which file is for which casepoint to each file from the step that needs it
A script fails in the APIno network, or a package that isn't installedbundle the dependency or rewrite without it
Description cut short in the listtoo many skills for the listing budgetshorten descriptions; hide background skills from the menu
Does nothing inside /loopthe skill has disable-model-invocation: truemake it model-invocable and guard its side effects in its steps
A goal never finishesthe condition isn't visible in the conversation, or has no boundhave the skill print the check's result; add "or stop after N turns"
Each loop run redoes earlier workno record of what's donekeep a state file the steps read and update

References