plugin-dev: command-development teaches `$1` as the first argument, but `$N` is 0-based
What's wrong
plugins/plugin-dev/skills/command-development/SKILL.md says "Capture individual arguments with $1, $2, $3, etc." and uses $1 as the first argument throughout. In Claude Code, $N is 0-based shorthand for $ARGUMENTS[N]: $0 is the first argument and $1 the second. That applies to commands/*.md files as well as skills.
The guide's own examples, run as written on Claude Code 2.1.273 (commands in .claude/commands/, request captured with a local stub):
| Guide example | Guide says it expands to | Claude received |
|---|---|---|
/review-pr 123 high alice |
Review pull request #123 with priority level high. / After review, assign to alice for follow-up. |
Review pull request #high with priority level alice. / After review, assign to $3 for follow-up. |
/deploy api staging --force --skip-tests |
Deploy api to staging environment with options: --force --skip-tests |
Deploy staging to --force environment with options: --skip-tests |
The second example is also wrong about $3: an indexed placeholder takes one argument, not "remaining arguments".
Since plugin-dev is what people (and Claude) use to write commands, the mistake spreads: code-modernization read every argument one position off, which #6153 fixes for that plugin only.
Where it appears
In command-development/SKILL.md:
- "Using Positional Arguments" and "Combining Arguments" (the two examples above)
- "Argument Handling", whose
$IF($1, …)example also uses a construct that isn't in the Claude Code docs - The file-reference, testing, documentation, workflow, plugin-pattern, integration and validation examples, such as
@$1,npm test $1,gh pr view $1andDeploy to $1 - Troubleshooting: "Verify
$1,$2syntax correct"
The copy in anthropics/claude-code/plugins/plugin-dev has the same text.
Suggested fix
Rewrite the positional examples to use named arguments, the way #6153 does for code-modernization, e.g.:
---
description: Review PR with priority and assignee
argument-hint: [pr-number] [priority] [assignee]
arguments: [pr, priority, assignee]
---
Review pull request #$pr with priority level $priority.
After review, assign to $assignee for follow-up.On 2.1.273, /review-pr 123 high alice with this file expands to Review pull request #123 with priority level high. and After review, assign to alice for follow-up.
Where indexed access is shown, use $0, $1, $2 (or $ARGUMENTS[0] and so on) with a note that numbering starts at 0, and that \$1 keeps a literal $1 for awk or shell snippets in a command body.
Related
- Same class of problem in a shipped command:
plugins/commit-commands/commands/clean_gone.mdhasawk '{print $1}'in its body. It's harmless when/clean_goneruns with no arguments or one word, but two or more words turn it intoawk '{print <second word>}'. Escaping it as\$1would make it robust. - anthropics/claude-code#94709 and #94496: users hit by the same substitution in their own skills.
Source: anthropics/claude-plugins-official