Best Practices for Claude Code
Tips and patterns for getting the most out of Claude Code, from configuring your environment to scaling across parallel sessions.
Claude Code is an agentic coding environment. Unlike a chatbot that answers questions and waits, Claude Code can read your files, run commands, make changes, and autonomously work through problems while you watch, redirect, or step away entirely.
This changes how you work. Instead of writing code yourself and asking Claude to review it, you describe what you want and Claude figures out how to build it. Claude explores, plans, and implements.
But this autonomy still comes with a learning curve. Claude works within certain constraints you need to understand.
This guide covers patterns that have proven effective across Anthropic's internal teams and for engineers using Claude Code across various codebases, languages, and environments.
Most best practices are based on one constraint: Claude's context window fills up fast, and performance degrades as it fills.
Claude's context window holds your entire conversation, including every message, every file Claude reads, and every command output. However, this can fill up fast. A single debugging session or codebase exploration might generate and consume tens of thousands of tokens.
This matters since LLM performance degrades as context fills. When the context window is getting full, Claude may start "forgetting" earlier instructions or making more mistakes. The context window is the most important resource to manage.
Give Claude a way to verify its work
Include tests, screenshots, or expected outputs so Claude can check itself. This is the single highest-leverage thing you can do.
Claude performs dramatically better when it can verify its own work, like run tests, compare screenshots, and validate outputs.
Without clear success criteria, it might produce something that looks right but actually doesn't work. You become the only feedback loop, and every mistake requires your attention.
| Strategy | Before | After |
|---|---|---|
| Provide verification criteria | "implement a function that validates email addresses" | "write a validateEmail function. example test cases: user@example.com is true, invalid is false, user@.com is false. run the tests after implementing" |
| Verify UI changes visually | "make the dashboard look better" | "[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them" |
| Address root causes, not symptoms | "the build is failing" | "the build fails with this error: [paste error]. fix it and verify the build succeeds. address the root cause, don't suppress the error" |
Your verification can also be a test suite, a linter, or a Bash command that checks output. Invest in making your verification rock-solid.
Explore first, then plan, then code
Separate research and planning from implementation to avoid solving the wrong problem. Use Plan Mode to separate exploration from execution.
The recommended workflow has four phases:
1. Explore
Enter Plan Mode. Claude reads files and answers questions without making changes.
read /src/auth and understand how we handle sessions and login.
also look at how we manage environment variables for secrets.2. Plan
Ask Claude to create a detailed implementation plan.
I want to add Google OAuth. What files need to change?
What's the session flow? Create a plan.Press Ctrl+G to open the plan in your text editor for direct editing before Claude proceeds.
3. Implement
Switch back to Normal Mode and let Claude code, verifying against its plan.
implement the OAuth flow from your plan. write tests for the
callback handler, run the test suite and fix any failures.4. Commit
Ask Claude to commit with a descriptive message and create a PR.
commit with a descriptive message and open a PRPlan Mode is useful, but also adds overhead. For tasks where the scope is clear and the fix is small (like fixing a typo, adding a log line, or renaming a variable) ask Claude to do it directly. Planning is most useful when you're uncertain about the approach, when the change modifies multiple files, or when you're unfamiliar with the code being modified.
Provide specific context in your prompts
The more precise your instructions, the fewer corrections you'll need.
Claude can infer intent, but it can't read your mind. Reference specific files, mention constraints, and point to example patterns.
| Strategy | Before | After |
|---|---|---|
| Scope the task | "add tests for foo.py" | "write a test for foo.py covering the edge case where the user is logged out. avoid mocks." |
| Point to sources | "why does ExecutionFactory have such a weird api?" | "look through ExecutionFactory's git history and summarize how its api came to be" |
| Reference existing patterns | "add a calendar widget" | "look at how existing widgets are implemented on the home page to understand the patterns. HotDogWidget.php is a good example. follow the pattern to implement a new calendar widget" |
| Describe the symptom | "fix the login bug" | "users report that login fails after session timeout. check the auth flow in src/auth/, especially token refresh. write a failing test that reproduces the issue, then fix it" |
Provide rich content
- Reference files with @ instead of describing where code lives
- Paste images directly — copy/paste or drag and drop images into the prompt
- Give URLs for documentation and API references
- Pipe in data by running
cat error.log | claude - Let Claude fetch what it needs — tell Claude to pull context itself using Bash commands, MCP tools, or by reading files
Configure your environment
Write an effective CLAUDE.md
Run /init to generate a starter CLAUDE.md file based on your current project structure, then refine over time.
CLAUDE.md is a special file that Claude reads at the start of every conversation. Include Bash commands, code style, and workflow rules.
# Code style
- Use ES modules (import/export) syntax, not CommonJS (require)
- Destructure imports when possible
# Workflow
- Be sure to typecheck when you're done making a series of code changes
- Prefer running single tests, and not the whole test suite, for performance| Include | Exclude |
|---|---|
| Bash commands Claude can't guess | Anything Claude can figure out by reading code |
| Code style rules that differ from defaults | Standard language conventions Claude already knows |
| Testing instructions and preferred test runners | Detailed API documentation (link to docs instead) |
| Repository etiquette (branch naming, PR conventions) | Information that changes frequently |
| Architectural decisions specific to your project | Long explanations or tutorials |
| Developer environment quirks (required env vars) | File-by-file descriptions of the codebase |
| Common gotchas or non-obvious behaviors | Self-evident practices like "write clean code" |
CLAUDE.md files can import additional files using @path/to/import syntax. You can place CLAUDE.md files in several locations: home folder, project root, parent directories, and child directories.
Configure permissions
Use /permissions to allowlist safe commands or /sandbox for OS-level isolation.
Use CLI tools
Tell Claude Code to use CLI tools like gh, aws, gcloud, and sentry-cli when interacting with external services. CLI tools are the most context-efficient way to interact with external services.
Connect MCP servers
Run claude mcp add to connect external tools like Notion, Figma, or your database.
Set up hooks
Use hooks for actions that must happen every time with zero exceptions. Hooks run scripts automatically at specific points in Claude's workflow. Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens.
Create skills
Create SKILL.md files in .claude/skills/ to give Claude domain knowledge and reusable workflows. Skills extend Claude's knowledge with information specific to your project, team, or domain.
Create custom subagents
Define specialized assistants in .claude/agents/ that Claude can delegate to for isolated tasks. Subagents run in their own context with their own set of allowed tools.
Install plugins
Run /plugin to browse the marketplace. Plugins add skills, tools, and integrations without configuration.
Communicate effectively
Ask codebase questions
Ask Claude questions you'd ask a senior engineer:
- How does logging work?
- How do I make a new API endpoint?
- What does
async move { ... }do on line 134 offoo.rs? - What edge cases does
CustomerOnboardingFlowImplhandle?
Let Claude interview you
For larger features, have Claude interview you first:
I want to build [brief description]. Interview me in detail using the AskUserQuestion tool.
Ask about technical implementation, UI/UX, edge cases, concerns, and tradeoffs.
Keep interviewing until we've covered everything, then write a complete spec to SPEC.md.Manage your session
Course-correct early and often
- Esc: stop Claude mid-action
- Esc + Esc or /rewind: restore previous conversation and code state
- "Undo that": have Claude revert its changes
- /clear: reset context between unrelated tasks
If you've corrected Claude more than twice on the same issue in one session, the context is cluttered with failed approaches. Run /clear and start fresh.
Manage context aggressively
- Use
/clearfrequently between tasks - Run
/compact <instructions>for controlled compaction - Use
/btwfor quick questions that don't need to stay in context - Use subagents to keep investigation off your main context
Use subagents for investigation
Delegate research with "use subagents to investigate X". They explore in a separate context, keeping your main conversation clean.
Rewind with checkpoints
Every action Claude makes creates a checkpoint. Double-tap Escape or run /rewind to open the rewind menu.
Resume conversations
claude --continue # Resume the most recent conversation
claude --resume # Select from recent conversationsUse /rename to give sessions descriptive names.
Automate and scale
Run non-interactive mode
claude -p "Explain what this project does"
claude -p "List all API endpoints" --output-format json
claude -p "Analyze this log file" --output-format stream-jsonRun multiple Claude sessions
Three main ways:
- Claude Code desktop app: multiple local sessions with isolated worktrees
- Claude Code on the web: secure cloud infrastructure in isolated VMs
- Agent teams: automated coordination with shared tasks and messaging
Writer/Reviewer pattern:
| Session A (Writer) | Session B (Reviewer) |
|---|---|
| Implement a rate limiter for our API endpoints | |
| Review the rate limiter implementation. Look for edge cases, race conditions, and consistency. | |
| Address review feedback |
Fan out across files
for file in $(cat files.txt); do
claude -p "Migrate $file from React to Vue. Return OK or FAIL." \
--allowedTools "Edit,Bash(git commit *)"
doneAvoid common failure patterns
- The kitchen sink session: Using one session for unrelated tasks → Fix:
/clearbetween tasks - Correcting over and over: Failed corrections pollute context → Fix: After two fails,
/clearand write a better prompt - The over-specified CLAUDE.md: Too long, Claude ignores half → Fix: Ruthlessly prune
- The trust-then-verify gap: Plausible but broken code → Fix: Always provide verification
- The infinite exploration: Unscoped investigation fills context → Fix: Scope narrowly or use subagents
Develop your intuition
Pay attention to what works. When Claude produces great output, notice what you did: the prompt structure, the context you provided, the mode you were in. When Claude struggles, ask why.
Over time, you'll develop intuition that no guide can capture. You'll know when to be specific and when to be open-ended, when to plan and when to explore, when to clear context and when to let it accumulate.
Related resources
- How Claude Code works: the agentic loop, tools, and context management
- Extend Claude Code: skills, hooks, MCP, subagents, and plugins
- Common workflows: step-by-step recipes for debugging, testing, PRs, and more
- CLAUDE.md: store project conventions and persistent context