Skill tool: multi-word args cause $N positional substitution to corrupt literal $N tokens in skill body (e.g. Excel cell refs)
Description
When invoking a Skill via the Skill tool with a multi-word args string, the returned skill content can be corrupted: literal $N tokens inside the skill's Markdown body (e.g. Excel-style absolute cell references like $B$2) get replaced with words from the args string, as if the harness were doing shell-style positional-parameter substitution ($1, $2, ...) against the whole skill body using the invocation args as the positional-parameter list.
This looks like the same templating mechanism used for slash-command files (which support $ARGUMENTS, $1, $2, ... placeholders) is being applied to Skill content as well, where it was never intended to run — Skill bodies are plain documentation/instructions, not command templates, and can legitimately contain literal $N sequences (spreadsheet cell references being the clearest example).
Steps to reproduce
- Install the official
xlsxskill (fromanthropics/skills,skills/xlsx/SKILL.md) under~/.claude/skills/xlsx/SKILL.md. Its body contains literal Excel references such as `$B$2,$B$5,$B$6`. - Invoke it with a multi-word
argsstring, e.g.:
````
Skill({ skill: "xlsx", args: "smoke test: confirm skill loads cleanly, no action needed" })
- Observe the returned skill content.
Expected
The skill body is returned byte-for-byte as written in SKILL.md.
Actual
Several $N tokens in the body are replaced with words from args, e.g. (own reproduction):
- `
$B$2→$Bconfirm` - `
$B$5→$Bcleanly,` - `
$B$6→$Bno`
The substitution appears to be positional: args split on whitespace, 0-indexed, and $N in the body replaced with args_words[N]. For the args string "smoke test: confirm skill loads cleanly, no action needed" (0=smoke, 1=test:, 2=confirm, 3=skill, 4=loads, 5=cleanly,, 6=no, ...), $2→confirm, $5→cleanly,, $6→no all match exactly.
Verified NOT a file corruption
Re-reading the on-disk SKILL.md file directly afterward shows it is byte-for-byte correct ($B$2 etc. intact). The corruption only appears in what the Skill tool returns/renders for that turn — so this is a rendering/templating bug in the Skill invocation path, not a persistence bug.
Suggested fix
Don't apply $1/$2/$ARGUMENTS-style positional substitution to Skill body content — that behavior belongs to slash-command templates only. If Skill invocations are meant to support argument templating in the future, it should require an explicit opt-in marker in the SKILL.md rather than blindly matching any literal $N substring.
Environment
- Windows 11 Pro, PowerShell 5.1 primary shell, Git Bash also available
- Reproduced via Claude Code CLI