A simple, ESM-first SSH client for Node.js with key or password authentication and sequential command execution.
The implementation is organized into focused modules under src/; the root entry point remains the public compatibility barrel.
CI validates ordinary main pushes and pull requests; npm publishing remains restricted to v* tags.
Host certificate verification parses and verifies OpenSSH certificate wire data directly with ssh2; no external executable is required. It validates the CA signature, signing key, host principal, certificate type, validity interval, and revoked/negated host records. File transfers use SFTP (through ssh2), not the separate SCP protocol.
- Simple SSH command execution for Node.js
- Private-key and password authentication
- Sequential execution of multiple commands in a single SSH session
- Returns merged stdout/stderr and exit code for each command
- TypeScript type definitions included
- Fully ESM compatible
- Easily testable/mocked via dependency injection
- Node.js 26 or newer
- An SSH server and private-key or password authentication
npm install @eliware/ssh-clientimport { sshExec } from '@eliware/ssh-client';
const results = await sshExec({
host: 'your.ssh.server',
username: 'youruser', // optional if same as local user
commands: [
'echo Hello, SSH!',
'uname -a',
],
});
for (const [i, { result, code }] of results.entries()) {
console.log(`Command #${i + 1} exit code: ${code}`);
console.log(result);
}Executes one or more commands on a remote SSH server using private-key or password authentication.
host(string): Hostname or IP address (required)port(number): SSH port (default: 22)username(string): SSH username (default: current user)commands(string[]): List of commands to execute (required)privateKey/privateKeyPath(string): Private-key credentialspassword(string): Password credential for bootstrap or password-authenticated serversknownHosts/knownHostsPath(string): OpenSSH known-host recordshostCaPath(string): Trusted OpenSSH host CA public key
Promise<Array<{ result: string, code: number }>>: Resolves to an array of results for each command, with merged stdout/stderr and exit code.
- If connection or authentication fails, or if required credentials are unavailable.
sshExec validates the host, command list, and port before connecting. It throws SshError with codes for invalid options, missing keys, authentication failures, connection failures, connection timeouts, command failures, and command timeouts. Configure host verification with hostVerifier or knownHosts; do not weaken verification defaults in production.
Creates a reusable connection exposing exec(commands), shell({ onData, onInput }), upload(localPath, remotePath), download(remotePath, localPath), and close(). Transfers use SFTP. Host certificates are verified against @cert-authority records or hostCaPath; certificate principals must include the requested host name or IP address.
npm test
npm run lint
npm run typecheck
npm run packTreat private keys, passphrases, agents, host credentials, and command content as sensitive. Never commit keys or credentials. Prefer knownHosts/hostVerifier, limit command scope, and avoid logging command output containing secrets.
Type definitions are included:
export interface SshExecOptions {
host: string;
port?: number;
username?: string;
commands: string[];
privateKey?: string;
privateKeyPath?: string;
password?: string;
knownHosts?: string;
knownHostsPath?: string;
hostCaPath?: string;
}
export interface SshExecResult {
result: string;
code: number;
}
export interface SshConnection {
exec(commands: string[]): Promise<SshExecResult[]>;
shell(options?: { onData?: (data: Buffer) => void; onInput?: (stream: any) => void }): Promise<any>;
upload(localPath: string, remotePath: string): Promise<void>;
download(remotePath: string, localPath: string): Promise<void>;
close(): Promise<void>;
}
export declare function sshExec(options: SshExecOptions): Promise<SshExecResult[]>;
export declare function connect(options: Omit<SshExecOptions, 'commands'>): Promise<SshConnection>;For help, questions, or to chat with the author and community, visit:


