Skills Are Just Markdown Files and That's What Makes Them Powerful
When most developers hear "extend an AI coding assistant," they reach for familiar concepts. An SDK. An API layer. A build pipeline. This is the same instinct that leads people to over-invest in prompt engineering when context engineering is what matters. Maybe a plugin system with lifecycle hooks, configuration schemas, and a deployment target. That is how every tool ecosystem has worked for the last twenty years.
Claude Code skills are none of that.
A skill is a markdown file. You describe what the skill does, how it should route arguments, what tools it can use, and Claude follows the instructions. No compilation. No dependencies. No deployment. No runtime. You write a .md file, drop it in a directory, and it works.
I've been building and using skills daily for months. I have skills for tracking calories, automating grocery lists, and planning dates, generating logos, building presentations, and designing frontend interfaces. Every single one of them is a markdown file with instructions. The fact that this sounds too simple to work is exactly the point.
What a Skill Actually Is
A skill is a .md file -- typically named SKILL.md -- that lives inside a directory under ~/.claude/skills/. The directory name is the skill's identity. The markdown file is its brain. When you invoke a skill from Claude Code using a slash command like /calorie-tracker log 2 eggs and toast, Claude reads that file and follows the instructions inside it.
That is the entire mechanism. There is no skill runner. There is no skill SDK. There is no compilation step that transforms your markdown into something executable. Claude reads your file the same way it reads a CLAUDE.md or any other markdown document -- as natural language instructions that it follows.
The directory structure looks like this:
~/.claude/skills/
calorie-tracker/
SKILL.md
logo-generator/
SKILL.md
presentation-chef/
SKILL.md
superdesign/
SKILL.md
Each directory is a skill. Each SKILL.md defines what that skill does. When you type /calorie-tracker in a Claude Code session, Claude finds the matching directory, reads the SKILL.md, and executes accordingly.
If you have used CLAUDE.md files to give Claude project-level instructions, you already understand the concept. Skills are the same idea -- markdown instructions that shape Claude's behavior -- but scoped to a specific capability that you invoke on demand rather than loading automatically.
The Anatomy of a SKILL.md
A SKILL.md has two parts: YAML frontmatter and a markdown body.
The frontmatter is metadata. It tells Claude when and how to use the skill:
---
name: calorie-tracker
description: Track daily food intake and nutrition using the FatSecret API
argument-hint: [log <food> | summary | trends | undo]
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
---
The body is the actual instruction set. It tells Claude how to execute the skill:
# Calorie Tracker
You are a nutrition tracking assistant. When invoked, parse
the user's arguments and execute the matching workflow.
## Argument Routing
| Pattern | Workflow |
|---------|----------|
| `log <food description>` | Log food workflow |
| `summary` | Daily summary workflow |
| `trends` | Weekly trends workflow |
| `undo` | Undo last entry |
## Workflows
### Log Food
1. Parse the food description from $ARGUMENTS
2. Query the FatSecret API for nutritional data
3. Present the top matches to the user for confirmation
4. Write the confirmed entry to the SQLite database
5. Show updated daily totals
### Daily Summary
1. Read today's entries from the database
2. Calculate totals for calories, protein, carbs, fat
3. Compare against daily targets
4. Display a formatted summary table
...The frontmatter tells Claude WHEN to use the skill. The body tells Claude HOW. The separation is clean and intentional.
Let me walk through each frontmatter field because they matter more than they look.
name is the identifier. It matches the directory name and determines the slash command.
description is Claude's decision trigger. When you invoke a skill, Claude reads this to confirm it's the right one. Write it like a one-line job description. Be specific about what the skill does and when it should be used.
argument-hint shows the user what subcommands are available. When you type /calorie-tracker without arguments, Claude can reference this to suggest options. The square brackets and pipes follow the standard CLI convention for optional and alternative arguments.
allowed-tools is the security boundary. This one deserves its own section.
Allowed Tools: The Security Boundary
The allowed-tools field in the frontmatter controls which Claude Code tools the skill can use. This is not a suggestion. It is a constraint. If a skill's allowed-tools list includes only Read, Glob, Grep, that skill cannot edit files, cannot run bash commands, cannot write anything. It can only look.
This matters for two reasons.
First, it is a security mechanism. When you build a skill that does research -- reading files, searching patterns, summarizing codebases -- you can restrict it to read-only tools. Even if the instructions accidentally imply that Claude should edit something, the tool restriction prevents it. The restriction is enforced at a level below the natural language instructions. You cannot "prompt your way out" of a tool restriction.
Second, it forces design discipline. When you sit down to write a skill and you have to declare upfront which tools it needs, you think more carefully about what the skill actually does. A skill that needs Bash access is fundamentally different from one that only needs Read and Grep. The tool list makes that distinction explicit.
Here are some patterns I use:
- Read-only research skills:
Read, Glob, Grep-- can explore the codebase but cannot modify anything - File generation skills:
Read, Write, Glob, Grep-- can create new files but cannot run arbitrary commands - Full automation skills:
Bash, Read, Write, Edit, Glob, Grep-- full access, for skills that need to run scripts, call APIs, and manage files - Presentation and design skills:
Bash, Read, Write, Glob, Grep, WebFetch-- needs web access for fetching assets or guidelines
The principle is least privilege. Give each skill the minimum set of tools it needs and nothing more. A calorie tracking skill needs Bash to call APIs and Read/Write to manage the database. It does not need Edit or Glob. A logo generator needs Write to create SVG files and Bash to run export scripts. Scope it accordingly.
Argument Routing: One Skill, Multiple Workflows
The $ARGUMENTS variable is where skills get interesting. When you type /calorie-tracker log 2 eggs and toast, the string log 2 eggs and toast becomes $ARGUMENTS. The skill's routing table maps that input to a specific workflow.
This is what lets a single skill handle multiple subcommands:
## Argument Routing
| Pattern | Workflow |
|---------|----------|
| `log <food description>` | Log the described food |
| `summary` | Show today's nutrition totals |
| `summary <date>` | Show totals for a specific date |
| `trends` | Show weekly calorie trends |
| `trends <nutrient>` | Show weekly trends for a specific nutrient |
| `undo` | Remove the last logged entry |
| `goal set <calories>` | Set daily calorie target |Each row is a pattern-to-workflow mapping. Claude reads the arguments, matches them against the patterns, and executes the corresponding workflow. The matching is natural language pattern matching, not regex. Claude understands that log a banana and peanut butter matches the log <food description> pattern without you needing to write a parser.
This is one of those things that sounds fragile but works remarkably well in practice. Claude is very good at understanding intent from natural language patterns. I have never had a routing mismatch with a well-written routing table. The key is making your patterns distinct enough that there is no ambiguity. If log and lookup are both options, Claude will never confuse them.
Some of my skills have routing tables with eight or ten entries. They work fine. The routing table is documentation as much as it is configuration. When you come back to a skill months later, the table tells you everything it can do at a glance.
My Coding Skills: A Tour
I have built a collection of skills that I use regularly for development work. Each one started as a specific problem I kept solving manually and decided to automate. Here is a quick tour.
superdesign
This is my design-first development skill. When I invoke it before building a UI feature, it forces a design thinking phase before any code gets written. It fetches design guidelines, considers the user experience, thinks about information hierarchy and interaction patterns, and then runs a design CLI to generate structured design specs.
The key insight behind this skill is that Claude, left to its defaults, will jump straight to code. It will write a React component that technically works but looks like every other AI-generated interface. Superdesign inserts a deliberate pause. Think about the design first. Then implement.
frontend-design
This skill generates distinctive, production-grade frontend interfaces. The instruction file is explicit about avoiding generic AI aesthetics -- the cookie-cutter layouts with rounded cards and blue gradients that every AI tool produces by default.
The SKILL.md contains specific rules about typography choices, spacing ratios, color theory, and visual hierarchy. It knows when to use whitespace aggressively and when density is appropriate. It references real design systems and established visual patterns rather than inventing generic ones.
premium-web-animations
Different animation libraries have different strengths, and picking the wrong one for your use case wastes hours. This skill knows the landscape. Theatre.js for timeline-based cinematic sequences. Anime.js for lightweight element animations. GSAP for complex, performance-critical animation choreography. CSS scroll-driven animations for scroll-linked effects that do not need JavaScript.
The skill evaluates the animation requirement, recommends the right library, and generates implementation code that follows each library's best practices. It also knows the performance implications. It will not suggest a heavy JavaScript animation library for something CSS can handle natively.
logo-generator
This one surprised me with how useful it became. You invoke it in a project directory, and it scans for context: README files, package.json, existing CSS files with color variables, any existing brand assets. Then it brainstorms logo concepts based on the project's identity, generates SVG logos, and exports a full brand kit -- favicons at multiple sizes, social media images, dark and light variants.
The context scanning is the valuable part. Instead of generating a generic logo, it grounds the design in what the project actually is. A developer tools project gets a different aesthetic than a consumer app. A data visualization library gets a different treatment than a personal blog.
presentation-chef
Converts any content into cinematic HTML presentations. Think Apple Keynote aesthetics -- glassmorphism, smooth transitions, calculated typography -- but as a single self-contained HTML file that you can open in any browser.
I use this constantly. When I need to present something, whether it is a project demo, a technical talk, or a team update, I feed the content to presentation-chef and get a polished slide deck in minutes. The output is a single .html file with all styles and animations inlined. No dependencies. No build step. Just open it in a browser.
theme-factory
A companion to presentation-chef and other visual skills. Theme-factory has ten pre-set themes with curated color palettes, font pairings, and spacing systems. You can apply a theme to slides, documents, reports, or landing pages. Instead of making design decisions every time you build something visual, you pick a theme and the skill handles consistency.
Each theme is opinionated. They are not generic "blue theme" or "dark theme" labels. They have specific character -- one is brutalist, another is editorial, another is warm and organic. The skill applies the theme's design tokens throughout whatever it is building.
Writing Your First Skill
Here is how to build a skill from scratch. I will walk through a practical example: a skill that generates structured project README files.
Step 1: Create the directory.
mkdir -p ~/.claude/skills/readme-generatorStep 2: Create the SKILL.md file.
touch ~/.claude/skills/readme-generator/SKILL.mdStep 3: Write the frontmatter.
---
name: readme-generator
description: Generate a comprehensive README.md by analyzing the project structure, dependencies, and code
argument-hint: [generate | update | section <name>]
allowed-tools: Read, Write, Glob, Grep
---
Notice the tool selection. This skill needs to read the codebase and write a README file. It does not need Bash because it is not running any commands. It does not need Edit because it is generating a new file, not modifying existing code.
Step 4: Write the instructions.
This is where the actual skill lives. Write the body as if you are onboarding a smart junior developer who has never seen the project and needs to produce a high-quality README.
# README Generator
Generate comprehensive, accurate README files by analyzing
the actual project, not by guessing.
## Argument Routing
| Pattern | Workflow |
|---------|----------|
| `generate` | Full README generation |
| `update` | Update existing README with current state |
| `section <name>` | Generate or update a specific section |
## Full README Generation Workflow
1. **Scan the project structure.** Use Glob to map the directory
tree. Identify the primary language, framework, and build system.
2. **Read key files.** Check package.json, pyproject.toml,
Cargo.toml, or equivalent for dependencies and scripts.
Read any existing README for context to preserve.
3. **Analyze the codebase.** Use Grep to find entry points,
exported modules, CLI commands, and API endpoints.
4. **Generate sections in this order:**
- Project title and one-line description
- What the project does (2-3 sentences, not marketing copy)
- Prerequisites and installation
- Usage with real examples from the actual code
- Project structure (top-level directories only)
- Configuration options (if any)
- Contributing guidelines (if applicable)
5. **Write the file.** Output as README.md in the project root.
## Rules
- Never invent features. Only document what exists in the code.
- Use actual command names from package.json scripts, not generic
placeholders.
- Keep it under 200 lines. Longer READMEs don't get read.
- No badges unless the project already uses them.
- No "Table of Contents" for READMEs under 150 lines.Step 5: Use it.
Open Claude Code in any project directory and type:
/readme-generator generate
Claude reads the SKILL.md, scans your project, and generates a README based on what it actually finds in the code. Not a template. Not a generic boilerplate. A README grounded in your actual project.
The key to writing good skill instructions is specificity. Vague instructions produce vague results. "Generate a good README" is useless. "Scan package.json for scripts, use actual command names, keep it under 200 lines" is actionable. Every line in your SKILL.md should either constrain the output or direct a specific action.
One more tip: include a Rules section. Claude follows explicit rules reliably. Rules like "never invent features" and "no badges unless the project already uses them" prevent the most common failure modes. Without those rules, Claude will occasionally hallucinate a feature or add a wall of badges to a personal project that has no CI pipeline.
Why Markdown Works
There is a deeper question here. Why does this work at all? Why can a markdown file with natural language instructions serve as a reliable skill definition?
The answer is that markdown is the native language of LLMs. Not Python. Not YAML schemas. Not JSON configuration files. Markdown.
Claude was trained on massive amounts of markdown documentation, tutorials, specifications, and instruction sets. When it reads a SKILL.md file, it is reading text in the exact format it understands best. There is no impedance mismatch between how you write instructions and how Claude processes them. No serialization layer. No parsing step. No schema validation that might reject valid instructions because they do not match a type definition.
Compare this to how traditional plugin systems work. You write code in a specific language. You conform to an interface. You handle lifecycle methods. You register your plugin with a runtime. You debug serialization issues when your plugin's output does not match the expected schema. You version your plugin against the host application's API. When the host updates, your plugin might break.
Skills have none of these problems. There is no API to version against. There is no runtime to register with. There is no interface to conform to. If Claude understands natural language, and it does, then it understands your skill.
This also means skills are trivially portable. A skill I write works on any machine with Claude Code installed. There is no "works on my machine" problem because there is nothing machine-specific about a markdown file. Copy the directory, and the skill works identically.
It means skills are trivially inspectable. You do not need to decompile anything or trace through abstraction layers to understand what a skill does. Open the SKILL.md. Read it. It says what it does in plain language. The documentation is the implementation. They are the same file.
And it means skills are trivially modifiable. Want to change how a skill works? Edit the markdown. There is no rebuild. No recompile. No restart. The next time you invoke the skill, Claude reads the updated file and follows the new instructions. The iteration cycle is as fast as saving a file.
Tips From Building Eighteen Skills
I have built eighteen skills over the past few months. Some work beautifully. Some went through multiple rewrites before they worked well. Here is what I have learned.
Be prescriptive about output format. If you want a skill to produce a specific kind of output -- a formatted table, a file in a specific location, a summary with specific sections -- spell it out. Claude will follow formatting instructions precisely. If you leave the format open, you will get inconsistent results across invocations.
Include negative rules. "Do not" instructions are some of the most valuable lines in a SKILL.md. "Do not add placeholder content." "Do not suggest changes outside the scope of this skill." "Do not ask clarifying questions when the input is unambiguous." These prevent the most common failure modes and keep the skill focused.
Keep workflows numbered. When a workflow has multiple steps, number them. Claude follows numbered steps more reliably than paragraph-form instructions. Each step should be one action. If you find yourself writing a step that includes "and then also," break it into two steps.
Test with edge cases early. After writing a skill, invoke it with the simplest possible input, the most complex input, and something slightly ambiguous. The simple case validates the basic flow. The complex case validates that the routing and logic handle real-world inputs. The ambiguous case shows you where the instructions need tightening.
Version your skills with git. Your ~/.claude/skills/ directory should be version controlled. You can see my full skills directory structure in my exact setup walkthrough. These files represent accumulated knowledge about how to automate your workflows. Losing them would be like losing your dotfiles. I keep mine in a private repo that I sync across machines.
Start narrow, then expand. My calorie tracker started as a single-workflow skill that logged food. That was it. Once that worked reliably, I added the summary workflow. Then trends. Then undo. Each addition was small and testable. Skills that try to do everything from day one usually do nothing well.
The Simplest Architecture That Could Possibly Work
There is an engineering principle I keep coming back to: the simplest architecture that could possibly work is usually the best one. Skills embody this.
No SDK means no dependency management. No build step means no build failures. No runtime means no runtime errors. No deployment means no deployment pipeline. No versioning scheme means no version conflicts. The entire system is: write a file, read the file, follow the instructions.
Could you build a more sophisticated skill system? Of course. You could add schema validation, typed arguments, middleware chains, dependency injection, and all the other machinery that makes traditional plugin systems "robust." And every piece of that machinery would add complexity, add failure modes, add things to learn, add reasons why someone's skill does not work on their machine.
Or you could write a markdown file and have it work everywhere, immediately, with no setup.
I know which one I prefer.
Skills are markdown files, and that is exactly why they work. No build step means no friction. No SDK means no lock-in. No runtime means no runtime failures. You write what you want Claude to do, in plain language, in the format Claude understands best. And it does it.
If you have been thinking about building a skill but have not started because it seemed like it would be complicated -- it is not. Create a directory. Write a SKILL.md. Describe what you want. The barrier to entry is the ability to write clear instructions. Everything else is already handled.
Start with something small. A skill that generates a specific kind of file you create often. A skill that runs a workflow you repeat weekly. A skill that automates the most tedious part of your development process. Write the instructions, invoke the skill, and iterate on the instructions until the output is right.
That is it. That is the whole system. And that simplicity is the feature.
Related Posts
Custom Commands and Slash Commands: Building Your Own Claude Code CLI
Slash commands turn Claude Code into a personalized CLI. A markdown file becomes a reusable workflow you invoke with a single slash. Here's how to build them.
NotebookLM from the Terminal: Querying Your Docs with Claude Code
A Claude Code skill that queries Google NotebookLM notebooks directly from the terminal. Source-grounded answers from Gemini, with citations, without opening a browser.
Plan Mode, Context Windows, and Not Wasting Tokens
The 200k context window is your most valuable resource in Claude Code. Here's how to manage it, why plan mode is the most important habit, and what happens when you run out.