Graft: создание карты кодовой базы для AI-агентов
Используйте Graft для индексации репозитория через tree-sitter. Инструмент создает карту связей для MCP, что исключает повторное сканирование файлов и экономит контекст модели.
Что такое карта кодовой базы для агентов программирования
Карта кодовой базы для агентов программирования — это постоянный индекс вашего репозитория, в котором агент ищет информацию, вместо того чтобы каждый раз выполнять поиск через grep с нуля в новой сессии. Graft — одна из реализаций этой идеи. Она анализирует ваш код с помощью tree-sitter, создает папку со связанными узлами в формате markdown и графом связей для каждого символа, а также предоставляет инструменты поиска через MCP (model context protocol, стандартный интерфейс, который агенты программирования используют для вызова внешних инструментов).
Graft не является прокси или шлюзом. Ничто не находится между вашим агентом и API модели. Карта — это папка на диске, которую считывает агент. Это различие определяет, какую именно задачу вы решаете: самохостируемый шлюз токенов учитывает и маршрутизирует запросы, которые вы уже отправляете, в то время как карта меняет общее количество запросов, которые вам необходимо отправить.
Эта техника старше данного инструмента и переживет его. Сначала изучите саму технику, а затем механику её работы.
Почему агенты для написания кода тратят контекст на повторное изучение структуры
Посмотрите, как агент начинает работу над репозиторием, который он уже видел пятьдесят раз. Он выводит список директорий. Он выполняет grep для поиска символа. Он открывает три файла, чтобы найти, в каком из них определена функция, а затем четвертый, чтобы узнать, кто её вызывает. Ни одно из этих действий не является основной задачей. Это ориентация, и за неё приходится платить входными токенами в каждой сессии.
Причина проста. У модели нет памяти между сессиями. Всё, что агент узнал о вашей структуре, находилось в окне контекста, которое было удалено после завершения сессии. Поэтому процесс обнаружения каждый раз запускается с нуля за полную стоимость. В большом репозитории фаза ориентации стоит дороже, чем само редактирование: десять вызовов инструментов для поиска кода и один для его изменения. Ориентация — это лишь половина счета, а редактирование — вторая, поэтому навык, заставляющий агента вносить минимально необходимые изменения стоит сочетать с картой, а не выбирать что-то одно.
Карта разрывает этот цикл, перенося процесс обнаружения с модели на диск. Парсер один раз обходит репозиторий, записывает, где определен каждый символ и кто его вызывает, а затем поддерживает эту запись в актуальном состоянии по мере изменения кода. Агент задает один вопрос и получает ответ с указанием файла и строки. Повторное исследование превращается в дешевый поиск.
Вы уже используете более слабую версию этого подхода. Файл AGENTS.md, описывающий ваши соглашения, не дает агенту каждый раз заново выводить ваши правила. Сгенерированная карта не дает ему заново изучать структуру. Разница заключается в том, кто это пишет. Вы вручную составляете файл инструкций, поэтому он остается небольшим. Парсер генерирует карту, поэтому она может охватывать десять тысяч файлов. О том, на что на самом деле расходуется бюджет внутри сессии, читайте в как Claude Code расходует окно контекста.
Что на самом деле создает Graft
Два артефакта, оба находятся в папке graft/ в корне репозитория.
Первый — это граф узлов, написанный в виде связанных markdown-файлов, по одному файлу на узел. Каждый узел содержит краткое описание на обычном языке, «суть» важных логических строк, извлеченных из исходного кода, точные исходные файлы с хешем содержимого, типизированные вики-ссылки на другие узлы (depends_on, part_of, uses, implements) и раздел заметок, который сохраняется при перегенерации, чтобы вы могли записывать контекст, который парсер не может определить самостоятельно.
Второй — это graft/.graph/wiring.json, структурный граф по символам, который извлекает tree-sitter: определения, ссылки и ребра вызовов между ними.
Это разделение важно, так как только одна часть требует использования модели. graft build — это чистый tree-sitter, он никогда не обращается к LLM (большой языковой модели), поэтому он детерминирован и бесплатен. graft build --deep добавляет текстовые описания и «суть» по каждому символу, а это вызовы модели, за которые вы платите.
Поддержка языков разделена на уровни, и уровень определяет, насколько можно доверять графу вызовов. TypeScript, JavaScript, Python, Go и Java получают разрешение ссылок между файлами с учетом области видимости. Rust, C, C++, C#, Ruby, PHP, Kotlin, Scala, Swift, Elixir, Solidity, OCaml, Zig и Dart получают символы и общие ребра вызовов, что означает, что ребро может быть совпадением имен, а не разрешенной ссылкой. Ребра уровня компилятора подключаются опционально с помощью --lsp и сервера языка, такого как rust-analyzer или gopls.
Установка Graft и фиксация версии
Для работы Graft требуется Node.js версии 20 или новее; проект распространяется по лицензии MIT. По состоянию на август 2026 года актуальным релизом является 0.10.1, а первая опубликованная версия 0.1.0 датирована июлем 2026 года. Учитывайте, что это новое программное обеспечение.
npm install -g @nanonets/graft@0.10.1
npm ls -g @nanonets/graftnpm ls -g должен вывести @nanonets/graft@0.10.1. Фиксируйте версию намеренно. Обычная команда npm install -g @nanonets/graft разрешает тег latest в момент запуска, и в проекте, выпускающем несколько минорных релизов в месяц, это приведет к тому, что во вторник у вас будет другой инструмент, нежели тот, который коллега установил в понедельник. Фиксированная версия гарантирует единообразие флагов CLI и формата графа для всех участников, поэтому вы обновляетесь только тогда, когда сами принимаете такое решение.
Затем подключите его к своему репозиторию:
cd /path/to/your/repo
graft init --dry-run
graft initgraft init запрашивает, какой из ваших агентов для написания кода нужно подключить, после чего строит граф. Сначала запустите --dry-run и изучите список файлов, которые планируется изменить, так как некоторые из них находятся вне репозитория. Команда graft init идемпотентна и не перезаписывает существующие конфигурации, поэтому повторный запуск безопасен.
По состоянию на август 2026 года интеграция охватывает Claude Code, Cursor, Codex, GitHub Copilot, Google Gemini, Kiro, Windsurf и AdaL. Claude Code получает наиболее глубокую интеграцию: запись MCP-сервера, строку состояния с размером и актуальностью графа, хуки после редактирования, которые перестраивают граф, и файл навыков в .claude/. Остальные агенты получают инструкцию или файл правил, сообщающий агенту о наличии инструментов. Таким образом, «поддержка» означает, что Graft создает конфигурацию подключения, поэтому агент, игнорирующий собственные файлы правил, проигнорирует и карту. Это обычная причина, по которой агенты игнорируют написанные для них инструкции, и здесь это работает так же, как и везде.
Что попадает в ваш репозиторий, а что не должно находиться в git
После graft init ожидайте появления следующих элементов:
graft/: граф узлов markdown иgraft/.graph/wiring.json. Автоматически добавлены в.gitignore..mcp.json: регистрирует MCP-сервер graft, чтобы Claude Code запускал его..claude/settings.json: объединён на месте, добавляет строку состояния и хуки после редактирования.AGENTS.md,GEMINI.md,.github/copilot-instructions.md,.cursor/rules/graft.mdc,.kiro/steering/graft.md,.windsurf/rules/graft.mdи.adal/skills/graft/SKILL.md: секции, ограниченные маркерами, добавленные в файлы, соответствующие выбранным вами агентам.~/.codex/config.toml,~/.codex/hooks.jsonи~/.codex/hooks/graft/graft-hooks.cjs: глобальные настройки для всей системы, записываются только при выборе Codex.graft init --no-globalпропускает их, аgraft init --no-hooksотдельно пропускает прослойку хуков.
Граф является кэшем, подобно node_modules. Не добавляйте его в коммит. Он пересоздаётся из кода за секунды, меняется почти при каждом редактировании, а его коммит превращает исправление одной строки в diff из сотен файлов, который никто не будет проверять. Вместо этого коммитьте конфигурацию связей, включая AGENTS.md и .mcp.json. Коллега клонирует репозиторий, выполняет graft build и получает собственный локальный граф.
Убедитесь, что правило игнорирования добавлено до вашего первого коммита:
grep -n graft .gitignore
git status --shortgrep должен вывести строку, содержащую graft/, а git status --short не должен выводить ничего в graft/. Если файлы из graft/ появляются в этом выводе, значит, запись об игнорировании отсутствует или переопределена в другом месте. Исправьте это до коммита, так как git продолжает отслеживать файл, если он уже был добавлен, и последующее редактирование .gitignore не исключит его из отслеживания.
Если вы предпочитаете зарегистрировать MCP-сервер вручную или зафиксировать его на той же версии, которую вы установили, запись будет выглядеть так:
{
"mcpServers": {
"graft": {
"command": "npx",
"args": ["-y", "@nanonets/graft@0.10.1", "mcp"]
}
}
}Инструменты поиска, которые ваш агент использует вместо grep
Graft предоставляет шесть инструментов через MCP. graft_find_code возвращает ранжированные узлы для описания задачи с указанием файла и строки. graft_file_api возвращает все сигнатуры в файле без тел функций. graft_trace_calls выполняет обход вызывающих или вызываемых функций на несколько уровней в глубину. graft_find_all возвращает результаты поиска по регулярным выражениям, сгруппированные по символам. graft_repo_map позволяет получить первое представление о незнакомом репозитории. graft_check_freshness сообщает, соответствует ли граф текущему состоянию кода.
У каждого из них есть аналог в CLI, с помощью которого можно проверить, что именно получает ваш агент:
graft map .
graft ask "where do we validate the refresh token"
graft skeleton src/auth/session.ts
graft callers validateRefreshToken
graft callers validateRefreshToken --direction out
graft grep "refresh_token" --jsongraft ask должен выводить ранжированные узлы со ссылками file:line, а не содержимое файлов. В этом заключается весь механизм: агент получает указатель и открывает один файл вместо чтения десяти для поиска нужного. graft viz открывает интерактивный просмотрщик на localhost, если вы хотите изучить граф самостоятельно. Если graft ask не возвращает ничего полезного для вопроса, на который вы могли бы ответить за 30 секунд, значит, граф устарел или ваш язык программирования относится к категории с базовой поддержкой, и карта не поможет вашему агенту.
Одну из затрат легко упустить из виду. Шесть определений инструментов внедряются в системный промпт каждого запроса на протяжении всей сессии. Вы платите за это независимо от того, использует агент карту или нет. В репозитории, который целиком помещается в контекстное окно, эти фиксированные расходы могут превышать экономию от использования поиска по графу.
Что происходит с графом при изменении кода
Структурное обновление выполняется быстро и автоматически. Graft считывает рабочее дерево, а не git, поэтому изменения, которые вы еще не закоммитили или добавили в индекс, видны инструменту одинаково. Запрос повторно парсит только те файлы, у которых изменился статус stat, что, согласно документации проекта, создает накладные расходы примерно в 3 мс, а пересборка в конце цикла затрагивает только те файлы, где переместился код. Установите GRAFT_NO_REFRESH=1 или передайте --no-refresh, чтобы получить ответ из графа на диске без повторного парсинга. Передайте --no-reuse, чтобы принудительно выполнить «холодный» парсинг всего проекта; это необходимо после обновления самого Graft.
Часть, созданная моделью, ведет себя иначе, и именно она может незаметно прийти в неактуальное состояние. Сводки и ключевые моменты кэшируются. Каждый узел записывает хеш содержимого своих исходных файлов, поэтому при изменении исходного файла узел помечается как устаревший, а не отображается как актуальный. Этот флаг помогает только в том случае, если что-то реагирует на него. Выполните обновление с помощью graft build --deep, что потребует повторного расхода токенов модели.
Сделайте устаревание видимым:
graft check .
echo $?Код завершения 0 означает, что граф соответствует коду. Код завершения 1 означает расхождение. Запускайте эту проверку в pre-push хуке или в ветке в CI, чтобы карта полугодовой давности не выдавала уверенные ответы о коде, который был переписан в марте.
Внимательно изучайте опубликованные результаты тестов
Основное заявление Graft гласит: «до 4 раз дешевле и в 3 раза быстрее, при лучшей или аналогичной точности». Эти данные взяты из собственных тестов проекта, опубликованных в его README. Ниже приведены два полных прогона, о которых сообщает проект.
The data behind this chart
[
{
"label": "Controlled sweep",
"run_count": 162,
"token_saving_pct": 42,
"tool_call_saving_pct": 46,
"correctness_pct": 93,
"baseline_correctness_pct": 93
},
{
"label": "SWE-bench Verified",
"run_count": 50,
"token_saving_pct": 23,
"tool_call_saving_pct": 25,
"correctness_pct": 66,
"baseline_correctness_pct": 54
}
]Контролируемое исследование включает 162 запусков по двум репозиториям, один из которых — сам Graft, с тремя попытками на каждую задачу. Отчет показывает на 42% меньше токенов и на 46% меньше вызовов инструментов. Прогон SWE-bench Verified состоит из 50 примеров с использованием одной и той же модели для обоих вариантов, и он показывает меньшую экономию: 23% токенов и 25% вызовов инструментов. Третий прогон воспроизвел пять объединенных pull-реквестов PocketBase со стоимостью 11.02 доллара США против 13.91 доллара для базовой линии.
Относитесь ко всему этому как к вендорскому тестированию. Есть два фактора, ограничивающих информативность этих данных. Контролируемое исследование включает собственный репозиторий Graft, под который авторы и настраивали инструмент. SWE-bench Verified — это публичный набор данных с задачами из известных open-source проектов на Python, а публичные наборы данных — это именно то, под что инструменты оптимизируются, намеренно или нет. Ни один из этих тестов не является показателем работы в вашем частном монорепозитории, у которого свои привычки именования и свой «мертвый» код.
Вопрос точности заслуживает отдельного внимания. В контролируемом исследовании показатель не изменился: 93% с использованием карты против 93% без нее. Рост до 66% с 54% наблюдается только в SWE-bench Verified. Инструмент, который сокращает ваши расходы на токены и сохраняет качество на прежнем уровне, — это выгодное решение. Просто не стоит объединять результат точности из SWE-bench с результатом экономии токенов из другого исследования и выдавать их за одно утверждение.
Измерьте собственную дельту токенов, прежде чем верить любым данным
Единственное число, которое имеет значение, — это число из вашего репозитория. Этот метод займет у вас вторую половину дня.
Выберите задачу, которую вы можете повторить в точности. Вопрос лучше правки, так как правка изменяет репозиторий, и второй запуск перестает быть тем же самым экспериментом. «Какой модуль обеспечивает ограничение частоты запросов на маршруте входа» — это правильный формат.
Включите телеметрию и направьте её в свой терминал:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
claudeКонсольный экспортер выводит записи метрик по мере их сбора. Нужная вам метрика — claude_code.token.usage, которая содержит атрибут type со значением input, output, cacheRead или cacheCreation. Ориентация отображается в input и cacheRead, так как именно туда попадает содержимое файлов. Сложите эти два значения.
Выполните задачу три раза, каждый раз в новой сессии, с подключенной картой. Затем удалите запись graft из .mcp.json и выполните задачу еще три раза. Сравнивайте медианные значения, а не результаты отдельных запусков, так как время работы агента сильно варьируется, и один неудачный запуск может показать вам результат, противоположный истине. Также запишите количество вызовов инструментов: вызовы инструментов — это механизм, а токены — это следствие, поэтому экономия токенов без снижения количества вызовов инструментов означает, что изменилось что-то другое.
Затем вычтите расходы, которые не учитываются в бенчмарке. graft build --deep расходует токены модели при каждом полном обновлении. Шесть схем инструментов передаются в каждом запросе. Если ваши агенты работают на арендованном сервере, установка жесткого лимита на расходы агента превращает это из неожиданности в бюджет, а что на самом деле сообщает телеметрия агента для написания кода описывает, какие данные покидают машину после включения экспортера.
В каких случаях карта кодовой базы перестает быть полезной?
- Репозиторий уже помещается в контекст. Одиночный небольшой сервис не нуждается в карте, а вы продолжаете платить за шесть схем инструментов при каждом запросе. Если ваш агент находит любой файл за один или два вызова инструментов, пропустите этот шаг.
- Ваш язык относится к категории с широким охватом. Общие ребра вызовов означают, что
graft callersможет пропустить вызывающую сторону или создать ложную связь из-за совпадения имен. Подтверждайте данные с помощьюgraft grep, прежде чем доверять оценке радиуса поражения. - Граф устарел, и этого никто не заметил.
graft checkзавершается с кодом 1 при расхождении данных, что полезно только в том случае, если его кто-то запускает. Это должен быть хук или шаг CI, а не привычка. - Монорепозиторий требует сегментации. Монорепозиторий с одним git-репозиторием автоматически разделяется файлом рабочей области,
go.mod,pyproject.tomlилиCargo.toml, аgraft ask "..." --in services/billing/сужает область поиска до одного подпроекта. Тот же принцип, который приводит к вложенным файлам AGENTS.md для каждого пакета, применим и к карте. - Агент игнорирует структуру связей. Проследите за вызовами инструментов в реальной сессии, прежде чем делать вывод, что карта используется. Если агент продолжает выполнять
grep, это означает, что он не читал файл правил.
FAQ
Стоит ли добавлять папку graft/ в git?
Нет. graft build автоматически добавляет graft/ в ваш .gitignore, так как граф является кэшем, который можно пересоздать, подобно node_modules. Он меняется почти при каждом редактировании, поэтому добавление его в репозиторий скроет реальные изменения (diffs) за сотнями сгенерированных файлов. Добавляйте в репозиторий только конфигурацию связей, которая сообщает агентам о существовании карты, включая AGENTS.md и .mcp.json, а выполнение graft build оставьте каждому участнику команды локально. Перед первым коммитом выполните проверку с помощью grep -n graft .gitignore и git status --short, так как git продолжает отслеживать файл после того, как он был добавлен, и редактирование .gitignore впоследствии не отменит отслеживание.
Требует ли Graft оплаты за использование?
Структурная часть — нет. graft build, graft ask, graft check и шесть инструментов извлечения MCP — это операции tree-sitter, которые не обращаются к модели. graft build --deep — это платная часть: она создает краткие описания на обычном языке и ключевые выжимки для каждого символа с помощью LLM, настроенной через GRAFT_PROVIDER, GRAFT_API_KEY и GRAFT_MODEL, а также GRAFT_BASE_URL для любого OpenAI-совместимого endpoint. Вы можете использовать Graft только со структурной частью и не тратить токены на сам граф.
Сколько токенов на самом деле сэкономит карта кодовой базы в моем репозитории?
Никто не скажет вам точно без измерений. Проект сообщает о снижении потребления токенов на 42% в ходе собственного тестирования за 162 прогонов и на 23% в SWE-bench Verified по сравнению с базовым уровнем без карты. Оба теста являются вендорскими, один из них частично выполнен на собственном репозитории Graft, и ни один из них не описывает ваш закрытый код. Выполните один повторяемый запрос три раза с картой и три раза без нее, установив CLAUDE_CODE_ENABLE_TELEMETRY=1 и OTEL_METRICS_EXPORTER=console, а затем сравните медианные значения claude_code.token.usage для типов input и cacheRead.
Что происходит с графом при рефакторинге?
Структура перепарсивается самостоятельно. Graft проверяет состояние рабочего дерева и перепарсивает только измененные файлы, поэтому переименование учитывается в следующем запросе с накладными расходами примерно в 3 мс. Инструмент видит незакоммиченные изменения, так как читает файлы, а не историю git. Устаревают описания, написанные моделью: каждый узел хранит хэш содержимого своих исходных файлов, и изменение исходного файла помечает узел как устаревший, вместо того чтобы перезаписывать его. Запустите graft check ., чтобы увидеть расхождения, а затем graft build --deep, чтобы обновить текстовую часть.
Какие агенты для программирования могут использовать Graft сегодня?
По состоянию на август 2026 года graft init поддерживает Claude Code, Cursor, Codex, GitHub Copilot, Google Gemini, Kiro, Windsurf и AdaL. Claude Code получает максимум возможностей: запись MCP-сервера в .mcp.json, строку состояния, хуки после редактирования и файл навыков в .claude/. Codex получает секцию AGENTS.md плюс записи на уровне всей системы в ~/.codex/, которые graft init --no-global пропускает. Остальные получают файл правил или файл управления. Любой другой MCP-клиент может использовать сервер напрямую, зарегистрировав команду npx -y @nanonets/graft@0.10.1 mcp.