Agent skill

command-authoring

Create single-file commands with dynamic content injection (@path and !command). Use when building commands that need filesystem access, git state, runtime context, or argument handling with $1 placeholders. Includes @file injection, !shell execution, <injected_content> wrappers, and single-file structure patterns. Not for skills (use skill-development) or audit workflows.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/command-authoring

SKILL.md

<mission_control> Create single-file commands with @path and !command injection for dynamic content and runtime state <success_criteria>Command has valid frontmatter, proper @/! injection patterns, and graceful error handling</success_criteria> </mission_control>

Quick Start

If you need to inject file content: Use @path pattern at invocation time.

If you need to execute shell commands: Use !`command` for dynamic state.

If you need graceful file handling: Wrap @path in <injected_content> with fallback text.

If you need argument handling: Use $1 for unique identifiers (IDs, hashes, slugs) only.

Navigation

If you need... Read this section...
File injection ## PATTERN: @ Path Injection
Command execution ## PATTERN: ! Command Injection
Structure ## PATTERN: Command Structure
Namespacing ## PATTERN: Namespacing
Thin interface ## PATTERN: Thin Interface
Engine separation ## PATTERN: Engine Separation
Argument handling ## PATTERN: Argument Patterns
Anti-patterns ## ANTI-PATTERN: Common Mistakes

PATTERN: @ Path Injection

Basic @ Syntax

markdown
<injected_content>
@.claude/workspace/handoffs/diagnostic.yaml
</injected_content>

Or inline:

markdown
Current handoff: @.claude/workspace/handoffs/latest.yaml

What @ Does

At invocation time, the file content replaces the @path pattern. This captures the current state of files that change between sessions.

@ Rules

Rule Example
Wrap in <injected_content> Semantic grouping
Use absolute or relative paths @/path/file or @./path/file
Content replaces pattern File content inlines at invocation

@ Use Cases

Use Case Example
Handoff files @.claude/workspace/handoffs/*.yaml
Configuration @.claude/settings.json
Diagnostic files @.claude/workspace/diagnostic.yaml

Error Handling

Scenario Behavior
File exists Injects content
File missing Empty result (command handles gracefully)

Graceful File Handling

markdown
<injected_content>
@.claude/workspace/handoffs/diagnostic.yaml
</injected_content>

If file doesn't exist: Create new diagnostic

Multiple File Injection

markdown
<injected_content>
@.claude/workspace/handoffs/diagnostic.yaml
@.claude/workspace/handoffs/handoff.yaml
</injected_content>

PATTERN: ! Command Injection

Basic ! Syntax

markdown
Current branch: !`git branch --show-current`
Git status: !`git status --short`

What ! Does

At invocation time, the bash command executes and its output replaces the !`command` pattern. This captures runtime state that changes between invocations.

! Rules

Rule Example
Use backticks !`command`
Standard bash syntax git, gh, ls, etc.
Output inlines at invocation stdout replaces pattern

! Use Cases

Use Case Example
Git state !`git branch --show-current
CI status !`gh run list --limit 1 --json conclusion
File stats !`wc -l file.ts

Error Handling

Scenario Behavior
Command succeeds Injects stdout
Command fails Empty result (command handles gracefully)

Safe Commands

markdown
✅ Safe:
!`git branch --show-current`
!`gh run list --limit 1 --json conclusion`
!`pwd`
!`ls *.md`

❌ Unsafe:
!`rm file.ts`
!`git push --force`
!`chmod -R 777 .`

Graceful Patterns

markdown
<injected_content>
@.claude/workspace/handoff.yaml
</injected_content>

If no handoff exists: Create new session

Current branch: !`git branch --show-current 2>/dev/null || echo "detached"`

PATTERN: Command Structure

Single-File Structure

Commands are single markdown files:

.claude/commands/folder-name.md

Or flat structure:

.claude/commands/command-name.md

Flat Structure

.claude/commands/analyze.md
.claude/commands/create.md
.claude/commands/verify.md

Nested Structure

.claude/commands/analysis/
├── diagnose.md
├── explore.md
└── reason.md

Command Scope

Scope Location Description
Project .claude/commands/ Command available in this project only
Personal ~/.claude/commands/ Command available in all projects

Command Components

Component Required? Notes
Frontmatter Yes YAML with description
## Quick Start Yes Scenario-based
Content Yes With @/! injection
<critical_constraint> Yes At bottom

What Commands Contain

Content Type Notes
Frontmatter Required First content
Quick Start Required Scenario-based
@ injection Optional Dynamic file content
! injection Optional Dynamic command output
<critical_constraint> Required At file bottom

What Commands Don't Contain

Excluded Reason
references/ folder Commands are single-file
SKILL.md Skills use this format
Progressive disclosure Commands load full content

Frontmatter Fields

Commands use minimal frontmatter - no name field (auto-derived from path):

yaml
---
description: "Brief description, non spoiling of the content. Use when {trigger condition + keywords + key sentences user might say that should lead the command to be triggered}. Not for {exclusions}."
argument-hint: "<identifier>"  # Optional: hint for positional args
context: fork  # Optional: for orchestration, see ## PATTERN: Thin Interface
---

All Frontmatter Fields

Field Required? Purpose
description Yes Auto-discovery, shown in slash menu
argument-hint No Placeholder for $1 arguments
context No fork for orchestration with result return
hooks No Event hooks configuration
disable-model-invocation No true for liaison commands (requires AskUserQuestion)

Example Frontmatter

yaml
---
description: "Refine skill content for quality and portability. Use when improving existing skills, fixing quality issues, or updating documentation. Includes pattern validation and anti-pattern detection. Not for creating new skills from scratch."
argument-hint: "<skill-name>"
hooks:
  PreToolUse:
    - matcher: "tool == \"Bash\" && tool_input.command matches \"rm\""
      type: prompt
      prompt: "About to run rm - confirm this is intentional."
---

Argument Handling

Syntax Description Example
$ARGUMENTS Everything after command /test authRun tests matching: auth
$1, $2 Positional arguments /fix 123 high → Issue #123, priority high

String Substitutions

Variable Replaces With
$ARGUMENTS All passed args (appended if missing)
$ARGUMENTS[N] Nth arg (0-based)
$N Shorthand for $ARGUMENTS[N]
${CLAUDE_SESSION_ID} Current session ID

Best Practices

  1. Discovery: Commands available via slash command menu
  2. Security: Limit allowed-tools to essentials when needed
  3. Organization: Use subdirectories for namespacing complex projects

Command Frontmatter

yaml
---
description: "Verb + object. Use when [condition]. Includes [features]. Not for [exclusions]."
---

Command Body

markdown
## Quick Start

**If you need X:** Do Y

## Core Content

[Content with @ and ! injection patterns]

<injected_content>
@path/to/file.yaml
</injected_content>

Commands vs Skills

Aspect Commands Skills
Structure Single file SKILL.md + references/
Injection @, ! supported Not supported
Frontmatter Required Required
References Optional references/ Extensive references/

PATTERN: Engine Separation

Commands SHOULD NOT contain complex logic. They should:

  1. Gather context (via @/!)
  2. Ask clarifying questions (if Liaison)
  3. Invoke the appropriate Skill

Anti-Pattern: Command with Logic

markdown
❌ Wrong: A 200-line "how-to" guide in a command
✅ Correct: 5-line context gatherer → invoke Skill

Command Responsibilities

Responsibility Description
Context Injection Use @/! to capture current state
Human Negotiation Use AskUserQuestion to clarify intent
Skill Invocation Delegate to Engine with compiled context

When to Move to Skill

Use a Skill instead of a Command when:

  • You need references/ for documentation
  • Logic exceeds 50 lines of content
  • Multiple patterns and anti-patterns needed
  • Complex decision trees required

Rule: If you need references/, you are building a Skill, not a Command.


PATTERN: Namespacing

Commands use folder hierarchy for namespacing. Path maps to colon syntax:

Folder Path Command Invocation
.claude/commands/meta/refine/rules.md /meta:refine:rules
.claude/commands/strategy/architect.md /strategy:architect
.claude/commands/meta/audit/all.md /meta:audit:all

Namespacing Rules

Rule Example
No name field in frontmatter Auto-derived from path
Only description is mandatory Frontmatter is minimal
argument-hint optional "<skill-name>"
Folders create namespace hierarchy meta/refine//meta:refine:

Flat vs Namespaced

Type Use When Example
Flat Core, high-frequency commands /continue, /handoff
Namespaced Related commands, complex domains /meta:refine:rules

Namespace Categories

Namespace Purpose Example Commands
meta/* Toolkit self-improvement refine, audit, reflect, capture
strategy/* Planning and execution architect, execute
handoff/* Session continuity resume, diagnostic
learning/* Knowledge capture archive, refine-rules

PATTERN: Thin Interface

Commands are "Skin" - thin interfaces that bind Reality to Knowledge Skills ("Brain").

Three Command Use-Cases

Use-Case Pattern Example
Context Gathering @ and ! injection Gather git state, file content
Liaison Work AskUserQuestion Clarify ambiguous intent
Delegation Skill(tool) invocation Call Knowledge Skill for logic

Thin Interface Rules

  1. Commands MUST provide at least one "Reality" source (@ or !)
  2. Commands SHOULD NOT contain complex logic - delegate to Skills
  3. Commands MUST NOT delegate to other commands (only to Skills)
  4. Skill chaining IS allowed when using context:forked in frontmatter

Context Forking (Orchestration)

When a command/skill must orchestrate subprocesses and receive their results:

Without context:forked:

markdown
---
description: "Call skill B."
---
1. Invoke `skill-b` skill.
2. [Skill A ends here - unreliable return]

Skill B runs but results don't reliably return to Skill A.

With context:forked:

yaml
---
description: "Call skill B with result return."
context: forked
---
markdown
1. Invoke `skill-b` skill.
2. [Skill B completes, result returns to Skill A]
3. Process skill B results...

How it works:

  • context: forked in frontmatter makes the component behave like a subagent
  • Results reliably return to the parent for analysis
  • Essential for: multi-step workflows, result aggregation, orchestration

Delegation Pattern

markdown
## Execution
1. Read the provided skill content.
2. Invoke `skill-development` skill.
3. Compare content against standards.
4. Apply refinements autonomously.

Reality Source Requirement

Do Don't
Use @ for current file state Assume static content
Use ! for runtime state Hardcode git status, etc.
Provide at least one injection Create pure logic commands

PATTERN: Argument Patterns

Dual-Mode Pattern

Commands can operate in two modes:

Mode Behavior Example
Implicit Infer from context /handoff:resume → scans handoffs
Explicit Use provided argument /handoff:resume session-x → loads specific

Argument Rules

Rule Example
$1 for unique identifiers only session-x, abc123
Not for flags/options $1 cannot be --verbose
Positional only No --flag value syntax

Example

markdown
$IF($1, Use the provided argument, Scan conversation for context and infer intent)

Argument Use Cases

Use Case Example
Session ID /handoff:resume session-x
File hash /ops:extract abc123
Project slug /strategy:create my-project

Valid Arguments

markdown
✅ Valid (identifiers only):
session-abc123  # session ID
hash-xyz789     # file hash
my-project      # project slug

Invalid Arguments

markdown
❌ Invalid (flags not allowed):
--verbose               # flag
output-format json      # flag with value
--max-results 10        # flag with value

PATTERN: Error Handling

@ Error Behavior

Scenario Result
File exists Content injected
File missing Empty string

! Error Behavior

Scenario Result
Command succeeds stdout injected
Command fails Empty string

ANTI-PATTERN: Common Mistakes

Anti-Pattern: Using @ in Skills

markdown
❌ Wrong (skill):
@injected_content>
@.claude/workspace/file.yaml
</injected_content>

✅ Correct (skill):
Read `references/configuration.md` to understand the schema.

Fix: Skills use semantic instructions, not @ injection.

Anti-Pattern: @ for Static Content

markdown
❌ Wrong:
@.claude/commands/static-template.md

✅ Correct:
[inline the template directly]

Fix: Use @ for dynamic content (changes between invocations), not static templates.

Anti-Pattern: No Error Handling

markdown
❌ Wrong:
Current branch: !`git branch --show-current`
[no fallback]

✅ Correct:
Current branch: !`git branch --show-current` (or detached HEAD)

Fix: Consider edge cases and provide context.

Anti-Pattern: $1 for Options

markdown
❌ Wrong:
--verbose               # using flags
output-format           # option names

✅ Correct:
session-abc123          # identifier only

Fix: $1 is for IDs, slugs, hashes only—not flags or options.

Anti-Pattern: Command with References/

❌ Wrong:
.claude/commands/example/
├── command.md
└── references/
    └── detail.md

✅ Correct:
.claude/commands/example.md  # Single file

Or if needed:
.claude/skills/example/
├── SKILL.md
└── references/

Anti-Pattern: Wrong Extension

❌ Wrong:
.claude/commands/command.txt
.claude/commands/command

✅ Correct:
.claude/commands/command.md

Anti-Pattern: Inconsistent Naming

❌ Wrong:
.claude/commands/create-prompt.md
.claude/commands/run_prompt.md
.claude/commands/runprompt.md

✅ Correct:
.claude/commands/create-prompt.md
.claude/commands/run-prompt.md
.claude/commands/run-prompt.md  # Consistent kebab-case

Anti-Pattern: Complex Logic in !

❌ Wrong:
!`for f in *.ts; do echo $f; done`

✅ Correct:
Use bash with proper escaping or inline differently

EDGE: Special Cases

Edge Case: No @ or !

Commands that don't need dynamic content:

✅ Valid:
.claude/commands/simple.md
[no @ or ! injection]

Content is static, no dynamic state needed.

Edge Case: Multiple Injections

Commands with complex injection:

markdown
<injected_content>
@.claude/workspace/handoff.yaml
</injected_content>

Current branch: !`git branch --show-current`
Modified files: !`git status --porcelain`

Edge Case: Nested Wrappers

markdown
<injected_content>
@main-file.yaml

<details>

<injected_content>
@supporting.yaml
</injected_content>

</details>
</injected_content>

Edge Case: Conditional Injection

markdown
$IF($1, Use explicit: $1, Infer from context)

Edge Case: Command Grouping

Related commands in folder:

.claude/commands/handoff/
├── create.md
├── diagnostic.md
├── resume.md
└── create-full.md

Edge Case: Single Command

No folder needed for single command:

.claude/commands/simple.md

Edge Case: Many Commands

Use folders for organization:

.claude/commands/
├── analysis/
├── build/
├── handoff/
├── learning/
├── ops/
├── planning/
├── qa/
├── strategy/
└── sync/

Edge Case: Optional Injection

Commands with optional @/!:

✅ Valid:
!`git branch --show-current` (or detached)

<injected_content>
@optional-file.yaml
</injected_content>
(if exists)

Edge Case: Multiple Commands

Commands with multiple ! patterns:

markdown
Branch: !`git branch --show-current`
Status: !`git status --short`
Last commit: !`git log -1 --oneline`

Edge Case: Conditional Arguments

markdown
$IF($1, Use: $1, Infer from context)

Validation Checklist

Before claiming command authoring complete:

Structure:

  • Single markdown file in .claude/commands/
  • File has .md extension
  • Valid YAML frontmatter with description

Injection Patterns:

  • @path for dynamic file content (not in skills)
  • !command for runtime state capture
  • Wrapped in <injected_content> for semantic grouping
  • Paths are absolute or relative to workspace root

Error Handling:

  • Missing files handled gracefully (empty result)
  • Command failures handled gracefully

Argument Handling:

  • $1 used only for identifiers (IDs, slugs, hashes)
  • No flags or modes as $1 arguments

Content:

  • Follows What-When-Not-Includes format in description
  • Imperative/infinitive voice throughout
  • No references/ folder (commands are single-file)

Common Mistakes to Avoid

Mistake 1: Using @ or ! in Skills

Wrong:

markdown
# My Skill
Current branch: !`git branch --show-current`

Correct: Skills use semantic instructions:

markdown
# My Skill
Determine the current Git branch using standard git commands.

Mistake 2: Using $1 for Flags

Wrong:

yaml
$1: --verbose

Correct:

yaml
$1: session-id  # Only for identifiers

Mistake 3: Missing Frontmatter

Wrong:

markdown
# My Command
description: Does something useful

Correct:

yaml
---
name: my-command
description: "Verb + object. Use when [condition]. Includes [features]. Not for [exclusions]."
---

Mistake 4: Complex Bash in !

Wrong:

markdown
!`for f in $(ls *.json); do cat $f | jq '.name'; done`

Correct:

markdown
!`find . -name "*.json" -exec jq -r '.name' {} \;`

Mistake 5: Missing Error Handling

Wrong:

markdown
@/path/to/mandatory/file.yaml

(If file doesn't exist, command fails)

Correct:

markdown
@/path/to/file.yaml

(gracefully handles missing files)


---

## Best Practices Summary

✅ **DO:**
- Use @path for dynamic file content that changes between sessions
- Use !command for runtime state (git status, CI results)
- Wrap injections in `<injected_content>` for semantic grouping
- Handle missing files gracefully
- Use $1 only for unique identifiers (IDs, slugs)
- Follow single-file structure (no references/ folder)
- Provide at least one "Reality" source (@ or !)
- Delegate complex logic to Skills

❌ **DON'T:**
- Use @ or ! in skills (skills use semantic instructions)
- Use $1 for flags, modes, or non-identifier values
- Create multi-file commands (use skills instead)
- Skip .md extension
- Skip frontmatter description
- Use complex bash in ! without proper escaping
- Delegate from command to another command (delegate to Skills only)

---

## Recognition Questions

| Question                                | Recognition |
| :-------------------------------------- | :---------- |
| Does @ inject dynamic file content?     | Yes, content changes between sessions |
| Does ! execute for runtime state?       | Yes, captures git status, CI, etc.    |
| Does command use single-file structure? | Yes, no references/ folder            |
| Does $1 use identifier-only pattern?    | Yes, IDs/slugs, not flags             |
| Is XML minimal?                         | Only injected_content wrapper         |
| Does command delegate to Skill?         | Yes, if logic exceeds ~50 lines       |

---

## Validation Checklist

Before claiming command authoring complete:

- [ ] @ injections provide dynamic content
- [ ] ! executions capture runtime state
- [ ] Single-file structure, no references/ folder
- [ ] $1 uses identifier-only pattern
- [ ] XML minimal (only injected_content wrapper)
- [ ] Complex logic delegated to skills

---

<critical_constraint>
**Command-Only Injection:**

1. Skills MUST NEVER use `@` or `!` syntax
2. Commands MAY use `@` and `!` freely
3. Use `<injected_content>` wrapper for semantic grouping
4. All paths MUST be absolute or relative to workspace root

**Namespacing:**

- Commands use folder hierarchy for namespacing
- Path `.claude/commands/meta/refine/rules.md` → `/meta:refine:rules`
- No `name` field in frontmatter (auto-derived from path)
- Only `description` is mandatory in frontmatter

**Thin Interface:**

- Commands are "Skin" that bind Reality to Knowledge Skills ("Brain")
- Commands MUST provide at least one "Reality" source (`@` or `!`)
- Commands MUST NOT delegate to other commands (only to Skills)
- Skill chaining requires `context: forked` in frontmatter for result return
- Without `context: forked`, subprocess results don't reliably return
- Commands SHOULD NOT contain complex logic (delegate to Skills)

**Engine vs Interface:**

- Commands are Interfaces that bind Skills to Reality
- Commands SHOULD NOT contain complex logic (delegate to Skills)
- If you need references/, you are building a Skill, not a Command

@ and ! are command-only features.

Skills MUST use semantic instructions, not injection.

Commands MUST handle missing files gracefully.

Commands MUST be single markdown files.

Commands MUST use .md extension.

Commands MUST have frontmatter with description.
</critical_constraint>

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results