Skip to content

Building with Intelligence: Subagents, Hooks, and Output Styles

Building with Intelligence: Subagents, Hooks, and Output Styles

Section titled “Building with Intelligence: Subagents, Hooks, and Output Styles”

Beyond simple chat, Claude Code offers a powerful toolkit for building robust, intelligent automations. This is where you graduate from being a user to a creator. In this chapter, we’ll explore the three fundamental building blocks that allow you to customize, extend, and control Claude Code’s behavior: Subagents, Hooks, and Output Styles.

Imagine you’re managing a software project. You wouldn’t ask a single developer to be an expert in database administration, frontend design, and cybersecurity. Instead, you’d build a team of specialists. That’s exactly what ‘Subagents’ are for Claude Code.

A Subagent is a specialized AI agent you define for a specific task. It has its own system prompt, its own set of allowed tools, and its own context window. When the main Claude Code agent encounters a task that matches a subagent’s expertise, it can delegate the job to that specialist.

You can create subagents at the user level (~/.claude/agents/) to have them available everywhere, or at the project level (.claude/agents/) to share them with your team. They are defined as Markdown files with YAML frontmatter.

.claude/agents/code-reviewer.md
---
description: A subagent that reviews code for quality, style, and potential bugs.
allowedTools:
- Read
- Grep
---
You are an expert code reviewer. Your task is to analyze the provided code files. Look for violations of the project's style guide (PEP8 for Python), identify potential bugs, and suggest improvements for clarity and performance. Do not suggest adding new features.

With this file in your project, you can now invoke it. Claude Code might delegate automatically if your prompt is specific enough (> review my recent code for style issues), or you can request it explicitly (> use the code-reviewer subagent to check the auth module).

If Subagents are your specialists, ‘Hooks’ are the automated processes that ensure rules are followed and workflows are consistent. Hooks are custom shell commands that you can configure to run at specific points during Claude Code’s execution lifecycle. They give you deterministic control over the agent’s behavior.

This is incredibly powerful for enforcing project standards, integrating with other tools, or adding custom validation steps. Hooks are configured in your settings.json file.

Here are some key events where you can insert a hook:

  • PreToolUse: Runs before a tool (like Write or Bash) is used. A great place for a validation step. You can even block the tool use if your script returns a non-zero exit code.
  • PostToolUse: Runs after a tool has been used. Perfect for logging actions or running a code formatter/linter after a file is written.
  • UserPromptSubmit: Runs right after you submit a prompt, but before Claude sees it. You could use this to inject extra context or validate the prompt.
  • Stop: Runs when the agent has finished its response.
.claude/settings.json
{
"hooks": [
{
"event": "PostToolUse",
"tool": "Write",
"pattern": "\\.py$",
"hook": "black $CLAUDE_CODE_TOOL_ARG_PATH"
}
]
}

In this example, we’ve set up a PostToolUse hook. Whenever Claude Code uses the Write tool on a file ending in .py, this hook will automatically run the black code formatter on that file. This ensures all generated Python code adheres to project standards without you or the AI needing to remember.

Output Styles: Controlling the Presentation

Section titled “Output Styles: Controlling the Presentation”

How you receive information is just as important as the information itself. Claude Code provides different ‘Output Styles’, primarily for headless or scripted use, to ensure you can easily parse and utilize its responses.

You can specify the output format using the --output-format flag when running in non-interactive mode (-p or --print).

  • text (default): This provides a standard, human-readable text output, similar to what you see in interactive mode.
  • json: This style formats the entire response as a single JSON object. This is ideal for programmatic use, as you can easily parse the result, cost, token counts, and other metadata with tools like jq.
  • stream-json: For real-time applications, this style streams the conversation as a series of JSON objects, one for each message turn. This allows you to process the conversation as it happens.
Terminal window
# Get a standard text response
claude -p "what is the capital of France?"
# Get the response as a single, parsable JSON object
claude -p "write a python function to add two numbers" --output-format json
# Get a stream of JSON objects representing the conversation
claude -p "build a simple web server in node.js" --output-format stream-json

By mastering Subagents, Hooks, and Output Styles, you can transform Claude Code from a helpful assistant into a fully integrated and customized engine for intelligent automation in your development lifecycle.