Skip to content

Repository files navigation

eliware.org

@eliware/ssh-client npm versionlicensebuild status

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.


Table of Contents

Features

  • 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

Requirements

  • Node.js 26 or newer
  • An SSH server and private-key or password authentication

Installation

npm install @eliware/ssh-client

Usage

ESM Example

import { 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);
}

API

sshExec(options)

Executes one or more commands on a remote SSH server using private-key or password authentication.

Parameters

  • 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 credentials
  • password (string): Password credential for bootstrap or password-authenticated servers
  • knownHosts / knownHostsPath (string): OpenSSH known-host records
  • hostCaPath (string): Trusted OpenSSH host CA public key

Returns

  • Promise<Array<{ result: string, code: number }>>: Resolves to an array of results for each command, with merged stdout/stderr and exit code.

Throws

  • If connection or authentication fails, or if required credentials are unavailable.

Errors / Troubleshooting

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.

connect(options)

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.

Development

npm test
npm run lint
npm run typecheck
npm run pack

Security

Treat 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.

TypeScript

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>;

Support

For help, questions, or to chat with the author and community, visit:

Discordeliware.org

eliware.org on Discord

License

MIT © 2025 Eli Sterling, eliware.org

Links

About

A simple, ESM-first SSH client for Node.js with private key authentication and sequential command execution.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages