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.
Install
Section titled “Install”Your controller serves an install script; one line, no sudo (installs to ~/.local/bin):
curl -fsSL https://tessera.example.com/downloads/install.sh | shReplace 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.exenext to the app.
Authenticate
Section titled “Authenticate”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:
tessera-cli login --url https://tessera.example.com --token tpat_xxxxxxxxThe 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):
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.
List targets
Section titled “List targets”tessera-cli list # everything you can accesstessera-cli ssh list # only SSH targetstessera-cli db list # only databasestessera-cli k8s list # only Kubernetes clusterstessera-cli rdp list # only RDP hostsAdd --json for scripting. Each row shows the name, kind, address, your access mode, and the
target id.
Connect
Section titled “Connect”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>.
tessera-cli ssh prod-web # interactive SSH shelltessera-cli k8s connect prod-cl # opens a subshell with KUBECONFIG already settessera-cli db connect prod-db # opens a local port and prints the psql/mysql commandtessera-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
KUBECONFIGexported — exit to tear it down. - Databases print a ready-to-paste
psql/mysqlcommand and keep the port open until you pressCtrl+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.
Background tunnels
Section titled “Background tunnels”Start a tunnel that keeps running after you close the terminal, then manage it:
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:
tessera-cli forward prod-db # foreground tunnel, auto-picked porttessera-cli forward prod-db --listen 127.0.0.1:5432 # pin the local porttessera-cli forward prod-cl --kubeconfig ./kube.yaml # write the kubeconfig here (Kubernetes)Command aliases
Section titled “Command aliases”Most commands accept short aliases:
| Canonical | Aliases |
|---|---|
list | ls |
kubernetes | k8s, kube |
database | db |
active | ps, tunnels |
kill | stop, down |
init | up, start |
SSH via native ssh
Section titled “SSH via native ssh”Prefer plain ssh <name>? Install a one-time wildcard config:
tessera-cli ssh-config --install # writes ~/.ssh/config.d/tessera + an Includessh prod-web.tessera.localThe 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.
Using Tessera from WSL
Section titled “Using Tessera from WSL”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.
Config file
Section titled “Config file”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/.
Troubleshooting
Section titled “Troubleshooting”command not found—~/.local/binisn’t on yourPATH; add it (the installer prints the exact line).401on connect — token expired or access revoked. Re-runtessera-cli loginwith 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
--insecuretologin, only against a controller you trust. - Writes refused — your grant is read-only, or an admin downgraded your live session. See Read-only sessions.
We would like to count visits with Google Analytics, which needs a cookie. Nothing is loaded and nothing is stored unless you accept. What this sets.