Консольный менеджер SSH-подключений, маршрутов, секретов, туннелей и постоянных сессий.
sshkeeper не заменяет OpenSSH и не пытается быть Ansible. Это локальный менеджер подключений: он хранит профили серверов в SQLite, пароли и passphrase — в зашифрованном vault, умеет собирать маршруты через bastion/jump-host’ы и запускает системный ssh с нужными параметрами.
Основной интерфейс — клавиатурный TUI на Bubble Tea. Те же данные и операции доступны через CLI, поэтому sshkeeper подходит и для интерактивной работы, и для скриптов.

Основные возможности
- профили SSH-серверов, группы, теги и заметки;
- авторизация по ключу, через
ssh-agent, по паролю и с passphrase; - зашифрованный локальный vault для паролей и passphrase;
- маршруты / ProxyJump и цепочки bastion-host’ов со стабильными ссылками на профили;
- Local, Remote и SOCKS port forwarding;
- запуск, просмотр и остановка фоновых SSH-туннелей;
- постоянные SSH-сессии через
tmux— можно держать несколько подключений живыми и переключаться между ними; - шаблоны команд и запуск команд на выбранных серверах;
- живой fuzzy-поиск по имени, alias, host, пользователю, группе, тегам, заметкам, маршрутам и портам;
- сортировка по имени, последнему использованию или группам, сворачиваемые группы и индикаторы тестов, туннелей и сессий;
- массовая проверка доступности видимых или отмеченных серверов;
- импорт существующего
~/.ssh/config, экспорт и генерация OpenSSH-конфигурации; - русский и английский интерфейс;
- полноценный CLI для автоматизации.
Зашифрованная синхронизация между устройствами
Начиная с v0.7.0, sshkeeper умеет синхронизировать между несколькими компьютерами профили, маршруты, port-forward правила, группы, теги, шаблоны команд, секреты vault и используемые профилями приватные ключи.

Хранилищем может быть:
- общая папка — например Syncthing, Nextcloud, Dropbox или сетевой диск;
- Git-репозиторий на отдельной ветке.
Все синхронизируемые данные передаются внутри одного зашифрованного файла. Для добавления нового устройства используется шестизначный код с ограниченным сроком действия и мастер-пароль уже подключённого устройства. При создании sync-space выдаётся recovery key на случай потери всех устройств.
Локальные состояния — последний вход, результаты тестов, запущенные туннели, язык интерфейса и сортировка — между машинами не переносятся.
Маршруты, туннели и сессии
Маршруты хранятся как упорядоченная цепочка переходов. Если hop ссылается на профиль sshkeeper, связь идёт по стабильному ID: переименование bastion-профиля не ломает зависимые подключения. Для сессии sshkeeper сам формирует временный OpenSSH config, поэтому имя профиля не обязано дублироваться в ~/.ssh/config.
Port forward в sshkeeper — это сохранённое правило, а tunnel — уже запущенный SSH-процесс, который активирует такие правила. Отдельно доступен опциональный режим Sessions: если установлен tmux, SSH-подключения можно оставлять работающими и возвращаться к ним позже.
Состояние проекта
Статус: активная разработка; текущий стабильный релиз — v0.7.0.
Платформы: Linux amd64/arm64 и macOS amd64/arm64 — основные цели; Windows amd64 — экспериментально.
Пакеты: для Linux выпускаются .deb, .rpm и tar.gz; для macOS — tar.gz; для Windows — ZIP.
Зависимости: системный OpenSSH; tmux необязателен и нужен только для постоянных Sessions; git нужен только при выборе Git-хранилища синхронизации.
Технологии: Go, Bubble Tea, Cobra, SQLite, OpenSSH.
Лицензия: MIT.
Установка
Debian / Ubuntu, amd64:
sudo apt install ./sshkeeper_0.7.0-1_amd64.deb
Fedora / RHEL family, x86_64:
sudo dnf install ./sshkeeper-0.7.0-1.x86_64.rpm
После установки проверить реально запускаемый бинарник и версию можно так:
command -v sshkeeper
sshkeeper --version
Безопасность
Vault использует XChaCha20-Poly1305, а мастер-пароль проходит через Argon2id. Секреты не передаются через аргументы командной строки. Синхронизация также шифруется до помещения данных в общую папку или Git-репозиторий.
Независимого аудита безопасности проект пока не проходил, поэтому для особо критичных сред стоит отдельно изучить реализацию и модель угроз.
Ссылки
Релизы ·
Руководство ·
Скриншоты ·
Исходный код ·
Сообщить об ошибке
История релизов
v0.7.0 — sshkeeper v0.7.0
sshkeeper v0.7.0 — encrypted sync between devices
v0.7.0 keeps your devices in step: profiles, port forwards, command
templates, groups and tags, vault secrets, and the private keys your profiles
use travel end-to-end encrypted through a folder or a git repository.
Added
- Sync between devices.
m→ Settings → Synchronization chooses the
storage — a shared folder (Syncthing, Nextcloud, Dropbox, a network drive)
or a git repository — and the form shows only the fields that storage
needs. The first device creates the sync space; others join with a
six-digit code.
- Six-digit pairing. "Add device" shows a code valid for ten minutes.
The new device enters it together with the master password of the device
showing it. The code alone is worthless and is deleted after use; in git it
lives on a temporary branch that never enters the history.
- Recovery key. Shown when the sync space is created, for the case when
every device is lost. It also works in place of a pairing code.
- Automatic sync. With auto sync on, the TUI syncs at start and three
seconds after each change. The dashboard header shows ⇅ with the time
since the last sync, and changes from other devices refresh the list.
sshkeeper synccommands:setup,init,add-device,join,
status, recovery-key, leave, and plain sync.
How secrets stay secret
- Everything travels in one file sealed with XChaCha20-Poly1305 under a
random 256-bit key. The storage sees a format tag and a key fingerprint —
no names, hosts, or even how many secrets exist.
- The sync key lives only in each device's vault; a stolen sync file has no
password to guess.
- Sync refuses to run while the vault is locked, so missing secrets are never
mistaken for deletions.
- Existing key files are never overwritten, and a device's own different key
at the same path never travels to other devices.
- Changes merge per item by the latest edit; deletions travel too. Device-local
facts — last connection, last test, running tunnels, language, sort order —
stay on each device.
Changed
- Manage → Settings is now a menu with Language and Synchronization.
Fixed
- Esc in the identity-file, tags, startup-command, or route picker of the
server form left the whole form instead of closing the picker. With a filter
typed in a picker, the first Esc now clears the filter.
- Groups, Tags, Command templates, Sessions, and Running tunnels opened from
the Manage menu return to it on Esc.
- The vault no longer prints "Deriving key..." when saving, which could draw
over the TUI.
To install on Debian/Ubuntu x86-64, download the release asset and run
sudo apt install ./sshkeeper_0.7.0-1_amd64.deb (use the arm64 package on
ARM64). Git sync needs the system git; folder sync needs nothing extra.
v0.6.0 — sshkeeper v0.6.0
sshkeeper v0.6.0 — a faster, more recognizable dashboard
v0.6.0 reworks the TUI dashboard around the everyday path: find a server,
connect, come back. Everything stays keyboard-first and fits the same
60x16 minimum.
Added
- Live filter.
/(orCtrl+F) filters the list as you type and
highlights the matched letters. Names rank first, then aliases, then fuzzy
name matches (bst finds Bastion), then host, user, group, tags, notes,
route hops, and forward names or ports. Enter connects, Tab keeps the
filter, Esc clears it.
- Sort by recent use or group.
scycles between name, most recent
connection, and group, and saves the choice as ui.sort. A new SEEN column
shows the time since the last connection. In group order, group headings
fold with Enter, Space, ←, or →.
- State column.
●/✗for the last test,◌while testing,⇄when a
background tunnel for the server is running, ▣ when a tmux session is
open. Tunnels and sessions refresh every 10 seconds, including tunnels
started by another sshkeeper process.
- Test all.
Ttests every visible (or marked) server, six at a time,
and summarizes the result.
- Single-key shortcuts on the server list:
aadd,eedit,ddelete,
t test, x actions, f forwards, r run template, Space mark, q quit,
and j/k/g/G navigation. The Ctrl shortcuts still work.
- Welcome screen on the first run, with
ito import hosts from
~/.ssh/config.
- ASCII mode for terminals and fonts without box drawing:
glyphs = "ascii" under [ui], or SSHKEEPER_ASCII=1.
Changed
- New look: adaptive light/dark palette with one amber accent, a key logo in
every header, rounded panels with titles in the border, an accent cursor
bar, and shorter key action · key action footers. NO_COLOR is honored.
- The details panel shows the route as a chain (
you → bastion → host), the
last test with its reason, saved forwards with their state, open sessions,
and notes, instead of repeating host, port, and user.
- A clean ssh exit returns straight to the dashboard, with the cursor on the
same server and a ← Back from <server> · 42m notice. A failed connection
still waits for Enter so ssh's output stays readable.
- Confirmations open as a centered dialog over the dimmed screen.
- The auth method in the server form is a selector:
←/→cycle
password ‹key› key+pass agent.
- Success notices fade after five seconds; errors stay until the next key.
- The list drops the AUTH column (it is in the details panel) to give names
room.
Fixed
- A connection test result could be recorded on whichever server the cursor
had moved to by the time the test finished.
- Fast typing or key repeat delivered as one event (
jjj,/prod) is now
handled key by key.
To install on Debian/Ubuntu x86-64, download the release asset and run
sudo apt install ./sshkeeper_0.6.0-1_amd64.deb (use the arm64 package on
ARM64). Linux and macOS are the primary targets; the Windows build remains
experimental.
nightly — sshkeeper nightly (v0.6.0-7-ge65d591)pre-release
Automated build from the tip of main, rebuilt on every push.
This is not a stable release. It is untagged, unannounced and may be
broken. The Latest badge stays on the newest v* release, which is
what you want for normal use.
| | |
|---|---|
| Version | v0.6.0-7-ge65d591 |
| Commit | e65d5913d02c65d90a83da18fefa8cd7aac3da48 |
| Built | 2026-09-29 18:30 UTC |
Verify downloads against checksums.txt.
v0.5.3 — sshkeeper v0.5.3
sshkeeper v0.5.3 — Russian and English interface
v0.5.3 adds Russian and English localization to the TUI and CLI.
Changed
- Interface language follows the system locale by default. On Unix, detection
checks LC_ALL, then LC_MESSAGES, then LANG; unsupported locales use English.
- The TUI management menu (
m) now has a Settings screen for choosing System,
Russian, or English. The choice is saved in ui.language in the config file.
- TUI screens, tunnel actions, help, prompts, and CLI messages are translated.
Command names, flags, server aliases, and SSH parameters are unchanged.
This release also includes the clearer tunnel-starting flow introduced in
v0.5.2. To install on Debian/Ubuntu x86-64, download the release asset and run
sudo apt install ./sshkeeper_0.5.3-1_amd64.deb (use the arm64 package on ARM64).
v0.5.2 — sshkeeper v0.5.2
sshkeeper v0.5.2 — Tunnel TUI usability
v0.5.2 makes the path from a saved port-forward rule to a running tunnel clearer.
Changed
- The port-forwards screen now offers
Ctrl+Bto start a background tunnel and
Ctrl+X to choose any tunnel mode; saving a rule points to these actions.
- Server actions show the selected server, enabled-forward count, and why a
tunnel mode is unavailable. TUI tunnel modes require an enabled rule.
- Background startup keeps the TUI open and leaves its PID acknowledgement or
error visible. Running tunnels has an empty-state start hint.
- Foreground no-shell mode tells you to stop with
Ctrl+Cand return with Enter. - CLI
--forward-onlynow rejects configurations with no enabled forwards.
Background mode still requires key or SSH-agent authentication. Password and
key-passphrase authentication remain available in foreground modes.
For Debian/Ubuntu on x86-64, install the release asset with
sudo apt install ./sshkeeper_0.5.2-1_amd64.deb (use the arm64 package on ARM64).
v0.5.1 — sshkeeper v0.5.1
sshkeeper v0.5.1 — Package Migration Fix
v0.5.1 is a patch release on top of v0.5.0 Persistent SSH Sessions.
Fixed
- Fixed DEB/RPM post-install discovery of legacy per-user binaries at
~/.local/bin/sshkeeper. - Package installation now correctly backs up a legacy binary and replaces its old path with a symlink to
/usr/bin/sshkeeper. - Added a regression test that discovers the user path through passwd data, matching the real package-install path.
sshkeeper --versionandsshkeeper versioncontinue to report the embedded release version.
No session functionality from v0.5.0 is removed or rolled back.
v0.5.0 — sshkeeper v0.5.0
sshkeeper v0.5.0 — Persistent SSH Sessions
v0.5.0 adds an optional multi-session workflow backed by tmux. It lets
sshkeeper keep several interactive SSH connections alive in one terminal
workspace without turning sshkeeper itself into a terminal emulator.
tmux is intentionally optional. If it is not available, Sessions are not
shown anywhere in the TUI and ordinary Connect/Tunnel workflows behave exactly
as they did in v0.4.1.
Persistent sessions
When tmux is available in PATH:
- Server Actions → Open in session opens the selected server in a persistent
tmux window;
- Manage → Sessions lists SSH windows created by sshkeeper;
Enterattaches to the selected session;Ctrl+Dcloses it after confirmation;Ctrl+Rrefreshes the list.
If sshkeeper runs outside tmux, it uses a dedicated tmux workspace named
sshkeeper. If it is already running inside tmux, new SSH windows are created
inside the current tmux session rather than starting a nested client.
Vault and authentication
Sessions continue to use the existing sshkeeper/OpenSSH connection planner,
including routes, bastions, identity files and startup commands.
Key and SSH-agent sessions do not need a vault unlock. Password and
key-passphrase sessions ask for the vault master password inside their own tmux
window. Secrets are not copied through command-line arguments, environment
variables or temporary shell scripts.
Platform behavior
Linux and macOS support Sessions when tmux is installed. On macOS it can be
installed with Homebrew using brew install tmux.
Native Windows builds keep Sessions hidden because upstream tmux is not a native
Windows backend for this workflow. Windows users can use Sessions by running the
Linux build inside WSL with tmux installed there.
Linux native packages do not require tmux. Package metadata keeps OpenSSH as
the hard dependency and marks tmux only as Recommends, so the application
remains fully usable without the Sessions feature.
Validation
The release is covered by normal unit tests plus a real tmux lifecycle test that
creates a temporary workspace/window, verifies sshkeeper can discover its
metadata, closes it, and confirms it disappears.
The release gate also runs go vet, Linux package migration tests and release
cross-builds for Linux amd64/arm64, macOS amd64/arm64 and Windows amd64. GitHub
CI additionally runs the test suite natively on both Ubuntu and macOS.
Install
Debian/Ubuntu (amd64):
sudo apt install ./sshkeeper_0.5.0-1_amd64.deb
Fedora/RHEL-family (x86_64):
sudo dnf install ./sshkeeper-0.5.0-1.x86_64.rpm
ARM64 packages and tar/zip archives are published alongside them. Verify
downloads against checksums.txt.
v0.4.1 — sshkeeper v0.4.1
sshkeeper v0.4.1 — Package Install & Version Fixes
This patch release makes native Linux packages authoritative after installation
and exposes the version embedded in the executable.
Package installation now wins over legacy binaries
DEB and RPM installs detect older sshkeeper copies at known legacy paths:
/usr/local/bin/sshkeeper;- per-user
~/.local/bin/sshkeeperpaths discovered from the system account database.
A detected legacy entry is preserved as *.legacy-backup, then its old path is
replaced by a symlink to /usr/bin/sshkeeper. This deliberately handles both
PATH precedence and shells that have already cached the previous executable
path. No database, vault, configuration, SSH key, or other user data is touched.
The migration is idempotent across package upgrades. Removing the package restores
the preserved legacy binary when the redirect is still package-managed; if the
user changed that path while the package was installed, the package leaves the
user's replacement alone and keeps the backup rather than overwriting it.
Version reporting
Both forms are now supported without initializing the database or vault:
sshkeeper --version
sshkeeper version
A v0.4.1 release binary prints:
sshkeeper v0.4.1
The build and release scripts now link the discovered version into the real
cmd.Version symbol instead of the stale main.version target.
Packaging verification
The release gate now tests legacy-path migration and restoration in addition to
the existing Go tests, vet, and cross-platform builds. DEB/RPM packages continue
to contain the exact Linux binary produced for the matching tarball.
v0.4.0 — sshkeeper v0.4.0
sshkeeper v0.4.0 — Model & Workflow Cleanup
v0.4.0 is a structural release. The main goal is to make sshkeeper's data model
match what the user sees: server profiles are real reusable objects, routes
reference those objects instead of mutable text, and the TUI offers pickers for
things that already exist instead of asking you to retype them.
Existing databases and vaults are migrated automatically. No manual conversion
is required.
Routes are now real relationships
The old implementation stored both ProxyJump text and a second route
representation. Different commands wrote different fields, and runtime SSH used
one in preference to the other. That made it possible for edit --proxy-jump to
say "Saved" while the old structured route was still used.
v0.4.0 makes Route canonical and stores profile hops in a normalized
server_route_hops table with foreign keys to stable server IDs.
- Renaming a bastion no longer breaks dependent routes.
- Deleting a profile that is still used as a route hop is rejected and names
the dependent profiles.
- Self references, duplicate hops and route cycles are rejected.
proxy_jumpand legacyroute_hopsremain compatibility projections for old
databases/tools, not competing sources of truth.
- Existing
group_namestrings are likewise migrated to first-classgroups
with stable IDs.
Profile hops no longer depend on ~/.ssh/config
A route hop that references a sshkeeper profile now resolves that profile's real
host, user, port and identity file from SQLite. sshkeeper generates a temporary
OpenSSH config for the connection and passes it with ssh -F.
This fixes the old accidental requirement that a sshkeeper alias such as
bastion-prod also had to exist as a matching Host in the user's OpenSSH
config.
CLI route syntax is explicit when needed:
# exact known aliases are profile references
sshkeeper route set prod --jumps bastion,dmz-gw
# force the interpretation
sshkeeper route set prod --jumps profile:bastion,raw:ops@external-gw:2222
An unprefixed value matching an existing sshkeeper alias becomes a profile hop;
an unknown value remains a raw OpenSSH target.
Password or key-passphrase authentication on an *intermediate* profile hop is
rejected with a clear error for now. The current PTY secret flow can safely feed
the target profile, but it cannot reliably route different vault secrets to
multiple OpenSSH prompts in a jump chain. Key/agent bastions are supported.
Route editor in the TUI
Ctrl+X → Route, or / while the Route field is focused, opens an ordered
route editor.
Enteradds an existing server profile as a hop.x/ Delete removes a hop.[/]moves a hop up/down in the chain./filters the available profiles.raw:<target>remains available in the editable field for arbitrary OpenSSH
targets.
The server form no longer claims that a picker exists while still requiring a
comma-separated string.
Server Actions vs Manage
Ctrl+X is now strictly about the selected server:
- Connect
- Connect with tunnels
- Start tunnels only / in background
- Port forwards
- Route
- Test connection
- Edit
- Delete
Press m for global management:
- Groups
- Tags
- Command templates
- Running tunnels
- Import SSH config
- Export
- Vault lock / password change
Groups now have their own manager with server counts, create/rename/delete
operations, and safe delete consequences.
Context-aware server form
The form now exposes only authentication fields that matter:
| Auth | Fields |
|------|--------|
| password | Password |
| key | Identity File |
| key_passphrase | Identity File + Key passphrase |
| agent | no credential fields |
/ opens context-specific pickers:
- Auth method → auth list
- Identity File → detected private keys in
~/.ssh - Route → profile/chain editor
- Group → existing groups
- Startup Command → global command templates (the command is copied, not linked)
- Tags → multi-select existing tags; new tags can still be typed manually
CLI consistency fixes
All writers now go through the same route semantics.
add,edit,route set, TUI save and SSH config import all create the same
canonical route model.
- SSH config import is two-pass: profiles are created first, then
ProxyJump
aliases are resolved against the complete imported/existing profile set.
edituses Cobra'sChanged()state, so--group '',--notes '',
--startup-command '', --identity-file '', --proxy-jump '' and
--tags '' can actually clear values.
- An empty server
Userno longer produces the invalid target@host; OpenSSH
is allowed to choose its configured/current user.
- Shared server/auth/route validation replaced duplicated partial checks.
Vault identity follows the server, not its alias
New and migrated server secrets are stored under stable server IDs. Renaming a
profile no longer requires a risky copy/delete of secrets keyed by alias.
Legacy server:<alias>:<type> records remain readable and are lazily migrated
when used. vault list understands both legacy and stable-ID records and
resolves stable IDs back to current aliases when the database is available.
TUI server save now commits the database change before rewriting vault state;
if the vault step fails, the profile/tags are rolled back instead of leaving the
database and vault disagreeing.
Port forward fixes
Two concrete TUI bugs are fixed:
- Editing a disabled forward no longer silently re-enables it.
- Remote-forward preview now uses the same semantic builder as validation/save,
so listen/target endpoints cannot be shown reversed.
The editor has an explicit Enabled toggle and the forward list supports Space
to enable/disable a rule quickly.
Tunnel fixes
Profile routes work consistently for foreground and background tunnels.
Background tunnels keep their generated temporary SSH config for the lifetime of
the process and remove it on stop/stop-all.
Tunnel Manager now reports running separately from tracked; stale tracked
state is no longer counted as a running process.
Cleanup
- Removed the stale per-server
CommandTemplate.ServerIDfield; command
templates are global.
- Removed an unused legacy
model.Secrettype; the encrypted vault has its own
actual storage model.
- Added regression coverage for stable route references, deletion protection,
cycle detection, stable-ID vault metadata, contextual auth fields, Manage,
route/identity/tag/startup pickers, and forward semantics.
Upgrade notes
On first start, v0.4.0 automatically creates groups and
server_route_hops, links existing group names, and converts existing route
text/JSON. The old columns are retained for compatibility.
As always, keep a copy of ~/.local/share/sshkeeper/ before a major upgrade if
the data matters to you.
Install
Debian/Ubuntu (amd64):
sudo apt install ./sshkeeper_0.4.0-1_amd64.deb
Fedora/RHEL-family (x86_64):
sudo dnf install ./sshkeeper-0.4.0-1.x86_64.rpm
ARM64 packages (arm64.deb / aarch64.rpm) and the original tar.gz archives
are published alongside them. Package dependencies pull in the distro OpenSSH
client; user config, database and vault files are not owned or modified by the
package.
Verify downloads against checksums.txt. Linux and macOS are the primary
release targets. Windows remains experimental and requires OpenSSH Client
(ssh.exe) in PATH.
v0.3.2 — sshkeeper v0.3.2
Release automation and reproducible packaging. sshkeeper itself behaves exactly
as in v0.3.1 — no functional changes to the TUI or the CLI.
This is also the first release published by GitHub Actions rather than by hand.
In this release
Archives are now reproducible. Rebuilding a tag on a different machine used
to produce different checksums even when every packaged file was byte-identical,
because three host properties leaked into the archives:
| Leak | Effect |
|------|--------|
| File modes followed the builder's umask | umask 002 packaged 664/775, umask 022 packaged 644/755 |
| sort orders entries by locale | a ru_RU.UTF-8 host emitted docs/ before LICENSE, a C locale the reverse |
| zip stores DOS local time with no zone | the same commit embedded 19:06 at UTC+08 and 11:06 at UTC |
All three are pinned now. A build on ubuntu-latest and one on a workstation
with a different umask, locale and timezone produce identical checksums for all
five archives. The binaries were always reproducible; only the packaging varied.
CI. The repository previously had no automation. It now runs gofmt,
go vet and go test on Linux *and* macOS for every push and pull request,
plus a cross-build of all five release targets. macOS is a stated release
target that until now was only ever cross-compiled, never tested.
Releases are automated. Pushing a v* tag runs the release checks, builds
through the same release.sh used locally, and publishes. Nightly builds from
main are published as a separate nightly prerelease, so the Latest badge
always points at a real release.
---
Everything since v0.2.0
Breaking change: full help moved off F1
Ctrl+H opens full help. F1 no longer has any binding. ? still opens
contextual quick help outside text editors. This landed in v0.3.0.
Ctrl+H is the BS control character (0x08). xterm and most modern emulators
send DEL (0x7F) for Backspace, so help and text editing do not collide. A
terminal configured to send BS for Backspace cannot tell them apart; switch it
to DEL (in xterm, backarrowKey: false).
Nothing else requires action when upgrading. Vaults, server profiles and stored
port forwards are unchanged, and no migration runs.
The TUI was rebuilt around one shell (v0.3.0)
In v0.2.0 only the server dashboard had a real layout. Other screens rendered
free-form strings or the default Bubbles list frame, so they had no shared
width budget, no borders, and footers that floated wherever the content ended.
Every full-screen state now shares one contract: a header with breadcrumb and
truthful vault status, a separator, framed content panels, and a contextual
footer anchored to the last terminal row.
- Actions, search, tag input, confirmations and both help screens render inside
the shell.
- The port forward manager and editor use framed, width-budgeted layouts. Column
widths derive from the panel's inner width, so no row consumes the terminal's
last column.
- Tag, command template, template picker/mode/results and tunnel managers use
framed lists with a > selection marker, so selection never depends on colour
alone.
- Server and template editors use a framed form panel with the title moved into
the breadcrumb. Required markers, validation and dirty-state confirmation are
unchanged.
Responsive layouts. The supported floor is 60x16. Wide (100+ columns)
shows two panels, medium (70–99) stacks them, narrow (60–69) keeps a single
compact panel. Below the floor only the minimum-size message renders. Long
ASCII, Cyrillic, CJK, combining and emoji content truncates by display cells
rather than byte count.
Safety. Destructive actions confirm with Cancel selected first and name the
exact target and its consequence. Status and help context stay truthful to
actual vault and connection state. Form validation prevents silent loss of
edits.
forward add was completely broken (fixed in v0.3.1)
sshkeeper forward add could never succeed in v0.2.0 or v0.3.0. The command
read --local-port and marked it required, but the flag was never registered,
so cobra rejected it as unknown and the value fell back to 0:
$ sshkeeper forward add web --type local --local-port 15432 \
--remote-addr 127.0.0.1 --remote-port 5432
unknown flag: --local-port
No combination of arguments worked. Both documented forms work now:
$ sshkeeper forward add web --name "Local PostgreSQL" --type local \
--local-port 15432 --remote-addr db01.internal.example.com --remote-port 5432
✓ Forward added [1]
$ sshkeeper forward add web --name "SOCKS proxy" --type dynamic --local-port 1080
✓ Forward added [2]
Omitting the flag now reports required flag(s) "local-port" not set instead of
a misleading port-range error. The TUI (Ctrl+W) was never affected.
The command's tests had constructed their own throwaway cobra command and
registered the flags by hand, so the real command's registration was never
exercised and the suite passed against a broken command. Coverage now parses
argv into the actual command. An audit of every other command found no further
flag that is read but never registered.
Also fixed since v0.2.0
- Port forward fields accept digits correctly (
10bcc07). - Platform and repository status are stated accurately in the docs: Linux and
macOS are primary release targets, Windows is experimental.
Release-by-release
| Version | Contents |
|---------|----------|
| v0.3.0 | Unified TUI shell, responsive layouts, F1 → Ctrl+H |
| v0.3.1 | forward add fix |
| v0.3.2 | Reproducible packaging, CI, automated releases |
Install
tar -xzf sshkeeper_v0.3.2_linux_amd64.tar.gz
sudo install -m 0755 sshkeeper_v0.3.2_linux_amd64/sshkeeper /usr/local/bin/sshkeeper
Verify downloads against checksums.txt. Linux and macOS are the primary
release targets; the Windows build is experimental and needs OpenSSH Client
available as ssh.exe on PATH.
To verify a build yourself, check out the tag and run ./release.sh v0.3.2 —
the checksums should match this release exactly, given the same Go version.
Источник: GitHub Releases · данные кэшируются на сервере.