Best Practices
Proven strategies and techniques for getting the most out of Claude Code
Context Management
Effective context management is the key to getting accurate and relevant responses from Claude Code.
Keep Context Focused
Only include relevant files and information in your context window. Use CLAUDE.md to provide project-specific guidance. Start fresh sessions for new topics with /clear.
Use Compact Mode
Use /compact to summarize the conversation while preserving key information when context gets large. Use /btw for side questions that don't pollute main context.
Leverage Memory and Handoffs
Use CLAUDE.md at project and user level to persist important context across sessions. Write HANDOFF.md before starting fresh to migrate context between sessions.
# Project-level CLAUDE.md example
# Place at your repository root
## Project Overview
This is a Next.js 15 app with TypeScript and Tailwind CSS.
## Architecture
- /src/app/ - App Router pages
- /src/components/ - Reusable UI components
- /src/lib/ - Utility functions and configs
## Commands
- pnpm dev - Start dev server
- pnpm test - Run tests
- pnpm lint - Run linter
## Conventions
- Use functional components with hooks
- Prefer immutable patterns (spread, map, filter)
- All new files must have testsUse /btw for Side Questions
When you have a quick question unrelated to your main task, prefix it with /btw. This tells Claude it's a tangent so the main conversation flow stays clean and focused.
Write HANDOFF.md Before Fresh Starts
Before ending a long session, ask Claude to write a HANDOFF.md summarizing current progress, decisions made, and next steps. Your next session can pick up exactly where you left off.
# Ask Claude to create a handoff document
> Write a HANDOFF.md summarizing what we did today,
> open decisions, and next steps.
# In your next session
> Read HANDOFF.md and continue from where we left off.Verification & Testing
Always verify Claude Code output to ensure correctness and quality.
Review Before Accepting
Always review code changes before accepting them. Use visual diffs to understand what changed. Create draft PRs to review everything before merging.
Run Tests Frequently
Ask Claude to run tests after making changes. Set up autotest hooks for automatic verification. Include test commands in your prompts.
# In your CLAUDE.md, add verification commands:
## After Every Change
- Run: pnpm test
- Run: pnpm lint
- Run: pnpm typecheck
# Or set up a PostToolUse hook in .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "pnpm test --bail 2>&1 | tail -20"
}
]
}
}Use Checkpoints and Self-Verification
Leverage git checkpoints to safely experiment and roll back with /rewind. Ask Claude to double-check its claims and use /chrome for visual verification of web apps.
Ask Claude to Verify Its Own Work
After implementation, explicitly ask Claude to review what it wrote. Phrases like "now review that code for bugs" or "does this handle edge cases?" trigger a critical second pass that often catches issues.
# Good verification prompts:
> Now review that implementation for edge cases
> Run the tests and fix any failures
> Check if this handles null/undefined inputs
> Does this match the existing code style?Use /chrome for Visual Verification
For web applications, use /chrome to let Claude take a screenshot and visually verify that UI changes look correct. This catches CSS issues, layout problems, and visual regressions that tests miss.
Plan Mode & Structured Thinking
Use Plan Mode for complex tasks that benefit from structured analysis before implementation.
Start with Planning
For complex features, press Shift+Tab to enter Plan Mode. Let Claude analyze the problem before writing code. Review the plan before approving execution.
Break Down Large Tasks
Divide complex work into smaller, manageable steps. This improves accuracy and makes it easier to verify each piece. Use subagents for isolated investigation.
# Instead of one big prompt:
> Build a complete auth system with OAuth, sessions, and RBAC
# Break it down into phases:
> Phase 1: Set up the session store with Redis.
> Only create the session middleware - no auth yet.
> Run tests before moving on.
> Phase 2: Add email/password authentication.
> Use the session store from Phase 1.
> Add login, logout, and registration routes.
> Phase 3: Add OAuth (Google, GitHub).
> Integrate with the existing session/auth system.
> Phase 4: Add role-based access control.
> Define roles: admin, editor, viewer.
> Add middleware to protect routes.Use Extended Thinking
Enable extended thinking for complex architectural decisions that require deep reasoning. Use 'think', 'think hard', or 'ultrathink' keywords to trigger progressively deeper analysis.
# Trigger levels of extended thinking:
> think about how to refactor this module
# Light analysis, good for moderate complexity
> think hard about the tradeoffs between
> microservices vs monolith for our scale
# Deeper analysis, explores more alternatives
> ultrathink about the security implications
> of our auth architecture
# Maximum reasoning depth, best for critical decisionsUse Subagents for Investigation
When planning reveals unknowns, use subagents to investigate specific areas without polluting your main context. Each subagent gets its own context window and can focus on one aspect of the problem.
Review and Iterate on Plans
Don't accept the first plan. Ask Claude to consider alternatives, identify risks, and think about edge cases. A good plan should include rollback strategies and success criteria.
Prompt Engineering
How you communicate with Claude Code significantly affects the quality of results.
Be Specific
Provide clear, specific instructions including file paths, function names, and expected behavior. Say "fix the null reference in handleSubmit in user.tsx" not "fix the error".
# Bad: vague prompt
> Fix the bug in the login page
# Good: specific prompt with context
> In src/app/auth/login.tsx, the handleSubmit
> function throws a null reference when the
> email field is empty. Add input validation
> before the API call on line 45. The validation
> should show an inline error message matching
> the style in src/components/FormError.tsx.Provide Examples and Context
Show Claude examples of the pattern or style you want. Use @ to reference specific files. Paste screenshots of errors, UIs, or designs. Include success criteria.
Set Constraints and Standards
Tell Claude about project constraints, coding standards, and patterns to follow. Include verification steps: "all tests should pass and the linter should be clean".
# Include constraints directly in your prompt:
> Add a user search endpoint to the API.
> Requirements:
> - Follow the pattern in src/api/products.ts
> - Use Zod for input validation
> - Add rate limiting (100 req/min)
> - Return paginated results
> - Include unit tests with >80% coverage
> - All existing tests must still pass
> - No console.log statementsUse @ References and Images
Reference files directly with @filename to pull them into context. Paste screenshots of error messages, UI designs, or expected output. Visual context often communicates requirements better than words.
Front-load Intent, Not Just Instructions
Start prompts with WHY before WHAT. When Claude understands the goal, it makes better decisions about implementation details and catches design issues early.
# Less effective: just instructions
> Add a cache layer to getUserById
# More effective: intent + instructions
> Users are seeing 2s load times on profile pages
> because getUserById hits the database every time.
> Add a Redis cache layer with 5-minute TTL.
> Invalidate on user update. Follow the caching
> pattern we use in getProductById.Scaling with Claude Code
Techniques for using Claude Code effectively on larger projects and teams.
Use Headless Mode for CI/CD
Integrate Claude Code into your CI/CD pipeline with claude -p for automated code reviews, test generation, and documentation updates.
# GitHub Actions example: automated code review
name: Claude Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Claude Review
run: |
claude -p "Review the changes in this PR.
Focus on: security issues, performance,
and code style. Output as markdown." \
--output-format json > review.jsonConfigure Team Standards
Use shared CLAUDE.md files for consistent behavior across team members. Create custom skills and subagents. Share via plugins for team distribution.
# .claude/settings.json - shared team config
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(pnpm test*)",
"Bash(pnpm lint*)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force*)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
}Leverage Subagents and Teams
Use subagents to fan out across files. Use Agent Teams (experimental) for coordinated parallel work. Use git worktrees for isolation between agents.
Use Git Worktrees for Parallel Agents
When running multiple Claude Code agents on the same repo, use git worktrees to give each agent its own working directory. This prevents file conflicts and lets agents work truly in parallel.
# Create worktrees for parallel agents
git worktree add ../project-agent-1 -b feature/auth
git worktree add ../project-agent-2 -b feature/api
# Run Claude in each worktree
cd ../project-agent-1 && claude -p "Implement auth"
cd ../project-agent-2 && claude -p "Build API endpoints"
# Merge results back
git checkout main
git merge feature/auth
git merge feature/apiCreate Custom Skills for Repeated Tasks
If your team frequently performs the same type of task (e.g., creating API endpoints, writing migration scripts), define custom skills with SKILL.md files that encode your team's patterns and standards.
# .claude/skills/api-endpoint/SKILL.md
---
name: create-api-endpoint
description: Create a new REST API endpoint
---
## Steps
1. Create route handler in src/api/
2. Add Zod validation schema
3. Add rate limiting middleware
4. Write integration tests
5. Update OpenAPI spec
## Template
Follow the pattern in src/api/products.ts
Always include error handling middleware
Use the shared response format from src/lib/response.ts