@mcesystems/command-client
v1.0.85
Published
Multi-platform command client for WSL, PowerShell, and Bash with persistent shell, auto-restart, and typed events
Maintainers
Readme
command-client
Multi-platform command client for WSL, PowerShell, and Bash
Run shell commands with a unified API, persistent shell with auto-restart, and typed events for stdout/stderr. Use BashClient on any platform; WSLClient and PowershellClient on Windows only.
Description
- BashClient: Runs commands in Bash. Works on Linux, macOS, and Windows (e.g. Git Bash).
- WSLClient: Runs commands in a WSL distribution. Windows only; throws in
start()if not on Windows. - PowershellClient: Runs commands in PowerShell. Windows only; throws in
start()if not on Windows.
All clients share the same interface: start(env) returns a Shell; the Shell exposes command(cmd), copy(src, dest), delete(path), and ls(path). Each returns a CommandHandle (typed EventEmitter) so you can listen to stdout, stderr, done, and error. With reuseShell: true (default), one persistent process is kept and auto-restarted until stop().
Install
# From workspace root
pnpm install
# Build the package
pnpm --filter @mcesystems/command-client buildExamples
See src/examples/persistent-shell-with-recovery.ts: runs commands, kills the shell process, then runs another command to show recovery. Run with:
pnpm exec tsx src/examples/persistent-shell-with-recovery.tsAPI
Clients
BashClient(options?)
options.reuseShell?: boolean— defaulttrue.options.shellPath?: string— default/bin/bashon Unix,"bash"on Windows.
WSLClient(distributionName, options?)
distributionName: WSL distro (e.g."Ubuntu").options.reuseShell?: boolean— defaulttrue.- Throws in
start()ifprocess.platform !== "win32".
PowershellClient(options?)
options.reuseShell?: boolean— defaulttrue.- Throws in
start()if not Windows.
Session
client.start(environmentVariables?): Shell
Returns a Shell. In reuse mode spawns the persistent process; env is applied to that process.client.stop(): void
Stops the session; in reuse mode kills the process and stops auto-restart.
Shell (typed EventEmitter)
shell.command(cmd: string): CommandHandle
Runs one raw command. Returns a CommandHandle (EventEmitter).shell.copy(src, dest): CommandHandle
Convenience: copy file or directory (shell-native command).shell.delete(path): CommandHandle
Convenience: delete file or directory.shell.ls(path): CommandHandle
Convenience: list directory; output on stdout.shell.getPid(): number | undefined
PID of the persistent process (reuse mode only).shell.on("stdout" | "stderr", listener)
Session-level: receive all stdout/stderr from any command.
CommandHandle (typed EventEmitter)
- handle.on("stdout", (chunk: string) => void)
- handle.on("stderr", (chunk: string) => void)
- handle.on("done", (result: CommandResult) => void) —
result:{ stdout, stderr, code }. - handle.on("error", (err: Error) => void)
Types
- CommandResult:
{ stdout: string; stderr: string; code: number } - ClientOptions:
{ reuseShell?: boolean } - BashClientOptions:
{ reuseShell?: boolean; shellPath?: string }
Flow
import { WSLClient } from "@mcesystems/command-client";
const wsl = new WSLClient("Ubuntu", { reuseShell: true });
const shell = wsl.start({ FOO: "bar" });
// Session-level: log any command output
shell.on("stdout", ({ chunk }) => process.stdout.write(chunk));
const handle = shell.command("ls -ltr /var/lib/");
handle.on("done", (result) => console.log("Exit code:", result.code));
shell.command("usbmuxd --port 27015");
wsl.stop();Setup
- BashClient: On Windows, ensure Bash is on PATH (e.g. Git Bash) or set
shellPath. On Linux/macOS,/bin/bashis used by default. - WSLClient: WSL2 and the chosen distribution must be installed. Use the distribution name (e.g.
"Ubuntu") in the constructor. - PowershellClient: PowerShell is expected on PATH (e.g.
powershell.exeon Windows).
TODO
- Optional: configurable sentinel and timeouts.
- Optional: expose adapter implementations for custom shells.
