Previously in the seriesThe Bare Minimum SetupCLAUDE.md Done RightModels, Tiers, and EffortThe Context Window TaxHooks That Guard Your CodeMCP Servers Worth AddingIntroductionSkills are one of those Claude Code features that seem straightforward until you actually try to use them consistently. The idea is simple: write a markdown file with instructions, drop it in the right directory, and Claude loads it when relevant — or you invoke it explicitly with a slash command. In practice, that "when relevant" part is where things get interesting, and not always in a good way.\This article covers how skills work, where they live, what actually controls whether they fire, and the common ways they silently fail. I'll also walk through a few patterns I find genuinely useful versus the ones that add file clutter without measurable benefit.What skills are.Skills are markdown files with YAML frontmatter that Claude Code loads into context. Each skill creates a slash command — write ~/.claude/skills/security-review/SKILL.md , and you get /security-review. You can invoke it directly, or Claude can invoke it automatically when the conversation matches the skill's description.\That dual-invocation model is what separates skills from the older .claude/commands/ approach, which was user-invoked only. The merge happened in version 2.1.3, and both locations now produce the same result. If you have existing files in .claude/commands/, they keep working — skills take precedence when there's a name conflict.\Skills live at three levels:Personal (~/.claude/skills/) — available across all your projectsProject (.claude/skills/) — committed to the repo, shared with the teamEnterprise — managed settings apply to the whole organization\When the same skill name exists at multiple levels, enterprise wins, then personal, then project. This is the opposite of what most people expect — your global skills override project-level ones, not the other way around. I'll come back to why that matters.The anatomy of a skill.Every skill needs a SKILL.md with two things: YAML frontmatter and markdown instructions.name: pr-reviewdescription: Reviews staged changes for correctness, test coverage, and consistency with project conventions. Use when the user asks for a code review or is about to open a PR.Review the current changes:1. Run `git diff --staged` to see what's changing.2. Check that every modified function has a corresponding test change.3. Flag any hardcoded values that should be environment variables.4. Confirm the commit message matches the conventional commit format used in this repo.Return findings as a short numbered list. If nothing to flag, say so explicitly.\The name field becomes the slash command. The description is what Claude reads to decide whether to load this skill automatically — it is not documentation for humans, even though it reads like it is. That distinction matters.\Supporting files are optional but useful. A skill directory can contain templates, example outputs, scripts, or reference docs:.claude/skills/pr-review/├── SKILL.md├── examples/good-review.md└── conventions.md\Reference these explicitly from SKILL.md so Claude knows they exist. Files in the directory are not loaded automatically — you have to point at them.What actually controls auto-invocation.Claude decides whether to load a skill automatically based on the description field. The description is compared against the current conversation context, and Claude makes a judgment call. This is a semantic match, not keyword matching — which sounds flexible but has a concrete downside: it is hard to predict or test.\There's a character budget for descriptions. All skill names are always loaded into context, but descriptions get truncated to fit within a dynamic cap (1% of the context window, with an 8,000-character fallback). Each individual description is capped at 250 characters regardless.\This means two things:If your description runs long, it gets cut. Front-load the use case — what task, what trigger.If you have many skills, they compete for budget. Ten mediocre skills will crowd out the important ones.\You can raise the budget with SLASH_COMMAND_TOOL_CHAR_BUDGET, but the more useful fix is writing tighter descriptions and keeping the total skill count low. This is the same pressure as the MCP server tool count — both compete for the same context budget, and they compound. A session with ten MCP tools and fifteen skills is burning budget before you've typed a prompt.\To prevent a skill from auto-invoking at all, add disable-model-invocation: true to the frontmatter. Deployment and other destructive workflows should always have this — you do not want Claude deciding on its own that now is a good time to ship.name: deploydescription: Deploy the application to productiondisable-model-invocation: truePitfallsThe precedence inversionThe priority order — enterprise > personal > project — catches people off guard. If you have a global ~/.claude/skills/deploy/SKILL.md and your team adds a project-level deploy skill with different steps for that specific repo, the project-level one loses. The global one wins.\This is the opposite of how most configuration works (project-level overrides global). The fix is to use distinct names for project-specific workflows, not to rely on override behavior that does not exist.# Don't do this — assumes project-level wins~/.claude/skills/deploy/SKILL.md # global deploy.claude/skills/deploy/SKILL.md # intended project override — will be ignored# Do this instead~/.claude/skills/deploy/SKILL.md # generic deploy scaffold.claude/skills/deploy-staging/SKILL.md # project-specific.claude/skills/deploy-prod/SKILL.md # project-specific with env contextThe silent no-match problemSkills that are supposed to auto-invoke often simply do not. The description is too vague, too long, or does not match how the conversation is actually phrased. There is no warning. Claude just does not load the skill, and unless you are watching for it, you assume the feature is broken.\Here's the failure pattern:# Too vague — Claude doesn't know when this appliesdescription: Helps with code quality and reviews# Better — specific trigger condition, specific taskdescription: Reviews staged changes for test coverage and conventional commit format. Use before opening a PR.\When a skill isn't firing, the first thing to check is not the instructions — it's the description. Test by invoking the skill directly with /skill-name to confirm the instructions themselves work, then refine the description until auto-invocation is reliable.\If you want guaranteed invocation for a workflow, add it to CLAUDE.md with a note like "Use /pr-review before every PR." That is a manual protocol, not automation, but it is reliable. Auto-invocation is convenient when it works and invisible when it does not.Context bloat from always-loaded skillsAuto-invoked skills add their instructions to the context window every time they fire. A skill that fires on every file explanation, every code review, every commit — that is, tokens consumed on every one of those tasks. In long sessions, this compounds.\The bundled /simplify skill is a good example of when this matters: it spawns three review agents in parallel, each reading files. That is intentional for a one-shot refactor pass, not for something you want loading on every question.\Be deliberate about which skills you allow to auto-invoke versus which should be explicitly called. Task skills — deployments, migrations, PR creation — should almost always use disable-model-invocation: true. Reference skills — conventions, patterns, API documentation — are reasonable candidates for auto-invocation, because their whole value is being available without you asking.\There is also an interaction with hooks worth noting: a hook that runs a formatter on every file write already adds token overhead on its own. Layer a broadly auto-invoking skill on top of that, and the per-turn cost climbs fast in active editing sessions. If you're running PostToolUse hooks, be more conservative about which skills you let auto-fire.Bundled skills worth knowing.Claude Code ships several built-in skills. These are prompt-based (not hardcoded), so they can read files, spawn agents, and adapt to your codebase:/batch — decomposes a large change into parallel units, spawns one agent per unit in an isolated git worktree, and opens a PR per unit. Requires a git repo. Useful for migrations across a codebase./simplify [focus] — spawns three parallel review agents, aggregates findings, and applies fixes. Pass a focus: /simplify focus on memory efficiency./loop [interval] — runs a prompt repeatedly on a schedule while the session is open. Useful for watching a deployment or polling an external resource./debug [description] — enables debug logging mid-session and reads the log. More useful than it sounds when a tool call is behaving unexpectedly./claude-api — loads API reference material for your project's language. Also auto-invokes when it detects an Anthropic SDK import in your code.\The distinction between bundled skills and built-in slash commands (/compact, /clear, /cost) matters: built-in commands execute fixed logic and cannot be customized. Bundled skills are prompt-based, and you can override them by creating a skill with the same name at a higher priority level.Tips & TricksKeep project skills in version control. Commit .claude/skills/ to the repo. Future team members get the workflows without onboarding steps.One skill, one job. A skill that does code review, generates a commit message, and checks coverage is worse than three focused skills. Split them.Use supporting files for long reference content. If your skill instructions reference your team's coding conventions, put the conventions in conventions.md inside the skill directory and link to it from SKILL.md. Keeps the instructions readable.Test skill instructions by invoking directly. /skill-name bypasses the description matching. If the skill works when invoked manually but not automatically, the description needs work — not the instructions.Add a skills inventory to CLAUDE.md. List available custom skills and when to use them. Claude reads it at the session start, which reinforces both auto-invocation and team awareness.SummarySkills are useful, but they require more deliberate setup than the documentation implies. Auto-invocation depends entirely on description quality, and the silent failure mode — where a skill just does not fire — takes a while to diagnose the first time you hit it. The precedence order (global beats project) will surprise almost everyone.\The pattern that works well: use project-level skills for team workflows, keep them focused and explicitly named, use disable-model-invocation: true for anything destructive, and supplement auto-invocation with a skills inventory in CLAUDE.md for the cases where reliability matters more than convenience.\In the next article, I'll cover subagents — how they differ from skills, when spawning a separate agent is worth the overhead, and why their isolation model (a fresh context window per agent, no shared history) is the right answer for the kind of verbose work that skills shouldn't be doing inline.\