Process execution for humans
Execa runs commands in your script, application or library. Unlike shells, it is optimized for programmatic usage. Built on top of the child_process
core module.
One of the maintainers @ehmicky is looking for a remote full-time position. Specialized in Node.js back-ends and CLIs, he led Netlify Build, Plugins and Configuration for 2.5 years. Feel free to contact him on his website or on LinkedIn!
zx
.npx
.PATHEXT
, and more.stdout
and stderr
similar to what is printed on the terminal.Uint8Array
s, iterables or objects.npm install execa
Execution:
Input/output:
Advanced usage:
import {execa} from 'execa'; const {stdout} = await execa`npm run build`; // Print command's output console.log(stdout);
import {$} from 'execa'; const {stdout: name} = await $`cat package.json`.pipe`grep name`; console.log(name); const branch = await $`git branch --show-current`; await $`dep deploy --branch=${branch}`; await Promise.all([ $`sleep 1`, $`sleep 2`, $`sleep 3`, ]); const directoryName = 'foo bar'; await $`mkdir /tmp/${directoryName}`;
$ npm install -D eslint
await execa({preferLocal: true})`eslint`;
const {stdout, pipedFrom} = await execa`npm run build` .pipe`sort` .pipe`head -n 2`; // Output of `npm run build | sort | head -n 2` console.log(stdout); // Output of `npm run build | sort` console.log(pipedFrom[0].stdout); // Output of `npm run build` console.log(pipedFrom[0].pipedFrom[0].stdout);
const {all} = await execa({all: true})`npm run build`; // stdout + stderr, interleaved console.log(all);
const {stdout} = await execa({stdout: ['pipe', 'inherit']})`npm run build`; // stdout is also printed to the terminal console.log(stdout);
// Similar to: npm run build > output.txt await execa({stdout: {file: './output.txt'}})`npm run build`;
const {stdout} = await execa({input: getInputString()})`sort`; console.log(stdout);
const {stdout} = await execa({lines: true})`npm run build`; // Print first 10 lines console.log(stdout.slice(0, 10).join('\n'));
for await (const line of execa`npm run build`) { if (line.includes('WARN')) { console.warn(line); } }
let count = 0; // Filter out secret lines, then prepend the line number const transform = function * (line) { if (!line.includes('secret')) { yield `[${count++}] ${line}`; } }; await execa({stdout: transform})`npm run build`;
const response = await fetch('https://example.com'); await execa({stdin: response.body})`sort`;
import {execa} from 'execa'; import {pipeline} from 'node:stream/promises'; import {createReadStream, createWriteStream} from 'node:fs'; await pipeline( createReadStream('./input.txt'), execa`node ./transform.js`.duplex(), createWriteStream('./output.txt'), );
import {execa, ExecaError} from 'execa'; try { await execa`unknown command`; } catch (error) { if (error instanceof ExecaError) { console.log(error); } /* ExecaError: Command failed with ENOENT: unknown command spawn unknown ENOENT at ... at ... { shortMessage: 'Command failed with ENOENT: unknown command\nspawn unknown ENOENT', originalMessage: 'spawn unknown ENOENT', command: 'unknown command', escapedCommand: 'unknown command', cwd: '/path/to/cwd', durationMs: 28.217566, failed: true, timedOut: false, isCanceled: false, isTerminated: false, isMaxBuffer: false, code: 'ENOENT', stdout: '', stderr: '', stdio: [undefined, '', ''], pipedFrom: [] [cause]: Error: spawn unknown ENOENT at ... at ... { errno: -2, code: 'ENOENT', syscall: 'spawn unknown', path: 'unknown', spawnargs: [ 'command' ] } } */ }
await execa`npm run build`; await execa`npm run test`;