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.
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:
---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.
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
As a skill
Only name and description upfront
Full body loads on a match
Costs nothing the rest of the time
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.
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
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.
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.
.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:
---description: Add a new article to the dizenz blog. Use when asked towrite, draft, or publish a blog post for the site.allowed-tools: Read Write Edit Bash(pnpm lint)---## Procedure1. 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 theslug to `SLUG_TO_MESSAGE_KEY`.4. Run `node scripts/check-locales.mjs <camelKey>` — both locales mustreport the same key tree.5. Run `pnpm lint`.## Gotchas- Prose lives in `messages/{locale}.json`. Never inline copy in the pagefile — only code samples and icon arrays go there.- `en.json` and `es.json` must have identical key trees. Only the valuesdiffer.- A slug missing from `SLUG_TO_MESSAGE_KEY` silently breaks the localizedcard for any multi-word slug — it falls back to the raw slug as the key.- Spanish copy is Argentine voseo ("Instalalo", "Creá"), not neutralSpanish.- Display order in `BLOG_POSTS` is array order, not `date`. `date` isSEO-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.
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:
mkdir -p .claude/skills/new-postgit add .claude/skills/new-postgit 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.
{"name": "blog-tools","description": "Skills for writing and maintaining the dizenz blog","version": "1.0.0","author": { "name": "dizenz" }}
{"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:
/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.
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.
# 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.
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.



