Documentation
¶
Overview ¶
backlog.go detects when idle agents have ready work in the bead backlog. It runs a periodic check every 2 minutes: if any agent is idle without a bead AND bd has ready beads, it emits EventAgentIdle events so the operator knows dispatch is needed.
control_mux.go multiplexes a single yamux control stream so multiple RemotePanes can send concurrent requests without interleaving responses. A single reader goroutine routes responses by ID to waiting callers, and routes unsolicited events to a broadcast channel.
daemon.go implements the headless initech daemon. It manages local agent panes without a TUI, listens on TCP, and streams PTY bytes to connected clients over yamux-multiplexed connections.
Protocol:
- Client connects via TCP, yamux server wraps the connection.
- Client opens stream 0 (control channel), sends hello.
- Server validates token, responds with hello_ok + agent list.
- Server sends stream_map (yamux stream ID -> agent name).
- Server opens one yamux stream per agent for bidirectional PTY bytes.
- Control channel accepts JSON commands (send, peek, resize).
help.go renders the full-screen help reference card modal. Opened by typing "help" or "?" in the command modal. Closed by pressing Esc, backtick, or q.
ipc_lifecycle.go contains IPC handlers for pane lifecycle operations: stop, start, restart, add, and remove. These handlers create, replace, or destroy panes in the running TUI session.
Separated from ipc.go (which owns the socket server, router, and message-oriented handlers) to reduce merge conflicts when lifecycle and messaging logic are edited concurrently.
logger.go provides structured application logging for the TUI. Writes to .initech/initech.log with automatic rotation at 10MB. Uses log/slog for leveled, structured output.
multisink.go implements a fan-out io.Writer that replicates writes to multiple downstream writers. Used by the daemon to stream PTY bytes to all connected clients plus the ring buffer simultaneously.
Package tui implements a terminal multiplexer with PTY management, VT emulation via charmbracelet/x/vt, and a tcell-based rendering engine.
pane_journal.go contains JSONL session file watching, entry parsing, activity state derivation, and event detection (bead claims, completions, stalls, stuck loops). The watchJSONL goroutine polls for new entries and feeds them into the pane's ring buffer and event detectors.
pane_render.go contains the Render method and visual conversion helpers for drawing a pane's terminal content and ribbon onto the tcell screen.
pid.go manages the .initech/initech.pid file and post-mortem crash detection.
On startup: write current PID. On clean exit: delete it. If the file exists at startup, the previous run exited uncleanly (signal, OOM, cgo crash). We log a warning and query the macOS system log and DiagnosticReports for evidence of what happened.
reconnect.go manages persistent connections to remote daemon peers with automatic reconnection on failure. Each remote peer gets a background goroutine that handles the connect/reconnect lifecycle.
remote_conn.go manages outbound connections to headless daemon peers. On TUI startup, it dials each configured remote, performs the yamux+hello handshake, and returns RemotePane instances that the TUI adds to its pane list. Failures are logged and skipped (graceful degradation).
remote_pane.go implements PaneView for network-backed agent panes. A RemotePane connects to a headless daemon via yamux and presents the remote agent as a local pane in the TUI grid. PTY bytes flow downstream (daemon -> local emulator) for rendering, and keystrokes flow upstream (TUI -> daemon -> PTY) for input.
Package tui resource management.
resource.go is the home for all resource-aware agent lifecycle code: memory monitoring, auto-suspend policy, and resume-on-message. All of this is gated behind the autoSuspend bool on the TUI struct.
When autoSuspend is false (the default), nothing in this file runs. The memory monitor goroutine is never started, the suspend policy never checks, and agents are never automatically suspended or resumed.
ringbuf.go implements a fixed-size circular byte buffer for PTY output replay on reconnect. When the buffer fills, new writes overwrite the oldest data. Snapshot returns the buffered content in chronological order.
signals.go installs OS signal handlers so every external termination leaves a trace in initech.log before the process exits.
Without this, SIGTERM/SIGHUP/SIGKILL from the OS kill the process silently and leave the terminal in raw mode (screen.Fini never runs). The handlers here fix that for catchable signals. SIGKILL still can't be caught — for that case, the PID file + system log check in pid.go provides post-mortem evidence.
stderr_linux.go redirects os.Stderr (fd 2) to .initech/stderr.log at the OS file-descriptor level. This must happen before screen.Init() puts the terminal into raw mode, so that cgo/native crash stack traces are written to a file rather than into the garbled terminal buffer.
Go's own panic handler writes through os.Stderr (Go level), which also goes through fd 2, so this captures both Go panics and cgo crashes.
Uses syscall.Dup3 instead of syscall.Dup2 because Dup2 is not available on linux/arm64 (the kernel exposes only dup3 on that architecture). Dup3 with flags=0 is semantically identical to Dup2.
timer.go implements the timer data model and JSON persistence for scheduled sends ("initech at"). Timers survive restarts via .initech/timers.json.
Index ¶
- Constants
- func DeleteLayout(projectRoot string) error
- func EmitEvent(ch chan<- AgentEvent, ev AgentEvent)
- func InitLogger(projectRoot string, level slog.Level) func()
- func LogDebug(component string, msg string, args ...any)
- func LogError(component string, msg string, args ...any)
- func LogInfo(component string, msg string, args ...any)
- func LogWarn(component string, msg string, args ...any)
- func Run(cfg Config) error
- func RunDaemon(cfg DaemonConfig) error
- func SaveLayout(projectRoot string, state LayoutState) error
- func SocketPath(projectRoot, projectName string) string
- type ActivityState
- type AgentEvent
- type AgentInfo
- type AgentStatus
- type Config
- type ControlCmd
- type ControlMux
- type ControlResp
- type Daemon
- type DaemonConfig
- type Divider
- type ErrorMsg
- type EventType
- type HelloMsg
- type HelloOKMsg
- type IPCRequest
- type IPCResponse
- type JournalEntry
- type LayoutMode
- type LayoutState
- type MultiSink
- type Pane
- func (p *Pane) Activity() ActivityState
- func (p *Pane) BacklogCount() int
- func (p *Pane) BeadID() string
- func (p *Pane) ClearIdleWithBacklog()
- func (p *Pane) ClearNetworkSink()
- func (p *Pane) Close()
- func (p *Pane) DrainQueue() []QueuedMessage
- func (p *Pane) Emulator() *vt.SafeEmulator
- func (p *Pane) EnqueueMessage(text string, enter bool) bool
- func (p *Pane) ForwardMouse(ev uv.MouseEvent)
- func (p *Pane) GetRegion() Region
- func (p *Pane) Host() string
- func (p *Pane) IdleWithBacklog() bool
- func (p *Pane) InResumeGrace() bool
- func (p *Pane) InScrollback() bool
- func (p *Pane) IsAlive() bool
- func (p *Pane) IsPinned() bool
- func (p *Pane) IsSuspended() bool
- func (p *Pane) LastOutputTime() time.Time
- func (p *Pane) MemoryRSS() int64
- func (p *Pane) Name() string
- func (p *Pane) QueueLen() int
- func (p *Pane) RecentEntries() []JournalEntry
- func (p *Pane) Render(screen tcell.Screen, focused bool, dimmed bool, index int, sel Selection)
- func (p *Pane) Resize(rows, cols int)
- func (p *Pane) ScrapeQuota() int
- func (p *Pane) ScrollDown(n int)
- func (p *Pane) ScrollUp(n int)
- func (p *Pane) SendKey(ev *tcell.EventKey)
- func (p *Pane) SendPaste(start bool)
- func (p *Pane) SendText(text string, enter bool)
- func (p *Pane) SessionDesc() string
- func (p *Pane) SetBead(id, title string)
- func (p *Pane) SetIdleWithBacklog(n int)
- func (p *Pane) SetNetworkSink(w io.Writer)
- func (p *Pane) SetPinned(v bool)
- func (p *Pane) SetResumeGrace(until time.Time)
- func (p *Pane) SetSuspended(v bool)
- func (p *Pane) SetVisible(v bool)
- func (p *Pane) Start()
- func (p *Pane) Visible() bool
- type PaneConfig
- type PaneRender
- type PaneView
- type PeerInfo
- type PersistentLayout
- type QueuedMessage
- type Region
- type RemotePane
- func (rp *RemotePane) Activity() ActivityState
- func (rp *RemotePane) BacklogCount() int
- func (rp *RemotePane) BeadID() string
- func (rp *RemotePane) Close()
- func (rp *RemotePane) Emulator() *vt.SafeEmulator
- func (rp *RemotePane) GetRegion() Region
- func (rp *RemotePane) Host() string
- func (rp *RemotePane) IdleWithBacklog() bool
- func (rp *RemotePane) IsAlive() bool
- func (rp *RemotePane) IsPinned() bool
- func (rp *RemotePane) IsSuspended() bool
- func (rp *RemotePane) LastOutputTime() time.Time
- func (rp *RemotePane) Name() string
- func (rp *RemotePane) Render(screen tcell.Screen, focused bool, dimmed bool, index int, sel Selection)
- func (rp *RemotePane) Resize(rows, cols int)
- func (rp *RemotePane) SendKey(ev *tcell.EventKey)
- func (rp *RemotePane) SendText(text string, enter bool)
- func (rp *RemotePane) SessionDesc() string
- func (rp *RemotePane) SetBead(id, title string)
- func (rp *RemotePane) Start()
- type RenderPlan
- type RingBuf
- type Selection
- type StreamMapMsg
- type TUI
- type Timer
- type TimerStore
Constants ¶
const DefaultRingBufSize = 256 * 1024
DefaultRingBufSize is the per-pane ring buffer capacity. 256KB holds ~12 full screen rewrites of terminal output, enough to reconstruct the current screen state on reconnect.
const DefaultStallThreshold = 10 * time.Minute
DefaultStallThreshold is the duration of inactivity before an agent with an assigned bead is considered stalled.
Variables ¶
This section is empty.
Functions ¶
func DeleteLayout ¶
DeleteLayout removes .initech/layout.yaml. Returns nil if the file doesn't exist (idempotent).
func EmitEvent ¶
func EmitEvent(ch chan<- AgentEvent, ev AgentEvent)
EmitEvent sends an event to the TUI's event channel without blocking. If the channel is full, the event is dropped (producers must not stall).
func InitLogger ¶
InitLogger sets up the application logger writing to .initech/initech.log. level is the minimum severity (slog.LevelDebug for verbose, slog.LevelInfo for normal). Safe to call multiple times; subsequent calls replace the logger. Returns a cleanup function that closes the log file.
func RunDaemon ¶ added in v0.23.18
func RunDaemon(cfg DaemonConfig) error
RunDaemon starts the headless daemon. Blocks until SIGINT/SIGTERM.
func SaveLayout ¶
func SaveLayout(projectRoot string, state LayoutState) error
SaveLayout writes the layout state to .initech/layout.yaml using atomic write (temp file + rename) to prevent corruption. Creates .initech/ if it doesn't exist.
func SocketPath ¶
SocketPath returns the socket path for a project. The socket is placed inside the project's .initech/ directory (not /tmp/) so it is scoped to the project and not world-visible.
Types ¶
type ActivityState ¶
type ActivityState int
ActivityState describes what an agent is doing based on JSONL session tailing.
const ( StateRunning ActivityState = iota // Claude is processing. StateIdle // Waiting for input. StateDead // Process has exited; pane is no longer alive. StateSuspended // Auto-suspended by resource policy. Eligible for resume. )
func (ActivityState) String ¶
func (s ActivityState) String() string
String returns a human-readable label for the state.
type AgentEvent ¶
type AgentEvent struct {
Type EventType
Pane string // Agent name (e.g., "eng1").
BeadID string // Relevant bead ID (empty if N/A).
Detail string // Human-readable description.
Time time.Time // When the event was detected.
}
AgentEvent represents a semantic event from an agent's activity. Emitted by JSONL watchers and consumed by the TUI main loop.
type AgentInfo ¶
type AgentInfo struct {
Name string
Status string // Display text: activity string or bead ID.
Activity ActivityState // Actual activity state for dot color.
Visible bool
IdleWithBacklog bool // True when idle with ready beads in the backlog.
BacklogCount int // Number of ready beads (when IdleWithBacklog is true).
Pinned bool // True when operator has pinned this agent.
Remote bool // True for agents on remote peers.
}
AgentInfo describes an agent for the status overlay.
type AgentStatus ¶ added in v0.23.18
type AgentStatus struct {
Name string `json:"name"`
Alive bool `json:"alive"`
Activity string `json:"activity"`
Bead string `json:"bead,omitempty"`
}
AgentStatus describes an agent's state for the hello handshake.
type Config ¶
type Config struct {
Agents []PaneConfig // One entry per agent pane.
ProjectName string // Used for socket path.
ProjectRoot string // Project root for .initech/ layout persistence.
ResetLayout bool // Ignore saved layout and start with defaults.
Verbose bool // Enable DEBUG-level logging (default: INFO).
Version string // Build version for crash reports.
AutoSuspend bool // Enable resource-aware auto-suspend/resume.
PressureThreshold int // RSS percentage threshold (0 uses default 85).
PaneConfigBuilder func(name string) (PaneConfig, error) // Optional factory for hot-add. Nil disables add command.
Project *config.Project // Full project config. Used for remote peer connections.
UpdateResult <-chan string // Receives newer version string from background check. Nil = no check.
}
Config controls what agents the TUI launches.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a config with standard shell-only agents.
type ControlCmd ¶ added in v0.23.18
type ControlCmd struct {
ID string `json:"id,omitempty"` // Request ID for response correlation.
Action string `json:"action"` // "send", "peek", "resize", "schedule", etc.
Target string `json:"target"` // Agent name.
Host string `json:"host,omitempty"`
Text string `json:"text,omitempty"`
Enter bool `json:"enter,omitempty"`
Lines int `json:"lines,omitempty"`
Rows int `json:"rows,omitempty"`
Cols int `json:"cols,omitempty"`
FireAt string `json:"fire_at,omitempty"` // RFC3339 for schedule command.
}
ControlCmd is a command sent on the control channel after handshake.
type ControlMux ¶ added in v0.23.27
type ControlMux struct {
// contains filtered or unexported fields
}
ControlMux multiplexes a yamux control stream for concurrent request/response use by multiple RemotePanes. Each Request call gets a unique ID, writes the command, and waits for the response with that ID. A single readLoop goroutine reads all messages and dispatches by ID.
func NewControlMux ¶ added in v0.23.27
func NewControlMux(conn net.Conn) *ControlMux
NewControlMux creates a multiplexer for the given control stream connection and starts the background reader goroutine.
func (*ControlMux) Close ¶ added in v0.23.27
func (m *ControlMux) Close()
Close shuts down the multiplexer by closing the underlying connection.
func (*ControlMux) Done ¶ added in v0.23.27
func (m *ControlMux) Done() <-chan struct{}
Done returns a channel that is closed when the read loop exits (stream died).
func (*ControlMux) Events ¶ added in v0.23.27
func (m *ControlMux) Events() <-chan ControlResp
Events returns a channel that receives unsolicited server-pushed messages (responses with no ID, such as agent_died or timer_fired events).
func (*ControlMux) Request ¶ added in v0.23.27
func (m *ControlMux) Request(cmd ControlCmd) (ControlResp, error)
Request sends a command on the control stream and waits for the correlated response (matched by ID). Returns an error if the stream is closed or the request times out after 10 seconds.
type ControlResp ¶ added in v0.23.18
type ControlResp struct {
ID string `json:"id,omitempty"` // Echoed from request for correlation.
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Data string `json:"data,omitempty"`
}
ControlResp is the response to a control command.
type Daemon ¶ added in v0.23.18
type Daemon struct {
// contains filtered or unexported fields
}
Daemon manages headless agent panes and streams them to a yamux client.
type DaemonConfig ¶ added in v0.23.18
type DaemonConfig struct {
Project *config.Project
Agents []PaneConfig
Version string
Verbose bool
}
DaemonConfig holds the configuration for a headless daemon session.
type EventType ¶
type EventType int
EventType classifies semantic events from agent activity detection.
const ( EventBeadCompleted EventType = iota // Agent finished a bead (DONE comment, ready_for_qa). EventBeadClaimed // Agent claimed a bead (in_progress). EventBeadFailed // QA failed a bead or agent reported failure. EventAgentStalled // No output for configurable threshold (warning). EventAgentStuck // Extended inactivity or error loop detected. EventAgentIdle // Agent returned to idle after work. EventAgentIdleWithBead // Agent went running->idle while holding a bead. EventAgentSuspended // Agent auto-suspended by resource pressure policy. EventAgentResumed // Agent resumed from suspension (triggered by message). EventMessageSent // Message delivered to an agent via IPC send. EventAgentStarted // Agent pane started via IPC. EventAgentStopped // Agent pane stopped via IPC. EventAgentRestarted // Agent pane restarted via IPC. EventAgentAdded // New agent pane added to session. EventAgentRemoved // Agent pane removed from session. EventTimerFired // Scheduled timer delivered its message. )
type HelloMsg ¶ added in v0.23.18
type HelloMsg struct {
Action string `json:"action"` // "hello"
Version int `json:"version"` // Protocol version (1).
Token string `json:"token"` // Auth token.
PeerName string `json:"peer_name"` // Client's peer name.
}
HelloMsg is sent by the client to initiate the handshake.
type HelloOKMsg ¶ added in v0.23.18
type HelloOKMsg struct {
Action string `json:"action"` // "hello_ok"
Version int `json:"version"` // Protocol version (1).
PeerName string `json:"peer_name"` // Server's peer name.
Agents []AgentStatus `json:"agents"` // Current agent states.
}
HelloOKMsg is the server's response to a successful hello.
type IPCRequest ¶
type IPCRequest struct {
Action string `json:"action"` // "send", "peek", "list", "peers_query"
Target string `json:"target"` // Role name (for send/peek).
Host string `json:"host"` // Remote peer name (for cross-machine send). Empty = local.
Text string `json:"text"` // Text to inject (for send).
Lines int `json:"lines"` // Number of lines to return (for peek, 0 = all).
Enter bool `json:"enter"` // Append Enter after text (for send).
}
IPCRequest is the JSON structure sent by CLI commands to the TUI socket.
type IPCResponse ¶
type IPCResponse struct {
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Data string `json:"data,omitempty"` // Pane content for peek, pane list for list.
}
IPCResponse is the JSON structure returned by the TUI socket.
type JournalEntry ¶
type JournalEntry struct {
Type string // "user", "assistant", "progress", "system", "last-prompt", etc.
Content string // Text content (assistant message, tool output). Capped at 4KB.
ToolName string // For tool_use/tool_result: which tool was called.
ExitCode int // For Bash tool results: exit code if available.
Timestamp time.Time // When this entry was written.
}
JournalEntry represents a parsed JSONL entry from a Claude Code session.
type LayoutMode ¶
type LayoutMode int
LayoutMode determines how panes are arranged on screen.
const ( LayoutFocus LayoutMode = iota // Single pane, full screen. LayoutGrid // Arbitrary NxM grid. Layout2Col // Main pane left, stacked right. )
type LayoutState ¶
type LayoutState struct {
Mode LayoutMode `yaml:"mode"`
GridCols int `yaml:"grid_cols"`
GridRows int `yaml:"grid_rows"`
Zoomed bool `yaml:"zoomed,omitempty"`
Focused string `yaml:"focused"` // Pane name, not index.
Hidden map[string]bool `yaml:"hidden,omitempty"` // Pane names that are hidden.
Pinned map[string]bool `yaml:"pinned,omitempty"` // Pane names protected from auto-suspend.
Order []string `yaml:"order,omitempty"` // Pane names in display order (from show command).
Overlay bool `yaml:"overlay"`
// Per-column and per-row proportional sizing (future).
// nil means uniform. Values are relative weights (e.g., [60, 40] = 60%/40%).
ColWeights []int `yaml:"col_weights,omitempty"`
RowWeights []int `yaml:"row_weights,omitempty"`
}
LayoutState captures the complete layout intent. It is the single authority on what the screen should look like. Trivially serializable to YAML for persistent layout.
func DefaultLayoutState ¶
func DefaultLayoutState(paneNames []string) LayoutState
DefaultLayoutState creates a LayoutState with auto-calculated grid dimensions for the given pane names.
func LoadLayout ¶
func LoadLayout(projectRoot string, paneNames []string) (LayoutState, bool)
LoadLayout reads .initech/layout.yaml and merges it into a LayoutState, filtering stale pane references. Returns false if the file doesn't exist, is empty, contains invalid YAML, or would result in all panes hidden.
type MultiSink ¶ added in v0.23.22
type MultiSink struct {
// contains filtered or unexported fields
}
MultiSink writes to all registered writers. Dead writers (those that return errors) are automatically removed. All methods are safe for concurrent use.
func NewMultiSink ¶ added in v0.23.22
func NewMultiSink() *MultiSink
NewMultiSink creates an empty MultiSink. Add writers with Add().
func (*MultiSink) Write ¶ added in v0.23.22
Write sends p to all registered writers. Writers that return errors are removed automatically (dead client cleanup). Returns len(p), nil to satisfy io.Writer (the caller should not stall on downstream failures).
The writer list is snapshot'd under lock, then writes happen lock-free. This prevents a slow/blocked writer from holding the lock and stalling Add/Remove or other concurrent Write calls.
type Pane ¶
type Pane struct {
// contains filtered or unexported fields
}
Pane represents a terminal pane backed by a PTY process. It uses a SafeEmulator from charmbracelet/x/vt for terminal emulation.
func NewPane ¶
func NewPane(cfg PaneConfig, rows, cols int) (*Pane, error)
NewPane creates a terminal pane running the configured command (or $SHELL).
func (*Pane) Activity ¶
func (p *Pane) Activity() ActivityState
Activity returns the current activity state based on JSONL session tailing.
func (*Pane) BacklogCount ¶
BacklogCount returns the number of ready beads at the last idle-with-backlog detection.
func (*Pane) ClearIdleWithBacklog ¶
func (p *Pane) ClearIdleWithBacklog()
ClearIdleWithBacklog clears the idle-with-backlog indicator.
func (*Pane) ClearNetworkSink ¶ added in v0.23.21
func (p *Pane) ClearNetworkSink()
ClearNetworkSink removes the network sink. Safe to call if no sink is set.
func (*Pane) Close ¶
func (p *Pane) Close()
Close terminates the PTY, kills the process, and signals goroutines to exit.
func (*Pane) DrainQueue ¶
func (p *Pane) DrainQueue() []QueuedMessage
DrainQueue returns all queued messages in FIFO order and clears the queue. Called on resume to deliver buffered messages.
Caller must be on the main goroutine (via runOnMain).
func (*Pane) Emulator ¶ added in v0.23.13
func (p *Pane) Emulator() *vt.SafeEmulator
Emulator returns the pane's terminal emulator for cell-level access.
func (*Pane) EnqueueMessage ¶
EnqueueMessage appends a message to the pane's queue. If the queue is at capacity (maxMessageQueue), the oldest message is dropped. Returns true if a message was dropped to make room.
Caller must be on the main goroutine (via runOnMain).
func (*Pane) ForwardMouse ¶
func (p *Pane) ForwardMouse(ev uv.MouseEvent)
ForwardMouse sends a mouse event to the emulator with pane-local content coordinates translated to emulator coordinates. The emulator silently drops the event if the child process hasn't enabled mouse reporting.
func (*Pane) Host ¶ added in v0.23.13
Host returns the hostname for this pane. Local panes always return "".
func (*Pane) IdleWithBacklog ¶
IdleWithBacklog returns true when the pane is idle and ready beads exist.
func (*Pane) InResumeGrace ¶
InResumeGrace returns true if the pane is within the post-resume grace period. During this window the pane is exempt from auto-suspend and idle-with-bead notifications.
func (*Pane) InScrollback ¶
InScrollback returns true when the pane is viewing scrollback history.
func (*Pane) IsPinned ¶
IsPinned reports whether the operator has pinned this pane to prevent auto-suspension. Pinned panes are always kept running.
func (*Pane) IsSuspended ¶
IsSuspended returns whether the pane has been stopped by the auto-suspend policy. A suspended pane is distinct from dead (crashed) and will auto-resume when a message arrives.
func (*Pane) LastOutputTime ¶
LastOutputTime returns the last time PTY output was received.
func (*Pane) MemoryRSS ¶
MemoryRSS returns the pane's last polled RSS in kilobytes. Returns 0 if the memory monitor has not yet polled or the process is dead.
func (*Pane) RecentEntries ¶
func (p *Pane) RecentEntries() []JournalEntry
RecentEntries returns a copy of the recent JSONL entries ring buffer.
func (*Pane) Render ¶
Render draws the pane's bottom ribbon and terminal content onto the tcell screen. When dimmed is true, foreground colors are reduced to ~70% brightness. The index parameter is the 1-based pane number shown in the ribbon badge. All writes are clamped to the pane's region to prevent bleed-through.
func (*Pane) Resize ¶
Resize updates the emulator and PTY dimensions. Holds renderMu to serialize with readLoop writes and Render cell reads, preventing garbled output when the buffer is reorganized during zoom or layout changes (ini-ipr).
func (*Pane) ScrapeQuota ¶ added in v0.21.3
ScrapeQuota reads the emulator's status bar rows and extracts the quota percentage ("N% of limit"). Returns 0-100 on success, -1 if not found. Skips panes in alt-screen mode (vim, less) where the status bar is hidden.
func (*Pane) ScrollDown ¶
ScrollDown moves the viewport down (toward live output) by n rows. When scrollOffset reaches 0, the pane returns to live view.
func (*Pane) SendKey ¶
SendKey translates a tcell key event into a charmbracelet KeyPressEvent and sends it through the emulator, which encodes it for the PTY.
func (*Pane) SendPaste ¶
SendPaste writes a bracketed paste marker to the PTY. On start=true it writes \x1b[200~ (paste start); on start=false it writes \x1b[201~ (paste end). The child process uses these delimiters to distinguish pasted content from typed keystrokes. No-op if the PTY is not open.
func (*Pane) SendText ¶ added in v0.23.13
SendText injects text into the pane's PTY via keystroke injection, with optional Enter. Acquires sendMu to serialize with concurrent sends. Sends Ctrl+S to stash pending user input before injecting (ini-gd0).
func (*Pane) SessionDesc ¶
SessionDesc returns the session description extracted from Claude's cursor row.
func (*Pane) SetIdleWithBacklog ¶
SetIdleWithBacklog marks the pane as idle with n ready beads in the backlog.
func (*Pane) SetNetworkSink ¶ added in v0.23.21
SetNetworkSink sets the writer that receives a copy of all PTY output. Used by the daemon to stream bytes to a connected client. The sink receives bytes after the emulator, so network backpressure cannot stall local rendering.
func (*Pane) SetResumeGrace ¶
SetResumeGrace sets the post-resume grace period expiration.
func (*Pane) SetSuspended ¶
SetSuspended marks the pane as suspended or resumed by the auto-suspend policy.
func (*Pane) SetVisible ¶
SetVisible controls whether the pane appears in the layout. Hiding a pane does not stop its process or resize its emulator.
type PaneConfig ¶
type PaneConfig struct {
Name string // Display name (role name).
Command []string // Command + args. Empty means use $SHELL.
Dir string // Working directory. Empty means inherit.
Env []string // Extra env vars (KEY=VALUE). TERM is always set.
}
PaneConfig describes how to launch a pane's process.
type PaneRender ¶
type PaneRender struct {
Pane PaneView
Region Region
Index int // 1-based pane number (position in full pane list).
Focused bool // Receives keyboard input.
Dimmed bool // Render with reduced contrast.
}
PaneRender describes how to render a single pane.
type PaneView ¶ added in v0.23.13
type PaneView interface {
Name() string
Host() string // "" for local panes.
IsAlive() bool
IsSuspended() bool
IsPinned() bool
Activity() ActivityState
LastOutputTime() time.Time
BeadID() string
SessionDesc() string
IdleWithBacklog() bool
BacklogCount() int
Emulator() *vt.SafeEmulator
GetRegion() Region
SetBead(id, title string)
SendKey(ev *tcell.EventKey)
SendText(text string, enter bool)
Render(screen tcell.Screen, focused bool, dimmed bool, index int, sel Selection)
Resize(rows, cols int)
Close()
}
PaneView abstracts pane behavior so both local panes (Pane) and future network-backed panes (RemotePane) can be used interchangeably by the TUI.
type PeerInfo ¶ added in v0.23.20
PeerInfo describes a peer and its agents for the peers_query response.
type PersistentLayout ¶
type PersistentLayout struct {
Grid string `yaml:"grid"` // e.g. "3x2"
Hidden []string `yaml:"hidden,omitempty"` // Role names of hidden panes.
Pinned []string `yaml:"pinned,omitempty"` // Role names protected from auto-suspend.
Order []string `yaml:"order,omitempty"` // Pane display order (from show command).
Mode string `yaml:"mode"` // "grid", "focus", "main"
}
PersistentLayout is the subset of LayoutState that survives sessions. Focused pane is deliberately excluded (momentary choice, not a preference). Overlay and weights are excluded (not layout-changing from the user's perspective).
type QueuedMessage ¶
QueuedMessage is a message waiting to be delivered to a suspended pane. On resume, the queue is drained in FIFO order via injectText.
type Region ¶
type Region struct {
X, Y, W, H int
}
Region defines a rectangular area on screen (outer bounds including border).
type RemotePane ¶ added in v0.23.19
type RemotePane struct {
// contains filtered or unexported fields
}
RemotePane is a PaneView backed by a yamux stream to a headless daemon. The local VT emulator receives PTY bytes from the stream for rendering. Keystrokes are forwarded upstream to the daemon for injection into the PTY.
func NewRemotePane ¶ added in v0.23.19
func NewRemotePane(name, host string, stream net.Conn, mux *ControlMux, cols, rows int) *RemotePane
NewRemotePane creates a RemotePane connected to a remote agent. The mux is shared across all RemotePanes from the same peer connection. The caller must call Start() to begin the readLoop goroutine.
func (*RemotePane) Activity ¶ added in v0.23.19
func (rp *RemotePane) Activity() ActivityState
func (*RemotePane) BacklogCount ¶ added in v0.23.19
func (rp *RemotePane) BacklogCount() int
func (*RemotePane) BeadID ¶ added in v0.23.19
func (rp *RemotePane) BeadID() string
func (*RemotePane) Close ¶ added in v0.23.19
func (rp *RemotePane) Close()
Close terminates the yamux stream and stops background goroutines.
func (*RemotePane) Emulator ¶ added in v0.23.19
func (rp *RemotePane) Emulator() *vt.SafeEmulator
func (*RemotePane) GetRegion ¶ added in v0.23.19
func (rp *RemotePane) GetRegion() Region
func (*RemotePane) Host ¶ added in v0.23.19
func (rp *RemotePane) Host() string
func (*RemotePane) IdleWithBacklog ¶ added in v0.23.19
func (rp *RemotePane) IdleWithBacklog() bool
func (*RemotePane) IsAlive ¶ added in v0.23.19
func (rp *RemotePane) IsAlive() bool
func (*RemotePane) IsPinned ¶ added in v0.23.19
func (rp *RemotePane) IsPinned() bool
func (*RemotePane) IsSuspended ¶ added in v0.23.19
func (rp *RemotePane) IsSuspended() bool
func (*RemotePane) LastOutputTime ¶ added in v0.23.19
func (rp *RemotePane) LastOutputTime() time.Time
func (*RemotePane) Name ¶ added in v0.23.19
func (rp *RemotePane) Name() string
func (*RemotePane) Render ¶ added in v0.23.19
func (rp *RemotePane) Render(screen tcell.Screen, focused bool, dimmed bool, index int, sel Selection)
Render draws the remote pane with [R] badge in the ribbon title.
func (*RemotePane) Resize ¶ added in v0.23.19
func (rp *RemotePane) Resize(rows, cols int)
Resize updates the local emulator immediately and debounces the control command to the remote daemon. Rapid resize events (SIGWINCH storms from dragging the terminal edge) are collapsed: only the final geometry is sent after a 50ms quiet period.
func (*RemotePane) SendKey ¶ added in v0.23.19
func (rp *RemotePane) SendKey(ev *tcell.EventKey)
SendKey encodes a tcell key event as raw ANSI bytes and writes them upstream to the daemon, which injects them into the remote PTY.
func (*RemotePane) SendText ¶ added in v0.23.19
func (rp *RemotePane) SendText(text string, enter bool)
SendText sends text to the remote agent via the control channel. This uses the daemon's "send" command which injects text through the emulator path (same as initech send), handling Ctrl+S stash and paste detection.
func (*RemotePane) SessionDesc ¶ added in v0.23.19
func (rp *RemotePane) SessionDesc() string
func (*RemotePane) SetBead ¶ added in v0.23.19
func (rp *RemotePane) SetBead(id, title string)
func (*RemotePane) Start ¶ added in v0.23.19
func (rp *RemotePane) Start()
Start launches background goroutines: readLoop (stream -> dataCh) and responseLoop (drains emulator responses so Write never blocks on the internal io.Pipe).
type RenderPlan ¶
type RenderPlan struct {
Panes []PaneRender // One entry per pane to draw (ordered).
Dividers []Divider // Vertical lines between pane columns.
ScreenW int
ScreenH int
// ValidatedFocus is the name of the pane that actually receives input.
// May differ from LayoutState.Focused if that pane is hidden.
ValidatedFocus string
}
RenderPlan is the complete set of instructions for one frame. Produced by computeLayout, consumed by the render loop.
type RingBuf ¶ added in v0.23.21
type RingBuf struct {
// contains filtered or unexported fields
}
RingBuf is a fixed-size circular byte buffer. It implements io.Writer. All methods are safe for concurrent use.
func NewRingBuf ¶ added in v0.23.21
NewRingBuf creates a ring buffer with the given capacity in bytes.
type StreamMapMsg ¶ added in v0.23.18
type StreamMapMsg struct {
Action string `json:"action"` // "stream_map"
Streams map[uint32]string `json:"streams"` // Stream ID -> agent name.
}
StreamMapMsg tells the client which yamux stream ID maps to which agent.
type TUI ¶
type TUI struct {
// contains filtered or unexported fields
}
TUI is the main terminal multiplexer. It owns the tcell screen, a set of terminal panes, and handles input routing, layout, and rendering.
func (*TUI) PressureThreshold ¶
PressureThreshold returns the configured RSS percentage above which agents may be auto-suspended. Returns 85 (the default) when not explicitly set.
func (*TUI) ResourceEnabled ¶
ResourceEnabled reports whether resource-aware auto-suspend is active for this TUI instance. All resource management code should check this gate before taking any action.
func (*TUI) SystemMemoryAvailable ¶
SystemMemoryAvailable returns the last polled available system RAM in kilobytes. Returns 0 if not yet polled or if the query failed.
func (*TUI) SystemMemoryTotal ¶
SystemMemoryTotal returns total system RAM in kilobytes.
type Timer ¶ added in v0.23.23
type Timer struct {
ID string `json:"id"`
Target string `json:"target"`
Host string `json:"host,omitempty"`
Text string `json:"text"`
Enter bool `json:"enter"`
FireAt time.Time `json:"fire_at"`
CreatedAt time.Time `json:"created_at"`
}
Timer represents a scheduled send: deliver Text to Target at FireAt.
type TimerStore ¶ added in v0.23.23
type TimerStore struct {
// contains filtered or unexported fields
}
TimerStore manages scheduled timers with JSON persistence. All methods are safe for concurrent use.
func NewTimerStore ¶ added in v0.23.23
func NewTimerStore(path string) *TimerStore
NewTimerStore creates a store backed by the given file path. If the file exists, timers and the ID counter are loaded from it. If the file doesn't exist or is invalid, the store starts empty.
func (*TimerStore) Add ¶ added in v0.23.23
Add creates a new timer and persists to disk. Returns the created timer.
func (*TimerStore) Cancel ¶ added in v0.23.23
func (ts *TimerStore) Cancel(id string) (Timer, error)
Cancel removes a timer by ID and persists. Returns the canceled timer.
func (*TimerStore) FireDue ¶ added in v0.23.23
func (ts *TimerStore) FireDue(now time.Time) []Timer
FireDue returns and removes all timers where FireAt <= now. Persists after removal. Returns nil if no timers are due.
func (*TimerStore) List ¶ added in v0.23.23
func (ts *TimerStore) List() []Timer
List returns all pending timers sorted by FireAt (earliest first).
func (*TimerStore) Pending ¶ added in v0.23.23
func (ts *TimerStore) Pending() int
Pending returns the count of pending timers.
Source Files
¶
- backlog.go
- battery_linux.go
- control_mux.go
- crash.go
- daemon.go
- detect.go
- eventlog.go
- events.go
- help.go
- input.go
- ipc.go
- ipc_lifecycle.go
- layout.go
- logger.go
- mouse.go
- multisink.go
- pane.go
- pane_journal.go
- pane_render.go
- pid.go
- reconnect.go
- remote_conn.go
- remote_pane.go
- render.go
- resource.go
- resource_linux.go
- ringbuf.go
- signals.go
- stderr_linux.go
- timer.go
- top.go
- tui.go