Intermediate

Paste this guide into Claude Code and it will walk you through every step interactively.

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/skills/ ├── meeting-prep/ │ ├── SKILL.md # the skill definition (required) │ └── scripts/ │ └── fetch-transcript.sh # optional helper script ├── create-invoice/ │ ├── SKILL.md │ └── templates/ │ └── invoice-template.html └── security-audit/ └── SKILL.md

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.

--- name: meeting-prep description: > Prepare a pre-call briefing by pulling context from Google Calendar, Fireflies transcripts, CRM data, and web search. Use when the user mentions an upcoming call, meeting, or client session. triggers: - "meeting prep" - "prep for my call" - "I have a call with" ---

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

mkdir -p ~/.claude/skills/meeting-prep/scripts

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.

--- name: meeting-prep description: > Prepare a briefing document for an upcoming call. Pulls from Google Calendar, Fireflies, GoHighLevel, and web search. Use when the user mentions any upcoming call, meeting, client session, or discovery call. triggers: - "meeting prep" - "prep for my call" - "I have a call with" - "prepping for" --- # /meeting-prep Skill You are preparing a pre-call briefing document. Work fast, be thorough, and produce a single structured document the user can read in 3 minutes. ## Trigger Invoked via `/meeting-prep` or when the user says they have an upcoming call/meeting. Ask for the contact name or company name if not provided. ## Steps ### 1. Identify the meeting - Ask: "Who is the call with, and roughly when?" (skip if already stated) - Parse the name/company from the user's message if possible - If a time was given, note it for Calendar lookup ### 2. Pull Google Calendar - Use the Google Calendar MCP to list events for today and tomorrow - Find the matching event by contact name or company - Extract: start time, duration, video link (Zoom/Meet/Teams), attendees ### 3. Search Fireflies for recent transcripts - Search Fireflies MCP for transcripts mentioning the contact/company - Look at the last 2-3 meetings if multiple exist - Extract: key topics discussed, pain points mentioned, objections raised, commitments made (what did YOU promise?), open questions ### 4. Pull CRM context from GoHighLevel - Search GHL MCP for the contact by name or company - Extract: pipeline stage, deal value, tags, last activity date, conversation history (last 3-5 messages), any notes ### 5. Web research (if new prospect) - If no Fireflies transcript found (first meeting), search the web - Look up: company size, industry, recent news, LinkedIn presence, funding status if relevant - Max 5 minutes of research - prioritise LinkedIn and company website ### 6. Generate the briefing document Produce a structured markdown document in this exact format: ``` # Pre-Call Brief: [Name / Company] **Date:** [date] at [time] ([duration]) **Link:** [video link or "TBC"] **Pipeline Stage:** [stage] | **Value:** [deal value] ## Who They Are [2-3 sentences: what the company does, size, their role] ## Where We Left Off [Bullet points from last Fireflies transcript - max 6 bullets] ## Their Pain Points [What they said they're struggling with - exact phrases where possible] ## Open Commitments [What YOU promised to do/show/prepare - highlight in bold] ## Questions to Ask [3-5 targeted questions based on context] ## Objections to Expect [Based on past transcripts or typical objections for this ICP] ## Suggested Next Step [Clear single action to propose at end of call] ``` ## Rules - Never fabricate data. If a source returns nothing, say "No data found." - Keep bullet points tight - max 10 words each where possible - Flag any commitments YOU made in a previous call (bold + ⚠️) - If this is a first meeting, skip "Where We Left Off" section - Do not include filler phrases - every line must be actionable intel ## Output Print the briefing document directly in the chat. Do not save to a file unless the user asks. Offer to open the calendar event link at the end.
Tip: Write your rules section in the negative as well as the positive. "Never fabricate data" catches a different failure mode than "only use real data." Both are worth having.

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:

## Skills Available (invoke via /skill-name) - `/meeting-prep` - Pre-call briefing from Calendar, Fireflies, and GHL - `/create-invoice` - Generate invoices from CRM data - `/security-audit` - Scan for leaked keys, audit package.json, check .gitignore

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.

Want a custom AI system built for your business?

Skills, agents, dashboards, and integrations - built and deployed for you.

Book a Call

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:

SymptomCause and Fix
Claude skips a stepYour 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 wrongInclude a literal example in your SKILL.md. Claude matches format examples very reliably. Abstract format descriptions get interpreted loosely.
Claude asks too many questionsYour trigger detection is weak. Add more trigger phrases, or instruct Claude to infer the contact name from context before asking.
Data sources not being calledCheck 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.

# In SKILL.md - reference the helper script ### Step 2: Fetch latest Stripe revenue Run the following command and parse the JSON output: ~/.claude/skills/meeting-prep/scripts/fetch-stripe-mtd.sh Extract: MRR, month-to-date revenue, last 5 transactions
#!/bin/bash # ~/.claude/skills/meeting-prep/scripts/fetch-stripe-mtd.sh source ~/.env # load STRIPE_SECRET_KEY START=$(date -d "$(date +%Y-%m-01)" +%s 2>/dev/null || date -v1d +%s) curl -s "https://api.stripe.com/v1/charges?created[gte]=${START}&limit=100" \ -u "${STRIPE_SECRET_KEY}:" \ | jq '{ total: [.data[].amount] | add / 100, count: .data | length, recent: [.data[:5] | .[] | {id, amount: (.amount/100), description}] }'
Warning: Always load secrets from ~/.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.

Next Guide
5 Skills Every Business Needs