ssherd
Run commands on many servers at once — one Python file, zero dependencies, powered by your OpenSSH client.
ssherd is a small batch-SSH CLI for server fleets. Your ~/.ssh/config (or a project-local .ssh/config) is the inventory: ssherd reads the Host aliases, fans out commands in parallel, and lets the real ssh client handle everything it already does best — addresses, jump hosts (ProxyJump), users, keys, host keys.
Works on Linux, macOS, and Windows (Git-Bash / PowerShell).
Features
- Single file, zero dependencies — copy
ssherd.pyanywhere, needs only Python 3.9+ andssh - SSH config as inventory — selectors by name, comma list, or range (
web-01..web-16,all) - Parallel execution with a live per-device progress bar
- Smart grouped output — identical results collapse into one block, outliers shown as compact diffs (
--diff) - Jump hosts / keys / users — all resolved natively by OpenSSH, never re-implemented
- Password auth support via OpenSSH's official
SSH_ASKPASS_REQUIRE=force(no sshpass, never touches your tty) - Sudo fan-out —
sudo -Swrapping with one local password prompt add-user— generates plain, auditable bash commands by default (--execto run them)
Installation
pipx install ssherd # isolated venv + global command (recommended)
pip install ssherd # or plain pip — works on any OS
Requirements: Python 3.9+ and the OpenSSH client (ssh) you already have.
Prefer no installer at all? It's one self-contained file — grab it, read it, hack it:
curl -fsSL https://raw.githubusercontent.com/trdthg/ssherd/master/ssherd.py \
-o ~/.local/bin/ssherd && chmod +x ~/.local/bin/ssherd
Uninstall: pipx uninstall ssherd or pip uninstall ssherd.
Quick start
# the inventory is just your ssh config Host aliases
python -m ssherd list
# run in parallel across a range
python -m ssherd run web-01..web-16 -- whoami
# comma lists and single hosts work too
python -m ssherd run web-01,web-05,db-01 -- hostname
# sudo: prompts once, wraps remotely with sudo -S
python -m ssherd run --sudo db-01..db-32 -- apt update
# scriptable: pass passwords inline (note: lands in shell history)
python -m ssherd run --sudo=SUDOPASS db-01 -- systemctl restart nginx
# group identical outputs, show only the differences
python -m ssherd run all --diff -- 'cat /etc/os-release'
Inventory
Devices are the Host entries in your SSH config (Host * wildcards are skipped):
Host web-01
HostName 192.0.2.10
User deploy
# ProxyJump jumpbox ← jump hosts just work, ssh handles them
A .ssh/config in the current directory takes precedence over ~/.ssh/config,
so a fleet per project is one folder away. Put .ssh/ in .gitignore and real
IPs never get committed. Selectors accept aliases, comma lists, ranges
(web-01..web-16), and all / *.
Creating users
add-user prints the plain bash commands (useradd / usermod / chpasswd) for you
to audit and paste, or to wrap in your own loop. Add --exec to fan them out
through the same parallel channel:
python -m ssherd add-user web-01..web-16 deploy
python -m ssherd add-user web-01..web-16 deploy --sudo --password 'TempPass-123' --exec
Why not Ansible / pssh / fabric?
They are great; this is for the other 90% of ops work: one-off fleet commands
where you refuse to install anything, write a playbook, or learn a DSL.
ssherd delegates all connection semantics to OpenSSH, so anything your
ssh can reach, ssherd can reach — including bastion hosts.
Tests
python -m unittest discover -v
License
Metadata
Release files for ssherd 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ssherd-0.1.2.tar.gz | 12.7 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ssherd-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.6 kB
Release files / ssherd-0.1.2.tar.gz
| Download URL | ssherd-0.1.2.tar.gz |
|---|---|
| Size | 12.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0239580a5230fd0551fba8bd8faacbd800f2b9e08b5fb462cfd80bf9b7da237f
|
|
BLAKE2b-256 checksum How to use checksums |
283c539707261d7102797139aaf1ec0f44cb6bb0e1bee166139db2297d44e4e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / ssherd-0.1.2-py3-none-any.whl
| Download URL | ssherd-0.1.2-py3-none-any.whl |
|---|---|
| Size | 12.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e14b4af1740e16638b166580e850404affdbf5082ff60024cdd6ac7a971d230a
|
|
BLAKE2b-256 checksum How to use checksums |
0317b307e6f817b91ebdd7da8fcae20757d47b983683cddb72452220b6da8513
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logSecurity for ssherd 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ssherd-0.1.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.