Graphify C# даёт ИИ-агентам точный поиск использований кода

Graphify C# даёт ИИ-агентам точный поиск использований кода

На Hacker News показали Graphify C#, бесплатный headless-индексатор кода на C# (без графического интерфейса, рассчитанный на запуск из скриптов и агентов), лицензированный по MIT. Отправная точка разработчиков, конкретная проблема: когда ИИ-агент работает с чужим кодом и ищет, кто использует такой-то метод, поле или интерфейс, обычный текстовый поиск находит только совпадения по написанию. Он не может достоверно определить, какая именно перегрузка метода была вызвана, какому проекту принадлежит вызывающий код, или является ли найденная реализация интерфейса именно тем символом, который имелся в виду. Graphify C# загружает проект через MSBuild (систему сборки .NET) и спрашивает у Roslyn, официального компилятора C#/.NET с открытым API, что каждый символ означает на самом деле. Результат, устойчивые идентификаторы символов и направленные связи между ними: вызовы, ссылки, реализации интерфейсов, наследование и переопределения, в том числе через перегрузки, дженерики, границы разных проектов и разных целевых платформ. В граф попадают почти все виды объявлений и связей C#, от классов, структур, интерфейсов и делегатов до локальных функций, параметров и переменных LINQ-запросов, а также связи, которые выбирает сам компилятор: перегруженные операторы, неявные преобразования, деконструкция, foreach/await/using, сопоставление с образцом и выражения коллекций. Всё это сохраняется в один JSON-файл с узлами, рёбрами и гиперрёбрами, который агент может прочитать напрямую, опросить через jq, обработать своим кодом или передать отдельному, не входящему в этот пакет инструменту Graphify (без «C#» в названии), о его роли ниже.

Работу инструмента разработчики показывают на примере его собственного репозитория. Для внутреннего метода DeclarationCatalogBuilder.ForTesting граф находит ровно один входящий вызов, разрешённый компилятором, из тестового класса Graphify.CSharp.Tests.Roslyn.CSharp14FeatureTests, строка 143 файла CSharp14FeatureTests.cs. В документации подчёркивается: это семантическое доказательство, а не подсчёт текстовых совпадений, и по такому доказательству агент может классифицировать метод как используемый только тестами и вынести решение на проверку человеку.

Ставится Graphify C# как обычный dotnet global tool: dotnet tool install --global Graphify.CSharp --framework net10.0. Пакет включает две сборки инструмента, между которыми переключаются флагом --framework: в примере установки из документации указан net10.0, в примере обновления, net11.0. Дальше индексатор запускается на решении, файле .sln.slnx.csproj или файловом SDK-приложении на .cs, с параметрами --root, --configuration и --output; SDK, пакеты и входные данные MSBuild самого проекта должны быть доступны локально, иначе Roslyn не сможет его загрузить. Для агента, который обращается к проекту постоянно, есть фоновый режим слежения, включается флагом --watch, держит рабочее пространство Roslyn прогретым и готовит изменившиеся проекты в фоне, а обычный запуск без него служит явным барьером обновления и возвращает управление только после того, как весь JSON-снимок пересобран заново; флаг --rebuild сбрасывает промежуточный кэш. В комплект входит отдельный навык (skill) с именем graphify-csharp, который объясняет агенту, когда обновлять индекс, как идти по связям и где заканчивается статический анализ; путь установки навыка разный для Codex-совместимых проектов и для Claude Code, и после установки или обновления навыка сессию агента нужно перезапустить. Если агент навыками не пользуется, разработчики предлагают короткое правило прямо в инструкциях проекта: перед ответом на вопросы о структуре C#-кода обновлять graphify-out/csharp.json инструментом graphify-csharp, искать объявления по symbol_key, смотреть рёбра calls и references, а ноль входящих рёбер считать зафиксированным статическим наблюдением, а не доказательством, что код нигде не используется.

Разработчики прямо описывают место инструмента среди соседей по рынку. Rider и ReSharper дают программисту интерактивную навигацию, инспекции, рефакторинги и быстрые исправления внутри среды разработки. NDepend, широкий коммерческий пакет для анализа архитектуры и качества кода: зависимости, метрики, правила, отчёты, базовые линии, визуализации. Graphify C# занимает более узкую полосу, семантические данные о C#-коде в открытом формате, рассчитанные на ИИ-агента, а не на человека перед экраном IDE. Пересечение с NDepend по вызовам, зависимостям, наследованию и поиску мёртвого кода разработчики признают напрямую, но настаивают: это не бесплатный клон NDepend и не замена IDE, а Roslyn-нативный семантический индекс, на котором могут строиться другие инструменты и агенты. Сам Graphify C# работает независимо и не вызывает, не загружает и не требует отдельный продукт с названием просто Graphify: без него JSON-граф можно опрашивать агентом, через jq, из кода на C# или Python. Вместе с Graphify тот же граф получает более высокоуровневые запросы, поиск путей, объяснения, кластеризацию и экспорт, например, запрос на естественном языке вида «какие методы вызывают сервис заказов».

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

Ключевые факты

  • Graphify C#, бесплатный индексатор кода на C# по лицензии MIT: он загружает проект через MSBuild, спрашивает у компилятора Roslyn, что означает каждый символ, и сохраняет вызовы, ссылки, наследование и переопределения, включая перегрузки, дженерики и связи между проектами, в один JSON-файл с узлами и рёбрами.
  • На собственном репозитории проекта показан пример: для метода DeclarationCatalogBuilder.ForTesting граф находит ровно один входящий вызов, разрешённый компилятором, из тестового класса CSharp14FeatureTests, строка 143, и по этому факту, а не по текстовому совпадению, метод можно пометить как используемый только тестами.
  • Ставится инструмент как dotnet global tool (dotnet tool install --global Graphify.CSharp --framework net10.0) и включает две сборки, выбираемые флагом --framework; в комплекте, навык graphify-csharp с отдельными путями установки для Codex и для Claude Code.
  • Инструмент можно использовать отдельно, опрашивать JSON-граф агентом или через jq, либо вместе с отдельным продуктом Graphify, который добавляет запросы на естественном языке, поиск путей и кластеризацию по тому же графу.
  • Разработчики сами очерчивают границу метода: он видит только то, что компилятор разрешает статически, поэтому «ноль входящих ссылок», не доказательство, что код не используется в рантайме, а классификация «только для тестов» и решение об удалении кода всё равно остаются за человеком.

Почему это важно

Агент, который автономно правит код, регулярно должен отвечать на вопрос «кто ещё использует эту функцию, поле или интерфейс», прежде чем что-то переименовать, удалить или отрефакторить. Дешёвый способ получить такой ответ, текстовый поиск или догадка самой модели по фрагменту кода, и оба способа в C# систематически ошибаются на перегруженных методах, дженериках и реализациях интерфейсов: буквы совпадают, а вызывается на самом деле другой символ. Graphify C# убирает эту догадку: агент получает не текстовое совпадение, а факт, который разрешил тот же компилятор Roslyn, что в итоге и собирает программу. Это тот же принцип, на котором в IDE строится функция поиска использований (Find Usages) для разработчика-человека, только перенесённый в автономный, без интерфейса, открытый JSON-формат, чтобы им мог пользоваться любой агент или скрипт, а не только человек внутри Rider или ReSharper.

Кому это важно

В первую очередь, командам, которые уже подключают ИИ-агентов вроде Claude Code или Codex к реальным проектам на C#/.NET, особенно к большим решениям из нескольких проектов, где вручную держать в голове все связи невозможно. Важно это и тем, кто использует агента для рискованных операций, поиска мёртвого кода, подготовки к удалению или крупному рефакторингу, потому что именно там ошибка текстового поиска дороже всего. Разработчикам собственных инструментов и интеграций Graphify C# даёт готовый источник структурированной правды о C#-коде, который не нужно строить самим поверх Roslyn с нуля. Меньше это нужно тем, кто работает внутри Rider или ReSharper сам, без агента в контуре: интерактивная навигация там уже решена другим способом, а Graphify C# рассчитан именно на потребление машиной, а не человеком за экраном.

Как это применить

Инструмент бесплатный и распространяется по лицензии MIT. Ставится как обычный dotnet global tool: dotnet tool install --global Graphify.CSharp --framework net10.0; пакет включает две сборки, и нужная выбирается тем же флагом --framework, в примере обновления из документации указан net11.0. Дальше индексатор запускается на .sln.slnx.csproj или файловом SDK-приложении на .cs с параметрами --root, --configuration и --output; проектные SDK, пакеты и входные данные MSBuild должны быть доступны локально. На выходе, один JSON-файл с узлами и рёбрами, который можно смотреть агентом напрямую, опрашивать через jq или обрабатывать своим кодом. Для агента, который работает с проектом постоянно, есть отдельный режим: флаг --watch держит рабочее пространство Roslyn прогретым в фоне, чтобы не пересобирать индекс с нуля на каждый вопрос, а --rebuild сбрасывает кэш, если что-то пошло не так. В комплекте, навык graphify-csharp с инструкциями, когда обновлять индекс и как читать рёбра; путь установки навыка разный для Codex и для Claude Code, и сессию агента после установки нужно перезапустить. Без навыков хватает короткого правила в инструкциях проекта: обновлять graphify-out/csharp.json перед ответом на вопросы о структуре кода и опознавать объявления по symbol_key.

Можно ли доверять

Материал, Show HN, то есть автор представляет собственный проект, а не независимый обзор со стороны. Инструмент открытый и лицензирован по MIT, так что логику разрешения символов можно проверить по исходному коду, а не верить на слово. Хороший сигнал доверия, сами разработчики явно, без маркетингового приукрашивания, описывают, где заканчиваются возможности их инструмента: статическую природу анализа они называют ограничением, а не выдают её за полное решение. При этом в тексте нет ни имени автора или организации-мейнтейнера, ни даты выхода или номера версии, ни каких-либо цифр по производительности или числу пользователей, судить по одному этому материалу, как инструмент ведёт себя на реальных больших кодовых базах, не на чем; это требует отдельной проверки.

Риски и подводные камни

Главное предупреждение сформулировано в самой документации: Graphify C# показывает только то, что Roslyn может определить статически. Рефлексия, внедрение зависимостей, нативные обратные вызовы, динамические вызовы и код за пределами загруженной сборки способны создавать в рантайме связи, которых в графе не будет ни одним ребром. Отсюда три следствия, которые разработчики называют сами: «ноль входящих ссылок» в графе значит только «ноль замеченных статических ссылок», а не доказательство, что метод нигде не используется; пометка «используется только тестами» зависит от того, как сам пользователь классифицирует свои проекты и неймспейсы, а не выставляется инструментом автоматически; и любой кандидат на удаление, который подсказал граф, всё равно требует решения человека, а не может приниматься агентом самостоятельно. Отдельное практическое ограничение: инструменту нужны локально доступные SDK, пакеты и входные данные MSBuild проекта, на «голом» исходном коде без пригодного к сборке окружения он не работает.