> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 04-3 Commands (Slash Commands): What, Why, How

> A slash command binds a frequently-used prompt or workflow to a single /name invocation. This unit covers command format, authoring, $ARGUMENTS injection, and the decision criterion for choosing a command over a Skill.

export const LearnerPrimer = ({items = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    title: "Before this unit, be honest with yourself",
    sub: "If you can't answer these, that gap is exactly what this unit closes."
  } : {
    title: "讀這個單元前，先誠實面對",
    sub: "這幾題答不出來，正是這個單元要替你補的洞。"
  };
  const css = `
  .lp-root{--lp-bg:#FAF7F1;--lp-surface:rgba(191,117,81,0.05);--lp-border:rgba(0,0,0,0.09);--lp-edge:rgba(191,117,81,0.42);--lp-text:#2b2722;--lp-dim:#6f6a62;--lp-accent:#bf7551;border:1px solid var(--lp-border);border-left:3px solid var(--lp-edge);border-radius:13px;background:var(--lp-bg);color:var(--lp-text);overflow:hidden;margin:1.25rem 0;}
  .dark .lp-root{--lp-bg:#1b1a18;--lp-surface:rgba(207,138,104,0.07);--lp-border:rgba(255,255,255,0.08);--lp-edge:rgba(207,138,104,0.5);--lp-text:#e7e3da;--lp-dim:#a8a299;--lp-accent:#cf8a68;}
  .lp-head{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;border-bottom:1px solid var(--lp-border);background:var(--lp-surface);}
  .lp-ic{color:var(--lp-accent);flex-shrink:0;}
  .lp-htx{display:flex;flex-direction:column;gap:1px;min-width:0;}
  .lp-title{font-size:14px;font-weight:650;line-height:1.3;letter-spacing:.01em;}
  .lp-sub{font-size:12px;color:var(--lp-dim);line-height:1.4;}
  .lp-list{list-style:none;margin:0;padding:10px 18px 14px;display:flex;flex-direction:column;gap:0;}
  .lp-item{display:flex;align-items:baseline;gap:11px;padding:7px 0;font-size:14px;line-height:1.6;border-top:1px solid var(--lp-border);}
  .lp-item:first-child{border-top:none;}
  .lp-mark{flex-shrink:0;color:var(--lp-accent);font-size:13px;font-weight:700;line-height:1.55;font-variant-numeric:tabular-nums;opacity:.85;}
  .lp-q{flex:1 1 0;min-width:0;color:var(--lp-text);}
  @media (max-width:620px){.lp-head{padding:12px 14px 10px;}.lp-list{padding:8px 14px 12px;}}
  `;
  return <div className="lp-root">
      <style>{css}</style>
      <div className="lp-head">
        <svg className="lp-ic" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>
        <span className="lp-htx">
          <span className="lp-title">{t.title}</span>
          <span className="lp-sub">{t.sub}</span>
        </span>
      </div>
      <ul className="lp-list">
        {items.map((q, i) => <li className="lp-item" key={i}>
            <span className="lp-mark">{String(i + 1).padStart(2, "0")}</span>
            <span className="lp-q">{q}</span>
          </li>)}
      </ul>
    </div>;
};

<LearnerPrimer
  lang="en"
  items={[
"If you don't type a command, the model won't either.",
"Any workflow with side effects gets disable-model-invocation by default.",
"$ARGUMENTS exists to stop you repeating yourself.",
"Commands are deliberate; Skills are automatic.",
"Write a vague description and you won't remember what the command does in three days.",
"Commit a command file with sensitive data to a public repo and you've just leaked it.",
"Skip disable-model-invocation on a deploy command and the model will run it the moment it thinks it should.",
]}
/>

<Info>
  **What this unit solves**

  A slash command binds a frequently-used prompt or workflow to a single `/name` invocation. The key difference from a Skill: a command is **triggered by you deliberately**; a Skill is invoked by the model **based on its own judgment**. This unit covers command format, authoring, `$ARGUMENTS` parameter injection, and the decision criterion for choosing a command over a Skill.
</Info>

## Learning objectives

* [ ] Explain the difference and division of responsibility between a command (user-triggered) and a Skill (model-invoked).
* [ ] Create a custom command file under `.claude/commands/` or `~/.claude/commands/`.
* [ ] Use `$ARGUMENTS`, `$0`, `$1`, and named-variable syntax to give a command dynamic capability.
* [ ] Use `disable-model-invocation: true` to prevent Claude from invoking a specific command on its own.
* [ ] Decide whether a given requirement belongs as a command or a Skill, and state the criterion.

***

