Claude Code Best Practices

10 tips from basic to advanced — get the most out of AI coding

Fundamental practices — start with these on day one

01

Planning: Interview → Specification → Code

Don't start with "build me feature X". First, switch Claude to Plan Mode (Shift+Tab twice) and ask it to interview you: about architecture, edge cases, tradeoffs, existing patterns. Claude will ask things you wouldn't have thought of yourself. Write the result into SPEC.md — a detailed specification. Then open a new session and say: "Implement according to SPEC.md". Separating planning from implementation is the difference between "Claude made a mess" and "Claude built exactly what I needed".

# Step 1: Plan Mode (Shift+Tab x2)
"I need a referral link system.
Ask me questions before planning."

# Claude asks:
- What commission percentage?
- Does the referral get a signup bonus?
- How to handle self-referral?
- Do you need a multi-level system?

# Step 2: Result → SPEC.md

# Step 3: New session
"Implement the referral system per SPEC.md.
Run pnpm test after each step."
02

CLAUDE.md — Three-Level Hierarchy

CLAUDE.md works as a hierarchy: Global (~/.claude/CLAUDE.md) — your personal preferences across all projects. Project (./CLAUDE.md) — team conventions, committed to the repo. Subdirectory — per-package rules in a monorepo. Each level adds context. Key insight: "CLAUDE.md is a hint. A Hook is a rule" (Max Ghenis). Instructions in CLAUDE.md can be ignored by Claude, but hooks execute deterministically. Use CLAUDE.md for preferences and context, hooks for mandatory checks.

# ~/.claude/CLAUDE.md (global)
- No fallbacks, errors must be explicit
- Minimal abstractions
- Always check latest versions

# ./CLAUDE.md (project, in git)
## Commands
pnpm dev / build / test

## Architecture
Monorepo: apps/web (Next.js), apps/api (Express)
packages/db (Prisma), packages/shared (types)

## Rules
- Translations: en.json + ru.json always together
- API: Express 5, routes in src/routes/

# apps/api/CLAUDE.md (subdirectory)
- Tests: Jest + Supertest
- Middleware: userAuth, adminAuth
03

Tests as a Self-Correction Mechanism

Tests create a self-correction loop: Claude writes code → runs tests → sees failures → fixes → repeats. Without this loop, Claude gets no feedback and may deliver broken code. The TDD approach works best: write tests FIRST describing expected behavior, then ask Claude to implement until all tests pass. This is the "single biggest quality boost" according to Boris Cherny (creator of Claude Code).

# TDD Workflow — the most effective approach

"Write tests for a discount calculator:
- 20% percentage discount on 1000 = 800
- Fixed discount 150 on 1000 = 850
- Discount cannot exceed the price
- Coupon with usage limit

Then implement calculateDiscount()
until all tests pass.
After each change: pnpm test"

# Claude self-corrects:
# implement → test → fail → fix → test → pass
04

Prompts: "What" and "Why", Not "How"

A good prompt answers 4 questions: What needs to be done? Where in the code? What are the constraints? How to verify the result? Don't give step-by-step instructions — Claude will find the best path itself. Reference existing patterns via @file. Use constraint prompting: explicitly state what NOT to do to prevent Claude's typical mistakes (unnecessary abstractions, unrequested refactoring, adding features nobody asked for).

# Bad prompt
"Create file utils/validate.ts with function
validateEmail using regex /^[a-z...$/"

# Good prompt
"Add email validation to the registration form.

What: inline validation with error below field
Where: @src/components/register-form.tsx
Pattern: same as @src/components/login-form.tsx
Constraints:
- Do NOT create a separate utils file
- Do NOT add validation to other fields
- Do NOT change existing styles
Verify: pnpm test && pnpm build"

Techniques for those who've mastered the basics and are ready for the next level

05

Context Management: Document-and-Clear

The context window is your main resource. Don't wait until it overflows. Document-and-Clear technique: ask Claude to write the current work state to a file (what's done, what remains, key decisions), then /clear, then "read STATUS.md and continue". For /compact you can set a custom instruction: "Keep details about the payment system, summarize everything else". Thresholds: <50% context — full speed, 50-70% — plan compaction, >70% — must /clear.

# Document-and-Clear Workflow

# Step 1: Save progress
"Write to STATUS.md:
- What's been done
- What remains
- Key decisions and reasoning
- Files that were modified"

# Step 2: Clear
/clear

# Step 3: Continue
"Read STATUS.md and continue
from where you left off."

# /compact with instruction
/compact Keep details about API endpoints
and DB schema, summarize everything else.
06

Custom Slash Commands

Slash commands are markdown files that work as templates. .claude/commands/ — your personal ones, project .claude/commands/ — shared with the team. Features: $ARGUMENTS for parameters, @file for including files, !`command` for running bash. Create a starter set: /spec (feature specification), /commit (smart commit), /review (code review), /catchup (what changed). Anti-pattern: don't build complex workflows — commands should be simple shortcuts.

# .claude/commands/spec.md
I need to implement: $ARGUMENTS

Ask 5-10 clarifying questions before
proposing a plan. Ask about:
- Edge cases and errors
- Existing patterns in the project
- Constraints and tradeoffs

# .claude/commands/catchup.md
Analyze recent changes:
!`git log --oneline -20`
!`git diff HEAD~5 --stat`

Briefly describe: what changed, why,
and what to pay attention to.

# Usage
> /spec referral link system
> /catchup
07

Hooks — Rules That Can't Be Skipped

Hooks are shell commands tied to Claude's tool events. Three essential hooks to start with: PostToolUse (Write|Edit) → auto-format with prettier, PreToolUse (Bash git commit) → block if tests fail, Stop → verify task completion. Exit code 2 blocks the tool execution — use it for hard constraints. Important: hooks are loaded at session start. If you change hooks mid-session — you need to restart Claude Code.

// .claude/settings.json
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "command": "npx prettier --write $CLAUDE_FILE_PATH"
    }],
    "PreToolUse": [{
      "matcher": "Bash(git commit)",
      "command": "pnpm test || exit 2"
      // exit 2 = blocks the commit
    }],
    "Stop": [{
      "matcher": "",
      "command": "echo 'Task completed'"
    }]
  }
}

# Exit codes:
# 0 — OK, proceed
# 2 — BLOCK, don't execute the tool

Patterns for experienced users and teams

08

Parallelization: Git Worktrees

A git worktree creates a separate working directory with shared history. In each one you launch a separate Claude Code session on different tasks — true parallelization. Advanced pattern: a dedicated analysis worktree — read-only for logs, metrics, and data, no commits. Important: pnpm install is needed in each worktree (node_modules aren't shared). After merging — cleanup via git worktree remove.

# Create 3 parallel worktrees
git worktree add -b feat/api ../proj-api main
git worktree add -b feat/ui ../proj-ui main
git worktree add -b analysis ../proj-read main

# Each gets its own Claude session
cd ../proj-api && pnpm install && claude
cd ../proj-ui && pnpm install && claude
cd ../proj-read && claude  # read-only

# Cleanup after merging
git worktree remove ../proj-api
git worktree remove ../proj-ui
git worktree remove ../proj-read
git worktree prune
09

Subagents for Research

When Claude searches a large codebase, it can spawn a subagent — a separate process with its own context. The result returns as a concise summary to the main context. You can explicitly ask: "research via subagent". To save tokens on research, use the CLAUDE_CODE_SUBAGENT_MODEL=haiku environment variable — subagents will use the fast and cheap model while the main session stays on Opus/Sonnet.

# Explicit subagent request
"Research via subagent how the payment
system works — which services are involved,
how they connect, where webhooks are handled."

# Claude launches Task(Explore):
# → reads dozens of files
# → returns brief summary
# → main context stays clean

# Save tokens on research
export CLAUDE_CODE_SUBAGENT_MODEL=haiku

# Subagents: haiku (fast, cheap)
# Main session: opus (quality)
10

Statusline — Developer Dashboard

The statusline is a custom script whose output displays at the bottom of the terminal. The basic version shows: context usage (color-coded bar: green <70%, yellow 70-89%, red 90+%), session cost, branch and changes. Advanced versions add: task tracker integration (Linear/Jira), self-evaluation metrics, session duration. You can see at a glance: how much context remains, whether it's time to /clear, which task you're working on.

# ~/.claude/statusline.sh
#!/bin/bash
BRANCH=$(git branch --show-current 2>/dev/null)
MOD=$(git diff --shortstat 2>/dev/null)

# Context (from Claude Code variables)
PCT=${CLAUDE_CONTEXT_PERCENT:-0}
if [ "$PCT" -lt 70 ]; then
  BAR="\033[32m"   # green
elif [ "$PCT" -lt 90 ]; then
  BAR="\033[33m"   # yellow
else
  BAR="\033[31m"   # red
fi

echo -e "${BAR}${PCT}%\033[0m | $BRANCH $MOD"

# Extend: add session cost,
# Linear task, eval metrics, timer