DEV Community

Alex Cloudstar
Alex Cloudstar

Posted on • Originally published at alexcloudstar.com

Writing Your Own Claude Code Skill in 2026: The Practical Guide

I noticed I was typing the same five paragraphs into the Claude Code prompt every morning. The paragraphs explained how I wanted PR reviews done on my own projects: which directories to weight, which patterns I cared about, what to ignore, what to flag, what to never suggest. Five paragraphs, every morning, sometimes twice.

The third time I noticed it, I copied the paragraphs into a SKILL.md, dropped it in my plugin directory, and added a one-sentence trigger description. The next morning I typed "review this branch." Claude pulled the skill in automatically and produced exactly the review I had been asking for by hand. I have not pasted those paragraphs again.

That was the moment I understood that skills are not for sharing with the world. They are for sharing with future-you. The marketplace is great, but the highest-leverage skills you will ever use are the ones you write for your own projects, your own quirks, your own opinions about how the work should be done. This post is the missing manual for writing them.

If you have not seen the Claude Code plugin marketplace post, read that first for the broader context. This one is the hands-on follow-up: how to actually write a skill, where they live, what makes them fire, and the patterns that keep tripping up developers who try.


Why You Should Write Your Own Skills

There is a category of work that you do over and over again, that has a clear right answer, and that you have to re-explain to the model every time. That is the skill-shaped hole in your workflow. Pattern-match for it.

Common examples from my own machine.

A skill that knows how my Astro blog is structured, where posts live, what the frontmatter schema is, and how internal links should look. Saves me a paragraph of context every time I write a post.

A skill that turns "review the work" into a deep verification pass with a specific checklist, instead of the generic "looks good to me" review the model produces by default.

A skill that estimates how long a ticket should take, in story points, using the rubric my team has agreed on. This used to be a paragraph I copy-pasted from a Notion doc. Now it is a slash command.

A skill that knows my testing conventions and refuses to suggest tests that mock the database, because we agreed not to mock the database two quarters ago and the model keeps forgetting.

None of these are interesting to the world. All of them save me actual time, every week, on specific work I am going to do anyway. That is the skill bar. Useful to you, repeatedly, on real work. Everything else is a hobby.

The other reason to write skills, separate from the time savings, is that the model's default behavior is a compromise designed to please everyone. Your work is not "everyone." Your work is yours. Every skill you write pushes the model's behavior closer to what you actually want, and away from the average of what everyone wanted in the training data. That distance, accumulated across a dozen skills, is what makes the difference between "the AI is a smart intern" and "the AI is a smart colleague who already knows how we do things here."


The Anatomy Of A Skill

A skill is a directory with a SKILL.md at the root. That is it. Everything else is optional. The directory can also contain supporting files (scripts, references, examples, additional Markdown chunks the skill points to) but only the SKILL.md is required.

The SKILL.md has frontmatter and a body. The frontmatter looks like this.

---
name: review-blog-post
description: Review a draft blog post for voice consistency, em-dash usage, and SEO hygiene before publishing. Use when the user mentions "review the post," "check the draft," or pastes a blog post for feedback.
---
Enter fullscreen mode Exit fullscreen mode

Two fields. Name is the slug. Description is the trigger. The description is doing roughly ninety percent of the work and most people get it wrong on the first try. I will come back to that.

The body of the SKILL.md is the instructions the model reads when the skill fires. It is plain Markdown. You can use headings, bullets, code blocks, examples, anything that helps the model do the work. The body is loaded into context as system instructions for the turn, so treat every word as load-bearing.

A skill can also live inside a plugin. A plugin is a directory with a plugin.json and one or more skills inside a skills/ subfolder. Plugins are the unit that the marketplace ships. For personal use you do not need a plugin wrapper at all. Just drop the skill into ~/.claude/skills/ and it will fire. If you want to share the skill or use it across multiple projects with version control, wrap it in a plugin and ship it through your own Git-backed marketplace, the way the marketplace post walks through.


The Trigger Description Is The Whole Game

If you take one thing from this post, take this. The skill's trigger description is the single most important line you will write, and it is the line developers most consistently underthink.

The description is what the model reads at the top of every turn to decide whether to load the skill. The model sees a list: skill name, one line of description, skill name, one line of description. Maybe forty entries. It picks the ones that match the current task. Your description is competing with thirty-nine others for the model's attention. If your description is vague or generic, it loses, and your skill never fires.

What a bad description looks like.

description: Helps with code reviews.
Enter fullscreen mode Exit fullscreen mode

What a good description looks like.

description: Review code for the alexcloudstar.com Astro blog. Use when the user runs /review, asks to review a PR or branch, or pastes a diff and asks for feedback. Checks voice consistency, em-dash usage, internal-link health, and MDX frontmatter schema.
Enter fullscreen mode Exit fullscreen mode

The good one names the triggers (/review, "review a PR or branch," pasting a diff), describes the scope (this blog specifically), and lists the checks. The model now has a clear handle on when this skill applies and when it does not. The bad one matches "code review" abstractly and ends up either firing on every code-review-shaped task and confusing the model, or never firing at all because something more specific outranks it.

The pattern I use.

{What it does in a sentence}. Use when {trigger phrase 1}, {trigger phrase 2}, or {trigger phrase 3}. {Optional scope note}.

If a skill could plausibly fire on anything code-related, you have not been specific enough. Tighten the description until it fires on the cases you want and stays silent on the rest. The wrong skill firing at the wrong time is worse than no skill firing at all, because it wastes the turn.


Writing Your First Skill: A Walkthrough

Let me walk through a concrete example end to end. The goal: a skill that codifies how I want commit messages written on my projects.

I open a terminal and run.

mkdir -p ~/.claude/skills/conventional-commits
cd ~/.claude/skills/conventional-commits
Enter fullscreen mode Exit fullscreen mode

I create SKILL.md.

---
name: conventional-commits
description: Write a Git commit message in the project's conventional-commits style. Use when the user runs /commit, asks to "write a commit message," or finishes a change and asks what to commit. Generates the message; never runs git commit unless explicitly asked.
---

# Conventional Commits

You are writing a commit message for code changes the user has made. Follow these rules.

## Format

`<type>(<scope>): <subject>`

- type: one of feat, fix, refactor, chore, docs, test, perf, style, build, ci
- scope: optional, lowercase, one or two words max, no spaces (use hyphens)
- subject: imperative mood, lowercase, no trailing period, under 72 characters

## Body

- Wrap at 72 characters
- Explain the **why**, not the **what**. The diff already shows the what
- Reference related issues with `Refs: #123` or `Closes: #123` on their own line
- Skip the body entirely for trivial commits

## Hard rules

- Never use em dashes. Use commas, periods, or restructure the sentence
- Never add Co-Authored-By unless the user explicitly asks for it
- Never run `git commit` yourself. Output the message and let the user decide
- If the diff touches more than one logical change, suggest splitting into multiple commits rather than writing one big message

## Examples

`feat(blog): add MCP server tutorial post`

`fix(rss): drop trailing slash in canonical URL`

`refactor(content): split shared frontmatter into a helper`
Enter fullscreen mode Exit fullscreen mode

That is the skill. It took five minutes. I save the file, restart Claude Code (or run /plugin reload), and from the next session forward, when I finish a change and say "what should I commit," the model produces a message in exactly the format I want. No back and forth, no reminders, no "actually I prefer the subject in lowercase."

The reason this works is the description. It names three trigger phrases I actually use. It scopes the skill to commit-message writing only. It mentions a guardrail (does not run git commit) that disambiguates this skill from any general "make a commit" skill that might exist. The model loads it when relevant and ignores it the rest of the time.


The CLAUDE.md To Skill Promotion Path

The fastest way to write good skills is to not start with skills. Start with CLAUDE.md.

When I am working on a new project, every instruction I find myself giving the model more than once goes into CLAUDE.md first. The file lives in the project root, loads automatically on every turn, and is the lowest-friction way to capture a working pattern. Most projects need ten to thirty lines of CLAUDE.md and that is the right amount.

The problem with CLAUDE.md is that it loads on every turn. As it grows past a couple hundred lines, the model spends real context on it whether the current task is relevant or not. That is when you promote.

Pick a section of CLAUDE.md that only matters for a specific class of task. Move it to a skill. Write a description that targets exactly that class of task. The CLAUDE.md keeps the always-relevant rules. The skill carries the sometimes-relevant ones. The model loads the sometimes-relevant ones only when they apply.

This promotion path is the most reliable way to write skills that actually fire well, because the body of the skill is content you have already validated by using it as CLAUDE.md instructions. You know it works. You know the model follows it. You are just changing the trigger surface from "always" to "when relevant."

Do not skip the validation step. Skills written from scratch, without a real-use loop, are almost always too abstract. The model ignores them in practice because the descriptions sound right but the body says nothing it cannot infer on its own. Skills written by promotion are concrete, opinionated, and load-bearing.

The same pattern applies to skills you find in the marketplace. Install the one that almost fits. Use it for a week. Note where it does the wrong thing. Fork it, write your own copy in your local ~/.claude/skills/, and tune the body to match your project. The forked skill outperforms the original every time, because the original was the average of what worked for everyone and yours is exactly what works for you.


Skill Versus Subagent Versus Hook Versus MCP

This is the matrix that confused me for months. Let me draw it cleanly.

A skill is structured instructions the model reads when the trigger matches. Pure prompt. Runs in the same turn. No external process. Fires when relevant, sits silent otherwise. Use for: codifying how you want the model to approach a class of task.

A subagent is a separately-spawned model invocation, with its own context window, that returns a summary to the main agent. Use for: research, broad code exploration, parallel work, or any case where you want to protect the main context from a lot of intermediate output.

A hook is a shell command the harness runs in response to a lifecycle event. Runs outside the model. Use for: enforcing rules the model cannot enforce on its own (formatters, linters, tests, audit logs). The right tool when the requirement is "every time X happens, Y must run, regardless of what the model decides."

An MCP server exposes tools to the model that it can call mid-turn to read or modify external systems. Use for: any case where the model needs to touch a system it does not natively know about (your database, your ticketing system, your build pipeline). See the MCP server building guide for how to write one.

The honest matrix.

  • "I want the model to do X consistently" → skill
  • "I want to delegate X without polluting context" → subagent
  • "I want X to happen every time, no matter what" → hook
  • "I want the model to read or modify Y" → MCP server

A well-tuned project uses two or three of these together. A skill that tells the model how to use an MCP server is the canonical pairing. A hook that runs a test suite after every code edit, paired with a skill that explains how to interpret the test output, is the second-most-common pairing. The primitives compose.

What you should not do is reach for an MCP server when a skill would have been enough, or reach for a skill when a hook is the right answer. The first wastes engineering time. The second produces unreliable enforcement, because the model can decide not to follow a skill but cannot decide not to run a hook.


Patterns That Work, And Ones I Keep Failing With

After roughly thirty skills written (most kept, some thrown out), here are the patterns I trust.

Skills that codify a checklist work brilliantly. Anything where there are five to fifteen specific things you want the model to do or not do, in a specific order, is a perfect fit. The review-work skill on my machine is twenty bullet points. It runs the same checks every time. The model reliably executes the list. The output is consistent.

Skills that name the bad outputs explicitly work better than skills that describe the good ones. "Do not use em dashes. Do not write Of course!. Do not start with Let me dive into." beats "Write in a clean style." The model is much better at avoiding specific banned strings than at hitting a vague target.

Skills that include before/after examples work better than skills that just state rules. Two paragraphs of "here is the rule" plus one paragraph of "here is a wrong version and the right version" produces dramatically better adherence than three paragraphs of pure rules.

Skills scoped to a tool or a file type work better than skills scoped to a "domain." A skill for Astro MDX posts is better than a skill for "blog writing." A skill for Drizzle migrations is better than a skill for "database work." Narrow scope, sharp trigger, concrete body.

The patterns I keep failing with.

Skills that try to teach the model a whole domain in five hundred lines. The model already knows the domain. The skill should add the specifics of how you want the domain handled, not re-teach it. Long, comprehensive skills load slowly, dilute attention, and often get ignored when something more specific exists.

Skills with overlapping triggers. If two of my skills both claim to fire on "code review," the model picks one (often the wrong one) and the other never gets used. Audit your triggers. Make sure each skill owns a clear slice of the task space.

Skills that mix instructions for the model with documentation for humans. Pick a lane. The SKILL.md body is read by the model on every fire. If you want a human-readable README, put it in README.md next to SKILL.md. The body of the skill should be all model-facing, all the time.

Skills that depend on context the model does not have. "Use the patterns from the design system" is useless if the design system is not in context. Either inline the relevant patterns, or have the skill instruct the model to read a specific file before continuing.


Versioning, Shipping, And The Plugin Wrapper

For personal skills, sitting in ~/.claude/skills/, you do not need a plugin or a version. You are the only user. Just edit the file when it needs to change.

The moment you want to share a skill (with a teammate, with a client, with the world), wrap it in a plugin.

A plugin is a directory with a plugin.json and a skills/ subfolder. The plugin.json looks roughly like this.

{
  "name": "alexcloudstar-blog-tools",
  "version": "0.2.0",
  "description": "Skills for writing and reviewing posts on alexcloudstar.com",
  "author": "alexcloudstar",
  "skills": ["review-blog-post", "estimate-post-effort", "publish-checklist"]
}
Enter fullscreen mode Exit fullscreen mode

Push that to a public or private Git repo, point your marketplace.json at it, and /plugin install alexcloudstar-blog-tools works for anyone with the marketplace added.

Versioning matters more than people expect. The moment a skill is in use by anyone other than you, breaking changes to the skill's behavior need a major version bump. Otherwise users who pull the latest version will see different outputs from the same prompts, and they will not understand why. Treat skills like API contracts. They are read by an agent, but the agent's behavior is observable, and the user has built a mental model around it.

A CHANGELOG.md next to your plugin.json is more important than you would guess. The plugins that get adopted have changelogs. The ones that do not have changelogs feel risky to install. The cost of writing two lines per release is roughly zero. Do it.


What I Wish I Knew After Twenty Skills

A few hard-won lessons in no particular order.

Most skills should be under a hundred lines. If you find yourself writing a fifth heading, you are probably building two skills, not one. Split.

Test triggers explicitly. After writing a skill, start a fresh session and use natural-sounding prompts that should fire the skill. If it does not fire, the description is wrong. Iterate on the description until it fires reliably on three or four trigger phrases you actually use.

Re-read your own skills monthly. Skills rot. The conventions in the body drift away from the conventions you actually follow. If a skill no longer matches how you work, edit it or delete it. Stale skills are worse than no skills, because they produce confident wrong answers.

Skills compose with subagents better than you would expect. If you have a skill that explains how to do a deep review, and you spawn a subagent to do the review, the subagent inherits the skill. You get focused, high-quality work in a protected context window. The combination is one of the strongest patterns in the system.

Do not skill-ify creative work. A skill that "writes a blog post" produces formulaic blog posts. The point of writing is that the output is yours, not the model's. Skills are excellent for repetitive, rule-based work, and they are the wrong tool for work where the value is in the unique judgement you are bringing. For my own writing, I have skills for the mechanical parts (frontmatter schema, internal-link patterns, SEO checks) and no skills for the actual prose. The mechanical parts are happily automated. The prose is mine.

Treat skills as a backlog, not a one-shot. I keep a notes file with "things I keep typing into the prompt." Every couple of weeks I look at the list, pick the top one, and turn it into a skill. The compounding effect over a year is significant. The single-week effect is not.


Where The Skills Ecosystem Is Going

The skills surface is going to grow fast in late 2026. Anthropic has signalled that the official marketplace will start accepting third-party plugins under a review process by Q3. Cursor is shipping their own skill format (compatible enough that conversion will be a script). The MCP integration with skills is getting tighter: a skill that knows about a specific MCP server's tools and explains how to chain them is becoming the canonical "useful plugin."

What this means in practice. The half-life of a useful skill is increasing. The skills I wrote six months ago still fire, still work, and still save time. The skills I write now have a longer runway than the skills I wrote in 2025, because the surrounding ecosystem (plugins, marketplaces, MCP, hooks, subagents) is no longer changing weekly. The investment compounds.

The other thing it means. The teams that have ten well-tuned internal skills are dramatically more productive than the teams that have none. The gap is roughly the size of a junior developer per developer. That is a real number. It does not show up on dashboards. It shows up in the rate at which work that used to be repetitive becomes automatic.

If you have read this far, the next step is concrete. Open ~/.claude/skills/. Create a directory. Drop a SKILL.md in it. Pick the smallest, most boring, most repeated thing you do every week and codify it. Spend twenty minutes on the description. Test the trigger. Use the skill for a week.

If you do that one time, the next nine skills will write themselves. The leverage is real. The investment is small. The hard part is just starting.

The dotfiles era of AI tooling produced your vimrc. The skills era produces your ~/.claude/skills/ directory. Treat it with the same care, and it will repay you the same way.

Top comments (0)