Context
Task: would a single top-level ESLint config improve lint/format speed?
Short answer: No. The dominant, zero-risk win is --cache (~10x incremental). Collapsing to one top-level config is a modest cold-only win (~2x) that costs per-package isolation and widens lint scope.
How lint runs today
- One shared config
@cpn-console/eslint-config (flat config over @antfu/eslint-config) consumed by 17 eslint.config.* files.
pnpm -r run lint spawns ~15 separate eslint ./ processes; each re-imports the shared config, reloading Node + plugins + typescript-eslint parser. That startup/parser cost — not config-file count — is what we pay for.
- 14/17 configs are byte-identical bare wrappers. Only 3 diverge:
- root: ignores
apps/packages/plugins (so lint:root is effectively inert for repo source)
- harbor: ignores
src/api/Api.ts
- client: 2 rule overrides
- No
--cache flag anywhere.
Measurements (Node 24.12, ESLint 10.5, antfu 8.2)
| Command |
Cold |
Warm (cache) |
pnpm -r run lint (17 procs) |
22.1s |
— |
single root eslint . |
10.4s |
2.0s |
single root eslint . --cache |
10.4s |
2.0s |
Recommendation (in priority order)
- Ship
--cache — DO. Zero-risk, ~10x incremental warm, works under either layout. Adds --cache to the lint/format scripts and ignores .eslintcache.
- Implementation is already prepared in worktree branch
wt/t_2fb40277 (17 files, +34/-31, uncommitted, pending review → PR).
- Verified: cold
pnpm lint 18.98s, warm 8.91s (~2.1x re-run), exit 0; 14 per-package .eslintcache produced.
- Do NOT collapse to one top-level config. ~2x cold win only; kills per-package lint isolation; surfaces ~40 currently-unlinted root-level violations (
pnpm-workspace.yaml, README.md, commitlint.config.cjs, docker/*.yml, every package.json). Revisit only if per-package isolation is explicitly unwanted.
- Secondary follow-ups (optional):
- Fix or delete the dead
lint:root scope (root config ignores the whole monorepo source).
- Resolve doc/config drift: AGENTS.md claims
server-nestjs uses Prettier, but its eslint.config.mjs does not enable it.
Acceptance
Context
Task: would a single top-level ESLint config improve lint/format speed?
Short answer: No. The dominant, zero-risk win is
--cache(~10x incremental). Collapsing to one top-level config is a modest cold-only win (~2x) that costs per-package isolation and widens lint scope.How lint runs today
@cpn-console/eslint-config(flat config over@antfu/eslint-config) consumed by 17eslint.config.*files.pnpm -r run lintspawns ~15 separateeslint ./processes; each re-imports the shared config, reloading Node + plugins + typescript-eslint parser. That startup/parser cost — not config-file count — is what we pay for.apps/packages/plugins(solint:rootis effectively inert for repo source)src/api/Api.ts--cacheflag anywhere.Measurements (Node 24.12, ESLint 10.5, antfu 8.2)
pnpm -r run lint(17 procs)eslint .eslint . --cacheRecommendation (in priority order)
--cache— DO. Zero-risk, ~10x incremental warm, works under either layout. Adds--cacheto thelint/formatscripts and ignores.eslintcache.wt/t_2fb40277(17 files, +34/-31, uncommitted, pending review → PR).pnpm lint18.98s, warm 8.91s (~2.1x re-run), exit 0; 14 per-package.eslintcacheproduced.pnpm-workspace.yaml,README.md,commitlint.config.cjs,docker/*.yml, everypackage.json). Revisit only if per-package isolation is explicitly unwanted.lint:rootscope (root config ignores the whole monorepo source).server-nestjsuses Prettier, but itseslint.config.mjsdoes not enable it.Acceptance
--cachemerged and.eslintcachegitignoredlint:root+ Prettier drift resolved in follow-up