Pass arguments to a Claude Code custom slash command
Put $ARGUMENTS, $0, $1 or named arguments in a .claude/commands markdown file, then check how quoted values and missing arguments are substituted.
To use the words typed after /x foo bar inside the prompt, put placeholders in the command file. The output below comes from four claude -p runs on 2.1.302.
[1] Create a markdown file in .claude/commands/. The file name without the extension is the command name. A subfolder becomes /folder:name.
---description: Echo argumentsargument-hint: [first] [second]---Reply with exactly this one line and nothing else:ALL=[$ARGUMENTS] ZERO=[$0] ONE=[$1] TWO=[$2]argument-hint is only the hint shown in autocomplete. It has no effect on substitution.
[2] Run it with arguments.
$ claude -p "/x foo bar" --max-turns 1ALL=[foo bar] ZERO=[foo] ONE=[bar] TWO=[$2]$ARGUMENTS is the whole string as typed. $0 is the first argument and $1 the second. Counting starts at 0, so code written with $1 as "first" is off by one.
[3] Quote values that contain spaces. Numbered arguments follow shell-style quoting.
$ claude -p '/x "hello world" second' --max-turns 1ALL=["hello world" second] ZERO=[hello world] ONE=[second] TWO=[$2]$ARGUMENTS keeps the quotes exactly as typed. Use $0 when you want a path or sentence as one value, and $ARGUMENTS when you want to paste everything that was typed.
[4] To refer to arguments by name, declare arguments in the frontmatter, as a space-separated string or a YAML list. Names map to positions in the order declared.
---description: Named argsarguments: [issue, branch]---Reply with exactly this one line and nothing else:ISSUE=[$issue] BRANCH=[$branch]$ claude -p "/z 42 fix-login" --max-turns 1ISSUE=[42] BRANCH=[fix-login][5] If a command has no placeholder at all and you pass arguments, the docs say Claude Code appends a line ARGUMENTS: <what you typed> to the end of the content. The value is not lost, but it has no fixed position. This was not run here.
[6] To write a literal $ before a digit ($1.00), escape it as \$1.00. If a passed value itself contains $1 or $ARGUMENTS, it is inserted as literal text and not expanded again. Both are from the docs.
[7] If the command does not show up or the values do not arrive, check this table.
| Symptom | Check |
|---|---|
No /name | The file is directly in .claude/commands/ (or a subfolder) and ends in .md. In a subfolder the name is /folder:name |
| A skill has the same name | The skill runs (docs) |
| A frontmatter field has no effect | Field names must match exactly, hyphens included. Unknown names are ignored without an error (docs). Writing argument instead of arguments declares no named arguments |
| Frontmatter shows up as prompt text | If the opening --- is not the first line of the file, everything including the --- lines is treated as content (docs) |
| Broken YAML | Only the body loads, with no fields (docs) |
A file with a blank line before the frontmatter (w.md) was also run. The reply looked the same either way, so this output cannot tell whether the frontmatter ended up in the prompt. Follow the docs and start the file with ---.
A .claude/commands/ file and a .claude/skills/<name>/SKILL.md create the same /name and use the same argument syntax. The docs recommend skills for new work. If a skill does not appear, see Claude Code skills not appearing or not triggering.