Languages: EN RU

Best practices and code organization patterns

Previous articles covered specific tools: plan mode, the TDD loop, and the explore → plan → code → commit pattern. This article is about the organizational layer: habits and principles that make all those tools effective. There is nothing fundamentally new here — only what separates a user who "occasionally uses Claude Code" from one who has integrated it into their daily workflow.


CLAUDE.md: infrastructure, not a README

A common mistake is treating CLAUDE.md as a "brief project description." In practice, it is the first file Claude reads at the start of every session, and it entirely determines how well the agent understands context without any upfront explanation.

A good CLAUDE.md contains not narrative description but operational data: what to run, what to leave alone, what is currently in progress.

# payments-service

## Build & test
npm run build        # TypeScript compilation
npm test             # Jest — run after every change
npm run lint         # ESLint + Prettier

## Architecture constraints
- HTTP handlers go in src/handlers/ only, not in src/routes/
- Direct DB calls are forbidden from handlers/; use src/db/ only
- Types for external APIs go in src/types/external/

## Code standards
- Functions must not exceed 40 lines; decompose if longer
- Wrap errors in AppError, do not throw native Error

## Current context
- Active task: migrating from Stripe v2 to v3 API
- src/legacy/ — code freeze until Q3, do not touch

Three principles for CLAUDE.md:

Commands, not explanations. "Run npm test" instead of "we use Jest." The agent needs to know what to execute, not what to read in the documentation.

Constraints stated explicitly. What is frozen, what must not be changed, which invariants are dangerous to break. This saves far more tokens than any other field.

Current task context. What is currently in progress — so the agent does not spend half its context window exploring things you already know.

Auto memory lets Claude write its own discoveries into CLAUDE.md between sessions — for example, an unconventional way to run tests or a hidden dependency. This is convenient, but it is worth periodically cleaning up auto-written entries: stale context is worse than no context at all.

Check yourself
Imagine a project without CLAUDE.md. What are you forced to do at the start of every new session that could be entirely avoided with a well-written file? Name at least two specific things.

Context discipline: the core skill

The most common anti-pattern is not a bad prompt — it is a polluted context window. When a session stretches over several hours across several different tasks, the agent is working in a space where architectural discussion, three versions of the same file, and debug messages from three hours ago are all mixed together. Quality degrades not because the model is weaker, but because the signal drowns in the noise.

One task — one session. When you are done, /clear, and start the next task with a clean slate. CLAUDE.md and the files on disk are not going anywhere; all that is lost is the conversation history, which you will not need for the next task anyway.

/compact before a deep dive. The command compresses the history into a summary, freeing space in the context. Use it before a long exploration of unfamiliar code — it is better to enter with a compressed summary than to hit the limit halfway through a task.

@file imports, used precisely. Instead of "look at all of src/auth/" — @src/auth/handlers.ts targeting exactly the file you need. The agent will read the dependencies itself if required; there is no need to load everything upfront.

Context before the command. The first prompt is not "add Google OAuth," but "here is the current auth flow: @src/auth/session.ts and @src/auth/jwt.ts. The task is to add Google OAuth without breaking the existing JWT. Constraint: do not change sessionMiddleware." The agent understands first, then acts.

flowchart TD A([Start working]) --> B{New task?} B -->|Yes| C["/clear — clean session"] B -->|Continue| D{Context near limit?} D -->|Yes| E["/compact — compress history"] D -->|No| F[Continue session] C --> G[Add @files selectively] E --> G F --> G G --> H[First prompt: context + goal + constraints] H --> I[Agent work] I --> J{Task complete?} J -->|Yes| K[git commit → /clear] J -->|Stuck| L[Stop, clarify context] L --> G style C fill:#d4edda,stroke:#28a745 style E fill:#d4edda,stroke:#28a745 style K fill:#d4edda,stroke:#28a745 style L fill:#fff3cd,stroke:#ffc107
flowchart TD
    A([Start working]) --> B{New task?}
    B -->|Yes| C["/clear — clean session"]
    B -->|Continue| D{Context near limit?}
    D -->|Yes| E["/compact — compress history"]
    D -->|No| F[Continue session]
    C --> G[Add @files selectively]
    E --> G
    F --> G
    G --> H[First prompt: context + goal + constraints]
    H --> I[Agent work]
    I --> J{Task complete?}
    J -->|Yes| K[git commit → /clear]
    J -->|Stuck| L[Stop, clarify context]
    L --> G
    style C fill:#d4edda,stroke:#28a745
    style E fill:#d4edda,stroke:#28a745
    style K fill:#d4edda,stroke:#28a745
    style L fill:#fff3cd,stroke:#ffc107
Context management decisions: when to clear, when to compress, when to continue

Task decomposition: the vertical slice

A beginner decomposes tasks horizontally: first all models, then all routes, then all tests. An experienced user cuts vertically — one complete slice of functionality all the way through, including the test.

Example: the task is to add CSV data export.

Horizontal decomposition (worse):

Step 1: create models for ExportJob
Step 2: add all routes for export
Step 3: implement CSV generation
Step 4: write tests for everything

Vertical decomposition (better):

Step 1: implement export of the users table to CSV + test
Step 2: add date filtering + test
Step 3: implement async ExportJob for large result sets + test
A horizontal slice groups all components of a single layer; a vertical slice cuts through all layers for a single feature.Source: dev.to

Why this works: each step can be verified and rolled back independently. A failure at step 2 does not break step 1. The agent works with a smaller, well-defined context each time. If one iteration goes wrong, the losses are minimal.

For multi-step tasks that do not fit into a single session, it is useful to maintain a checklist directly in CLAUDE.md. Claude checks items off as they are completed, and when the session resumes it immediately sees where it left off.

Check yourself
Why is vertical task decomposition better than horizontal when working with an agent? Name two specific arguments for what improves.

Multi-agent patterns

Multiple agents outperform a single agent in three situations: the task is too large for one context window, independent verification is needed, or parts of the task are parallel and do not depend on each other.

Writer/Reviewer — one agent writes the code, a second checks it in a clean context. The Reviewer has no visibility into the writing history and catches things the Writer stopped noticing along the way. This is the primary use case described in the article on Subagents and context isolation.

Parallel processing — if you need to analyze 20 legacy code files: one subagent per file, with results collected at the end. A single agent with 20 files in context loses precision toward the end of the list.

Specialization — different subagents for different roles:

.claude/agents/
  security-reviewer.md    # Security aspects only
  perf-analyzer.md        # Profiling and bottlenecks
  test-writer.md          # Specializes in writing tests

For most everyday tasks, a single agent with a clean context is sufficient. Subagents add overhead — do not use them without a concrete reason.


What actually distinguishes an experienced user

Everything above comes down to a few working principles.

Invest in CLAUDE.md upfront. A beginner explains context to the agent at the start of every session. An experienced user wrote a good CLAUDE.md once, and the agent knows everything it needs from the very first token. Time spent on CLAUDE.md pays off starting with the very first session.

Talk about the outcome, not the steps. Instead of "open the file, find function X, change Y" — "the calculateTax function returns incorrect results for EU tax rates; investigate and fix it, running npm test -- calculateTax after each change." The agent knows how to plan — give it a goal and a verifier.

Provide explicit stop conditions. An agent without a stop condition runs until the token limit or until an arbitrary "I think it's done." With a stop condition, it runs until the test is green, until a PR is created, or until an explicit "if three consecutive attempts fail — stop and explain the problem." This is covered in more detail in the article Plan mode and test-driven development.

Do not mix tasks in a single session. This feels like extra work until you encounter an agent that conflates the context of two tasks and confidently does the wrong thing.

Use git as a safety net. A commit before every major step — not because the agent will necessarily make a mistake, but because it lets you compare the diff and roll back without any losses. Claude Code can make meaningful commits with informative messages — assign it that task explicitly. Details are in the article Git, commits and pull requests.

Check yourself
You ask the agent to "add email validation to the registration form." Is this a "steps"-style or a "goal + verifier"-style instruction? How would an experienced user rephrase it?

Quick recall
В чём преимущество вертикальной декомпозиции (один срез с тестом) над горизонтальной (все модели, потом роуты, потом тесты)?
Quick recall
Как загрязнённое контекстное окно снижает качество работы Claude Code?

See also

  • CLAUDE.md and the memory system — a full breakdown of formats, memory hierarchy, auto memory, and @path imports
  • Managing the context window — /clear, /compact, /rewind, and when to use each
  • Typical workflows: explore, plan, implement — the explore → plan → code → commit pattern and its variations
  • Plan mode and test-driven development — plan mode and the TDD loop as verification tools
  • Subagents and context isolation — the Writer/Reviewer and parallel processing patterns in detail
  • Git, commits and pull requests — how to integrate the agent into a git workflow and use worktrees