Java-скрипт для экспорта проекта в один файл для LLM | AiManual
AiManual Logo Ai / Manual.
28 Май 2026 Инструмент

Склейка монстра: как я упаковал 1000 файлов Java в один, чтобы DeepSeek понял проект целиком

Java-скрипт, который собирает весь проект в один файл для DeepSeek, Claude и GPT. Ускорьте код-ревью и рефакторинг — примеры и сравнение с альтернативами.

Разработчики, которые пихают LLM по одному файлу из проекта, похожи на врачей, пробующих лечить слона по кусочкам. Модель видит только локальный контекст — и начинает галлюцинировать, хоть у неё консьерж-класса контекстное окно. Я перепробовал все: ручное копирование, cat *.java, скрипты на Python. Но только когда написал на Java утилиту, которая склеивает весь проект в один файл-монстр, DeepSeek действительно начал понимать, о чём проект.

Идея проста: собрать все исходники, конфиги, README, Git-логи в один текстовый файл с чёткой структурой путей. LLM видит архитектуру целиком — догадки о том, что такое UserRepository и как оно связано с AuthFilter, превращаются в точные ответы.

Почему с LLM не работал обычный «cat»?

Классика: find . -name '*.java' -exec cat {} \; > bundle.txt. Получаем кашу из package, без заголовков, без структуры. Модель тратит 30% контекстного окна на разделение файлов. А если проектов десятки — контекст деградирует быстрее, чем кофе стынет. В статье про три рабочих способа борьбы с галлюцинациями показано, что структурированный контекст снижает ошибки модели на 40%.

Как работает скрипт

Утилита написана на чистой Java без зависимостей — java ProjectExporter.java /path/to/project output/result.md. Она рекурсивно обходит директории, собирая файлы с заданными расширениями, и генерирует Markdown-файл:

  • Структура проекта — дерево каталогов, только важное (исключает target, node_modules, .git).
  • Каждый файл — в блоке кода с указанием полного пути, например src/main/java/com/example/service/AuthService.java.
  • Настройка — в начале скрипта массив INCLUDES и EXCLUDES.
  • Статистика — количество файлов, строк, общий размер.
private static void writeFileContent(BufferedWriter bw, Path file, Path root) throws IOException {
    bw.write("### " + root.relativize(file).toString() + "\n\n");
    bw.write("```java\n");
    bw.write(Files.readString(file));
    bw.write("\n```\n\n");
}

Важно: скрипт не очищает чувствительные данные. Перед отправкой в LLM обязательно проверьте, не попали ли в бандл пароли, ключи API или приватные SSH-ключи. Лучше добавить EXCLUDES с application-secret.properties.

Живой пример: рефакторинг Feature Flags

Недавно я мигрировал систему фиче-флагов в проекте на Java 21. Старый код был размазан по 30 файлам. Вместо того чтобы объяснять DeepSeek архитектуру десятью разрозненными промптами, я скормил ему бандл. Модель сразу выявила дублирующиеся проверки и предложила использовать общий FeatureFlagFilter. Этот кейс подробно разобран в гайде по рефакторингу Feature Flags — разница в скорости между подачей по файлам и цельным контекстом составила 3×.

Сравнение с альтернативами

Инструмент Структура вывода Игнор-файлы Размер токенов (1000 файлов) Простота настройки
ProjectExporter (Java) Markdown + tree + пути Да, массивы INCLUDE/EXCLUDE ~350K (с путями) Минимальная (batch-файл)
tree + find + cat Простой текст, нет разделителей Только руками ~320K Средняя (пишется каждый раз)
Repo2txt (Python) Markdown, пути Да, но свой формат ~360K Требует Python
Copy as Markdown (IDE-плагин) Только выделенные файлы Нет Зависит от выбора Ручная работа

Главное преимущество Java-скрипта — его можно встроить прямо в CI/CD или в IDE как внешний инструмент. Никаких зависимостей, работает на любом JDK 17+. В отличие от Python-скрипта, не нужно возиться с виртуальным окружением. Для тех, кто работает с локальными LLM, это особенно важно — как в реальных кейсах локальных LLM, где каждый дополнительный слой зависимостей может сломать пайплайн.

Под капотом: как справиться с миллионным контекстом

DeepSeek V4 обещает до 1M токенов контекста. На практике, если склеить весь корпоративный проект на Java с кучей либ — это легко 500K токенов. Без структуры модель теряет связность уже на 100K. В статье про архитектуру KV cache показано, что миллионный контекст возможен только при правильной упаковке данных. Наш скрипт как раз этим и занимается: превращает кучу файлов в линейную, плотную историю.

Кому это спасёт жизнь

  • Разработчикам, практикующим «вайб-кодинг» — когда вы просто бросаете в чат весь проект и просите починить баг. Без контекста LLM начинает деградировать, а с бандлом проблема решается за один промпт. Подробнее — в руководстве по управлению контекстом.
  • Инженерам, которые проводят код-ревью — можно скормить весь PR-модуль DeepSeek и получить моментальный анализ.
  • Авторам технической документации — сгенерировать бандл с JavaDoc и описанием архитектуры для LLM, чтобы модель могла написать мануал.
  • Тем, кто проверяет, не пора ли делегировать LLM часть пайплайна. Есть ситуации, когда LLM не стоит пускать в продакшн — чек-лист от инженера даёт критерии. Но подготовка контекста — никогда не вредна.

Как НЕ надо делать: типичные ошибки

Ошибка 1: включить в бандл весь vendor/ или node_modules/. LLM утонет в чужих библиотеках. Настройте EXCLUDES на /target/, /build/, *.jar, *.class. Если проект на Maven/Gradle — исключите ~/.m2 и .gradle.

Ошибка 2: не добавлять маркер «конец контекста». В начале сгенерированного файла вставьте блок с задачей: /* PROJECT OVERVIEW: микросервис для работы с заказами, использует Spring WebFlux, Kafka. Запрос: ... */. Так вы явно задаёте фокус, а не надеетесь, что модель угадает.

Ошибка 3: использовать UTF-16 или другие кодировки. LLM ожидает UTF-8. В скрипте явно укажите StandardCharsets.UTF_8.

Куда двигаться дальше

Сейчас я экспериментирую с добавлением в скрипт семантического сжатия — выкидывать из методов тела, но оставлять сигнатуры и комментарии. Для DeepSeek с тестируемой поддержкой 1M токенов это может быть избыточно, но для Claude или GPT-5, где контекст поменьше, экономия токенов критична. Если интересно — напишите в комментариях, выложу модифицированную версию.

💡
Совет под занавес: не храните сгенерированные бандлы в репозитории — они быстро устаревают и захламляют диффы. Добавьте *.project-context.md в .gitignore. Генерируйте бандл по требованию, а если нужна автоматизация — вешайте на git-хук.

Подписаться на канал