## 1. What a command is

A slash command is an encapsulated prompt you trigger by typing `/name` at the start of a Claude Code session. It does not depend on the model recognizing your intent -- **what you type is what runs** (as of 2026-06, per the official commands documentation \[1]).

Three key properties:

1. **Deliberately triggered**: you don't type it, Claude won't suggest it. The decision is entirely yours.
2. **Reusable**: write it once; every future invocation is identical.
3. **Version-controlled**: files in `.claude/commands/` can go into Git and be shared across the team.

<Tip>
  **Commands vs. pasting a prompt**

  You can paste the same prompt repeatedly, but every time you have to trim parameters and adjust phrasing yourself. A command packages that work: you type `/<name> <args>` and the logic stays consistent. That consistency pays dividends wherever the output format is fixed (commit messages, PR summaries, changelogs) or for inspection workflows you run repeatedly.
</Tip>

## 2. Commands vs. Skills: deliberate vs. automatic

`.claude/commands/<name>.md` and a Skill (`SKILL.md`) **now share the same underlying mechanism** in Claude Code \[2]. Their trigger timing differs:

| Dimension          | Command                                                        | Skill                                                                  |
| ------------------ | -------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Trigger            | User types `/name`                                             | Model invokes based on `description` semantics                         |
| Default visibility | Shown in `/` menu; user-typed                                  | Model-visible; user can also type `/name`                              |
| File location      | `.claude/commands/<name>.md` or `~/.claude/commands/<name>.md` | `.claude/skills/<name>/SKILL.md` or `~/.claude/skills/<name>/SKILL.md` |
| Name collision     | If a skill and a command share a name, the skill wins \[2]     | Same                                                                   |
| Right fit          | "I know I want to do X right now"                              | "Let the model judge when to do X"                                     |

Simplified decision rule:

* **High certainty, fixed workflow** → command.
* **Has side effects, you don't want the model deciding when to run it** (deploy, send message, commit) → command + `disable-model-invocation: true`.
* **Should depend on reading user intent** (code review, doc search, refactor suggestions) → Skill.

<Warning>
  **Workflows with side effects default to command**

  Deployments, pushes, Slack sends, writes to external systems -- anything that is hard to undo -- default to command + `disable-model-invocation: true`. You do not need Claude to trigger a deployment on its own because it "looks like the right time."
</Warning>

## 3. Authoring: file location and structure

File locations (as of 2026-06):

| Location                       | Scope                                                     |
| ------------------------------ | --------------------------------------------------------- |
| `~/.claude/commands/<name>.md` | All projects                                              |
| `./.claude/commands/<name>.md` | Current project; shared with the team via version control |
| `<plugin>/commands/<name>.md`  | Available within an enabled plugin                        |

The filename is the word after `/`: `.claude/commands/deploy.md` responds to `/deploy`; `.claude/commands/fix-issue.md` responds to `/fix-issue`.

### 3.1 Minimal form

```markdown theme={null}
You are helping me write a commit message for the current changes. Use the project's existing commit style (Conventional Commits). Output only the commit message, no preamble.
```

When you trigger `/commit`, this text is injected into Claude's current conversation and Claude uses it to generate a commit message.

### 3.2 Using frontmatter to configure behavior

```markdown theme={null}
---
description: Generate a commit message for staged changes
argument-hint: [optional context]
allowed-tools: Bash(git status *) Bash(git diff *) Bash(git log *)
model: sonnet
---

## Staged changes
!`git diff --cached`

## Recent commit style
!`git log --oneline -10`

## Task
Write a Conventional Commits message for the staged changes above.
$ARGUMENTS
```

Commonly used frontmatter fields (as of 2026-06, per the official Skills and commands documentation \[1, 2]):

| Field                            | Purpose                                                               |
| -------------------------------- | --------------------------------------------------------------------- |
| `description`                    | Shown in the `/` menu; used by Claude when evaluating semantics       |
| `argument-hint`                  | Autocomplete hint text, e.g. `[issue-number]`                         |
| `allowed-tools`                  | Tools that need no additional confirmation when the command is active |
| `model`                          | Override the model; defaults to the current session model             |
| `disable-model-invocation: true` | Prevent Claude from invoking this command on its own                  |
| `user-invocable: false`          | Hide from the `/` menu; model-only invocation                         |

<Note>
  **Why `disable-model-invocation: true` matters**

  Suppose you write a `/deploy` command. Without the flag, the model may see "this code looks ready to deploy" in conversation and invoke `/deploy` on its own -- while you are still reviewing. With `disable-model-invocation: true`, the command only runs when you explicitly type `/deploy`; the model cannot see it at all. For any workflow with side effects -- deploy, send, push -- add this flag by default.
