src/skills/shared-tooling-eslint-prettier/SKILL.md
ESLint 9/10 flat config with defineConfig(), Prettier v3.0+ shared config, eslint-config-prettier integration, typescript-eslint v8+ projectService
npx skillsauth add agents-inc/skills shared-tooling-eslint-prettierInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: ESLint 9+ flat config with
defineConfig()andglobalIgnores(). typescript-eslint v8+ withprojectService: true. Prettier shared config with consistent formatting. eslint-config-prettier to disable conflicting rules. eslint-plugin-only-warn for better DX.WARNING: ESLint 10 was released February 2026 and completely removes .eslintrc support. Migrate to flat config now.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use ESLint 9+ flat config with defineConfig() from eslint/config - NOT legacy .eslintrc)
(You MUST use globalIgnores() for explicit global ignore patterns - NOT bare ignores property)
(You MUST use typescript-eslint v8+ with projectService: true for typed linting)
(You MUST include eslint-plugin-only-warn to convert errors to warnings for better DX)
(You MUST use eslint-config-prettier to disable formatting rules that conflict with Prettier)
</critical_requirements>
Auto-detection: ESLint 9 flat config, defineConfig, globalIgnores, eslint.config.ts, Prettier config, prettier.config.mjs, eslint-config-prettier, eslint-plugin-only-warn, typescript-eslint projectService, .eslintrc migration
When to use:
When NOT to use:
Detailed Resources:
Linting and formatting should be fast, consistent, and non-blocking. Developers should not fight with tools - tools should help catch issues early while staying out of the way during development.
Core principles:
ESLint 9+ uses flat config. The defineConfig() helper from eslint/config provides type safety and automatic array flattening. globalIgnores() explicitly marks global ignore patterns.
// eslint.config.ts — the essential flat config
import js from "@eslint/js";
import { defineConfig, globalIgnores } from "eslint/config";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
import * as onlyWarnPlugin from "eslint-plugin-only-warn";
export default defineConfig(
globalIgnores(["dist/**", "generated/**", "node_modules/**"]),
js.configs.recommended,
eslintConfigPrettier,
tseslint.configs.recommended,
{ plugins: { "only-warn": onlyWarnPlugin } }, // must be last
);
Key points: defineConfig() auto-flattens arrays (no spread operators needed), globalIgnores() prevents ambiguous behavior of bare ignores, only-warn converts all preceding errors to warnings, eslint-config-prettier disables formatting rules that conflict with Prettier.
See examples/core.md for the complete standalone and shared config patterns.
The projectService feature (stable since v8) auto-discovers the nearest tsconfig.json for each file, replacing the fragile manual project path.
parserOptions: {
projectService: true,
allowDefaultProject: ["*.config.ts", "*.config.mjs"],
},
Key points: Eliminates need for tsconfig.eslint.json files, faster than manual project configuration, allowDefaultProject handles config files not in tsconfig.
See examples/core.md for full typescript-eslint configuration.
For teams or monorepos, extract linting config into a shared package to prevent drift.
// packages/eslint-config/base.ts — shared config
export const baseConfig = defineConfig(
globalIgnores(["dist/**", "generated/**"]),
js.configs.recommended,
eslintConfigPrettier,
tseslint.configs.recommended,
{ plugins: { "only-warn": onlyWarnPlugin } },
);
// apps/my-app/eslint.config.ts — consuming shared config
export default defineConfig(baseConfig, customRules, {
rules: { "no-console": "warn" },
});
Key points: defineConfig() auto-flattens so no spread operators needed, single source of truth prevents config drift, TypeScript config file for type checking.
See examples/eslint.md for shared config and custom rules patterns.
Prettier config should be consistent across all packages. Use a shared config for teams.
// prettier.config.mjs
const config = {
printWidth: 100,
semi: true,
singleQuote: false,
bracketSpacing: true,
arrowParens: "always",
endOfLine: "lf",
bracketSameLine: false,
// trailingComma: "all" is the default in Prettier 3.0+
};
export default config;
Key points: trailingComma: "all" is the default in v3.0+ (don't set it explicitly), bracketSameLine replaces deprecated jsxBracketSameLine, explicit endOfLine: "lf" prevents cross-platform issues.
See examples/prettier.md for TypeScript config files, experimental options, and ignore patterns.
Common custom rules for enforcing project conventions — named exports, consistent type imports, unused variable detection, and import boundary enforcement:
export const customRules = {
rules: {
"import/no-default-export": "warn",
"@typescript-eslint/consistent-type-imports": [
"warn",
{ prefer: "type-imports" },
],
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
},
};
See examples/eslint.md for the full custom rules pattern including import boundary restrictions.
The extends property in flat config objects simplifies plugin composition — standardizes config merging regardless of plugin format (object, array, or string):
export default defineConfig({
files: ["**/*.ts", "**/*.tsx"],
extends: [
"eslint/recommended",
tseslint.configs.recommended,
// Add your framework plugin's flat config here
],
rules: { "no-console": "warn" },
});
See examples/core.md for the full extends pattern.
</patterns><decision_framework>
Need linting and formatting?
├─ Speed is critical bottleneck (1000+ files)?
│ └─ YES → Consider a Rust-based unified linter/formatter (not this skill's scope)
└─ Need mature plugin ecosystem?
└─ YES → ESLint 9/10 + Prettier ✓
ESLint + Prettier strengths: Mature ecosystem, extensive plugin support, framework-specific plugins
Which ESLint version?
├─ New project?
│ └─ ESLint 10 (latest, cleanest API)
├─ Existing project with flat config?
│ └─ ESLint 10 (straightforward upgrade)
├─ Existing project with .eslintrc?
│ ├─ Can invest time to migrate?
│ │ └─ YES → Migrate to flat config, then ESLint 10
│ └─ NO → ESLint 9.x (still supported, but plan migration)
└─ Node.js < 20.19.0?
└─ ESLint 9.x (ESLint 10 requires 20.19.0+)
Setting up linting/formatting?
├─ Monorepo with multiple packages?
│ └─ YES → Shared config ✓
├─ Team project (2+ developers)?
│ └─ YES → Shared config (consistency matters)
└─ Single package / solo project?
└─ YES → Local config is fine
What Prettier config format to use?
├─ Need type checking in config?
│ ├─ Node.js 22.6.0+? → prettier.config.ts
│ └─ NO → Use .mjs with JSDoc types
├─ ESM project? → prettier.config.mjs
└─ CommonJS project? → prettier.config.cjs
</decision_framework>
<red_flags>
High Priority Issues:
ignores property instead of globalIgnores() helper (ambiguous behavior — acts as global ignores when alone, but as local excludes when paired with other properties)Medium Priority Issues:
project option instead of projectService: true in typescript-eslint (fragile in monorepos, slower)jsxBracketSameLine option in Prettier (renamed to bracketSameLine in Prettier 2.4)trailingComma: "all" in Prettier 3.0+ (it is already the default)tseslint.config() wrapper (planned for deprecation in favor of ESLint's native defineConfig())Gotchas & Edge Cases:
defineConfig() auto-flattens arrays — never use spread operators with itprojectService requires typescript-eslint v8+ (was EXPERIMENTAL_useProjectService in v6-v7)^20.19.0 || ^22.13.0 || >=24 (v21.x and v23.x explicitly unsupported).prettierrc.ts) require Node.js 22.6.0+; before Node v24.3.0 run with --experimental-strip-types@prettier/sync for sync wrappers)eslint.config.ts TypeScript config files and extends property supported natively--concurrency flag (30-300% performance boost on large projects)/* eslint-env */ comments now trigger errors; deprecated Linter methods removed</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md
(You MUST use ESLint 9+ flat config with defineConfig() from eslint/config - NOT legacy .eslintrc)
(You MUST use globalIgnores() for explicit global ignore patterns - NOT bare ignores property)
(You MUST use typescript-eslint v8+ with projectService: true for typed linting)
(You MUST include eslint-plugin-only-warn to convert errors to warnings for better DX)
(You MUST use eslint-config-prettier to disable formatting rules that conflict with Prettier)
Failure to follow these rules will cause inconsistent tooling, conflicting formatting rules, and blocked developers.
WARNING: ESLint 10 (February 2026) completely removes .eslintrc support. Plan migration now.
</critical_reminders>
development
Material Design component library for Vue 3
development
VitePress 1.x — Vue-powered static site generator for documentation sites, built on Vite
tools
Docusaurus 3.x documentation framework — site configuration, docs/blog plugins, sidebars, versioning, MDX, swizzling, and deployment
development
TanStack Form patterns - useForm, form.Field, validators, arrays, linked fields, createFormHook, type safety