frunk — supercharging npm scripts

frunk is a fast, lightweight runner for orchestrating npm scripts. It runs tasks in parallel by default, supports readable sequential chains with ->, and resolves dependencies across scripts with automatic deduplication.
Highlights
- 🚀 Parallel by default: run many scripts at once
- 🔗 Sequential chains:
[a,b]->[c] for clear order
- 🎯 Globs and excludes:
*:dev, build:*, !test:e2e
- 📦 Dependency graph: dedupe shared deps across scripts
- 🎨 Clean output: colored, aligned, prefixed logs
Installation
Install as a dev dependency:
npm i -D frunk
NOTE: Until frunk hits 1.0, breaking changes may be made on minor versions (0.x.0) and the remaining changes will be patch versions (0.0.x)
Quickstart
Add a few scripts to package.json:
{
"scripts": {
"dev": "frunk [*:dev]",
"build": "frunk [build:*]",
"start": "frunk [build] -- node server.js",
"test": "frunk [lint,typecheck]->[test:*]",
"lint": "frunk -- eslint .",
"typecheck": "frunk -- tsc --noEmit",
"test:unit": "frunk -- vitest run",
"test:playwright": "frunk [build] -- playwright test"
}
}
Tip: You can shorten frunk to f (used below).
Comparison
| Parallel by default | ✅ | ✅ | ✅ | ➖ |
| Sequential chains | ✅ | ✅ | ➖ | ✅ |
| Globs/excludes | ✅ | ✅ | ➖ | ➖ |
| Dep graph + dedupe | ✅ | ➖ | ➖ | ✅ |
| Colored prefixes | ✅ | ➖ | ✅ | ➖ |
Docs
Syntax
f [patterns] [flags] -- command
frunk runs bracketed pattern groups. Tasks inside a single group run in parallel. Use -> to chain groups so that all tasks in the left group finish before the next group starts. Anything after -- is treated as a shell command and executed once the preceding groups complete.
Pattern Matching
Patterns resolve to npm script names:
- Exact names:
test:unit runs that script if present.
- Globs:
build:*, *:dev match multiple scripts using shell-safe micromatch patterns.
- Exclusions: prefix with
! to omit matches, e.g. [test:*,!test:e2e].
- Parallel sets: comma‑separate inside a group, e.g.
[lint,typecheck].
- Sequencing: chain groups with
->, e.g. [lint,typecheck]->[build].
Square brackets are required. They prevent shell expansion and make intent explicit.
Command Separator --
Place -- before an inline command to run after the selected groups complete, e.g. [build] -- node server.js. The command runs through your system shell and inherits PATH including node_modules/.bin.
Flags
-q, --quiet: Reduce noise by hiding task output.
-c, --continue: Don’t stop the run on failure; continue running remaining tasks/groups.
--no-prefix: Disable the colored [script] | prefixes.
--prefix=<str>: Replace the default prefix label with a custom string.
By default, failures stop downstream groups. Use -c to keep going when some tasks fail.
Notes
- Nested frunk commands are not supported.
- Output is colorized and aligned with stable, per‑task prefixes.
Example
Medium-size setup showing shared deps, parallel groups, and sequences:
{
"scripts": {
"generate": "graphql-codegen",
"dev": "f [*:dev]",
"build": "f [*:build]",
"start": "f [*:start]",
"test": "frunk [lint,typecheck]->[test:*]",
"lint": "frunk -- eslint .",
"typecheck": "frunk -- tsc --noEmit",
"test:unit": "frunk -- vitest run",
"test:playwright": "frunk [build] -- playwright test",
"worker:dev": "f -- tsx --watch ./src/worker/start.ts",
"worker:start": "f -- tsx ./src/worker/start.ts",
"api:dev": "f -- tsx --watch ./src/api/server.ts",
"api:start": "f -- tsx ./src/api/server.ts",
"app:dev": "f [generate] -- vite dev",
"app:build": "f [generate] -- vite build",
"app:start": "f -- vite serve"
}
}
Running npm run dev executes shared:dep once, even though multiple dev tasks depend on it.
Links