Repository: sindresorhus/execa (JavaScript)

Issue:
`ipc` option
When using Node.js IPC feature (which is pretty nice), I sometimes find having to add `'ipc'` at the end of the `stdio` array slightly cumbersome. It is also potentially error-prone, since one needs to remember for it to be the 4th item (or later), and not to repeat it (as some users might be tempted to). Also, it forces users to use the `stdio` option instead of the simpler `stdin`/`stdout`/`stderr` options Execa provides.

Moreover, while `ipc` does use a file descriptor, it does so in a different way than other `stdio` values.
  - The wire format is undocumented, so that file descriptor is not really something users directly use. It is more of an implementation detail.
  - Only one file descriptor can use it.
  - With Execa, it cannot be combined with other values for a given file descriptor. 

I am wondering whether Node.js should have exposed this feature using an `{ ipc: true }` option instead? Should we add that option, which would automatically add `ipc` to the underlying `stdio` option? We would then undocument passing `ipc` to the `stdio` option, but still support it for compatibility.

What are your thoughts about this?


Discussion: > I am wondering whether Node.js should have exposed this feature using an { ipc: true } option instead? Should we add that option, which would automatically add ipc to the underlying stdio option? We would then undocument passing ipc to the stdio option, but still support it for compatibility.

Yes, I agree that Node.js should have done that, and that we should do it.



Fix (patch):
diff --git a/index.d.ts b/index.d.ts
index fef129c2df..65865c9032 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -309,7 +309,6 @@ type CommonOptions<IsSync extends boolean = boolean> = {
 	- `'pipe'`: Sets [`childProcess.stdin`](https://nodejs.org/api/child_process.html#subprocessstdin) stream.
 	- `'overlapped'`: Like `'pipe'` but asynchronous on Windows.
 	- `'ignore'`: Do not use `stdin`.
-	- `'ipc'`: Sets an [IPC channel](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). You can also use `execaNode()` instead.
 	- `'inherit'`: Re-use the current process' `stdin`.
 	- an integer: Re-use a specific file descriptor from the current process.
 	- a Node.js `Readable` stream.
@@ -332,7 +331,6 @@ type CommonOptions<IsSync extends boolean = boolean> = {
 	- `'pipe'`: Sets `childProcessResult.stdout` (as a string or `Uint8Array`) and [`childProcess.stdout`](https://nodejs.org/api/child_process.html#subprocessstdout) (as a stream).
 	- `'overlapped'`: Like `'pipe'` but asynchronous on Windows.
 	- `'ignore'`: Do not use `stdout`.
-	- `'ipc'`: Sets an [IPC channel](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). You can also use `execaNode()` instead.
 	- `'inherit'`: Re-use the current process' `stdout`.
 	- an integer: Re-use a specific file descriptor from the current process.
 	- a Node.js `Writable` stream.
@@ -353,7 +351,6 @@ type CommonOptions<IsSync extends boolean = boolean> = {
 	- `'pipe'`: Sets `childProcessResult.stderr` (as a string or `Uint8Array`) and [`childProcess.stderr`](https://nodejs.org/api/child_process.html#subprocessstderr) (as a stream).
 	- `'overlapped'`: Like `'pipe'` but asynchronous on Windows.
 	- `'ignore'`: Do not use `stderr`.
-	- `'ipc'`: Sets an [IPC channel](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). You can also use `execaNode()` instead.
 	- `'inherit'`: Re-use the current process' `stderr`.
 	- an integer: Re-use a specific file descriptor from the current process.
 	- a Node.js `Writable` stream.
@@ -374,7 +371,7 @@ type CommonOptions<IsSync extends boolean = boolean> = {
 
 	A single string can be used as a shortcut. For example, `{stdio: 'pipe'}` is the same as `{stdin: 'pipe', stdout: 'pipe', stderr: 'pipe'}`.
 
-	The array can have more than 3 items, to create additional file descriptors beyond `stdin`/`stdout`/`stderr`. For example, `{stdio: ['pipe', 'pipe', 'pipe', 'ipc']}` sets a fourth file descriptor `'ipc'`.
+	The array can have more than 3 items, to create additional file descriptors beyond `stdin`/`stdout`/`stderr`. For example, `{stdio: ['pipe', 'pipe', 'pipe', 'pipe']}` sets a fourth file descriptor.
 
 	@default 'pipe'
 	*/
@@ -558,7 +555,12 @@ type CommonOptions<IsSync extends boolean = boolean> = {
 	readonly all?: IfAsync<IsSync, boolean>;
 
 	/**
-	Specify the kind of serialization used for sending messages between processes when using the `stdio: 'ipc'` option or `execaNode()`:
+	Enables exchanging messages with the child process using [`childProcess.send(value)`](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback) and [`childProcess.on('message', (value) => {})`](https://nodejs.org/api/child_process.html#event-message).
+	*/
+	readonly ipc?: IfAsync<IsSync, boolean>;
+
+	/**
+	Specify the kind of serialization used for sending messages between processes when using the `ipc` option:
 	- `json`: Uses `JSON.stringify()` and `JSON.parse()`.
 	- `advanced`: Uses [`v8.serialize()`](https://nodejs.org/api/v8.html#v8_v8_serialize_value)
 
@@ -657,21 +659,21 @@ type ExecaCommonReturnValue<IsSync extends boolean = boolean, OptionsType extend
 	/**
 	The output of the process on `stdout`.
 
-	This is `undefined` if the `stdout` option is set to only [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the `lines` option is `true, or if the `stdout` option is a transform in object mode.
+	This is `undefined` if the `stdout` option is set to only [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the `lines` option is `true, or if the `stdout` option is a transform in object mode.
 	*/
 	stdout: StdioOutput<'1', OptionsType>;
 
 	/**
 	The output of the process on `stderr`.
 
-	This is `undefined` if the `stderr` option is set to only [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the `lines` option is `true, or if the `stderr` option is a transform in object mode.
+	This is `undefined` if the `stderr` option is set to only [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the `lines` option is `true, or if the `stderr` option is a transform in object mode.
 	*/
 	stderr: StdioOutput<'2', OptionsType>;
 
 	/**
 	The output of the process on `stdin`, `stdout`, `stderr` and other file descriptors.
 
-	Items are `undefined` when their corresponding `stdio` option is set to only [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). Items are arrays when their corresponding `stdio` option is a transform in object mode.
+	Items are `undefined` when their corresponding `stdio` option is set to only [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). Items are arrays when their corresponding `stdio` option is a transform in object mode.
 	*/
 	stdio: StdioArrayOutput<OptionsType>;
 
@@ -723,7 +725,7 @@ type ExecaCommonReturnValue<IsSync extends boolean = boolean, OptionsType extend
 
 	This is `undefined` if either:
 	- the `all` option is `false` (default value)
-	- both `stdout` and `stderr` options are set to [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
+	- both `stdout` and `stderr` options are set to [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
 
 	This is an array if the `lines` option is `true, or if either the `stdout` or `stderr` option is a transform in object mode.
 	*/
@@ -801,7 +803,7 @@ export type ExecaChildPromise<OptionsType extends Options = Options> = {
 
 	This is `undefined` if either:
 	- the `all` option is `false` (the default value)
-	- both `stdout` and `stderr` options are set to [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
+	- both `stdout` and `stderr` options are set to [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
 	*/
 	all: AllStream<OptionsType>;
 
@@ -938,7 +940,7 @@ export function execa<OptionsType extends Options = {}>(
 /**
 Same as `execa()` but synchronous.
 
-Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
+Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `ipc`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
 
 Returns or throws a `childProcessResult`. The `childProcess` is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), `.pipe()` and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -1039,7 +1041,7 @@ export function execaCommand<OptionsType extends Options = {}>(
 /**
 Same as `execaCommand()` but synchronous.
 
-Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
+Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `ipc`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
 
 Returns or throws a `childProcessResult`. The `childProcess` is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), `.pipe()` and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -1098,7 +1100,7 @@ type Execa$<OptionsType extends CommonOptions = {}> = {
 	/**
 	Same as $\`command\` but synchronous.
 
-	Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
+	Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `ipc`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
 
 	Returns or throws a `childProcessResult`. The `childProcess` is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), `.pipe()` and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -1152,7 +1154,7 @@ type Execa$<OptionsType extends CommonOptions = {}> = {
 	/**
 	Same as $\`command\` but synchronous.
 
-	Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
+	Cannot use the following options: `all`, `cleanup`, `buffer`, `detached`, `ipc`, `serialization`, `signal` and `lines`. Also, the `stdin`, `stdout`, `stderr`, `stdio` and `input` options cannot be an array, an iterable or a web stream. Node.js streams must have a file descriptor unless the `input` option is used.
 
 	Returns or throws a `childProcessResult`. The `childProcess` is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), `.pipe()` and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -1269,7 +1271,7 @@ This is the preferred method when executing Node.js files.
 Like [`child_process#fork()`](https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options):
 - the current Node version and options are used. This can be overridden using the `nodePath` and `nodeOptions` options.
 - the `shell` option cannot be used
-- an extra channel [`ipc`](https://nodejs.org/api/child_process.html#child_process_options_stdio) is passed to `stdio`
+- the `ipc` option defaults to `true`
 
 @param scriptPath - Node.js script to execute, as a string or file URL
 @param arguments - Arguments to pass to `scriptPath` on execution.
diff --git a/index.js b/index.js
index 09a5540e76..688f852091 100644
--- a/index.js
+++ b/index.js
@@ -10,7 +10,6 @@ import {npmRunPathEnv} from 'npm-run-path';
 import {makeError} from './lib/error.js';
 import {handleInputAsync, pipeOutputAsync, cleanupStdioStreams} from './lib/stdio/async.js';
 import {handleInputSync, pipeOutputSync} from './lib/stdio/sync.js';
-import {normalizeStdioNode} from './lib/stdio/normalize.js';
 import {spawnedKill, validateTimeout, normalizeForceKillAfterDelay, cleanupOnExit} from './lib/kill.js';
 import {pipeToProcess} from './lib/pipe.js';
 import {getSpawnedResult, makeAllStream} from './lib/stream.js';
@@ -86,6 +85,7 @@ const addDefaultOptions = ({
 	killSignal = 'SIGTERM',
 	forceKillAfterDelay = true,
 	lines = false,
+	ipc = false,
 	...options
 }) => ({
 	...options,
@@ -106,6 +106,7 @@ const addDefaultOptions = ({
 	killSignal,
 	forceKillAfterDelay,
 	lines,
+	ipc,
 });
 
 // Prevent passing the `timeout` option directly to `child_process.spawn()`
@@ -223,6 +224,7 @@ const handlePromise = async ({spawned, options, stdioStreamsGroups, originalStre
 
 export function execaSync(rawFile, rawArgs, rawOptions) {
 	const {file, args, command, escapedCommand, options} = handleArguments(rawFile, rawArgs, rawOptions);
+	validateSyncOptions(options);
 
 	const stdioStreamsGroups = handleInputSync(options);
 
@@ -286,6 +288,12 @@ export function execaSync(rawFile, rawArgs, rawOptions) {
 	};
 }
 
+const validateSyncOptions = ({ipc}) => {
+	if (ipc) {
+		throw new TypeError('The "ipc: true" option cannot be used with synchronous methods.');
+	}
+};
+
 const normalizeScriptStdin = ({input, inputFile, stdio}) => input === undefined && inputFile === undefined && stdio === undefined
 	? {stdin: 'inherit'}
 	: {};
@@ -332,15 +340,13 @@ export function execaCommandSync(command, options) {
 	return execaSync(file, args, options);
 }
 
-export function execaNode(scriptPath, args, options = {}) {
-	if (args && !Array.isArray(args) && typeof args === 'object') {
+export function execaNode(scriptPath, args = [], options = {}) {
+	if (!Array.isArray(args)) {
 		options = args;
 		args = [];
 	}
 
-	const stdio = normalizeStdioNode(options);
 	const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect'));
-
 	const {
 		nodePath = process.execPath,
 		nodeOptions = defaultExecArgv,
@@ -348,18 +354,7 @@ export function execaNode(scriptPath, args, options = {}) {
 
 	return execa(
 		nodePath,
-		[
-			...nodeOptions,
-			getFilePath(scriptPath),
-			...(Array.isArray(args) ? args : []),
-		],
-		{
-			...options,
-			stdin: undefined,
-			stdout: undefined,
-			stderr: undefined,
-			stdio,
-			shell: false,
-		},
+		[...nodeOptions, getFilePath(scriptPath), ...args],
+		{ipc: true, ...options, shell: false},
 	);
 }
diff --git a/lib/stdio/normalize.js b/lib/stdio/normalize.js
index 128596d4f1..041b538a6b 100644
--- a/lib/stdio/normalize.js
+++ b/lib/stdio/normalize.js
@@ -1,13 +1,14 @@
 import {STANDARD_STREAMS_ALIASES} from './utils.js';
 
 // Add support for `stdin`/`stdout`/`stderr` as an alias for `stdio`
-export const normalizeStdio = options => {
-	if (!options) {
-		return [undefined, undefined, undefined];
-	}
-
-	const {stdio} = options;
+export const normalizeStdio = ({stdio, ipc, ...options}) => {
+	const stdioArray = getStdioArray(stdio, options);
+	return ipc && !stdioArray.includes('ipc')
+		? [...stdioArray, 'ipc']
+		: stdioArray;
+};
 
+const getStdioArray = (stdio, options) => {
 	if (stdio === undefined) {
 		return STANDARD_STREAMS_ALIASES.map(alias => options[alias]);
 	}
@@ -29,9 +30,3 @@ export const normalizeStdio = options => {
 };
 
 const hasAlias = options => STANDARD_STREAMS_ALIASES.some(alias => options[alias] !== undefined);
-
-// Same but for `execaNode()`, i.e. push `ipc` unless already present
-export const normalizeStdioNode = options => {
-	const stdio = normalizeStdio(options);
-	return stdio.includes('ipc') ? stdio : [...stdio, 'ipc'];
-};
diff --git a/readme.md b/readme.md
index a1970a286d..ce74249e78 100644
--- a/readme.md
+++ b/readme.md
@@ -244,7 +244,7 @@ This is the preferred method when executing Node.js files.
 Like [`child_process#fork()`](https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options):
 - the current Node version and options are used. This can be overridden using the [`nodePath`](#nodepath-for-node-only) and [`nodeOptions`](#nodeoptions-for-node-only) options.
 - the [`shell`](#shell) option cannot be used
-- an extra channel [`ipc`](https://nodejs.org/api/child_process.html#child_process_options_stdio) is passed to [`stdio`](#stdio-1)
+- the [`ipc`](#ipc) option defaults to `true`
 
 #### $\`command\`
 
@@ -278,7 +278,7 @@ This is the preferred method when executing a user-supplied `command` string, su
 
 Same as [`execa()`](#execacommandcommand-options) but synchronous.
 
-Cannot use the following options: [`all`](#all-2), [`cleanup`](#cleanup), [`buffer`](#buffer), [`detached`](#detached), [`serialization`](#serialization), [`signal`](#signal) and [`lines`](#lines). Also, the [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1), [`stdio`](#stdio-1) and [`input`](#input) options cannot be an array, an iterable or a web stream. Node.js streams [must have a file descriptor](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr) unless the `input` option is used.
+Cannot use the following options: [`all`](#all-2), [`cleanup`](#cleanup), [`buffer`](#buffer), [`detached`](#detached), [`ipc`](#ipc), [`serialization`](#serialization), [`signal`](#signal) and [`lines`](#lines). Also, the [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1), [`stdio`](#stdio-1) and [`input`](#input) options cannot be an array, an iterable or a web stream. Node.js streams [must have a file descriptor](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr) unless the `input` option is used.
 
 Returns or throws a [`childProcessResult`](#childProcessResult). The [`childProcess`](#childprocess) is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), [`.pipe()`](#pipeexecachildprocess-streamname) and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -287,7 +287,7 @@ Returns or throws a [`childProcessResult`](#childProcessResult). The [`childProc
 
 Same as [$\`command\`](#command) but synchronous.
 
-Cannot use the following options: [`all`](#all-2), [`cleanup`](#cleanup), [`buffer`](#buffer), [`detached`](#detached), [`serialization`](#serialization), [`signal`](#signal) and [`lines`](#lines). Also, the [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1), [`stdio`](#stdio-1) and [`input`](#input) options cannot be an array, an iterable or a web stream. Node.js streams [must have a file descriptor](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr) unless the `input` option is used.
+Cannot use the following options: [`all`](#all-2), [`cleanup`](#cleanup), [`buffer`](#buffer), [`detached`](#detached), [`ipc`](#ipc), [`serialization`](#serialization), [`signal`](#signal) and [`lines`](#lines). Also, the [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1), [`stdio`](#stdio-1) and [`input`](#input) options cannot be an array, an iterable or a web stream. Node.js streams [must have a file descriptor](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr) unless the `input` option is used.
 
 Returns or throws a [`childProcessResult`](#childProcessResult). The [`childProcess`](#childprocess) is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), [`.pipe()`](#pipeexecachildprocess-streamname) and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -295,7 +295,7 @@ Returns or throws a [`childProcessResult`](#childProcessResult). The [`childProc
 
 Same as [`execaCommand()`](#execacommand-command-options) but synchronous.
 
-Cannot use the following options: [`all`](#all-2), [`cleanup`](#cleanup), [`buffer`](#buffer), [`detached`](#detached), [`serialization`](#serialization), [`signal`](#signal) and [`lines`](#lines). Also, the [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1), [`stdio`](#stdio-1) and [`input`](#input) options cannot be an array, an iterable or a web stream. Node.js streams [must have a file descriptor](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr) unless the `input` option is used.
+Cannot use the following options: [`all`](#all-2), [`cleanup`](#cleanup), [`buffer`](#buffer), [`detached`](#detached), [`ipc`](#ipc), [`serialization`](#serialization), [`signal`](#signal) and [`lines`](#lines). Also, the [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1), [`stdio`](#stdio-1) and [`input`](#input) options cannot be an array, an iterable or a web stream. Node.js streams [must have a file descriptor](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr) unless the `input` option is used.
 
 Returns or throws a [`childProcessResult`](#childProcessResult). The [`childProcess`](#childprocess) is not returned: its methods and properties are not available. This includes [`.kill()`](https://nodejs.org/api/child_process.html#subprocesskillsignal), [`.pid`](https://nodejs.org/api/child_process.html#subprocesspid), [`.pipe()`](#pipeexecachildprocess-streamname) and the [`.stdin`/`.stdout`/`.stderr`](https://nodejs.org/api/child_process.html#subprocessstdout) streams.
 
@@ -317,7 +317,7 @@ Stream [combining/interleaving](#ensuring-all-output-is-interleaved) [`stdout`](
 
 This is `undefined` if either:
 - the [`all` option](#all-2) is `false` (the default value)
-- both [`stdout`](#stdout-1) and [`stderr`](#stderr-1) options are set to [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
+- both [`stdout`](#stdout-1) and [`stderr`](#stderr-1) options are set to [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
 
 #### pipe(execaChildProcess, streamName?)
 
@@ -376,7 +376,7 @@ Type: `string | Uint8Array | string[] | Uint8Array[] | unknown[] | undefined`
 
 The output of the process on `stdout`.
 
-This is `undefined` if the [`stdout`](#stdout-1) option is set to only [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the [`lines` option](#lines) is `true, or if the `stdout` option is a [transform in object mode](docs/transform.md#object-mode).
+This is `undefined` if the [`stdout`](#stdout-1) option is set to only [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the [`lines` option](#lines) is `true, or if the `stdout` option is a [transform in object mode](docs/transform.md#object-mode).
 
 #### stderr
 
@@ -384,7 +384,7 @@ Type: `string | Uint8Array | string[] | Uint8Array[] | unknown[] | undefined`
 
 The output of the process on `stderr`.
 
-This is `undefined` if the [`stderr`](#stderr-1) option is set to only [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the [`lines` option](#lines) is `true, or if the `stderr` option is a [transform in object mode](docs/transform.md#object-mode).
+This is `undefined` if the [`stderr`](#stderr-1) option is set to only [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). This is an array if the [`lines` option](#lines) is `true, or if the `stderr` option is a [transform in object mode](docs/transform.md#object-mode).
 
 #### all
 
@@ -394,7 +394,7 @@ The output of the process with `stdout` and `stderr` [interleaved](#ensuring-all
 
 This is `undefined` if either:
 - the [`all` option](#all-2) is `false` (the default value)
-- both [`stdout`](#stdout-1) and [`stderr`](#stderr-1) options are set to only [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
+- both [`stdout`](#stdout-1) and [`stderr`](#stderr-1) options are set to only [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio)
 
 This is an array if the [`lines` option](#lines) is `true, or if either the `stdout` or `stderr` option is a [transform in object mode](docs/transform.md#object-mode).
 
@@ -404,7 +404,7 @@ Type: `Array<string | Uint8Array | string[] | Uint8Array[] | unknown[] | undefin
 
 The output of the process on [`stdin`](#stdin), [`stdout`](#stdout-1), [`stderr`](#stderr-1) and [other file descriptors](#stdio-1).
 
-Items are `undefined` when their corresponding [`stdio`](#stdio-1) option is set to [`'inherit'`, `'ipc'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). Items are arrays when their corresponding `stdio` option is a [transform in object mode](docs/transform.md#object-mode).
+Items are `undefined` when their corresponding [`stdio`](#stdio-1) option is set to [`'inherit'`, `'ignore'`, `Stream` or `integer`](https://nodejs.org/api/child_process.html#child_process_options_stdio). Items are arrays when their corresponding `stdio` option is a [transform in object mode](docs/transform.md#object-mode).
 
 #### failed
 
@@ -555,7 +555,6 @@ Default: `inherit` with [`$`](#command), `pipe` otherwise
 - `'pipe'`: Sets [`childProcess.stdin`](https://nodejs.org/api/child_process.html#subprocessstdin) stream.
 - `'overlapped'`: Like `'pipe'` but asynchronous on Windows.
 - `'ignore'`: Do not use `stdin`.
-- `'ipc'`: Sets an [IPC channel](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). You can also use [`execaNode()`](#execanodescriptpath-arguments-options) instead.
 - `'inherit'`: Re-use the current process' `stdin`.
 - an integer: Re-use a specific file descriptor from the current process.
 - a [Node.js `Readable` stream](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr).
@@ -578,7 +577,6 @@ Default: `pipe`
 - `'pipe'`: Sets [`childProcessResult.stdout`](#stdout) (as a string or `Uint8Array`) and [`childProcess.stdout`](https://nodejs.org/api/child_process.html#subprocessstdout) (as a stream).
 - `'overlapped'`: Like `'pipe'` but asynchronous on Windows.
 - `'ignore'`: Do not use `stdout`.
-- `'ipc'`: Sets an [IPC channel](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). You can also use [`execaNode()`](#execanodescriptpath-arguments-options) instead.
 - `'inherit'`: Re-use the current process' `stdout`.
 - an integer: Re-use a specific file descriptor from the current process.
 - a [Node.js `Writable` stream](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr).
@@ -599,7 +597,6 @@ Default: `pipe`
 - `'pipe'`: Sets [`childProcessResult.stderr`](#stderr) (as a string or `Uint8Array`) and [`childProcess.stderr`](https://nodejs.org/api/child_process.html#subprocessstderr) (as a stream).
 - `'overlapped'`: Like `'pipe'` but asynchronous on Windows.
 - `'ignore'`: Do not use `stderr`.
-- `'ipc'`: Sets an [IPC channel](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback). You can also use [`execaNode()`](#execanodescriptpath-arguments-options) instead.
 - `'inherit'`: Re-use the current process' `stderr`.
 - an integer: Re-use a specific file descriptor from the current process.
 - a [Node.js `Writable` stream](#redirect-a-nodejs-stream-fromto-stdinstdoutstderr).
@@ -620,7 +617,7 @@ Like the [`stdin`](#stdin), [`stdout`](#stdout-1) and [`stderr`](#stderr-1) opti
 
 A single string can be used as a shortcut. For example, `{stdio: 'pipe'}` is the same as `{stdin: 'pipe', stdout: 'pipe', stderr: 'pipe'}`.
 
-The array can have more than 3 items, to create additional file descriptors beyond `stdin`/`stdout`/`stderr`. For example, `{stdio: ['pipe', 'pipe', 'pipe', 'ipc']}` sets a fourth file descriptor `'ipc'`.
+The array can have more than 3 items, to create additional file descriptors beyond `stdin`/`stdout`/`stderr`. For example, `{stdio: ['pipe', 'pipe', 'pipe', 'pipe']}` sets a fourth file descriptor.
 
 #### all
 
@@ -639,6 +636,13 @@ Split `stdout` and `stderr` into lines.
 - [`childProcess.stdout`](https://nodejs.org/api/child_process.html#subprocessstdout), [`childProcess.stderr`](https://nodejs.org/api/child_process.html#subprocessstderr), [`childProcess.all`](#all) and [`childProcess.stdio`](https://nodejs.org/api/child_process.html#subprocessstdio) iterate over lines instead of arbitrary chunks.
 - Any stream passed to the [`stdout`](#stdout-1), [`stderr`](#stderr-1) or [`stdio`](#stdio-1) option receives lines instead of arbitrary chunks.
 
+#### ipc
+
+Type: `boolean`\
+Default: `true` with [`execaNode()`](#execanodescriptpath-arguments-options), `false` otherwise
+
+Enables exchanging messages with the child process using [`childProcess.send(value)`](https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback) and [`childProcess.on('message', (value) => {})`](https://nodejs.org/api/child_process.html#event-message).
+
 #### reject
 
 Type: `boolean`\
@@ -692,7 +696,7 @@ Explicitly set the value of `argv[0]` sent to the child process. This will be se
 Type: `string`\
 Default: `'json'`
 
-Specify the kind of serialization used for sending messages between processes when using the [`stdio: 'ipc'`](#stdio-1) option or [`execaNode()`](#execanodescriptpath-arguments-options):
+Specify the kind of serialization used for sending messages between processes when using the [`ipc`](#ipc) option:
 	- `json`: Uses `JSON.stringify()` and `JSON.parse()`.
 	- `advanced`: Uses [`v8.serialize()`](https://nodejs.org/api/v8.html#v8_v8_serialize_value)