Claude Code Agents and Skills: A Practical Guide
Claude Code Agents and Skills: A Practical Guide
Claude Code ships with two systems that most developers underuse: agents and skills. Agents let you parallelize complex work across autonomous subprocesses. Skills turn repeatable workflows into one-command operations. Together, they're the difference between using Claude Code as a fancy autocomplete and using it as an actual engineering partner.
I've built entire projects — NovaMX, internal tools, this very site — using these systems daily. Here's everything I've learned about making them work.
What Are Claude Code Agents?
An agent in Claude Code is an autonomous subprocess that handles a task independently. When you ask Claude Code to do something complex, it can spawn agents that work in parallel — each with their own context window, tools, and focus area.
Think of it like delegation. Instead of Claude Code reading 50 files sequentially to answer your question, it launches multiple agents that each explore a part of the codebase simultaneously. Each agent runs in isolation, does its work, and returns only the relevant results — keeping the main context clean.
Built-in Agent Types
Claude Code offers specialized agent types out of the box:
| Agent Type | Purpose | Can Edit Files? |
|---|---|---|
| general-purpose | Research, code search, multi-step tasks | Yes |
| Explore | Fast codebase exploration (quick/medium/thorough) | No |
| Plan | Architecture analysis, implementation planning | No |
The Explore agent is read-only by design — it can search and read but never modify your code. The Plan agent is similar: it gathers context and produces plans without executing them. This separation is intentional. Read-heavy agents don't need write access, and restricting it prevents accidental changes during analysis.
You can also define custom subagents in .claude/agents/ with their own system prompts, tool restrictions, and permission modes. More on that later.
When to Use Agents vs Direct Tools
This is where most people get it wrong. Here's the decision flow:
The rule: direct tools for simple, directed searches. Agents for broad exploration or parallel work. Spawning an agent has overhead — a new context window, tool initialization — so don't use one to read a single file.
Foreground vs Background Execution
Agents can run in two modes:
- Foreground (blocking) — The main agent waits for the result before continuing. Use this when you need the output to make the next decision.
- Background (async) — The main agent keeps working while the subagent runs independently. Use this for tasks that take over 30 seconds and don't block your next step.
I run research agents in the background while doing codebase analysis in the foreground. By the time I need the research, it's already done.
What Are Claude Code Skills?
Skills are reusable, user-defined workflows triggered by slash commands. You write a skill once — defining the steps, the voice, the tools to use — and then invoke it with a simple /skill-name command.
This blog post was generated by a skill. My /blog-post skill handles research, SEO optimization, writing in my voice, file creation, and build verification — all from one command.
How Skills Work: Progressive Disclosure
Skills use a concept called progressive disclosure to manage context efficiently:
- Scan — Claude Code reads only the frontmatter (name + description) of every skill. This is cheap.
- Load — When your intent matches a skill, the full SKILL.md body is loaded into context.
- Execute — Reference files (
references/directory) are loaded only when the skill needs them during execution.
This keeps context lean. You can have 50 skills installed and Claude Code only pays the token cost for the ones it actually uses.
The SKILL.md Format
Here's the actual structure Claude Code expects:
---
name: my-skill-name # max 64 chars, lowercase + hyphens
description: | # max 1024 chars — this is what Claude reads during scan
Helps generate blog posts with SEO optimization
and consistent voice. Use when the user wants
to create a new article.
allowed-tools: # optional — restrict which tools the skill can use
- Read
- Write
- Bash
- Agent
---
Below the frontmatter, you write the instructions in markdown. Keep it under 500 lines. Use {baseDir} for portable file paths that resolve to the skill's directory.
Creating Your First Skill
Here's a complete, minimal skill you can copy:
.claude/
skills/
gen-component/
SKILL.md
references/
conventions.md
And the SKILL.md:
---
name: gen-component
description: |
Generates a React component following project conventions.
Use when the user asks to create a new component.
allowed-tools:
- Read
- Write
- Bash
---
## Instructions
1. Read {baseDir}/references/conventions.md for component patterns
2. Read existing components in `src/components/` to match the style
3. Ask the user for the component name and props (skip if provided in arguments)
4. Generate the component file at `src/components/<name>.tsx`
5. Run `npm run lint` to verify no errors
6. Report the file path and any issues
The key insight: skills encode your decision-making process. Every time you find yourself giving Claude Code the same multi-step instructions, that's a skill waiting to be created.
Custom Subagents
Beyond skills, you can define custom subagents in .claude/agents/. These are markdown files with YAML frontmatter that specify:
- A custom system prompt
- Which tools the agent can access
- Permission mode (strict, normal, permissive)
- Which skills the agent can use
This is how you build specialized team members. A "code reviewer" agent that only has read access and runs linting. A "database migration" agent that can only touch migration files and run prisma migrate. Scope tools per agent to minimize blast radius.
The Agent + Skill Orchestration Pattern
The real power shows up when skills orchestrate agents. Here's the pattern I use for complex workflows:
This pattern — parallel research, sequential execution, verification loop — works for blog posts, feature development, refactoring, and audit workflows. The blog post you're reading right now was built exactly this way: one agent researched competing articles while another analyzed my codebase for internal linking opportunities.
Best Practices for Working with Claude Code
After hundreds of hours using Claude Code across real projects, here's what actually matters.
1. CLAUDE.md Is Your Most Important File
Your CLAUDE.md is the onboarding doc for an engineer joining your team. Keep it under 200 lines. Include:
- Project overview — what this codebase does, in one paragraph
- Architecture — patterns, conventions, file structure
- Commands — how to build, test, lint, deploy
- Constraints — what to avoid, known issues, tech debt
Don't write a novel. Document what Claude Code gets wrong — that's more valuable than documenting what it gets right. If it keeps adding unnecessary error handling, add a line: "Don't add error handling for internal functions."
2. Be Specific About What You Want
Bad: "Make this better"
Good: "Refactor getUserData in src/lib/api.ts to use a single SQL query instead of the N+1 pattern. Keep the return type unchanged."
Specificity isn't just helpful — it's the multiplier. The more precise your instruction, the less rework you do.
3. Plan Before You Execute
Use plan mode or explicitly ask for a plan before approving execution. Review the plan. This catches architectural mistakes before they become code — and it's much cheaper to fix a plan than to fix an implementation.
This maps directly to the Spec-Driven Development methodology I use on every project.
4. Use /clear Between Distinct Tasks
Context contamination is real. If you just finished debugging a payment bug and now ask Claude Code to build a new feature, the debugging context bleeds into the feature work. Use /clear to start fresh. Use /compact if you want to keep some context but reduce noise.
5. Don't Let the Same Agent Review Its Own Code
Spawn a separate reviewer agent. The agent that wrote the code is biased toward thinking it's correct. A fresh agent with a clean context will catch things the author missed. This is the AI equivalent of "don't review your own PR."
6. Create Skills for Repeated Workflows
If you've given Claude Code the same multi-step instruction three times, create a skill. Common candidates:
- Blog post generation — research, outline, write, publish
- Component scaffolding — create component with tests and stories
- Code audits — security checks, performance reviews, quality scans
- Release workflows — changelog, version bump, tag, deploy
7. Use Hooks for Deterministic Checks
Don't rely on Claude Code to "remember" to lint or type-check. Use hooks — shell commands that execute automatically at agent lifecycle events (PreToolUse, PostToolUse, Stop). A PostToolUse hook on file writes that runs eslint --fix is more reliable than asking Claude Code to lint after every change.
A Complete Workflow Example
Here's how I use agents and skills together to build a feature for NovaMX:
Each step uses a different specialized agent. The spec drives everything — the planner reads it, the executor follows it, the verifier checks against it. No ambiguity, no drift. And because each agent gets a clean context window, there's no confusion from previous steps leaking in.
When Things Go Wrong
No article I've read covers what happens when agents fail. Here's what I've learned:
Agent returns garbage. Usually a context issue. The prompt was too vague or the agent didn't have enough information. Fix: be more specific in the agent prompt and include file paths when possible.
Skill doesn't trigger. Check your description field in the SKILL.md frontmatter. Claude Code matches user intent against this text. If it's too narrow or uses different terminology than the user, it won't match.
Context overflow on long tasks. Subagents have their own context windows, but they're not infinite. If a single agent is doing too much, break the work into multiple agents. Use /compact in the main conversation to free up space.
Build breaks after agent execution. Always include a verification step. My skills end with npm run build — if the build fails, the skill loops back to fix the issue before reporting success.
Setting Up From Scratch
Getting started takes five minutes:
- Create a skill:
mkdir -p .claude/skills/my-skill/references - Write your SKILL.md with frontmatter and instructions
- Add reference files for supporting context
- Test by invoking the skill command
For custom agents: mkdir -p .claude/agents and create a markdown file with the agent's system prompt and tool restrictions.
The official skills repository and awesome-claude-skills have community-contributed skills you can use as starting points.
The Takeaway
Treat Claude Code as a system to configure, not just a chat to prompt. The developers getting 10x results aren't writing better prompts — they're building better systems around the tool. CLAUDE.md for context. Skills for workflows. Agents for parallel work. Hooks for guardrails.
Start with your CLAUDE.md. Then create one skill for your most common workflow. Then experiment with agents. The compound effect is real.
Check out my tools and stack to see what else I use alongside Claude Code, or read about Spec-Driven Development for the methodology that ties it all together.
Building something with Claude Code? Reach out — I'm always interested in how other engineers structure their AI workflows.