Preflight Checklist
What's Wrong?
Title: Skill re-invocation dedupe is keyed on the RENDERED content, so changing only the arguments re-appends the entire SKILL.md — composing skills costs N × body
Type: design flaw / enhancement (the behaviour matches the docs; the docs describe a design that defeats skill composition)
Environment
- Claude Code 2.1.276 (CLI), Linux (WSL2)
- Project skills under
.claude/skills/*/SKILL.md, invoked by the model through the Skill tool
What happens
The skills docs (§ Skill content lifecycle) state:
When Claude re-invokes a skill whose rendered content is identical to the copy already in context, Claude Code adds a short note that the skill is already loaded rather than a second copy of the content. When the rendered content differs, because the arguments changed […], Claude Code appends the full content again.
So the dedupe key is the skill body after argument substitution. Any skill that takes an argument — i.e. any skill designed to be called — renders differently on every call with a new argument, and the full body is appended again each time.
Why this is worth fixing
The control shows Claude Code already has the right rendering: instructions once, arguments delivered per call. It only takes that path when the arguments did not change — the one case where re-invoking is least useful. It is a loader that hashes a function together with its call frame, so every distinct call looks like a new function.
The re-invocation header even reads as though a delta was intended ("the arguments or dynamic output below are new"), but what follows is the whole body, not just the new arguments.
Practical cost: an orchestrating skill that calls a worker skill once per item (per file, per ticket, per finding) pays the worker's full body per item. That pushes authors away from small, composable, argument-taking skills toward either monolithic skills, or passing the subject implicitly through conversation state purely to keep the args string constant — ambient state, which is worse engineering and fails silently when mis-resolved.
What Should Happen?
Proposed behaviour
Key the dedupe on the skill's template (pre-substitution body + resolved file identity), not the rendered output:
- template unchanged, args changed → emit the short note plus the new
Arguments: — the exact shape the identical-args path already produces;
- template unchanged, a dynamic-context command's output changed → emit the note plus only the changed dynamic output;
- template changed on disk → append the full content (today's behaviour).
If a skill interpolates $ARGUMENTS mid-body, the note can carry the arguments once; the model already holds the body that says where they apply.
Error Messages/Logs
Steps to Reproduce
Repro
Use any reasonably large project skill that accepts arguments — say .claude/skills/process-item/SKILL.md (~6–7K tokens), whose body refers to its arguments (via $ARGUMENTS, or the auto-appended ARGUMENTS: trailer).
-
Have the model call Skill(skill="process-item", args="item-1") → the full body enters context. Expected.
-
Have it call Skill(skill="process-item", args="item-2"), then item-3, then item-4.
-
Each of those calls is answered with
(Re-invocation of /process-item — the skill instructions were previously loaded; the arguments or dynamic output below are new.)
followed by the complete SKILL.md body again. Four calls ≈ 20K+ tokens of byte-identical instructions; only the one argument token differs between them.
Control — re-invoke a skill with byte-identical args. The entire response is one line:
Skill /process-item is already loaded above; instructions unchanged. Arguments: item-1
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.276
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
Not the same as
Preflight Checklist
What's Wrong?
Title: Skill re-invocation dedupe is keyed on the RENDERED content, so changing only the arguments re-appends the entire SKILL.md — composing skills costs N × body
Type: design flaw / enhancement (the behaviour matches the docs; the docs describe a design that defeats skill composition)
Environment
.claude/skills/*/SKILL.md, invoked by the model through theSkilltoolWhat happens
The skills docs (§ Skill content lifecycle) state:
So the dedupe key is the skill body after argument substitution. Any skill that takes an argument — i.e. any skill designed to be called — renders differently on every call with a new argument, and the full body is appended again each time.
Why this is worth fixing
The control shows Claude Code already has the right rendering: instructions once, arguments delivered per call. It only takes that path when the arguments did not change — the one case where re-invoking is least useful. It is a loader that hashes a function together with its call frame, so every distinct call looks like a new function.
The re-invocation header even reads as though a delta was intended ("the arguments or dynamic output below are new"), but what follows is the whole body, not just the new arguments.
Practical cost: an orchestrating skill that calls a worker skill once per item (per file, per ticket, per finding) pays the worker's full body per item. That pushes authors away from small, composable, argument-taking skills toward either monolithic skills, or passing the subject implicitly through conversation state purely to keep the args string constant — ambient state, which is worse engineering and fails silently when mis-resolved.
What Should Happen?
Proposed behaviour
Key the dedupe on the skill's template (pre-substitution body + resolved file identity), not the rendered output:
Arguments:— the exact shape the identical-args path already produces;If a skill interpolates
$ARGUMENTSmid-body, the note can carry the arguments once; the model already holds the body that says where they apply.Error Messages/Logs
Steps to Reproduce
Repro
Use any reasonably large project skill that accepts arguments — say
.claude/skills/process-item/SKILL.md(~6–7K tokens), whose body refers to its arguments (via$ARGUMENTS, or the auto-appendedARGUMENTS:trailer).Have the model call
Skill(skill="process-item", args="item-1")→ the full body enters context. Expected.Have it call
Skill(skill="process-item", args="item-2"), thenitem-3, thenitem-4.Each of those calls is answered with
followed by the complete SKILL.md body again. Four calls ≈ 20K+ tokens of byte-identical instructions; only the one argument token differs between them.
Control — re-invoke a skill with byte-identical args. The entire response is one line:
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.276
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
Not the same as