wardenssh

command module
v0.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 13 Imported by: 0

README ΒΆ

WardenSSH πŸ›‘οΈ

Cross-Platform SSH Management TUI with native Bitwarden & Vaultwarden Integration

Go Version License Platform Security Test Release

WardenSSH is a modern, cross-platform Terminal User Interface (TUI) application designed to manage SSH host connections and private keys seamlessly. Built using tview + tcell with an embedded terminal emulator (tvxterm).

The core security guarantee of WardenSSH is Zero-Disk-Footprint: private keys stored in Bitwarden/Vaultwarden are never written to disk. Keys are decrypted strictly in RAM at rest and served directly to ssh via an in-process SSH agent.


✨ Features

  • πŸ” Native Bitwarden / Vaultwarden Integration: Direct in-process integration with Bitwarden Password Manager API (supports custom fields and multi-vault).
  • πŸ”’ Zero-Disk-Footprint Security: Private keys remain encrypted at rest in your vault and exist only in RAM during execution. Served dynamically to ssh via an in-process agent.
  • ⚑ Multi-Source Host Aggregation: Aggregate SSH hosts from multiple Bitwarden vaults alongside your local ~/.ssh/config.
  • πŸ” Instant Fuzzy Search & Scoping: Lightning-fast filtering by host name, alias, or source scope (Tab cycle between all sources, individual vaults, or ~/.ssh/config).
  • πŸ–₯️ Embedded Terminal + Split Panes: Host list on the left, live SSH terminal on the right. Press Ctrl+B or Esc to move focus between panes.
  • πŸ”„ Parallel Session Management: Run multiple concurrent SSH sessions β€” new hosts open in the right pane while previous sessions keep running in the background (yield-and-switch).
  • πŸ”‘ Secure OS Keyring Storage: Vault refresh tokens are stored securely in your operating system's native keyring (Windows Credential Manager, macOS Keychain, Linux Secret Service).
  • 🌐 Cross-Platform: Full support for Linux, macOS, and Windows (utilizing Windows ConPTY and Named Pipes).
  • πŸ”Œ Graceful Offline Mode: Unreachable vaults degrade gracefully without breaking access to local ~/.ssh/config hosts.

πŸ—οΈ Architecture & How It Works

WardenSSH acts as the TUI Host Launcher, Vault Client, and In-Process SSH Agent simultaneously. No external bw CLI binary or OS ssh-agent service is required.

                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚   Bitwarden / Vaultwarden Server    β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                     β”‚ Encrypted Sync (HTTPS)
                                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ WardenSSH (Single Binary Process)                                      β”‚
β”‚                                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Decrypted    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Native Vault Clientβ”‚ ─────────────> β”‚ RAM Key Cache              β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   (In-RAM)     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                      β”‚                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ tview TUI Launcher β”‚                β”‚ In-Process SSH Agent       β”‚  β”‚
β”‚  β”‚ (split panes +     β”‚                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚  β”‚  tvxterm terminal) β”‚                              β”‚                 β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                       β”‚ SSH_AUTH_SOCK
                                                       β”‚ (Named Pipe / Unix Socket)
                                                       β–Ό
                                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                         β”‚  ssh Client (OpenSSH)     β”‚
                                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Vault Sync & Key Decryption: On host connection, the required SSH private key is decrypted on-demand into memory.
  2. In-Process Agent: WardenSSH serves an ssh-agent protocol server on a local pipe/socket (\\.\pipe\wardenssh-agent on Windows, unix socket on Linux/macOS).
  3. Execution: WardenSSH sets SSH_AUTH_SOCK and spawns ssh, enabling public-key authentication without writing key files to the filesystem.

πŸš€ Installation

Prerequisites
  • Go 1.26+
  • OpenSSH client (ssh) installed and available in your PATH.
Installing via go install

The easiest way to install the latest release:

go install github.com/ac-kurniawan/wardenssh@latest

Verify the installed version:

wardenssh -version

Alternatively, clone the repository and build manually:

git clone https://github.com/ac-kurniawan/wardenssh.git
cd wardenssh
go build -o wardenssh .

🏁 Quick Start

Launch WardenSSH by running:

wardenssh

On first launch, WardenSSH will guide you through setting up your Bitwarden or Vaultwarden vault connections.

--no-keyring Fallback

If running in a headless environment without an OS keyring service available, use the --no-keyring flag to prompt for master passwords interactively on launch:

wardenssh --no-keyring

βš™οΈ Configuration

Configuration is stored in ~/.ssh/wardenssh.json. This file contains only non-sensitive preferences and connection parameters. No secrets or tokens are stored in this file.

{
  "vaults": [
    {
      "name": "personal",
      "server": "https://vw.example.com",
      "email": "user@example.com"
    },
    {
      "name": "work",
      "server": "https://vaultwarden.company.com",
      "email": "employee@company.com"
    }
  ],
  "custom_fields": {
    "host": "host",
    "user": "user",
    "port": "port",
    "proxyjump": "proxyjump"
  },
  "keyring": true
}
Bitwarden Vault Item Structure

To have an SSH Key item from Bitwarden/Vaultwarden appear in your WardenSSH host list:

  1. Create an item of type SSH Key (Type 5) in your vault.
  2. Store your private key in the standard SSH Key field.
  3. Add a Custom Field named host (value: target hostname or IP address).
  4. (Optional) Add Custom Fields for user, port, and proxyjump.

⌨️ Controls & Shortcuts

Host List (left pane)
Key / Shortcut Action
↑ / ↓ Navigate host list
Enter Connect to selected host
Tab Cycle source filter scope (All β†’ Vaults β†’ ~/.ssh/config)
Type any text Fuzzy filter hosts
Esc Clear filter β€” or open the quit confirmation modal when the filter is empty
q / Ctrl+C Open the exit confirmation modal
Ctrl+B Move focus to the terminal pane (when a session is running)
Terminal pane (right)
Key / Shortcut Action
Mouse click-drag Select terminal text; copied to the OS clipboard on release
Ctrl+C (with a selection) Copy the selection to the OS clipboard
Ctrl+C (no selection) Forwarded to the remote shell as SIGINT
Ctrl+B Return focus to the host list (session keeps running)
Esc Forwarded to the remote shell (e.g. exits insert mode in vim)
All other keys Forwarded to the remote shell

Copy reaches the OS clipboard via the native Wayland/X11 tool (wl-copy/xclip/xsel) when available, falling back to the OSC 52 escape sequence. On Windows the Win32 clipboard API is used. Terminals built on VTE (e.g. GNOME Terminal) do not support OSC 52, so copy there requires wl-clipboard/xclip to be installed.

Sessions
Action Result
Enter on a new host Opens a new session in the right pane; previous sessions keep running in the background
Enter on the active host Opens a disconnect confirmation modal (y/Enter = disconnect, n/Esc = cancel)
Enter on a background host Switches the right pane to that session (no duplicate spawn)
Session exits Only that host's green dot clears; the most recent remaining session becomes active
Modals
Key Action
k / Enter Kill all sessions & quit
d Detach sessions & quit
c / Esc Cancel / dismiss

πŸ”’ Security Model

WardenSSH is built with strict zero-trust local hygiene:

  • Zero-Disk-Footprint: Private keys reside only in vault storage at rest and in volatile process RAM during active sessions. Keys are never written to ~/.ssh/, /tmp, or any local disk file.
  • In-Memory Passphrases: Key passphrases are prompted interactively and cached only in session memory.
  • Secure Keyring Auth: Vault session refresh tokens are saved in OS-level credential stores (Windows Credential Manager, macOS Keychain, Linux Secret Service).
  • Master Password Required Each Launch: A refresh token alone cannot derive the vault symmetric key, so WardenSSH always prompts for the master password on startup.
  • Read-Only SSH Config: WardenSSH parses ~/.ssh/config as a read-only data source and never modifies your local SSH configuration files.
  • No Disk Logging: Diagnostics and errors are written strictly to stderr. No key material, hostnames, or connection metadata are logged to disk.

🌐 Cross-Platform Support

OS Agent Socket / Pipe OS Keyring Backend PTY Engine
Linux Unix Domain Socket Secret Service API / libsecret go-pty
macOS Unix Domain Socket macOS Keychain go-pty
Windows Named Pipe (\\.\pipe\...) Windows Credential Manager ConPTY (go-pty)

πŸ§ͺ Testing

The CI pipeline (go test ./...) runs on every push to main across Linux, macOS, and Windows (see .github/workflows/test.yml):

go build ./...   # compile
go vet ./...     # static checks
go test ./...    # all tests

Key test areas:

  • Agent protocol β€” every message type (list, sign, add, remove) plus malformed/oversized inputs (go test -run TestAgent).
  • Crypto β€” Bitwarden test vectors, byte-identical to bw CLI output (go test -run TestCrypto).
  • Vault client β€” mock-server tests for login/sync (go test -run TestVault).
  • TUI β€” model state transitions, multi-session pane lifecycle, quit/disconnect modals.

The e2e harness (e2e/) drives the real binary via tmux against a live Vaultwarden + sshd and is run manually β€” it requires infrastructure that CI does not provision.


πŸ“„ License

This project is licensed under the MIT License.

Documentation ΒΆ

Overview ΒΆ

Command wardenssh is the WardenSSH launcher entrypoint. v0 wiring:

  • load ~/.ssh/wardenssh.json (non-secret config; first run -> defaults)
  • build the merged host list from ~/.ssh/config (file source) and the vault client (real vault auth via TUI setup modal, or FakeClient when no vaults are configured)
  • start the in-process ssh-agent on a platform pipe and run the tview/tvxterm launcher

Directories ΒΆ

Path Synopsis
cmd
capture command
internal
app
Package app wires WardenSSH's subsystems together at the front door: it builds the launcher's merged host list from the two sources β€” a parsed ~/.ssh/config (file source, read-only per Q6/A) and the vault client's sources (Q10/C, Q16/B multi-vault) β€” applying the no-dedup + source-label policy (Q11/C) and the wildcard exclusion for ssh_config defaults.
Package app wires WardenSSH's subsystems together at the front door: it builds the launcher's merged host list from the two sources β€” a parsed ~/.ssh/config (file source, read-only per Q6/A) and the vault client's sources (Q10/C, Q16/B multi-vault) β€” applying the no-dedup + source-label policy (Q11/C) and the wildcard exclusion for ssh_config defaults.
config
Package config loads and saves ~/.ssh/wardenssh.json (the non-secret config, per .local/spec.md Q16/B).
Package config loads and saves ~/.ssh/wardenssh.json (the non-secret config, per .local/spec.md Q16/B).
connect
Package connect wires the launcher's ConnectMsg into the full connect flow: lazy-decrypt the vault key (Q8/C), load it into the in-process agent (Q19/B ref-counted), and spawn ssh via the session manager with SSH_AUTH_SOCK pointed at our agent pipe (Q4/B).
Package connect wires the launcher's ConnectMsg into the full connect flow: lazy-decrypt the vault key (Q8/C), load it into the in-process agent (Q19/B ref-counted), and spawn ssh via the session manager with SSH_AUTH_SOCK pointed at our agent pipe (Q4/B).
hosts
Package hosts holds the unified, source-merged host list that the launcher TUI renders (Q10/C dual-source, Q11/C no-dedup + source badges, Q18/iii live-session green dots, Q29/B fuzzy filter + source-scope cycling).
Package hosts holds the unified, source-merged host list that the launcher TUI renders (Q10/C dual-source, Q11/C no-dedup + source badges, Q18/iii live-session green dots, Q29/B fuzzy filter + source-scope cycling).
keyring
Package keyring provides cross-platform OS keyring storage for vault refresh tokens (Q7/D), using zalando/go-keyring (Windows Credential Manager, macOS Keychain, Linux Secret Service).
Package keyring provides cross-platform OS keyring storage for vault refresh tokens (Q7/D), using zalando/go-keyring (Windows Credential Manager, macOS Keychain, Linux Secret Service).
session
Package session implements the WardenSSH session manager (Q18/iii yield-and-switch): N concurrent child processes each on their own PTY, one active (foreground) at a time, background sessions drained into bounded ring buffers so memory does not grow unbounded while a session is hidden.
Package session implements the WardenSSH session manager (Q18/iii yield-and-switch): N concurrent child processes each on their own PTY, one active (foreground) at a time, background sessions drained into bounded ring buffers so memory does not grow unbounded while a session is hidden.
sshagent
Package sshagent implements WardenSSH's in-process ssh-agent (see .local/spec.md): a keyring holding private keys in RAM, served over a pipe to ssh.exe.
Package sshagent implements WardenSSH's in-process ssh-agent (see .local/spec.md): a keyring holding private keys in RAM, served over a pipe to ssh.exe.
sshconfig
Package sshconfig reads ~/.ssh/config (read-only in v0 per .local/spec.md Q6/A) and extracts launchable host entries for the host-list source "file" (Q10/C, Q27/C).
Package sshconfig reads ~/.ssh/config (read-only in v0 per .local/spec.md Q6/A) and extracts launchable host entries for the host-list source "file" (Q10/C, Q27/C).
tviewui
Package tviewui implements the WardenSSH launcher TUI using tview + tcell + tvxterm (embedded terminal emulator).
Package tviewui implements the WardenSSH launcher TUI using tview + tcell + tvxterm (embedded terminal emulator).
vault
Package vault is the seam between WardenSSH and the BitWarden/VaultWarden vault (Subsystem 2, .local/plan.md).
Package vault is the seam between WardenSSH and the BitWarden/VaultWarden vault (Subsystem 2, .local/plan.md).
vaultadapter
Package vaultadapter bridges the vaultclient (BitWarden API + crypto) into the vault.Source/Client interfaces that app.BuildHostList and the TUI consume.
Package vaultadapter bridges the vaultclient (BitWarden API + crypto) into the vault.Source/Client interfaces that app.BuildHostList and the TUI consume.
vaultclient
Package vaultclient: auth.go implements the password-grant login flow and the vault sync, decrypting the user's Protected Symmetric Key + RSA private key from the token response.
Package vaultclient: auth.go implements the password-grant login flow and the vault sync, decrypting the user's Protected Symmetric Key + RSA private key from the token response.
vaultcrypto
Package vaultcrypto: cipher.go implements the BitWarden encrypted-string format "2.<base64(iv||ciphertext||mac)>" with AES-256-CBC + HMAC-SHA256 (encType=2).
Package vaultcrypto: cipher.go implements the BitWarden encrypted-string format "2.<base64(iv||ciphertext||mac)>" with AES-256-CBC + HMAC-SHA256 (encType=2).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL