Hussh: SSH for humans.

Hussh (pronounced "hush") is a client-side ssh library that offers low level performance through a high level interface.
Hussh uses pyo3 to create Python bindings around the ssh2 library for Rust.
Installation
pip install hussh
QuickStart
Hussh currently just offers a Connection
class as your primary interface.
from hussh import Connection
conn = Connection(host="my.test.server", username="user", password="pass")
result = conn.execute("ls")
print(result.stdout)
That's it! One import and class instantion is all you need to:
- Execute commands
- Perform SCP actions
- Perform SFTP actions
- Get an interactive shell
Why Hussh?
- 🔥 Blazingly fast!
- 🪶 Incredibly lightweight!
- 🧠 Super easy to use!
Benchmarks
Hussh demonstrates the performance you'd expect from a low level ssh library.
Hussh is also much lighter weight in both total memory and memory allocations.
Local Server

Remote Server

Try it for yourself!
Hussh's benchmark script are also open sourced in the benchmarks
directory in this repository.
Clone the repo, follow the setup instructions, then let us know how it did!
Authentication
You've already seen password-based authentication, but here it is again.
conn = Connection(host="my.test.server", username="user", password="pass")
conn = Connection(host="my.test.server", password="pass")
If you prefer key-based authentication, Hussh can do that as well.
conn = Connection(host="my.test.server", private_key="~/.ssh/id_rsa")
conn = Connection(host="my.test.server", private_key="~/.ssh/id_rsa", password="pass")
Hussh can also do agent-based authentication, if you've already established it.
conn = Connection("my.test.server")
Cleaning up after yourself
Hussh will clean up after itself automatically when the Connection
object is garbage collected.
However, if you want to more explicitly clean up after yourself, you can close
the connection.
conn.close()
or you can use the Connection
class' context manager, which will close
when you exit the context.
with Connection(host="my.test.server", password="pass") as conn:
result = conn.execute("ls")
assert result.status == 0
Executing commands
The most basic foundation of ssh libraries is the ability to execute commands against the remote host.
For Hussh, just use the Connection
object's execute
method.
result = conn.execute("whoami")
print(result.stdout, result.stderr, result.status)
Each execute returns an SSHResult
object with command's stdout, stderr, and status.
SFTP
If you need to transfer files to/from the remote host, SFTP may be your best bet.
Writing files and data
conn.sftp_write(local_path="/path/to/my/file", remote_path="/dest/path/file")
conn.sftp_write_data(data="Hello there!", remote_path="/dest/path/file")
Reading files
conn.sftp_read(remote_path="/dest/path/file", local_path="/path/to/my/file")
contents = conn.sftp_read(remote_path="/dest/path/file")
Copy files from one connection to another
Hussh offers a shortcut that allows you to copy a file between two established connections.
source_conn = Connection("my.first.server")
dest_conn = Connection("my.second.server", password="secret")
source_conn.remote_copy(source_path="/root/myfile.txt", dest_conn=dest_conn)
By default, if you don't pass in an alternate dest_path
, Hussh will copy it to the same path as it came from on source.
SCP
For remote servers that support SCP, Hussh can do that to.
Writing files and data
conn.scp_write(local_path="/path/to/my/file", remote_path="/dest/path/file")
conn.scp_write_data(data="Hello there!", remote_path="/dest/path/file")
Reading files
conn.scp_read(remote_path="/dest/path/file", local_path="/path/to/my/file")
contents = conn.scp_read(remote_path="/dest/path/file")
Tailing Files
Hussh offers a built-in method for tailing files on a Connection
with the tail
method.
with conn.tail("/path/to/file.txt") as tf:
print(tf.read())
print(tf.contents)
Interactive Shell
If you need to keep a shell open to perform more complex interactions, you can get an InteractiveShell
instance from the Connection
class instance.
To use the interactive shell, it is recommended to use the shell()
context manager from the Connection
class.
You can send commands to the shell using the send
method, then get the results from result
when you exit the context manager.
with conn.shell() as shell:
shell.send("ls")
shell.send("pwd")
shell.send("whoami")
print(shell.result.stdout)
Note: The read
method sends an EOF to the shell, so you won't be able to send more commands after calling read
. If you want to send more commands, you would need to create a new InteractiveShell
instance.
Disclaimer
This is a VERY early project that should not be used in production code!
There isn't even proper exception handling, so expect some Rust panics to fall through.
With that said, try it out and let me know your thoughts!
Future Features
- Proper exception handling
- Concurrent actions class
- Async Connection class
- Low level bindings
- Misc codebase improvements
- TBD...