SSH
Connect to an agent
tealc ssh [AGENT_NAME] is a wrapper around SSH that automatically handles authentication and proxy setup to connect you to an agent through the server.
Quick usage
tealc list
tealc ssh AGENT_NAME
Embedded shell
The embedded shell is a simple, stateful REPL implemented inside the agent. It is useful when no native shell is available or when the operator wants predictable in-memory command behavior. It does not launch a separate shell binary for the REPL itself.
The embedded command set is designed to avoid relying on the target’s system
binaries for common shell work. Commands such as ls, cat, grep, cp,
and tar run inside the agent process, which reduces external process launches
and can make routine shell activity less conspicuous to process-level monitoring
(it is not an invisibility or evasion guarantee).
This also makes the embedded shell useful in constrained environments such as distroless containers, minimal images, recovery systems, and hosts where a standard shell or core utilities are unavailable. Filesystem access, permissions, kernel interfaces, and platform-specific features still depend on what the target environment provides.
Select it for one SSH connection with --shell:
tealc ssh --shell=embedded AGENT_NAME
Execution modes
embedded combines the in-memory command handlers with normal binary lookup through PATH:
tealc ssh --shell=embedded AGENT_NAME
embedded-only disables PATH lookup. Bare command names must be implemented in memory, while explicitly qualified paths remain available:
tealc ssh --shell=embedded-only AGENT_NAME
For example, in embedded-only:
ls # uses the embedded handler
/bin/ls # executes the explicitly requested binary
python3 # rejected unless implemented as an embedded handler
The embedded-only name refers specifically to PATH lookup. It does not prohibit an explicitly requested external path. For example, /bin/ls or ./tool can still be executed when the operating system permits it. This is useful when a command is unavailable as an embedded handler but its exact path is known.
REPL features
The embedded REPL supports:
- shell variables and state across commands;
cdand a working-directory-aware prompt;- pipelines and redirects supported by the embedded interpreter;
- command history and completion;
- the
helpcommand, which lists registered embedded handlers; man COMMAND, which shows mvdan’s native builtin help or a structured mini-man page for an embedded command, including its synopsis and supported flags; and- persistent sessions when used with
--session.
For example:
$ man ls
NAME
ls - List directory contents.
SYNOPSIS
ls [-a d F h l p Q R S] [FILE]...
DESCRIPTION
List directory contents.
For shell builtins such as break, cd, and echo, man delegates to the
mvdan shell’s native help database. For registered u-root commands and Goauld
fallback commands, it displays the embedded mini-man synopsis.
The prompt has this form:
[Agent_NAME]@goashell:/current/working/directory$
Limitations
Embedded mode does not provide a PTY to external programs. Full-screen or terminal-dependent programs such as Vim, top, htop, tmux, and interactive terminal UIs are unsupported. Use the default native backend for those programs.
The embedded backend is selected per SSH connection and is not an agent-wide configuration setting. When creating a persistent session, the selected backend becomes part of that session; attaching to an existing session does not change its backend.
Add standard SSH options after the agent name:
tealc ssh AGENT_NAME -L 127.0.0.1:8080:127.0.0.1:8080
The detailed command expansion below is useful when debugging or integrating with another SSH tool. Most operators do not need to run it manually.
How tealc ssh works
Generated SSH command
The following is the full command tealc ssh builds and executes on your behalf. It is shown for debugging and integration; do not type it manually.
# Environment setup and authentication
env SSH_ASKPASS_REQUIRE=force \
SSH_ASKPASS=/usr/local/bin/tealc \
TEALC_TYPE=agent \
TEALC_SERVER=http://localhost \
TEALC_SSH_SERVER=localhost:2222 \
TEALC_ACCESS_TOKEN=ACCESS_TOKEN_REPLACE_ME \
TEALC_ADMIN_TOKEN= \
TEALC_AGENT=user@hostname1 \
TEALC_VERBOSE=0 \
TEALC_QUIET=false \
TEALC_CONFIG_FILE= \
TEALC_PROMPT=true \
# Main SSH invocation with security options and proxy forwarding
ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null \
-oPubkeyAuthentication=no -oPreferredAuthentications=password \
-oLogLevel=ERROR -oExitOnForwardFailure=no \
-oNumberOfPasswordPrompts=1 \
# ProxyCommand for agent connection through server
-oProxyCommand='env SSH_ASKPASS_REQUIRE=force \
SSH_ASKPASS=/usr/local/bin/tealc \
TEALC_TYPE=otp \
TEALC_SERVER=http://localhost \
TEALC_SSH_SERVER=localhost:2222 \
TEALC_ACCESS_TOKEN=ACCESS_TOKEN_REPLACE_ME \
TEALC_ADMIN_TOKEN= \
TEALC_AGENT=user@hostname1 \
TEALC_VERBOSE=0 \
TEALC_QUIET=false \
TEALC_CONFIG_FILE= \
TEALC_PROMPT=true \
ssh -oClearAllForwardings=no -oStrictHostKeyChecking=no \
-oUserKnownHostsFile=/dev/null -oPubkeyAuthentication=no \
-oPreferredAuthentications=password -oLogLevel=ERROR \
-oExitOnForwardFailure=no -oNumberOfPasswordPrompts=1 \
-p2222 -W127.0.0.1:49521 -L1080:127.0.0.1:49524 \
-L3128:127.0.0.1:54079 user@hostname1@localhost' \
# Target agent connection
user@hostname1@39fce32832f3375a409d99a13a4f0c77
Default proxy forwarding
By default, tealc ssh automatically forwards the agent’s proxies (SOCKS, HTTP, MITM HTTP, and WireGuard) locally if they are exposed by the agent. See Proxies for details.
Custom SSH options
You can pass additional arguments to the underlying SSH command. These must be placed at the end of the command line, after the agent name:
tealc ssh [AGENT_NAME] -L "127.0.0.1:8080:127.0.0.1:8080"
By default, tealc ssh makes two chained SSH connections. The first connects to the Goauld server and sets up the proxy forwards. The second, the actual ssh process you see run, uses the first as its ProxyCommand and connects through it to the agent’s own SSHD. Additional arguments are appended to this second connection, so they only apply when it’s actually established, i.e. when --ssh is active (enabled by default for tealc ssh).
With --no-ssh, only the first connection (to the server) is made, purely to forward the proxy ports. The agent’s SSHD is never contacted directly. Since there is no second connection, additional arguments are dropped.
Connecting over WebSocket
If the server is behind a reverse proxy or firewall that only allows HTTP(S) egress, pass --ws to tunnel SSH traffic over a WebSocket instead of a raw TCP connection to --ssh-server. The WebSocket is dialed against --server’s address (the same one /manage/ and /admin/ use), with its scheme swapped to ws/wss; --ssh-server is not used at all in this mode. All SSH traffic (both the outer/inner ssh subprocess connections tealc ssh builds, and tealc’s own internal SSH client used by kill/reset/delete/clipboard/wireguard) then tunnels through the server’s /ssh-ws/ endpoint instead of dialing the sshd port directly.
This requires the server to be started with --ssh-websocket, see Reverse proxy support in Access control.
tealc bind and tealc embed-server always route their own SSH access through an equivalent in-process WebSocket bridge, whether or not --ws is passed: see Agent binding and Embed server. --ws here is specifically the opt-in for tealc ssh (and the other commands sharing its SSH connection path) to reach a separately deployed server the same way.
SSH options
Global client options such as --server, --access-token, --ws, and --wait-timeout are shared by all commands. See the configuration reference for the complete common option list.
SSH-specific options include:
--[no-]socks Forward the agent's SOCKS proxy to the local host ($TEALC_SOCKS).
--[no-]http Forward the agent's HTTP proxy to the local host ($TEALC_HTTP).
--[no-]http-mitm Forward the agent's HTTP MITM proxy to the local host ($TEALC_HTTP_MITM).
--[no-]wg Forward the agent's WireGuard interface to the local host ($TEALC_WG).
--socks-port=1080 Local port to bind the SOCKS proxy ($TEALC_SOCKS_PORT).
--http-port=3128 Local port to bind the HTTP proxy ($TEALC_HTTP_PORT).
--http-mitm-port=3129 Local port to bind the HTTP MITM proxy ($TEALC_HTTP_MITM_PORT).
--wg-port=51820 Local port to bind the WireGuard proxy ($TEALC_WG_PORT).
--[no-]ssh Connect directly to the agent's SSH service ($TEALC_SSH).
--[no-]print Print the generated SSH command instead of executing it ($TEALC_PRINT).
--proxy Use direct STDIN/STDOUT mode for ProxyCommand compatibility ($TEALC_PROXY).
--log Record the SSH session to a log file ($TEALC_LOG).
--session Select and attach to a persistent shell session ($TEALC_SESSION).
--shell=auto Remote shell backend: auto, embedded, or embedded-only ($TEALC_SHELL).
-o, --ssh-opts=SSH-OPTS,... Additional SSH options (equivalent to '-o')
-F, --ssh-config-file=STRING Path to an SSH configuration file to use ($TEALC_SSH_CONFIG_FILE).
SSH configuration file behavior differs across commands:
tealc ssh: Uses config file only to resolve agent namestealc scp: Passes config file directly to the underlying scp command (see SCP)
tealc ssh -V/--version is a special case: it prints the version of the system’s ssh client instead of tealc’s own version.
If the agent password is wrong, the client automatically re-prompts for it and retries, up to 4 attempts in total, before giving up. This applies to tealc ssh, scp, rsync, rclone, jump, and bind (which reuses the same SSH connection path), as well as tealc clip get/set, kill, and reset.
--save-password writes the prompted password to the client’s configuration file in cleartext, under a top-level agent-password: map keyed by agent name:
agent-password:
user@hostname1: [password]
On later runs, if the target agent is found in this map, the password prompt is skipped automatically. This also applies when -M/--control-master is used: if there is no already-open control connection yet, the client falls back to a saved or explicitly supplied (-P) password instead of prompting.