Building Custom Claude Skills: Reusable Task Scripts

8 min readYaseen Khatib · MERN + AI Architect

There's a workflow you've typed into Claude forty times: "cut a release — bump the version, update the changelog from the commits since the last tag, run the build, then draft the GitHub release notes." Every time you reconstruct the same paragraph from memory, miss a step under pressure, and get slightly different output. Pasting instructions is not reuse. A Skill is: a discoverable, versioned task script the agent loads on demand and executes the same way every time.

Core Architectural Concepts & Trade-offs

A Skill is a folder with a SKILL.md at its root: YAML frontmatter declaring a name and a description, followed by the instructions the agent should follow when the skill fires. The crucial design property is progressive disclosure. Only the name and description sit in the context window by default — a few tokens advertising the capability. The full instruction body loads only when the model decides the skill is relevant. You can ship fifty skills without paying for fifty skills' worth of context on every turn.

That makes the description the single most important line in the file — it's the entire basis on which the model decides whether to invoke. Same lesson as tool descriptions (Lesson 4), same stakes: state precisely what the skill does and the trigger conditions for using it. "Cut a release: bump version, regenerate changelog, build, draft notes" gets selected at the right moment; "release helper" does not. The description is a routing decision encoded as prose.

Skills compose with everything earlier in the series, which is what makes them more than prompt snippets. A skill body can instruct the agent to call MCP tools (Lesson 5), enforce structured output (Lesson 3), and run shell commands that the permission layer gates (Lesson 7). It can bundle supporting files — scripts, templates, reference docs — that the agent pulls in only when needed. The skill becomes the orchestration layer; the primitives underneath it do the work.

The trade-off is curation. Skills are cheap to add and that's the trap — a sprawl of overlapping, vaguely-described skills produces misrouting, where the model picks the wrong one or none. Treat your skill library like a public API: few, sharp, non-overlapping capabilities with descriptions precise enough that selection is unambiguous. A small set of well-scoped skills beats a large set of fuzzy ones, every time.

A Release Skill

Frontmatter advertises the capability cheaply; the body — loaded only on invocation — is the deterministic script.

skills/cut-release/SKILL.md
---
name: cut-release
description: >
  Cut a release for this repo. Use when asked to "cut a release",
  "ship a version", or "tag a release". Bumps the version, regenerates
  the changelog from commits since the last tag, builds, and drafts
  GitHub release notes. Does NOT push or publish without confirmation.
---

# Cut a release

Follow these steps in order. Stop and ask before any push/publish.

1. Determine the bump (patch/minor/major) from the commits since the
   last tag. If ambiguous, ask.
2. Run `pnpm version <bump> --no-git-tag-version`.
3. Regenerate `CHANGELOG.md`: group commits since the last tag by
   Conventional-Commit type (feat / fix / chore). Use the template in
   `./changelog-section.md`.
4. Run `pnpm build && pnpm test`. If either fails, stop and report.
5. Draft GitHub release notes from the new changelog section. Output
   them in a `<release_notes>` block — do not post them.
6. Summarize what changed and wait for go-ahead to tag and push.

Invoke it with /cut-release (or just describe the intent) and the agent loads this body, follows the steps deterministically, and stops at the boundary you defined — the same sequence, every release, with no reconstruction from memory.

Progressive Disclosure

always in contextcut-release · desctriage-bug · descaudit-deps · descgen-migration · desc~few tokens eachmatch: cut-releaseon demandSKILL.md body loads+ bundled scripts / templatesfull step-by-step instructions(only now in context)executes via MCP tools · shell (gated) · structured output
Names cost a few tokens each; only the matched skill's full body loads. Ship fifty, pay for one.

Skills are reusable behavior; the next lesson makes all of it cheaper to run by reusing the static context itself — the prompt caching deep dive. Or browse the full roadmap.

Looking to architect a similar system?

Let's ship it at AI-speed.

Start a conversation →