| name | skill-capabilities |
| description | When authoring a new skill or updating an existing one -- reference this for the two advanced frontmatter capabilities: dynamic context injection via `!`command`` syntax and `allowed-tools` for pre-approving tool use. Apply selectively; both features add overhead and should only appear where they genuinely help. |
Skill capabilities reference
Two frontmatter capabilities are available in SKILL.md files that are
underused by default: dynamic context injection and allowed-tools.
This skill describes what they do, when to use them, and which skills in
this repo use each.
Dynamic context injection
Any line in a skill body that contains !`command` is treated as an
inline shell execution. Claude Code runs the command before the skill
content is loaded into context, replacing the backtick expression with
the command's stdout.
Current open issues: !`gh issue list --state open --json number,title,labels`
When this skill loads, the backtick expression is replaced with the live
output. The agent sees the issues list as part of the skill body, not as
a Bash tool call result.
When to use dynamic context injection
Use it when:
- The skill is invoked to do a specific action (not just as background
reference), AND
- Live state -- current git status, open issues, PR list -- would
meaningfully change how the agent uses the skill, AND
- The command is fast (< 1 second) and low-cost.
Don't use it when:
- The skill is pure reference material (the agent reads it once at
session start and doesn't invoke it again).
- The command might fail or produce large output (truncation degrades
the skill body in unpredictable ways).
- The information is already available in the agent's context via
another channel.
$ARGUMENTS in dynamic injection
When a skill is used as a slash command (/skill-name arg), the user's
arguments are available as $ARGUMENTS:
!`gh issue view $ARGUMENTS --json title,body,labels`
This only works for slash-command invocation. Background skills (always-
loaded from ~/.claude/skills/) don't receive $ARGUMENTS -- those
expressions run with an empty argument and may produce errors or empty
output.
Skills using dynamic injection in this repo
| Skill | Command | Purpose |
|---|
triage | gh issue list --state open --json number,title,labels | Inject current open issue list at triage-start |
allowed-tools
The allowed-tools frontmatter field pre-approves specific tools so
they run without per-use permission prompts while the skill is active.
---
name: my-skill
description: ...
allowed-tools: Bash(gh:*) Bash(git:*)
---
Or using YAML list syntax:
---
name: my-skill
description: ...
allowed-tools:
- Bash(gh:*)
- Bash(git:*)
---
When to use allowed-tools
allowed-tools has effect only when the skill body directly invokes
commands via !command dynamic injection. If the skill body describes commands for the agent to run (without `!`... markers), allowed-tools
does NOT pre-approve those commands -- the agent issues them via the Bash
tool, and the usual permission rules apply.
Use it when:
- The skill body contains
!command`` patterns, AND
- Those commands need tools not in the agent's current allowlist.
The most common case: a skill with !gh ...`` patterns needs
allowed-tools: Bash(gh:*).
For skills that only describe commands (reference material), adding
allowed-tools has no technical effect on those commands. However,
adding it signals to skill authors that this skill expects those tools to
be available when active.
Scope guidance
Use narrow scopes:
Bash(gh:*) not Bash(*) -- approve GitHub CLI, not all Bash
Bash(git:*) not Bash(*) -- approve git, not all Bash
- List each tool separately; don't over-broad with
Bash(*)
Skills using allowed-tools in this repo
| Skill | allowed-tools | Reason |
|---|
triage | Bash(gh:*) | Has !gh issue list...`` dynamic injection |
pr-review | Bash(gh:*) | Reviewer actions (approve, merge, request-changes) use gh |
Interaction between the two features
Dynamic context injection (!command) executes commands during skill loading. `allowed-tools` pre-approves the tool needed for those commands. They work together: add `allowed-tools` to any skill that has `!`command patterns using Bash.
A skill with only !gh ...`` patterns but no allowed-tools: Bash(gh:*)
will prompt the user each time the skill loads. Add both together.
Checking for existing usage
To see which skills currently use these features:
grep -r "allowed-tools" skills/*/SKILL.md
grep -r "!\`" skills/*/SKILL.md
Anti-patterns
- Adding
allowed-tools to skills describing agent-run commands -- it only affects dynamic injection, not agent Bash.
- Using
Bash(*) as an over-broad scope when Bash(gh:*) or Bash(git:*) would suffice -- prefer narrow scopes.
- Adding dynamic injection to pure-reference skills -- live state at load time may be stale by the time the skill is used.
Related
orchestration-prompt-template
-- the prompt template for runner dispatches; similar frontmatter
concepts apply when writing custom commands.
sandbox-preflight -- the runtime
tool-availability check at dispatch start; complements allowed-tools
at the session level.