Skip to main content

Overview

The SSHClient class provides efficient command execution on guest VMs using persistent SSH connections. It uses paramiko to maintain a single TCP connection that is reused for all commands, eliminating the ~170ms overhead of forking a new ssh process per call. The connection is established lazily on first use and automatically reconnects if the connection is lost.

Constructor

host
str
required
Guest IP address or hostname.
user
str
default:"root"
SSH username for authentication.
port
int
default:"22"
SSH port on the guest.
key_path
str | None
default:"None"
Optional path to an SSH private key file.
password
str | None
default:"None"
Optional password for authentication.
connect_timeout
int
default:"10"
Seconds to wait for the TCP connection.
shell_kind
Literal["sh", "powershell", "cmd"]
default:"sh"
Login-shell flavor used to wrap commands when run(..., shell="login") is called:
  • "sh" (default) — POSIX guests. Wraps with $SHELL -lc <quoted>.
  • "powershell" — Windows guests. Wraps with powershell.exe -NoProfile -EncodedCommand <base64> so the command bytes survive Windows OpenSSH’s cmd.exe layer unchanged.
  • "cmd" — Windows guests where you want cmd.exe /c "<command>" semantics instead. You are responsible for cmd.exe quoting.
shell="raw" on run(...) bypasses the wrap entirely regardless of shell_kind.

Properties

connected

Check if the SSH connection is currently alive.
returns
bool
True if the connection is active, False otherwise.

Methods

run

Execute a command on the guest VM using the persistent SSH connection. If the connection is not yet established or has been lost, it is (re)created transparently.
command
str
required
Shell command to execute.
timeout
int
default:"30"
Maximum seconds to wait for the command to complete.
shell
Literal['login', 'raw']
default:"login"
Command execution mode:
  • "login" (default): Run via guest login shell with environment variables loaded
  • "raw": Execute command directly with no shell wrapping
returns
CommandResult
Result object with:
  • exit_code (int): Exit code of the command (0 = success)
  • stdout (str): Standard output captured from the command
  • stderr (str): Standard error captured from the command
  • ok (bool): Whether the command succeeded (exit_code == 0)
  • output (str): Convenience alias for stripped stdout
raises
  • ValueError: If command is empty
  • OperationTimeoutError: If the command exceeds timeout
  • SmolVMError: If the SSH connection cannot be established

wait_for_ssh

Wait for the SSH daemon to become reachable on the guest. Uses a two-phase approach for fast detection:
  1. TCP probe - Lightweight socket.connect() calls (~1ms each) to detect when sshd is listening
  2. Paramiko connect - Full SSH handshake + auth. The resulting connection is kept open for subsequent run() calls
timeout
float
default:"60.0"
Maximum seconds to wait for SSH to become available.
interval
float
default:"0.1"
Seconds between TCP probe attempts.
raises
OperationTimeoutError
If SSH does not become available within timeout seconds.

close

Close the SSH connection and release resources. It’s recommended to use the client as a context manager instead of calling this manually.

Usage Patterns

Basic Command Execution

Error Handling

Using with SmolVM

Persistent Connection Benefits

Shell Modes

Performance

The persistent SSH connection provides significant performance benefits:
  • First command: ~100-200ms (establishes connection)
  • Subsequent commands: ~10-50ms (reuses connection)
  • Without persistence: ~170ms per command (fork + handshake overhead)
For workloads that execute many commands, this can reduce total execution time by 80-90%.
  • CommandResult - Result object returned by run()
  • SmolVM - High-level VM facade that uses SSHClient internally
Last modified on May 26, 2026