Skip to content

Command-line client (tessera-cli)

tessera-cli is a standalone command-line client for Tessera. It lets you list targets, connect to them, and run background tunnels for SSH, databases, Kubernetes and RDP with no desktop app — credentials are still injected server-side and every session is audited. It’s the recommended way to use Tessera from WSL, remote servers, or CI.

Your controller serves an install script; one line, no sudo (installs to ~/.local/bin):

Terminal window
curl -fsSL https://tessera.example.com/downloads/install.sh | sh

Replace tessera.example.com with your controller’s address. The script detects your OS and architecture (Linux and macOS, amd64/arm64), downloads the matching binary, and prints the line to add ~/.local/bin to your PATH if it isn’t already.

Other install options
  • Different directory: TESSERA_BIN_DIR=~/bin curl -fsSL …/install.sh | sh
  • Point at a specific controller: TESSERA_BASE_URL=https://tessera.example.com/downloads sh install.sh
  • Windows: the desktop installer already ships tessera-cli.exe next to the app.

The cleanest way to sign a headless CLI in is a personal access token. Create one in the console under Access keys → New token and copy the tpat_… secret (shown once). Then:

Terminal window
tessera-cli login --url https://tessera.example.com --token tpat_xxxxxxxx

The token authenticates as your user and inherits all your access grants; it’s revocable and can carry an expiry. See Access tokens for the rules (one token per account, device-bound).

Username and password also works (add --insecure only against a controller with a self-signed certificate):

Terminal window
tessera-cli login --url https://tessera.example.com --user alice --pass ''

tessera-cli whoami shows who you are; tessera-cli logout forgets the saved login.

Terminal window
tessera-cli list # everything you can access
tessera-cli ssh list # only SSH targets
tessera-cli db list # only databases
tessera-cli k8s list # only Kubernetes clusters
tessera-cli rdp list # only RDP hosts

Add --json for scripting. Each row shows the name, kind, address, your access mode, and the target id.

connect attaches you to a target immediately. The kind is auto-detected, or scope it explicitly. A handy shortcut: tessera-cli ssh <name> is the same as ssh connect <name>.

Terminal window
tessera-cli ssh prod-web # interactive SSH shell
tessera-cli k8s connect prod-cl # opens a subshell with KUBECONFIG already set
tessera-cli db connect prod-db # opens a local port and prints the psql/mysql command
tessera-cli rdp connect win-box # opens a local port and prints host + credentials
  • SSH drops you into the remote shell; exit to close the tunnel.
  • Kubernetes writes a kubeconfig and launches a subshell with KUBECONFIG exported — exit to tear it down.
  • Databases print a ready-to-paste psql/mysql command and keep the port open until you press Ctrl+C.
  • RDP prints 127.0.0.1:<port> plus the injected credentials — point a remote-desktop client at it.

Targets can be given by name, by name.tessera.local, or by id.

Start a tunnel that keeps running after you close the terminal, then manage it:

Terminal window
tessera-cli init prod-db # start a detached tunnel (stable port per target)
tessera-cli active # list running tunnels (id, target, kind, listen, uptime, pid)
tessera-cli kill db-prod-db # stop one (by id, target name, or `all`)

init assigns each target a stable local port derived from its name, so the same target always lands on the same port and three databases get three distinct ports. The bound port is always printed and shown in active; pin an exact one with --listen 127.0.0.1:PORT. For Kubernetes, init also writes a kubeconfig and prints the export KUBECONFIG=… line.

Prefer a foreground tunnel that lives only as long as the terminal? Use forward — it opens the port, prints it, and holds it open until you press Ctrl+C:

Terminal window
tessera-cli forward prod-db # foreground tunnel, auto-picked port
tessera-cli forward prod-db --listen 127.0.0.1:5432 # pin the local port
tessera-cli forward prod-cl --kubeconfig ./kube.yaml # write the kubeconfig here (Kubernetes)

Most commands accept short aliases:

CanonicalAliases
listls
kubernetesk8s, kube
databasedb
activeps, tunnels
killstop, down
initup, start

Prefer plain ssh <name>? Install a one-time wildcard config:

Terminal window
tessera-cli ssh-config --install # writes ~/.ssh/config.d/tessera + an Include
ssh prod-web.tessera.local

The installed config routes *.tessera.local through tessera-cli, which resolves each target from the hostname at connect time — so it never needs regenerating when targets change. Use --domain my.company to change the suffix.

On Windows, the desktop app is a GUI process and can’t act as an SSH ProxyCommand — the installed config routes through tessera-cli.exe instead, which the desktop installer ships next to the app. Nothing to configure; just note that removing the CLI breaks ssh *.tessera.local.

The desktop app is native-only. To use Tessera from inside WSL, install tessera-cli in your WSL distribution and log in exactly as above (Install, Authenticate) — everything runs in WSL’s own network, no host/loopback tricks.

login writes the controller URL, token and TLS setting to a 0600 config.json, located per platform (Go’s os.UserConfigDir):

  • Linux~/.config/tessera/config.json
  • macOS~/Library/Application Support/tessera/config.json
  • Windows%AppData%\tessera\config.json

If no CLI config is present, tessera-cli falls back to the signed-in desktop account. Working files (known_hosts, generated kubeconfigs, tunnel state) live under ~/.tessera/.

  • command not found~/.local/bin isn’t on your PATH; add it (the installer prints the exact line).
  • 401 on connect — token expired or access revoked. Re-run tessera-cli login with a fresh token; if it persists, your grant may have been removed (ask an admin or request just-in-time access).
  • this access token is bound to another device — see Access tokens → If a token stops working.
  • Self-signed TLS error — pass --insecure to login, only against a controller you trust.
  • Writes refused — your grant is read-only, or an admin downgraded your live session. See Read-only sessions.