wardenssh

command module
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 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
Esc / Ctrl+B Return focus to the host list (session keeps running)
All other keys Forwarded to the remote shell (including Ctrl+C = SIGINT)
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
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).
spike

Jump to

Keyboard shortcuts

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