---
url: >-
  https://adk.nht.io/api/batteries/isolation/child_process/interfaces/IsolatedChildLike.md
description: >-
  The minimal Node `ChildProcess`-shaped duck this transport drives.
  Structurally satisfied by BOTH:
---

# Interface: IsolatedChildLike

Defined in: [src/batteries/isolation/child\_process/transport.ts:102](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L102)

The minimal Node `ChildProcess`-shaped duck this transport drives. Structurally satisfied by BOTH:

* the object returned by `node:child_process`'s own `fork()`, and
* an `execa`≥9 subprocess spawned with `{ ipc: true }` — empirically verified: execa's
  `Subprocess<OptionsType>` type is `Omit<ChildProcess, keyof ExecaCustomSubprocess<OptionsType>> &
  ExecaCustomSubprocess<OptionsType>`, i.e. it keeps the classic Node `ChildProcess` EventEmitter
  surface (`.send()`, `.on('message'|'exit'|'error', ...)`, `.kill()`, `.connected`) alongside
  execa's own promise-based `sendMessage()`/`getEachMessage()` API. This transport only ever uses the
  classic EventEmitter surface, so an execa `{ ipc: true }` subprocess satisfies this duck WITHOUT
  any adapter.

execa's channel, like node's own `fork()`, defaults to JSON-style serialization unless the
subprocess is spawned with `serialization: 'advanced'` (execa forwards that option straight to the
underlying `child_process.fork()` it uses internally for `ipc: true`) — the same "pin `advanced` for
exotic-value fidelity" requirement documented on [ForkIsolatedOptions](../type-aliases/ForkIsolatedOptions.md) applies whether the
child came from this module's own `fork()` call or from a caller-supplied [ChildResolver](../type-aliases/ChildResolver.md).

## Remarks

A [ChildResolver](../type-aliases/ChildResolver.md) must NOT itself attach a `'message'` listener to the child it returns before
handing it back to this transport (e.g. for logging). Node buffers a child's `message`/`ipc` events
until the FIRST listener is attached, then flushes the whole buffer to that one listener exactly
once — a resolver-side listener attached first (even just to log) permanently steals the buffered
`ready` envelope from `connect()`'s own listener, which then waits out `readyTimeoutMs` for a `ready`
that already came and went. execa's `Subprocess` additionally proxies raw child events through its
own internal debounced `message` re-emitter (see execa's `lib/ipc/forward.js`), so this applies to
execa subprocesses too — empirically confirmed by instrumenting a resolver with a diagnostic
`subprocess.on('message', ...)` and observing the resulting connection hang.

A [ChildResolver](../type-aliases/ChildResolver.md) that returns an execa `{ ipc: true }` subprocess should attach its own
no-op `.catch(() => {})` to it before returning. execa's subprocess is ITSELF a promise (via
`mergePromise`) that settles REJECTED on a non-zero exit or termination signal — including the
ordinary `SIGTERM` this transport's `terminate()` sends on every `dispose()`/`recycle()`. Since this
transport only ever drives the classic EventEmitter surface (never awaits/`.then()`s the child
itself — see this module's `spawnChild` remarks for why an unguarded `await`/`return` of a thenable
child is unsafe in the first place), nothing else ever attaches a rejection handler; without one, a
routine `terminate()` reports as an unhandled promise rejection.

## Properties

| Property                                     | Type      | Description                                                                                                                             | Defined in                                                                                                                                                            |
| -------------------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|  `connected?` | `boolean` | Whether the IPC channel is currently open. Read once at connect time for a `send`-before-`connect` sanity check; not polled thereafter. | [src/batteries/isolation/child\_process/transport.ts:120](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L120) |

## Methods

### kill()

```ts
kill(signal?: number | Signals): boolean | void;
```

Defined in: [src/batteries/isolation/child\_process/transport.ts:117](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L117)

Send a termination signal to the child.

#### Parameters

| Parameter | Type                  |
| --------- | --------------------- |
| `signal?` | `number` | `Signals` |

#### Returns

`boolean` | `void`

***

### off()?

```ts
optional off(event: string, fn: (...args: any[]) => void): unknown;
```

Defined in: [src/batteries/isolation/child\_process/transport.ts:113](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L113)

Unsubscribe, mirroring `.on`. Optional — some resolvers may return a duck without it; this
transport degrades to leaking the listener rather than throwing (the process is short-lived and
torn down on `terminate()`/`recycle()` regardless).

#### Parameters

| Parameter | Type                           |
| --------- | ------------------------------ |
| `event`   | `string`                       |
| `fn`      | (...`args`: `any`\[]) => `void` |

#### Returns

`unknown`

***

### on()

```ts
on(event: string, fn: (...args: any[]) => void): unknown;
```

Defined in: [src/batteries/isolation/child\_process/transport.ts:109](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L109)

Subscribe to a child lifecycle/IPC event (`'message'`, `'exit'`, `'error'`). Listener param typed
`any[]` to structurally match node's own `ChildProcess#on` overload set (whose listener signatures
are themselves `(...args: any[]) => void`).

#### Parameters

| Parameter | Type                           |
| --------- | ------------------------------ |
| `event`   | `string`                       |
| `fn`      | (...`args`: `any`\[]) => `void` |

#### Returns

`unknown`

***

### removeListener()?

```ts
optional removeListener(event: string, fn: (...args: any[]) => void): unknown;
```

Defined in: [src/batteries/isolation/child\_process/transport.ts:115](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L115)

Alias some ducks expose instead of/alongside `off`.

#### Parameters

| Parameter | Type                           |
| --------- | ------------------------------ |
| `event`   | `string`                       |
| `fn`      | (...`args`: `any`\[]) => `void` |

#### Returns

`unknown`

***

### send()?

```ts
optional send(msg: unknown): boolean | void;
```

Defined in: [src/batteries/isolation/child\_process/transport.ts:105](https://github.com/NHTIO/ADK/blob/v1.20260713.1/src/src/batteries/isolation/child_process/transport.ts#L105)

Send a message across the IPC channel. Returns `false` (or void, depending on the implementation)
when the channel is closed/backed-up; this transport does not currently act on that return value.

#### Parameters

| Parameter | Type      |
| --------- | --------- |
| `msg`     | `unknown` |

#### Returns

`boolean` | `void`
