У нейросетей есть ограничение на количество символов в чате или на число запросов. И бывает так, что лимит уже закончился, а разработка проекта — нет.
Тогда приходится открывать новый чат и заново напоминать контекст: что за проект, какая структура, какие файлы важны, где уже были изменения. Обычно это сводится к ручному копированию кода, а это долго и неудобно.
Отдельная проблема — DeepSeek не всегда понимает ссылки на репозиторий и не смотрит код по ним так, как хотелось бы. Зато если дать ему сам контекст кода текстом, он включает его в анализ.
Идея
Пишем скрипт, который не надо компилировать, а сразу можно выполнить. Нужна java не ниже 11 версии. Идея в том что мы в один файл собираем весь контекст который нужен для анализа.
Вместо ручного копирования десятков файлов получается одна операция.
java ScanProject.java
Я обычно кладу данный файлик в корень папки с проектами и вызываю уже в самом проекте примерно так:
# из папки проектаjava ../../ScanProject.java
Или так:
# из корня папки с проектамиjava ScanProject.java .\java\scanner-profile\ result.txt
# Можно и для конкретной папки проекта, если нужен не весь код, а только часть.java ScanProject.java .\java\scanner-profile\src\main\java\ru\mcs\scanner\profile\domain\model result.txt
Вам нужно лишь создать файл ScanProject.java и поместить следующий код:
import java.io.*;import java.nio.file.*;import java.nio.file.attribute.BasicFileAttributes;import java.util.ArrayList;import java.util.List;public class ScanProject { private static final List<String> INCLUDED_EXTENSIONS = List.of( ".java", ".gradle", ".kt", ".kts", ".xml", ".yml", ".yaml", ".properties", ".json", ".md", ".txt" ); private static final List<String> EXCLUDED_DIRS = List.of( ".git", ".gradle", "build", "target", "out", "bin", ".idea", "node_modules" ); public static void main(String[] args) { String projectRoot = args.length > 0 ? args[0] : "."; String outputFile = args.length > 1 ? args[1] : "project_code.txt"; try { scanProject(projectRoot, outputFile); System.out.println("Project scanned successfully! Output: " + outputFile); } catch (IOException e) { System.err.println("Error scanning project: " + e.getMessage()); e.printStackTrace(); } } private static void scanProject(String rootPath, String outputFile) throws IOException { Path root = Paths.get(rootPath).toAbsolutePath(); List<Path> files = new ArrayList<>(); // Собираем все файлы Files.walkFileTree(root, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { String dirName = dir.getFileName().toString(); if (EXCLUDED_DIRS.contains(dirName)) { return FileVisitResult.SKIP_SUBTREE; } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (isIncludedFile(file)) { files.add(file); } return FileVisitResult.CONTINUE; } }); // Сортируем файлы для удобства чтения files.sort((p1, p2) -> { int depthCompare = Integer.compare(p1.getNameCount(), p2.getNameCount()); return depthCompare != 0 ? depthCompare : p1.compareTo(p2); }); // Записываем в выходной файл try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) { writer.println("PROJECT STRUCTURE:"); writer.println("=================="); for (Path file : files) { writer.println(root.relativize(file)); } writer.println("\n\nSOURCE CODE:"); writer.println("============"); for (Path file : files) { writer.println("\n" + "=".repeat(80)); writer.println("FILE: " + root.relativize(file)); writer.println("=".repeat(80)); try { List<String> lines = Files.readAllLines(file); for (String line : lines) { writer.println(line); } } catch (IOException e) { writer.println("ERROR READING FILE: " + e.getMessage()); } } } } private static boolean isIncludedFile(Path file) { String fileName = file.getFileName().toString(); return INCLUDED_EXTENSIONS.stream() .anyMatch(ext -> fileName.toLowerCase().endsWith(ext)); }}
Скрипт я писал под свой стек, но его легко изменить так как вам надо. Можно добавить например:
-
параметр для указания расширения фалов, которые вам нужны для обсуждения
-
параметр только для вывода структуры проекта
-
параметры для указания маски для выбора толко определныых файлов
Я этого не делал потому, что данный скрипт нужен, чтобы начать обсуждение проекта, а не постоянно собирать запрос для нейросети.
Что делает скрипт
-
рекурсивно обходит проект;
-
может исключать не нужные директории вроде
.git,node_modules,build,target; (строчки 13-15) -
Можно указать расширения файлов которые вам нужны (строчки 8-10)
-
собирает структуру проекта; (строчки 64-66)
-
добавляет содержимое нужных файлов в один итоговый
.txt; (строчки 71-84)
В result.txt или project_code.txt будет примерно текст такого содержания:
-
структура проекта
-
исходники кода
Весь текст нет смысла показывать там много букв, но контекст будет примерно таким:
PROJECT STRUCTURE:==================build.gradledocker-compose.ymlREADME.mdsettings.gradledata\stats-data.jsongradle\wrapper\gradle-wrapper.propertiessrc\main\resources\application.propertiessrc\main\resources\questions\questions_en.jsonsrc\main\resources\questions\questions_ru.jsonsrc\main\resources\questions\questions_zh.jsonsrc\main\resources\templates\index.htmlsrc\main\resources\templates\lencioni-test.htmlsrc\main\resources\templates\result.htmlsrc\main\resources\templates\sher-test.htmlsrc\main\resources\templates\stats.htmlsrc\main\resources\templates\welcome.html....SOURCE CODE:============================================================================================FILE: build.gradle================================================================================<source code>================================================================================FILE: docker-compose.yml================================================================================<source code>....================================================================================FILE: src\main\java\ru\mcs\scanner\profile\ScannerProfileApplication.java================================================================================<source code>================================================================================FILE: src\main\java\ru\mcs\scanner\profile\controller\TestController.java================================================================================<source code>================================================================================FILE: src\main\java\ru\mcs\scanner\profile\service\AiRecommendationService.java================================================================================<source code>....
Зачем это вообще нужно
Многие могут возразить: а зачем, если есть GitHub Copilot, Codex или Claude, которые видят весь проект?
Отвечаю:
-
Стоимость. Copilot и Claude с доступом к репозиторию — платные. DeepSeek бесплатный и при этом хорошо работает с кодом.
-
Независимость от IDE. Скрипт работает из терминала. Никаких плагинов, расширений, привязки к VS Code или IDEA.
-
Работа с любой моделью. Сегодня DeepSeek, завтра — любая другая модель в браузере или API. Один файл подходит для всех.
-
Приватность. Ты видишь точно, что ты отдаёшь. Не «модель проиндексировала репозиторий», а конкретный текстовый файл, который можно открыть и проверить.
Для меня это способ быстро начать новый чат с нейросетью и напомнить ей, что уже было в прошлом обсуждении, без долгого ручного копирования файлов.
Не идеальный инструмент, а просто маленькая утилита, которая экономит время в реальной работе.
P.S. Надеюсь, скрипт окажется полезен кому-то ещё.
ссылка на оригинал статьи https://habr.com/ru/articles/1040420/