Часть стека Ataraxy Labs — агент-ориентированная инфраструктура для разработки программного обеспечения. См. также: weave (драйвер слияния Git на уровне сущностей) · inspect (семантическое ревью кода) · opensessions (боковая панель tmux для агентов).
Манифест: https://ataraxy-labs.com/#thesis · Статьи: https://ataraxy-labs.com/blogs · LLM-интерфейс: https://ataraxy-labs.com/llms.txt
Семантический контроль версий, построенный поверх Git.
Вместо изменённых строк sem показывает, какие сущности изменились: функции, методы, классы.
sem — инструмент семантического контроля версий, работающий поверх Git. Он разбирает (парсит) код с помощью tree-sitter, извлекает каждую функцию, класс и метод как отдельную сущность и строит дифф на уровне сущностей, а не строк. В результате вместо «изменились строки x–y» вы видите «функция blahh была изменена».
Инструмент работает в любом Git-репозитории без какой-либо предварительной настройки.
Установка
curl -fsSL https://raw.githubusercontent.com/Ataraxy-Labs/sem/main/install.sh | sh
Через Homebrew:
brew install sem-cli
Или установите npm-обёртку в node_modules:
npm install --save-dev @ataraxy-labs/sem
При использовании Bun нужно разрешить пакету выполнять postinstall-скрипт, загружающий бинарный файл:
bun add -d @ataraxy-labs/sem
bun pm trust @ataraxy-labs/sem
После установки обновиться до последней версии можно в любой момент:
sem update
Или соберите из исходников (требуется Rust):
cargo install --git https://github.com/Ataraxy-Labs/sem sem-cli
Также можно скачать готовый бинарный файл со страницы GitHub Releases.
Или запустить через Docker:
docker build -t sem .
docker run --rm -it -u "$(id -u):$(id -g)" -v "$(pwd):/repo" sem diff
Конфликт имён с GNU Parallel
GNU Parallel устанавливает бинарный файл sem (/usr/bin/sem) как символическую ссылку на parallel. Если оба инструмента установлены одновременно, они будут конфликтовать. Выполните sem --version, чтобы проверить, какой именно sem используется. (#77)
Быстрые способы решения:
# Вариант 1: псевдоним в профиле оболочки (~/.bashrc, ~/.zshrc)
alias sem="$HOME/.cargo/bin/sem"
# Вариант 2: убедитесь, что каталог cargo bin стоит первым в PATH
export PATH="$HOME/.cargo/bin:$PATH"
# Вариант 3: если установлено через Homebrew
export PATH="$(brew --prefix)/bin:$PATH"
Если вы установили пакет через npm/bun, бинарный файл находится в node_modules/.bin/sem и вызывается через npx sem или bunx sem — конфликта в этом случае не возникает.
Команды
Работает в любом Git-репозитории без предварительной настройки. Также может использоваться вне Git для сравнения произвольных файлов.
sem хранит SQLite-кэш сущностей за пределами репозитория — по умолчанию в системном каталоге кэша (OS cache directory). Чтобы изменить корневой каталог кэша, задайте переменную SEM_CACHE_DIR=/path/to/cache; локальные переопределения на уровне репозитория игнорируются, чтобы файлы кэша не «загрязняли» рабочее дерево.
sem diff
Дифф на уровне сущностей с определением переименований, структурным хэшированием и пословным выделением изменений.
# Семантический дифф рабочих изменений
sem diff
# Только индексированные изменения (staged)
sem diff --staged
# Конкретный коммит
sem diff --commit abc1234
# Диапазон коммитов
sem diff --from HEAD~5 --to HEAD
# Подробный режим (пословный инлайн-дифф для каждой сущности)
sem diff -v
# Вывод в виде обычного текста (в стиле git status)
sem diff --format plain
# JSON-вывод (для ИИ-агентов, CI-пайплайнов)
sem diff --format json
# Markdown-вывод (для PR, отчётов)
sem diff --format markdown
# Сравнить два произвольных файла (репозиторий не нужен)
sem diff file1.ts file2.ts
# Читать изменения файлов из stdin (репозиторий не нужен)
echo '[{"filePath":"src/main.rs","status":"modified","beforeContent":"...","afterContent":"..."}]' \
| sem diff --stdin --format json
# Только определённые типы файлов
sem diff --file-exts .py .rs
sem impact
Граф межфайловых зависимостей показывает, что сломается при изменении той или иной сущности.
# Полный анализ влияния
sem impact authenticateUser
# Только прямые зависимости
sem impact authenticateUser --deps
# Только прямые зависимые
sem impact authenticateUser --dependents
# Только затронутые тесты
sem impact authenticateUser --tests
# JSON-вывод
sem impact authenticateUser --json
# Уточнить по файлу
sem impact authenticateUser --file src/auth.ts
# Включить сгенерированные/сборочные каталоги, которые при стандартном сканировании пропускаются
sem impact authenticateUser --no-default-excludes
sem blame
Аннотация на уровне сущностей: показывает, кто последним изменял каждую функцию, класс или метод.
sem blame src/auth.ts
# JSON-вывод
sem blame src/auth.ts --json
sem log
История изменений отдельной сущности в git-истории.
sem log authenticateUser
# Подробный режим (показывает дифф содержимого между версиями)
sem log authenticateUser -v
# Ограничить количество проверяемых коммитов
sem log authenticateUser --limit 20
# JSON-вывод
sem log authenticateUser --json
sem entities
Список всех сущностей в указанном файле или каталоге. Без аргументов эквивалентно ..
sem entities
sem entities .
sem entities src/auth.ts
# JSON-вывод
sem entities --json
sem entities src/auth.ts --json
# Включить сгенерированные/сборочные каталоги, которые при стандартном сканировании пропускаются
sem entities --no-default-excludes
sem context
Контекст для больших языковых моделей (LLM) с ограничением по токенам: сама сущность, её зависимости и зависимые сущности, уложенные в жёсткий бюджет токенов содержимого. Если сигнатура целевой сущности не умещается в бюджет, JSON-вывод содержит target_omitted: true.
sem context authenticateUser
# Задать размер токен-бюджета
sem context authenticateUser --budget 4000
# JSON-вывод
sem context authenticateUser --json
# Включить сгенерированные/сборочные каталоги, которые при стандартном сканировании пропускаются
sem context authenticateUser --no-default-excludes
Использование как дифф-инструмент Git по умолчанию
Замените вывод git diff диффами на уровне сущностей. Агенты и разработчики будут автоматически получать вывод sem, не меняя привычных команд.
sem setup
После этого git diff будет показывать изменения на уровне сущностей вместо строчного диффа. Никакой дополнительной настройки ни для агентов, ни для разработчиков не требуется — всё, что вызывает git diff, автоматически получает вывод sem. Кроме того, устанавливается pre-commit-хук, показывающий радиус поражения (blast radius) индексированных изменений на уровне сущностей.
Чтобы отключить и вернуться к стандартному git diff:
sem unsetup
Поддерживаемые языки
31 язык программирования с полным извлечением сущностей через tree-sitter:
| Язык | Расширения | Сущности |
|---|---|---|
TypeScript |
|
функции, классы, интерфейсы, типы, перечисления, экспорты |
JavaScript |
|
функции, классы, переменные, экспорты |
Python |
|
функции, классы, определения с декораторами |
Go |
|
функции, методы, типы, переменные, константы |
Rust |
|
функции, структуры, перечисления, импл-блоки, трейты, модули, константы |
Java |
|
классы, методы, интерфейсы, перечисления, поля, конструкторы |
C |
|
функции, структуры, перечисления, объединения, typedef |
C++ |
|
функции, классы, структуры, перечисления, пространства имён, шаблоны |
C# |
|
классы, методы, интерфейсы, перечисления, структуры, свойства |
Ruby |
|
методы, классы, модули |
PHP |
|
функции, классы, методы, интерфейсы, трейты, перечисления |
Swift |
|
функции, классы, протоколы, структуры, перечисления, свойства |
Elixir |
|
модули, функции, макросы, охранные выражения, протоколы |
Bash |
|
функции |
HCL/Terraform |
|
блоки, атрибуты (квалифицированные имена для вложенных блоков) |
Kotlin |
|
классы, интерфейсы, объекты, функции, свойства, companion-объекты |
Fortran |
|
функции, подпрограммы, модули, программы |
Vue |
|
блоки template/script/style + вложенные сущности TS/JS |
XML |
|
элементы (вложенные, идентификация по имени тега) |
ERB |
|
блоки, выражения, теги кода |
Svelte |
|
блоки компонента + rune JS/TS модули |
Perl |
|
подпрограммы, пакеты |
Dart |
|
классы, миксины, расширения, перечисления, псевдонимы типов, функции |
OCaml |
|
значения, модули, типы, классы, внешние объявления |
Scala |
|
классы, объекты, трейты, перечисления, функции, val, расширения |
Nix |
|
привязки, объявления inherit |
Haskell |
|
функции, сигнатуры, типы данных, newtype, классы, экземпляры, синонимы типов |
Elm |
|
объявления значений, псевдонимы типов, объявления типов, аннотации портов, объявления infix |
Clojure |
|
переменные, функции, макросы, мультиметоды, протоколы, записи, типы |
D |
|
модули, функции, классы, структуры, интерфейсы, объединения, перечисления, шаблоны, псевдонимы, unittest-блоки |
Zig |
|
функции, тесты, переменные |
SQL |
|
таблицы, представления, функции, индексы, типы, схемы, триггеры, последовательности |
А также форматы структурированных данных:
| Формат | Расширения | Сущности |
|---|---|---|
JSON |
|
свойства, объекты (пути по RFC 6901) |
YAML |
|
секции, свойства (пути через точку) |
TOML |
|
секции, свойства |
EDN |
|
записи верхнего уровня в отображении (ключи-ключевые слова) |
CSV |
|
строки (первый столбец как идентификатор) |
Markdown |
|
секции на основе заголовков |
Все остальные файлы обрабатываются с помощью чанкового (chunk-based) диффинга.
Нестандартные расширения и файлы без расширения
Для файлов с нестандартными расширениями создайте .semrc в корне проекта:
.xyz = cpp .j = json .mypy = python
sem также читает паттерны из .gitattributes (diff= и linguist-language=), если они уже настроены. При пересечении .semrc имеет приоритет.
Для файлов совсем без расширения sem автоматически определяет язык по содержимому (импорты, объявления, shebang-строки, vim-модлайны). Это работает для 19 языков без какой-либо настройки.
Принцип сопоставления сущностей
Сопоставление выполняется в три этапа:
-
Точное совпадение идентификатора — одна и та же сущность в версиях «до» и «после» = изменена или не изменена.
-
Совпадение структурного хэша — одинаковая структура AST при разных именах = переименована или перемещена (пробелы и комментарии игнорируются).
-
Нечёткое сходство — перекрытие токенов >80% = вероятное переименование.
Таким образом, sem обнаруживает переименования и перемещения, а не только добавления и удаления. Структурное хэширование также позволяет отличить косметические изменения (пробелы, форматирование) от реальных изменений логики.
Использование с ИИ-агентами (MCP)
sem mcp запускает сервер Model Context Protocol через stdin/stdout. Это не команда, которую запускают и читают вручную: это сервер, который агент запускает в фоне, чтобы задавать sem вопросы в процессе работы. Именно поэтому mcp соседствует с обычными командами. Агент получает 6 инструментов, все на уровне сущностей: sem_impact, sem_context, sem_diff, sem_entities, sem_blame, sem_log.
Зачем это агенту: вместо того чтобы читать файлы целиком и тратить токены, агент может спросить «что сломается, если изменить submitOrder» (sem_impact) или «дай мне контекст для рефакторинга этой функции» (sem_context) и получить точный ответ из графа зависимостей.
Настройте один раз — и общайтесь с агентом в обычном режиме. Нужные инструменты он вызовет сам.
Claude Code:
claude mcp add sem -- sem mcp
Cursor, Claude Desktop или любой клиент с конфигурацией mcpServers:
{
"mcpServers": {
"sem": {
"command": "sem",
"args": ["mcp"]
}
}
}
Если sem недоступен в PATH агента, укажите абсолютный путь к бинарному файлу. Отдельной установки не требуется: sem mcp входит в тот же бинарный файл, что и все остальные команды.
JSON-вывод
sem diff --format json
{
"summary": {
"fileCount": 2,
"added": 1,
"modified": 1,
"deleted": 1,
"moved": 0,
"renamed": 0,
"reordered": 0,
"binary": 0,
"orphan": 0,
"total": 3
},
"changes": [
{
"entityId": "src/auth.ts::function::validateToken",
"changeType": "added",
"entityType": "function",
"entityName": "validateToken",
"startLine": 12,
"endLine": 18,
"oldStartLine": null,
"oldEndLine": null,
"filePath": "src/auth.ts"
}
],
"binaryChanges": []
}
Именованные типы изменений (added, modified, deleted, moved, renamed, reordered) в сумме всегда дают total. orphan — это отдельный счётчик метаданных для изменений на уровне модуля; такие изменения уже включены в именованные категории.
Использование как библиотека
Архитектура
-
tree-sitter — разбор кода (нативный Rust, не WASM)
-
git2 — операции с Git
-
rayon — параллельная обработка файлов
-
xxhash — структурное хэширование
-
Система плагинов для добавления новых языков и форматов
Телеметрия
sem собирает анонимные данные об использовании: имя команды (например, diff, impact), версию CLI и операционную систему. Больше ничего — никакого кода, путей к файлам, имён репозиториев или идентификаторов пользователей. События накапливаются локально и отправляются в фоне, так что выполнение команд не ждёт сети.
Отключить в любой момент:
export SEM_NO_TELEMETRY=1 # или DO_NOT_TRACK=1
Участие в разработке
Хотите добавить поддержку нового языка? Пошаговая инструкция — в CONTRIBUTING.md.
Лицензия
MIT OR Apache-2.0