Back to Essays
#claude#ai#engineering#workflow

The Levers of Control in Claude Code

A deep dive into Memory, Slash Commands, Skills, Subagents, and Hooks—and when to pull which lever.

Lots going on with Claude this year. Let's break it down.

As developers, we're used to having precise control over our tools. But with AI agents like Claude Code, the "controls" aren't always knobs and dials—they're layers of interaction.

The goal of this post is to give you a complete picture of the Claude Code landscape. We'll look at the interaction models available to you and build a strong mental model for when to tweak a layer or add to one.

When you have a specific need—whether it's a more deterministic workflow or a specialized autonomous agent—which lever do you pull?

Let's explore the five main levers: Memory (CLAUDE.md), Slash Commands, Skills, Subagents, and Hooks.


The Mental Model

Before diving into the details, here is the high-level heuristic:

LeverRoleAnalogy
Memory (CLAUDE.md)The Foundation. "Who are you and what are your core rules?"The Constitution
Slash CommandsThe Shortcuts. "Do this specific thing right now." (User-invoked)Shell Script
SkillsThe Toolbelt. "Here is how you do this task if it comes up." (Model-invoked)Employee Training
SubagentsThe Delegates. "Go handle this complex project for me." (Autonomous)Specialist Contractor
HooksThe Guardrails. "Run this automatically when X happens." (Event-driven)Git Hooks

1. Memory (CLAUDE.md): The Foundation

Memory files define the global context, behavioral constraints, and project knowledge that apply to every interaction. But there's nuance here—Claude Code has a hierarchy of configuration that behaves differently depending on where you put it.

The Configuration Hierarchy

Claude Code reads memories recursively, starting from your current working directory and traversing up to (but not including) the root. This means you can layer project-wide conventions with directory-specific overrides.

There are three distinct mechanisms:

  1. CLAUDE.md files — Injected as a user message following the system prompt. These are your primary tool for project memory.
  2. Output Styles — Actually modify the system prompt itself. Use /output-style to switch between modes like default, explanatory, or learning.
  3. --append-system-prompt — Appends content directly to the system prompt at runtime.

Your CLAUDE.md becomes part of Claude's context automatically. Every conversation starts with this loaded, eliminating the need to explain basic project information repeatedly.

Where to Put What

LocationScopeUse Case
~/.claude/CLAUDE.mdUser (all projects)Personal preferences, global conventions
./CLAUDE.md or ./.claude/CLAUDE.mdProject (shared)Team conventions, build commands, architecture
./CLAUDE.local.mdProject (personal)Your overrides, auto-added to .gitignore
Nested directoriesSubtreeModule-specific guidance

When to use it?

  • Global Behavior: You want Claude to always speak in a certain tone or follow specific conventions.
  • Core Rules: Non-negotiable constraints (e.g., "never delete files without asking," "always write tests first").
  • Project Context: Build commands, code style, architectural patterns your team uses.

Best Practices

  • Be specific: "Use 2-space indentation" beats "Format code properly."
  • Keep it lean: Memory files consume context window space on every interaction.
  • Document your tools: Include tool names, basic usage patterns, and mention if they support --help.
  • Use imports for modularity: You can reference other files with @path/to/import syntax.
MARKDOWN
# CLAUDE.md Example

See @README for project overview and @package.json for available npm commands.

## Code Style
- Use TypeScript strict mode
- Prefer functional components with hooks
- Run `pnpm lint` before committing

## Additional Instructions
@docs/git-workflow.md

Think of it as: Setting the "Constitution" for your AI—always present, always respected.


2. Slash Commands: The Deterministic Workflow

Slash commands (/test, /fix, /deploy) are explicit, user-driven triggers. They're best for repeatable, deterministic workflows where you want to manually kick off a process.

How They Work

Custom slash commands are Markdown files that Claude Code executes. They're organized by scope:

  • Project commands: .claude/commands/ — Shared with your team via version control
  • Personal commands: ~/.claude/commands/ — Available across all your projects
BASH
# Create a project command
mkdir -p .claude/commands
echo "Analyze this code for performance issues and suggest optimizations:" > .claude/commands/optimize.md

# Create a personal command
mkdir -p ~/.claude/commands
echo "Review this code for security vulnerabilities:" > ~/.claude/commands/security-review.md

Commands support arguments through $ARGUMENTS or numbered placeholders like $1 and $2.

The SlashCommand Tool (New!)

Here's where it gets interesting: Claude can now invoke slash commands programmatically via the SlashCommand tool. This bridges the gap between user-invoked and model-invoked.

To enable this, reference the command by name in your CLAUDE.md or prompts:

MARKDOWN
Run /write-unit-test when you are about to start writing tests.

The SlashCommand tool only works with custom commands that have a description field in their frontmatter.

When to use them?

  • Human-in-the-Loop: You want to explicitly trigger an action at a specific time.
  • Shortcuts: You have a complex prompt you type often.
  • Deterministic Actions: You want a predictable outcome without the AI "thinking" too much about whether to do it.

Think of it as: A shell script or a macro. You type it, it happens.


3. Skills: The Adaptive Toolbelt

Skills are where Claude Code gets genuinely interesting. Unlike slash commands, skills are model-invoked. You define how to do something, and Claude decides when to use it based on conversation context.

The Innovation: Progressive Disclosure

The key insight behind Skills is progressive disclosure—loading information in stages as needed, rather than flooding the context window upfront.

Progressive disclosure is the core design principle that makes Agent Skills flexible and scalable. Like a well-organized manual that starts with a table of contents, then specific chapters, and finally a detailed appendix, skills let Claude load information only as needed.

Here's how it works:

  1. Startup: Claude loads only the name and description from each Skill's YAML frontmatter (~100 tokens per skill)
  2. Relevance Detection: When your request matches a Skill's description, Claude reads the full SKILL.md
  3. On-Demand Resources: If instructions reference other files, Claude reads only those it needs
  4. Script Execution: When Claude runs a bundled script, only the output enters context—the code itself never loads

This is why Skills scale. You can have dozens installed with minimal context penalty.

How It Works in Practice

User: "Extract the text from this PDF and summarize it"

Claude's process:
1. Scans skill metadata → "PDF Processing" matches
2. Reads pdf-skill/SKILL.md → Instructions loaded
3. Sees reference to forms.md → Skips it (not relevant)
4. Runs extract_text.py → Only output enters context

The sales.md and product.md files remain on the filesystem, consuming zero context tokens until needed.

Skill Structure

my-skill/
├── SKILL.md           # Main instructions with YAML frontmatter
├── scripts/           # Optional executable scripts
│   └── helper.py
└── references/        # Optional supporting files
    └── api-docs.md
MARKDOWN
---
name: pdf-processing
description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction.
---

# PDF Processing

## Quick Start
When a user needs to work with PDFs:
1. Identify the operation (extract, fill, merge)
2. For form filling, see [forms.md](references/forms.md)
3. Run the appropriate script from `scripts/`

## Available Scripts
- `scripts/extract_text.py` - Extract text from PDF
- `scripts/fill_form.py` - Fill PDF form fields

Skills vs. CLAUDE.md

CLAUDE.mdSkills
LoadingAlways loadedProgressive disclosure
ScopeProject-specificPortable across projects
ContentSingle markdown fileDirectory with scripts & resources
PlatformClaude Code onlyAll Claude platforms (API, claude.ai, Code)

CLAUDE.md is for project-specific guidance that lives in your repo. Skills are for substantial, reusable expertise that spans projects—data warehouse schemas, company design standards, domain knowledge.

When to use them?

  • Best Practices: Teach Claude the "right way" to perform tasks in your domain.
  • Contextual Help: The task might arise naturally, and you don't want to remember to type a command.
  • Portable Knowledge: Share capabilities across projects or teams.
  • Large Reference Material: API docs, schemas, or examples that shouldn't always be in context.

Best Practices

  • Keep SKILL.md under 500 lines. Split into separate files using progressive disclosure patterns.
  • Write specific descriptions. "Extract text and tables from PDF files, fill forms, merge documents" beats "Work with PDFs."
  • Prefer scripts for deterministic operations. Write validate_form.py rather than asking Claude to generate validation code.
  • Make execution intent clear: "Run analyze_form.py to extract fields" (execute) vs. "See analyze_form.py for the algorithm" (read as reference).

Think of it as: Teaching an employee a new technique. They know how to do it and will apply it when the situation calls for it—without being asked.


4. Subagents: The Specialized Delegates

Subagents are specialized instances of Claude with their own context, tools, and system prompt, designed to handle specific domains or complex tasks autonomously.

How They Work

Each subagent operates in its own context window, preventing pollution of the main conversation. When Claude encounters a task matching a subagent's expertise, it delegates—the subagent works independently and returns results.

Subagents are defined as Markdown files in .claude/agents/ (project) or ~/.claude/agents/ (personal):

MARKDOWN
---
name: test-runner
description: Expert test automation specialist. Use proactively to run tests and fix failures.
tools: Bash, Read, Write
model: sonnet
permissionMode: default
skills: testing-patterns
---

You are a test automation expert.

When invoked:
1. Identify failing tests
2. Analyze the failures
3. Fix them while preserving the original test intent
4. Verify the fixes pass

Key practices:
- Run the full test suite first
- Isolate flaky tests
- Document any test changes

