@skapxd/lint-agent
v1.5.0
Published
Lint Agent: executable ESLint guardrails for coding agents across TypeScript, React, backend, frontend, and package projects
Maintainers
Readme
Lint Agent
Reglas de ESLint para que los agentes no negocien la arquitectura de tu proyecto.
Lint Agent convierte opiniones de arquitectura en guardrails ejecutables: archivos pequenos, nombres semanticos, errores modelados con Result, causas preservadas y fronteras explicitas. El paquete npm se publica como @skapxd/lint-agent. El README queda como puerta de entrada; el detalle vive en docs/ para que npm no entierre lo importante en 2.400 lineas.
Skill para agentes
Instala la skill skapxd-lint en tu agente con un comando compatible con skills.sh y 20+ agentes como Claude Code, Cursor y Copilot:
npx skills add skapxd/lint-agentLuego pide al agente que la use:
- "Audita este proyecto con skapxd-lint y muestrame los hallazgos."
- "Adopta las reglas skapxd de forma incremental (10%) en este repo legacy."
- "Verifica el lote de adopcion skapxd con la seed que acaba de generar el CLI."
La skill esta indexada en skills.sh, invoca el CLI publicado de Lint Agent (@skapxd/lint-agent@1) con npm provenance y no modifica el proyecto medido: la evaluacion es efimera y solo lectura salvo que pidas aplicar fixes.
Si no usas la skill, puedes invocar el CLI directo:
npx @skapxd/lint-agent@1 <path> --yes --format toonUso rapido
pnpm add -D @skapxd/lint-agent eslint typescript typescript-eslintimport skapxd from "@skapxd/lint-agent";
export default [
skapxd.configs.shared.base,
];Luego ejecutalo como cualquier regla de ESLint:
pnpm eslint
pnpm eslint src
pnpm eslint --max-warnings=0Documentacion
Los enlaces apuntan a GitHub de forma absoluta para que funcionen tambien desde npmjs.com.
| Tema | Contenido | | --- | --- | | Axiomas y motivacion | Por que existe Lint Agent, que protege y por que las alternativas no bastan. | | Presets y estructura | Shared, backend, frontend, Next.js, NestJS, Astro, package y strict. | | Adopcion incremental y legacy | Lint sobre cambios, olas de adopcion, overrides y propuestas de reglas. | | Pipeline Result | Como encajan @skapxd/result, ts-pattern y el trace global. | | Notas type-aware | Supuestos, limites conocidos y notas de reglas que dependen del checker. | | Tarea para un agente de codigo | Como escribir el markdown autocontenido que implementa un cambio (regla, ajuste o paquete). | | Indice de reglas | Las 73 fichas individuales en docs/reglas/. |
Reglas
| Regla | Que protege |
| --- | --- |
| skapxd/one-root-function-per-file | Un archivo, una función top-level semántica. |
| skapxd/one-root-unit-per-file | Una sola clase o función top-level. Activa en las reglas base. |
| skapxd/filename-matches-root-function | El nombre del archivo es la versión kebab de su función raíz exportada. |
| skapxd/dense-function-requires-comment | Funciones exportadas densas en líneas, literales y ramas declaran su motivación en un comentario de bloque. |
| skapxd/complex-inline-callback-requires-name | Callbacks inline con dos o más decisiones propias se extraen a una función con nombre semántico. Activa en las reglas base. |
| skapxd/async-functions-return-result | Funciones async de dominio deben retornar Promise<Result<...>>. Apagada por defecto; opt-in (ver motivos en su sección). |
| skapxd/requires-strict-tsconfig | El tsconfig debe ser implacable (strict, noImplicitReturns, noUncheckedIndexedAccess): sin ellos, el compilador no puede hacer irrepresentable lo inválido. |
| skapxd/result-error-requires-cause | Un Result.err derivado debe preservar cause: result.error. |
| skapxd/result-error-requires-handling | Prohíbe descartar en silencio un Result fallido: el error se transforma o se entrega, nunca se ignora. |
| skapxd/result-error-requires-modeling | Una frontera no puede devolver Result<_, unknown>: el canal de error debe modelarse como un error de dominio (tagged union), no quedar opaco. |
| skapxd/await-requires-result | Todo await debe resolver en un Result: o la función llamada retorna Promise<Result<...>> (preferido), o se envuelve en trySafe, o awaitea otro @UseCase real de @skapxd/nest como frontera de aplicación. Obligatoria en todos los presets tipados. |
| skapxd/no-rethrow-result-error | Prohíbe re-lanzar el error crudo de un Result: el flujo no vuelve de trySafe a excepción cruda. |
| skapxd/trysafe-only-at-boundary | Exige que trySafe capture en la frontera runtime/paquete, no una capa arriba sobre código del proyecto. En las bases (agnóstica de framework); detección conservadora para acotar falsos positivos. |
| skapxd/no-ad-hoc-ok-result | Evita contratos { ok: ... } hechos a mano en async exports. |
| skapxd/max-class-size | Limita cada clase a 150 líneas y señala datos declarativos extraíbles solo cuando explican todo el exceso. |
| skapxd/max-hook-size | Marca hooks grandes o con demasiados useState. |
| skapxd/class-properties-require-readonly | Toda propiedad de clase es readonly: el cambio se modela con instancias nuevas, no con mutación. |
| skapxd/max-public-methods | Una clase, una responsabilidad: máximo N métodos públicos (default 1). Agnóstica al framework, en las reglas base; el preset nest le inyecta sus hooks. |
| skapxd/no-exported-function-bag | Prohíbe exportar objetos que publican varias funciones: una bolsa de funciones es una clase o namespace disfrazado. En las bases. |
| skapxd/no-local-function-bag | Prohíbe objetos locales que definen varias funciones inline: una bolsa local es un namespace disfrazado. En las bases. |
| skapxd/no-accessors | Prohíbe get/set: un método explícito dice la verdad; el accessor esconde computación (y métodos disfrazados). |
| skapxd/jsx-return-name-pascal-case | Funciones que retornan JSX deben nombrarse como componentes. |
| skapxd/nest-controller-delegates-to-use-case | Los route handlers de un @Controller adaptan HTTP y delegan una sola operación a un @UseCase real. Registrada como opt-in mientras #191 decide el preset. |
| skapxd/nest-controller-injects-use-case | Controllers y gateways inyectan casos de uso con @UseCase, no services/repositories directos. Preset nest. |
| skapxd/nest-controller-input-dtos | Los inputs HTTP decorados de un @Controller entran como DTO completo extends Dto() con brand "dto" de @skapxd/nest, no como campos sueltos, arrays crudos, aliases ni clases sin contrato. Preset nest. |
| skapxd/nest-controller-returns-dto | Los métodos de ruta de un @Controller retornan una clase top-level extends Dto() con brand "dto" de @skapxd/nest, no interfaces, schemas de DB ni listas crudas. Preset nest. |
| skapxd/nest-dto-no-class-decorator | Un DTO con brand de @skapxd/nest no declara decoradores de clase: @Schema/@Entity lo convierten en modelo de persistencia disfrazado. Preset nest. |
| skapxd/nest-dto-no-inline-object | Los objetos anidados de un DTO se modelan como clases DTO, no como tipos inline ni type: Object. Preset nest. |
| skapxd/nest-dto-requires-api-property | Toda propiedad pública de un *.dto.ts lleva @ApiProperty: el contrato HTTP se documenta en el DTO. Preset nest. |
| skapxd/nest-dto-requires-validation | Todo DTO valida en runtime: class-validator en cada propiedad, @IsOptional si hay ?, @Type junto a @ValidateNested; zod/valibot para uniones. Preset nest. |
| skapxd/nest-layer-import-direction | La matriz de capas Nest impide que domain/application dependan de transporte o adaptadores concretos. Preset nest. |
| skapxd/nest-module-layer-folders | Los módulos Nest declaran http, application, domain, infrastructure y contracts en el árbol; la raíz queda para el module file e index.ts. Preset nest. |
| skapxd/nest-no-direct-instantiation | Prohíbe new sobre imports internos en services: las dependencias entran por el constructor (DI). Preset nest. |
| skapxd/nest-no-inline-query-params | Dos o más @Query('x')/@ApiQuery individuales son un DTO disfrazado: consolida en @Query() filters: Dto. Preset nest. |
| skapxd/nest-no-result-response | Los métodos de un @Controller no retornan Result: el envelope se serializaría al cliente. La activa el preset nest. |
| skapxd/nest-no-swagger-in-controllers | Los controllers no se llenan de decoradores de swagger; el plugin introspecciona los DTOs. Preset nest. |
| skapxd/nest-requires-swagger-plugin | nest-cli.json debe tener el plugin @nestjs/swagger: la premisa de las reglas de swagger, verificada. Preset nest. |
| skapxd/nest-use-case-no-result-response | Los métodos públicos de un @UseCase real consumen Result y lanzan excepciones, no propagan el envelope al controller. Preset nest. |
| skapxd/nest-validation-pipe-config | Todo new ValidationPipe configura transform y whitelist: la premisa de las reglas de DTOs. Preset nest. |
| skapxd/nested-function-requires-capture | Una funcion anidada nombrada debe capturar scope local; si no, es un helper extraible. Preset shared, en error. |
| skapxd/no-anonymous-condition | El if solo acepta condiciones ya nombradas; todo cómputo (llamada, comparación, &&/||) se extrae a una const con nombre semántico. |
| skapxd/no-deep-relative-imports | Limita la profundidad de los imports relativos (../). |
| skapxd/no-default-export | Prohíbe export default; el nombre del símbolo es el contrato. Exime configs/stories y, en el preset next, los entrypoints del App Router. |
| skapxd/no-else | Prohíbe else/else if: el else es el estado sin nombre. Retorno anticipado, ternario simple o match(). |
| skapxd/no-emoji | Prohíbe emojis en strings y JSX; cada sistema los renderiza distinto. Usa un icono SVG. |
| skapxd/no-internal-module-imports | Una carpeta con barrel index.ts/index.js declara API pública: desde fuera se importa el índice, no sus archivos internos. |
| skapxd/no-explicit-any | Prohíbe any: apaga el sistema de tipos donde más se necesita. unknown para lo desconocido, el tipo real para lo demás. Wrapper de typescript-eslint. |
| skapxd/no-floating-promises | Promesas sin await ni void: el rechazo muere sin pasar por trySafe. El mensaje corrige el consejo upstream (.then/.catch aquí están prohibidos). Wrapper de typescript-eslint. |
| skapxd/no-magic-numbers | Prohíbe números mágicos: un literal numérico significativo debe extraerse a una const con nombre de dominio. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-argument | Impide pasar un any invisible como argumento: la frontera debe declararse unknown y estrecharse con schema o predicate. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-assignment | Impide asignar un any invisible a variables o propiedades: la frontera debe declararse unknown y validarse. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-call | Impide invocar valores any: antes de llamar hay que probar el tipo real con evidencia runtime. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-member-access | Impide leer propiedades sobre any: JSON.parse()/response.json() pasan por unknown + schema/predicate antes de tocar campos. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-return | Impide retornar any desde una funcion tipada: el dato externo se estrecha antes de salir de la frontera. Wrapper de typescript-eslint. |
| skapxd/no-unverified-cast | Prohíbe casts as que estrechan sin evidencia: schema, type predicate honesto o tipo de origen mejor modelado. Wrapper de typescript-eslint. |
| skapxd/prefer-schema-validation | Detecta validadores artesanales con muchos checks estructurales sobre el mismo unknown/any: eso ya es un schema, decláralo. |
| skapxd/no-impossible-branch | Condiciones que el type-checker demuestra constantes: la pregunta ya tiene respuesta. Es @typescript-eslint/no-unnecessary-condition con nombre semántico y mensajes que enseñan el fix. |
| skapxd/no-nested-if | Prohíbe if anidados: retorno anticipado o match(). Menos carga cognitiva y sin puntos ciegos para las demás reglas. |
| skapxd/no-non-null-assertion | Prohíbe el !: es "cállate, yo sé más que tú" dicho al compilador. Modela el tipo o maneja la duda. Wrapper de typescript-eslint. |
| skapxd/no-runtime-state-guard | Prohíbe if (this.x) throw en métodos: el estado inválido se hace irrepresentable en el tipo, no se vigila en runtime. |
| skapxd/no-silenced-compiler | Prohíbe @ts-ignore/@ts-nocheck: silenciar la alarma no arregla el incendio. @ts-expect-error con descripción queda para tests de tipos. Wrapper de ban-ts-comment. |
| skapxd/no-tunnel-props | Ninguna prop viaja más de un nivel: quien la recibe no puede reenviarla a otro componente. Mata el prop drilling. |
| skapxd/prefer-abort-signal | Listeners en efectos se limpian con AbortController ({ signal } + abort()), no con removeEventListener. |
| skapxd/prefer-node-protocol-for-builtins | Builtins de Node siempre con protocolo node:: separa runtime de npm y evita ambigüedad cross-runtime. |
| skapxd/prefer-tagged-union-state | Prohíbe estados inconsistentes representables: flag de loading + campo de error independientes → unión etiquetada. |
| skapxd/prefer-type-over-interface | Las uniones discriminadas son types; un type no crece en silencio por declaration merging. Wrapper de consistent-type-definitions. |
| skapxd/no-functions-inside-components | Prohíbe definir funciones dentro de componentes React. |
| skapxd/no-try-catch | Prohíbe try/catch; usa trySafe de @skapxd/result. |
| skapxd/no-promise-chain | Prohíbe .then/.catch/.finally; usa await (+ trySafe). |
| skapxd/prefer-ts-pattern | Prohíbe switch y ternarios anidados; usa match() de ts-pattern. |
| skapxd/package-requires-typed-exports | Los exports del package.json declaran types por condición (import → .d.mts, require → .d.ts): mata el bug FalseCJS. Preset package. |
| skapxd/untrusted-module-requires-adapter | Los paquetes con tipos mentirosos (@types desfasados) solo se importan desde su adaptador: la mentira vive en UN archivo. Preset package. |
| skapxd/no-jsx-ternary-null | Prefiere cond && <El /> sobre cond ? <El /> : null en JSX. |
| skapxd/repeated-jsx-requires-component | Detecta patrones JSX repetidos tres veces que ya son un componente sin nombre. Activa como error en frontend, next/react y astro/react. |
Licencia
MIT
