How to Write a Claude Code Skill That Actually Triggers
You wrote a beautiful SKILL.md. Detailed instructions, clean formatting, solid examples. Then you asked Claude to do the exact thing your skill was supposed to handle—and it ignored the skill entirely, improvising its own approach.
I’ve built over a dozen custom skills. Most of them didn’t trigger the first time. Here’s what I learned about making them work.
What you’ll learn
- Why Claude decides to load a skill (or not)—the metadata-first architecture
- The description trick that makes skills “pushy” enough to trigger
- How to test whether your skill is actually loading
- Three patterns that work: instruction-only, script-backed, and forked subagent
How Claude decides to use your skill
Claude only sees two things before loading a skill: the name and the description in your frontmatter. That’s it. Your beautifully written instructions, your examples, your templates—Claude hasn’t read any of that yet.
If the description is vague, Claude handles the task itself and never loads the skill. This is the number one reason skills don’t trigger.
Here’s the thing most people miss: Claude defaults to NOT triggering skills. It’s confident in its own abilities. Your description needs to be specific enough that Claude thinks “this is a job for the skill, not for me.”
Bad vs. good descriptions
Bad—too vague:
name: code-helper
description: Helps with code tasks
Good—specific trigger conditions:
name: pr-review
description: >
Review pull requests for code quality, security issues,
and adherence to project conventions. Use when user mentions
'review', 'PR', 'pull request', or asks to check code changes.
The good version tells Claude exactly when to activate. It’s slightly “pushy”—and that’s intentional.
💡 List the trigger words explicitly. “Use when user mentions X, Y, or Z” is the most reliable pattern I’ve found.
The three skill patterns
Pattern 1: Instruction-only (just Markdown, no scripts)
Best for: coding standards, review checklists, writing style guides. If Claude’s language ability is enough for the task, use this.
Pattern 2: Script-backed (SKILL.md + supporting files)
Best for: tasks that need templates, reference data, or shell commands. Your skill can include files alongside SKILL.md and inject dynamic context via !\command`` syntax.
Pattern 3: Forked subagent (context: fork in frontmatter)
Best for: research tasks, deep analysis, anything that benefits from isolated context. The skill runs in a separate agent that doesn’t pollute your main conversation.
How to test if your skill is loading
Type /context in Claude Code. It shows a colored grid of what’s in the context window. If your skill loaded, you’ll see it listed. If it’s not there, your description isn’t triggering.
Another way: type /your-skill-name directly. If it’s a valid skill, Claude loads it immediately. If nothing happens, check the file path.
I got wrong at first
⚠️ 🔬 Tested: I put skills in .claude/commands/ instead of .claude/skills/. Both paths work now (they merged), but .claude/skills/ is the recommended location because it supports frontmatter features like context: fork and disable-model-invocation.
⚠️ 🔬 Tested: Skills with $ARGUMENTS placeholder must be invoked with arguments. If you call /fix-issue without a number, $ARGUMENTS stays as a literal string and Claude gets confused.
⚠️ 🔍 Searched: The Towards Data Science guide on building production skills emphasizes spending time on design before writing prompts. The description is the skill’s interface—if the interface is wrong, the implementation doesn’t matter.
What skills can’t do
❌ Skills can’t call external APIs on their own. If you need API access, combine with MCP servers.
❌ Skills don’t persist state between sessions. Each invocation starts fresh. Use memory files or Notion for cross-session state.
❌ Skills with context: fork can’t modify files in your main workspace. They run in a read-only context.
Getting started
- Create the folder:
mkdir -p .claude/skills/my-skill - Create
SKILL.mdwith frontmatter (name + description) and instructions - Test by typing
/my-skillin Claude Code - Check
/contextto verify it loaded - Iterate on the description until it triggers naturally
For reference: code.claude.com/docs/en/skills