Every AI agent hits the same wall right after the first one. It can reason well out of the box, but it doesn't know your team's deploy checklist, the API your last vendor never documented properly, or the three gotchas your senior engineer has repeated in every code review for the past year. That knowledge exists — it's just never lived anywhere an agent could pick it up.

Agent Skills are Anthropic's answer: a folder-shaped, open format for packaging a procedure, a convention, or a piece of institutional memory so an agent can load it exactly when it's relevant, and not a token before.

This post covers what a skill actually is, the specific problem it solves, and then gets practical: creating a real one, publishing it so a team can share it, and keeping it current once people start relying on it.

01

What a Skill Actually Is

At its core, a skill is a directory with one required file: SKILL.md. Its YAML frontmatter carries metadata — at minimum a description — and the markdown body underneath is the instructions the agent follows once the skill loads. Nothing more is required to make one:

markdown
1
2
3
4
5
---
description: Summarize uncommitted changes and flag anything risky
---
Run `git diff HEAD`, summarize it in three bullets, then list any risks.

That's a complete, working skill. The description is the only thing an agent sees before deciding whether it applies to the current task — everything below the frontmatter only loads once that match happens.

A skill can grow well past three lines. It can bundle reference docs, templates, and executable scripts alongside SKILL.md, and point to them by name so the agent pulls each one in only when the instructions actually call for it. That bundling is what makes skills work at any size, from a one-line reminder to a multi-step workflow with its own test scripts.

02

The Problem They Solve

Before skills, there were exactly three ways to get an agent to follow a team's specific procedure. Paste it into the conversation, and it's gone the moment the session ends. Push it into the system prompt or a file like CLAUDE.md that loads on every turn, and now its full token cost is paid on every single request — including the ones it's irrelevant to. Build a dedicated agent around it, and there's a maintenance burden that doesn't travel to any other tool.

In the system prompt

Paid on every single turn
Competes with everything else for attention
Grows harder to maintain as more gets added

As a skill

Only name and description upfront

Full body loads on a match

Costs nothing the rest of the time

Loading a procedure into the system prompt costs its full size on every turn; a skill's body only enters context once its description matches the task.

None of those trade-offs are really about the procedure — they're about when it gets paid for. A skill's description sits in context from the start, cheap enough to keep dozens of them on hand, and its actual instructions only load once a task matches. The rest of the time, they cost nothing.

That's the whole pitch: not a smarter agent, but a way to hand it exactly the context it's missing, exactly when it needs it, without taxing everything else it's doing.

03

Progressive Disclosure

The mechanism behind that is called progressive disclosure, and it works in three stages. At startup, the agent loads only every available skill's name and description — enough to know what exists, not enough to read any of it. When a task matches one, the full SKILL.md body loads into context. And if that skill bundles its own reference files, scripts, or templates, those load only when its own instructions point the agent to them.

Discovery

At startup, every session

Name and description only

Activation

A task matches the description

The full SKILL.md body

Execution

The instructions point to a file

Bundled references, assets, or scripts

Three stages, each going deeper than the last — the agent only pays for what a task actually needs.

The practical guidance follows directly from the mechanism: keep SKILL.md itself under roughly 500 lines and 5,000 tokens — just what the agent needs on every run — and move anything longer, like a full API reference or a large example set, into its own file that the instructions link to by name.

04

Creating One

The best skills come out of a real, repeated task rather than a generic description of best practices — so here's one pulled straight out of this repository. Every post on this blog follows the same seven-file pattern: a page component, one or two diagram components, an entry in a central registry, and matching translation blocks in two locale files. That's exactly the kind of procedure worth capturing once instead of re-explaining every time.

bash
1
2
3
4
5
6
7
8
.claude/skills/new-post/
├── SKILL.md # overview + the procedure
├── references/
│ └── message-keys.md # full blog.<key> shape, both locales
├── assets/
│ └── page.template.tsx # starting point for the new route
└── scripts/
└── check-locales.mjs # diffs en.json vs es.json key trees

The SKILL.md itself stays short — a numbered procedure, plus the gotchas this repository has actually produced:

markdown
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
---
description: Add a new article to the dizenz blog. Use when asked to
write, draft, or publish a blog post for the site.
allowed-tools: Read Write Edit Bash(pnpm lint)
---
## Procedure
1. Pick a slug and copy `assets/page.template.tsx` to
`app/[locale]/blog/<slug>/page.tsx`.
2. Add a `blog.<camelKey>` block to both `messages/en.json` and
`messages/es.json` — see `references/message-keys.md` for the shape.
3. Prepend an entry to `BLOG_POSTS` in `lib/blog-posts.ts` and add the
slug to `SLUG_TO_MESSAGE_KEY`.
4. Run `node scripts/check-locales.mjs <camelKey>` — both locales must
report the same key tree.
5. Run `pnpm lint`.
## Gotchas
- Prose lives in `messages/{locale}.json`. Never inline copy in the page
file — only code samples and icon arrays go there.
- `en.json` and `es.json` must have identical key trees. Only the values
differ.
- A slug missing from `SLUG_TO_MESSAGE_KEY` silently breaks the localized
card for any multi-word slug — it falls back to the raw slug as the key.
- Spanish copy is Argentine voseo ("Instalalo", "Creá"), not neutral
Spanish.
- Display order in `BLOG_POSTS` is array order, not `date`. `date` is
SEO-only metadata.

A handful of frontmatter fields shape how a skill behaves once it exists. These four cover most of what a real skill needs:

description & when_to_use

The only thing an agent sees before deciding to load a skill. Put the key use case first — the combined text is truncated at 1,536 characters in the listing.

disable-model-invocation & user-invocable

Who's allowed to trigger it. A side-effecting workflow like a deploy should be user-only; background knowledge the agent should just know should be model-only.

allowed-tools

Tools pre-approved for the turn that invokes the skill, so it runs without a permission prompt. It grants rather than restricts, and the grant clears on the next message.

context: fork

Runs the skill in its own subagent, so a long procedure doesn't spend the tokens of the conversation that triggered it.

Notice what's missing from that gotchas section: generic advice like 'write clear code' or 'test your changes.' A skill's value is almost entirely in what the agent would otherwise get wrong — a specific file, a specific rule, a mistake someone actually made. Every correction an agent's output needs is a gotcha waiting to be added.

05

Publishing It

Where a skill lives determines who can use it. For something that only matters to one repository, committing it to that repo's .claude/skills/ directory is the entire publishing step — anyone who clones the project gets it automatically, no separate install:

bash
1
2
3
4
5
6
mkdir -p .claude/skills/new-post
git add .claude/skills/new-post
git commit -m "chore: add new-post skill"
# That's the whole distribution step for a single repo — anyone who
# clones it and opens Claude Code gets the skill automatically.

Sharing a skill across repositories, or with people outside a team, means wrapping it in a plugin instead: a manifest describing the plugin (plugin.json), and a marketplace catalog (marketplace.json) listing where to find it.

json
1
2
3
4
5
6
{
"name": "blog-tools",
"description": "Skills for writing and maintaining the dizenz blog",
"version": "1.0.0",
"author": { "name": "dizenz" }
}
json
1
2
3
4
5
6
7
8
9
10
11
{
"name": "dizenz",
"owner": { "name": "dizenz" },
"plugins": [
{
"name": "blog-tools",
"source": "./plugins/blog-tools",
"description": "Skills for writing and maintaining the dizenz blog"
}
]
}

From there, anyone can add the marketplace and install the plugin by name. Its skill ends up namespaced under the plugin, so two teams' new-post skills never collide:

bash
1
2
3
4
5
6
/plugin marketplace add dizenz/claude-plugins
/plugin install blog-tools@dizenz
# Namespaced under the plugin, so it can't collide with anyone
# else's new-post skill:
/blog-tools:new-post

For an entire organization, the same plugin can be deployed through managed settings instead of an opt-in install — every seat gets it without anyone running a command.

06

Updating It

A skill committed straight to a project's .claude/skills/ updates the moment the file changes — no restart, no reinstall. Anyone with the repo checked out sees the new version on their very next prompt.

bash
1
2
3
4
5
6
7
# In the plugin repo: bump the version, then push
# .claude-plugin/plugin.json: "version": "1.1.0"
git commit -am "chore: bump blog-tools to 1.1.0"
git push
# On the consumer's machine
/plugin marketplace update dizenz

A skill shipped through a plugin doesn't update on its own. Bumping the version field in plugin.json is what tells a marketplace this is a new release; skip that, and every consumer keeps running the old copy indefinitely, silently.

There's one more lifecycle detail worth knowing before relying on a skill mid-task: once invoked, its rendered content stays in the conversation for the rest of that session and is never re-read. Editing a skill while an agent already has it loaded doesn't change anything until the next fresh invocation.

Before shipping an edit, it's worth confirming it's actually an improvement rather than a regression dressed up as one — the skill-creator plugin automates exactly that, running the same test prompts against both versions and comparing the results side by side.

07

Where This Is Going

Agent Skills started as an Anthropic format but didn't stay one — it's now an open specification, and a long list of other agents and editors already read the same SKILL.md shape, from Cursor and GitHub Copilot to Gemini CLI and Codex. A skill written for one of them is, for the most part, a skill written for all of them.

That's the real difference from stuffing everything into a system prompt: a skill is portable in a way vendor-specific instructions never were. It pairs naturally with MCP, too — MCP gives an agent the reach to touch a system, a skill gives it the procedure for using that reach well. Write the knowledge once, and it keeps paying off everywhere an agent that speaks the format shows up.