Dynamic Context Injection and Substitutions
Inlining Live Data Before Claude Sees It
One of the most powerful skill features is dynamic context injection: the `` !`command` `` syntax runs a shell command BEFORE the skill content is sent to Claude, and the command's output replaces the placeholder. So Claude receives actual data — your live git diff, the current PR — not an instruction to go fetch it. It's preprocessing, not something Claude executes.
---
description: Summarizes uncommitted changes and flags anything risky.
Use when the user asks what changed or wants a commit message.
---
## Current changes
!`git diff HEAD`
## Instructions
Summarize the changes above in two or three bullet points, then list any
risks such as missing error handling, hardcoded values, or tests to update.How Injection Works
Each !`command` executes first, its output is inlined, and only the fully-rendered prompt (with real data) reaches Claude.
- 1.Each !`<command>` executes immediately, before Claude sees anything.
- 2.Its output replaces the placeholder in the skill content.
- 3.Claude receives the fully-rendered prompt with actual data — it never runs the command itself.
- 4.Substitution runs once over the file; injected output isn't re-scanned for more placeholders.
Syntax and safety
The inline form is only recognized when ! starts a line or follows whitespace (so KEY=!`cmd` is treated as literal). For multi-line commands, use a fenced block opened with ```! instead. Admins can disable this entirely with "disableSkillShellExecution": true in settings.
String Substitutions
Alongside command injection, skills support string substitution for dynamic values — letting one skill handle many inputs and adapt to the session.
| Variable | Expands to |
|---|---|
| $ARGUMENTS | All arguments passed to the skill |
| $ARGUMENTS[N] / $N | The Nth argument (0-based): $0, $1, ... |
| $name | A named argument from the 'arguments' frontmatter |
| ${CLAUDE_SESSION_ID} | The current session ID (logging, session files) |
| ${CLAUDE_SKILL_DIR} | The skill's own directory (script paths) |
Combine injection (live data) with substitution (arguments) to build flexible, parameterized skills.
---
name: migrate-component
description: Migrate a component from one framework to another
---
Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.A Real Pattern: Live PR Summary
Putting it together, here's a skill that summarizes a pull request by injecting live GitHub data — combining command injection, allowed-tools, and (as a preview of the next lesson) running in a forked subagent.
---
name: pr-summary
description: Summarize changes in a pull request
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
## Pull request context
- PR diff: !`gh pr diff`
- PR comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`
## Your task
Summarize this pull request...Next
That last skill used context: fork. The next lesson explains running a skill inside a subagent — and how skills and subagents combine in both directions.
Key Takeaways
- ✓Dynamic context injection: the !`command` syntax runs a shell command BEFORE the skill reaches Claude, and the output replaces the placeholder — so Claude gets real data, not an instruction to fetch it.
- ✓It's preprocessing: each command runs first, output is inlined, and Claude never executes the command itself; substitution runs once and isn't re-scanned.
- ✓Inline ! is only recognized at line start or after whitespace; use a fenced ```! block for multi-line commands; admins can disable it via disableSkillShellExecution.
- ✓String substitutions parameterize skills: $ARGUMENTS, $ARGUMENTS[N]/$N, named $name, ${CLAUDE_SESSION_ID}, ${CLAUDE_SKILL_DIR}.
- ✓Example: /migrate-component SearchBar React Vue fills $0/$1/$2 — one skill, many inputs.
- ✓Injection + substitution + allowed-tools combine into powerful grounded skills (e.g. a PR summary that inlines live gh pr diff output).
Check Your Understanding
Test what you learned in this lesson.
Q1.What does the !`command` syntax in a skill do?
Q2.In the skill body, what does $ARGUMENTS[0] (or $0) expand to?
Q3.For a multi-line shell command in a skill, which form should you use?
Q4.What is true about the timing of dynamic context injection?
Practice This Lesson