SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-08-14

Graft: карта кодової бази для coding agents

Graft аналізує репозиторій через tree-sitter, створює карту зі зв’язками символів і надає пошук через MCP, щоб агент не вивчав структуру заново.

Що таке карта кодової бази для coding agents

Карта кодової бази для coding agents — це постійний індекс вашого репозиторію, у якому агент шукає потрібну інформацію, замість того щоб під час кожного нового сеансу щоразу виконувати пошук по всій кодовій базі. Graft — одна з реалізацій цієї ідеї. Він аналізує код за допомогою tree-sitter, записує папку зі зв’язаними markdown-вузлами та графом зв’язків для кожного символу, а також надає інструменти пошуку через MCP (model context protocol — стандартний інтерфейс, за допомогою якого coding agents викликають зовнішні інструменти).

Graft не є proxy і не є gateway. Між вашим агентом і model API нічого не розміщується. Карта — це папка на диску, яку читає агент. Ця відмінність визначає, яку саме проблему ви розв’язуєте: self-hosted token gateway обліковує та маршрутизує запити, які ви вже надсилаєте, тоді як карта змінює кількість запитів, які взагалі потрібно надсилати.

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

Чому coding agents витрачають контекст на повторне виявлення структури

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

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

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

Ви вже використовуєте слабший варіант цього підходу. Файл AGENTS.md із вашими правилами не дає агенту щоразу заново виводити ваші правила. Згенерована карта не дає йому щоразу заново визначати структуру. Відмінність полягає в тому, хто її створює. Файл з інструкціями ви пишете вручну, тому він залишається невеликим. Карту генерує парсер, тому вона може охоплювати десять тисяч файлів. Щоб зрозуміти, куди саме витрачається бюджет у межах сеансу, див. як Claude Code використовує своє вікно контексту.

Що насправді створює Graft

Два артефакти в одній папці graft/ у корені репозиторію.

Перший — граф вузлів у форматі пов’язаних markdown-файлів, по одному файлу на вузол. Кожен вузол містить короткий опис простою англійською мовою, «суть» важливих рядків логіки, взятих із вихідного коду, точні шляхи до вихідних файлів із хешем вмісту, типізовані wikilinks до інших вузлів (depends_on, part_of, uses, implements), а також розділ нотаток, який зберігається під час повторної генерації. У ньому можна записати контекст, який парсер не здатен визначити.

Другий — graft/.graph/wiring.json, структурний граф для кожного символу, який tree-sitter витягує з коду: визначення, посилання та ребра викликів між ними.

Такий поділ важливий, оскільки лише для однієї частини потрібна модель. graft build працює виключно на tree-sitter і ніколи не викликає LLM (large language model), тому результат є детермінованим і не потребує витрат. graft build --deep додає текстові описи та «суть» для кожного символу, а для цього виконуються виклики моделі, за які потрібно платити.

Підтримка мов має кілька рівнів, і рівень визначає, наскільки можна довіряти графу викликів. TypeScript, JavaScript, Python, Go та Java отримують кросфайлове розв’язання з урахуванням областей видимості. Rust, C, C++, C#, Ruby, PHP, Kotlin, Scala, Swift, Elixir, Solidity, OCaml, Zig та Dart отримують символи й узагальнені ребра викликів. Це означає, що ребро може ґрунтуватися на збігу імені, а не на розв’язаному посиланні. Ребра рівня компілятора можна ввімкнути за допомогою --lsp і language server, наприклад 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/graft

npm ls -g має вивести @nanonets/graft@0.10.1. Навмисно зафіксуйте цю версію. Простий npm install -g @nanonets/graft у момент виконання визначає тег latest. Якщо проєкт випускає кілька мінорних релізів на місяць, у вівторок ви можете отримати інструмент, відмінний від того, який ваш колега встановив у понеділок. Зафіксована версія забезпечує однакові прапорці CLI та формат графа для всіх. Оновлення виконується тоді, коли ви вирішите.

Потім підключіть його до репозиторію, яким ви керуєте:

cd /path/to/your/repo
graft init --dry-run
graft init

graft init запитує, до яких ваших coding agents потрібно підключити Graft, а потім будує граф. Спочатку виконайте --dry-run і перегляньте список файлів, які команда планує змінити, оскільки деякі з них розташовані за межами репозиторію. graft init є ідемпотентною командою та не перезаписує наявні конфігурації, тому повторний запуск безпечний.

Станом на серпень 2026 року підключення підтримує Claude Code, Cursor, Codex, GitHub Copilot, Google Gemini, Kiro, Windsurf і AdaL. Claude Code отримує найглибшу інтеграцію: запис MCP server, statusline із розміром графа та інформацією про його актуальність, post-edit hooks для перебудови графа і skill file у .claude/. Для решти створюється instruction або rule file, який повідомляє агенту про доступні інструменти. Отже, «підтримується» означає, що Graft записує конфігурацію підключення. Якщо агент ігнорує власний rules file, він також ігноруватиме карту. Саме тому зазвичай агенти ігнорують інструкції, які ви для них пишете, і тут діє та сама причина.

Що потрапляє до репозиторію, а що не додається до git

Після graft init очікуйте на такі зміни:

  • graft/: граф markdown-вузлів і graft/.graph/wiring.json. Додається до .gitignore автоматично.
  • .mcp.json: реєструє MCP-сервер graft, щоб Claude Code запускав його.
  • .claude/settings.json: об’єднується на місці, додаючи statusline і post-edit hooks.
  • 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 окремо пропускає hook shim.

Граф — це кеш, подібний до node_modules. Не додавайте його до комітів. Він за секунди генерується повторно з коду, змінюється майже після кожного редагування, а його коміт перетворює однорядкове виправлення на diff із кількома сотнями файлів, який ніхто з рев’юерів не читатиме. Натомість додавайте до коміту файли інтеграції, зокрема AGENTS.md і .mcp.json. Колега клонує репозиторій, виконує graft build і отримує власний локальний граф.

Перевірте, що правило ігнорування додалося, перш ніж створювати перший коміт:

grep -n graft .gitignore
git status --short

grep має вивести рядок, що містить 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" --json

graft ask має вивести вузли, упорядковані за релевантністю, із посиланнями file:line, а не вміст файлів. У цьому полягає весь механізм: агент отримує вказівник і відкриває один файл, замість того щоб читати десять файлів у пошуках потрібного. graft viz відкриває інтерактивний переглядач на localhost, якщо ви хочете самостійно переглянути граф. Якщо graft ask не повертає нічого корисного для запитання, на яке ви могли б відповісти за тридцять секунд, граф застарів або ваша мова належить до широкого рівня підтримки. У такому разі карта також не допоможе вашому агенту.

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

Що відбувається з графом після зміни коду

Структурне оновлення виконується швидко й автоматично. Graft читає робоче дерево, а не git, тому для нього однаково видимі незбережена зміна та зміна, додана до staging area. Під час запиту повторно аналізуються лише файли, у яких змінився stat. У документації проєкту зазначено, що це додає приблизно 3 ms накладних витрат. Під час перебудови наприкінці ітерації обробляються лише файли, у яких змінився код. Використовуйте GRAFT_NO_REFRESH=1 або передайте --no-refresh, щоб отримати відповідь із графа на диску без повторного аналізу. Передайте --no-reuse, щоб примусово повторно проаналізувати все без використання кешу. Це потрібно робити після оновлення самого Graft.

Частина, яку генерує модель, працює інакше. Саме тут помилки можуть залишатися непомітними. Зведення та ключові висновки кешуються. Кожен вузол зберігає хеш вмісту своїх джерел. Тому після зміни вихідного файлу вузол позначається як застарілий, а не вважається актуальним. Цей прапорець корисний лише тоді, коли його обробляють. Оновіть дані за допомогою graft build --deep. Це знову використає токени моделі.

Зробіть застарілість видимою:

graft check .
echo $?

Код завершення 0 означає, що граф відповідає коду. Код завершення 1 означає розбіжність. Запускайте цю перевірку з pre-push hook або для гілки в CI. Так карта, якій уже шість місяців, не зможе впевнено відповідати про код, переписаний у березні.

Уважно читайте опубліковані результати бенчмарків

Головне твердження Graft звучить так: «до 4 разів дешевше та у 3 рази швидше, без погіршення коректності або з мінімальним погіршенням». Ці показники взято із власних бенчмарків проєкту, опублікованих у його README. Нижче наведено повні результати двох запусків.

ChartGraft's own published benchmark results, versus a no-map baseline, as of August 2026
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 request у PocketBase: вартість становила 11.02 долара США проти 13.91 для базового варіанта.

Розглядайте все це як бенчмарк постачальника. Є два чинники, які обмежують його інформативність. Контрольований прогін включає власний репозиторій Graft — кодову базу, під яку автори налаштовували інструмент. SWE-bench Verified — це загальнодоступний набір даних із завданнями з відомих open-source проєктів на Python, а загальнодоступні набори даних зазвичай оптимізують під інструменти, навіть якщо це не було чиїмось наміром. Жоден із цих результатів не описує ваш приватний монорепозиторій, у якого є власні правила іменування та власний мертвий код.

Коректність потребує окремого аналізу. У контрольованому прогоні вона не змінилася: 93% із map проти 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, оскільки саме там міститься вміст файлів. Додайте ці два значення.

Запустіть завдання 3 рази, щоразу в новому сеансі, коли карта підключена. Потім видаліть запис graft із .mcp.json і запустіть завдання ще 3 рази. Порівнюйте медіани, а не окремі запуски, оскільки результати роботи агента значно відрізняються, і один невдалий запуск може дати висновок, протилежний дійсності. Також зафіксуйте кількість викликів інструментів: виклики інструментів є механізмом, а токени — наслідком, тому економія токенів без зменшення кількості викликів інструментів означає, що змінилося щось інше.

Потім відніміть витрати, які бенчмарк не показує. graft build --deep витрачає токени моделі під час кожного повного оновлення. Шість схем інструментів передаються в кожному запиті. Якщо ваші агенти працюють на орендованому сервері, встановлення жорсткого ліміту витрат на агентів перетворює це з несподіваних витрат на бюджет, а матеріал що насправді показує телеметрія coding agent описує, що залишає машину після ввімкнення експортера.

Де карта кодової бази перестає бути корисною?

  • Репозиторій уже вміщується в контекст. Для одного невеликого сервісу карта не потрібна, а за кожен запит ви все одно платите за шість схем інструментів. Якщо ваш агент сьогодні знаходить будь-який файл за один або два виклики інструментів, пропустіть її.
  • Ваша мова належить до загальної категорії. Узагальнені зв’язки викликів означають, що graft callers може не знайти викликач або створити хибний зв’язок через збіг імен. Перш ніж довіряти радіусу впливу, перевірте його за допомогою graft grep.
  • Граф застарів, і ніхто цього не помітив. graft check завершується з кодом 1, якщо виявлено розбіжності. Це корисно лише тоді, коли команду хтось запускає. Додайте її до hook або кроку CI, а не покладайтеся на звичку.
  • Monorepo потребує обмеження області. Один monorepo з Git автоматично розділяється за workspace-файлом, go.mod, pyproject.toml або Cargo.toml, а graft ask "..." --in services/billing/ обмежує запит одним підпроєктом. Той самий підхід, який підказує використовувати вкладені файли AGENTS.md для кожного пакета, застосовується і до карти.
  • Агент ігнорує зв’язки. Перегляньте виклики інструментів у реальному сеансі, перш ніж робити висновок, що карта використовується. Якщо агент і далі запускає grep, це означає, що він не прочитав файл правил.

FAQ

Чи потрібно додавати папку graft/ до git?

Ні. graft build автоматично додає graft/ до вашого .gitignore, оскільки граф є кешем, який можна повторно згенерувати, як і node_modules. Він змінюється майже після кожного редагування, тому його додавання до репозиторію приховує справжні відмінності під сотнями згенерованих файлів. Додайте до репозиторію конфігурацію, яка повідомляє агентам про наявність карти, зокрема 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-сумісної кінцевої точки. 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 мс додаткових витрат. Незакомічені зміни також враховуються, оскільки Graft читає файли, а не історію git. Застарілими стають створені моделлю підсумки: кожен вузол зберігає хеш умісту своїх джерел, а зміна джерела позначає вузол як застарілий, не перезаписуючи його. Виконайте graft check ., щоб переглянути розбіжності, а потім graft build --deep, щоб оновити текстову частину.

Які агенти для написання коду можуть використовувати Graft уже сьогодні?

Станом на August 2026 graft init налаштовує підключення Claude Code, Cursor, Codex, GitHub Copilot, Google Gemini, Kiro, Windsurf і AdaL. Claude Code отримує найбільше можливостей: запис сервера MCP у .mcp.json, statusline, хуки після редагування та файл skill у .claude/. Codex отримує секцію AGENTS.md, а також загальносистемні записи у ~/.codex/, які graft init --no-global пропускає. Інші агенти отримують файл правил або steering-файл. Будь-який інший MCP-клієнт може безпосередньо використовувати сервер, якщо зареєструвати команду npx -y @nanonets/graft@0.10.1 mcp.