Every developer eventually has a workflow that they repeat. A method by which they write the commit message. A checklist they run before opening a pull request. A structure they follow when reviewing code. They do it manually, explain it to their agents every session, and watch the agent interpret it differently each time.
Agent skills fix it. A skill is a Markdown file that is automatically loaded into the CloudCode context when you need it. You write the workflow once. The agent follows it every time. And because skills follow an open standard, the same file works in Claude Code, GitHub Copilot, Cursor, and the Gemini CLI.
This tutorial shows you how to make a skill from scratch. You’ll build a commit message writer—a skill that reads your incremental changes and produces a structured commit message that conforms to the standards of traditional commits. By the end, you’ll have working skills installed and ready to use, and you’ll understand the structure well enough that you’ll need any skills.
Table of Contents
What are the skills of the agent?
A skill is a folder that contains a SKILL.md File This file has two parts: a YAML frontend block at the top, and a Markdown body below it.
my-skill/
└── SKILL.md
The front meter tells the agent what skills to call and when to use them. The body tells the agent what to do when it loads the skill. Here is the minimal structure:
---
name: my-skill
description: What this skill does and when to use it.
---
# My Skill
Instructions for the agent go here.
When you request a skill – either clearly /skill-name Or specifying what you want — the agent reads the SKILL.md body and executes the instructions within it. The front meter never reaches the agent’s instructions. This is the metadata that the skill system uses to decide whether to load the skill at all.
How the agent decides to load skills.
Before writing your first skill it is most important to understand: The agent decides whether to load your skill based entirely on the description field.
In the context of cloud code, a skill appears as a list of names and descriptions. When you make a request, the agent scans the list and loads any skills that match the description you requested. If the description is vague, the skill won’t load when you need it. If the description is too narrow, it won’t load for variants of the same request.
Instruction in the body matters only after the load of skill. Getting the detail right is what determines if a skill is a load at all.
What skills are not
Skills are instruction files. They can’t run the code themselves—but they can instruct the agent to run the code using its existing tools. They are not plugins, extensions or packages. They have no runtime. They are Markdown files that the agent reads, like a recipe a chef follows.
How to choose what to make
The best skills share three characteristics.
They encode a repeatable workflow. If you do something different every time, skill won’t help. If you follow the same steps every session — even if you explain them differently each time — that’s a skilled candidate.
They have a clear motivation. You should be able to finish the sentence “I need this skill when I want to…”. If you can’t end that sentence in one clause, the workflow isn’t good enough for the skill.
They produce a consistent output format. Skills that develop within a fixed structure—a commit message, a code review, a spec—are easier to build and test than skills that develop open-ended prose.
Good candidates: Send messages, application descriptions, code reviews, changelog entries. Bad candidates: “help me think about it”, “make it better” – too open to encode into skills.
Commit message generation is the correct scope for this tutorial. The trigger is clear (you want to commit), the workflow is defined (read incremental changes, apply the traditional commit format), and the output is structured (a commit message with a specific format).
How to build your skills
Each skill starts as a folder with a file:
commit-message-writer/
└── SKILL.md
As skills grow, they can add additional files that the agent loads as needed:
commit-message-writer/
├── SKILL.md ← always loaded when skill triggers
└── references/
└── examples.md ← loaded only when the agent needs examples
The SKILL.md body should be under 500 lines. If your instructions go beyond that, move the supporting description to a. references/ Tell the subfolder and agent when to read these files. This keeps skills lean – the agent loads only what it needs.
For this tutorial, a single SKILL.md is sufficient.
How to write a description?
The detail field is the trigger state. This determines when your skills load and when they don’t. Most skills fail not because the instructions are wrong, but because the description doesn’t match how people actually ask for help.
Here is a weak explanation:
description: Generates commit messages.
This will under trigger. “generate a commit message” will load it. “Write a commit for my changes” probably won’t. “Summarize my staged difference” certainly won’t – even though all three are asking for the same thing.
Here is a strong explanation:
description: Generates structured commit messages following the Conventional Commits standard. Use when you want to commit your changes and need a well-formatted message. Triggers on "write a commit message", "commit my changes", "summarize my staged diff", "what should my commit say", or any request to describe or document code changes for version control.
The pattern is: What the skill does + when to use it + specific trigger phrases. Trigger sentences cover the different ways a developer can ask for the same thing.
Two rules of explanation:
Be specific about the output. “Generates commit messages” is ambiguous. “Generates structured commit messages according to the standard of traditional commits” tells the agent and user exactly what they will receive.
Be a little pushy. Agents have a natural tendency to down-skill — to offload a skill rather than handle requests themselves. A description that clearly lists the trigger phrase counters that. You are not useless. You are training the trigger.
How to write instructions
The body of SKILL.md is where you define what the agent does when the skill is loaded. Good instruction follows two principles.
Create first, clarify second. The agent should provide output immediately rather than asking obvious questions. If it needs to make assumptions, it should make them and flag them – don’t ask. Asking questions before generating output increases friction and loses the benefit of mastery.
Clearly define the output format. Don’t say, “Write a good commit message.” Explain exactly what the structure is, what fields are required, what the character limits are. The more specific the output format, the more consistent the results.
Here’s what weak directives look like:
# Commit Message Writer
Look at the staged changes and write a commit message that describes what changed.
It will produce different results each time — different formats, different lengths, different conventions. It is not a skill. This is a prompt.
Here’s what strong directives look like:
# Commit Message Writer
Read the staged diff using `git diff --staged`. Generate a commit message
following the Conventional Commits standard.
Output format:
type(scope): short description under 72 characters
Body (if changes are non-trivial):
- What changed and why, not how
- One bullet per logical change
Footer (if applicable):
BREAKING CHANGE: description
Closes #issue-number
The agent knows exactly what to produce. Output will be consistent across sessions, across projects, and across agents that support the standard.
How to build commit-message-writer skill
Now make it. Create a skills directory:
mkdir -p ~/.claude/skills/commit-message-writer
On Windows PowerShell:
Note: PowerShell uses backticks (`For line continuation, no backslash.
New-Item -ItemType Directory -Force -Path "$HOME\.claude\skills\commit-message-writer"
Create a SKILL.md file inside this directory. Here is the full content:
---
name: commit-message-writer
description: Generates structured commit messages following the Conventional Commits
standard. Use when you want to commit your changes and need a well-formatted message.
Triggers on "write a commit message", "commit my changes", "summarize my staged
diff", "what should my commit say", or any request to describe or document staged
changes for version control.
---
# commit-message-writer
You generate structured commit messages from staged git changes.
## How to invoke
Run `git diff --staged` to read the staged changes. If nothing is staged, tell the
user and suggest they run `git add` first.
Generate first. Do not ask clarifying questions before producing the commit message.
If you need to make assumptions about scope or type, make them and note them after
the output.
## Output format
~~~
type(scope): short description
(body — optional, include if changes are non-trivial)
(footer — optional)
~~~
**Type** — choose one:
- `feat` — a new feature
- `fix` — a bug fix
- `docs` — documentation changes only
- `refactor` — code change that neither fixes a bug nor adds a feature
- `test` — adding or updating tests
- `chore` — build process, tooling, or dependency updates
**Scope** — the module, file, or area affected. Use the directory name or component
name. Omit if the change spans the entire codebase.
**Short description** — imperative mood, under 72 characters, no period at the end.
"Add user authentication" not "Added user authentication" or "Adds user authentication."
**Body** — what changed and why, not how. One bullet per logical change. Skip if the
short description is self-explanatory.
**Footer** — include `BREAKING CHANGE:` if the commit breaks backward compatibility.
Include `Closes #N` if it resolves a GitHub issue.
## Quality rules
- Never use "updated", "changed", or "modified" in the short description — be specific
- Never write "various improvements" or "misc fixes" — name what improved
- If more than three files changed across unrelated concerns, flag it:
"These changes may be better split into separate commits: (list concerns)"
- The short description must be under 72 characters — count before outputting
## Example output
Input: staged changes adding a rate limiter to an API endpoint
~~~
feat(api): add rate limiting to /query endpoint
- Limits requests to 100 per minute per IP using Cloudflare's rate limit binding
- Returns 429 with Retry-After header when limit is exceeded
- Adds rate limit configuration to wrangler.toml
Closes #47
~~~
Save this file. Talent is born.
How to install and test your skills
Verify that the file exists.
cat ~/.claude/skills/commit-message-writer/SKILL.md
You should see the full SKILL.md content. If you get an error, check the directory path.
Take a skill test.
Open CloudCode in any git repository that has changes. Type:
/commit-message-writer
The agent will read your phase difference and generate a commit message following the format you specify.
You can also activate it naturally:
write a commit message for my staged changes
what should my commit say
summarize my diff for git
All three should load the skill and generate a structured commit message. If the skill doesn’t trigger on natural language requests, the description needs more trigger sentences — see the Improvements section below.
Test edge cases
Check these matters before relying on production expertise:
# Stage nothing, then ask for a commit message
git add -p # stage nothing
# In Claude Code: "write a commit message"
# Expected: skill tells you nothing is staged and suggests git add
# Stage changes across unrelated files
git add src/api.ts src/styles.css README.md
# In Claude Code: "write a commit message"
# Expected: skill flags that commits may be better split
How to improve your skills over time
The first version of any skill is a draft. You improve it by seeing where it produces inconsistent or incorrect output, then updating the instructions.
When skill under-triggers
If you type “summarize my changes for git” and the skill doesn’t load, add this phrase to the description trigger list:
description: ... Triggers on "write a commit message", "commit my changes",
"summarize my staged diff", "summarize my changes for git", ...
Detail is your primary lever for fixing triggering problems.
When the output format increases.
If the agent starts generating commit messages that don’t match your format—invalid type, missing scope, malformed body—the instructions need to be more specific. Add a concrete example that shows the failure and correct output:
## Common mistakes to avoid
Wrong: "Updated the authentication flow"
Right: "refactor(auth): simplify token validation logic"
Wrong: "Fixed bugs"
Right: "fix(api): handle null response from upstream service"
Concrete counterexamples are more effective than abstract principles.
When scope increases.
If you find yourself wanting skills to handle related tasks – reviewing commit messages, creating changelogs, writing PR descriptions – resist the urge to lump everything into one skill. Create separate skills. Each skill should do one job well. The Agent Skills standard is designed to be structured and not monolithically prescriptive.
Where to go next?
The commit message writer covers the basic pattern. The same structure works for any repeatable workflow.
Draw the application specifications. Follow the same format – read diff, apply a structure, generate consistent output. The stimulus phrases are different (“Write a PR description”, “Summary my branch for review”) and the output format includes motivation and test sections, but the structure of SKILL.md is the same.
Code review checklist Work together efficiently when your team has a standardized review process. The trigger is “review this code” or “check this PR”, and the instructions encode whatever your team actually checks — security concerns, test coverage, naming conventions.
The commit message writer is the simplest architecture — just instructions. As your skills become more proficient, two other artifacts become useful.
The first adds a references/ Directory: The Voice Humanizer skill loads a CORPUS.md file containing the author’s published text, which the agent reads when it needs to check the output against a specified style. The second adds quality rules and structured output formats that make results tighter and more consistent—that’s the pattern SpecWriter uses to map assumptions to the inline level. Each is the same SKILL.md structure at a different level of complexity.
Just start with the instructions. Add references when the agent needs external context. Add output format rules when consistency is more important than flexibility.
The AgentSkills standard is supported in CloudCode, GitHub Copilot in VS Code, Cursor, and Gemini CLI. A skill that you install once in all of them. The installation path varies depending on the agent:
| Agent | Skills Directory |
|---|---|
| Claude Code | ~/.claude/skills/ |
| GitHub Copilot | ~/.copilot/skills/ or .github/skills/ |
| Cursor | ~/.cursor/skills/ |
| Gemini CLI | ~/.gemini/skills/ |
The SKILL.md format is the same in all of them.
The commit message writer you just created is a skill to work with. The next one will take less time. By the third, you’ll start seeing workflows you repeat and immediately think: This must be a skill.
That’s the point.