lint-staged
17.6.0 · 26 Sep 2026MIT26.8M / weekRepositoryHomepagenpmAtom feed
268 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
- 17.x · latest line
17.6.0
26 Sep 2026Task functions like
{ title, task }can now use a logger functionlog()to emit output while the task runs. By default, the output will only be visible if the task fails, unless the--verboseoption was used. Additionally, when the task rejects, the error will be shown in the output.import { defineConfig } from 'lint-staged/config' export default defineConfig({ '*': { title: 'Fail if PDF files are committed', task: async (filepaths, { log }) => { const pdfFiles = filepaths.filter((f) => f.toLowerCase().endsWith('.pdf')) if (pdfFiles.length > 0) { log('PDF files should not be committed: %s', pdfFiles) throw new Error('Failed') } }, }, })lint-staged now stages changes to all tracked files modified by tasks, including files that weren’t originally staged or didn’t match the configured globs. This can happen when your task has side-effects, or it's a function that ignores the staged files like
() => "prettier --write .".If you have unstaged changes in a file and the task also edits that file, your unstaged changes will be staged too. Use
--hide-unstagedto hide your changes while tasks run.The assignment of staged files to lint-staged configuration files (when using multiple, for example in a monorepo) has been rewritten to be more efficient. As a reminder, each staged file is assigned to exactly one configuration (the closest one), even if that config doesn't match the file in its globs.
Minor Changes
Task functions like
{ title, task }can now use a logger functionlog()to emit output while the task runs. By default, the output will only be visible if the task fails, unless the--verboseoption was used. Additionally, when the task rejects, the error will be shown in the output.import { defineConfig } from 'lint-staged/config' export default defineConfig({ '*': { title: 'Fail if PDF files are committed', task: async (filepaths, { log }) => { const pdfFiles = filepaths.filter((f) => f.toLowerCase().endsWith('.pdf')) if (pdfFiles.length > 0) { log('PDF files should not be committed: %s', pdfFiles) throw new Error('Failed') } }, }, })lint-staged now stages changes to all tracked files modified by tasks, including files that weren’t originally staged or didn’t match the configured globs. This can happen when your task has side-effects, or it's a function that ignores the staged files like
() => "prettier --write .".If you have unstaged changes in a file and the task also edits that file, your unstaged changes will be staged too. Use
--hide-unstagedto hide your changes while tasks run.
Patch Changes
The assignment of staged files to lint-staged configuration files (when using multiple, for example in a monorepo) has been rewritten to be more efficient. As a reminder, each staged file is assigned to exactly one configuration (the closest one), even if that config doesn't match the file in its globs.
Fix running parallel tasks for a single glob, when tasks are created by a function. Nesting one level of arrays inside an array of tasks will result in the inner tasks running in parallel. This behavior should now be consistent when creating tasks using functions. In the following example
eslintandprettierwill run in parallel (for all files, when any JS files are staged):import { defineConfig } from 'lint-staged/config' export default defineConfig({ '*.js': () => [['eslint --max-warnings=0 .', 'prettier --list-different .']], })Various performance improvements from skipping redundant internal Git calls.
Partially staged changes are hidden in a uniquely-named patch file to avoid multiple invocations of lint-staged overwriting it. This makes it safer to run lint-staged in multiple worktrees at the same time.
17.5.1
10 Sep 2026Fix TypeScript issue
TS1254fromdefineConfig()by changing the signature fromconstto afunction:A 'const' initializer in an ambient context must be a string or numeric literal or literal enum reference.
17.5.0
5 Sep 2026Lint-staged now refuses to run when files were staged with
--intent-to-add, because Git stash doesn't support them. Previously this was an unhandled error.Lint-staged now handles color support better in non-TTY streams, and honors the
FORCE_COLORenvironment variable.Update
tinyexec@1.3.1so that local binaries fromnode_modules/.binare resolved starting from the directory of each lint-staged configuration file (in monorepo setups). This behavior was broken inlint-staged@16.3.0where they were only resolved from the current working directory and up.
Minor Changes
Lint-staged now refuses to run when files were staged with
--intent-to-add, because Git stash doesn't support them. Previously this was an unhandled error.
Patch Changes
Lint-staged now handles color support better in non-TTY streams, and honors the
FORCE_COLORenvironment variable.Update
tinyexec@1.3.1so that local binaries fromnode_modules/.binare resolved starting from the directory of each lint-staged configuration file (in monorepo setups). This behavior was broken inlint-staged@16.3.0where they were only resolved from the current working directory and up.Do not try to restore untracked files when using
--hide-alland there is no initial commit yet.
17.4.1
27 Aug 2026This is a version-bump-only release because the previous version
17.4.0was not published to npmjs.com due to problems with GitHub Actions and Changesets.
17.3.0
31 Jul 2026It is now possible to run multiple tasks in parallel for a single glob by configuring it with an array of tasks (which run sequentially), and then placing another array inside it (where the tasks will run in parallel). The following demonstrates the order tasks will start in:
{ "*.ts": ["first", "second", ["third", "third"], "fourth"] }As a concrete example, lint-staged's own configuration is:
/** @type {import('./lib/index.js').Configuration} */ export default { '*': [ ['oxfmt --check --no-error-on-unmatched-pattern', 'oxlint --no-error-on-unmatched-pattern'], ], '*.ts': () => 'tsc', }which means:
During an in-progress merge, files that are unchanged from the branch being merged are now skipped. Technically, files are only included if there are staged changes against both
HEADandMERGE_HEAD.
17.2.0
23 Jul 2026The chunking of tasks based on maximum command line argument length has been re-implemented to be more precise. Now the chunking happens based on the final generated command string, instead of just the list of staged files like previously. This benefits mainly Windows platforms and function commands like:
/** @type {import('lint-staged').Configuration} */ export default { '*.ts': () => 'tsc', // Run "tsc" when any TS file is changed (for entire project) }Where the spawned command is literally
"tsc"without any extra arguments. Previously, this was still chunked when a lot of files were staged. Now, it probably won't be chunked because the length of the command is just three letters.Also, native JavaScript/Node.js function tasks won't be chunked at all, when previously they were run multiple times when chunked:
/** @type {import('lint-staged').Configuration} */ export default { '*.js': { title: 'Log staged JS files to console', task: async (files) => { console.log('Staged JS files:', files) }, }, }
17.1.1
22 Jul 2026It's now possible to set
--max-arg-length=Infinityto effectively disable chunking of tasks based on the number of staged files. The parsing and validation of the numeric CLI options--max-arg-lengthand--concurrencyhas been improved.
17.1.0
18 Jul 2026The console output of lint-staged has been simplified so that there's less interactive spinners and more explicit messages like "Started…" -> "Done!". The primary purpose of this was to remove
Listr2, a very large dependency.Before:
Size of
node_modules/after installing:1561.7 kBwith 29 packages.Fancy interactive spinners, but output dynamically changes:
✔ Backed up original state in git stash (0b191303) ✔ Running tasks for staged files... ✔ Staging changes from tasks... ✔ Cleaning up temporary files...
After:
Size of
node_modules/after installing:974.0 kBwith 5 packages (37.6 % smaller, 82.7 % less transitive dependencies).Simpler but more explicit output:
⋯ Backing up original state… ✔ Done backing up original state (35b38ed1)! ⋯ Running tasks for staged files… *.js — 1 file ⋯ oxlint --fix *.{json,md} — 1 file ⋯ oxfmt --write ✔ oxfmt --write ✔ oxlint --fix ✔ Done running tasks for staged files! ⋯ Staging changes from tasks… ✔ Done staging changes from tasks! ⋯ Cleaning up temporary files… ✔ Done cleaning up temporary files!Try to restore hidden unstaged changes when using
--no-revert.Console output colors are enabled/disabled more consistently.
Minor Changes
The console output of lint-staged has been simplified so that there's less interactive spinners and more explicit messages like "Started…" -> "Done!". The primary purpose of this was to remove
Listr2, a very large dependency.Before:
Size of
node_modules/after installing:1561.7 kBwith 29 packages.Fancy interactive spinners, but output dynamically changes:
✔ Backed up original state in git stash (0b191303) ✔ Running tasks for staged files... ✔ Staging changes from tasks... ✔ Cleaning up temporary files...
After:
Size of
node_modules/after installing:974.0 kBwith 5 packages (37.6 % smaller, 82.7 % less transitive dependencies).Simpler but more explicit output:
⋯ Backing up original state… ✔ Done backing up original state (35b38ed1)! ⋯ Running tasks for staged files… *.js — 1 file ⋯ oxlint --fix *.{json,md} — 1 file ⋯ oxfmt --write ✔ oxfmt --write ✔ oxlint --fix ✔ Done running tasks for staged files! ⋯ Staging changes from tasks… ✔ Done staging changes from tasks! ⋯ Cleaning up temporary files… ✔ Done cleaning up temporary files!
Patch Changes
Try to restore hidden unstaged changes when using
--no-revert.Console output colors are enabled/disabled more consistently.
Failed JS function tasks now properly kill other tasks, unless
--continue-on-erroris used. Previously their failure didn't affect other tasks.
17.0.8
20 Jun 2026Fix lint-staged discarding the ongoing merge conflict status (
.git/MERGE_HEAD) when using the--hide-unstagedor--hide-alloptions.Fix issues with Git commands that are successful but also emit warnings to
stderr, by ignoring thestderroutput completely when the process exits with code 0. This was the behavior when usingnano-spawnandexeca, but when switching totinyexecin 16.3.0 bothstdoutandstderrwere used as interleaved output.
17.0.7
31 May 2026Only updates dependencies, nothing else changes.
17.0.6
30 May 2026Run all tests with Deno, in addition to Node.js and Bun.
Fix performance regression of lint-staged v17 by going back to using
git addto stage task modifications. This was changed togit update-index --againin v17 for less manual work, but unfortunately theupdate-indexcommand gets slower in very large Git repos.This version of lint-staged uses the new staged publishing for npm packages feature. Releases are already published from GitHub Actions with trusted publishing, but now an additional approval with two-factor authentication is also required.
Patch Changes
Run all tests with Deno, in addition to Node.js and Bun.
Fix performance regression of lint-staged v17 by going back to using
git addto stage task modifications. This was changed togit update-index --againin v17 for less manual work, but unfortunately theupdate-indexcommand gets slower in very large Git repos.This version of lint-staged uses the new staged publishing for npm packages feature. Releases are already published from GitHub Actions with trusted publishing, but now an additional approval with two-factor authentication is also required.
Downgrade dependency
tinyexec@1.2.2to avoid issues in version 1.2.3.
17.0.5
16 May 2026Correctly set the
--max-arg-lengthdefault value based on the running platform. This controls how very long lists of staged files are split into multiple chunks.
17.0.4
9 May 2026Another fix for making sure lint-staged adds task modifications correctly to the commit in the following cases:
There's new test cases which actually setup the Git
pre_commithook to run lint-staged and verify them. These issues started in v17.0.0 when trying to improve support for committig without having explicitly staged files.
17.0.3
8 May 2026Fix lint-staged behavior when implicitly committing files without using
git addby either:
17.0.2
6 May 2026Enable immutable GitHub releases
17.0.1
6 May 2026Adjust GitHub Actions workflow so that automatic publishing works with signed commits.
17.0.0
6 May 2026- breaking
Node.js v20 is no longer supported, and the oldest supported version is now
22.22.1, which is an active LTS version at the time of this release. Node.js 20 will be EOL after April 2026. Please upgrade your Node.js version! - breaking
Lint-staged now tries to verify the installed Git version is at least
2.32.0, released in 2021. If you're using an even older Git version, you need to upgrade it before running lint-staged! - breaking
The dependency
yamlis now marked as optional and probably won't be installed by default. If you're using a YAML configuration file you should install the package separately:npm install --development yaml
If you're using
.lintstagedrcas the config file name (without a file extension), it will be treated as a YAML file. If the content is JSON, consider renaming it to.lintstagedrc.jsonto avoid needing to installyaml.
Major Changes
- breaking
Node.js v20 is no longer supported, and the oldest supported version is now
22.22.1, which is an active LTS version at the time of this release. Node.js 20 will be EOL after April 2026. Please upgrade your Node.js version! - breaking
Lint-staged now tries to verify the installed Git version is at least
2.32.0, released in 2021. If you're using an even older Git version, you need to upgrade it before running lint-staged! - breaking
The dependency
yamlis now marked as optional and probably won't be installed by default. If you're using a YAML configuration file you should install the package separately:npm install --development yaml
If you're using
.lintstagedrcas the config file name (without a file extension), it will be treated as a YAML file. If the content is JSON, consider renaming it to.lintstagedrc.jsonto avoid needing to installyaml.
Minor Changes
Add new option
--hide-allfor hiding all unstaged changes and untracked files, before running tasks. This makes it easier to run tools like Knip which check for unused code. Untracked files are included in the backup stash and restored automatically after running.Lint-staged now runs
git update-index --againafter running tasks, instead ofgit add <originally staged files>. This should improve compatibility when using non-default indexes, for example when committing with a pathspecgit commit -m "message" .instead of adding files to the index.- removed
Remove
commanderas a dependency and use the built-inparseArgsfromnode:utilto parse CLI flags.
Patch Changes
All tests now pass on the Bun runtime (latest).
Remove manual handling for
git stash --keep-indexresurrecting deleted files, because the issue was fixed in Git2.23.0and lint-staged requires at least Git2.32.0.Fix documentation about multiple config files and the
--cwdoption. When using it, all tasks will be run in the specified directory. For example, to run everything in the actualprocess.cwd(), uselint-staged --cwd=".".
- 16.x
16.4.0
14 Mar 2026Reading the note…
16.3.4
14 Mar 2026Reading the note…
16.3.3
10 Mar 2026Reading the note…
16.3.2
3 Mar 2026Reading the note…
16.3.1
1 Mar 2026Reading the note…
16.3.0
28 Feb 2026Reading the note…
16.2.7
19 Nov 2025Reading the note…
16.2.6
22 Oct 2025Reading the note…
16.2.5
20 Oct 2025Reading the note…
16.2.4
11 Oct 2025Reading the note…
16.2.3
28 Sep 2025Reading the note…
16.2.2
28 Sep 2025Reading the note…
16.2.1
25 Sep 2025Reading the note…
16.2.0
22 Sep 2025Reading the note…
16.1.6
1 Sep 2025Reading the note…
16.1.5
8 Aug 2025Reading the note…
16.1.4
3 Aug 2025Reading the note…
16.1.3
3 Aug 2025Reading the note…
16.1.2
15 Jun 2025Reading the note…
16.1.1
14 Jun 2025Reading the note…
16.1.0
27 May 2025Reading the note…
16.0.0
10 May 2025Reading the note…
- 15.x
15.5.2
6 May 2025Reading the note…
15.5.1
11 Apr 2025Reading the note…
15.5.0
12 Mar 2025Reading the note…
15.4.3
26 Jan 2025Reading the note…
15.4.2
23 Jan 2025Reading the note…
15.4.1
16 Jan 2025Reading the note…
15.4.0
16 Jan 2025Reading the note…
15.3.0
28 Dec 2024Reading the note…
15.2.11
10 Dec 2024Reading the note…
15.2.10
1 Sep 2024Reading the note…
15.2.9
13 Aug 2024Reading the note…