Skip to content
Mastering Claude

Home / Extending: skills, MCP, subagents, hooks, plugins

Extending: skills, MCP, subagents, hooks, plugins9 minPratique

Creating a skill that is also a command

A custom command and a skill are now the same mechanism: a .claude/commands/name.md file and a .claude/skills/name/SKILL.md folder both produce the /name command with the same behaviour, and for a personal or project skill, it is the folder's name, not the frontmatter's name field, that becomes the command's name.

A custom command and a skill have become the same mechanism. A .claude/commands/deploy.md file and a .claude/skills/deploy/SKILL.md folder both produce the /deploy command, with the same behaviour at execution time: old command files keep working without any change, and the folder form is now recommended for anything beyond a simple instruction, because it can bundle supporting files alongside the text.

Where a skill lives, and how far it reaches

A personal skill lives in ~/.claude/skills/skill-name/SKILL.md and stays available across every project opened from that account. A project skill lives in .claude/skills/skill-name/SKILL.md and applies only to that specific repository, and it is that one you commit to version control to share with a team. Two other locations exist, one for a company-provided skill, the other for a skill shipped inside a plugin, each with its own priority in the event of a name shared across several sources. The choice of location is therefore made before writing, by asking who should see this command: yourself alone across every project, or a whole team on this specific repository.

Frontmatter and argument substitution

In the frontmatter, only the description field is genuinely recommended, every other one remains optional, including name. For a personal or project skill, this field only serves as a display label, without determining the command's name, which comes from the folder's name; in a plugin skill, however, name fixes the command's last segment, with the plugin's prefix staying in front. In the file's body, $ARGUMENTS receives everything the user typed after the command, as a single string; indexing is zero-based, $0 receives the first word, $1 the second, and so on, $ARGUMENTS[N] being the long form equivalent to $N; and an argument declared by its name in the frontmatter is read directly with $declared-name in the text.

# Exemple illustratif, sur un dossier de démonstration
mkdir -p demo-commande/resumer-pr
cat > demo-commande/resumer-pr/SKILL.md <<'EOF'
---
description: Resume une pull request a partir de son numero, pour preparer une revue rapide.
arguments:
  - name: numero_pr
---
Resume la pull request numero $numero_pr en trois points : ce qui change,
ce que ca casse potentiellement, ce qui reste a tester.
EOF

This merger simplifies a choice that, a few months earlier, forced a decision between two neighbouring files right from the start. It does not remove the need to choose the right location, personal or project, nor to write a description precise enough for the skill to trigger at the right moment without intervention: it is precisely this triggering mechanism, already set out in teaching Claude a workflow, that decides whether the writing work is worth anything. A command that exists but that no one thinks to type, for lack of a description that could have triggered it automatically, renders exactly the same service as if it had never been written.

Figure 1

Personal skill versus project skill

A skill's locationFile pathProjects coveredWhat is committed to version control
Personal skill~/.claude/skills/name/SKILL.mdEvery project opened from this accountStays out of the current project's repository
Project skill.claude/skills/name/SKILL.mdThis specific repository onlyCommitted to the repository to be shared with the team
Both locations produce a command in the same way, they differ in scope and in what you choose to share.
Figure 2

From typed command to substituted text

01
Call
The user types /name followed by one or more words.
02
Full string
$ARGUMENTS receives everything that follows the command, as a single string.
03
Separate words
$0 receives the first word, $1 the second, indexing being zero-based.
04
Named argument
An argument declared in the frontmatter is read by its own name in the body of the file.
Each form of substitution receives a different portion of what the user typed after the command.
Calibrate it yourself

A developer opens an old .claude/commands/deploy.md file written several months earlier in her project, types the command /deploy in a Claude Code session, and Claude applies this file's content to the letter.

Write, in one sentence, what this situation establishes, and in one sentence what it does not establish.

What to remember
  • A .claude/commands/name.md file and a .claude/skills/name/SKILL.md folder produce the same command with the same behaviour, old files keep working without conversion.
  • For a personal or project skill, the command's name comes from the folder's name, not from the frontmatter's name field, which only serves as a display label; in a plugin skill, name fixes the command's last segment.
  • A personal skill under ~/.claude/skills applies to every project on the account, a project skill under .claude/skills applies only to the repository it is committed to.
  • $ARGUMENTS receives the whole string typed after the command; word indexing starts at zero, $0 is the first word and $1 the second, and an argument named in the frontmatter is read by its own name in the body.
Do this now

Choose an action you repeat in your work, write it in a .claude/skills/mon-geste/SKILL.md file with a one-sentence frontmatter description and the body of instructions, then invoke it with /mon-geste in a session to confirm it runs.

Check the source

Every datable claim in this lesson links here to the public text behind it. A source that does not open proves nothing.