package.json scripts across the packages and modules of your workspace, in dependency order, with a content-addressed task cache. Tasks whose inputs have not changed are restored from the cache instead of re-executed.
Usage
Examples
Build and lint every package and module:Options
| Option | Description | Default |
|---|---|---|
--commands | Comma-separated script names to run, in order. Required. | — |
--packages | Comma-separated package names to include (under packages/). | All packages and modules |
--modules | Comma-separated module names to include (under modules/). | All packages and modules |
--logs | Stream plain log lines instead of the interactive view. | false |
--no-cache | Skip reading and writing the task cache. | false |
Execution
Each command in--commands runs as a group: first every build, then every lint, and so on. Within a group, targets run in workspace dependency order — a target waits for the targets it depends on — with up to four tasks running concurrently.
A target whose package.json does not define the script is skipped without an error. If any task fails, the run stops immediately: remaining tasks are cancelled, the failing task’s output is printed, and the command exits with code 1.
Output
Without--logs, an interactive view keeps a live status bar pinned to the bottom of the terminal while finished tasks scroll into your normal terminal history above it — scrollback is preserved, not taken over.
- Every task prints a permanent line when it finishes: a green
✔ billing:build 1.2son success,✔ user:lint cachedon a cache hit,○ shared:test no "test" scriptwhen skipped, or a red✖ web:build failed exit 1on failure. - The status bar shows a progress bar with the completed/total count and elapsed time, plus one line per running task — each with a spinner and that task’s latest log line.
- Press
ctrl+c(orq) to abort.
--logs, each task streams its output live, prefixed with the task label so concurrent tasks stay readable, and closes with a ✔ or ✖ line and its duration:
Caching
Results are cached invar/cache/monorepo/ at the project root. A task’s cache key hashes every source file of its target individually, the fingerprints of all transitive workspace dependencies, the script text, and the root config files (package.json, bun.lock, tsconfig.json, biome.jsonc). Build artifacts such as node_modules, dist, and var are excluded, so a task re-runs exactly when something it can observe has changed.
A cache hit restores the task’s output artifacts — dist/ by default — so you can delete dist/ and still get it back instantly, and prints a ✔ … cached line instead of re-running the script. Only successful runs are cached. To capture different directories, declare them in the target’s package.json: