TurboSSH — SSH / Serial / SFTP / SCP / FTP / RDP terminal & automation toolkit for automotive & embedded (Python API, CLI, and a full PyQt5 GUI with a VT100 terminal).
Project description
TurboSSH
TurboSSH is an SSH / Serial / SFTP / SCP / FTP / RDP terminal and automation toolkit built on Paramiko — for automotive & embedded work, test automation, and everyday remote ops. It ships three ways in one install:
- Python API —
import turbosshfor scripts and test frameworks. - CLI —
turbossh …, fully argument-driven. - GUI —
turbossh-gui, a tabbed multi-session terminal with a true VT100 emulator (htop / vim / top work), an SFTP browser, serial consoles, and RDP launch. Ships as a prebuilt Windows exe (PyQt5 baked in — no PyQt5 install needed, even on Windows ARM64).
pip install turbossh
turbossh-gui
Table of contents
- Install
- The GUI
- Quick start (API)
- Connecting — local, jump host, RDP
- Running commands
- Continuous logs
- File transfer — SFTP / SCP / FTP
- Serial / COM ports
- Port forwarding (tunnels)
- Keys & passwordless setup
- Automotive / legacy devices
- Confidential credentials
- Enable SSH on a Windows box (offline)
- CLI reference
- Result objects & error handling
- Full Paramiko capability
- API map
Install
pip install turbossh # API + CLI + prebuilt Windows GUI exe
pip install "turbossh[gui]" # also installs PyQt5 to run the GUI from source
Batteries included: paramiko, scp, pyserial, keyring, pywinrm, and
pyte (VT100) are pulled in automatically. Only PyQt5 is optional — the shipped
GUI exe already contains it, so turbossh-gui works without installing PyQt5.
The GUI
turbossh-gui
- Session manager sidebar — saved SSH / Serial / RDP sessions (right-click for New / Open / Edit / Duplicate / Delete). Passwords live in the OS credential vault, never in plaintext. A Quick connect box filters as you type.
- Tabbed sessions + a
+button; Split tiles several sessions in a grid. - Menu bar (File / Edit / View / Session / Help) with icons — New session, Save output, Set up SSH server, Copy/Paste/Clear, Split, Check for updates…
- True VT100 terminal (pyte) — full-screen apps (htop, vim, top, less, nano) render correctly, with colors, a block cursor, and live PTY resize.
- 5000-line scrollback — wheel up to read old output; typing snaps back to the live tail. Save all output writes the entire session, not just what's on screen.
- Quick buttons — one-click
slog2info -w,journalctl -f,dmesg -w,tail -f, plus Ctrl-C and Clear. - Split SFTP browser under each terminal — navigate, upload, download, mkdir, rename, delete (transfers on a separate channel; the UI never blocks).
- Serial console — local, or on a remote RDP machine over SSH with a one-click Scan remote to list that machine's COM ports.
- 🖧 SSH server button — turn this Windows box into an SSH server, offline, from the bundled OpenSSH (see below).
- Check for updates — one click pulls the latest from PyPI and reinstalls.
- Settings — dark/light theme, terminal font + size, default baud (persisted, applied live).
- Crash-proof — all I/O on background threads; a startup failure shows a popup and writes a crash log; runtime errors are logged, never fatal.
Quick start (API)
from turbossh import SSHHandler, SSHConfig
with SSHHandler(SSHConfig(host="10.0.0.5", username="root", password="pw")) as ssh:
print(ssh.run("uname -a").text) # clean single-line output
ssh.run("systemctl restart nginx", check=True)
ssh.push("local.txt", "/tmp/remote.txt")
ssh.pull("/etc/nginx", "./backup", recursive=True)
Connecting — local, jump host, RDP
# direct
cfg = SSHConfig(host="10.0.0.5", username="root", password="pw",
host_key_policy="ignore") # ignore = lab/reimaged devices
# through a bastion/jump (laptop -> jump -> target)
jump = SSHConfig(host="10.232.9.22", domain="CORP", username="user", password="pw")
cfg = SSHConfig(host="10.120.1.91", username="root", password="pw", jump_host=jump)
host_key_policy |
Behaviour |
|---|---|
"auto" (default) |
add unknown keys, reject changed keys |
"ignore" |
accept any key incl. changed — for reimaged/DHCP lab devices |
"reject" |
strict; only keys already in known_hosts |
Auth is auto-selected: password, private key (+ passphrase), agent / discovered
keys, empty-password accounts, or passwordless=True. Connects retry with
backoff and reconnect automatically; a failed connect self-diagnoses (probes the
SSH/RDP ports and explains why).
Running commands
r = ssh.run("ls -la", timeout=30, check=False)
print(r.text, r.exit_code, r.ok, r.duration)
ssh.run_many(["a", "b", "c"], stop_on_error=True)
ssh.sudo("systemctl restart app", password="pw")
with ssh.open_shell() as sh: # interactive send/expect
sh.send("cd /var/log"); print(sh.read_until("$", timeout=5).output)
Continuous logs
ssh.stream("slog2info -w", on_line=print,
match=r"error|fail", save_to="device.log", timeout=120) # ANSI auto-cleaned
for line in ssh.iter_lines("journalctl -f"):
print(line)
File transfer — SFTP / SCP / FTP
ssh.push("fw.bin", "/tmp/fw.bin") # SFTP upload
ssh.pull("/var/log/messages", "messages.log") # SFTP download
ssh.push("./build", "/tmp/build", recursive=True) # folder, progress callback
ssh.scp_push("img.tar", "/tmp/img.tar") # SCP protocol
from turbossh import FTPHandler, FTPConfig
with FTPHandler(FTPConfig(host="ftp.x", username="u", password="p", use_tls=True)) as ftp:
ftp.push("a.txt", "a.txt"); ftp.pull("b.txt", "b.txt")
Through a jump host, transfers ride the tunnel automatically. Remote FS helpers:
listdir, stat, exists, isdir, mkdir, makedirs, rename, remove, chmod, read_text,
write_text, walk.
Serial / COM ports
# local port (device plugged into THIS machine)
from turbossh import SerialHandler, list_serial_ports
print(list_serial_ports())
with SerialHandler("COM5", baudrate=115200) as ser:
ser.write_line("version")
ser.stream(on_line=print, match=r"login:", save_to="com5.log")
# port on a REMOTE machine, over SSH/jump (COM = Windows, /dev/tty* = Linux)
ssh.serial_write("COM5", "version", baudrate=115200)
ssh.serial_stream("COM5", baudrate=115200, on_line=print, match=r"login:",
save_to="com5.log")
Port forwarding (tunnels)
# ssh -L : reach a remote service on a local port (e.g. a web UI behind the host)
fwd = ssh.forward_local("127.0.0.1", 8080, local_port=18080)
print("now browse http://127.0.0.1:%d" % fwd.local_port)
fwd.close()
# ssh -R : expose a local service on a remote port
rfwd = ssh.forward_remote(9000, "127.0.0.1", 3000)
rfwd.close()
Both work through a jump host and return a handle with .close() (or use as a
context manager).
Keys & passwordless setup
from turbossh import generate_keypair
generate_keypair("~/.ssh/turbo_key") # writes turbo_key and turbo_key.pub
# deploy it (ssh-copy-id) so future logins are passwordless
ssh.copy_id(public_key_file="~/.ssh/turbo_key.pub")
Automotive / legacy devices
Old ECUs / embedded SSH servers often use crypto modern Paramiko drops. Re-enable it:
cfg = SSHConfig(host="10.0.0.9", username="root", password="pw",
enable_legacy_algorithms=True) # old KEX/ciphers/host-keys
# fine-grained: disabled_algorithms={"pubkeys": ["rsa-sha2-512"]}
In the GUI, tick "Enable legacy algorithms" in the session dialog.
Confidential credentials
| Mechanism | What it does |
|---|---|
Secret |
wraps a password; logs/reprs show ********; only .reveal() exposes it |
mask() |
redacts secrets from any string (applied to all logging automatically) |
CredentialStore |
stores/reads passwords in the OS vault via keyring — no plaintext |
prompt_password() |
hidden terminal input |
Enable SSH on a Windows box (offline)
Run this on the RDP / Windows machine to turn it into an SSH server — so TurboSSH (and your scripts) can reach it, including the COM ports plugged into it. It's fully offline: the OpenSSH binaries (ARM64 / Win64 / Win32) ship inside the package, so it works on locked-down corporate networks where downloads are blocked.
From the GUI (easiest): click 🖧 SSH server in the ribbon. Choose:
- This PC — approve the Administrator prompt; it installs OpenSSH Server,
starts
sshd, opens the firewall, fixes host keys, and the GUI confirms when it's listening. - A remote machine (WinRM) — install OpenSSH on another Windows box from here, fully offline: the bundled OpenSSH is pushed over WinRM and installed remotely. Needs WinRM (port 5985) reachable and a local-admin account on the target — handy for enabling SSH on an RDP machine without logging into it.
From the terminal:
turbossh-setup # self-elevates, installs OpenSSH Server from the bundled
# ZIP (ARM64/Win64/Win32), starts sshd, opens firewall,
# generates + fixes host keys. No internet / Windows Update.
turbossh-setup --InstallPip --Port 22 # also pip-install turbossh; custom port
Or auto-enable a remote box over WinRM: SSHConfig(auto_bootstrap_via_winrm=True).
Tip: this is the "serve" step — do it once per RDP machine and you'll never have to remember to enable SSH by hand again.
CLI reference
turbossh run --host H --user U [--domain CORP] [--use-stored] uname -a
turbossh push --host H --user U ./build /tmp/build --recursive
turbossh pull --host H --user U /var/log ./logs --recursive
turbossh info --host H --user U --json
turbossh store-credential --user U --domain CORP --service my_lab
turbossh-gui # launch the GUI
turbossh-setup # install OpenSSH Server on this machine (offline)
turbossh-shortcut # create a Desktop shortcut to the GUI
turbossh-docs # open the docs
Result objects & error handling
CommandResult—.exit_code,.stdout,.text,.stderr,.duration,.okTransferResult—.size_bytes,.duration,.human_speed,.filesOperationResult— safe-mode wrapper:bool(res),.value,.error,.unwrap()
Raise mode (default): typed exceptions — SSHConnectionError,
SSHAuthenticationError, SSHTimeoutError, SSHCommandError, SSHTransferError,
FTPError, SerialError, WinRMError, CredentialError (all subclass SSHError).
Safe mode (SSHHandler(cfg, safe=True)): every call returns an
OperationResult instead of raising — ideal for GUIs and long-running tools.
Full Paramiko capability
TurboSSH wraps the common operations with retries, structured results, and safe secrets — but it never hides Paramiko. Anything Paramiko can do is available:
- Commands / shells —
run,run_many,sudo,open_shell,stream,iter_lines - SFTP — full file operations + recursive
push/pullwith progress - SCP —
scp_push/scp_pull - Port forwarding —
forward_local(-L),forward_remote(-R) - Keys —
generate_keypair,copy_id(ssh-copy-id) - Jump host / ProxyJump —
SSHConfig(jump_host=…) - Algorithm control —
enable_legacy_algorithms,disabled_algorithms - Keepalives, compression, timeouts, host-key policy — all on
SSHConfig - Raw escape hatch —
ssh.client(theparamiko.SSHClient) andssh.transport(theparamiko.Transport) are exposed, so any lower-level Paramiko call works:
transport = ssh.transport
sftp = ssh.client.open_sftp()
chan = transport.open_session()
# …anything Paramiko supports
API map
turbossh/
config.py SSHConfig (jump, legacy algos, host-key policy…), FTPConfig
core.py SSHHandler (SSH + SFTP + SCP + stream + serial + tunnels +
keys + diagnose), ShellSession
tunnel.py LocalForward, RemoteForward, generate_keypair
serial_handler.py SerialHandler, list_serial_ports
ftp.py FTPHandler (FTP/FTPS)
winrm_bootstrap.py enable_openssh_via_winrm
pool.py SSHPool (parallel multi-host)
credentials.py Secret, CredentialStore, mask, prompt_password
results.py CommandResult, TransferResult, ShellResult, OperationResult
cli.py CLI + launchers (gui / docs / setup / shortcut / rdp)
pyqt_worker.py SSHWorker (embed in your own PyQt5 app)
bin/turbossh-gui.exe prebuilt GUI (PyQt5 baked in)
gui/ the desktop app
vt100.py true VT100 terminal (pyte) — htop/vim render correctly
sftp_browser.py · session_widgets.py · session_dialog.py · sessions.py
settings.py · settings_dialog.py · main_window.py · app.py · theme.py
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file turbossh-0.19.4-py3-none-any.whl.
File metadata
- Download URL: turbossh-0.19.4-py3-none-any.whl
- Upload date:
- Size: 90.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5351af6e53c3cad27399241b08b262f90f0b84388eb30b7fc07566ad06226120
|
|
| MD5 |
e534e934edfc5bae072cdf75716fcbe7
|
|
| BLAKE2b-256 |
b28a9e9a649c129f6c33a9b2000bc02467df31d4f966f5e541ded3415e11ad61
|