Claude Code has three ways to customize it, and their names don't make the differences obvious. We counted about 4,100 posts on subagents, hooks and slash commands, and about 3,200 on agent skills and SKILL.md, in our X sample, and most of the questions were some version of "which one do I use?"
Here's the short version, then an example of each.
The one-table answer
| Skill | Subagent | Hook | |
|---|---|---|---|
| What it is | A SKILL.md file of instructions | A separate worker with its own context | A script or command run at set points |
| Who triggers it | Claude (when relevant) or you (/name) |
Claude delegates to it, or you ask for it | Claude Code automatically, on an event |
| Is it guaranteed? | No, it's guidance | No, Claude decides | Yes, it always runs when the event matches |
| Best for | Repeatable procedures and checklists | Noisy side tasks, like search, logs and reviews | Hard rules, formatting, blocking risky commands |
| Lives in | .claude/skills/<name>/SKILL.md |
.claude/agents/<name>.md |
.claude/settings.json |
The rule of thumb: skills teach, subagents delegate, hooks enforce.
Skills: "here's how we do X"
Create a skill when you keep pasting the same instructions, checklist or multi-step procedure into chat. That's straight from the docs.
<!-- .claude/skills/pre-deploy/SKILL.md -->
---
name: pre-deploy
description: Checklist to run before deploying. Use when the user says deploy, ship, or release.
---
1. Run the test suite and stop if anything fails.
2. Check for secrets in the diff (API keys, .env values).
3. Confirm database migrations are reversible.
4. Summarize what will change in production.
How it loads: Claude Code keeps every skill's name and description in context so Claude knows what's available, and loads the full content only when the skill is invoked. So a good description matters. It's how Claude decides to use the skill.
Two things worth knowing:
- Old custom commands have merged into skills.
.claude/commands/deploy.mdand.claude/skills/deploy/SKILL.mdboth create/deploy. - Add
disable-model-invocation: trueto the frontmatter if only you should be able to trigger it, e.g. a real deploy.
Claude Code skills follow the open Agent Skills standard, so they work in other tools too. Start with our guide to writing your first skill, or grab the pre-deploy check skill and starter skills pack.
Subagents: "go do this and report back"
Per the docs, each subagent "runs in its own context window with a custom system prompt, specific tool access, and independent permissions". Use one when a side task would flood your main conversation with search results, logs or file contents you won't need again. The subagent does the messy work and returns only a summary.
<!-- .claude/agents/code-improver.md -->
---
name: code-improver
description: Scans files and suggests improvements for readability, performance, and best practices. Use after writing or modifying code.
tools: Read, Grep, Glob
model: sonnet
---
You are a code improvement specialist. For each issue you find, explain the problem, show the current code, and provide an improved version.
That's adapted from the docs' own example. tools: Read, Grep, Glob makes it read-only. Put it in ~/.claude/agents/ to use it in every project, or .claude/agents/ for one project. You can also describe the subagent you want in plain English and Claude will write the file.
Cost note: subagents send their own requests, which count toward the same usage limits as your main session. Our subagents starter has ready-made ones.
Hooks: "always do this, no exceptions"
Skills and subagents rely on Claude choosing to use them. Hooks don't. They run on lifecycle events:
- Per session:
SessionStart,SessionEnd - Per turn:
UserPromptSubmit,Stop - Per tool call:
PreToolUse,PostToolUse
The docs' example blocks destructive shell commands. In .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
}
}
And the script, which you make executable with chmod +x:
#!/bin/bash
# .claude/hooks/block-rm.sh
COMMAND=$(jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q 'rm -rf'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
else
exit 0
fi
A PreToolUse hook can also block a call by exiting with code 2. A PostToolUse hook can't block, because the tool already ran, but it can show feedback to Claude. That makes it a good spot for "run the formatter after every edit".
Where you put the hook sets its scope: ~/.claude/settings.json (all your projects), .claude/settings.json (this project, shareable via git) or .claude/settings.local.json (this project, not committed). Our hooks starter and safe settings are good starting points.
Hooks run real commands on your machine. Read any hook before you add it, especially from someone else's repo.
New: record a skill instead of writing one
Anthropic's help center now describes Record a skill in Cowork in Claude for Mac:
- Who: Pro, Max and Team plans. Not in chat, not on Windows, not on Free or Enterprise.
- How: click + → Record a skill, or go to Customize > Skills > Add > Record your screen. You'll need to grant macOS Accessibility and Screen Recording permissions.
- What it captures: your screen, clicks, typing and voice narration. Claude then proposes a skill for you to review before saving.
- Warning from Anthropic: don't show passwords, keys or other sensitive information while recording.
It's handy for procedures that are easier to show than describe, like a weekly report you assemble across three apps.
Which should you use?
- "I keep explaining the same process" → skill
- "This task makes my chat messy" → subagent
- "This must happen every time, or must never happen" → hook
Most solid setups use all three. A CLAUDE.md holds project facts, skills hold procedures, subagents do side work, and hooks guard the edges. For the wider safety picture, see running coding agents safely.






