Claude Code Best Practices
Five techniques top engineers use with Claude Code every day: PRDs, modular rules, commands, context resets, and a system-evolution mindset.
Most developers treat Claude Code like a chatbot. Type a vague request, get a vague result, blame the tool. The developers pulling 10x results are doing something different. They have built systems around Claude Code so every session is more productive than the last.
These are the five habits that separate engineers who ship from engineers who struggle. No plugins, no special setup. Just a better operating model for working with agentic AI.
1. PRD-First Development
The biggest single mistake in agentic coding is starting without a plan. You open Claude Code, describe a feature in two sentences, turn it loose. Twenty minutes later you are three tangents deep into code that does not match what you actually needed.
A Product Requirements Document fixes it. Not a 50-page corporate spec. A lightweight markdown file that takes five minutes.
# Feature: User Authentication
## Mission
Add email/password authentication with session management.
## In Scope
- Sign up, login, logout flows
- Password hashing with bcrypt
- JWT session tokens with 24-hour expiry
- Protected route middleware
## Out of Scope
- OAuth providers (Phase 2)
- Two-factor authentication (Phase 3)
- Password reset flow (separate task)
## Architecture
- Auth routes: /api/auth/signup, /api/auth/login, /api/auth/logout
- Middleware: src/middleware/auth.ts
- Database: users table with email, password_hash, created_atWithout a PRD, context drifts. Claude starts making architectural calls you never discussed. It adds OAuth because "that's what most auth systems include." It builds a password reset flow because it seemed relevant. You spend more time course-correcting than building.
With a PRD, every session has guardrails. You tell Claude "read the PRD, then implement the signup flow." It knows exactly what is in scope, what is not, and what patterns to match. When one section lands, you ask "based on the PRD, what should we build next?" and it stays on track.
This works on existing projects too. On greenfield work, the PRD is your MVP brief. On brownfield work, the PRD documents what you already have and then spells out what you want next. Different starting points, same structure.
The PRD also solves the multi-session problem. Claude Code has no memory between conversations, but your PRD does. Each new session opens with the same document, so you pick up exactly where you left off.
2. Modular Rules Architecture
Most developers make the same mistake with their CLAUDE.md: they dump everything into one file. Tech stack, coding conventions, testing rules, deployment procedures, API patterns. One giant wall of instructions.
The issue is context waste. Claude loads your whole CLAUDE.md at session start, and every token in it competes for attention. Your React patterns load while you debug a database migration. Your deployment rules load while you write unit tests.
A better approach: keep CLAUDE.md lean and point to task-specific docs.
# CLAUDE.md
## Tech Stack
- Next.js 15 with App Router
- TypeScript strict mode
- PostgreSQL with Prisma ORM
- Tailwind CSS
## Standards
- Use path aliases (@/components, @/lib, @/utils)
- All functions require explicit return types
- Error handling: guard clauses with early returns
- Tests required for business logic
## Reference Docs (load when relevant)
- Frontend conventions: .claude/skills/react/SKILL.md
- API patterns: .claude/skills/api/SKILL.md
- Database rules: .claude/skills/postgres/SKILL.md
- Deployment: .claude/skills/infra/SKILL.mdAbout 15 lines. It covers the universal rules that apply to every task. Detailed knowledge lives in separate files Claude only loads when the task calls for it.
The folder layout:
.claude/
├── skills/
│ ├── react/ # Component patterns, hooks, state
│ ├── api/ # Route conventions, validation, auth
│ ├── postgres/ # Schema patterns, query optimization
│ └── infra/ # Docker, CI/CD, deployment
└── CLAUDE.md # Lightweight global rulesCompare this to the "everything in one file" habit where 200+ lines of instructions sit in CLAUDE.md. That file burns context on every session, relevant or not. The modular approach loads domain knowledge on demand.
3. Command-ify Everything
If you prompt something twice, it should be a command.
A command in Claude Code is a markdown file in .claude/commands/ that defines a reusable workflow. When you type /commit, Claude reads the command file and follows the instructions. No retyping. No forgotten steps.
Here is what a simple command looks like:
# /commit
Review all staged changes with `git diff --cached`.
Write a commit message that:
- Starts with a verb (add, fix, update, remove)
- Summarizes the WHY, not the WHAT
- Stays under 72 characters
- Uses lowercase
Create the commit. Do not push.Save that as .claude/commands/commit.md and you never write commit instructions again.
Five starter commands worth building:
/commitfor consistent, well-formatted git commits/reviewfor code review against your project's standards/planfor generating a structured implementation plan before writing code/primefor loading session context at the start of each conversation/executefor running a plan document created in a previous session
Each command takes five minutes to write and saves hundreds of prompts over a project's lifetime. They also enforce consistency. Your commits always follow the same format. Your code reviews always check the same things. The compound effect is real.
4. The Context Reset
This is the one habit that feels counterintuitive: planning and execution should happen in separate conversations.
The flow:
- Plan session: research the problem, discuss tradeoffs, explore approaches. Claude outputs a structured plan document (a markdown file saved to your project).
- Clear context: exit the conversation entirely. Kill the session.
- Execute session: start fresh. Feed Claude only the plan document from step one. Nothing else.
Why go through this? Because context window degradation is real.
After a long planning conversation, Claude's context is full of exploratory tangents, rejected approaches, and intermediate reasoning that no longer applies. When you then say "okay, now build it," Claude carries all that noise into execution. It might avoid an approach you discussed and discarded, even if your final plan recommends it. It might carry forward assumptions from early in the conversation that you corrected later.
A fresh context with just the plan means Claude starts execution with a clean head. No baggage from the planning phase. No stale assumptions. Just the spec. And because you are not burning tokens on planning history, Claude has more room to reason about implementation details and self-check its work.
The plan document has to stand alone. A good plan includes the feature description, user story, architecture context, references to the relevant components, and a task-by-task breakdown. If Claude needs to ask clarifying questions during execution, your plan has gaps.
In practice:
# Planning session
claude "Research auth patterns for our Next.js app and create
an implementation plan. Save it to docs/auth-plan.md"
# (exit, start new session)
# Execution session
claude "Read docs/auth-plan.md and implement Phase 1"The plan document acts as a handoff between your planning brain and your execution brain. Both sessions are sharper because neither one is trying to do both jobs.
5. System Evolution Mindset
Every bug is a system failure, not a one-time mistake. The gap between good and great agentic engineering is whether you fix the instance or fix the system.
Three real examples:
Wrong import style. Claude keeps using relative imports (../../components/Button) instead of your path aliases. You could fix each one by hand. Or you add one line to CLAUDE.md: "Always use @ path aliases for imports, never relative paths." The bug never comes back.
Forgot to run tests. You finish a feature, push to CI, tests fail because Claude never ran them locally. Instead of remembering to prompt "run tests" every time, you update your /execute command template to include a mandatory testing step at the end of every implementation. Now every execution session finishes with a test run by default.
Wrong auth flow. Claude builds JWT auth with cookies when your project uses bearer tokens in headers. It happened because there is no reference document for your auth patterns. You create .claude/skills/auth/SKILL.md with your token format, header conventions, and middleware patterns. Next time anyone (including future you) works on auth, Claude loads the right patterns automatically.
The pattern is always the same: something goes wrong, you trace it back to a missing instruction or a missing reference, and you add it to your system. Over weeks, your configuration gets tighter. Claude makes fewer mistakes because your system has fewer gaps.
A practical way to build the habit: after every feature, ask Claude to review your rules and commands, compare the execution against the plan, and suggest what to improve. "Read CLAUDE.md and the commands we used. What rules or process changes would have prevented the issues we hit?" That turns system evolution from an afterthought into a routine step.
This is what separates a Claude Code user from a Claude Code practitioner. The user fixes bugs. The practitioner fixes the system that produced the bug.
Putting It All Together
These five habits are not independent tips. They form a system.
The PRD scopes your work. Modular rules keep context clean. Commands kill repetition. Context resets keep sessions sharp. System evolution makes the whole thing better over time.
None of this needs new tools or expensive setups. It is a set of habits that compound with every project you build. Start with whichever one addresses your biggest pain today, and add the rest as you go.
Stop configuring. Start building.
The Claude Code Source Map Leak
A missing line in .npmignore published 512K lines of TypeScript, 44 feature flags, an autonomous daemon called KAIROS, and Undercover Mode.
Claude Code on a VPS
Run Claude Code on a VPS with SSH, Docker, and headless mode. Real commands, monitoring patterns, and security hardening for a production box.