claudeplugins.
claudeplugins7 min read

Claude Skill Discoverability: Make Skills Fire When You Need Them

Concrete rules for naming and describing Claude Code skills so the agent loads them automatically instead of waiting for a slash invocation.

Claude Skill Discoverability: Make Skills Fire When You Need Them

A Claude Code skill that nobody triggers is dead weight on disk. You wrote the YAML, dropped the file in .claude/skills/, restarted the agent, and now you sit there wondering why typing "audit my SEO" produces a vanilla response instead of pulling in your 40-line seo-audit runbook. The problem is almost never the skill body. It is the name and description fields in the frontmatter, and the way Claude's skill matcher decides which skills are even candidates for a given turn.

This piece walks through how skill discovery actually works inside Claude Code, the exact frontmatter levers you control, when a skill fires automatically vs requires /skill-name invocation, and a debug loop you can run when a skill stubbornly refuses to load.

How skill discovery works under the hood

Claude Code loads every skill file as a system reminder at session start. The agent then sees an available-skills list that looks roughly like this:

- seo-audit: When the user wants to audit existing SEO issues on a staging
  subdomain. Also trigger on "SEO audit", "technical SEO", "why am I not
  ranking", "page speed", "core web vitals", "crawl errors".
- copywriting: When the user wants to write or rewrite marketing copy
  for a landing page, hero section, CTA, or value proposition.

That list is the entire input the model uses to decide whether to invoke a skill on a given turn. It does not read your skill body until it decides to invoke. Three implications follow:

  1. The description field is your matcher. The skill body is your payload.
  2. Skills compete for attention. A vague description loses every time to a specific one.
  3. Adding more skills makes every existing skill harder to discover, because the matcher has more noise to sort through.

This is the opposite of how most engineers approach it. People treat the description as documentation for humans browsing the skill directory. It is not. It is the prompt the matcher reads.

The frontmatter contract: name and description

A Claude Code skill file starts with YAML frontmatter:

---
name: seo-audit
description: When the user wants to audit existing SEO issues on a staging
  subdomain. Also trigger on "SEO audit", "technical SEO", "why am I not
  ranking", "on-page SEO", "meta tags review", "SEO health check",
  "page speed", "core web vitals", "crawl errors", "indexing issues".
---

# Body content here...

Two fields, two jobs.

The name field

This is what the user types after the slash. name: seo-audit becomes /seo-audit. Constraints:

  • Kebab-case, lowercase, no spaces
  • Globally unique across user-scope and project-scope skills
  • Stable across versions \u2014 renaming breaks muscle memory and any saved keybindings

If your skill ships as part of a plugin, the resolved name becomes plugin-name:skill-name when there's a namespace collision. Avoid relying on plugin prefixes for disambiguation in user-facing docs; pick a name that is unambiguous on its own.

The description field

This is the matcher prompt. Anatomy of a good description:

  1. A primary use clause \u2014 "When the user wants to X" or "Use when X is needed"
  2. Trigger phrases in quotes \u2014 exact strings or close paraphrases the user might type
  3. Disambiguation against sibling skills \u2014 "For Y, see other-skill" when overlap is real
  4. Scope boundaries \u2014 what this skill does NOT do, when the boundary is non-obvious

A weak description:

description: "Helps with SEO."

A strong description:

description: When the user wants to audit, review, or diagnose SEO issues
  on a staging subdomain. Also trigger on "SEO audit", "technical SEO",
  "why am I not ranking", "on-page SEO", "meta tags review", "SEO health
  check", "traffic dropped", "lost rankings", "not showing up in Google",
  "page speed", "core web vitals", "crawl errors", "indexing issues". Use
  this even if the request is vague ("my SEO is bad"). For building pages
  at scale, see programmatic-seo. For JSON-LD structured data, see
  schema-markup.

The weak version matches roughly nothing because every other vaguely-SEO-shaped skill description matches better. The strong version anchors on at least eight specific phrases the user might actually type, calls out the vague-request case explicitly, and prevents collision with two adjacent skills.

Auto-fire vs explicit invocation

Skills fire in two distinct modes. Knowing which mode you are designing for changes how you write the description.

Auto-fire mode

The model reads the user turn, scans the skill list, and decides on its own to invoke a skill via the Skill tool. This happens when:

  • The user phrasing closely matches a trigger phrase in the description
  • The work being requested clearly maps to a skill's primary use clause
  • No competing skill is a better match

Auto-fire is what you want for high-frequency, predictable workflows. SEO audits, code reviews, schema generation \u2014 anything where the user describes a goal instead of typing a command.

To maximize auto-fire reliability:

  • Frontload trigger phrases the user is likely to type, not phrases an expert would use
  • Include vague variants ("my SEO is bad") explicitly
  • Cover synonyms across user skill levels \u2014 "ranking" and "showing up in Google" both belong in an SEO audit description
  • Keep the description tight at 200-400 characters. Beyond that, the matcher signal dilutes.

Explicit invocation mode

The user types /skill-name directly. The matcher is bypassed entirely. The skill loads no matter how vague or generic its description is.

This is the right design for:

  • Destructive operations where auto-fire would surprise the user
  • Skills that need explicit input arguments (/loop 5m /audit)
  • Maintenance tooling the user invokes deliberately
  • Skills that are too domain-specific to risk false positives

If a skill is explicit-invocation-only, you can keep the description short and use it purely as documentation. There is no matcher win to chase.

Discoverability anti-patterns

Three patterns kill discoverability faster than anything else.

Description-as-documentation. Writing "This skill helps you audit SEO. It checks meta tags, sitemap, structured data..." reads like documentation. The matcher sees a featureless paragraph. Rewrite as trigger-phrase-dense.

Name collisions with built-in commands. Naming a skill init competes with Claude Code's built-in /init. The disambiguation rules favor the built-in. Pick a unique name like project-init or bootstrap-monorepo.

Generic catch-all skills. A skill named code-helper with description "helps with code" will steal triggers from every more-specific skill in the directory. The agent has no way to know your code-helper doesn't handle Rust, so it will try. Make skills narrow and name them after the narrow scope.

Debug loop when a skill won't fire

When you expect auto-fire and get nothing, run this sequence:

  1. Verify the skill loaded. Type /skill-name directly. If it works, the skill file is parsed correctly and the matcher is the issue. If it fails, the YAML is broken or the file is in the wrong path.
  2. Check the description for the exact trigger phrase. Use the user's literal words. If they typed "audit my SEO" and your description only contains "SEO audit", the bigram order may not match strongly enough.
  3. Check for sibling competition. List all skills with overlapping vocabulary. If seo-audit and seo-technical both match "Core Web Vitals", one will win and the other will starve. Make the boundary explicit in both descriptions.
  4. Reduce skill count temporarily. Disable half your skills and retry. If discovery suddenly works, you have a matcher-noise problem and need tighter descriptions globally.

The Claude Code docs at https://docs.claude.com/en/docs/claude-code/skills.md cover the file format and lifecycle in depth, and the upstream skills repository at https://github.com/anthropics/claude-code-cookbook has reference examples worth grepping for matcher patterns.

A workable checklist before you ship a skill

  • Name is kebab-case, unique, and stable
  • Description leads with "When the user wants to..." or "Use when..."
  • 5-15 specific trigger phrases in quotes
  • Sibling-skill disambiguation called out explicitly
  • Vague-request case covered with a literal example
  • Total description length under 500 characters
  • You tested the skill via at least three different user phrasings, not just the obvious one

Discoverability is a one-time cost paid in the description field. Spend an extra ten minutes there and the skill earns its keep for months. Skip it and the skill sits in the directory like a CLI tool nobody remembers the name of.

References: