ezssh 0.2.1
A lightweight, ergonomic SSH library.
License: Apache-2.0
Requires Python: >=3.9
Keywords: ssh, automation, remote-execution, batch, paramiko, infrastructure, devops, control-plane

# EZSSH

#### An Ergonomic and Lightweight SSH Library.

## Installation

``` bash
pip install ezssh
```

## Quick Start
Username and password authentication to a remote server.
``` python
from ezssh import SSHRunner, Command, BatchPolicy

# As of v0.0.9, SSHRunner will auto-add on new host. Disable for added security.
with SSHRunner(
    host="10.0.0.5",
    username="ubuntu",
    password="secret", # password as null will attempt pubkey using current user keystore in ~/.ssh
    missing_host_key_policy='autoadd'
) as runner:

    result = runner.run("uname -a")
    print(result.stdout)

    batch = runner.run_batch(
        [
            "whoami",
            Command("systemctl is-active ssh", sudo=True, name="ssh_status"),
        ],
        policy=BatchPolicy(stop_on_failure=False),
    )

    for r in batch.results:
        print(r.command.name, r.exit_status)

```

## SSH Key filename/Directory Support
EzSSH Supports key-based authentication. Specify a key file or directory of keys to use, like so:

``` python
from ezssh.client import SSHRunner

if __name__ == "__main__":
    # define a key file
    with SSHRunner('x.x.x.x', 'username', pkey_file='./keys/id_rsa') as client:
        # classify_keyfile(key_file='./keys/id_rsa')
        print(client.run('uname -a').stdout)
```

As of Version 0.1.2, EzSSH now supports key directories. This will authenticate against a server using all keys in the specified directory.

``` python
from ezssh.client import SSHRunner

if __name__ == "__main__":
    # define a directory of key files 
    with SSHRunner('x.x.x.x', 'username', keys_dir='./some/directory') as client:
        print(client.run('uname -a').stdout)

```


## Batch Operations
batch processing of cli commands is also available. To execute a chain of prepared commands:

``` python
batch = runner.run_batch(
    [
        Command("mkdir -p /tmp/example"),
        Command("touch /tmp/example/file.txt"),
        Command("false", name="intentional_failure"),
        Command("echo still runs"),
    ],
    policy=BatchPolicy(stop_on_failure=False),
)
# Each returns an exit status, stdout/stderror, start/end and duration.
```

## Authentication Behavior
Password auth uses password only, agent and key discovery are opt-in.
```python
SSHRunner(
    host="example.com",
    username="user",
    password="secret",
    allow_agent=False,
    look_for_keys=False,
)
```



## When to Use ezssh

Use ezssh if you need:
- Programmatic SSH execution embedded in a Python application
- Deterministic batch execution with structured results
- Explicit authentication behavior
- Lightweight automation without orchestration frameworks

Do not use ezssh if you need:
- Configuration management
- Long-lived agents
- Inventory management
- Declarative state convergence

## How ezssh Compares

| Tool     | ezssh | Paramiko | Fabric | Ansible |
|----------|-------|----------|--------|---------|
| Embedded in apps | ✅ | ⚠️ | ⚠️ | ❌ |
| Best Effort Auth | ✅ | ⚠️ | ❌ | ❌ |
| Batch semantics | ✅ | ❌ | ⚠️ | ✅ |
| Explicit auth | ✅ | ❌ | ❌ | ⚠️ |
| Minimal deps | ✅ | ✅ | ❌ | ❌ |
| YAML required | ❌ | ❌ | ❌ | ✅ |