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

TypeScript
90%
MIT

OpenClaw

AI Agents · AI Assistants

392,894

An open-source AI assistant that runs on your own hardware and meets you in Discord, Slack, WhatsApp, iMessage, Telegram, and 20+ other channels, with native apps for every major platform.

View details
88
Repo Health
88
Technical
66
Dependency
Built with
TypeScript 90%
Updated 5 days ago
Go
36%

OpenPanel

Devops · Hosting Control Panel

764

Docker-powered web hosting control panel that gives every user a fully isolated environment with dedicated web server, database, and networking — VPS-grade security on shared hardware.

View details
87
Repo Health
75
Technical
63
Dependency
Built with
Go 36%
HTML 30%
TypeScript 24%
Updated 6 days ago
Rust
99%
GPL 3.0

Pake

Developer Tools

62,284

Turn any webpage into a lightweight native desktop app with one command — built on Rust/Tauri instead of Electron, producing installers nearly 20x smaller (typically under 10MB) for macOS, Windows, and Linux.

View details
94
Repo Health
75
Technical
72
Dependency
Built with
Rust 99%
Updated 5 days ago
TypeScript
96%
MIT

Payload CMS

Blogging · CMS · Developer Tools

45,458

The open-source, Next.js-native headless CMS that lives inside your /app folder and gives you a full TypeScript backend instantly.

View details
92
Repo Health
88
Technical
65
Dependency
Built with
TypeScript 96%
Updated 5 days ago
TypeScript
91%
AGPL 3.0

PeerTube

Social Media

15,362

A federated, ActivityPub-based video hosting platform built by Framasoft — self-hostable instances interconnect into a network with no vendor lock-in, P2P-assisted streaming, and no ads.

View details
96
Repo Health
75
Technical
66
Dependency
Built with
TypeScript 91%
Updated 1 weeks ago
TypeScript
90%
MIT

Plasmic

CMS · Design Tools · Low Code Platforms

7,125

The open-source visual builder that lets teams design React apps and websites with drag-and-drop while integrating seamlessly with your codebase.

View details
81
Repo Health
78
Technical
64
Dependency
Built with
TypeScript 90%
Updated 6 days ago
TypeScript
98%
MIT

Promptfoo

AI Development

26,358

An open-source CLI and library for evaluating and red-teaming LLM applications — replace trial-and-error prompt engineering with systematic evals, vulnerability scanning, and CI/CD integration.

View details
90
Repo Health
73
Technical
67
Dependency
Built with
TypeScript 98%
Updated 5 days ago
Rust
72%
Apache 2.0

Rivet

AI Agents · Developer Tools

6,326

Stateful actors as a primitive for AI agents, real-time collaboration, and durable execution — with in-memory state, WebSockets, queues, and scheduling built in.

View details
87
Repo Health
81
Technical
64
Dependency
Built with
Rust 72%
TypeScript 25%
Updated 5 days ago
Ruby
62%
BSD 3

Spree Commerce

CRM · Ecommerce · Marketing

15,774

Open-source headless eCommerce platform with a REST API, TypeScript SDK, and Next.js storefront for B2B, cross-border, and marketplace commerce — no vendor lock-in, no platform fees.

View details
91
Repo Health
84
Technical
75
Dependency
Built with
Ruby 62%
TypeScript 37%
Updated 6 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