knack
← all posts

How to Use Claude Skills: A Walkthrough for Claude Code, Claude.ai, and Claude Desktop

Where skills live on disk, how Claude discovers them, the difference between the three surfaces, and the troubleshooting playbook when one won't load.

The most underrated thing about Claude Skills is the part nobody explains in the install instructions. You almost never type the skill's name. Claude reads the description field in the YAML frontmatter at session start, decides it's relevant to whatever you just asked, and loads the rest of the file on its own. You ask "what did I change?" and a summarize-changes skill fires because the description says "Use when the user asks what changed." No slash, no menu, no ceremony.

That auto-discovery model is also where new users get stuck. They install a skill, type the request they had in mind, nothing visibly happens, so they assume the install failed. Usually the skill loaded fine and Claude decided your phrasing didn't match. The fix is in the description, not the install.

This walkthrough covers the three surfaces where Skills work today, in order of how much control you have: Claude Code, Claude Desktop (which shares the same on-disk model), and Claude.ai on the web. I'll show you the exact paths, the frontmatter fields, the slash command syntax, and the four mistakes behind most "my skill isn't triggering" threads.

What a skill actually is

A skill is a folder. Inside it, a file called SKILL.md with YAML frontmatter on top and markdown instructions below. Optional siblings: scripts, templates, reference docs, examples. That's it. The format is the Agent Skills open standard, which Anthropic, Codex, and a growing list of other tools have adopted. The canonical reference for Claude Code lives at code.claude.com/docs/en/skills.

The only code block in this article, frontmatter showing the four fields you'll actually touch (drawn from Anthropic's documentation):

---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---

Two fields do most of the work. name becomes the slash command (/deploy). description is what Claude reads to decide whether your current request matches. Everything else is opt-in.

How discovery actually works

When you open Claude Code, it walks every configured skills directory, reads only the frontmatter of each SKILL.md, and packs name plus description into a listing in the system prompt. The body stays on disk. Anthropic calls this progressive disclosure, and the rationale sits on the platform docs overview page: metadata costs about 100 tokens per skill, instructions stay under 5k tokens and load only when triggered, and bundled scripts or reference files load on demand when Claude reads them via Bash.

The practical model is this. Claude sees a one-line summary of every installed skill. If your prompt fits the summary, Claude pulls in the full SKILL.md and follows the instructions. If it doesn't fit, the skill stays dormant and costs you almost nothing.

This is why the description field is load-bearing in a way the docs underplay. Bad description, your skill is dead weight. Good description with the trigger phrases a real user would type, your skill fires without you ever invoking it by name. The Anthropic docs are explicit: put the key use case first, because the combined description and when_to_use text gets truncated at 1,536 characters in the listing.

To force a skill to run regardless of phrasing, type /skill-name and it fires unconditionally.

Claude Code: the canonical surface

Claude Code is where Skills are most fully implemented and most worth learning. Everything else borrows from this model.

Where skills live on disk

Four locations, in precedence order. Enterprise managed settings override personal, personal overrides project, plugins live in their own namespace.

The personal location is ~/.claude/skills/<skill-name>/SKILL.md. On Windows that's C:\Users\<you>\.claude\skills\<skill-name>\SKILL.md. Anything you drop there is available across every project on the machine.

The project location is .claude/skills/<skill-name>/SKILL.md, sitting at the root of your repo. Commit it to git and your whole team gets the same skills the next time they pull. Claude Code walks parent directories from your starting point up to the repo root, and on demand it picks up nested .claude/skills/ folders in subdirectories you touch. That's the design that makes monorepos work.

Plugin skills sit inside a plugin folder and get namespaced as plugin-name:skill-name, so they cannot collide with personal or project skills of the same name. You install plugins through Claude Code's /plugin command. Anthropic's official skills repo is itself installable via /plugin marketplace add anthropics/skills.

The one place Knack shows up in this article: knack pull <slug> writes a SKILL.md folder into one of these locations (project by default, personal with --global), and the result is indistinguishable from a skill you wrote yourself.

Letting Claude invoke a skill

Just talk normally. If your skill's description says "Use when the user asks what changed, wants a commit message, or asks to review their diff," then typing "what did I change?" is enough. Claude reads the listing, matches the intent, and loads the skill.

Two signs it worked. The response is grounded in real data your skill produced (often via !`<command>` shell injection in the skill body) rather than generic guessing, and asking Claude "what skills did you use just now?" surfaces the name.

Explicit invocation with slash commands

Type / and a menu appears with every user-invocable skill on your machine, filtered as you type. Hit Enter and the skill fires.

Arguments are positional and live in $ARGUMENTS. A skill named fix-issue with Fix GitHub issue $ARGUMENTS following our coding standards. in its body, invoked as /fix-issue 1247, expands to Fix GitHub issue 1247 following our coding standards. Claude runs from there. For multiple positional args, use $ARGUMENTS[0], $ARGUMENTS[1], or the shorthand $0, $1. Quote multi-word values: /migrate "old auth" new-auth.

If your skill body never references $ARGUMENTS and you pass them anyway, Claude Code appends ARGUMENTS: <your input> to the bottom of the rendered skill so the values stay visible. Workable as a fallback, but structure the prompt around the args if you care how they get used.

The two invocation-control flags

disable-model-invocation: true means Claude won't auto-trigger this skill from a description match. Only you can fire it, by typing the slash command. Use this for anything with side effects you want to time yourself: /commit, /deploy, /send-slack-message. You don't want Claude deciding the diff looks ready and shipping it.

user-invocable: false is the inverse. Claude can load the skill when relevant, but it won't appear in your / menu. Use this for background knowledge that isn't a meaningful action, like a legacy-system-context skill that explains how an old internal service works. Claude should know it exists. You wouldn't type /legacy-system-context at it.

The flags compose. A skill with both set is invisible to everyone, which is rarely what you want.

Claude Desktop and the shared filesystem

Claude Desktop reads skills from the same ~/.claude/skills/ directory as Claude Code. Anything you've installed for the CLI is available in Desktop without copying or re-uploading. The invocation surface is conversational rather than command-line, but the discovery model is identical: frontmatter loads at session start, Claude matches your request against descriptions, and pulls in the full body when relevant.

Slash commands work the same way in Desktop's input box. Type /, pick from the menu, fire the skill. If you maintain both surfaces, treat the personal skills folder as your source of truth and let both apps share it.

Claude.ai on the web

This is the surface where the model differs most, and where the most documentation confusion lives. As of May 2026, custom Skills on claude.ai are uploaded as zip files through Settings, under Features, on Pro, Max, Team, and Enterprise plans with code execution enabled. The reference sits at platform.claude.com/docs/en/agents-and-tools/agent-skills/overview, and Anthropic's skills explainer blog post covers the user-facing version.

Three things to know that bite people.

First, custom skills on claude.ai are per-user. No organization-wide rollout, no centralized admin distribution, no shared workspace. If you and three teammates all want the same skill, all four of you upload it.

Second, custom skills do not sync across surfaces. A skill uploaded to claude.ai is invisible to the API, to Claude Code, and to Claude Desktop unless you also place it in ~/.claude/skills/. The standard is shared. The hosting is not.

Third, auto-discovery still applies. Claude reads the description, decides relevance, and triggers the skill when your prompt matches. You don't pick a skill from a dropdown mid-conversation. The closest thing to manual selection is uploading the skill in the first place.

To add one, open Settings, go to Features, find Skills, click Upload, point it at a zip of your skill folder. The zip should contain the skill directory itself, with SKILL.md at its root, plus any supporting files. Once it's uploaded, start a new conversation and ask for whatever your description says to trigger on.

Pre-built skills for PowerPoint, Excel, Word, and PDF are already on claude.ai and don't require setup. They fire when you ask Claude to create or edit one of those file types.

Troubleshooting the four mistakes

Most "my skill isn't working" reports trace back to one of these.

The first is a description that doesn't match how users phrase requests. If your description says "Performs codebase analysis and quality assessment," nobody is typing those words. They're typing "review my code" or "is this any good?" Write the description with the trigger phrases your real users would say, ideally including a "Use when the user asks..." clause that lists three or four common ways to ask. Anthropic's own example for summarize-changes does this well.

The second is YAML frontmatter that won't parse. The --- delimiters need to be the first thing in the file and on lines by themselves. Field names are lowercase with hyphens, not underscores. disable-model-invocation, not disable_model_invocation. Run /skills inside Claude Code to see what actually loaded. If a skill you installed never appears in that list, the parser dropped it silently. /doctor is the broader configuration-health check and will surface schema errors in your settings files.

The third is description budget overflow. Claude Code allocates roughly 1% of the model's context window to the combined skill listing. Install thirty skills with 800-character descriptions and the listing overflows, descriptions get truncated, and the keywords Claude needs to match your request get cut off. The fix is to raise the budget with skillListingBudgetFraction, mark low-priority skills as "name-only" in skillOverrides, or trim the descriptions. /doctor shows you whether you're overflowing.

The fourth is forgetting that skills are scope-sensitive. A skill in .claude/skills/ only loads when you launch Claude Code from inside that repo (or a parent of it). A skill in ~/.claude/skills/ loads everywhere. If you're staring at an empty / menu in a project where you swore you installed a skill, check whether the install was personal or project scope, and check which directory you're running from.

A bonus fifth, less a mistake than a property worth knowing: once a skill loads into a conversation, its body stays in context across turns. Claude Code does not re-read the file on subsequent messages. Edit the SKILL.md mid-session and the change takes effect on the next invocation, not the current one. For experimental authoring this is occasionally surprising. For day-to-day use it is exactly what you want.

What to do next

The obvious next question is how to write your own. That's covered in the no-code build walkthrough. If you want to see what good looks like before you write, fifteen real skills walked through is the companion.