Claude Academy
intermediate16 min

Advanced Custom Commands

Learning Objectives

  • Use shell injection with !`command` syntax in command files
  • Build deploy pipelines as slash commands
  • Add model overrides to command frontmatter
  • Create context-aware commands that read live data

Beyond Simple Commands

In the previous lesson, you built straightforward custom commands — markdown files with instructions and $ARGUMENTS. Now we'll level up with two powerful features: shell injection and model overrides.

These transform commands from static templates into dynamic, context-aware automation pipelines.

Shell Injection: !command

The !\`command\ syntax runs a shell command when the slash command is invoked and replaces itself with the output. Claude sees the result, not the command.

Basic Example

.claude/commands/status.md:
---

description: "Summarize the current project state"


Here's the current state of the project:

Git Status

!git status

Recent Commits

!git log --oneline -10

Current Branch

!git branch --show-current

Based on this information, give me a brief summary of:

1. What's been worked on recently

2. What's currently in progress (unstaged changes)

3. Any concerns (uncommitted work, diverged branches)

When you type /status, Claude sees the actual output of those commands — the real files that changed, the real commit messages, the real branch name. The command is dynamic, reflecting the current state every time it's invoked.

Live Context Injection

Shell injection is most powerful when it provides context Claude needs to make decisions:

.claude/commands/deploy.md:
---

description: "Run the deploy checklist for a target environment"

argument-hint: "staging|production"


Deploy to $ARGUMENTS environment.

Current Context

  • Branch: !git branch --show-current
  • Last commit: !git log --oneline -1
  • Uncommitted changes: !git status --short
  • Test status: !pnpm test --run 2>&1 | tail -5

Deploy Checklist

1. Verify branch: We should be on main for production deploys,

develop for staging. Check the current branch above.

2. Verify clean working tree: There should be no uncommitted changes.

If there are changes listed above, abort and commit first.

3. Verify tests pass: Check the test output above. If tests fail,

abort and fix them first.

4. Build: Run pnpm build and verify it succeeds.

5. Tag (production only): Create a version tag.

Read package.json for the current version.

6. Push: Push the branch and tags.

7. Deploy: Run the appropriate deploy command:

- staging: pnpm deploy:staging

- production: pnpm deploy:production

8. Verify: After deploy, run pnpm health-check:$ARGUMENTS

If any step fails, stop immediately and report the issue.

Usage:

/deploy staging

/deploy production

Claude sees the real branch, the real last commit, the real uncommitted changes, and the real test results. It makes deployment decisions based on actual data, not assumptions.

Model Overrides in Commands

Some commands need more reasoning power than others. A simple renaming command works fine with Sonnet. A complex security review needs Opus.

Add model to the frontmatter:

---

description: "Deep security review of the current branch"

model: opus

---

When to Override Models

| Command Type | Recommended Model |

|---|---|

| Security review, architecture analysis | opus |

| Code generation, testing, general review | sonnet |

| Simple formatting, renaming, boilerplate | haiku |

Example: Tiered Review System

.claude/commands/review-quick.md:
---

description: "Quick code review (Sonnet)"

model: sonnet


Quick review of changes on the current branch:

!git diff main --stat

Focus on obvious issues only: syntax errors, missing imports,

broken tests. Don't deep-dive into architecture.

.claude/commands/review-deep.md:
---

description: "Deep security and architecture review (Opus)"

model: opus


Comprehensive review of all changes on the current branch:

Changed Files

!git diff main --stat

Full Diff

!git diff main

Review for:

1. Security vulnerabilities (injection, auth bypass, data exposure)

2. Architecture violations (check CLAUDE.md rules)

3. Performance issues (N+1 queries, missing indexes)

4. Race conditions and concurrency issues

5. Error handling completeness

6. Test coverage gaps

For each issue, provide severity, location, and fix.

Two commands: /review-quick for daily reviews (fast, cheap), /review-deep for pre-release reviews (thorough, uses Opus).

Advanced Patterns

Command Chaining

Build commands that reference other commands or build on each other:

.claude/commands/release.md:
---

description: "Full release workflow"

argument-hint: "version (e.g., 2.3.0)"

model: opus


Execute the full release workflow for version $ARGUMENTS:

Pre-Release State

  • Current version: !node -p "require('./package.json').version"
  • Branch: !git branch --show-current
  • Unreleased commits: !git log $(git describe --tags --abbrev=0)..HEAD --oneline

Steps

1. Verify we're on the main branch

2. Verify all tests pass: pnpm test

3. Verify the build succeeds: pnpm build

4. Update version in package.json to $ARGUMENTS

5. Generate changelog from commits since last tag

6. Create a commit: "chore: release v$ARGUMENTS"

7. Tag: git tag v$ARGUMENTS

8. Push branch and tags

9. Create a GitHub release with the changelog

Execute each step sequentially. If any step fails, stop and report.

Database Migration Command

.claude/commands/migrate.md:
---

description: "Create and apply a database migration"

argument-hint: "migration-name"


Create a Prisma migration named $ARGUMENTS.

Current Schema State

!npx prisma migrate status 2>&1

Steps

1. Review the current schema changes in prisma/schema.prisma

2. Create the migration: npx prisma migrate dev --name $ARGUMENTS

3. Review the generated SQL in prisma/migrations/

4. Verify the migration is reversible

5. Run npx prisma generate to update the client

6. Update any affected repository files in src/repos/

7. Run tests to verify nothing broke

PR Description Generator

.claude/commands/pr-desc.md:
---

description: "Generate a PR description from the current branch"


Generate a pull request description for the current branch.

Context

  • Branch: !git branch --show-current
  • Commits: !git log main..HEAD --oneline
  • Changed files: !git diff main --stat

Template

Write a PR description with:

1. Summary: 1-2 sentences about what this PR does

2. Changes: Bulleted list of key changes (from the commits)

3. Testing: How to test these changes

4. Screenshots: (placeholder if UI changes)

5. Checklist:

- [ ] Tests added/updated

- [ ] Documentation updated

- [ ] No breaking changes (or documented)

Debugging Commands

If a command isn't working as expected, check:

1. File location: Is it in .claude/commands/ (project) or ~/.claude/commands/ (global)?

2. File extension: Must be .md

3. Frontmatter syntax: Valid YAML between --- markers

4. Shell injection: The command between backticks must be valid shell

5. $ARGUMENTS: Only works if the user provides arguments

Key Takeaway

Advanced commands use shell injection (!\command\`) to inject live context — current branch, changed files, test results — into the command prompt. Model overrides in frontmatter let you assign the right model to each command. Combined with $ARGUMENTS`, these features create powerful, context-aware automation: deploy pipelines, release workflows, database migrations, and PR generators that work with real data, not assumptions.