How to Create a Claude Code Skill: A Web Scraping Example with Firecrawl
TL;DR
- What skills are: markdown files (
SKILL.md) that give Claude new capabilities and trigger automatically based on context, using progressive disclosure to keep token costs low. - What you'll build: a complete web-access skill with Firecrawl covering markdown extraction, screenshots, structured data, web search, branding extraction, documentation crawling, and recurring monitoring for competitor pages.
- What you'll learn: the
SKILL.mdformat, how to write descriptions that trigger reliably (with a forced eval hook for ~84% activation), and how to organize multi-feature skills. - Where skills work: the same
SKILL.mdfile runs across Claude Code, the Claude.ai web app, the Claude API, and other coding agents like Codex CLI and Gemini CLI. - No terminal? No problem: you can also create a skill from the Claude.ai web interface via Settings, Capabilities, Skills, without writing a single file by hand.
Skills are how you extend Claude Code. They're markdown files that teach it new capabilities, trigger automatically based on context, and work across every project once you set them up.
This tutorial covers how to build one from scratch. You'll learn the file structure, how to write descriptions that trigger reliably, and how to organize multi-feature skills. The example we'll build handles web access: markdown extraction, screenshots, structured data extraction, web search, and documentation crawling. Web access is a good teaching example because it involves external API calls, multiple use cases in a single skill, and addresses limitations in Claude Code's default capabilities.
By the end, you'll have a working skill and the knowledge to build others for whatever workflows you need.
What are Claude Code skills?
A skill is a folder containing a SKILL.md file that gives Claude Code new abilities. The file contains instructions that Claude follows when the skill activates.
Skills can call external APIs, run scripts, read files, and execute code. They're how you integrate third-party services into Claude Code in a controlled, repeatable way. You define the behavior once, and it works the same every time.
Claude Code also has slash commands, which you invoke explicitly by typing /command. Skills work differently. They trigger through semantic matching: Claude reads your request, compares it against all available skill descriptions, and activates the right one automatically. Ask "get me the markdown from this URL" and a web scraping skill activates. Ask "what's in this PDF" and a PDF skill activates. You don't memorize commands or check documentation.
Two kinds of skills
Before you start building, it helps to know which kind of skill you're actually making. In his breakdown of Claude Code skills, Nate Herk draws a distinction that changes how you scope and write them.
Capability Uplift skills give Claude abilities it doesn't have on its own. Before the skill, Claude can't do the task. After installing it, it can. The Firecrawl web skill we're building in this tutorial is a Capability Uplift skill: Claude Code can't reliably scrape modern websites, take screenshots, or crawl docs without external infrastructure, and the skill bolts those abilities on.
Encoded Preference skills are different. Claude already knows how to do the underlying task. The skill encodes your specific way of doing it. Commit message formatting, code review checklists, weekly status reports, NDA reviews: Claude can do all of these, but an Encoded Preference skill captures the exact process and defaults you want so it doesn't reinvent them each time.
Both kinds load progressively and trigger contextually. But the distinction shapes how you write the description and structure the instructions. Capability Uplift skills lean heavily on bundled scripts and clear trigger phrases ("scrape this page", "take a screenshot"). Encoded Preference skills lean on examples and rules ("here's how we write release notes", "always include a rollback section"). For a curated list of both kinds worth installing, see the best Claude Code skills to try in 2026.
MCP vs. skills
MCP servers are another extension mechanism in Claude Code. They connect Claude to external tools, databases, and APIs. Anthropic's own framing captures the split neatly: MCP provides the professional kitchen (access to tools, ingredients, and equipment), and skills provide the recipes (the step-by-step instructions for turning those tools into something useful). MCP tells Claude what it can do; skills tell Claude how to do it well.
The difference: MCP servers provide tools, skills teach Claude how to use them. An MCP server gives Claude raw access to an API with all its endpoints and parameters. A skill encodes your preferences: which endpoints to call, what defaults to use, how to format output, and how to handle errors. You get consistent behavior instead of Claude figuring out usage from scratch each time. The underlying reason this works so well: CLIs tend to outperform direct API integrations for agents. A model can discover behavior on demand rather than needing the full schema preloaded.
There's also a context window difference. MCP servers load all tool definitions upfront before any conversation starts. A typical multi-server setup can consume 50K+ tokens before you ask anything. Skills use progressive disclosure: only names and descriptions load at startup, full instructions load when activated, and reference files load on-demand. You can have dozens of skills with minimal overhead. Skills also aren't tied to Claude Code specifically. Any coding agent with filesystem access, including Codex CLI and Gemini CLI, can read the same SKILL.md files without modification. Write a skill once; it works wherever the model can read files and run commands. For Codex users looking for the top skills to install, see the best Codex skills guide. If you're deciding between agents, see the Claude Code vs Codex comparison for a side-by-side on harness depth and sandboxing, or Claude Code vs OpenCode if you're evaluating the open-source model-agnostic alternative. If you're evaluating MCP against newer agent communication standards, see our breakdown of MCP vs. A2A protocols.
| MCP servers | Skills | |
|---|---|---|
| What they provide | Raw tool access to an API | Encoded workflow with your defaults baked in |
| Context cost | 50K+ tokens loaded upfront | Name + description only; full content loads on activation |
| Setup | Server process, protocol, transports | Markdown file in a folder |
| Behavior | Claude figures out usage from scratch each time | Consistent, predictable output |
| Portability | Tied to a specific client | Works with any agent that has filesystem access |
| Best for | Maximum API flexibility | Repeatable, opinionated workflows |

