CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-zx

A tool for writing better scripts by bridging JavaScript and shell commands with cross-platform wrappers around child_process

Overview
Eval results
Files

process-management.mddocs/

Process Management

Advanced process control including promises, output handling, piping, and process lifecycle management through ProcessPromise and ProcessOutput classes.

Capabilities

ProcessPromise Class

Extended Promise for handling shell command execution with additional process control methods.

/**
 * Promise-like class for shell command execution with process control
 */
class ProcessPromise extends Promise<ProcessOutput> {
  /** Start the process execution */
  run(): this;
  
  /** Kill the process with optional signal */
  kill(signal?: NodeJS.Signals | null): Promise<void>;
  
  /** Abort the process execution */
  abort(reason?: string): void;
  
  /** Configure whether to throw on non-zero exit codes */
  nothrow(v?: boolean): this;
  
  /** Configure output verbosity */
  quiet(v?: boolean): this;
  
  /** Configure verbose output */
  verbose(v?: boolean): this;
  
  /** Set execution timeout */
  timeout(d?: Duration, signal?: NodeJS.Signals | undefined): this;
  
  /** @deprecated Use $({halt: true})`cmd` instead */
  halt(): this;
  
  /** Configure standard input/output */
  stdio(stdin: IOType | StdioOptions, stdout?: IOType, stderr?: IOType): this;
}

Process Information Properties:

class ProcessPromise extends Promise<ProcessOutput> {
  /** Unique process identifier */
  get id(): string;
  
  /** Process ID (available after execution starts) */
  get pid(): number | undefined;
  
  /** Command string without arguments */
  get cmd(): string;
  
  /** Full command string with arguments */
  get fullCmd(): string;
  
  /** Child process instance */
  get child(): ChildProcess | undefined;
  
  /** Process execution stage */
  get stage(): ProcessStage;
  
  /** Whether execution is synchronous */
  get sync(): boolean;
  
  /** Abort signal */
  get signal(): AbortSignal;
  
  /** Abort controller */
  get ac(): AbortController;
  
  /** Process output (available after completion) */
  get output(): ProcessOutput | null;
}

type ProcessStage = 'initial' | 'halted' | 'running' | 'fulfilled' | 'rejected';

Stream Access:

class ProcessPromise extends Promise<ProcessOutput> {
  /** Standard input stream */
  get stdin(): Writable;
  
  /** Standard output stream */
  get stdout(): Readable;
  
  /** Standard error stream */
  get stderr(): Readable;
  
  /** Promise that resolves with exit code */
  get exitCode(): Promise<number | null>;
}

Output Processing Methods:

class ProcessPromise extends Promise<ProcessOutput> {
  /** Parse output as JSON */
  json<T = any>(): Promise<T>;
  
  /** Get output as text string */
  text(encoding?: Encoding): Promise<string>;
  
  /** Split output into lines */
  lines(delimiter?: Options['delimiter']): Promise<string[]>;
  
  /** Get output as Buffer */
  buffer(): Promise<Buffer>;
  
  /** Get output as Blob */
  blob(type?: string): Promise<Blob>;
}

State Check Methods:

class ProcessPromise extends Promise<ProcessOutput> {
  /** Check if process output is suppressed */
  isQuiet(): boolean;
  
  /** Check if verbose output is enabled */
  isVerbose(): boolean;
  
  /** Check if process won't throw on errors */
  isNothrow(): boolean;
  
  /** Check if process is halted */
  isHalted(): boolean;
}

Usage Examples:

import { $ } from "zx";

// Basic process control
const proc = $`sleep 10`;
console.log(proc.id); // Process identifier
console.log(proc.pid); // Process PID (after started)

// Timeout and error handling
const result = await $`some-command`
  .timeout('30s')
  .nothrow()
  .quiet();

// Stream access
const longProc = $`tail -f /var/log/system.log`;
longProc.stdout.on('data', (chunk) => {
  console.log('Log:', chunk.toString());
});

// Kill process
await longProc.kill('SIGTERM');

ProcessOutput Class

Result object containing command output, exit information, and processing methods.

/**
 * Command execution result with output data and metadata
 */
class ProcessOutput extends Error {
  /** Exit code (null if killed by signal) */
  readonly exitCode: number | null;
  
  /** Signal that killed the process (null if exited normally) */
  readonly signal: NodeJS.Signals | null;
  
  /** Standard output content */
  readonly stdout: string;
  
  /** Standard error content */
  readonly stderr: string;
  
  /** Combined stdout and stderr */
  readonly stdall: string;
  
  /** Execution duration in milliseconds */
  readonly duration: number;
  
  /** Whether command succeeded (exit code 0) */
  readonly ok: boolean;
  
  /** Error message */
  readonly message: string;
  
  /** Cause error (if any) */
  readonly cause: Error | null;
}

Output Processing Methods:

class ProcessOutput extends Error {
  /** Parse stdout as JSON */
  json<T = any>(): T;
  
  /** Get stdout as text with optional encoding */
  text(encoding?: Encoding): string;
  
  /** Split stdout into lines */
  lines(delimiter?: string | RegExp): string[];
  
  /** Get stdout as Buffer */
  buffer(): Buffer;
  
  /** Get stdout as Blob */
  blob(type?: string): Blob;
  
  /** String representation (returns stdout) */
  toString(): string;
  
  /** Primitive value (returns stdout) */
  valueOf(): string;
  
  /** Iterator over lines */
  [Symbol.iterator](dlmtr?: Options['delimiter']): Iterator<string>;
}

Static Methods:

class ProcessOutput extends Error {
  /** Format exit error message */
  static getExitMessage: typeof Fail.formatExitMessage;
  
  /** Format general error message */
  static getErrorMessage: typeof Fail.formatErrorMessage;
  
  /** Format error details */
  static getErrorDetails: typeof Fail.formatErrorDetails;
  
  /** Get exit code information */
  static getExitCodeInfo: typeof Fail.getExitCodeInfo;
  
  /** Create ProcessOutput from generic Error */
  static fromError(error: Error): ProcessOutput;
}

Usage Examples:

import { $ } from "zx";

// Basic output handling
const result = await $`ls -la`;
console.log(result.stdout); // File listing
console.log(result.exitCode); // 0 for success
console.log(result.ok); // true for success

// Error handling
try {
  await $`false`; // Command that always fails
} catch (error) {
  if (error instanceof ProcessOutput) {
    console.log('Exit code:', error.exitCode);
    console.log('stderr:', error.stderr);
    console.log('Duration:', error.duration, 'ms');
  }
}

// JSON parsing
const packageInfo = await $`cat package.json`;
const pkg = packageInfo.json();
console.log(pkg.name);

// Line processing
const logLines = await $`tail -n 10 /var/log/system.log`;
for (const line of logLines.lines()) {
  console.log('Log line:', line);
}

Process Piping

Connect processes together using Unix-style piping.

interface ProcessPromise extends Promise<ProcessOutput> {
  /** Pipe output to another command or stream */
  get pipe(): PipeMethod & {
    [key in keyof TSpawnStore]: PipeMethod;
  };
  
  /** Remove piping connection */
  unpipe(to?: PipeAcceptor): this;
}

type PipeMethod = {
  /** Pipe to shell command */
  (dest: TemplateStringsArray, ...args: any[]): ProcessPromise;
  /** Pipe to file */
  (file: string): PromisifiedStream;
  /** Pipe to writable stream */
  <D extends Writable>(dest: D): PromisifiedStream<D>;
  /** Pipe to another ProcessPromise */
  <D extends ProcessPromise>(dest: D): D;
};

type PipeAcceptor = Writable | ProcessPromise;

type PromisifiedStream<D extends Writable = Writable> = 
  D & PromiseLike<ProcessOutput & D> & {
    run(): void;
  };

Usage Examples:

import { $ } from "zx";
import fs from "fs";

// Pipe to another command
const result = await $`cat /etc/passwd`
  .pipe`grep root`
  .pipe`wc -l`;

// Pipe to file
await $`echo "Hello World"`
  .pipe('./output.txt');

// Pipe to stream
const writeStream = fs.createWriteStream('./data.txt');
await $`ls -la`.pipe(writeStream);

// Complex piping
await $`find /var/log -name "*.log"`
  .pipe`head -10`
  .pipe`sort`
  .pipe('./sorted-logs.txt');

Async Iteration

Process output as an async iterator for streaming data processing.

interface ProcessPromise extends Promise<ProcessOutput> {
  /** Async iterator over output lines */
  [Symbol.asyncIterator](): AsyncIterator<string>;
}

Usage:

import { $ } from "zx";

// Stream processing
const proc = $`tail -f /var/log/system.log`;

for await (const line of proc) {
  console.log('New log line:', line);
  
  if (line.includes('ERROR')) {
    proc.kill();
    break;
  }
}

Types

type Duration = string | number;

type IOType = 'pipe' | 'ignore' | 'inherit';

type StdioOptions = IOType | Array<IOType | Stream | number | null | undefined>;

type Encoding = BufferEncoding;

interface TSpawnStore {
  [key: string]: any;
}

Install with Tessl CLI

npx tessl i tessl/npm-zx

docs

cli.md

file-system.md

index.md

network-operations.md

process-management.md

shell-execution.md

user-interaction.md

utilities.md

tile.json