Mastering Claude Code: The Complete Developer Guide
Let's be honest: if you're using Claude Code just to send prompts and wait for responses, it's like buying a Ferrari to do your grocery shopping 🏎️. It works, but you're missing the point.
I've been using Claude Code daily for several months now, and I still regularly discover features that save me a ton of time. Agents, skills, hooks, MCP... At first, these terms seemed obscure. Today, I couldn't live without them.
In this guide, I'll share everything I've learned — the stuff that actually works, the pitfalls to avoid, and the little tricks that make a real difference day to day.
The basics we often forget
Before diving into advanced features, let's talk fundamentals. You'd be surprised how many devs don't know about these super handy options.
Different output modes
By default, Claude responds in text. But sometimes you need something more structured:
# The classic
claude -p "analyze this code"
# For integrating into a script or pipeline
claude -p "analyze this code" --output-format json
# To see the response in real-time (perfect for long tasks)
claude -p "analyze this code" --output-format stream-jsonJSON mode is particularly useful when you want to chain Claude with other tools. I use this regularly to automate code analysis.
Piping: your best friend
This is where it gets interesting. You can plug Claude directly into your shell pipelines:
# Analyze a file and save the result
cat code.py | claude -p "find bugs" > analysis.txt
# Chain with jq to extract what you need
echo "my code" | claude -p "improve" --output-format json | jq '.result'My favorite use: I often pipe git diff output to get an automatic review before committing.
Verbose mode (Ctrl+O)
I discovered this one by accident and it's become essential. Press Ctrl+O and you'll see Claude's complete reasoning — how it thinks, why it makes certain choices. It's fascinating and helps tremendously when something isn't working as expected.
Agents: delegating intelligently
OK, this is where it gets really powerful 💪. Subagents are Claude instances that work autonomously in their own context. Why is this awesome? Because it preserves your main context.
Imagine: you're working on a complex feature, you have 15 files open in your conversation, and you want to run a test suite. Without a subagent, test logs will pollute your context. With a subagent, it does the work on its side and just reports back the result.
Subagent types
| Type | What it is | When to use |
|---|---|---|
Explore | Fast, read-only | "Find all files that use this function" |
Plan | Thoughtful, read-only | "Analyze the architecture and propose a refactoring plan" |
General-purpose | Full access | Complex tasks that require writing code |
Creating your own agents
This is where it gets really fun 🎨. You can create specialized agents for your needs. I have one for code reviews, one for documentation, one for tests...
---
name: code-reviewer
description: My personal reviewer, focused on security and perf
model: sonnet
tools:
- Read
- Grep
- Glob
permissionMode: default
---
You're a code review expert. Be direct and concrete.
Focus on:
- Security vulnerabilities (injections, XSS, etc.)
- Obvious performance issues
- Best practice violations
- Maintainability
No need for compliments, just the problems and how to fix them.You can store your agents in three places:
- In the project (
.claude/agents/): shareable with your team via git - Personal (
~/.claude/agents/): available across all your projects - Session: via the
--agentsflag for one-off needs
Advanced configuration
For more complex cases, you can configure isolation, memory, and even connect MCP servers:
---
name: isolated-worker
description: Agent that works in its own corner without touching my branch
isolation: worktree # Creates its own copy of the repo
memory: user # Remembers our past conversations
maxTurns: 50 # Prevents infinite loops
mcpServers:
- github # Can access the GitHub API
- playwright: # And run E2E tests
type: stdio
command: npx
args: ["-y", "@playwright/mcp@latest"]
---How I use them daily
# When I want to explore without polluting my context
Use an Explore subagent to find all API endpoints
# When I have multiple independent questions
Launch 3 subagents in parallel to analyze:
- The auth module architecture
- The DB structure
- Error handling patterns
# For chained work
Use a reviewer agent to find problems,
then an agent to fix themSkills: your custom shortcuts
Skills are custom commands you invoke with /skill-name. Think of them as smart macros with dynamic context.
Built-in skills
Before creating your own, discover what already exists:
| Command | What it does |
|---|---|
/batch <instruction> | Applies a change across multiple files in parallel |
/claude-api | Loads the Claude API docs |
/debug [description] | Enables real-time debug logging |
/loop [interval] <prompt> | Repeats a prompt at regular intervals |
/simplify [focus] | Launches 3 agents for review + simplification |
/simplify has become my reflex after every big feature. Three agents reviewing your code from different angles — it's brutal but effective 🔥.
Creating your own skills
Here's a skill I use all the time to summarize PRs:
---
name: pr-summary
description: Summarizes a PR so I can review it intelligently
argument-hint: "[PR-number]"
allowed-tools: Read, Bash(gh pr)
context: fork
user-invocable: true
model: sonnet
---
## PR Context
- **Full diff**: !`gh pr diff $ARGUMENTS`
- **Modified files**: !`gh pr diff $ARGUMENTS --name-only`
- **Comments**: !`gh pr view $ARGUMENTS --comments`
- **Info**: !`gh pr view $ARGUMENTS`
## What I expect
1. A 2-3 sentence summary (the "why" of this PR)
2. Major changes by category
3. Things that deserve special attention
4. Your recommendation: merge or request changes?See those !\`command\`? That's dynamic injection. The skill executes these commands and injects the result into the prompt. Game changer ✨.
Available variables
| Variable | What it contains |
|---|---|
$ARGUMENTS | Everything you pass after the skill name |
$ARGUMENTS[0], $0 | The first argument |
${CLAUDE_SESSION_ID} | Your session ID (for logs) |
${CLAUDE_SKILL_DIR} | The folder where the skill is stored |
Hooks: automate without thinking
Hooks are actions that trigger automatically at certain moments. This is the next level in terms of automation.
Available events
| When | Event | Example usage |
|---|---|---|
| Session start | SessionStart | Load specific context |
| Before sending your prompt | UserPromptSubmit | Validate/modify the prompt |
| Before a tool | PreToolUse | Block certain commands |
| After a tool | PostToolUse | Auto-format code |
| Tool error | PostToolUseFailure | Log errors |
| End of response | Stop | Notify completion |
My favorite setup
I automatically format every file Claude modifies. Never again "oops, I forgot prettier" 😅:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $FILE_PATH"
}
]
}
],
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Reminder: We use Bun, not npm. Current sprint: auth refactor.'"
}
]
}
]
}
}Pro tip: The SessionStart hook with the compact matcher is a trick I love. When Claude compacts the context (because it gets too long), it loses certain info. This hook reinjects it automatically.
Return codes
| Code | What it does |
|---|---|
0 | OK, continue |
2 | Blocked, error message sent back to Claude |
| Other | Logged but action continues |
MCP: connecting Claude to your tools
The Model Context Protocol lets you plug Claude into external services. GitHub, Slack, your database, Figma... The possibilities are huge.
Basic configuration
{
"mcpServers": {
"github": {
"type": "stdio",
"command": "npx",
"args": ["@claude-mcp/github"]
},
"postgres": {
"type": "stdio",
"command": "npx",
"args": ["@anthropic-ai/mcp-server-postgres"],
"env": {
"DATABASE_URL": "postgresql://user:pass@localhost:5432/db"
}
}
}
}Once configured, you can do stuff like:
@github:repos/myorg/myrepo/issues
Summarize open issues and prioritize themMCP servers I recommend
- GitHub - Essential for anything touching repos, issues, PRs
- PostgreSQL - Query your DB directly from Claude
- Slack - Post messages, read channels
- Playwright - Browser automation for E2E tests
- Sentry - Analyze production errors
CLAUDE.md: your project's brain
The CLAUDE.md file is probably the best investment you can make. It's Claude's persistent memory for your project.
Structure I recommend
# CLAUDE.md
## Commands
```bash
bun dev # Dev server
bun test # Tests
bun build # Prod build
```
## Stack
- Next.js 15 (App Router)
- Tailwind + shadcn/ui
- Zustand for state
- Prisma + PostgreSQL
## Important conventions
- Components in kebab-case (my-component.tsx)
- Types centralized in src/types/
- No "any" except documented exceptional cases
## What to avoid
- NEVER use npm (we use Bun)
- No console.log in prod
- No force push to mainConditional rules
You can have rules that only apply to certain files:
---
paths:
- "src/api/**/*.ts"
- "lib/**/*.ts"
---
# API Rules
- Validate ALL inputs with Zod
- Error format: { error: string, code: number }
- Document with JSDocThese rules load automatically when Claude works on matching files. Clever, right? 😏
Automatic memory
Claude also maintains memory in ~/.claude/projects/<project>/memory/. You can ask it to remember stuff:
# Ask it to remember
Remember that I prefer atomic commits
# Check its memory
/memory
# Ask it to forget
Forget my preference about unit testsPermission modes
Claude asks permission before executing certain actions. You can configure this behavior:
| Mode | Behavior | When to use |
|---|---|---|
default | Asks for everything | Sensitive work, new project |
acceptEdits | Auto-accepts edits | Rapid code iteration |
plan | Read-only | Architecture analysis |
auto | An AI evaluates each action | Long autonomous tasks |
bypassPermissions | No verification | Isolated Docker/containers only |
Plan Mode
My favorite for big refactoring. Claude analyzes everything, proposes a detailed plan, and executes nothing until you've approved.
claude --permission-mode planPre-approve common commands
To avoid approving "npm test" 50 times, configure an allowlist:
{
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm run build)",
"Bash(git commit:*)",
"Read",
"Edit"
],
"deny": [
"Bash(rm -rf /)"
]
}
}Agent Teams: AI collaboration
Experimental but fascinating feature 🤯: multiple Claude instances working together.
Activation
{
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
}
}My favorite use case
Create a team of 3 reviewers:
- One focused on security (OWASP, injections)
- One focused on performance (N+1, memory leaks)
- One focused on tests (coverage, edge cases)
Review PR #142 and compile a unified report.Three different perspectives on the same code. It's like having a team of senior devs at your disposal 🎉.
Git Worktrees: working in parallel
Worktrees let you launch Claude in an isolated copy of your repo. Perfect for:
- Testing a risky approach without polluting your branch
- Working on multiple features in parallel
- Letting an agent work while you continue on something else
# Creates a worktree with a new branch
claude --worktree feature-auth
# Multiple parallel sessions
claude --worktree bugfix-123
claude --worktree refactor-apiIf the agent makes no changes, the worktree is automatically deleted. If there are changes, Claude asks what to do with them.
Scheduled tasks
Need to check something regularly? Claude can do that.
The /loop command
# Check every 5 minutes
/loop 5m check if deployment is finished
# Review a PR every 30 minutes
/loop 30m /review-pr 1234
# One-shot reminder
remind me at 3pm to push the releaseInterval syntax
5m,30s,2h,1d- No interval = 10 minutes default
- Flexible position:
/loop 5m taskor/loop task every 5m
Essential keyboard shortcuts
| Shortcut | Action |
|---|---|
Shift+Tab | Change mode |
Ctrl+O | Verbose mode |
Ctrl+V | Paste an image |
Alt+T | Toggle extended thinking |
Ctrl+C | Interrupt |
Ctrl+R | History search |
You can customize everything in ~/.claude/keybindings.json.
Extended Thinking
Sometimes you need Claude to think longer. Effort levels:
| Level | When to use |
|---|---|
low | Simple questions, quick answers |
medium | Daily usage |
high | Complex problems, architecture |
max | Really hard stuff (Opus only) |
To activate: Alt+T or add "ultrathink" to your prompt.
My favorite patterns
1. Isolate heavy operations
Use a subagent to run all tests
and only report failures.2. Parallel research
Launch 3 subagents in parallel to analyze:
- Auth architecture
- DB schema
- Error patterns
Compile a unified report.3. Worktree per feature
# Main feature
claude --worktree auth-refactor
# Urgent bugfix in parallel
claude --worktree hotfix-1234. Auto-restore after compaction
{
"hooks": {
"SessionStart": [
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "echo 'Stack: Bun + Next.js. Sprint: auth. Deadline: Friday.'"
}
]
}
]
}
}Wrapping up
Claude Code is a bit like vim: at first you use 10% of its features, then gradually you discover stuff that completely changes how you work.
My advice: don't try to master everything at once. Start with a good CLAUDE.md, add a few hooks for automatic formatting, then explore agents and skills when you need them.
The real game changer for me was understanding that Claude Code isn't just a chatbot — it's a complete development environment with AI integrated everywhere.
The golden tip 💎: invest time in your CLAUDE.md. A good config file is the difference between an assistant that understands you instantly and one that asks 15 questions before starting.
Happy coding! 🚀