Головна / Статті

Структурування проєктів Claude Code так, щоб агенти залишалися зосередженими у великих репозиторіях

Шість підходів для великих кодових баз: файли CLAUDE.md у шарах, навички, підагенти, правила відмови, розріджені дерева роботи та плагіни language-server, які підтримують чистоту контексту агента.

Видавець: REACTAPP.TOP10 хв читання2372 слів

Джерела: How I Structure Claude Code Projects So Agents Don’t Get Lost in Large Codebases

Уявіть собі просте запитання до Claude Code: виправити помилку таймауту сесії в проміжку автентифікації. Насправді для її виправлення потрібно лише три рядки. Проте перш ніж дістатися до них, агент блукає по системі журналів, історії міграцій, половині кінцевих точок API та, з причин, які ніхто не може пояснити, конфігураціях Terraform. Після 147-го прочитаного файлу розробник вже хоче натиснути клавішу Escape.

У такій ситуації винуватцем не є модель — винуватець — структура проекту. Кожна конвенція, команда збірки та архітектурне рішення були зібрані в одному кореневому файлі CLAUDE.md обсягом 340 рядків, який агент вірно читав під час запуску, перш ніж витратити решту свого „бюджету“ на аналіз коду, що не стосується автентифікації.

Ось що відбувається, коли з агента ставляться як із новим працівником, який мусить прочитати весь посібник компанії, перш ніж виправити опечатку. Йому потрібен правильний контекст у правильний момент, а не все одночасно. Далі наведено шість способів, які допомагають вирішити цю проблему, а також спосіб визначити, коли варто використовувати кожен з них.

Чому контекст швидко закінчується

Вікно контексту Claude Code, близько 200 000 токенів у використаній тут моделі, здається величезним, поки ви не перелічите все, що впливає на його обсяг: кожне надіслане повідомлення, кожен прочитаний файл, усі результати команд, кожна інструкція у форматі CLAUDE.md та будь-які автоматично збережені нотатки. Один токен становить приблизно чотири символи.

У великій базі коду 50 000 токенів можуть зникнути ще до того, як буде написана хоча б одна рядок коду. Файл CLAUDE.md з 300 рядків коштує приблизно 1 200 токенів, файл з 500 рядків — ще 2 000, а пошук за допомогою grep чи find додає ще більше. До того часу, як агент зрозуміє завдання, половина часового проміжку може вже минути. Коли цей проміжок заповнюється, продуктивність падає: ранні інструкції забуваються, файли перечитуються, і з’являються помилки, яких не було б у чистому контексті. Більші проміжки — не рішення. Рішенням є утримання нерелевантних матеріалів поза цим проміжком.

Шаблон 1: багатошарові файли CLAUDE.md

Першою помилкою є поміщення всього в кореневий файл: команди для створення API, шаблони компонентів фронтенду, правила міграції, списки перевірки для розгортання та конвенції тестування — усе разом.

Claude Code читає файли CLAUDE.md з робочої директорії аж до кореня репозиторію під час початку сесії. Якщо запустити його у піддиректорії, він бере файл цієї папки та всі файли батьківських директорій аж до кореня. Тож розділяйте контент за областю дії:

monorepo/
  CLAUDE.md                     # repository-wide rules only
  packages/
    api/
      CLAUDE.md                 # API-specific conventions
      .claude/skills/
      src/
    web/
      CLAUDE.md                 # frontend-specific conventions
      .claude/skills/
      src/
    shared/
      CLAUDE.md                 # shared library conventions
      src/

Кореневий файл містить лише структуру репозиторію та правила виконання комітів — близько 40 рядків, — а кожен пакет має власні деталі, специфічні для його стеку. Запустіть агента у директорії packages/api/, і він завантажить кореневий файл та файл API, не бачачи при цьому правил фронтенду. Перейдіть у packages/web/, і та сама логіка надасть іншу частину контексту.

У кореневому файлі може бути такий текст:

# Repository Structure

This is a monorepo with three packages under packages/:

- packages/api: Node.js REST API with Express, TypeScript, PostgreSQL
- packages/web: React frontend with Vite, TypeScript, TailwindCSS
- packages/shared: shared TypeScript utilities

Run commands from the package directory, not the monorepo root.
Each package has its own tsconfig.json, package.json, and test suite.

# Commit Conventions

- Prefix commits with the package name: "api: fix session timeout"
- One commit per logical change
- Run tests before committing

А пакет API додає лише те, що є важливим усередині цього пакета:

# API Package

This is the REST API server.

## Commands

- Run tests: `npm test` (uses Vitest)
- Run dev server: `npm run dev` (port 3001)
- Database migrations: `npm run migrate`
- Environment variables: copy `.env.example` to `.env`

## Code Patterns

API routes are in src/routes/. Each route file exports an Express router.
Database queries use Knex in src/db/. Never write raw SQL in route handlers.

## Testing

Tests are in src/__tests__/ mirroring the src/ directory.
Use supertest for HTTP assertions, not raw fetch.
Always wrap database tests in a transaction that rolls back.

У цьому прикладі ефект полягає у тому, що замість 340 ліній завантаженого контексту використовується 80, а кількість файлів для автентифікації становить 12 замість 147.

Шаблон 2: навички для знань за запитом

Навіть багатошарова структура може стати надмірною. Шаблони тестування, списки перевірки та посібники з виправлення помилок є процедурами, а не фактами, і агенту вони не потрібні під час запуску, лише тоді, коли це необхідно для виконання завдання. Саме для цього існують навички.

Навички знаходяться у директорії .claude/skills/ та завантажуються, коли Claude вважає їх корисними або коли вони викликаються безпосередньо через команду з слешем. У описі навички вказується, коли її використовувати, а її тіло містить фактичний контент. Тут інструкції з тестування переміщуються з файлу API до окремої навички:

# .claude/skills/api-testing/SKILL.md

---
name: api-testing
description: Testing patterns for the API package. Use when writing or modifying tests in packages/api/.
---

## Test Structure

Tests are in `src/__tests__/` mirroring the `src/` directory structure.
Each route file has a corresponding `.test.ts` file.

## Running Tests

- All tests: `npm test`
- Single file: `npm test -- src/__tests__/routes/users.test.ts`
- Watch mode: `npm test -- --watch`

## Test Utilities

- `src/__tests__/helpers/db.ts`: provides `setupTestDb()` and `teardownTestDb()`
- `src/__tests__/helpers/auth.ts`: provides `createTestUser()` and `getAuthToken()`

## Patterns

- Use `supertest` for HTTP assertions, not raw fetch
- Always wrap database tests in a transaction that rolls back
- Mock external services in `src/__tests__/mocks/`

Запитайте про тести для середовища автентифікації, і агент завантажить навичку тестування та буде діяти згідно з її правилами. Попросіть його виправити проблему з таймаутом, але навичка залишиться незавантаженою, оскільки тестування не є актуальним у цьому випадку.

Навички також підходять для повторюваних робочих процесів. Навичка, яку можна викликати за допомогою /fix-pr-comments, може читати коментарі до рев’ю у запиті на пул-ріквест у GitHub, визначати необхідні зміни, редагувати код, запускати тести та підтягувати зміни. Увесь процес знаходиться в самій навичці, а не в файлі CLAUDE.md, який щоразу потребує оновлення контексту.

Основне правило: факти, які потрібні щоразу, потрібно вказувати в CLAUDE.md, тоді як процедури та довідкові матеріали стають навичками.

Шаблон 3: підагенти для ізольованого дослідження

Навіть із використанням різних рівнів та навичок процес дослідження залишається занадто обтяжливим. Питання на кшталт „Як працює автентифікація?“ може призвести до 40 операцій з читання файлів, оскільки агент аналізує процес входу, зберігання сеансу, оновлення токенів та вихід, і весь цей текст залишається у основному діалозі після відповіді, забруднюючи решту сеансу.

