obix-core-process
v0.5.0
Published
Tool resolution and shell-free asynchronous spawn with AbortSignal, timeout, drained bounded output and owned-child cleanup.
Downloads
177
Maintainers
Readme
obix-core-process
Previous name:
@obinexusltd/obix-core-process— OBIX packages are named without an npm scope since decision D-102 (2026-09-29); the package, its version and its exports are unchanged.
Child-process execution for the OBIX CLI: tool resolution, bounded output
capture, timeouts, cancellation and (best-effort) tree termination. The
portable root takes an injected SpawnImpl; the /node subpath supplies
one over node:child_process.
The problem it owns
Running an external tool safely means: resolve it correctly (a JS bin runs under
the current runtime, not a global node; an executable is found via PATH
PATHEXTon Windows), never go through a shell, drain stdout and stderr concurrently (sequential draining deadlocks on a full pipe), bound the capture tomaxBuffer, honour anAbortSignaland atimeoutMs, and classify failures (tool-not-foundvsnonzero-exitvstimeoutvsaborted).
API
import {
createProcessRunner, resolveTool, canSpawn,
type ProcessRunnerAPI, type SpawnRequest, type SpawnResult, type ToolResolution,
} from "obix-core-process";
import {
createNodeProcessRunner, which, resolveJsBin,
} from "obix-core-process/node";| Export | Description |
|--------|-------------|
| createProcessRunner(spawnImpl) | spawnTool(req) · spawnShellScript(req & { shellArgsArray }) (.cmd/.bat/.ps1 only) · terminateChild · disposeAll · activeCount. |
| SpawnRequest | { command, args?, cwd?, env?, signal?, timeoutMs?, killSignal?, maxBuffer? (8 MiB), tree? }. |
| SpawnResult | { code, signal, timedOut, aborted, durationMs, stdout, stderr, stdoutTruncated, stderrTruncated }. |
| resolveTool({ kind: "js-bin", package, bin? } \| { kind: "executable", name }, hooks?) | JS bin → { command: <this runtime>, args: [absPath], runtime }; executable → which() result. |
| canSpawn() | Whether spawning is available on this host. |
| createNodeProcessRunner({ resolveFrom? }) | /node — runner + .resolve(), shell:false, windowsHide:true, killTree via taskkill /T /F on Win32. |
Example (JavaScript)
import { createNodeProcessRunner } from "obix-core-process/node";
const runner = createNodeProcessRunner();
const res = await runner.spawnTool({
command: process.execPath,
args: ["--version"],
timeoutMs: 10_000,
});
console.log(res.code, new TextDecoder().decode(res.stdout).trim());Example (TypeScript) — resolve then run a JS bin
import { createNodeProcessRunner } from "obix-core-process/node";
import type { SpawnResult } from "obix-core-process";
const runner = createNodeProcessRunner({ resolveFrom: process.cwd() });
const tool = runner.resolve({ kind: "js-bin", package: "typescript", bin: "tsc" });
if (!tool.found) throw new Error(tool.detail);
const out: SpawnResult = await runner.spawnTool({
command: tool.command, // = the current runtime
args: [...tool.args, "--noEmit"],
cwd: process.cwd(),
signal: AbortSignal.timeout(60_000),
});Host support (verified 2026-09-07)
| Runtime | spawnTool | tree kill | JS-bin runtime |
|---------|-------------|-----------|----------------|
| Node 26.7.0 / Win x64 | ✅ | ✅ taskkill /T /F | process.execPath (node) |
| Deno 2.9.6 / Win x64 | ✅ | direct child only | process.execPath (deno) |
| Bun 1.4.2 / Win x64 | ✅ | direct child only | process.execPath (bun) |
| browser / web worker | spawn capability unavailable → not applicable | — | — |
Linux/macOS and Node 22/24 LTS: authored, not-tested. POSIX process-group kill
(kill(-pid)) is authored for the tree path but unverified here.
Fallbacks
- No
treesupport / non-Win32 without a process-group kill → only the direct child is terminated;SpawnResult/the runner document this rather than pretending descendants were reaped. maxBufferexceeded → the stream is truncated andstdoutTruncated/stderrTruncatedis set; the process is still awaited.
Errors
CompatError: process/tool-not-found (spawn ENOENT), process/nonzero-exit,
process/timeout, process/aborted. A missing tool is classified from the async
spawn error, not guessed up front.
Boundary
No shell interpolation (scripts go through spawnShellScript with an explicit
args array). It does not manage long-running daemons or PTYs.
MIT — OBINexus Computing
Installation
npm install obix-core-processAPI surface
obix-core-process— 4 value exports:CompatError,canSpawn,createProcessRunner,resolveToolobix-core-process/node— 4 value exports:createNodeProcessRunner,resolveJsBin,resolveTool,which- Type declarations:
./dist/index.d.ts(and a declaration next to every JS entry point).
Architecture role
obix-core-process is a lower-level core package: an implementation building block of OBIX; applications normally reach OBIX through the umbrella obix, and install this package directly only for what it alone provides.
The architecture of OBIX — the package families and which packages are public API — is indexed in the umbrella: docs/architecture.md.
Package relationships
- Depends on (OBIX):
obix-core-capabilities. - Used by (OBIX): no other OBIX package.
Testing
- 1 test file ships in the npm package (
test/): the evidence of the package's contract, published so that its verification can be inspected — not runtime code (no entry point reaches it). - Standalone: 1 of 1 — it reads nothing outside the package.
- Run them with
npm test(node --test "test/*.test.mjs") in the OBIX monorepo, which provides the test tooling (Node's test runner, TypeScript) and the harness.
Documentation
- docs/spawn-model.md
- CHANGELOG.md
- The OBIX architecture index: obix/docs/architecture.md
Repository
- https://github.com/obinexus/obix-core-process —
[email protected]:obinexus/obix-core-process.git - Issues: https://github.com/obinexus/obix-core-process/issues
- The repository is a clean export of the package from the OBIX monorepo. Its lineage — the sources it was recovered from and its earlier names — is
PROVENANCE.json, shipped in this package; the repository's copy also records the monorepo commit it was exported from.
License
MIT — see LICENSE.
