ESLint v9 Flat Config in Monorepo Packages
Historical Note: This project migrated from ESLint to oxlint. This document is preserved for reference but ESLint is no longer used in this project.
ESLint v9 Flat Config in Monorepo Packages
Problem
After upgrading to ESLint v9 (or when adding a new package to the monorepo), pnpm lint fails silently or with
confusing errors. ESLint appears to run but finds nothing to lint, or reports that it cannot find a configuration file.
Symptoms:
pnpm lintexits non-zero with no lint output- ESLint reports “couldn’t find a configuration file”
- Using
--ext ts,tsxflag causes “Unknown CLI option” error - New monorepo package linting silently does nothing
Investigation
Steps Tried
- Checked if shared config (
@inklings/eslint-config) was installed — it was, as a workspace dependency - Checked if the shared config was in flat format — it was (exports an array)
- Realized the desktop app had no
eslint.config.jsto import the shared config
Root Cause
ESLint v9 is a breaking change that drops support for legacy configuration formats (.eslintrc.*, package.json
eslintConfig field). It requires every package to have an eslint.config.js (or .mjs/.cjs) file that exports a
flat config array.
Additionally, the --ext CLI flag was removed in v9. File type filtering is now handled within the config itself via
the files property on config objects.
In a monorepo, each package that runs ESLint needs its own eslint.config.js that imports the shared config. Without
it, ESLint has no configuration and either fails or does nothing.
Solution
1. Create eslint.config.js in each package
import reactConfig from "@inklings/eslint-config/react";
export default [ ...reactConfig, { ignores: ["dist/**", "src-tauri/**"], },];2. Update lint scripts — remove --ext flag
// Before (ESLint v8)"lint": "eslint src-react --ext ts,tsx"
// After (ESLint v9)"lint": "eslint src-react"Implementation Notes
- The shared config already defines file type matching via
files: ["**/*.{ts,tsx}"]internally - The
ignoresarray replaces.eslintignorein flat config - Each new monorepo package needs this boilerplate — consider it part of the “new package checklist”
Prevention
Best Practices
- When adding a new package to the monorepo, always create
eslint.config.jsthat imports the shared config - Never use
--extflag with ESLint v9+ - Test
pnpm lintafter adding any new package
Warning Signs
pnpm lintsucceeds suspiciously fast with zero output — likely means ESLint found no config- Any lint script containing
--extis using legacy syntax
Checklist for New Packages
- Add
@inklings/eslint-configas a devDependency - Create
eslint.config.jsimporting the appropriate shared config variant - Add
ignoresfor build output directories - Add
"lint": "eslint src"script (adjust path as needed) - Verify:
pnpm lintshould produce output (even if clean)
References
- ESLint v9 Migration Guide
- Commit:
097d2f0— Addedeslint.config.jsto desktop app
Tokio Background Worker Patterns Next
Proc-Macro Generated Code Triggers dead_code Warnings
Was this page helpful?
Thanks for your feedback!