</Note>

## 4. Parameter injection: `$ARGUMENTS` and indexed syntax

When you trigger a command, everything you type after `/name` is injected into the command body.

<Steps>
  <Step title="Simplest approach: $ARGUMENTS">
    Use `$ARGUMENTS` to receive everything typed after `/name`:

    ```markdown theme={null}
    ---
    description: Fix a GitHub issue by number
    ---

    Fix GitHub issue $ARGUMENTS following our coding standards.
    1. Read the issue description
    2. Understand the requirements
    3. Implement the fix
    4. Write tests
    5. Create a commit
    ```

    Typing `/fix-issue 123` replaces `$ARGUMENTS` with `123`; Claude receives "Fix GitHub issue 123 following our coding standards. ..." \[2].

    If the command body contains no `$ARGUMENTS`, Claude Code appends the arguments as `ARGUMENTS: <your input>` at the end of the body -- Claude still sees them \[2].
  </Step>

  <Step title="Positional index: $0, $1, $2">
    To split multiple arguments, use `$0`, `$1`, `$2`, or `$ARGUMENTS[0]`:

    ```markdown theme={null}
    ---
    description: Migrate a component from one framework to another
    ---

    Migrate the $0 component from $1 to $2.
    Preserve all existing behavior and tests.
    ```

    Typing `/migrate-component SearchBar React Vue` gives `$0` = `SearchBar`, `$1` = `React`, `$2` = `Vue`.

    Wrap multi-word arguments in quotes: `/migrate-component "Search Bar" React "Vue 3"`.
  </Step>

  <Step title="Named parameters">
    Declare `arguments` in frontmatter and reference them by name in the body:

    ```yaml theme={null}
    ---
    description: Create a commit with branch and issue context
    arguments:
      - branch
      - issue
    ---
    ```

    ```markdown theme={null}
    Create a commit on branch $branch referencing issue $issue.
    ```

    Typing `/commit feature-x 456` gives `$branch` = `feature-x` and `$issue` = `456` \[2].
  </Step>
</Steps>

### 4.1 Other available variables

| Variable               | Purpose                                                                     |
| ---------------------- | --------------------------------------------------------------------------- |
| `${CLAUDE_SESSION_ID}` | Current session ID; useful for log names or session-scoped filenames        |
| `${CLAUDE_SKILL_DIR}`  | Directory containing the command/skill; use to reference co-located scripts |
| `${CLAUDE_EFFORT}`     | Current effort level (`low` / `medium` / `high` / `xhigh` / `max`)          |

## 5. Dynamic context injection: `` !`command` ``

Command body content can use `` !`shell command` `` to execute a shell command **before the body is sent to Claude** and embed its output inline \[2]:

```markdown theme={null}
## Current changes
!`git diff HEAD`

## Status
!`git status --short`
```

When the command is invoked, Claude Code executes each `` !`cmd` `` in sequence, substitutes the output, and **only then passes the entire body to Claude as a prompt**. From Claude's perspective it receives plain text that already contains the git diff output.

Multi-line commands use the fenced code block form:

````markdown theme={null}
## Environment
```!
node --version
npm --version
git status --short
```
````

<Warning>
  **Two traps with dynamic injection**

  1. **The execution environment is your shell.** When you type `/deploy`, `` !`cmd` `` inside the command runs in your local shell (macOS/Linux defaults to `bash`; Windows defaults to PowerShell, configurable \[2]). Do not write sensitive operations into a command file.
  2. **Org-level disable setting**: organizations can set `"disableSkillShellExecution": true` in `settings.json`, replacing all dynamic injections with `[shell command execution disabled by policy]`. Do not rely on this mechanism for critical steps in commands destined for public repos.
</Warning>

## 6. Tool comparison

| Concept                       | Anthropic Claude (primary)                                   | OpenAI Codex                                                               | GitHub Copilot                                    | Cursor                                       |
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------- | ------------------------------------------------- | -------------------------------------------- |
| Custom command location       | `.claude/commands/<name>.md`, `~/.claude/commands/<name>.md` | `config.toml` configuration (path subject to current OpenAI documentation) | `.github/prompts/<name>.prompt.md` (prompt files) | `.cursor/commands/<name>.md`                 |
| Parameter injection syntax    | `$ARGUMENTS`, `$0`, `$1`, named variables                    | No equivalent `ARGUMENTS` syntax                                           | Structured frontmatter fields                     | `$ARGUMENTS`-style variables                 |
| Global vs. project scope      | `~/.claude/commands/` vs. `.claude/commands/`                | `~/.codex/prompts/` vs. `.codex/prompts/`                                  | Separate global and project files                 | Global User Rules + project `.cursor/rules/` |
| Trigger                       | User types `/name`                                           | User types                                                                 | User types                                        | User types                                   |
| Prevent model auto-invocation | `disable-model-invocation: true`                             | (mechanism differs significantly)                                          | (mechanism differs significantly)                 | (mechanism differs significantly)            |

