execa

A modern process-execution library for Node.js with template-string syntax and zero shell-injection risk.

Library
npm
v10.2.1
7,623 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
90 /100 Excellent
Development Activity 100
Maintenance 84
Community 76
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
90 /100 Excellent
Architecture 88
Code Quality 92
Innovation 90
Learning Curve 88

Execa is a process-execution library for Node.js that wraps the core child_process module in an ergonomic, promise-based API. It replaces manual escaping and string-concatenated shell commands with tagged-template syntax, so arguments are always passed as separate argv entries instead of being interpolated into a shell string — removing an entire class of shell-injection bugs by design rather than by convention.

Beyond basic execution, Execa adds features shells don’t have out of the box: piping between subprocesses while still retrieving each intermediate result, splitting output into text lines or iterating over them as they arrive, sending typed messages to and from Node.js child processes over IPC, and gracefully terminating subprocesses on cancellation instead of leaving orphaned children behind. It ships both async (execa) and sync (execaSync) variants sharing one options API, plus a script-style $ interface for shell-like one-liners without giving up any of the safety guarantees.

What You Get

  • Tagged-template command syntax (execacmd ${arg}) with automatic argument escaping and zero shell-injection risk
  • Synchronous (execaSync) and asynchronous (execa) execution sharing one identical options API
  • Subprocess piping via .pipe with access to every intermediate result, not just the final output
  • Built-in text-line splitting/iteration, binary output support, and file-based stdin/stdout redirection
  • IPC message exchange with child Node.js processes plus cancellation-aware graceful termination

Common Use Cases

  • Running build/test tool commands (npm scripts, linters, compilers) from a Node.js CLI or task runner
  • Writing cross-platform shell scripts in JavaScript instead of Bash, via the $ script interface
  • Chaining multiple subprocesses together (e.g. build | sort | head) while inspecting each stage’s output
  • Spawning and communicating with long-running Node.js worker subprocesses over IPC

Under The Hood

Architecture

Execa is built as a thin factory/dispatch layer over independently testable subsystems. lib/methods/create.js exposes a single createExeca(mapArguments, boundOptions, deepOptions, setBoundExeca) factory that every public export (execa, execaSync, execaNode, $) is built from; each variant differs only in how it maps arguments and merges options, not in a separately maintained code path. Calls are parsed as either tagged-template or classic (file, args, options) form, options are merged in layers (deep defaults, bound options, call-time options) via lib/methods/bind.js, and dispatch lands in execaCoreSync or execaCoreAsync. Cross-cutting concerns — stdio resolution (lib/stdio, lib/resolve), termination (lib/terminate: graceful signals, descendant killing, timeouts), IPC (lib/ipc), piping (lib/pipe), stream transforms (lib/transform), and verbose logging (lib/verbose) — are each isolated in their own directory and consumed through the shared merged-options object, so changing the options-merging logic ripples through all of them, but each subsystem itself stays independently readable and testable.

Tech Stack

Pure ESM (type: module) targeting Node.js 22+, with no runtime framework — everything is built directly on node:child_process and node:stream. Type definitions in index.d.ts are hand-written rather than compiled from TypeScript source. Dependencies are a set of small, single-purpose packages from the same ecosystem (@sindresorhus/merge-streams, human-signals, is-plain-obj, is-stream, npm-run-path, pretty-ms, signal-exit, yoctocolors, figures, get-stream), each handling one narrow concern rather than a general-purpose utility belt. Linting runs through xo, tests through ava with c8 coverage, type-checking through tsd plus tsc, and CI runs all of it via GitHub Actions with coverage reported to Codecov.

Code Quality

Tests are organized per-feature under test/, mirroring the lib/ module layout, with ava deliberately run single-threaded and at concurrency 1 — appropriate given the tests exercise real OS-level process and signal behavior rather than pure functions. Type correctness is verified separately from runtime behavior via tsd type-assertion tests plus a plain tsc check. Error handling is explicit and typed: dedicated ExecaError/ExecaSyncError classes carry shortMessage, exit code, signal, and the original cause, a DiscardedError sentinel distinguishes internal control-flow interruptions from real failures, and a well-known Symbol makes isExecaError checks work safely across realms instead of relying on instanceof. Naming and one-export-per-file conventions are consistent throughout. CI enforces lint, unit tests, and type checks on every push — this is a comprehensively tested and typed codebase.

