import { EventEmitter } from 'node:events'; import type { Writable } from 'node:stream'; export interface ShellRunner { /** Run a command, return stdout (trimmed). Throws on non-zero exit. */ exec(command: string, args: string[], options?: ExecOptions): Promise; /** Run a command and return { stdout, code }. Does not throw on non-zero. */ execQuiet(command: string, args: string[], options?: ExecOptions): Promise; /** Spawn a command with inherited stdio, forward signals, return exit code. * signalSource defaults to `process`; inject a fake for testing. */ spawnInherit(command: string, args: string[], options?: ExecOptions, signalSource?: EventEmitter): Promise; } export interface ExecOptions { cwd?: string; env?: Record; stdin?: string; /** If true, suppress stderr output (pipe to /dev/null). */ silentStderr?: boolean; /** Route child stderr to a caller-owned stream instead of process.stderr. */ stderr?: Writable; /** If set, stream stdout chunks to this stream (e.g. process.stderr) with * the given prefix, while also capturing into the returned stdout string. * Used for devcontainer up so the user sees build progress live. */ streamStdoutTo?: { stream: Writable; prefix: string; }; } export interface ExecResult { stdout: string; code: number; } /** Real ShellRunner using child_process. */ export declare class RealShellRunner implements ShellRunner { exec(command: string, args: string[], options?: ExecOptions): Promise; execQuiet(command: string, args: string[], options?: ExecOptions): Promise; /** * Spawn a child process with inherited stdio. Forwards SIGINT/SIGTERM from * the parent to the child. Resolves with the child's exit code. * * This replaces bash's `exec` — Node has no exec(2), so we spawn and wait, * making the child the effective foreground process. * * signalSource defaults to `process`; tests inject a fake EventEmitter so * they can emit signals without killing the vitest process. */ spawnInherit(command: string, args: string[], options?: ExecOptions, signalSource?: EventEmitter): Promise; } /** Singleton real runner. */ export declare const shell: ShellRunner; /** * Safely single-quote-escape a string for use inside a shell single-quoted * context. Replaces each `'` with `'{\}'` (close quote, escaped quote, * reopen quote), then wraps the whole thing in single quotes. * * Equivalent to bash's `printf '%q'` for the single-quote-in-single-quotes * case. Used for writing GH_TOKEN into /etc/profile.d/gh-token.sh. */ export declare function escapeShellSingleQuote(value: string): string; /** * Check if a command is available through a supplied shell runner. * Providers use this seam so prerequisite failures remain testable without * spawning host commands. */ export declare function commandExistsWithRunner(runner: ShellRunner, cmd: string): Promise; /** Check if a command is available on the host. */ export declare function commandExists(cmd: string): Promise;