npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

fast-staged

v1.0.2

Published

A drop-in replacement for lint-staged, optimized for speed

Readme

[!NOTE] Test of lint-staged alternatives, with the original built by AI, and the new one partially built with AI. Would not recommend for large projects.

fast-staged

A drop-in replacement for lint-staged — optimized for speed.

Why faster?

| | lint-staged | fast-staged | | -------------- | ---------------------------------------- | ------------------------------ | | Dependencies | listr2, picomatch, string-argv, tinyexec | zero (bundled single file) | | Startup | ~180ms | ~15ms | | Concurrency | Sequential by default | Concurrent by default | | Stash strategy | Full stash | Lightweight index stash | | Bundle size | ~300KB unpacked | ~25KB |

Install

npm install --save-dev fast-staged
# or
yarn add -D fast-staged

Usage

fast-staged is a drop-in replacement — it reads the same config as lint-staged:

// package.json
{
  "lint-staged": {
    "*.{js,ts}": "eslint --fix",
    "*.{css,scss}": ["stylelint --fix", "prettier --write"]
  }
}

Then in your .husky/pre-commit or lefthook.yml, just swap the binary:

# Before
npx lint-staged

# After (option 1 — explicit)
npx fast-staged

# After (option 2 — aliased, no changes needed)
# fast-staged also registers itself as `lint-staged` in node_modules/.bin

Config formats

All lint-staged config formats are supported:

  • package.json"lint-staged" or "fast-staged" key
  • lint-staged.config.js / .mjs / .cjs
  • .lintstagedrc / .lintstagedrc.json / .lintstagedrc.js
  • .lintstagedrc.yaml / .yml
  • fast-staged.config.js / .json
// lint-staged.config.js  ← works as-is
export default {
  "*.{js,ts}": ["eslint --fix", "prettier --write"],
  "*.md": "prettier --write",
};
// Can also export a function (same as lint-staged)
export default async function (stagedFiles) {
  return {
    "*.ts": `tsc --noEmit`,
  };
}

CLI Options

fast-staged [options]

  -c, --config <path>   Path to config file
  --no-stash            Don't stash unstaged changes before running
  --no-concurrent       Run tasks sequentially
  --allow-empty         Run even when no files match
  --lean                Minimize git subprocesses (see Lean mode below)
  --debug               Enable debug output
  -h, --help            Show help
  --version             Print version

Programmatic API

import { fastStaged } from "fast-staged";

const ok = await fastStaged({
  cwd: process.cwd(), // working directory
  concurrent: true, // run tasks concurrently (default)
  stash: true, // stash unstaged changes (default)
  diff: true, // re-stage files modified by commands
  allowEmpty: false, // run even with no matched files
  debug: false, // extra debug output
  lean: false, // or set `lean` in config — see Lean mode
});

process.exit(ok ? 0 : 1);

Lean mode

When you are fine with stricter tradeoffs, opt in so fast-staged avoids almost all git subprocesses besides listing the index (one git diff --cached per run):

  • Set "lean": true next to your globs in package.json (lint-staged / fast-staged) or in any supported config file, or pass --lean / { lean: true } to the API.
  • Skipped: git rev-parse (repo root is found by walking up for .git, with a rare fallback to git rev-parse), the unstaged-dirty probe, stashing, and post-run git add to re-stage formatter output.

Use lean mode only if a dirty working tree mixed with a partial stage will not confuse your tools, you do not rely on automatic re-staging after --write formatters, and a normal .git entry exists on disk (typical clones and worktrees).

{
  "lint-staged": {
    "lean": true,
    "*.{js,ts}": "eslint --fix"
  }
}

Lower-level utilities

import {
  loadConfig, // → { tasks, lean }; load + parse any lint-staged config format
  getStagedFiles, // list staged files via git diff --cached
  getGitRoot, // find git repository root (git subprocess)
  getGitRootPreferFs, // walk `.git` then optional git fallback
  peekPackageJsonLean, // read `lean` from package.json up the tree (sync)
  runTasks, // run commands against matched files
  buildMatcher, // glob → (file: string) => boolean
} from "fast-staged";

File substitution

By default, matched filenames are appended to the end of commands:

{ "*.js": "eslint --fix" }
// runs: eslint --fix file1.js file2.js

Use {staged_files} to control placement:

{ "*.js": "eslint --fix {staged_files} --format compact" }
// runs: eslint --fix file1.js file2.js --format compact

How it works

  1. Gitgit diff --cached --name-only lists staged files instantly
  2. Match — each file is tested against your glob patterns (zero-dep, inlined)
  3. Stash — if you have unstaged changes, they're stashed with --keep-index so commands only see staged content
  4. Run — all matching commands launch concurrently via child_process.spawn (no shell, minimal overhead)
  5. Re-stage — after formatters run, files are re-staged with git add
  6. Restore — the stash is popped

Building for npm

npm run build      # outputs dist/index.js (ESM) + dist/index.cjs (CJS)
npm publish

The published package has zero runtime dependencies — everything is bundled by esbuild.

License

MIT