Claude Code

Slash commands, and the prompt you keep retyping

Claude Code

Any prompt you have typed three times is a file waiting to exist. The modern mechanics: commands and skills are one system, invoked with a slash.

Applies to
Claude Fable 5.1 Claude Opus 5 Claude Sonnet 5 Claude Haiku 4.5
Last verified
Reviewed by
Timothy Fehr

Watch a week of your own sessions and a pattern shows up: the same review prompt before every merge, the same release checklist, the same "summarise what changed and draft the ticket update". Each retyping is a small tax, and each retyped variant drifts a little — so the fourth version of your review prompt is missing the step that mattered.

A slash command is that prompt as a file. Type /review, get the good version, every time.

The mechanics, as they are now

The system grew together with skills, and the documentation is explicit that they are one mechanism now: "A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way". The differences are additive — skills bring "a directory for supporting files, frontmatter to control whether you or Claude invokes them", and "the ability for Claude to load them automatically when relevant". One rule to know before it surprises you: when a skill and a file in .claude/commands/ share a name, the skill is the one that runs. The documentation now sets this out in a precedence table covering the enterprise, personal, project, nested, plugin and claude.ai locations as well as bundled skills, so check the table before assuming one rule covers your case.

The practical sorting: a single markdown file you invoke yourself is a command and needs nothing more. The moment it wants supporting files, or you want the model to reach for it unprompted, it is a skill, and that page covers when writing one pays.

Parameters are what make it a workflow

A command that does one fixed thing saves typing. A command that takes arguments encodes a procedure: $ARGUMENTS carries "All arguments passed when invoking the skill", so /triage 4512 can expand into the whole routine (read the issue, find the relevant code, propose a severity, draft a comment) with the issue number threaded through.

One placeholder stops being enough the moment a procedure takes two things. Declare them in frontmatter and they get names:

arguments: [issue, branch]

$issue and $branch then expand in order, which reads better in a long checklist than positional forms do. Those exist too: $ARGUMENTS[0] in full, $0 and $1 as shorthand. The two behave differently when an argument is missing, and the difference is worth knowing before it bites. A name expands to an empty string; an index with nothing at its position stays on the page as literal text.

If you pass arguments and no placeholder catches them, they are not dropped. Claude Code appends ARGUMENTS: <your input> to the end of the content so the model still sees what you typed, which is a quiet rescue for a misspelled placeholder and a reason to check the file when a command half-works.

Commands also stack. Typing /write-tests /fix-issue 123 loads both and hands 123 to each, for the first skill plus up to five more. That is the composable form of what this page is about: two stable procedures joined at the point of use, without a third file that does both.

The prompts worth this treatment are the ones this site keeps calling repeatable: the review pass, the debugging opener, the handover summary at the end of a quota window. The test for what goes in the file is the usual one: everything that was true last time and will be true next time.

Checked in, a command is team infrastructure

.claude/commands/ lives in the repository, which changes what a command is: not your shortcut but the team's procedure, versioned with the code it operates on. The new colleague's first /review runs the senior's full checklist. This is the same move as a good CLAUDE.md, knowledge out of heads and into the repo, applied to procedures instead of facts, and for a software team it is the cheapest standardisation available: one file, no meeting.

Two boundaries keep it honest. A command is still a prompt, so it inherits everything true of prompts, same words, varying outputs, and a procedure the model must never deviate from is a hook's job, not a command's. And a command file drifts like documentation drifts: the checklist references a step the build no longer has, and nobody notices, because nobody reads the file they invoke.

What goes wrong

The hardcoded argument. /deploy-staging, /deploy-prod, /deploy-that-one-weird-env: three diverging copies of what should be one file with a named argument.

The name collision you forgot. The command stopped running months ago because someone added a skill with the same name. Precedence is documented, silent, and easy to blame on the model.

The kitchen-sink command. Twelve steps, of which today's task needed three. The model dutifully performs the other nine. Costs accrue per token, and irrelevant instructions degrade the relevant ones.

Enforcement theatre. The command says "never push without tests" and usually that holds. If "usually" is not good enough, it needed a hook.

The unowned file. Team commands with no owner rot exactly like wiki pages. The fix is the same: a name in the file, and deletion on the first week it misleads someone.

How to check it worked

Pick your most-retyped prompt, make it a command, and count a fortnight: how often invoked, how often you edited the file afterwards. Invocations without edits mean it captured something stable: the drift went to zero and the fourth version is the first version. Frequent edits mean it was never a stable procedure, and a file was the wrong container for it. Both findings pay for the ten minutes.

Sources

  1. Slash commands — Claude Code documentation Tier 1 2026-09-11