Key Frontmatter Fields

FieldPurpose
nameIdentifier for the subagent
descriptionWhen to invoke (Claude uses this for matching)
toolsComma-separated list, or omit to inherit all
modelsonnet, opus, haiku, or inherit
skillsSkills to auto-load for this subagent

Tradeoffs

BenefitCost
Context efficiency: Preserves main context for longer sessionsLatency: Subagents start fresh, needing time to gather context
Narrow expertise: Fine-tuned for specific domainsHandoff overhead: Results must be communicated back

When to use them?

  • Complexity Management: The task is too big for a single context window or requires a specialized mindset.
  • Narrow Expertise: You need a "QA Engineer" that only cares about testing, or a "Security Auditor" that only looks for vulnerabilities.
  • Delegation: Your main agent can say, "I'll have the frontend subagent handle the UI changes while I work on the API."

Pro Tip

To encourage proactive use, include trigger phrases in your description:

MARKDOWN
description: Expert code reviewer. Use PROACTIVELY after any code changes.

You can also request a specific subagent explicitly:

> Use the test-runner subagent to fix failing tests
> Have the code-reviewer subagent look at my recent changes

Think of it as: Hiring a contractor or specialist team member. You give them a high-level goal, and they execute independently, reporting back when done.


5. Hooks: The Automated Guardrails

Hooks are event-driven automation—shell commands that run automatically when specific events occur. They're configured in your settings files.

Hook Events

EventWhen It Fires
PreToolUseBefore Claude uses a tool (can block or modify)
PostToolUseAfter a tool completes
NotificationWhen Claude sends a notification
StopWhen Claude stops processing

Configuration

JSON
// .claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "prettier --write \"$CLAUDE_FILE_PATH\""
          }
        ]
      }
    ]
  }
}

When to use them?

  • Code Quality: Auto-run formatters, linters, or type-checkers after edits.
  • Safety: Validate changes before they're accepted.
  • Notifications: Trigger alerts or logging on specific events.

Important Notes

  • Hooks execute arbitrary shell commands—use with caution.
  • Direct edits to hook configuration don't take effect until Claude Code restarts.
  • 60-second timeout by default, configurable per command.
  • All matching hooks run in parallel.

Think of it as: Git hooks, but for your AI. Automatic guardrails that enforce standards without manual intervention.


Choosing Between Skills and Slash Commands

This is a common point of confusion. Here's the decision matrix:

Slash CommandsSkills
InvocationUser types /commandModel decides automatically
Best forRepeatable workflows you controlExpertise Claude applies contextually
Context costFull content loads on invocationProgressive disclosure
DiscoverabilityMust know the command existsClaude matches based on description
ArgumentsSupports $ARGUMENTS, $1, $2Context-driven

Rule of thumb: If you find yourself typing the same slash command repeatedly because Claude "should have known" to do that, it's probably a Skill.


Summary: Which Lever to Pull?

FeatureInvocationBest For...Analogy
Memory (CLAUDE.md)Passive (Always on)Core persona, project context, global rulesThe Constitution
Slash CommandsUser (/cmd)Repeatable workflows, manual triggersShell Script
SkillsModel (Automatic)Teaching specific tasks, best practices, "how-to"Employee Training
SubagentsDelegatedComplex domains, autonomous projectsSpecialist Contractor
HooksEvent-drivenAutomated guardrails, formatting, validationGit Hooks

The Claude Agents SDK

If you're looking to build something entirely custom—a completely new interface or a deeply integrated application—the Claude Agents SDK gives you complete control over the system prompt and lets you build your own agent architectures from scratch.

The SDK provides access to all the default features available in Claude Code: Subagents, Hooks, Slash Commands, and Memory (CLAUDE.md). These features work identically to their Claude Code counterparts by reading from the same file system locations. But crucially, the Agents SDK lets you tweak the system prompt "down to the metal"—defining your agent's core identity, capabilities, and constraints without the guardrails of Claude Code's default configuration.

For most users of Claude Code, the five levers above are your primary toolkit. The Agents SDK is for when you need to go deeper: custom agent loops, bespoke tool implementations, or entirely new interaction paradigms.


Conclusion

Mastering Claude Code isn't just about writing good prompts; it's about architecting the interaction.

  • Want to change who Claude is globally? Configure your Memory (CLAUDE.md).
  • Want a button for a common task? Write a Slash Command.
  • Want to teach Claude a new trick? Create a Skill.
  • Want a partner to handle a big job? Spin up a Subagent.
  • Want automatic guardrails? Configure Hooks.

The real power comes from composition. A Skill might reference a Slash Command. A Subagent might have its own Skills loaded. Hooks ensure quality across all of them.

Go forth and configure.


Further Reading