What Makes It Unique

Execa’s tagged-template syntax passes interpolated values as separate argv entries rather than concatenating them into a shell string, removing shell-injection risk structurally instead of relying on the caller to escape input correctly — a guarantee most process-execution wrappers don’t offer. Its sync and async entry points share one argument-parsing and options-merging path rather than being separately maintained implementations that can drift apart. Piping exposes pipedFrom so every intermediate stage of a subprocess chain remains inspectable, unlike native shell pipes which discard everything but the final output. IPC helpers (sendMessage, getOneMessage, getEachMessage) and cancellation-aware graceful termination (cancelSignal plus gracefulCancel) give it primitives well beyond a typical wrapper around child_process.spawn.

Used by 43 apps in this directory

Ruby
61%
GPL 2.0

Discourse

Community

48,001

Open-source community platform with dynamic trust levels, real-time chat, and a powerful plugin architecture for self-hosted forums.

View details
89
Repo Health
89
Technical
67
Dependency
Built with
Ruby 61%
JavaScript 32%
Updated 5 days ago
TypeScript
74%
Apache 2.0

Fern

Developer Tools

3,822

Fern turns a single OpenAPI, AsyncAPI, or Protobuf definition into type-safe SDKs for nine languages and a hosted API documentation site, all from one CLI and one source of truth.

View details
90
Repo Health
86
Technical
66
Dependency
Built with
TypeScript 74%
Updated 5 days ago
MDX
50%
Apache 2.0

Formizee

Forms Surveys

184

An open-source form backend and builder platform — design forms, collect submissions, and get analytics without hosting your own server, positioned as an alternative to Formspree and Typeform.

View details
30
Repo Health
59
Technical
67
Dependency
Built with
MDX 50%
TypeScript 49%
Updated 1 years ago
TypeScript
58%
AGPL 3.0

Frappe Books

Invoicing Finance

5,003

Offline desktop accounting with double-entry, POS, and custom invoice templates

View details
88
Repo Health
77
Technical
72
Dependency
Built with
TypeScript 58%
Vue 39%
Updated 3 weeks ago
TypeScript
77%
Other

Joplin

Note Taking

56,853

The privacy-first, open-source note-taking app with end-to-end encrypted sync, AI assistance, and a powerful plugin ecosystem across every platform.

View details
93
Repo Health
87
Technical
60
Dependency
Built with
TypeScript 77%
JavaScript 14%
Updated 6 days ago
TypeScript
98%
AGPL 3.0

Karakeep

Bookmarks Archiving

29,926

Self-hosted bookmark manager that captures links, notes, images, and PDFs with AI tagging, full-text search, and automatic archiving.

View details
88
Repo Health
76
Technical
66
Dependency
Built with
TypeScript 98%
Updated 1 weeks ago
TypeScript
99%
MIT

KeystoneJS

CMS · Developer Tools

9,980

The superpowered headless CMS for developers built with GraphQL and React

View details
92
Repo Health
81
Technical
64
Dependency
Built with
TypeScript 99%
Updated 6 days ago
TypeScript
98%
Other

Kibana

Analytics · Monitoring

21,338

Your open source window into the Elastic Stack — query, visualize, and act on data stored in Elasticsearch with real-time dashboards, AI-assisted search, and automated alerting.

View details
98
Repo Health
87
Technical
63
Dependency
Built with
TypeScript 98%
Updated 5 days ago
TypeScript
97%
Other

Lightdash

Analytics · Data Engineering

6,196

The open-source Looker alternative that turns your dbt project's metrics and dimensions into governed, self-serve charts and dashboards — no license key required.

View details
93
Repo Health
84
Technical
64
Dependency
Built with
TypeScript 97%
Updated 5 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers