Building Your First Skill
What this gives you: Reusable one-command workflows that save you hours every week. Instead of explaining the same process every time, you type /meeting-prep or /follow-up and Claude handles everything automatically.
What Is a Skill?
A skill is a reusable, invokable workflow that lives in your ~/.claude/skills/ directory. You call it with a slash command like /meeting-prep or /create-invoice, and Claude executes the entire workflow defined inside it - pulling data from APIs, reading files, generating output, and handing you a finished result.
The difference between a skill and just asking Claude something in chat is repeatability. A skill bakes in your exact process: which data sources to hit, what format the output should be, what rules to follow, what to do when something is missing. You define it once and invoke it hundreds of times. It behaves identically every time and gets better when you update the definition - not when you try to re-explain the same instructions from memory each session.
Skills are plain markdown files. No code to compile, no frameworks to learn, no deployment pipeline. You write a SKILL.md file that describes what Claude should do step by step, and Claude Code reads that file at invocation time and executes it. You can ship a new skill in under 10 minutes.
File Structure
Every skill lives in its own named subdirectory inside ~/.claude/skills/. The only required file is SKILL.md. Anything else - helper scripts, templates, reference data - lives alongside it.
Claude Code will automatically discover any skill whose directory name is listed in your CLAUDE.md capabilities section. The directory name becomes the slash command. A folder called meeting-prep becomes /meeting-prep.
The SKILL.md Frontmatter Format
Every SKILL.md starts with a YAML frontmatter block that tells Claude Code how to surface and describe the skill. Below the frontmatter is the skill body - plain markdown with instructions, steps, rules, and output format specifications.
The description field is what Claude reads to decide whether to auto-suggest this skill when the user says something that sounds like it fits. The triggers list gives explicit phrases that should surface this skill. Keep descriptions precise - vague descriptions mean Claude suggests the wrong skill at the wrong time.
Step-by-Step: Build a /meeting-prep Skill
Step 1: Create the directory
Step 2: Write the SKILL.md
Open ~/.claude/skills/meeting-prep/SKILL.md in your editor and write the full skill definition. This is where you invest the time upfront. The more precise your steps, rules, and output format, the less you have to think during the actual meeting prep.
Registering the Skill in CLAUDE.md
Claude Code only knows about a skill if you list it in your CLAUDE.md capabilities section. Open ~/.claude/CLAUDE.md and add an entry under the skills section:
Keep descriptions short - one line each. Claude reads this section to understand what tools are available. The description here is different from the one in the SKILL.md frontmatter: this one appears in your global context on every conversation, so keep it to one punchy sentence.
Testing and Iterating on Skills
The fastest way to test a skill is to just invoke it. Open a new Claude Code session (important - fresh context), type /meeting-prep, and follow the prompts. Watch what Claude does at each step and note where it deviates from what you wanted.
Common issues on first run and how to fix them:
| Symptom | Cause and Fix |
|---|---|
| Claude skips a step | Your step description is ambiguous. Rewrite it as a concrete action with a subject and verb. "Search Fireflies for transcripts" beats "check previous meetings." |
| Output format is wrong | Include a literal example in your SKILL.md. Claude matches format examples very reliably. Abstract format descriptions get interpreted loosely. |
| Claude asks too many questions | Your trigger detection is weak. Add more trigger phrases, or instruct Claude to infer the contact name from context before asking. |
| Data sources not being called | Check your MCP servers are connected. If an MCP tool isn't available, Claude will silently skip it. Add a rule: "If MCP X is unavailable, say so explicitly." |
After each iteration, test in a fresh session. Existing sessions carry state that can mask whether your changes actually fixed the problem. The discipline of always testing fresh is what separates skills that work reliably from skills that seem to work during development then fail in production.
Adding Helper Scripts
Sometimes a skill needs to run shell commands that are complex enough to warrant their own file. Put these in a scripts/ subdirectory inside your skill folder. Reference them in the SKILL.md by absolute path.
~/.env inside scripts, never hardcode them. And always add your skills directory to your .gitignore if you push it anywhere - your SKILL.md files may reference env var names and contain private workflow logic.Best Practices: One Job Each
The single most important principle for skills that actually work in production: each skill does exactly one job. Not "meeting prep and CRM update." Not "invoice and follow-up email." One job.
When you give a skill two jobs, two things go wrong. First, the steps start to conflict - meeting prep wants to read from GHL while CRM update wants to write to GHL, and the order matters. Second, the skill becomes hard to invoke correctly because the trigger condition is now a conjunction: you only want both jobs when both conditions are true, which is rare enough that you invoke manually each time anyway.
If you find yourself writing a skill that has two natural phases, split it. Make /meeting-prep read-only and write a separate /post-meeting skill for the CRM update and follow-up email. Then you can chain them: /meeting-prep before the call, /post-meeting after. Each one stays simple, testable, and reliable.
- Keep SKILL.md under 150 lines - if it's longer, split into two skills
- Use numbered steps, not prose paragraphs, for the execution flow
- Always include a rules section with the non-negotiables
- Always include a concrete output format with a real example
- Test in a fresh session after every edit
- Name skills after what they produce, not what they do:
/invoicenot/create-invoice-from-crm-and-email