Підагент працює у власному вікні контексту, виконує дослідження та надсилає лише короткий огляд. Операції з читання файлів та результати команди grep залишаються у його контексті. Основний потік отримує лише огляд, що дозволяє зберегти чистоту діалогу. Запит на дослідження може виглядати так:

Use a subagent to investigate how our authentication system handles
session timeout and token refresh. Report back what files are involved
and how the flow works.

Підагент читає те, що йому потрібно, відстежує логіку та надсилає звіт, тож основна розмова отримує зрозуміле пояснення довжиною близько 200 слів, а не вміст 40 файлів. Підагенти також допомагають під час перевірки після впровадження:

Use a subagent to review the session timeout fix for edge cases
and consistency with our existing auth patterns.

Підагент, який перевіряє, бачить актуальну різницю без пояснень, які призвели до змін.

Одна застереження: у резюме втрачаються деталі. Якщо вам потрібні точні номери рядків або уривки коду, основний агент може змушений буде знову прочитати файли, які вже бачив підагент. Підагенти підтримують основний процес реалізації, тоді як дослідження відбуваються в іншому місці.

Шаблон 4: зберігання створених та поставлених файлів у непрочитаному стані

Усе, що вказано в .gitignore, за замовчуванням ігнорується, що дозволяє не включати node_modules/, dist/ та build/ до результатів пошуку. Проте деякий створений або поставлений код все одно фіксується: скомпільовані визначення protobuf, поставлені SDK, створені типи GraphQL. Агент з радістю відкриє їх, якщо вони з’являться під час пошуку, хоча це ніколи не має траплятися.

Правила відмови у дозволі блокують можливість читання обраних шаблонів файлів. Загальна структура наведена нижче, а точну синтаксис слід перевірити у документації до вашої версії Claude Code:

# packages/api/.claude/settings.json

{
  "permissions": {
    "deny": [
      "Read(./**/dist/**)",
      "Read(./**/build/**)",
      "Read(./**/*.generated.*)",
      "Read(./vendor/**)"
    ]
  }
}

Коли пошук за фразою „GraphQL resolvers“ знаходить створений файл схеми, результат дійсно з’являється, але інструмент Read повідомляє про відмову у доступі, і агент зазвичай запитує, де знаходиться справжній джерело коду. Є ще один наслідок, про який варто знати: ці ж правила перешкоджають читанню, яке ви запитуєте вручну у вікні чату. Якщо попросити його відкрити src/schema.generated.ts, це буде відхилено; тоді варто тимчасово видалити це правило. Перевагою є те, що створений „шум“ не потрапляє до контексту, а агент спрямовується до справжнього джерела коду.

Шаблон 5: розріджені робочі дерева

Claude Code може створювати git-робочі дерева для паралельної чи ізольованої роботи, і за замовчуванням кожне з них завантажує весь репозиторій. У монорепозиторії це марнотратно, адже для виправлення API не потрібен фронтенд.

Функція sparse-checkout у Git записує на диск лише обрані каталоги, а решту залишає в індексі, причому параметр worktree.sparsePaths ґрунтується на цьому принципі. Перевірте значення цього параметра конфігурації у документації до вашої версії:

# packages/api/.claude/settings.json

{
  "worktree": {
    "sparsePaths": [
      ".claude",
      "packages/api",
      "packages/shared"
    ]
  }
}

Робочі дерева містять лише .claude/, packages/api/ та packages/shared/, а також кореневі файли на кшталт package.json та tsconfig.base.json. Їх легше створювати, і вони займають менше місця на диску. Якщо агент намагається прочитати файл, який не було вийнято, git видає помилку, і агент зазвичай запитує, які директорії існують. Функція Sparse-checkout вимагає git 2.25 або новішої версії, що можна перевірити за допомогою команди git --version.

Шаблон 6: інтелект коду замість сканування файлів

