Advanced Claude Code: Subagents, Hooks, and Slash Commands (2026 Power-User Guide) — Cesar Ayala
← All posts

Advanced Claude Code: Subagents, Hooks, and Slash Commands (2026 Power-User Guide)

After you install Claude Code, four features turn it from a helpful assistant into a configured teammate: CLAUDE.md plus auto memory steers every session; subagents run in their own context window with scoped tools and a cheaper model like Haiku to control cost; hooks are shell commands at lifecycle points that can block a tool; and skills or slash commands package repeatable workflows.

Beyond the basics: four features that make Claude Code a teammate

After you install Claude Code, four features turn it from a helpful assistant into a configured teammate. CLAUDE.md plus auto memory steers every session with your standards and decisions. Subagents run in their own context window with scoped tools and a cheaper model like Haiku to control cost. Hooks are shell commands that fire at lifecycle points and can block a tool before it runs. And skills or slash commands package repeatable workflows your whole team shares. This is the power-user layer that sits on top of the getting-started basics — if you have not installed it yet, start there.

Everything below assumes Claude Code is running in a project (curl -fsSL https://claude.ai/install.sh | bash, then claude). Note that Claude Code requires a paid or Console account — the free Claude.ai plan does not include it.

CLAUDE.md + memory
Subagents
Hooks
Skills / slash commands

Steer every session with CLAUDE.md and auto memory

CLAUDE.md is a markdown file at your project root that Claude Code reads at the start of every session. Treat it as the onboarding doc you would give a new engineer: coding standards, architecture decisions, preferred libraries, and review checklists. Because it loads every time, it is the highest-leverage file in the repo.

# CLAUDE.md

## Stack
- Astro + TypeScript. No React unless a component needs client state.
- Package manager: pnpm. Never npm.

## Conventions
- All money is stored in cents (integer). Never floats.
- Tests live next to source as *.test.ts.

## Review checklist
- No secrets in code. Read from env.
- Public API changes require a CHANGELOG entry.

On top of that, Claude Code builds auto memory across sessions — it remembers things like build commands and debugging insights without you writing anything down. You can also split rules into focused files under .claude/rules/*.md so a large project does not turn CLAUDE.md into a wall of text. Full details are in the memory docs.

Subagents: own context window, scoped tools, and cheaper models

A subagent is a specialized assistant that runs in its own context window with a custom system prompt, specific tool access, and independent permissions. This matters for four concrete reasons:

  • Preserve context. Exploration, logs, and long file dumps stay in the subagent’s window and never pollute your main conversation.
  • Enforce tool constraints. A reviewer subagent can be given read-only tools and literally cannot edit files.
  • Reuse and specialize. Drop a subagent in ~/.claude/agents/ and it works across every project.
  • Control cost. Route a high-volume, low-stakes subagent to a cheaper model like Haiku instead of burning your main model on it.

Do not confuse subagents with two related concepts: background agents are many parallel sessions, and agent teams are sessions that talk to each other. A subagent is a scoped worker your main session delegates to.

nameHow you and Claude refer to it
descriptionWhen Claude auto-delegates
toolsWhich tools it may use
modelCost lever — e.g. Haiku

Write a subagent: name, description, tools, and model

You define a subagent as a markdown file with YAML frontmatter under .claude/agents/ (project-scoped, committable) or ~/.claude/agents/ (available to all your projects). The frontmatter carries name, description, tools, and model; the body is the subagent’s system prompt.

---
name: pr-reviewer
description: Reviews a diff for bugs, missing tests, and security issues. Use PROACTIVELY before any commit or push.
tools: Read, Grep, Glob, Bash
model: haiku
---

You are a senior code reviewer. Given a diff:
1. Read the changed files for context.
2. Flag correctness bugs, missing edge cases, and secrets in code.
3. Rank findings most-severe first. Do NOT edit files — report only.

Two things do the heavy lifting here. The tools line omits Edit and Write, so this reviewer physically cannot modify code — a real guardrail, not a polite request. And model: haiku routes the whole review to a cheaper model, which is exactly the kind of high-frequency task where you want to save spend. If you want more depth on choosing models by cost and quality, see tuning cost, quality, effort, and batch.

How Claude delegates automatically (and how to route cost to Haiku)

You rarely invoke a subagent by hand. Claude reads each subagent’s description and decides when to delegate on its own — which is why the description should say what it does and when to use it, ideally with a cue like “Use PROACTIVELY.” When you commit, the pr-reviewer above gets pulled in without you asking.

The cost story is the reason power users lean on this. Your main session might run a strong model, but a subagent that greps logs, summarizes test output, or does a first-pass review does not need that horsepower. Pin those to Haiku:

Main model — architecture, tricky editskeep
Reviewer subagent → Haikucheap
Log-summarizer subagent → Haikucheap

The result: expensive tokens go to work that needs judgment, and the mechanical work runs cheap in an isolated window. The subagents docs cover the full frontmatter reference.

Hooks: run shell commands at Claude Code’s lifecycle points

Hooks are user-defined shell commands (they can also be HTTP calls or LLM prompts) that run automatically at lifecycle points. Where a subagent is who does the work, a hook is policy — deterministic automation that fires whether or not the model thinks to do it. They live in JSON settings at three scopes:

  • ~/.claude/settings.json — applies to all your projects.
  • .claude/settings.json — project-scoped and committable, so your team shares it.
  • .claude/settings.local.json — gitignored, for personal overrides.

The events you will reach for most are PreToolUse (fires before a tool runs and can block it) and PostToolUse (fires after a tool succeeds). Others include UserPromptSubmit, SessionStart, SessionEnd, Stop, SubagentStart, SubagentStop, PreCompact, PostCompact, and Notification.

The settings.json shape: event, matcher, and command

Every hook nests under an event, filters with a matcher, and runs a command:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "./scripts/format.sh" }
        ]
      }
    ]
  }
}

The matcher is a filter on the tool name — "Edit|Write" catches both file-writing tools. A command hook communicates back to Claude Code through its exit code: 0 means success, 2 is a blocking error where stderr is shown to Claude, and any other non-zero code is a non-blocking error. That exit-code contract is what makes PreToolUse a real gate.

  1. Tool about to runClaude requests Bash / Edit / Write
  2. Matcher checksDoes the tool name match?
  3. Hook command runsYour shell script inspects the call
  4. Exit code decides0 = allow, 2 = block (stderr to Claude)

Hook example 1: auto-format on PostToolUse Edit|Write

The most common hook keeps your tree clean by formatting anything Claude writes. Use PostToolUse with a "matcher": "Edit|Write" so it fires after every file change:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "pnpm exec prettier --write ." }
        ]
      }
    ]
  }
}

Now Claude never leaves unformatted code behind, and you never spend a review comment on whitespace. Because this lives in the committable .claude/settings.json, every teammate gets the same behavior for free.

Hook example 2: block rm -rf on PreToolUse Bash (exit code 2)

The guardrail hooks are where PreToolUse earns its place. Here we intercept destructive Bash commands before they run and block them with exit code 2:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "if": "Bash(rm *)",
        "hooks": [
          { "type": "command", "command": "echo 'Blocked: destructive rm is not allowed.' >&2; exit 2" }
        ]
      }
    ]
  }
}

Because the command exits 2, Claude Code blocks the tool call and shows the stderr message back to the model, which then picks a safer path. This is deterministic — it does not depend on the model deciding to be careful. The full event and exit-code reference is in the hooks docs.

Skills and slash commands: package /review-pr for your team

Once you have subagents and hooks, skills and slash commands are how you package a repeatable workflow behind a single name. Instead of retyping a ten-step review or deploy prompt, your team runs /review-pr or /deploy-staging and gets the exact same sequence every time. These are shareable, committed to the repo, and self-documenting — new engineers discover them by typing /.

A slash command can chain everything above: invoke the pr-reviewer subagent, run tests, and check the diff against your CLAUDE.md checklist. That composition — memory plus subagents plus hooks plus commands — is what turns Claude Code into a teammate that already knows how your team ships. To run this in CI or headless, see Claude Code in CI / headless.

Stay in control: permissions and plan mode

Automation is only safe when you keep the final say. Two features give you that. Plan mode lets Claude research and propose a plan that you review before it touches anything. Permissions gate what runs, using rules with a tool-and-pattern syntax:

{
  "permissions": {
    "allow": ["Bash(git *)", "Edit(src/**/*.ts)"],
    "deny": ["Bash(curl *)"]
  }
}

A rule like Bash(git *) allows git commands while a deny on curl keeps data from leaving your machine. Paired with the PreToolUse guardrail hook above, you get both a static policy and a dynamic gate. For a fuller comparison of how this control model differs from other tools, see Claude Code vs Cursor.

Connect your own tools with MCP

The Model Context Protocol (MCP) connects Claude Code to external tools and data — Google Drive, Jira, Slack, or your own internal services. A subagent scoped to just your MCP database tools becomes a safe, specialized data assistant. MCP is a big topic with real security implications, so start with connecting an agent to your data and then securing MCP servers before you expose anything sensitive. If you are building agents programmatically rather than through the CLI, the Claude API guide goes deeper.

One config, every surface: terminal, IDE, Desktop, and web

Here is the payoff for doing this work once: CLAUDE.md, your settings.json hooks and permissions, and your MCP servers all carry across surfaces. Configure them in the terminal and they follow you into the IDE, Claude Desktop, and the web. You are not maintaining four separate setups — you are configuring one teammate that shows up everywhere you work.

Your checklist to configure Claude Code as a teammate

Work through these in order and you will have a real configured setup rather than a bare assistant:

  • Write CLAUDE.md with your stack, conventions, and a review checklist; split overflow into .claude/rules/*.md.
  • Add a subagent in .claude/agents/ with scoped tools and model: haiku for high-frequency work.
  • Write a PostToolUse Edit|Write hook to auto-format everything Claude writes.
  • Write a PreToolUse Bash hook that exits 2 to block destructive commands.
  • Package a slash command like /review-pr so the workflow is one keystroke for the whole team.
  • Set permissions and use plan mode so you review before Claude acts.
  • Wire up MCP for your data — securely.

Do all seven and Claude Code stops being something you prompt and starts being something that already knows how your team ships. The whole AI agents hub goes deeper on each layer.