У нейросетей есть ограничение на количество символов в чате или на число запросов. И бывает так, что лимит уже закончился, а разработка проекта — нет.

Тогда приходится открывать новый чат и заново напоминать контекст: что за проект, какая структура, какие файлы важны, где уже были изменения. Обычно это сводится к ручному копированию кода, а это долго и неудобно.

Отдельная проблема — 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));
    }
}

Скрипт я писал под свой стек, но его легко изменить так как вам надо. Можно добавить например:

  • параметр для указания расширения фалов, которые вам нужны для обсуждения

  • параметр только для вывода структуры проекта

  • параметры для указания маски для выбора толко определныых файлов

Я этого не делал потому, что данный скрипт нужен, чтобы начать обсуждение проекта, а не постоянно собирать запрос для нейросети.

Что делает скрипт

  • рекурсивно обходит проект;

  • может исключать не нужные директории вроде .gitnode_modulesbuildtarget; (строчки 13-15)

  • Можно указать расширения файлов которые вам нужны (строчки 8-10)

  • собирает структуру проекта; (строчки 64-66)

  • добавляет содержимое нужных файлов в один итоговый .txt; (строчки 71-84)

В result.txt или project_code.txt будет примерно текст такого содержания:

  • структура проекта

  • исходники кода

Весь текст нет смысла показывать там много букв, но контекст будет примерно таким:

PROJECT STRUCTURE:
==================
build.gradle
docker-compose.yml
README.md
settings.gradle
data\stats-data.json
gradle\wrapper\gradle-wrapper.properties
src\main\resources\application.properties
src\main\resources\questions\questions_en.json
src\main\resources\questions\questions_ru.json
src\main\resources\questions\questions_zh.json
src\main\resources\templates\index.html
src\main\resources\templates\lencioni-test.html
src\main\resources\templates\result.html
src\main\resources\templates\sher-test.html
src\main\resources\templates\stats.html
src\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. Надеюсь, скрипт окажется полезен кому-то ещё.

Комментарии (15)


  1. Scank
    28.05.2026 06:54

    Клод не запоминает контекст между сессиями ?


    1. FilipLinx Автор
      28.05.2026 06:54

      Если говорить о Claude.ai  да пока открыт тред он помнит, но в бесплатной версии лимиты быстро заканчиваются.
      Если говорить Claude Code то он действительно по моему сейчас умеет запоминать контекст между сессиями, но это платный продукт.


      1. Scank
        28.05.2026 06:54

        бесплатный даже обсуждать не стоит.
        (Calude.ai запоминает контекст, который хранится в истории чата)


  1. Ioanna
    28.05.2026 06:54

    Ага, у меня тоже такой скрипт есть, только на Python. Никак не дорасту до Claude Code, поэтому просто запускаю скрипт, выгружаю весь проект одним файлом и закидываю в claude.ai.


  1. Shado_vi
    28.05.2026 06:54

    нечто подобное у меня было в первой версии. на пайтон.
    потом я оптимизировал структуру до md.

    меньше токенов, понятней и структурированей для нейронок.

    # bevy_camera
    
    ## Project Structure
    
    ```text 
    Structure
    ```
    
    ## Cargo.toml
    
    ```toml
    CODE
    ```
    
    ## camera.rs
    
    ```rust
    CODE
    ```


    1. FilipLinx Автор
      28.05.2026 06:54

      Отличное решение. Доработаю на досуге.
      У меня есть продолжение этого дела, но это уже не совсем скрипт. Я делал плагин для perplexity по сочетанию клавишь alt+ctrl+p появляется окошко, где ты в дереве файлов выбираешь, то что нужно отправить нейросети. Тоже все одним файлом формируется. Но плагин не стал публиковать, потому что там были функции парсинга ответов от нейросети и создания файлов по ответу. Этакий cloude code только кнопку нужно нажать, чтобы изменились файлы или создались новые. DeepSeek, Perplexity дают пользоватся чатом практически без ограничений, но любые парсеры запрещены на странице. Сделаю потом отдельным плагином, в котором будет только выбор файлов и се одним контекстом из буфера.


      1. Shado_vi
        28.05.2026 06:54

        perplexity с осени сильно деградировал по качеству. и продолжает...

        смысл плагина не вижу.
        сейчас за чатам стоят агенты которые умеют не загружать файлы целиком в контекст а парсить в файлах только нужные им строки.
        а скрипт для сборки md уже содержит правила в том числе чёрные списки того что не надо добавлять.


  1. Yevgeny_VS
    28.05.2026 06:54

    Тоже есть такой велосипед. Отличие - запуск с одним параметром создает json со списком расширений, которые есть в проекте. Удаляю руками лишние и с другим ключом получаю общую простыню.


  1. PechoraDev
    28.05.2026 06:54

    Наверное все, кто работает с нейросетями мутили подобную фичу) У меня - скрипт на php, который также генерит структуру и код проекта в обычный txt или json файл


  1. breninsul
    28.05.2026 06:54

    А разве нельзя прокинуть claude на deepseek через условный LiteLLM?

    У z.ai проще , там есть api antropic, не нужны прокси


    1. breninsul
      28.05.2026 06:54

      А у дипсика тоже антропик-совместимый эндпоинт

      В общем решение проблем, которых нет. Всё уже сделали за вас


    1. Shado_vi
      28.05.2026 06:54

      тут наверно про режим через чат от провайдеров нейронок с их агентами на их серверах.
      LiteLLM это про api а не чат?
      даже для вайбкодинга генерация подобных файлов может быть полезна.


      1. breninsul
        28.05.2026 06:54

        ну если через веб-интерфейс то да. Но это же как так работать можно...


        1. Shado_vi
          28.05.2026 06:54

          а какие есть варианты ещё?
          вайбкодинг занимает больше времени и качество выдаёт хуже.


  1. nickmanecannotbeempty
    28.05.2026 06:54

    Есть же уже repomix