Courses/Introduction to Agent Skills/Dynamic Context Injection and Substitutions
Multi-File and Advanced SkillsLesson 9 of 16

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.

markdownThe !`git diff HEAD` line is replaced with the actual diff before Claude reads the skill — so the response is grounded in your real working tree.
---
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

SKILL.md has!`git diff HEAD`command runs(preprocessing)output replacesthe placeholderClaude

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.

VariableExpands to
$ARGUMENTSAll arguments passed to the skill
$ARGUMENTS[N] / $NThe Nth argument (0-based): $0, $1, ...
$nameA 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.

markdownRunning /migrate-component SearchBar React Vue substitutes $0=SearchBar, $1=React, $2=Vue.
---
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.

markdownThe gh commands run first; Claude receives a fully-rendered prompt with the real PR data already inlined.
---
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