Skill `args` are substituted into `$0`/`$1`/`$2` in the SKILL.md body, silently corrupting shell commands

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 1 comment · opened Aug 5, 2026

Summary

When the Skill tool is invoked with args, occurrences of $0, $1, $2… in the SKILL.md body are replaced with the whitespace-split words of args. The file on disk is unchanged — only the loaded content differs. Invoking the same skill without args leaves them intact.

This appears to be slash-command positional-argument interpolation being applied to the whole skill body. Fenced/inline code spans are not exempt.

The failure is silent: the result is not an error but a plausible-looking different command.

Reproduction

~/.claude/skills/zz-repro-args/SKILL.md:

---
name: zz-repro-args
description: Temporary reproduction case.
---

# Repro

Line A: `awk '{print $1}'`
Line B: `awk '{print $2}'`
Line C: price is $0.10 per GB

Invoke with args: "alpha bravo charlie" → loaded content becomes:

Line A: `awk '{print bravo}'`
Line B: `awk '{print charlie}'`
Line C: price is alpha.10 per GB

So $0alpha, $1bravo, $2charlie.

Invoke the same skill with no args$1, $2, $0.10 are preserved correctly.

Impact

Any skill whose body contains $<digit> is affected when invoked with args:

  • awk field referencesawk '{print $1}' becomes awk '{print bravo}'. In awk an undefined variable is the empty string, so the command succeeds and returns nothing. A BASE_SHA=$(… | awk '{print $1}') silently yields an empty value rather than failing.
  • Shell positional parameters
  • PostgreSQL placeholdersUPDATE t SET n = n + $1
  • Dollar amounts in documentation tables$0.10/GB becomes <word>.10/GB, corrupting cost figures the model then reasons about.

This affects bundled skills as well. In the official superpowers plugin, skills/requesting-code-review/SKILL.md contains:

BASE_SHA=$(git log --oneline | grep "Task 1" | head -1 | awk '{print $1}')

Invoked with args, this resolves BASE_SHA to an empty string, so the subsequent diff range is wrong.

Expected behavior

$<digit> in a skill body should not be treated as a positional parameter, or interpolation should at minimum skip fenced code blocks and inline code spans. If positional interpolation in skills is intentional, an escape mechanism (e.g. $$1) and documentation for it would be needed.

Environment

  • Claude Code 2.1.222
  • macOS (Darwin 25.6.0)

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