termmux

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Apr 3, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultTERM      = "xterm-256color"
	DefaultCOLORTERM = "truecolor"
	DefaultCOLORFGBG = "15;0" // white on black (dark theme)
)
View Source
const (
	// SubscriptionBufferSize is the number of output chunks buffered per subscriber.
	// At ~4KB per chunk, this allows ~256KB of buffered output before drops.
	SubscriptionBufferSize = 64

	// MaxScrollbackSnapshotBytes caps the scrollback snapshot sent to subscribers.
	// At 4MB, this fits within ConnectRPC's default 16MB message limit while
	// providing substantial history (~40K lines of typical terminal output).
	MaxScrollbackSnapshotBytes = 4 * 1024 * 1024
)
View Source
const InputBurstBytes = 64 * 1024

InputBurstBytes is the burst allowance for input (paste operations).

View Source
const MaxInputRateBytes = 10 * 1024

MaxInputRateBytes is the maximum sustained input rate in bytes per second.

View Source
const MaxTerminalChunkSize = 64 * 1024

MaxTerminalChunkSize is the maximum size of a single TerminalOutput message. Larger PTY reads are split into multiple messages.

Variables

View Source
var ErrPTYWriteTimeout = errors.New("pty write timed out (child may be hung)")

ErrPTYWriteTimeout is returned when a write to the PTY master times out, indicating the child process is likely hung.

Functions

func TerminalEnvDefaults

func TerminalEnvDefaults() map[string]string

TerminalEnvDefaults returns the environment variables to set for headless child processes. These are merged with (but overridden by) any driver-specific or user-specified env vars.

Types

type Client

type Client struct {
	ID string
	// contains filtered or unexported fields
}

Client represents a connected client that can receive PTY output from a session.

func NewClient

func NewClient(id string) *Client

NewClient creates a new client with a buffered output channel.

func (*Client) Close

func (c *Client) Close()

Close marks the client as closed and closes the output channel.

func (*Client) Output

func (c *Client) Output() <-chan []byte

Output returns the read-only channel for receiving PTY output.

func (*Client) Send

func (c *Client) Send(data []byte)

Send sends data to the client's output channel. Non-blocking: drops data if the client's buffer is full.

type ClientManager

type ClientManager struct {
	// contains filtered or unexported fields
}

ClientManager handles multi-client attach/detach for a session.

func NewClientManager

func NewClientManager() *ClientManager

NewClientManager creates a new client manager.

func (*ClientManager) Attach

func (cm *ClientManager) Attach(id string) *Client

Attach adds a client and returns it. If a client with the same ID already exists, the old one is closed and replaced.

func (*ClientManager) CloseAll

func (cm *ClientManager) CloseAll()

CloseAll closes and removes all clients.

func (*ClientManager) Count

func (cm *ClientManager) Count() int

Count returns the number of attached clients.

func (*ClientManager) Detach

func (cm *ClientManager) Detach(id string)

Detach removes and closes a client by ID.

func (*ClientManager) FanOut

func (cm *ClientManager) FanOut(data []byte)

FanOut sends data to all attached clients. Non-blocking per client.

func (*ClientManager) List

func (cm *ClientManager) List() []string

List returns the IDs of all attached clients.

type ConfigDirManager

type ConfigDirManager struct {
	BaseDir string
}

ConfigDirManager manages per-session config directories for 3rd party agent drivers. Config directories contain authentication tokens, settings, and injected files (like CLAUDE.md) that drivers need at launch time.

func NewConfigDirManager

func NewConfigDirManager(baseDir string) *ConfigDirManager

NewConfigDirManager creates a new config directory manager.

func (*ConfigDirManager) Cleanup

func (m *ConfigDirManager) Cleanup(sessionID string) error

Cleanup removes the config directory for a session.

func (*ConfigDirManager) EnsureDir

func (m *ConfigDirManager) EnsureDir(sessionID string) (string, error)

EnsureDir creates the config directory if it doesn't exist and returns the path.

func (*ConfigDirManager) InjectFile

func (m *ConfigDirManager) InjectFile(sessionID, relativePath string, data []byte) error

InjectFile writes a file into the session's config directory. This is used by orchestrators to inject CLAUDE.md, agents.md, MCP configs, etc.

func (*ConfigDirManager) StablePath

func (m *ConfigDirManager) StablePath(sessionID string) string

StablePath returns the deterministic config directory path for a session. The same session ID always resolves to the same path, which is critical for auth token persistence across pause/resume cycles.

type EventSourceConfig

type EventSourceConfig struct {
	// OTEL callbacks — set by the driver's event handler
	OtelCallbacks otelserver.Callbacks

	// Session log path and callback — set by the driver
	SessionLogPath   string
	OnSessionLogLine func(line []byte)

	// Hook event handler — set by the driver
	OnHookEvent func(eventName string, payload []byte) []monitor.AgentEvent
}

EventSourceConfig configures the event sources for a session.

type ManagerOption

type ManagerOption func(*SessionManager)

ManagerOption configures the SessionManager.

func WithMaxSessions

func WithMaxSessions(n int) ManagerOption

WithMaxSessions sets the maximum number of concurrent sessions.

type Session

type Session struct {
	ID     string
	Config SessionConfig
	VT     *VirtualTerminal
	// contains filtered or unexported fields
}

Session represents a terminal multiplexer session with a PTY, an agent driver, and multi-client support.

func NewSession

func NewSession(id string, cfg SessionConfig) *Session

NewSession creates a new session but does not start it.

func (*Session) Attach

func (s *Session) Attach(clientID string) *Client

Attach adds a client to the session and returns it.

func (*Session) ClientCount

func (s *Session) ClientCount() int

ClientCount returns the number of attached clients.

func (*Session) CreatedAt

func (s *Session) CreatedAt() time.Time

CreatedAt returns the session creation time.

func (*Session) Detach

func (s *Session) Detach(clientID string)

Detach removes a client from the session.

func (*Session) ExitNotify

func (s *Session) ExitNotify() <-chan struct{}

ExitNotify returns a channel that is closed when the session exits.

func (*Session) IsPaused

func (s *Session) IsPaused() bool

IsPaused returns whether the session is currently paused.

func (*Session) IsRunning

func (s *Session) IsRunning() bool

IsRunning returns whether the session's child process is still running.

func (*Session) Monitor

func (s *Session) Monitor() *monitor.AgentMonitor

Monitor returns the session's agent monitor.

func (*Session) Pause

func (s *Session) Pause() error

Pause marks the session as paused. This is a controller-level gate that prevents new interactions while paused. The PTY child process continues running — pause/resume operates at the interaction level, not the process level.

func (*Session) Resize

func (s *Session) Resize(rows, cols int)

Resize changes the PTY size.

func (*Session) Resume

func (s *Session) Resume() error

Resume unpauses a paused session, allowing new interactions.

func (*Session) Start

func (s *Session) Start(ctx context.Context) error

Start launches the child process in a PTY and begins piping output.

func (*Session) StartEventSources

func (s *Session) StartEventSources(cfg EventSourceConfig) (*SessionEventSources, error)

StartEventSources initializes and starts the event sources for a session. The OTEL server must be started before launching the child process so that its endpoint can be injected into the child's environment.

func (*Session) Stop

func (s *Session) Stop()

Stop gracefully stops the session.

func (*Session) SubscribeTerminal

func (s *Session) SubscribeTerminal(subscriberID string) *TerminalSubscription

SubscribeTerminal creates a new terminal output subscription. The subscriber receives a scrollback snapshot of recent output and then live raw PTY output chunks via the Chunks channel.

func (*Session) TerminalSubscriberCount

func (s *Session) TerminalSubscriberCount() int

TerminalSubscriberCount returns the number of active terminal subscribers.

func (*Session) UnsubscribeTerminal

func (s *Session) UnsubscribeTerminal(subscriberID string)

UnsubscribeTerminal removes a terminal output subscription.

func (*Session) Wait

func (s *Session) Wait()

Wait blocks until the session exits.

func (*Session) WritePTY

func (s *Session) WritePTY(data []byte) (int, error)

WritePTY writes to the session's PTY with timeout.

type SessionConfig

type SessionConfig struct {
	DriverType  string
	Command     string
	Args        []string
	CWD         string
	Env         map[string]string
	InitialRows int
	InitialCols int
}

SessionConfig configures a new session.

type SessionEventSources

type SessionEventSources struct {
	OtelServer    *otelserver.Server
	SessionTailer *sessionlog.Tailer
	// contains filtered or unexported fields
}

SessionEventSources holds the running event sources for a session.

func (*SessionEventSources) OtelEndpoint

func (ses *SessionEventSources) OtelEndpoint() string

OtelEndpoint returns the OTEL server endpoint URL for injection into the child process environment.

func (*SessionEventSources) Stop

func (ses *SessionEventSources) Stop()

Stop shuts down all event sources.

type SessionInfo

type SessionInfo struct {
	ID          string
	DriverType  string
	Command     string
	State       monitor.State
	SubState    monitor.SubState
	CreatedAt   time.Time
	ClientCount int
}

SessionInfo is a summary of a session's state for listing.

type SessionManager

type SessionManager struct {
	// contains filtered or unexported fields
}

SessionManager manages the lifecycle of terminal multiplexer sessions.

func NewSessionManager

func NewSessionManager(opts ...ManagerOption) *SessionManager

NewSessionManager creates a new session manager.

func (*SessionManager) Count

func (sm *SessionManager) Count() int

Count returns the number of sessions.

func (*SessionManager) Create

func (sm *SessionManager) Create(id string, cfg SessionConfig) (*Session, error)

Create creates a new session with the given configuration. The session is not started until Start is called on it.

func (*SessionManager) Get

func (sm *SessionManager) Get(id string) (*Session, error)

Get retrieves a session by ID.

func (*SessionManager) Kill

func (sm *SessionManager) Kill(id string) error

Kill stops and removes a session.

func (*SessionManager) List

func (sm *SessionManager) List() []SessionInfo

List returns info about all sessions, sorted by creation time.

func (*SessionManager) Shutdown

func (sm *SessionManager) Shutdown(timeout time.Duration) error

Shutdown gracefully stops all sessions.

type StreamTerminalRequest

type StreamTerminalRequest struct {
	SessionID string `json:"session_id"`
}

StreamTerminalRequest is the initial attach request from the client.

type TerminalAttached

type TerminalAttached struct {
	Rows       int    `json:"rows"`
	Cols       int    `json:"cols"`
	Scrollback []byte `json:"scrollback,omitempty"`
}

TerminalAttached is sent after successful subscription, including current dimensions and scrollback history for replay.

type TerminalClientMessage

type TerminalClientMessage struct {
	Attach *StreamTerminalRequest `json:"attach,omitempty"`
	Input  *TerminalInput         `json:"input,omitempty"`
	Resize *TerminalResize        `json:"resize,omitempty"`
}

TerminalClientMessage is a message from the client to the server.

type TerminalDetached

type TerminalDetached struct {
	Reason string `json:"reason"` // "session_ended", "kicked", "error"
}

TerminalDetached is sent when the session ends or the client is kicked.

type TerminalInput

type TerminalInput struct {
	Data []byte `json:"data"`
}

TerminalInput carries raw keystrokes from the client to the PTY.

type TerminalOutput

type TerminalOutput struct {
	Data []byte `json:"data"`
}

TerminalOutput carries raw PTY output (including ANSI sequences) to the client.

type TerminalResize

type TerminalResize struct {
	Rows int `json:"rows"`
	Cols int `json:"cols"`
}

TerminalResize carries terminal dimension changes from the client.

type TerminalServerMessage

type TerminalServerMessage struct {
	Attached *TerminalAttached `json:"attached,omitempty"`
	Output   *TerminalOutput   `json:"output,omitempty"`
	Detached *TerminalDetached `json:"detached,omitempty"`
}

TerminalServerMessage is a message from the server to the client.

type TerminalSubscription

type TerminalSubscription struct {
	ID     string
	Chunks chan []byte   // Buffered channel acts as bounded queue
	Done   chan struct{} // Closed when subscription is cancelled

	// Scrollback snapshot delivered on subscribe
	Scrollback []byte
	Rows, Cols int
}

TerminalSubscription is a per-subscriber output stream with bounded buffering. Each subscriber gets its own ring buffer of raw PTY output chunks. Slow consumers drop oldest chunks rather than blocking the output pipeline.

type VirtualTerminal

type VirtualTerminal struct {
	Ptm *os.File // PTY master
	Cmd *exec.Cmd
	Mu  sync.Mutex // Guards all terminal state and writes

	Rows, Cols int
	ChildRows  int

	// Child process state
	ChildExited bool
	ChildHung   bool
	ExitError   error
	// contains filtered or unexported fields
}

VirtualTerminal wraps a PTY and child process with robust lifecycle management.

func NewVirtualTerminal

func NewVirtualTerminal() *VirtualTerminal

NewVirtualTerminal creates a VirtualTerminal with scrollback support.

func (*VirtualTerminal) AppendScrollback

func (vt *VirtualTerminal) AppendScrollback(data []byte)

AppendScrollback adds raw PTY output to the scrollback buffer. This is called from PipeOutput's callback to record output for late-attaching terminal subscribers.

func (*VirtualTerminal) Close

func (vt *VirtualTerminal) Close() error

Close closes the PTY master file descriptor.

func (*VirtualTerminal) KillChild

func (vt *VirtualTerminal) KillChild()

KillChild sends SIGKILL to the child process.

func (*VirtualTerminal) PipeOutput

func (vt *VirtualTerminal) PipeOutput(onData func([]byte)) error

PipeOutput reads from the PTY master and calls onData for each chunk. This blocks until the child exits or the PTY is closed. Runs its own goroutine to wait on the child process.

func (*VirtualTerminal) Resize

func (vt *VirtualTerminal) Resize(rows, cols, childRows int)

Resize changes the PTY window size.

func (*VirtualTerminal) ScrollbackSnapshot

func (vt *VirtualTerminal) ScrollbackSnapshot() []byte

ScrollbackSnapshot returns a copy of the most recent scrollback history as raw bytes suitable for replay into xterm.js. The snapshot is capped at MaxScrollbackSnapshotBytes. Must be called with Mu held.

func (*VirtualTerminal) SendSignal

func (vt *VirtualTerminal) SendSignal(sig syscall.Signal) error

SendSignal sends a signal to the child process.

func (*VirtualTerminal) StartPTY

func (vt *VirtualTerminal) StartPTY(command string, args []string, rows, cols int, env map[string]string, cwd string) error

StartPTY allocates a PTY and starts the command in it. If cwd is non-empty, the child process starts in that directory.

func (*VirtualTerminal) WritePTY

func (vt *VirtualTerminal) WritePTY(p []byte, timeout time.Duration) (int, error)

WritePTY writes to the PTY master with a timeout. If the write doesn't complete within the timeout, the child is assumed to be hung.

Directories

Path Synopsis
Package driver defines the TermmuxDriverAdapter interface and canonical conversation types for bidirectional session log conversion.
Package driver defines the TermmuxDriverAdapter interface and canonical conversation types for bidirectional session log conversion.
claudecode
Package claudecode implements the TermmuxDriverAdapter for Claude Code CLI.
Package claudecode implements the TermmuxDriverAdapter for Claude Code CLI.
codex
Package codex implements the TermmuxDriverAdapter for the Codex CLI.
Package codex implements the TermmuxDriverAdapter for the Codex CLI.
eventsrc
eventstore
Package eventstore provides JSONL event persistence.
Package eventstore provides JSONL event persistence.
otelserver
Package otelserver provides a per-session HTTP server that receives OTEL log, metric, and trace data from agent CLIs.
Package otelserver provides a per-session HTTP server that receives OTEL log, metric, and trace data from agent CLIs.
sessionlog
Package sessionlog provides a JSONL file tailer that polls for new lines.
Package sessionlog provides a JSONL file tailer that polls for new lines.
Package monitor provides the agent state machine, metrics, and event fan-out.
Package monitor provides the agent state machine, metrics, and event fan-out.

Jump to

Keyboard shortcuts

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