Your First Skill
Time to get your hands dirty. In this tutorial you will build a commit-message skill from scratch, test it, and iterate on it. By the end, you will have a working skill that generates conventional commit messages from your staged git changes.
We will use Claude Code's SKILL.md format for this walkthrough. If you use a different agent, the file format may vary slightly but the patterns are identical.
What We Are Building
The /commit-msg skill will:
- Read the currently staged git diff
- Analyze the changes to determine the type (feat, fix, docs, etc.)
- Generate a commit message following the Conventional Commits format
- Output the message without actually committing
This is intentionally simple so you can focus on the skill mechanics rather than complex logic.
Step 1: Create the Skill Directory
First, create the directory structure. We will place this as a project skill so your teammates can use it too:
For Cursor, use .cursor/rules/commit-msg/. For Windsurf, use .windsurf/rules/commit-msg/. The directory name becomes the skill identifier in all platforms.
Step 2: Write the Skill File
Create the skill file inside the directory. This is the only file required for a working skill:
---
description: Generate a conventional commit message from staged changes
allowed-tools:
- Bash(git diff --cached*)
- Bash(git status*)
---
# Commit Message Generator
Analyze the currently staged git changes and generate a commit message
following the Conventional Commits specification.
## Steps
1. Run `git diff --cached` to see the staged changes
2. Run `git status` to understand which files are affected
3. Determine the appropriate commit type:
- **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, dependencies, or tooling changes
- **style**: Formatting, whitespace, or cosmetic changes
4. Write the commit message:
- Subject line: `type(scope): description` (under 72 characters)
- Scope is optional â use the most relevant module or directory name
- Description uses imperative mood ("add" not "added")
- If changes are complex, include a body separated by a blank line
5. Output ONLY the commit message text â do not run git commit
## Example Output
```
feat(auth): add password reset flow
Implement the forgot-password endpoint and email sending logic.
Includes rate limiting to prevent abuse.
```Let's break down the key decisions:
- Description is short and starts with a verb. The agent will show this when listing available skills.
- allowed-tools is intentionally restrictive. This skill only needs to read git state, so we only allow
git diffandgit statuscommands. It cannot modify files or run arbitrary shell commands. - Steps are numbered so the agent follows them in order.
- An example output shows exactly what format we expect.
- An explicit negative constraint ("do not run git commit") prevents the agent from going further than we want.
Step 3: Test the Skill
Stage some changes in your repository, then invoke the skill:
The agent will load the skill, run git diff --cached and git status, analyze the output, and generate a commit message. The result will look something like:
refactor(components): simplify Header responsive breakpoints
Replace custom media query logic with Tailwind responsive utilities.
Remove unused useWindowSize hook import.Step 4: Iterate and Improve
Your first version will not be perfect. Here are common refinements you might make after testing:
Add scope detection logic
If the agent is picking bad scopes, add explicit guidance:
## Scope Rules
- If all changed files are in `src/components/`, scope is "components"
- If all changed files are in `src/api/`, scope is "api"
- If changes span multiple directories, omit the scope
- Never use file names as scope â use directory/module namesSupport arguments for context
You can use the $ARGUMENTS variable to let users pass additional context:
Analyze the staged changes and generate a commit message.
If the user provided additional context, incorporate it:
Additional context: $ARGUMENTSNow users can type /commit-msg fixes the login redirect bug and the agent will factor that context into the message.
Resist the urge to build a complex skill on your first try. Start with the simplest version that works, test it on real changes, and then add refinements one at a time. Each iteration, test with a variety of staged changes (single file, multiple files, different change types) to make sure the skill handles edge cases.
Step 5: Commit and Share
Once you are happy with the skill, commit it to your repository so your team can use it:
Every team member who pulls this change will immediately have access to the skill in their agent sessions.
Bonus: Making It Personal
If you want a version of this skill that only you use (perhaps with your preferred commit message style), create it in your personal skills directory instead:
Use a different name (my-commit vs. commit-msg) to avoid shadowing the project skill. Or use the same name if you intentionally want your personal version to take priority.
You have built a complete skill from scratch: created the directory, wrote a skill file with frontmatter and instructions, tested it, and learned how to iterate. These same patterns apply to every skill you build, regardless of which agent platform you use.
What's Next
The Fundamentals section is complete. In the Intermediate section, you will learn about progressive disclosure (the three-tier loading system), string substitutions, dynamic context injection, and fine-grained tool permissions.