Linting
Skills modulares para asistentes de codificación por IA. Define reglas, flujos de trabajo y estándares técnicos mediante archivos Markdowm.
npx -y skills add 14BryanEspinoza/agent-stack --skill lintingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 21 days oldThe repository was created 21 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Reglas de ESLint y Prettier - formato consistente, flat config, integración con husky/lint-staged, CI/CD
SKILL.md
12.7 KB, as published. Nobody here has run it
Linting — ESLint & Prettier
1. Filosofía
- Consistencia sobre preferencias — El linter y formatter eliminan discusiones de estilo. Lo importante es que el código sea uniforme, no qué estilo se elija.
- Formato automatizado — Prettier formatea solo, sin configuración por equipo. ESLint se enfoca en calidad de código, no en estilo.
- Flat config (ESLint 9+) — Desde ESLint v9, el formato legacy (
.eslintrc) está deprecado. Usareslint.config.jscon flat config. - Pre-commit hooks —
lint-staged+huskygarantizan que solo pase código linted y formateado. Sin atajos. - CI como cortafuegos — El CI también corre lint. Si pasa local pero falla en CI, hay un desajuste de configuración.
2. Versiones Mínimas
| Tecnología | Versión Mínima |
|---|---|
| Node.js | 22+ |
| ESLint | 9+ |
| Prettier | 3+ |
| @eslint/js | 9+ |
| typescript-eslint | 8+ |
| husky | 9+ |
| lint-staged | 15+ |
3. Instalación
# ESLint + Prettier + integración
pnpm add -D eslint prettier eslint-config-prettier
# Husky + lint-staged (pre-commit hooks)
pnpm add -D husky lint-staged
# TypeScript (opcional)
pnpm add -D typescript-eslint @eslint/js typescript
Inicializar Husky
pnpm exec husky init
# Crea .husky/pre-commit — luego agregar: pnpm exec lint-staged
4. ESLint — Flat Config (eslint.config.js)
ESLint 9+ usa flat config por defecto. No crear
.eslintrc.*.
Configuración básica (JavaScript/ESM)
// eslint.config.js
import js from "@eslint/js";
export default [
js.configs.recommended,
{
rules: {
"no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
"no-console": ["warn", { allow: ["warn", "error"] }],
"no-debugger": "error",
"no-duplicate-imports": "error",
"prefer-const": "error",
"no-var": "error",
eqeqeq: ["error", "always"],
curly: ["error", "all"],
"no-throw-literal": "error",
"prefer-template": "warn",
},
},
{
ignores: [
"dist/",
"build/",
"node_modules/",
".git/",
"coverage/",
"*.config.*",
],
},
];
TypeScript
// eslint.config.js
import js from "@eslint/js";
import tseslint from "typescript-eslint";
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.stylistic,
{
rules: {
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_" },
],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/consistent-type-imports": [
"error",
{ prefer: "type-imports" },
],
},
},
{
ignores: [
"dist/",
"build/",
"node_modules/",
".git/",
"coverage/",
"*.config.*",
"*.d.ts",
],
},
);
React + JSX
// eslint.config.js
import js from "@eslint/js";
import reactPlugin from "eslint-plugin-react";
import reactHooksPlugin from "eslint-plugin-react-hooks";
export default [
js.configs.recommended,
{
plugins: {
react: reactPlugin,
"react-hooks": reactHooksPlugin,
},
settings: {
react: { version: "detect" },
},
rules: {
...reactPlugin.configs.recommended.rules,
...reactHooksPlugin.configs.recommended.rules,
"react/react-in-jsx-scope": "off",
"react/jsx-uses-react": "off",
"react/prop-types": "off",
"react/jsx-no-target-blank": "error",
"react/self-closing-comp": "error",
},
},
{
ignores: ["dist/", "build/", "node_modules/", ".git/", "coverage/"],
},
];
Reglas recomendadas por categoría
Posibles errores
{
rules: {
"no-console": ["warn", { allow: ["warn", "error"] }],
"no-debugger": "error",
"no-duplicate-imports": "error",
"no-constant-binary-expression": "error",
"no-promise-executor-return": "error",
"no-self-compare": "error",
"no-template-curly-in-string": "error",
"no-unmodified-loop-condition": "error",
"no-unreachable-loop": "error",
"require-atomic-updates": "error",
},
}
Buenas prácticas
{
rules: {
"array-callback-return": "error",
"block-scoped-var": "error",
curly: ["error", "all"],
"default-case-last": "error",
eqeqeq: ["error", "always"],
"no-eval": "error",
"no-extend-native": "error",
"no-implied-eval": "error",
"no-iterator": "error",
"no-lone-blocks": "error",
"no-new-wrappers": "error",
"no-proto": "error",
"no-return-assign": "error",
"no-script-url": "error",
"no-throw-literal": "error",
"no-unused-expressions": "error",
"no-useless-concat": "error",
"prefer-regex-literals": "error",
"require-await": "warn",
yoda: "error",
},
}
Estilo
{
rules: {
"consistent-return": "error",
"no-lonely-if": "error",
"no-multi-assign": "error",
"no-nested-ternary": "error",
"no-unneeded-ternary": "error",
"one-var": ["error", "never"],
"prefer-const": "error",
"prefer-destructuring": "warn",
"prefer-object-spread": "error",
"prefer-template": "warn",
"sort-imports": ["warn", { ignoreDeclarationSort: true }],
},
}
5. Prettier
.prettierrc
{
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf",
"quoteProps": "as-needed"
}
Alternativa en eslint.config.js
import prettierConfig from "eslint-config-prettier";
export default [
// ... otras configs
prettierConfig, // Siempre al final para desactivar reglas conflictivas
];
Ignorar archivos (.prettierignore)
# .prettierignore
dist/
build/
node_modules/
.git/
coverage/
*.min.js
*.map
*.lock
*.svg
*.png
*.jpg
*.ico
CHANGELOG.md
Scripts en package.json
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check ."
}
}
6. Integración ESLint + Prettier
eslint-config-prettier (recomendado)
Desactiva todas las reglas de ESLint que entran en conflicto con Prettier. Se coloca al final del array en flat config.
// eslint.config.js
import js from "@eslint/js";
import prettierConfig from "eslint-config-prettier";
export default [
js.configs.recommended,
// ... otros plugins y reglas
prettierConfig, // último — desactiva reglas de estilo conflictivas
];
eslint-plugin-prettier (no recomendado)
Ejecuta Prettier como regla de ESLint. Tiene problemas de rendimiento y puede duplicar errores. Preferir eslint-config-prettier + ejecutar Prettier por separado.
// ❌ No recomendado
import eslintPluginPrettier from "eslint-plugin-prettier";
export default [
{
plugins: { prettier: eslintPluginPrettier },
rules: {
"prettier/prettier": "error",
},
},
];
Flujo recomendado
1. ESLint detecta errores de calidad (no estilo)
2. Prettier formatea automáticamente (estilo)
3. eslint-config-prettier evita conflictos entre ambos
4. lint-staged ejecuta ambos en pre-commit
7. Husky + lint-staged (Pre-commit Hooks)
Instalación
pnpm add -D husky lint-staged
pnpm exec husky init
Configurar pre-commit hook
# .husky/pre-commit
pnpm exec lint-staged
Configuración en package.json
{
"lint-staged": {
"*.{js,ts,tsx,mjs,cjs}": ["eslint --fix", "prettier --write"],
"*.{json,md,css,html,yaml,yml}": ["prettier --write"]
}
}
Sin husky (git hooks nativos)
# .git/hooks/pre-commit
#!/bin/sh
pnpm exec lint-staged
8. CI/CD
Pipeline básico
name: Lint & Format
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm format:check
Con múltiples versiones de Node
jobs:
lint:
strategy:
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- run: pnpm lint
9. ESLint en Editores
VS Code (settings.json)
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"eslint.validate": [
"javascript",
"typescript",
"javascriptreact",
"typescriptreact"
]
}
Neovim / Vim (lazy.nvim)
{
"nvimtools/none-ls.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
opts = function()
local null_ls = require("null-ls")
return {
sources = {
null_ls.builtins.formatting.prettier,
null_ls.builtins.diagnostics.eslint,
null_ls.builtins.code_actions.eslint,
},
}
end,
}
10. Linting para Otros Archivos
Markdown
pnpm add -D eslint-plugin-markdown
// eslint.config.js
import markdownPlugin from "eslint-plugin-markdown";
export default [
...markdownPlugin.configs.recommended,
{
files: ["**/*.md"],
processor: "markdown/markdown",
},
];
JSON
pnpm add -D prettier-plugin-packagejson
{
"plugins": ["prettier-plugin-packagejson"]
}
CSS / SCSS
pnpm add -D stylelint stylelint-config-standard
// stylelint.config.js
export default {
extends: ["stylelint-config-standard"],
rules: {
"selector-class-pattern": null,
},
};
11. Troubleshooting
ESLint no encuentra la config
# Verificar que eslint.config.js existe en la raíz
ls eslint.config.js
# Verificar que no hay .eslintrc.* (legacy)
ls .eslintrc* 2>/dev/null || echo "No legacy config"
# ESLint 9+ ignora .eslintrc si existe eslint.config.js
rm .eslintrc* 2>/dev/null; echo "Legacy configs removed"
Conflicto entre ESLint y Prettier
# eslint-config-prettier desactiva reglas conflictivas
# Asegúrate de que prettierConfig está AL FINAL del array flat config
lint-staged no ejecuta
# Verificar hook
cat .husky/pre-commit
# Asegurar que husky está instalado
pnpm exec husky
# Ejecutar manualmente
pnpm exec lint-staged --verbose
ESLint lento
# Ignorar node_modules y dist
# Usar --cache
pnpm lint --cache
# En flat config, los ignores en objeto tienen más prioridad
Error: "ESLint couldn't find the config"
# Asegurar que eslint.config.js exporta un array
node -e "import('./eslint.config.js').then(m => console.log(Array.isArray(m.default)))"
12. Prohibiciones
- ❌ NO usar
.eslintrc.*legacy en proyectos nuevos (usar flat configeslint.config.js) - ❌ NO desactivar reglas sin comentario explicativo (
// eslint-disable-next-line reason) - ❌ NO committear
console.log— usarno-console: warny revisar antes de commit - ❌ NO usar
eslint-plugin-prettier— preferireslint-config-prettier+ Prettier separado - ❌ NO ignorar warnings de lint en PRs (configurar
max-warnings: 0en CI) - ❌ NO saltar hooks de pre-commit (
git commit --no-verifysolo en emergencias) - ❌ NO mezclar flat config con legacy config en el mismo proyecto
- ❌ NO usar
// eslint-disable-next-linesin especificar la regla exacta - ❌ NO tener reglas de estilo en ESLint que Prettier ya maneja
- ❌ NO poner archivos autogenerados en lint (ignorar
dist/,build/,.next/) - ❌ NO usar
@babel/eslint-parsersi usas TypeScript (usar@typescript-eslint/parser) - ❌ NO instalar ESLint globalmente (usar la versión local del proyecto)
13. Referencias
Nota: Para CI/CD, ver Deploy Nota: Para scripts en package.json, ver Package Manager Nota: Para control de versiones y hooks, ver Git Nota: Para JavaScript/TypeScript, ver JavaScript
Última actualización: 2026-07