Shared ESLint, Prettier, and Knip configuration for modern TypeScript projects.
- Consistent linting across repos
- Zero-config Prettier setup
- Shared Knip static-analysis defaults
- Bundled tool binaries for ESLint, Prettier, and Knip
- Strict TypeScript rules without compromise
- One source of truth for tooling
- Flat ESLint config (latest standard)
- Preconfigured plugin ecosystem
- Prettier integration
- Shared Knip config factories
ankhorage-eslint,ankhorage-prettier, andankhorage-knipbinaries- Monorepo-friendly
bun add -D @ankhorage/devtoolsThe package owns the ESLint, Prettier, and Knip toolchain. Consuming repos should not install eslint, prettier, or knip directly unless they intentionally need a different version from the shared Ankhorage toolchain.
Use the devtools-owned binaries in package scripts:
{
"scripts": {
"lint": "ankhorage-eslint . --max-warnings=0",
"lint:fix": "ankhorage-eslint . --fix --max-warnings=0",
"format": "ankhorage-prettier --write .",
"format:check": "ankhorage-prettier --check .",
"knip": "ankhorage-knip"
}
}Create an eslint.config.js file:
import { createConfig } from '@ankhorage/devtools/eslint';
export default createConfig({
files: ['src/**/*.{ts,tsx}'],
project: ['./tsconfig.json'],
tsconfigRootDir: import.meta.dirname,
});Create a Prettier config file:
export { default } from '@ankhorage/devtools/prettier';CommonJS repos can use:
module.exports = require('@ankhorage/devtools/prettier');Create a repo-local knip.config.ts file:
import { createKnipConfig } from '@ankhorage/devtools/knip';
export default createKnipConfig();Repos can add narrow repo-specific patterns when needed:
import { createKnipConfig } from '@ankhorage/devtools/knip';
export default createKnipConfig({
entry: ['scripts/release.ts'],
project: ['scripts/**/*.ts'],
ignore: ['fixtures/**'],
ignoreBinaries: ['custom-tool'],
ignoreFiles: ['examples/fixture.ts'],
});For workspaces-based monorepos, use the monorepo preset:
import { createKnipMonorepoConfig } from '@ankhorage/devtools/knip';
export default createKnipMonorepoConfig({
root: {
ignoreFiles: ['.prettierrc.js', 'eslint.config.js'],
},
});By default, the monorepo preset configures Knip workspaces for the root package, packages/*, and apps/*. Repos can override those defaults or add extra workspace globs:
import { createKnipMonorepoConfig } from '@ankhorage/devtools/knip';
export default createKnipMonorepoConfig({
workspaceGlobs: ['packages/*', 'apps/*', 'examples/*'],
workspaceDefaults: {
ignoreFiles: ['fixtures/**'],
},
workspaces: {
'.': {
ignoreFiles: ['.prettierrc.js', 'eslint.config.js'],
},
'apps/editor': {
ignoreFiles: ['babel.config.js'],
ignoreDependencies: ['babel-preset-expo'],
},
},
});The shared config intentionally keeps defaults narrow so Knip can still report real unused files, exports, dependencies, and binaries. Prefer explicit entry, project, ignoreBinaries, ignoreDependencies, or ignoreFiles over broad ignores.
Run the scripts in CI after dependencies are installed:
- name: Run lint
run: bun run lint
- name: Run format check
run: bun run format:check
- name: Run Knip
run: bun run knipFor workflows that support optional scripts, use the same guard style as the other devtools checks:
- name: Run Knip
run: |
if node -e "const p=require('./package.json'); process.exit(p.scripts?.knip ? 0 : 1)"; then
bun run knip
else
echo "No knip script found; skipping."
fi- Monorepos with shared standards
- Teams that want strict, predictable linting
- Projects avoiding duplicated config
- Repos that need consistent unused-file, unused-export, and dependency checks
Maintaining ESLint, Prettier, and Knip configs across multiple repositories leads to:
- duplication
- inconsistency
- drift over time
This package centralizes tooling so all projects stay aligned.
Includes:
- ESLint configuration and binary wrapper
- Prettier configuration and binary wrapper
- Knip configuration and binary wrapper
Excludes:
- runtime code
- build tooling