Ir al contenido
CodArchel mapa vivo de la arquitectura
ESEN

codarch lint

codarch lint no trae un linter ni escribe configuración: lee el lint que el proyecto ya tiene y escribe un artefacto con lo que dijo. Si el repo no tiene lint, no se lo inventa: recomienda el mínimo y no escribe artefacto. El lint no entra en el snapshot —depende de las herramientas instaladas y de su configuración—, así que tiene su propio fichero, su propio checksum y su propio ciclo de vida. Quien lo mide en el uso normal es codarch analyze, en la misma pasada que las demás lentes; este comando es para medirlo suelto, sin mapa.

SistemaConfiguración que buscaQué se lee
ESLinteslint.config.*, .eslintrc*, eslintConfig en package.jsoneslint --format json y sus reglas activas con --print-config.
oxlintoxlint.json, .oxlintrc.json, .oxlintrcoxlint --format json y las reglas de su JSON.
Biomebiome.json, biome.jsoncbiome lint --reporter=json; sus reglas activas no se enumeran todavía.
Ruffruff.toml, .ruff.toml, [tool.ruff] en pyproject.tomlruff check --output-format=json, con el ruff del PATH.
Checkstylecheckstyle.xml, config/checkstyle/checkstyle.xml, el plugin en build.gradlecheckstyle -c <config> -f xml ., con el checkstyle del PATH. El plugin de Gradle no dice qué XML usa: ahí no se mide.
go vetgo.modgo vet ./..., con el go vet del PATH.
.NET*.csproj, *.sln`dotnet format <solución

Un sistema entra si tiene su configuración o si su herramienta está instalada. Si hay configuración y no hay binario, el comando lo dice: no se completa con npx, porque descargar una versión que el repo no eligió sería inventar la medida. Si hay binario y no hay archivo de configuración, también se dice con esas palabras, y sus reglas por defecto no se enumeran. Las herramientas corren con el binario del proyecto (node_modules/…) —Ruff y Checkstyle, que no viven ahí, con los que el proyecto tenga en el PATH— y su propia configuración.

Biome no da línea ni columna en su JSON —su span son desplazamientos de bytes—, así que sus mensajes entran sin posición en vez de calcularla a mano. Ruff no da severidad: todos sus hallazgos cuentan como error, que es como los trata al salir con código distinto de cero.

ESLint y oxlint dan el mismo mensaje normalizado: regla, severidad, línea, columna y texto. Las rutas absolutas se hacen relativas a la raíz y las que caen fuera del repo se descartan. Si dos herramientas dicen exactamente lo mismo del mismo sitio, se cuenta una vez.

  • ESLint se resuelve con eslint --print-config <fichero>, que lee la configuración real —flat config, plugins y overrides— en vez de interpretar el fichero a mano.
  • oxlint se lee de su JSON; sin archivo de configuración corre sus reglas por defecto, y la nota del sistema lo dice: no hay configuración y sus reglas no se enumeran.
  • Biome lee de su config las reglas que escribe, con su grupo y su nivel (style/useConst). Las de recommended dependen de la versión de Biome y no se enumeran: la nota del sistema lo dice.
  • Ruff enumera sus reglas, no sus selectores: lee select y extend-select (menos ignore y extend-ignore), pide el catálogo a su propia versión con ruff rule --all --output-format=json y expande por prefijo con la especificidad de Ruff: gana el selector más concreto y, si empatan, el ignorado. Sin select, corren las de por defecto y no se enumeran; sin catálogo, se listan los selectores y se dice. El catálogo se guarda en .codarch/lint-cache.json con la versión de Ruff que lo dio: solo se vuelve a pedir cuando actualizas Ruff. No es parte del artefacto ni del checksum, y no se crea .codarch/ para escribirlo.
  • Checkstyle lee los <module name="…"> de su XML, sin contenedores (Checker, TreeWalker) ni filtros de supresión. Su config no da severidad a cada módulo: la trae cada hallazgo.
  • go vet y los analizadores de .NET no enumeran sus reglas: van con la versión de Go o con el SDK y AnalysisLevel. Los hallazgos de go vet entran como go vet —su texto no firma el analizador—; los de .NET llevan su código (CA1822, CS0168). Una lista plausible sería peor que un hueco.

El bloque lint: de .codarch.yml es para los comandos que la detección no cubre. Si está, manda y se ejecuta tal cual:

lint:
- name: eslint
command: node node_modules/eslint/bin/eslint.js . --format json
format: eslint-json
- name: oxlint
command: node node_modules/oxlint/bin/oxlint --format json .
format: oxlint-json
list: node node_modules/oxlint/bin/oxlint --debug=files .

Cada entrada lleva name, command y format (eslint-json, oxlint-json, biome-json, ruff-json, checkstyle-xml, govet-text o dotnet-text). list es opcional: un comando que imprime una ruta por línea, el universo que la herramienta mira, limpios incluidos; sin él no se supone universo. Un bloque mal formado es un error en vez de una adivinanza.

Ventana de terminal
codarch lint [ruta] [opciones]
OpciónQué hace
-o, --out <dir>Carpeta del artefacto. Por defecto <ruta>/.codarch.
--config <file>YAML con el override. Por defecto .codarch.yml si existe.
--no-configIgnora el override del YAML; usa el lint del proyecto.
--no-detectNo detecta el lint del proyecto.
--fail-on <modo>never, errors o warnings. Por defecto never.
-h, --helpAyuda.
-v, --versionVersión.

Escribe lint.repmod.json en la carpeta de salida. Si crea .codarch/ en la raíz, añade .codarch/ al .gitignore; si la carpeta ya existía, no lo toca. Un .codarch/lint.json o lint.cc.json de una versión anterior no se lee: la hoja dirá «sin medir» hasta que se vuelva a analizar.

{
"schemaVersion": "1.3",
"domain": "code",
"meta": {
"checksum": "…",
"tools": ["eslint"],
"systems": [
{
"name": "eslint",
"config": "eslint.config.js",
"rules": [{ "id": "no-console", "severity": "warn" }]
}
]
},
"files": {
"src/a.ts": {
"errors": 0,
"warnings": 1,
"messages": [
{ "rule": "no-console", "severity": "warn", "line": 1, "column": 1, "message": "Unexpected console" }
]
}
},
"coverage": {
"tools": {
"eslint": {
"outcome": "enumerated",
"measuredPaths": ["src/a.ts"],
"eligiblePaths": null
}
}
},
"summary": { "files": 1, "errors": 0, "warnings": 1, "messages": 1, "measured": 1 }
}

meta.systems dice qué lint tiene el proyecto —con su configuración y sus reglas activas— y meta.tools cuáles midieron de verdad. Un artefacto 1.0–1.2 se sigue leyendo: la cobertura queda en unknown con legacy-global, y no se inventa measured.

summary.measured es cuántos ficheros derivó la cobertura, limpios incluidos, que no aparecen en files. Es una cifra global de la pasada. Solo se escribe si se puede derivar: un cero que no sale de una enumeración válida no se pone. ESLint declara el universo con lo que devolvió —también los limpios— y oxlint con --debug=files, así que el código puede quedar complete (ADR 0110); Checkstyle y las demás siguen en unknown si no listan los limpios. meta.tree es el checksum del snapshot que se midió; lo rellena quien analiza —codarch analyze y, en el live, serve—. Este comando suelto no analiza el repo, así que por sí solo no escribe tree: la app no puede comparar y no lo finge.

summary.files, summary.errors, summary.warnings, summary.messages y los errors y warnings de cada fichero se regeneran al leer desde los mensajes. summary.files son los ficheros con algún hallazgo. Un info cuenta como mensaje y como fichero, y no como error ni aviso. Las rutas se canonizan al leer —NFC por segmento, con /, sin ./ ni barras repetidas— y no se pasan a minúsculas. Si dos claves distintas caen en la misma ruta, no se funden en silencio: la lectura lo deja en diagnostics. El esquema es 1.3. Los nombres siguen siendo lint.repmod.json y lint-rest.repmod.json.

Ficheros por ruta relativa, mensajes ordenados por línea y columna, y un checksum que no cambia si la salida de las herramientas no cambia. Cero hallazgos no es «limpio»: hace falta cobertura complete, árbol al día y algo que medir. Cuando se cumple, la ficha dice «Limpio y al día»; si no, enseña las cuentas y el motivo. Que no haya artefacto significa que nadie midió.

El resumen cuenta la raíz, la fuente, el artefacto, lo que hizo cada herramienta y cada sistema con su configuración. Los ficheros con hallazgos son los que tienen algún mensaje, y se enseñan de los medidos —3 ficheros con hallazgos de 494 medidos—: eso es lo que distingue un repo limpio de uno sin medir. El recuento de reglas y hallazgos es el mismo que leen la app y el MCP, y --fail-on decide con esa misma cuenta, no con el resumen que declare el fichero.

Salida de codarch lint . en la terminal

Las herramientas se lanzan en paralelo y el comando espera a todas. Una que no está o que revienta se avisa y las demás siguen: el artefacto se escribe con lo que sí se midió, y solo con esas herramientas.

Un linter con hallazgos sale con código distinto de cero, y eso no es un fallo si dejó su JSON. Por eso el comando no bloquea por defecto: --fail-on errors es lo que se usa en CI, y --fail-on warnings cuenta errores y avisos.

No escribe configuración ni lanza un linter que el repo no tiene: el comando sale con 1 y recomienda el mínimo por lenguaje.

LenguajeMínimo recomendable
TypeScript y JavaScriptESLint + typescript-eslint en recommended.
PythonRuff con select = ["E", "F"].
Gogo vet ./... y staticcheck en CI.
JavaCheckstyle con google_checks.xml.
C#Analizadores de .NET con AnalysisLevel=latest-recommended.
Ventana de terminal
codarch lint .
codarch lint . --fail-on errors
codarch lint . --no-detect --config .codarch.yml
CódigoSignificado
0Artefacto escrito. No dice que el código esté limpio: eso lo dicen sus cuentas.
1Configuración inválida, ninguna herramienta midió (incluido «el proyecto no tiene lint»), no se pudo escribir el artefacto, o --fail-on encontró lo que buscaba.