Щоб знайти місце, де визначена чи використовується функція у великому кодовому базі, потрібно виконати багато запитів grep та опрацювати безліч файлів, оскільки агент сканує результати, відкриває потенційні варіанти та продовжує пошук.

Плагіни з інтелектом коду під’єднують агента до сервера мови. Замість сканування вони запитують, де визначений refreshAuthToken, і негайно отримують файл та номер рядка. Для проектів TypeScript офіційний плагін LSP встановлюється таким чином, хоча синтаксис встановлення відрізняється залежно від версії, тому перевірте документацію:

/plugin install typescript-lsp@claude-plugins-official

Запитайте, де використовується refreshAuthToken, і агент звертається до сервера мов та отримує відповідь:

src/middleware/auth.ts:47
src/routes/users.ts:103
src/__tests__/auth.test.ts:22

Не було потреби у читанні файлів, тому відповіді надходять швидше, а контекст залишається чистим. Цей плагін також виявляє помилки типу після змін без запуску tsc, тож помилки стають очевидними миттєво. Він добре поєднується з правилами відмови: вони блокують зайвий шум, а функція аналізу коду зменшує необхідність сканування того, що залишилося.

Усі шість разом

Після застосування кожної шаблонної конфігурації процес виправлення початкової помилки виглядає приблизно так:

  1. Запустіть Claude з каталогу packages/api/.
  2. Він завантажує основний файл CLAUDE.md (40 рядків) та файл API (50 рядків).
  3. Ви просите його виправити проблему таймауту сесії в середовищі автентифікації.
  4. Він відправляє підагента для дослідження процесу автентифікації, який у своєму контексті читає близько 20 файлів.
  5. Підагент повідомляє, що логіка таймауту знаходиться у файлі src/middleware/auth.ts на 47-му рядку та використовує неправильний оператор порівняння.
  6. Основний розробник читає цей файл, виправляє баг, пише тест та запускає його, працюючи приблизно з чотирма файлами в основному контексті.

У цьому прикладі «до» та «після» виглядають так: 147 операцій читання файлів, три невдалих спроби та 35 хвилин проти приблизно чотирьох операцій читання, однієї успішної спроби та 6 хвилин. Вважайте це анекдотом одного розробника, а не показником ефективності, але важливим є сам напрямок: така структура усуває перешкоди між запитанням та відповіддю.

Вибір потрібного

Не кожен проєкт потребує всіх шести елементів. Один репозиторій з 50 файлами не потребує ієрархічних файлів чи розріджених структур робочих дерев. Коли кодова база стає занадто великою для того, щоб одна людина могла її усю запам’ятати, ці елементи починають приносити користь:

  • Багатошарові файли CLAUDE.md підходять, коли ви прокручуєтеся повз нерелевантні розділи у кореневому файлі, або коли колеги запитують, чому у файлі API є правила фронтенду.
  • Навички підходять, коли розділ CLAUDE.md перетворюється на процедуру чи чек-лист, або коли ви постійно вставляєте однакові інструкції у чат.
  • Підагенти підходять, коли розслідування закінчується вимогою «прочитати ці 30 файлів», або коли ви хочете отримати оцінку без упереджень.
  • Правила відмови підходять, коли агент продовжує відкривати створений чи придбаний код попри наявність файлу .gitignore.
  • Розріджені робочі дерева підходять, коли монорепо займає понад 10 секунд для розгортання чи коли ви створюєте багато робочих дерев одночасно.
  • Плагіни для інтелекту коду стануть у пригоді, коли ви працюєте з мовою з типуванням, і агент витрачає більше часу на пошук визначень, ніж на написання коду.
  • Мета не в тому, щоб сліпо застосовувати все. Це про те, щоб помічати, коли контекст заповнюється зайвою інформацією, та обирати шаблон, який його очистить. Інші схеми також можуть підіймати для великих кодових баз, проте ці шість перетворюють агента, який читає все, на такого, що читає лише потрібні файли, пише виправлення та зупиняється.