Intermediate · 18 min read · updated 2026-07-14

Claude Code Slash Commands: Build Your Own in 2026

A practical guide to writing custom Claude Code slash commands that turn repeated prompts into one-word, shareable team commands.

Claude CodeSlash CommandsDeveloper ToolsAutomationAI Coding
Who this is for: developers already using Claude Code who keep retyping the same three-paragraph prompt every morning ("review this diff for security issues, check the tests, then summarize in Hebrew") and want it to become /review.

Claude Code slash commands turn a prompt you'd otherwise paste by hand into a single typed word. They live as plain Markdown files in .claude/commands/, they take arguments, and they're just as easy to commit to git as any other project file — which means your whole team gets the same commands the moment they pull the repo. This guide covers the file format, arguments, the difference between a command and a skill, and how to ship commands across a team without them rotting.

What a slash command actually is

A slash command is a .md file. That's the whole mechanism. Claude Code scans two directories:

  • .claude/commands/ — project-scoped, committed to git, shared with the team
  • ~/.claude/commands/ — personal, global across every project on your machine

Drop a file named deploy-check.md into .claude/commands/ and typing /deploy-check in any session in that repo injects the file's contents as your prompt. No build step, no registration, no plugin system. The frontmatter is optional — a bare Markdown file with just prose works fine, but you lose the metadata that makes commands discoverable and safe.

---
description: Run the pre-deploy checklist against the current branch
allowed-tools: Bash(npm run *), Bash(git status), Read
---

Run `npm run build` and `npm test`. Then check `git status` for
uncommitted files. Summarize pass/fail for each step and flag
anything that would block a deploy.

description shows up in the / autocomplete menu. allowed-tools scopes what the command is permitted to invoke without a permission prompt — worth setting deliberately rather than leaving wide open, especially for commands you plan to share.

Arguments: $ARGUMENTS and positional $1, $2

Commands accept input two ways.

$ARGUMENTS captures everything typed after the command name as one string:

---
description: Investigate a bug report end to end
---

Investigate this bug: $ARGUMENTS

Reproduce it first, then find the root cause before touching any code.

Typing /investigate the login button does nothing on Safari substitutes that whole phrase for $ARGUMENTS.

Positional arguments ($1, $2, $3) split space-separated input, which matters when a command needs distinct fields rather than one blob:

---
description: Open a scoped PR against a target branch
---

Create a pull request titled "$1" targeting branch $2.
Base the description on the diff between $2 and HEAD.

/pr "Fix RTL padding" release/2026-08 maps cleanly to title and branch. Positional args make commands feel like real CLI tools instead of a single freeform text box, and they're the right choice the moment a command has more than one distinct input.

Tip: if a command sometimes needs zero arguments and sometimes needs three, write the prompt so it degrades gracefully — e.g. "If no branch is given, use the current branch" — rather than assuming $2 is always populated.

Namespacing with subdirectories

Commands nest by folder, and the folder path becomes part of the command name with a colon separator. .claude/commands/git/commit.md becomes /git:commit. This matters once a team accumulates more than a dozen commands — flat lists in the / menu get unreadable fast.

A reasonable structure for a mid-size team:

.claude/commands/
  git/
    commit.md
    pr.md
    worktree-cleanup.md
  review/
    security.md
    a11y.md
    perf.md
  release/
    changelog.md
    deploy-check.md

That gives /git:commit, /review:security, /release:deploy-check — self-documenting, and it scales without anyone needing a README to remember what exists.

Frontmatter fields worth knowing

FieldPurposeDefault if omitted
descriptionShown in / autocompleteFirst line of the prompt body
allowed-toolsRestricts tool access for this commandInherits session permissions
modelPin the command to a specific model (e.g. force Haiku for a cheap, high-volume command)Session's current model
argument-hintShows placeholder text in autocomplete, e.g. [branch] [message]None

Pinning model matters more than it looks. A command like /summarize-log that runs on every CI failure doesn't need Opus reasoning — pointing it at a cheaper, faster model keeps token cost predictable, which is the same instinct covered in more depth in managing Claude Code token costs.

When a command beats a skill (and vice versa)

This is the question that trips people up most. Claude Code has two extension mechanisms that look similar from the outside but solve different problems.

A slash command is a static prompt template. It's deterministic in structure — same text, arguments substituted, sent every time. It's the right tool when the task is "run this exact sequence of instructions."

A skill is a capability Claude decides to invoke on its own, based on matching your request against the skill's description — it can carry its own tool logic, multi-step reasoning, and reference files, and it can be triggered implicitly ("review this PR" auto-invokes a review skill) rather than only by explicit typing.

Slash commandSkill
InvocationExplicit: user types /nameExplicit or implicit, matched by description
ContentStatic Markdown template + substituted argsCan bundle logic, multiple files, richer instructions
Best forRepeated exact workflows (release checklist, PR template, log triage)Fuzzy-matched capabilities (code review, design review, security scan)
DiscoverabilityAutocomplete menu onlyCan surface itself contextually without being typed
Authoring costOne .md file, minutesUsually a skill folder with a SKILL.md plus supporting scripts

Rule of thumb: if you find yourself writing "when the user says X, Y, or Z, do this multi-step thing" — that's a skill's job. If you find yourself thinking "I want a one-word shortcut for this prompt I keep pasting" — write a command first, it's cheaper to build and cheaper to maintain. A lot of teams start every workflow as a command and only promote it to a skill once they notice they want it triggered automatically rather than typed.

A realistic example: a security-review command

Here's a command close to what a small agency team would actually ship, combining allowed-tools, argument-hint, and a scoped prompt:

---
description: Security review of the current diff against OWASP top 10
argument-hint: "[optional: specific file path]"
allowed-tools: Bash(git diff *), Read, Grep
model: claude-opus-4-6
---

Review the current git diff (or $ARGUMENTS if a path is given) against
the OWASP Top 10. For each finding, report:
- file and line
- severity (low/medium/high)
- concrete exploit scenario, not a generic warning

Do not report style issues. Do not suggest refactors unrelated to security.

That last line matters more than it seems — commands that don't explicitly scope out adjacent behavior tend to drift into unrelated commentary, which wastes the reviewer's time filtering signal from noise. The same discipline applies to writing good Claude Code subagents: narrow scope beats broad scope every time.

Sharing commands across a team

Because commands are just files in .claude/commands/, git does the distribution for you. There's no marketplace step, no publish command. The workflow that actually works:

  1. Commit .claude/commands/ to the repo like any other source directory.
  2. Document non-obvious commands in your CLAUDE.md (or a .claude/rules/ file, if your team uses one) so new hires know they exist — autocomplete alone under-discovers.
  3. Review command changes in PRs the same way you'd review a CI config change. A command with overly broad allowed-tools is a real risk surface, not a cosmetic detail — see Claude Code permissions and safety for the broader model.
  4. Keep personal experiments in ~/.claude/commands/ (global, not committed) until they're proven, then promote the good ones into the repo.
Warning: don't put secrets, API keys, or internal URLs directly in a command's prompt text if the repo is ever going to be public or shared externally. Command files are plain text and get committed like everything else.

For teams already deep into automation, custom commands pair naturally with Claude Code hooks — a hook can enforce something happens every time (e.g. run lint after every edit), while a command is what a human deliberately invokes. They're complementary, not competing.

Debugging commands that don't behave

Three failure modes cover almost everything that goes wrong:

  • Command doesn't show up in / autocomplete. Check the file actually sits in .claude/commands/ (not a sibling folder) and has a .md extension. A missing description field won't hide it, but a typo in the folder name will.
  • $ARGUMENTS is empty when you expected text. You typed /mycommand with nothing after it. Guard for this in the prompt body explicitly rather than assuming Claude will infer intent from silence.
  • Command runs but ignores allowed-tools. Permissions are additive with session-level settings, not a hard sandbox override in every configuration — verify behavior in a fresh session rather than assuming the frontmatter is the final word.

FAQ

How do I create a custom slash command in Claude Code?

Create a Markdown file in .claude/commands/ (project-scoped) or ~/.claude/commands/ (personal, global). The filename becomes the command name — deploy-check.md becomes /deploy-check. Add optional YAML frontmatter for description, allowed-tools, and argument-hint, then write the prompt body below it.

Can Claude Code slash commands take arguments?

Yes, two ways: $ARGUMENTS captures everything typed after the command name as a single string, and $1, $2, $3 split space-separated input into positional variables for commands that need multiple distinct fields, like a title and a branch name.

What's the difference between a slash command and a skill in Claude Code?

A slash command is a static Markdown template invoked explicitly by typing /name — good for repeated exact workflows. A skill is a richer capability that Claude can invoke on its own by matching its description against your request, better suited to fuzzy, multi-step, or contextually-triggered tasks like code review or design review.

Do custom slash commands sync across a team?

Yes, if you put them in .claude/commands/ and commit that folder to git — every teammate who pulls the repo gets the same commands automatically. Commands in ~/.claude/commands/ are personal and stay local to your machine.

Are slash commands safe to share with untrusted collaborators?

Review allowed-tools on any command before sharing it — a command with broad tool access executes with whatever permissions the session grants, so treat command files in PRs the same way you'd review a CI config change, and never hardcode secrets into the prompt text.

Why isn't my slash command showing up in the autocomplete menu?

The most common cause is a misplaced file — it must sit directly in .claude/commands/ (or a subfolder for namespacing) with a .md extension. Double-check for typos in the directory path; a missing description field won't hide the command, but a wrong folder will.


Want a Claude Code setup — commands, hooks, and permissions — built for your team's actual workflow instead of copied from a blog post? Book a free 30-minute call through the contact form or message us directly on WhatsApp.

Sources