<Note>
  **Naming clarification**

  Commands and Skills share the same underlying mechanism in Claude Code: as of 2026-06 both are unified, and both `.claude/commands/<name>.md` and `.claude/skills/<name>/SKILL.md` produce a `/name` command \[2]. The difference is that the former is a single file while the latter is a directory (including `references/` and `scripts/`; see [04-4 Skills](/en/code-agent/customization/skills)). This unit focuses on the "user-triggered" face shared by both. OpenAI Codex, GitHub Copilot, and Cursor each have a "prompt file" or "prompt template" concept, but the paths and mechanisms differ significantly; the common denominator is "prompt files support `$ARGUMENTS`-style variables" -- consult each vendor's current documentation for details.
</Note>

## 7. Hands-on exercises

<Note>
  **30-minute practice**

  1. **Write a `/commit` command**: include `disable-model-invocation: true` and `allowed-tools: Bash(git *)` in the frontmatter; use `` !`git diff --cached` `` and `` !`git log --oneline -10` `` to pull in the staged diff and recent commit style, then ask Claude to output a Conventional Commits message.
  2. **Create a global command**: write `~/.claude/commands/weekly-review.md` that uses `$ARGUMENTS` to receive your focus topic; start a new project session and confirm `/weekly-review` works across projects.
  3. **Test the misfire guard**: write a `/deploy-prod` command deliberately **without** `disable-model-invocation`; mention "looks like it's ready to deploy" in conversation and observe whether Claude invokes it on its own. Then add `disable-model-invocation: true`, repeat the same sentence, and confirm Claude no longer self-triggers.
</Note>

## 8. Common pitfalls

<Warning>
  **Anti-pattern list**

  * **Turning every workflow into a command**: too many user-triggered invocations increase workflow friction. Use a Skill for cases where the model should judge the right time (code review, doc search).
  * **Vague `description`**: you will forget what the command does in three days. Describe the trigger condition and expected output precisely; "help me do X" is not a description.
  * **Writing deploy/push/send commands without `disable-model-invocation`**: the model may run them before you have confirmed, producing irreversible side effects.
  * **Committing command files with sensitive data to a public repo**: command bodies go into version control, so API keys, absolute paths, and internal URLs all leak.
  * **Dynamic injection that depends on unverified state**: writing `` !`./scripts/deploy.sh` `` when that script's permissions or content are not fixed destroys reproducibility. Deterministic deployment workflows belong in a Hook (see [04-6 Hooks](/en/code-agent/customization/hooks)) or a standalone CI step.
</Warning>

## Self-check

<Check>
  **The bar for passing this unit**

  1. Can you state the fundamental difference between a command and a Skill? (The trigger subject differs.)
  2. Can you write a command that accepts `$ARGUMENTS` in under five minutes?
  3. Can you identify which commands should carry `disable-model-invocation: true`?
  4. Do you have a prompt you type three or more times a week? Should it be a command or a Skill? State your criterion.
</Check>

## Sources and further reading

Factual claims are grounded in official documentation; fast-changing items are annotated as of 2026-05.

<div className="references">
  * \[1] Anthropic, "Commands," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/commands](https://code.claude.com/docs/en/commands) (as of 2026-06; covers built-in and custom commands)
  * \[2] Anthropic, "Extend Claude with skills," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills) (as of 2026-06; covers the unified command/skill mechanism, `$ARGUMENTS`, and complete frontmatter reference)
  * \[3] Anthropic, "How Claude remembers your project," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/memory](https://code.claude.com/docs/en/memory) (as of 2026-06; `CLAUDE.md` and modular rules)
</div>

* `CLAUDE.md` and auto-memory: [04-1 CLAUDE.md and memory files](/en/code-agent/customization/claude-md-memory).
* Path-scoped rules: [04-2 Rules](/en/code-agent/customization/rules).
* Advanced Skills (references/, scripts/, progressive disclosure): [04-4 Skills](/en/code-agent/customization/skills).
* Deterministic enforcement with hooks: [04-6 Hooks](/en/code-agent/customization/hooks).