Skills live in two places:
- User-level (
~/.claude/skills/): Available across all your projects. Good for personal tools you use everywhere. - Project-level (
.claude/skills/): Committed to git, shared with your team. Good for project-specific workflows.
This tutorial focuses on user-level skills since we're building something you'd want available everywhere, not tied to a single codebase.
Before building your own, it's worth knowing what's already available. Anthropic maintains an official skills repository with production-ready skills for document creation (PDF, DOCX, XLSX, PPTX), Slack GIF creation, and more. The Claude Skills Cookbook has patterns you can adapt. Community collections like Superpowers go further with structured workflow skills for brainstorming, planning, systematic debugging, and verification. These skills enforce process discipline so Claude doesn't skip planning and jump straight to code. You can install any of these with one command:
/plugin add marketplace https://github.com/anthropics/skillsFor a curated overview of what's worth installing, see the best Claude Code skills to try in 2026.
Claude Code also ships with a set of bundled skills out of the box. These are ready-made slash commands you can run without installing anything:
/simplify— rewrites selected code to be more concise and readable/batch— runs a task across multiple files or inputs in a single pass/debug— walks through debugging a problem step-by-step with structured reasoning/loop— iterates over a list of items and applies a task to each/claude-api— provides example code for calling the Anthropic API in various languages
Run /skills in any Claude Code session to see the full list of what's loaded, including both bundled and installed skills.
That said, building from scratch is the best way to understand how the system actually works. The rest of this tutorial does exactly that.
Now let's look at what goes inside that SKILL.md file.
How is a SKILL.md file structured?
Every skill starts with a SKILL.md file. The structure is straightforward: YAML frontmatter at the top, markdown instructions below.
---
name: processing-pdfs
description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction.
---
# PDF Processing
Instructions go here...The frontmatter has one required field and several optional ones:
description (required): Maximum 1024 characters. This field determines when your skill activates, so it matters more than anything else in the file. Write it in third person and answer two questions: what does this skill do, and when should Claude use it? Include specific terms users would say. "Extract text and tables" and "PDF files" will match requests better than "helps with documents."
name (optional): Lowercase letters, numbers, and hyphens only. Maximum 64 characters. If you omit this field, Claude Code uses the directory name automatically. Gerund forms work well (processing-pdfs, analyzing-data) but aren't required.
Optional fields give you more control:
allowed-tools: Restricts which tools Claude can use when the skill is active. Set allowed-tools: Read, Grep, Glob for a read-only skill. Set allowed-tools: Read, Bash(python:*) to allow only Python execution. You can scope Bash to specific commands using the Bash(command:*) syntax — for example, Bash(date:*) only allows running date, not arbitrary shell commands. Without this field, Claude can use any available tool.
model: Forces a specific model when the skill runs. Use model: claude-sonnet-4-20250514 for faster responses on simple tasks, or specify Opus for complex reasoning.
disable-model-invocation: Set to true to run the skill without making any LLM calls. Useful for deterministic scripts or shell commands where you don't want Claude reasoning over the output — just execute and return.
user-invocable: Set to false to hide the skill from the /skills list and prevent users from calling it by name. Useful for internal helper skills that other skills reference but that you don't want exposed directly.
argument-hint: A short string shown next to the skill name in /skills output. Use it to describe the expected input format, for example argument-hint: "<url> [--main-only]" so users know what to pass when invoking the skill explicitly.
context: Set to fork to run the skill in an isolated context that doesn't share conversation history with the main session. Good for self-contained tasks like code formatting or data transformation where you don't want the skill to see or modify your current conversation state.
The markdown body contains your actual instructions. Keep it under 500 lines. If you need more space, split content into separate files and link to them:
For API details, see [reference.md](reference.md)
For examples, see [examples.md](examples.md)Claude loads linked files only when needed. This progressive disclosure pattern lets you bundle detailed documentation without paying the token cost upfront. A skill with 2,000 lines of reference material loads the same as a 50-line skill until Claude actually needs that reference.
For multi-file skills, organize your directory like this:
skill-name/
├── SKILL.md # Required - main instructions
├── reference.md # Optional - API details
├── examples.md # Optional - usage examples
└── scripts/
└── validate.py # Optional - utility scriptsScripts execute without loading their contents into context. A 500-line Python validation script consumes zero tokens until it runs, and even then only the output counts.
Rules that silently break a skill
Most skill failures aren't "the script errored". They're "Claude never loaded the skill, and there was no error to tell you why". The platform enforces a handful of strict rules, and violating any of them makes the skill invisible:
SKILL.mdis case-sensitive. The file must be named exactlySKILL.md.skill.md,Skill.md, orSKILL.MDwill not be recognized. No warning, no log line, the skill just won't appear.- Folder names must be kebab-case. Lowercase letters and hyphens only. No spaces (
firecrawl web), no underscores (firecrawl_web), no capitals (FirecrawlWeb). The folder name should match thenamefield in your frontmatter exactly. - Reserved names. Skill names cannot contain
claudeoranthropic. These are reserved and the skill will be rejected. - No XML angle brackets in frontmatter. Frontmatter is injected directly into Claude's system prompt, so anything that looks like an XML tag could inject unintended instructions. The platform blocks it.
- No
README.mdinside the skill folder. All documentation Claude should see goes inSKILL.mdor under areferences/subdirectory. If you're distributing on GitHub, put the human-readable README at the repository root, not inside the skill folder.
If a skill doesn't show up in /skills after a restart, walk through this list first before debugging anything else.
For larger skills, Anthropic's canonical folder layout uses three optional subdirectories:
