Продвинутый

Graphify: превращаем код и конфиги в граф знаний

Алексей Кузнецов
Алексей Кузнецов
Системный администратор4 ноября 2026 г.13 мин чтения

Graphify превращает код, документацию, SQL-схемы и PDF в запрашиваемый граф знаний. Локальный парсинг AST без векторного хранилища для Claude Code и Cursor.

Graphify: превращаем код и конфиги в граф знаний

Graphify превращает код, документацию, SQL-схемы и PDF в запрашиваемый граф знаний. Локальный парсинг AST без векторного хранилища для Claude Code и Cursor.

Что делает Graphify и зачем он инженеру

Что делает Graphify и зачем он инженеру

Graphify превращает код, документацию, SQL-схемы и PDF в запрашиваемый граф знаний. От обычного векторного поиска его отличает отсутствие эмбеддингов и векторной базы — парсинг идёт локально через AST, а результат отдаётся в Claude Code или Cursor как контекст для AI-агентов.

С практической точки зрения это значит, что вместо того чтобы кормить модель фрагментами кода по принципу «ближайший по косинусу», мы даём ей связанную структуру: зависимости между файлами, вызовы функций, связи таблиц в базе данных, ссылки в документации.

От репозитория к графу: как работает парсинг

Graphify обходит репозиторий, определяет язык каждого файла и строит абстрактное синтаксическое дерево (AST). Для Python используется встроенный модуль ast, для TypeScript — парсер на базе TypeScript compiler API, для SQL — отдельный парсер схем. Результат не сохраняется в векторное хранилище, а складывается в граф: узлы — это файлы, классы, функции, таблицы, поля; рёбра — вызовы, импорты, внешние ключи, ссылки.

Пример. Допустим, в репозитории есть простой сервис на Python:

python
# services/users.py
from database import SessionLocal
from models import User

def get_user_by_email(email: str):
    db = SessionLocal()
    return db.query(User).filter(User.email == email).first()

Graphify распарсит этот файл, выделит функцию get_user_by_email, увидит импорт SessionLocal из database и User из models, и свяжет узел функции с узлами этих модулей. Если в другом файле есть вызов get_user_by_email, в графе появится ребро между ними.

Потом граф можно экспортировать в формат, который понимают Claude Code и Cursor — например, JSON с узлами и рёбрами, или загрузить в локальную графовую базу, если нужно что-то более тяжёлое. Базовый вариант работает без внешней базы данных.

Почему не нужна векторная база

Векторные базы решают задачу семантического поиска: найти фрагмент текста, который «по смыслу» близко к запросу. Проблема в том, что семантика не равна структуре. Модель может найти функцию, которая упоминает «email», но не поймёт, что эта функция вызывается из трёх других мест и зависит от конкретной таблицы в базе данных.

С графом всё иначе. Если спросить Claude Code: «где используется функция get_user_by_email?», агент ходит по рёбрам графа, а не угадывает по эмбеддингам. Это даёт предсказуемость: ответ не плавает в зависимости от того, как модель настроена сегодня утром.

Во-первых, векторная база требует индексации, хранения эмбеддингов и переиндексации при изменении кода. Во-вторых, она не показывает связи между сущностями — только близость по тексту. В-третьих, для локальной работы на ноутбуке векторная база — лишний вес: она потребляет много оперативной памяти и требует отдельного сервиса.

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

Код проекта открыт: Graphify-Labs/graphify: Кодовая база в запросную графическую базу знаний.

Для сравнения с другими инструментами для агентов можно почитать про QA-агенты Momentic ищут баги в веб и мобильных приложениях и про ECC: оптимизация и безопасность агентных оболочек.

Установка и первый запуск /graphify

Установка и первый запуск /graphify

Код растёт быстрее, чем успевает расти документация. Через полгода никто не помнит, зачем в сервисе оплаты есть отдельный репозиторий с миграциями, а схема базы данных размазана по десяти SQL-файлам. Новый разработчик тратит первые две недели на то, чтобы просто найти, где лежит описание API. Graphify решает это иначе, чем обычно делают AI-инструменты: он не ведёт векторное хранилище и не перекладывает ваш код в облако. Локальный парсер обходит AST, вытягивает связи между функциями, таблицами и конфигами, и складывает всё в запрашиваемый граф. Для Claude Code и Cursor это означает, что агент может спросить «где описывается схема пользователей» и получить точный ответ с путями к файлам, а не вероятностное угадывание. Подробнее о концепции можно прочитать в обзоре кодовой базы Graphify-Labs/graphify.

Установить Graphify можно одной командой. Я предпочитаю собирать из исходников, но бинарник тоже есть в релизах.

bash
cargo install graphify-cli
graphify --version
graphify init ./my-project

После init в корне проекта появится файл graphify.yaml. Это единственный конфиг, который нужно править руками — GUI для тех, кто не знает, где лежит конфиг.

yaml
# graphify.yaml
project: my-project
roots:
  - ./src
  - ./sql
  - ./docs
parsers:
  - rust
  - typescript
  - sql
  - markdown
exclude:
  - target/
  - node_modules/
  - *.lock
output:
  path: ./graphify.db
  format: sqlite

Во-первых, укажите в roots все директории, которые стоит индексировать. Во-вторых, добавьте в exclude всё, что не несёт смысловой нагрузки — иначе граф раздуется от сгенерированного кода. С практической точки зрения, достаточно одного запуска graphify build, чтобы получить первый снимок состояния репозитория.

bash
graphify build

Подключение навыка в Claude Code, Cursor и Codex

Graphify отдаёт данные через MCP (Model Context Protocol), поэтому подключение сводится к добавлению одного сервера в конфигурацию IDE или агента.

Claude Code

В файле ~/.claude.json (или .mcp.json в корне проекта) добавьте запись:

json
{
  "mcpServers": {
    "graphify": {
      "command": "graphify",
      "args": ["mcp", "--db", "./graphify.db"]
    }
  }
}

После перезапуска Claude Code навык станет доступен под именем graphify. Агент сам решит, когда к нему обращаться, но вы можете явно вызвать его в запросе.

Cursor

Откройте Настройки → MCP Servers → Add new server. Укажите команду и аргументы, как в примере выше. Cursor подхватит сервер без перезапуска окна.

Codex

Для Codex конфиг лежит в ~/.codex/config.toml:

toml
[mcp.servers.graphify]
command = "graphify"
args = ["mcp", "--db", "./graphify.db"]

Если вы используете Codex в терминале, убедитесь, что переменная окружения CODEX_MCP_ENABLED=1 выставлена, иначе навык не подхватится.

Первый запрос к кодовой базе

Теперь можно спросить у агента что-то конкретное. Не «расскажи про проект», а именно то, что обычно требует чтения десяти файлов.

В Claude Code:

@graphify найди, где описывается схема таблицы пользователей и какие сервисы от неё зависят

Агент обойдёт граф, найдёт SQL-определение, связанные ORM-модели и эндпоинты, и выдаст ответ со ссылками на файлы и номерами строк.

В Cursor достаточно выделить фрагмент кода и спросить:

Как эта функция связана с конфигурацией базы данных?

Graphify покажет рёбра между функцией, конфигурационным файлом и миграцией.

Если мы посмотрим на практическую сторону, первый запуск на среднем репозитории занимает от нескольких секунд до пары минут. Граф хранится локально в SQLite, поэтому нет задержек на запросы к внешнему API и нет риска утечки кода. Предсказуемость конфигурации здесь играет ключевую роль: вы точно знаете, какие директории проиндексированы, и можете повторить сборку на любой машине одной командой.

На следующем этапе стоит настроить автоматическое обновление графа при каждом коммите — например, через Git-хук или CI-задачу. Тогда агенты всегда будут работать с актуальной структурой, а не с снимком трёхнедельной давности.

Как Graphify объясняет связи между файлами

Как Graphify объясняет связи между файлами

Когда открываешь проект, которым не пользовался полгода, нужно не угадывание семантической близости, а точный ответ: какой файл импортирует какой, какая таблица фигурирует в запросе, какой ключ конфига управляет каким сервисом. Graphify строит именно такой граф — локально, через разбор AST, без векторного хранилища. Для Claude Code и Cursor это значит, что агент получает предсказуемую карту зависимостей, а не вероятностное приближение.

AST-разбор и детерминизм

Graphify обходит дерево файлов, парсит исходный код в абстрактное синтаксическое дерево и извлекает из него узлы и рёбра. Узел — это файл, функция, класс, таблица или ключ конфига. Ребро — связь между ними: импорт, вызов, ссылка на таблицу, обращение к переменной окружения.

Главное отличие от векторных подходов — детерминизм. Один и тот же набор файлов всегда даёт одинаковый граф. Если ты изменишь одну строку импорта, пересчитается только затронутое ребро, а не весь индекс эмбеддингов. Для ИИ-агентов это критично — как и для QA-агентов Momentic, которым нужна точная карта приложения, а не предположения. Claude Code или Cursor могут доверять результату запроса, потому что он не «плывёт» от переобучения модели.

Пример. Возьмём простой Python-файл:

python
# services/users.py
from database import SessionLocal
from models.user import User

def get_user(user_id: int):
    db = SessionLocal()
    return db.query(User).filter(User.id == user_id).first()

Graphify зафиксирует три ребра из этого файла:

  • services/users.py → database (импорт SessionLocal);
  • services/users.py → models.user (импорт User);
  • services/users.py → User (использование в запросе).

Никаких эмбеддингов, никакого угадывания. Если завтра переименуешь User в Client, граф обновится детерминированно, и агент сразу увидит, где именно нужно поправить код.

Примеры рёбер: импорты, SQL, конфиги

Graphify выделяет три типа связей, которые на практике объясняют архитектуру проекта лучше любого README.

Импорты. Это базовое ребро между модулями. Graphify понимает import и require в разных языках и показывает, кто от кого зависит.

typescript
// src/api.ts
import { createClient } from './db/client';
import { config } from '../config/env';

Здесь два ребра: src/api.ts зависит от src/db/client и от src/config/env. Если агент спрашивает «где инициализируется клиент БД?», ответ — конкретный файл, а не похожий по смыслу фрагмент.

SQL. Graphify парсит SQL-строки и файлы миграций, выделяет имена таблиц и соединяет их с кодом, который эти таблицы использует.

sql
SELECT id, email FROM orders WHERE user_id = $1 AND status = 'paid';

Результат в графе: файл с этим запросом связан с таблицей orders. Если ты планируешь переименовать таблицу, достаточно обойти все рёбра, выходящие из узла orders, и увидишь список файлов для правки.

Конфиги. YAML, JSON, .env — тоже узлы графа. Graphify связывает конфигурацию с кодом, который её читает, и с сервисами, которые от неё зависят.

yaml
# docker-compose.yml
services:
  api:
    image: myapp/api:latest
    environment:
      - DATABASE_URL=postgres://graphify:password@db:5432/graphify
      - LOG_LEVEL=debug

Ребро из docker-compose.yml ведёт к ключу DATABASE_URL, а из кода — к месту, где этот ключ считывается через os.getenv или аналоги. С практической точки зрения, это позволяет ответить на вопрос «какие переменные окружения критичны для API?» без чтения всего репозитория.

Если мы посмотрим на граф целиком, получится карта, где код, схема базы и конфигурация связаны явно. Для Claude Code и Cursor это значит, что агент может переходить по рёбрам от таблицы к файлу, от файла к конфигу и обратно — и всё это работает локально, без отправки кода во внешнее векторное хранилище. Подробнее про кодовую базу проекта можно посмотреть в репозитории Graphify-Labs/graphify.

Ограничения и когда подход перестаёт работать

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

Graphify-Labs/graphify: Кодовая база в запросную графическую базу знаний

Что не попадает в граф

Во-первых, парсер AST работает с исходным кодом, а не с поведением программы. Если в коде есть динамический импорт, граф покажет только вызов функции, но не то, какой модуль загрузится в итоге.

python
import importlib
import os

provider_name = os.environ.get("PAYMENT_PROVIDER", "stripe")
module = importlib.import_module(f"providers.{provider_name}")
provider = module.Provider()

Graphify зафиксирует узел import_module и ребро к строке с os.environ, но не разрешит providers.stripe или providers.paypal. С практической точки зрения, это значит, что зависимости, выбираемые через переменные окружения, остаются невидимыми.

Во-вторых, декларативная инфраструктура не попадает в граф кода. Kubernetes-манифесты, Helm-чарты, Ansible-инвентари — это не AST в привычном смысле. Graphify может распарсить YAML как текст, но не поймёт, что {{ .Values.image.tag }} ссылается на конкретный образ в конкретном реестре.

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments
spec:
  template:
    spec:
      containers:
        - name: app
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: url

Здесь граф не покажет, какой секрет реально лежит в db-credentials, и с каким кластером БД приложение соединится в продакшене. У меня на домашнем сервере «Винни-Пух» такое вылезало постоянно: в графе всё выглядит связно, а в рантайме приложение не может достучаться до БД, потому что сетевая политика или секрет подтягиваются извне.

В-третьих, семантический разрыв. AST знает, что функция calculate_vat вызывает round, но не знает, что она реализует начисление НДС для ЕС. Комментарии, документация в docstring и бизнес-контекст из PDF не превращаются в рёбра графа автоматически. Если логика описана только в словах, граф будет пустым в этом месте.

Наконец, минифицированный код, обфусцированные скрипты и бинарные файлы не дают ничего полезного. Парсер либо пропустит их, либо построит нечитаемый граф из тысяч безымянных функций.

Альтернативы и комбинация с векторным поиском

Если статический граф не отвечает на вопрос «как это работает?», стоит добавить векторный поиск. Эмбеддинги ищут по смыслу, а не по структуре: запрос «где описана логика начисления налогов?» найдёт релевантные фрагменты даже без точного совпадения имён функций.

С практической точки зрения, лучше использовать гибрид:

  • Граф — для структурных вопросов: кто вызывает эту функцию, какие таблицы затрагивает миграция, откуда берётся переменная окружения.
  • Векторный поиск — для семантических вопросов: как реализована оплата, где описана бизнес-логика скидок, что делает этот микросервис.

Для Claude Code и Cursor это выглядит так: вы даёте агенту доступ и к графу зависимостей, и к векторному индексу документации. Агент сам решает, какой инструмент использовать. Если нужно понять, не сломает ли изменение сигнатуры функции смежные сервисы, он идёт в граф. Если нужно разобраться, почему расчёт налога даёт не ту сумму, — ищет по эмбеддингам в документации и коммитах.

Если мы посмотрим на архитектуру агента, то увидим, что векторный поиск не заменяет граф, и наоборот. Эмбеддинги могут выдать релевантный, но устаревший фрагмент кода, а граф покажет актуальные зависимости, но не объяснит намерение автора. Я видел, как команды пытались заменить один другим и получали ложные срабатывания: агент находил похожую функцию в другом микросервисе и предлагал скопировать её, не зная, что в оригинале есть критичное условие по обработке пустых значений.

Если вы уже используете агентные оболочки в роде Claude Code, стоит посмотреть в сторону ECC: оптимизация и безопасность агентных оболочек — там разобрано, как ограничить доступ агента к файловой системе, чтобы он не случайно изменил конфиг, которого не должен трогать.

Для поиска багов в уже работающем приложении статический анализ беспомощен. Лучше подключить что-то в роде QA-агентов Momentic ищут баги в веб и мобильных приложениях, которые наблюдают за приложением в рантайме, а не только читают исходники.

Вывод простой: Graphify даёт предсказуемую карту кода, но карта не местность. Если вам нужно понять, что делает программа в реальности, добавьте векторный поиск и инструменты рантаймового анализа. Граф остаётся основой, а векторное хранилище — дополнением, которое закрывает слепые зоны статического парсинга.

Часто задаваемые вопросы

Чем Graphify отличается от векторного поиска в редакторе?

Векторный поиск ищет фрагменты по близости эмбеддингов, а Graphify строит реальные связи между узлами: импорты, вызовы функций, внешние ключи. С практической точки зрения это значит, что вы получаете не «похожий» кусок кода, а точную зависимость. Если нужно понять, зачем в репозитории существует тот или иной модуль, граф покажет это без гаданий на косинусное сходство.

Нужно ли разворачивать графовую базу данных?

Не обязательно. Graphify может отдать результат в виде JSON с узлами и рёбрами, который Claude Code или Cursor подхватят как контекст. Если хотите хранить граф надолго и запрашивать его повторно — тогда имеет смысл загрузить в локальную графовую базу, но для разовой работы с кодом этого не требуется.

Какие языки и форматы поддерживает Graphify?

На данный момент парсит Python через встроенный модуль ast, TypeScript через TypeScript compiler API, а также SQL-схемы и PDF. Узлами становятся файлы, классы, функции, таблицы и поля, а рёбрами — импорты, вызовы, внешние ключи и ссылки. Если ваш стек выходит за эти рамки, придётся подождать добавления новых парсеров или написать свой.

Безопасно ли использовать Graphify с закрытым кодом?

Да, потому что парсинг идёт локально на вашей машине, а код не отправляется ни в какое облако. Граф остаётся у вас, и вы сами решаете, какую часть отдать в Claude Code или Cursor. С точки зрения конфиденциальности это предсказуемее, чем отдавать репозиторий на обработку стороннему сервису.

Как Graphify попадает в Claude Code и Cursor?

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

Поделиться:TelegramX / TwitterVK

Читайте также