Home / Extending: skills, MCP, subagents, hooks, plugins
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.
Personal skill versus project skill
| A skill's location | File path | Projects covered | What is committed to version control |
|---|---|---|---|
| Personal skill | ~/.claude/skills/name/SKILL.md | Every project opened from this account | Stays out of the current project's repository |
| Project skill | .claude/skills/name/SKILL.md | This specific repository only | Committed to the repository to be shared with the team |
From typed command to substituted text
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 this establishes: This result establishes that the old .claude/commands file-based command mechanism keeps working on an existing file, even long after it was written.
What this does not establish: It does not establish which location to choose for a command written today, since only the working of an already-existing file was observed.
The three most common miscalibrations
- Too broad This result shows that the old command mechanism remains the recommended form for writing a new automation today.
- Too narrow This result proves nothing since only a single command was tested on a single project.
- Off the mark This result shows that the developer knew the exact content of the file before typing the command.
- 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.
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.
Every datable claim in this lesson links here to the public text behind it. A source that does not open proves nothing.
- Claude Code, skills, zero-based argument indexing and command name by scope consultée le 2026-09-02