Releases: Petyok/SSHub
Releases · Petyok/SSHub
Release list
v0.11.0
Changelog
All notable changes to SSHub are documented in this file.
[Unreleased]
[0.11.0] - 2026-07-30
Added
- Session switcher (
Alt+S, PR #46 by @michabbb) - a searchable
list of the sessions that are already open, so getting back to one no longer
means stepping through the tabs withCtrl+[/Ctrl+]. Rows carry the host,
its user@address and a lifecycle dot (up/new/dead); Enter jumps to
the session, and Ctrl+Shift+T still opens a local shell from inside the
picker. The new-session, SFTP-left-pane and switch-session dropdowns are one
widget with three purposes now, filtered by the same fuzzy matcher as the
host list and the palette. - Type-to-filter in Help and the keybinding editor (issue #48) - those two
overlays were the only long lists you could not search. Both now take a query
the same way the tag filter does (› query█): case-insensitive substring over
the key spec / action label and the description / configured binds. Arrows and
PageUp/PageDown move;j/ktype into the query. Esc clears a non-empty query
and closes only when it is empty (Help also still dismisses on Enter when the
query is idle). Section headers with no surviving help rows are dropped, and
the keybinding editor rebinds the filtered row (notKeyAction::ALL[selected]),
including while a capture is in progress. Row actions there moved to Ctrl+A /
Ctrl+R / Ctrl+X so every unmodified letter can be part of a search. - Stored passwords and passphrases are no longer write-only (issue #60) - a
saved secret showed as(set)and nothing else: you could not tell which one
was stored, could not get it out, and editing meant retyping from scratch. The
field now opens prefilled from the credential store, masked, withCtrl+Rto
show and copy it andCtrl+Yto copy without showing. Both say what they
copied and never the value, the reveal drops as soon as the field is left, and
the value stays out of every log, audit row and diagnostic. Both binds are
rebindable in the keybinding editor, and the form's hint row names them while
the field is focused, since a masked value gives no clue on its own. - Ad-hoc connect - typing an unknown
[user@]host[:port]into the fuzzy
palette (/), IPv6 in brackets included, now offers a "connect without saving"
row instead of reporting no matches, and Enter opens an embedded session
straight to it. The destination is validated and passed after--, so a host
that starts with a dash cannot turn into an ssh flag. - Local shell tab -
Ctrl+Shift+Topens a session tab running your login
shell ($SHELL, falling back to/bin/sh), with the same detach and close
behaviour as an ssh tab. - Push a public key to a host (PR #16 by @vesyorsins) -
Shift+Pfrom the
hosts list picks an identity, or from the Keys tab picks a host, and installs
that identity's public key into the remote~/.ssh/authorized_keys. The
remote side runs underumask 077, creates the file if missing, and appends
only when an exact matching line is not already there, so repeating it is
harmless. The public key comes from the.pubfile when one exists, otherwise
ssh-keygen -yextracts it with the passphrase staged through askpass rather
than argv. Authentication reuses the same stored-credential path as a normal
connect, and the result is written to the audit log. The help overlay has been
advertising this key since the feature was ceded to this PR; now it exists. - Generate SSH keys from the Keys tab (PR #15 by @vesyorsins) -
gopens a
form for the key type (Ed25519 or RSA-4096), passphrase, comment and target
path. The passphrase reachesssh-keygenthrough askpass rather than argv,
the new key is registered as an identity immediately, and its passphrase goes
to the credential store when one was set. Generation refuses to overwrite an
existing key or its.pub. - Credentials survive a missing keyring (PR #1 by @vesyorsins) - where no
Secret Service is reachable (WSL, Docker, a headless box), passwords and
passphrases used to have nowhere to go. They now fall back to an owner-only
credentials.jsonin the data directory, written through a0600temp file
and an atomic rename, and the status bar says so rather than letting you
assume the keyring took it. The fallback file is plaintext, since there is
no keyring to encrypt against. Once a keyring shows up again, its contents
migrate into it on the next launch and the file is removed, but only if every
entry made it across. - Install from npm (issue #51) -
npx sshub-tuiandnpm install -g sshub-tui
now work, installing a command still calledsshub. The npm package ships the
same prebuilt binaries the GitHub release does, delivered as platform-specific
optional dependencies, so there is no build step and nothing is fetched from
outside the registry. Prebuilt for Linux x64, macOS arm64 and macOS x64; every
other platform keeps usingcargo install sshub. - UI motion pass (issue #35) - the interface moves instead of cutting
between states. Popups drop in from off the top and are thrown back up on
close; tab bodies slide; a zoomed panel morphs out of its grid slot; the
full-screen host view slides in on connect and off on the way out; the SFTP
tab slides between its picker, "connecting…" and browser states, with the two
panes meeting in the middle and parting again. The host list scrolls under
the cursor rather than jumping half a panel, its highlight wipes in, and a
group's rows are revealed one at a time as it folds. Status is legible in
motion too: a host's dot flashes when its ping class changes, a reconnecting
tunnel's dot breathes, the header tally counts to its new values, a fresh
ping reading grows into the latency graph, and the SFTP queue has a progress
bar that sweeps between the worker's chunked updates. Everything is gated on
the existingappearance.disable_animationreduced-motion toggle, and the
frame rate only rises while something is actually animating. - SFTP between two servers - the left pane can be pointed at a second host
witho(and back to local files withO), so two servers sit side by side
with their own connections, listings and file operations. Transfers between
them are relayed through a local temp file, one leg at a time, since libssh2
has no server-to-server copy; an item only leaves the queue once it lands on
the far end, so a failure part-way keeps it for a retry. - SFTP queue stays open during a transfer - files can be staged while the
queue runs and roll into the next pass when the current one finishes. The
local pane stays browsable meanwhile. - SFTP
..row - both panes list their parent directory as a selectable
row, so walking up no longer depends on knowing aboutBackspace.
Changed
- SFTP hides dotfiles (issue #44), with
.to show them - in a home
directory they were most of the listing, pushing what you came for below the
fold. This changes what an existing install shows on first run, so the pane
says how many entries it is holding back, and a search beginning with a dot
(.ssh) lifts the hiding rather than reporting no matches. The toggle covers
both panes and is remembered across restarts. The..row is exempt from the
hiding, being a way out rather than an entry, but steps aside while searching
so the cursor lands on a result. - Smaller release binaries (issue #42) - release builds had no profile at
all, so they shipped with the symbol table and without cross-crate
optimisation. Addinglto = "thin",codegen-units = 1and
strip = "symbols"takes the Linux x86-64 binary from 14.8 MB to 11.6 MB
(-21.8%), which every distribution channel carries: the release tarballs,
cargo install, and anything that repackages them.cargo testand a plain
cargo buildare untouched, but every release build now takes noticeably
longer -- includingjust buildandjust install, which build in release
mode, and including every dependency, sincecodegen-units = 1applies across
the whole graph. One trade to be aware of when reporting a crash: stripping
the symbol table leavesRUST_BACKTRACEoutput empty in a released binary,
so a backtrace worth sending has to come from a debug build.
Fixed
- Session-strip binds only worked on the hosts tab (issue #67) - the header
strip and footer advertised resume, tabs, new tab, detach and sftp from every
dashboard tab, but the keys only fired on hosts. They are handled globally
whenever sessions exist, before the per-tab dispatch. Ctrl+T still opens a new
SSH session picker on the SFTP tab; plainoremains the left-pane picker.
The dashboard footer no longer listsdetach: you are already detached, so
advertising it was a lie; detach stays on the in-session header. - Upgrading while running broke password auth until restart (issue #63) - the
askpass helper is this binary, found throughcurrent_exe(), and an upgrade
replaces the file rather than writing into it, so the running process was left
pointing at<path> (deleted). ssh could not exec that, no stored secret was
delivered, and the failure read asPermission denied (publickey), which points
at the server rather than at the upgrade. The path is now re-resolved when it
disappears, so an in-place upgrade keeps working, and when the helper genuinely
cannot be found the session log says why instead of leaving a rejected-key
message to explain itself. - The agent panel printed over the identity cards - its position was derived
from whole card rows while the grid scrolls by lines, so mid-scroll it landed on
a card and its own short fields left the card showing through, giving lines like
loaded keys 0n (no key)andagent socket (not set)────┘. It is a fixed strip
at the bottom of the tab...
v0.10.0
v0.9.0
v0.8.0
v0.7.0
v0.5.7
v0.5.6
v0.5.0
v0.4.0
SSHub v0.4.0 — relicensed to AGPL-3.0-or-later
v0.3.1
SSHub v0.3.1 (docs-only: crates.io README images)