Custom Commands, Hooks, and Subagents: What Each One Is For
Claude Code ships with three separate ways to extend how it behaves: custom slash commands, hooks, and subagents.
They get grouped together because they all live under the same "customize Claude Code" umbrella, and because a real project usually ends up using all three at once.
But they solve different problems, run at different points in the workflow, and are configured in completely different ways.
Mixing them up is the single most common source of confusion for a team setting up Claude Code for the first time.
Summary
- Core Idea: a custom command is a reusable prompt, a hook is an automatic shell trigger, and a subagent is an isolated Claude instance with its own context and tools.
- Why It Matters: picking the wrong extension point for a job either fails outright (a hook cannot "think") or wastes effort (a subagent for something a one-line command would do).
- Key Concepts: slash command, frontmatter, prompt body, lifecycle event, PreToolUse, PostToolUse, Stop, isolated context, scoped tool access.
- When to Use: commands for repeatable requests you type often, hooks for anything that must happen deterministically outside Claude's judgment, subagents for work that needs its own context window or a narrower toolset.
- Limitations / Trade-offs: commands still consume the main session's context, hooks cannot reason (they only run shell logic), and subagents add latency and lose access to the parent's running context.
- Related Topics: slash command frontmatter, PostToolUse automation, PreToolUse blocking, parallel subagent research.
Foundations
Think of the three extension points as answers to three different questions.
Custom slash commands answer "how do I stop retyping the same request?"
A command is a markdown file with a frontmatter header and a prompt body, stored in a project or user commands directory.
Typing /review-pr sends that file's prompt into the current conversation exactly as if you had typed it yourself.
Hooks answer "how do I make something happen every time, without asking Claude to remember to do it?"
A hook is a shell command registered against a lifecycle event, such as before a tool runs or after a file edit completes.
The harness runs the hook directly. Claude does not decide whether the hook fires; the event firing is what triggers it.
Subagents answer "how do I give a piece of work its own clean slate?"
A subagent is a separate Claude instance, spawned by the main session, with its own context window and its own list of permitted tools.
It does the assigned work, then reports a summary back to the session that spawned it, without ever having seen everything else in that session's history.
A useful analogy: a command is a saved macro, a hook is a tripwire, and a subagent is a coworker you hand a sealed folder of instructions.
Mechanics & Interactions
The three extension points differ most clearly in who or what decides they run.
A command only runs when a user (or another prompt) explicitly invokes it by name. Nothing fires on its own.
A hook runs automatically whenever its registered event occurs, regardless of which command or prompt triggered that event. It has no awareness of intent, only of the event payload it receives.
A subagent runs when the parent session's Claude explicitly spawns one, typically because a task is large, independent, or would otherwise flood the main context with intermediate detail.
These three also differ in what they can see and touch.
A command's prompt body becomes part of the current conversation, so it shares the main session's full context and its full tool access.
A hook typically runs a plain shell script or CLI command; it has no model reasoning of its own; it just executes and returns an exit status.
A subagent gets an isolated context window seeded only with what the parent chooses to hand it, and a tool list that can be scoped down from the parent's own permissions.
# A hook does not "understand" the edit; it only reacts to the event payload.
# This is a PostToolUse hook entry in settings.json, conceptually:
{
"PostToolUse": [
{ "matcher": "Edit", "hooks": [{ "type": "command", "command": "npx prettier --write \"$FILE_PATH\"" }] }
]
}That snippet is a lifecycle wiring, not a prompt. Nothing in it asks Claude to decide whether to format the file; formatting simply happens every time an edit event fires.
Commands and subagents, by contrast, both route through the model, which is why both can reason, ask follow-up questions internally, and produce judgment calls that a hook never could.
Advanced Considerations & Applications
In practice the three extension points are rarely used in isolation. A command can itself instruct Claude to spawn several subagents. A PreToolUse hook can block one of those subagents' edits just as easily as it blocks the main session's. The lifecycle events a hook listens for do not care which layer of the system generated the tool call.
This composability is also where teams get into trouble. A command that always spawns three subagents for a task that only needed one wastes latency and tokens. A hook written to "help" by auto-committing on every Stop event can silently commit half-finished work if it fires on a subagent's Stop, not just the main session's. Understanding the boundaries in this article is what prevents those mistakes downstream.
| Extension Point | Triggered By | Runs Where | Best Fit |
|---|---|---|---|
| Custom slash command | Explicit /name invocation | Main session's context | Repeatable, reusable requests |
| Hook | A registered lifecycle event | Shell, outside the model | Deterministic side effects: format, log, block |
| Subagent | Claude spawning it mid-task | Its own isolated context | Large, independent, or parallel work |
There is also a governance dimension. Commands live in version control as plain markdown, so a team can review and share them like any other source file. Hooks live in settings.json and, because they run arbitrary shell commands, deserve the same scrutiny as any other executable checked into a repo. Subagent definitions can restrict tool access per role, which is a real security boundary, not just an organizational convenience, since a subagent scoped to read-only tools cannot edit files even if the prompt tries to talk it into doing so.
Common Misconceptions
- "A hook is just a command that runs itself." A hook has no prompt and no model reasoning attached to it; it is a shell trigger wired to an event, closer to a git pre-commit hook than to a slash command.
- "Subagents share the main session's context to save tokens." The opposite is true; isolation is the entire point, and a subagent only receives what the parent explicitly includes in its task prompt.
- "Commands can block or veto an action." Only hooks (specifically PreToolUse) can reject a tool call before it happens; a command can only shape what gets requested in the first place.
- "Any of the three can replace the others." Each covers a different mechanism (invocation, automation, isolation); a workflow that truly needs deterministic blocking will not get it from a command no matter how carefully worded the prompt is.
FAQs
What is the simplest way to remember the difference between the three?
- Command: something you ask for by name.
- Hook: something that happens automatically on an event.
- Subagent: someone else who does a piece of work in their own space.
Can a custom slash command spawn a subagent?
Yes. A command's prompt body can instruct Claude to delegate part of the task to one or more subagents, the same way a typed request could.
Do hooks require Claude to be "thinking" when they run?
No. Hooks are shell commands executed by the harness in response to an event; they run independently of whatever Claude is reasoning about at that moment.
Why would I use a subagent instead of just asking in the main session?
To keep the main session's context window from filling up with intermediate research or exploration detail that only matters for one subtask, not for the rest of the conversation.
Can a hook see what Claude is about to do before it happens?
Yes, for PreToolUse hooks specifically. They receive the proposed tool call as input and can approve, modify the outcome, or block it before the tool ever runs.
Are subagents and the main Claude Code session running different models?
Not necessarily. A subagent can be configured to use the same model as the parent session or a different one; the distinguishing feature is the isolated context and tool scope, not the model choice.
Where do custom commands live on disk?
As markdown files with a frontmatter header and a prompt body, in a commands directory scoped to the project or to the user, so they can be version-controlled alongside the rest of a repo.
Is a hook the right tool for "always run the linter after every edit"?
Yes. That is a deterministic, unconditional side effect tied to an event (a file edit), which is exactly what a PostToolUse hook is designed for.
Is a hook the right tool for "decide whether this refactor is a good idea"?
No. That requires judgment, which only a command's prompt or a subagent's reasoning can provide; a hook can only run fixed shell logic against the event it receives.
What happens to a subagent's context once it finishes?
It reports a summary back to the parent session and its full context is discarded; the parent never sees the subagent's raw intermediate exploration, only what it chose to report.
Can multiple hooks fire on the same event?
Yes. A single lifecycle event, such as PostToolUse, can have multiple hook commands registered against it, and they run in the order they are configured.
Do I need all three extension points to use Claude Code effectively?
No. Many projects use only custom commands for a long time before a real need for deterministic automation (hooks) or context isolation (subagents) shows up.
Related
- Custom Commands & Subagents Basics - a hands-on first command and first subagent.
- Writing Your First Custom Slash Command with Markdown Frontmatter - the file format behind every command.
- Common Hook Events and When to Use Each One - the full set of lifecycle events hooks can attach to.
- How Subagents Get Their Own Context and Tools - the isolation mechanism explained in depth.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5. Model names, pricing, and product features move quickly - verify current specifics at platform.claude.com/docs before relying on them.