sem-mcp
Inteligencia de código a nivel de entidad para agentes
Documentación
Parte del stack de Ataraxy Labs: infraestructura nativa para agentes en el desarrollo de software. Ver también: weave (controlador de fusión git a nivel de entidad) · inspect (revisión de código semántica) · opensessions (barra lateral tmux para agentes de codificación).
Lee el manifiesto: https://ataraxy-labs.com/#thesis · Ensayos: https://ataraxy-labs.com/blogs · LLMs: https://ataraxy-labs.com/llms.txt
Control de versiones semántico construido sobre Git.
En lugar de líneas cambiadas, sem te dice qué entidades cambiaron: funciones, métodos, clases.
¿Por qué sem? · Instalación · Comandos · Agentes (MCP) · Consentimiento en la nube · Lanzamientos
sem es una herramienta de control de versiones semántico que funciona sobre Git. Analiza tu código con tree-sitter, extrae cada función, clase y método como una entidad, y hace diff a nivel de entidad en lugar de líneas. Esto significa que ves "la función blahh fue modificada" en lugar de "las líneas x-y cambiaron."
Funciona en cualquier repositorio Git sin configuración.
Las consultas respaldadas por la nube son opcionales por repositorio: iniciar sesión no sube un repositorio ni envía una consulta. Consulta el flujo de consentimiento en la nube para los estados de repositorio público/privado, la pantalla de vista previa, el registro de auditoría local y los controles de olvido.
Instalación
curl -fsSL https://raw.githubusercontent.com/Ataraxy-Labs/sem/main/install.sh | sh
O mediante Homebrew:
brew install sem-cli
O mediante winget en Windows:
winget install AtaraxyLabs.sem
O mediante Scoop en Windows:
scoop install sem
O instala el envoltorio npm en node_modules:
npm install --save-dev @ataraxy-labs/sem
Con Bun, confía en el paquete para que su script postinstall pueda descargar el binario:
bun add -d @ataraxy-labs/sem
bun pm trust @ataraxy-labs/sem
Una vez instalado, actualiza a la última versión en cualquier momento:
sem update
O mediante cargo, desde crates.io:
cargo install sem-cli
O compila el último main desde el código fuente (requiere Rust):
cargo install --git https://github.com/Ataraxy-Labs/sem sem-cli
O descarga un binario desde GitHub Releases.
O ejecuta mediante Docker:
docker build -t sem .
docker run --rm -it -u "$(id -u):$(id -g)" -v "$(pwd):/repo" sem diff
Conflicto de nombre con GNU Parallel
GNU Parallel incluye un binario sem (/usr/bin/sem) como enlace simbólico a parallel. Si tienes ambos instalados, colisionarán. Ejecuta sem --version para verificar cuál estás usando. (#77)
Soluciones rápidas:
# Option 1: alias in your shell profile (~/.bashrc, ~/.zshrc)
alias sem="$HOME/.cargo/bin/sem"
# Option 2: make sure cargo bin comes first in PATH
export PATH="$HOME/.cargo/bin:$PATH"
# Option 3: if installed via Homebrew
export PATH="$(brew --prefix)/bin:$PATH"
Si lo instalaste mediante npm/bun, el binario vive en node_modules/.bin/sem y se invoca a través de npx sem o bunx sem, lo que evita el conflicto por completo.
Comandos
Funciona en cualquier repositorio Git. Sin configuración requerida. También funciona fuera de Git para comparación de archivos arbitrarios.
sem almacena su caché de entidades SQLite fuera del repositorio, bajo el directorio de caché del sistema operativo por defecto. Establece SEM_CACHE_DIR=/path/to/cache para anular la raíz de caché; las anulaciones locales del repositorio se ignoran para que los archivos de caché no ensucien el árbol de trabajo.
sem diff
Diff a nivel de entidad con detección de renombrados, hash estructural y resaltados en línea a nivel de palabra.
# Semantic diff of working changes
sem diff
# Staged changes only
sem diff --staged
# Specific commit
sem diff --commit abc1234
# Commit range
sem diff --from HEAD~5 --to HEAD
# Verbose mode (word-level inline diffs for each entity)
sem diff -v
# Plain text output (git status style)
sem diff --format plain
# JSON output (for AI agents, CI pipelines)
sem diff --format json
# Markdown output (for PRs, reports)
sem diff --format markdown
# Compare any two files (no git repo needed)
sem diff file1.ts file2.ts
# Read file changes from stdin (no git repo needed)
echo '[{"filePath":"src/main.rs","status":"modified","beforeContent":"...","afterContent":"..."}]' \
| sem diff --stdin --format json
# Only specific file types
sem diff --file-exts .py .rs
sem impact
El grafo de dependencias entre archivos muestra qué se rompe si una entidad cambia.
# Full impact analysis
sem impact authenticateUser
# Direct dependencies only
sem impact authenticateUser --deps
# Direct dependents only
sem impact authenticateUser --dependents
# Affected tests only
sem impact authenticateUser --tests
# JSON output
sem impact authenticateUser --json
# Disambiguate by file
sem impact authenticateUser --file src/auth.ts
# Include default-excluded paths such as generated, fixture, vendor, benchmark, and build trees
sem impact authenticateUser --no-default-excludes
sem blame
Blame a nivel de entidad que muestra quién modificó por última vez cada función, clase o método.
sem blame src/auth.ts
# JSON output
sem blame src/auth.ts --json
sem log
Rastrea cómo evolucionó una sola entidad a través del historial de git.
sem log authenticateUser
# Verbose mode (show content diff between versions)
sem log authenticateUser -v
# Limit commits scanned
sem log authenticateUser --limit 20
# JSON output
sem log authenticateUser --json
Sin entidad, sem log analiza el historial reciente del repositorio a nivel de entidad:
puntos calientes (funciones/clases más modificadas, con recuentos de autores) y
pares de co-cambio (entidades que cambian repetidamente en los mismos commits:
"si tocas una, no olvides la otra"):
sem log # repo hotspots + co-change pairs (last 50 commits)
sem log --limit 200 # deeper history
sem log --file src/auth.ts # scoped to one file
sem log --json # full data
sem entities
Lista todas las entidades bajo una ruta de archivo o directorio. Sin ruta es lo mismo que ..
sem entities
sem entities .
sem entities src/auth.ts
# JSON output
sem entities --json
sem entities src/auth.ts --json
# Include default-excluded paths such as generated, fixture, vendor, benchmark, and build trees
sem entities --no-default-excludes
sem context
Contexto con presupuesto de tokens para LLMs: la entidad, sus dependencias y sus dependientes, ajustado a un presupuesto estricto de tokens de contenido.
Cuando la firma objetivo en sí no cabe, la salida JSON informa target_omitted: true.
sem context authenticateUser
# Custom token budget
sem context authenticateUser --budget 4000
# JSON output
sem context authenticateUser --json
# Include default-excluded paths such as generated, fixture, vendor, benchmark, and build trees
sem context authenticateUser --no-default-excludes
sem find / callers / refs / grep
Búsquedas de arranque en frío respaldadas por un índice de consultas en disco, mapeable con mmap (index.sem, almacenado junto a la caché de entidades SQLite). La primera llamada en un repositorio construye el índice; cada llamada posterior lo lee directamente, sin demonio ni proceso en segundo plano:
# Find where an entity is defined
sem find "function diff_command"
# Who calls it
sem callers diff_command
# What it calls
sem refs diff_command
# Text search across source files (rg-compatible file:line:text output,
# served from the index's trigram postings when one exists)
sem grep "TODO"
# JSON output on any of the above
sem find diff_command --json
Medido en este repositorio (crates/) con time: la primera sem find (índice aún no construido) tomó 185ms; la segunda llamada contra el mismo repositorio, una vez que el índice existía, tomó 7ms. Pruébalo tú mismo; los números exactos dependerán de tu máquina y del tamaño del repositorio. El punto es la brecha frío-vs-cálido: no se necesita un demonio activo para que el número cálido se mantenga.
sem graph
Imprime el grafo completo de dependencias de entidades para el repositorio actual, o --json para la lista de aristas subyacente (el mismo grafo sobre el que se construyen sem impact y sem context):
sem graph
sem graph --json
sem stats
Contadores locales y acumulativos: cuántos diffs ha ejecutado sem en este entorno y cuánto de eso fue ruido filtrado. Nada de esto sale de tu máquina (ver Telemetría):
sem stats
Usar como diff de Git predeterminado
Reemplaza la salida de git diff con diffs a nivel de entidad. Los agentes y humanos obtienen la salida de sem automáticamente sin cambiar ningún comando.
sem setup
Ahora git diff muestra cambios a nivel de entidad en lugar de a nivel de línea. Sin avisos, sin configuración de agente necesaria. Todo lo que llama a git diff obtiene la salida de sem automáticamente. También instala un hook de pre-commit que muestra el radio de explosión a nivel de entidad de los cambios preparados.
En macOS y Linux, sem setup también registra un hook UserPromptSubmit de Claude Code (sem hook prompt-submit) para inyección de contexto en tiempo de aviso. Edita ~/.claude/settings.json de forma idempotente, hace una copia de seguridad primero y deja intactos los hooks que ya tengas.
Para deshabilitar y volver al diff de git normal (también elimina los hooks de sesión):
sem unsetup
Diffs a nivel de entidad en cada pull request
Agrega la GitHub Action y cada PR recibe un comentario fijo que muestra qué funciones, clases y métodos cambiaron. Se actualiza en su lugar en cada push y señala explícitamente los PRs solo cosméticos (formato/comentarios):
# .github/workflows/entity-diff.yml
name: Entity diff
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
entity-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Ataraxy-Labs/sem/action@v0.23.1
Sin configuración, sin claves API, nunca falla tu build. Ver action/ para detalles.
Aceleración en la nube (para escala y equipos)
Local siempre es gratis y siempre rápido: el índice en disco responde consultas diarias en milisegundos de un solo dígito incluso desde un proceso en frío, así que no hay nada que mantener caliente y no se requiere inicio de sesión. No pagas para que tu portátil sea rápido.
La nube es para lo que un portátil no puede hacer. En un monorepo muy grande, la primera construcción del grafo local puede tomar unos segundos; un grafo de equipo compartido no debería reconstruirse por cada desarrollador; y CI quiere el grafo sin hacer checkout. sem login conecta esos casos a sem cloud, que mantiene un grafo cálido y preconstruido para tus repositorios registrados y sirve las consultas pesadas desde él en lugar de reconstruir localmente.
sem login # GitHub device flow, one time
sem impact myFunc --file src/foo.rs # served from the cloud's warm graph
Es completamente opcional y transparente:
- ¿No has iniciado sesión, o la nube no está disponible? sem calcula localmente e imprime exactamente la misma salida. Sin fallos, sin diferencia en los resultados.
SEM_LOCAL=1fuerza el cálculo local incluso cuando has iniciado sesión.- Los repositorios pequeños no ven cambios, local ya es rápido. La ventaja es para bases de código grandes donde reconstruir el grafo cada vez es el cuello de botella.
Comandos relacionados, todos con alcance de cuenta en la nube:
sem logout # log out
sem whoami # show current cloud identity
sem cloud status # cloud + telemetry state for this repo (offline; sends nothing)
sem cloud enable # turn on cloud queries for a public repo (shows what's sent first)
sem cloud share # same, with extra confirmation, for a private repo
sem cloud forget # delete this repo's cloud index and unregister it
sem xref --json # cross-repo dependencies across your indexed repos
sem repos # where your code is stored: cloud-indexed repos + local caches
sem cloud --help lista cada subcomando (list, preview, log, never incluidos); cada uno es de solo lectura o requiere confirmación explícita antes de enviar algo.
Si tu equipo ejecuta la revisión de código a través de sem cloud, sem review listen <diff-id-or-url> ejecuta un agente de codificación preconfigurado para unirse a esa revisión como oyente en vivo que responde preguntas del revisor ancladas a líneas específicas del diff.
Qué analiza
32 lenguajes de programación con extracción completa de entidades mediante tree-sitter:
| Idioma | Extensiones | Entidades |
|---|---|---|
| TypeScript | .ts .tsx .mts .cts | funciones, clases, interfaces, tipos, enums, exports |
| JavaScript | .js .jsx .mjs .cjs .es6 | funciones, clases, variables, exports |
| Python | .py .pyi | funciones, clases, definiciones decoradas |
| Go | .go | funciones, métodos, tipos, vars, consts |
| Rust | .rs | funciones, structs, enums, impls, traits, mods, consts |
| Java | .java | clases, métodos, interfaces, enums, campos, constructores |
| C | .c .h | funciones, structs, enums, unions, typedefs |
| C++ | .cpp .cc .cxx .hpp .hh .hxx | funciones, clases, structs, enums, namespaces, plantillas |
| C# | .cs | clases, métodos, interfaces, enums, structs, propiedades |
| Ruby | .rb | métodos, clases, módulos |
| PHP | .php .inc .phtml .module | funciones, clases, métodos, interfaces, traits, enums |
| Swift | .swift | funciones, clases, protocolos, structs, enums, propiedades |
| Elixir | .ex .exs | módulos, funciones, macros, guards, protocolos |
| Bash | .sh | funciones |
| Fish | .fish | funciones |
| Lua | .lua | funciones (formas global, local, de tabla y de método) |
| HCL/Terraform | .hcl .tf .tfvars | bloques, atributos (nombres calificados para bloques anidados) |
| Kotlin | .kt .kts | clases, interfaces, objetos, funciones, propiedades, companion objects |
| Fortran | .f90 .f95 .f03 .f08 .f .for | funciones, subrutinas, módulos, programas |
| Vue | .vue | bloques template/script/style + entidades TS/JS internas |
| XML | .xml .plist .svg .csproj + 9 extensiones más de MSBuild/recursos | elementos (anidados, identidad por nombre de etiqueta) |
| ERB | .erb .html.erb | bloques, expresiones, etiquetas de código |
| Svelte | .svelte .svelte.js .svelte.ts (+ variantes .test/.spec) | bloques de componentes + módulos JS/TS de runas |
| Perl | .pl .pm .t | subrutinas, paquetes |
| Dart | .dart | clases, mixins, extensiones, enums, alias de tipos, funciones |
| OCaml | .ml .mli | valores, módulos, tipos, clases, externals |
| Scala | .scala .sc .sbt .kojo .mill | clases, objetos, traits, enums, funciones, vals, extensiones |
| Nix | .nix | bindings, declaraciones inherit |
| Haskell | .hs | funciones, firmas, tipos de datos, newtypes, clases, instancias, sinónimos de tipos |
| Elm | .elm | declaraciones de valores, alias de tipos, declaraciones de tipos, anotaciones de puertos, declaraciones infix |
| Clojure | .clj .cljs .cljc | vars, funciones, macros, multimétodos, protocolos, registros, tipos |
| D | .d .di | módulos, funciones, clases, structs, interfaces, unions, enums, plantillas, alias, unittests |
| Zig | .zig | funciones, tests, variables |
| SQL | .sql .psql .pgsql .ddl | tablas, vistas, funciones, índices, tipos, esquemas, triggers, secuencias |
Además, formatos de datos estructurados:
| Formato | Extensiones | Entidades |
|---|---|---|
| JSON | .json | propiedades, objetos (rutas RFC 6901) |
| YAML | .yml .yaml | secciones, propiedades (rutas de puntos) |
| TOML | .toml | secciones, propiedades |
| EDN | .edn | entradas de mapa de nivel superior (claves de palabras clave) |
| CSV | .csv .tsv | filas (primera columna como identidad) |
| Markdown | .md .mdx | secciones basadas en encabezados |
| LaTeX | .tex .latex .cls .sty | secciones (parte/capítulo/sección/…), además de teorema/lema/prueba/figura/tabla/algoritmo y otros entornos rastreados |
Todo lo demás recurre a la comparación de diferencias basada en fragmentos.
Extensiones personalizadas y archivos sin extensión
Para archivos con extensiones no estándar, crea un .semrc en la raíz de tu proyecto:
.xyz = cpp
.j = json
.mypy = python
sem también lee patrones .gitattributes (diff= y linguist-language=) si ya los tienes configurados. .semrc tiene prioridad cuando ambos definen la misma extensión.
Para archivos sin extensión, sem detecta el idioma automáticamente a partir del contenido (líneas shebang, modelines de vim y heurísticas estructurales como declaraciones package/import/use). Esto cubre más de 30 idiomas sin necesidad de configuración.
Cómo funciona la coincidencia
Coincidencia de entidades en tres fases:
- Coincidencia exacta de ID: misma entidad antes/después = modificada o sin cambios
- Coincidencia de hash estructural: misma estructura AST, nombre diferente = renombrada o movida (ignora espacios en blanco/comentarios)
- Similitud difusa: >80% de superposición de tokens = probable renombramiento
Esto significa que sem detecta renombramientos y movimientos, no solo adiciones y eliminaciones. El hash estructural también distingue cambios cosméticos (espacios en blanco, formato) de cambios lógicos reales.
Uso con agentes de IA (MCP)
En macOS y Linux, los clientes en el mismo checkout comparten un daemon de repositorio en caliente.
Ejecuta sem mcp --status para verificarlo. Consulta el contrato de runtime compartido y benchmark reproducible
para aislamiento de sesión, comportamiento de respaldo y límites actuales de plataforma.
sem mcp inicia un Model Context Protocol servidor sobre stdin/stdout. No es un comando que ejecutes y leas tú mismo: es un servidor que tu agente de codificación lanza en segundo plano para que pueda hacer preguntas a sem mientras trabaja. Esa es la razón por la que mcp vive junto a los comandos normales. El agente obtiene 8 herramientas a nivel de entidad que reflejan la CLI: sem_entities, sem_diff, sem_blame, sem_impact, sem_log, sem_context, sem_find, sem_grep. (Si también usas sem cloud para revisión de código, cuatro herramientas más permiten que un agente se adjunte a una revisión y responda preguntas del revisor en un bucle: join_review, wait_for_branch, reply_to_branch, list_open_branches.)
Por qué un agente quiere esto: en lugar de leer archivos completos y quemar tokens, puede preguntar "¿qué se rompe si cambio submitOrder" (sem_impact) o "dame solo el contexto para refactorizar esta función" (sem_context, que devuelve el código fuente de la función más sus llamadores y llamados) y obtener una respuesta precisa y determinista del grafo de dependencias en lugar de un resultado de grep que podría perder un llamador.
Agrégalo una vez, luego habla con tu agente normalmente. Él llama a las herramientas por su cuenta.
Claude Code:
claude mcp add sem -- sem mcp
O un comando que también instala la habilidad, para que el agente sepa cuándo recurrir a sem:
npx @ataraxy-labs/sem-skill
Cursor, Claude Desktop, o cualquier cliente con una configuración mcpServers:
{
"mcpServers": {
"sem": {
"command": "sem",
"args": ["mcp"]
}
}
}
Si sem no está en el PATH del agente, usa la ruta absoluta al binario. No se necesita instalación separada: sem mcp viene en el mismo binario que todos los demás comandos.
Salida JSON
sem diff --format json
Salida real, de un cambio de lógica de una línea en una función de Python:
{
"summary": {
"fileCount": 1,
"added": 0,
"modified": 1,
"deleted": 0,
"moved": 0,
"renamed": 0,
"reordered": 0,
"binary": 0,
"orphan": 0,
"total": 1
},
"changes": [
{
"entityId": "auth.py::function::authenticate_user",
"changeType": "modified",
"entityType": "function",
"entityName": "authenticate_user",
"startLine": 1,
"endLine": 6,
"oldStartLine": 1,
"oldEndLine": 4,
"oldEntityName": null,
"filePath": "auth.py",
"oldFilePath": null,
"oldParentId": null,
"beforeContent": "def authenticate_user(username, password):\n if not username or not password:\n return False\n return check_credentials(username, password)",
"afterContent": "def authenticate_user(username, password):\n if not username or not password:\n return False\n if not check_credentials(username, password):\n return False\n return True",
"commitSha": null,
"author": null,
"structuralChange": true
}
],
"binaryChanges": []
}
Los buckets de tipo de cambio nombrados (added, modified, deleted, moved, renamed, reordered) siempre suman total. orphan es un recuento de metadatos transversal para cambios a nivel de módulo, y esos cambios ya están incluidos en los buckets de tipo de cambio nombrados. beforeContent/afterContent llevan el código fuente completo de la entidad en ambos lados del cambio; structuralChange es false cuando el diff es solo cosmético (espacios en blanco, comentarios).
Como biblioteca
sem-core se puede usar como dependencia de biblioteca de Rust, desde crates.io:
[dependencies]
sem-core = "0.23"
Usado por weave (controlador de fusión semántica) e inspect (revisión de código a nivel de entidad).
Arquitectura
- tree-sitter para análisis de código (Rust nativo, no WASM)
- git2 para operaciones de Git
- rayon para procesamiento paralelo de archivos
- xxhash para hash estructural
- Un directorio de caché por repositorio (caché de entidades SQLite + un índice de consulta mapeable en memoria) respalda
find/callers/refs/grepcon búsquedas en procesos fríos y sin daemon en segundo plano - Sistema de complementos para agregar nuevos idiomas y formatos (consulta CONTRIBUTING.md)
Telemetría
Local por defecto: sem cuenta nombres de comandos (por ejemplo, diff, impact) solo en tu propia máquina, y en ese modo nunca se sube nada. No se registra código, rutas de archivos, nombres de repositorios ni identidad de usuario, y no se realiza ninguna llamada de red.
sem telemetry preview # see current mode and exactly what would be sent
sem telemetry on # opt in: also upload counts to help improve sem
sem telemetry off # record nothing at all
SEM_NO_TELEMETRY=1 o DO_NOT_TRACK=1 fuerzan el comportamiento de no registrar nada independientemente del modo. Las compilaciones de desarrollo (cualquier cosa ejecutada desde un directorio cargo build target/) nunca registran, por lo que trabajar en sem mismo no contamina los números.
Contribuciones
¿Quieres agregar un nuevo idioma? Consulta CONTRIBUTING.md para una guía paso a paso.
Historial de estrellas
Licencia
MIT OR Apache-2.0
