The simplest way to pass input to a subprocess is to use command arguments.
import {execa} from 'execa';
const commandArgument = 'build';
await execa`node child.js ${commandArgument}`;
If the subprocess is a Node.js file, those are available using process.argv
.
// child.js
import process from 'node:process';
const commandArgument = process.argv[2];
Unlike command arguments, environment variables have names. They are commonly used to configure applications.
If the subprocess spawns its own subprocesses, they inherit environment variables. To isolate subprocesses from each other, either command arguments or stdin
should be preferred instead.
// Keep the current process' environment variables, and set `NO_COLOR`
await execa({env: {NO_COLOR: 'true'}})`node child.js`;
// Discard the current process' environment variables, only pass `NO_COLOR`
await execa({env: {NO_COLOR: 'true'}, extendEnv: false})`node child.js`;
If the subprocess is a Node.js file, environment variables are available using process.env
.
// child.js
import process from 'node:process';
console.log(process.env.NO_COLOR);
Alternatively, input can be provided to stdin
. Unlike command arguments and environment variables which have size limits, stdin
works when the input is big. Also, the input can be redirected from the terminal, a file, another subprocess or a stream. Finally, this is required when the input might contain null bytes, for example when it might be binary.
If the input is already available as a string, it can be passed directly to the input
option.
await execa({input: 'stdinInput'})`npm run scaffold`;
The stdin
option can also be used, although the string must be wrapped in two arrays for syntax reasons.
await execa({stdin: [['stdinInput']]})`npm run scaffold`;
const subprocess = execa({stdin: 'ignore'})`npm run scaffold`;
console.log(subprocess.stdin); // undefined
await subprocess;
await execa({inputFile: 'input.txt'})`npm run scaffold`;
// Or:
await execa({stdin: {file: 'input.txt'}})`npm run scaffold`;
// Or:
await execa({stdin: new URL('file:///path/to/input.txt')})`npm run scaffold`;
The parent process' input can be re-used in the subprocess by passing 'inherit'
. This is especially useful to receive interactive input in command line applications.
await execa({stdin: 'inherit'})`npm run scaffold`;
If the subprocess uses Node.js, almost any type can be passed to the subprocess using the ipcInput
option. The subprocess retrieves that input using getOneMessage()
.
// main.js
import {execaNode} from 'execa';
const ipcInput = [
{task: 'lint', ignore: /test\.js/},
{task: 'copy', files: new Set(['main.js', 'index.js']),
}];
await execaNode({ipcInput})`build.js`;
// build.js
import {getOneMessage} from 'execa';
const ipcInput = await getOneMessage();
The stdio
option can be used to pass some input to any file descriptor, as opposed to only stdin
.
// Pass input to the file descriptor number 3
await execa({
stdio: ['pipe', 'pipe', 'pipe', new Uint8Array([/* ... */])],
})`npm run build`;
Next: 📢 Output
Previous: 🏁 Termination
Top: Table of contents