Persistent shell sessions

Restore agent shell sessions after an SSH disconnect

The client can create persistent shell sessions on an agent. The shell runtime remains alive when the operator’s SSH connection is interrupted, allowing a later connection to continue the same shell and working directory. Native sessions retain their PTY; embedded sessions retain a line-oriented REPL and do not provide a PTY for external programs.

Prerequisites

Persistent sessions must be enabled on the agent, and the client must be able to open a normal SSH session first.

Quick usage

Run tealc ssh AGENT --session. The interactive picker lists running sessions and a [NEW] entry. Choosing [NEW] creates and attaches to a shell; choosing a detached session resumes it. Choosing a session that already has a writable attachment opens a read-only observer instead. If no sessions exist, the client automatically creates and attaches to a new session without showing an empty picker.

tealc ssh AGENT --session

Select the embedded REPL per connection with --shell:

tealc ssh --shell=embedded --session AGENT
tealc ssh --shell=embedded-only --session AGENT

The selected backend applies when a new persistent session is created. Attaching to an existing session continues using that session’s original backend.

Attachment behavior

Only one writable attachment is allowed for a session. Up to 32 read-only observers can receive its recent output and live output, but cannot send input or resize the session. Session IDs are generated by the agent and displayed when a new session is attached.

Agent configuration

Persistent sessions are enabled by default. Use these agent settings to disable the feature, observers, or retained output:

sessions-enabled: true
session-observers: true
session-history-size: 4194304 # bytes; 0 disables output history

The default output history is 4 MiB per session; older output is discarded first. A shell that exits remains listed for ten minutes, but cannot be attached again.

Detach or terminate

While attached, press Ctrl-g followed by d to detach without terminating the shell. Ctrl-g followed by Ctrl-d is also accepted. Ctrl-D on its own and exit still terminate the shell itself. If the key after Ctrl-g is not d or Ctrl-d, the prefix is forwarded normally to the remote application.

Embedded sessions display prompts in this form:

[Agent_NAME]@goashell:/current/working/directory$

The help command lists the available in-memory command handlers. Use man COMMAND for command documentation: mvdan builtins use mvdan’s native help, while embedded u-root and fallback commands show a structured page with NAME, SYNOPSIS, and DESCRIPTION sections, including supported flags.

These in-memory handlers are intended to provide a pseudo-shell without requiring the target to have a complete userland installed. This is especially useful in distroless or otherwise constrained containers. Because common commands execute inside the agent rather than as separate host processes, the approach can also reduce process-level visibility, but it should not be treated as a security or detection-evasion guarantee.

In embedded-only mode, PATH lookup is disabled, but explicitly qualified paths such as /bin/ls and ./tool remain allowed. Bare commands are restricted to registered embedded handlers.

Limitations

Sessions are kept in the agent process. They are terminated when that process restarts or shuts down; they are not persisted across an agent restart. Retained output consumes agent memory up to the configured history size for each session and can contain sensitive terminal content.