Documentation
¶
Overview ¶
agents.go implements the agent management modal. It displays all agents in current display order with visibility, pin state, activity, and bead info. Rendered as a centered floating box over the live TUI. Opened via backtick+agents command or Alt+a shortcut.
Actions apply immediately and persist through the layout save path. Keybindings: Space (toggle visibility), Enter (grab/drop for reorder), p (toggle pin), A (reveal all), R (reset to config order).
Package tui — git branch detection for the status bar.
readBranch resolves the current branch of a repo (or git worktree) by reading .git/HEAD directly, avoiding a fork+exec on every poll. Returns "" when the directory is not a git repo or HEAD cannot be parsed.
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).
daemon_agent_ctrl.go implements the configure_agent / stop_agent / restart_agent control commands used by zero-config remote daemons. The local TUI is the source of truth for agent configuration; the daemon receives concrete instructions and manages process lifecycle.
daemon_web_bridge.go adapts the headless Daemon to the web.* interfaces so the web companion can run alongside initech serve.
help.go renders the help reference card as a centered floating modal. Opened by typing "help" or "?" in the command modal. Closed by pressing Esc, backtick, or q.
ipc_dispatch.go provides a shared IPC action dispatch used by both the TUI and headless daemon. Adding a new IPC action requires one change here instead of maintaining parallel switch statements.
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.
mcp_modal.go renders the MCP setup modal showing server status, bearer token, and pre-filled connection commands. Opened via the `mcp` command.
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.
paste.go implements buffered paste handling for the TUI. When the terminal delivers a bracketed paste (EventPaste start, N x EventKey, EventPaste end), characters are accumulated in pasteBuf and written to the focused pane's PTY in a single call. This turns O(N) renders into O(1) for large pastes.
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.
Package tui polling functions. These gather data on the render tick (tip rotation) or in background goroutines (battery). Separated from render.go so that file stays pure drawing.
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.
remote_push.go implements the TUI->daemon push protocol for zero-config remotes. After the hello handshake, the TUI computes a role-diff against the daemon's reported running agents and converges the daemon to the local config: pushes new/refresh roles via configure_agent, stops orphans via stop_agent.
render_common.go contains rendering helpers shared between Pane and RemotePane. These eliminate duplicate ribbon, cell, and cursor rendering logic.
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_unix.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.
watchdog.go implements a render watchdog that detects when the TUI main loop stops rendering (deadlock, infinite loop, blocked syscall). When no render completes within the timeout, the watchdog dumps all goroutine stacks to .initech/crash.log so the blocking path can be identified post-mortem.
web_modal.go renders the Web Companion modal showing server status, URL, and available endpoints. Opened via the `web` command.
webhook.go implements fire-and-forget HTTP POST of agent events to an external webhook URL. Each AgentEvent triggers a JSON POST with kind (dot-notation), agent, bead_id, detail, timestamp, and project fields.
Index ¶
- Constants
- func DeleteLayout(projectRoot string) error
- func DialIPC(socketPath string) (net.Conn, error)
- func EmitEvent(ch chan<- AgentEvent, ev AgentEvent)
- func GenerateToken() (string, error)
- func InitLogger(projectRoot string, level slog.Level) func()
- func LANIPv4() string
- 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 NewIPCScanner(r io.Reader) *bufio.Scanner
- func ReadOrCreateToken(dir string) (string, error)
- func ReadOrCreateTokenStatus(dir string) (token string, created bool, err error)
- func Run(cfg Config) error
- func RunDaemon(cfg DaemonConfig) error
- func SaveLayout(projectRoot string, state LayoutState) error
- func SetConfigureAgentBuilder(b configureAgentBuilder)
- func SocketPath(projectRoot, projectName string) string
- type ActivityState
- type AgentEvent
- type AgentInfo
- type AgentStatus
- type Config
- type ConfigureAgentCmd
- type ControlCmd
- type ControlMux
- func (m *ControlMux) Close()
- func (m *ControlMux) Done() <-chan struct{}
- func (m *ControlMux) Events() <-chan ControlResp
- func (m *ControlMux) Request(cmd ControlCmd) (ControlResp, error)
- func (m *ControlMux) RequestRaw(payload any) (ControlResp, error)
- func (m *ControlMux) SetRequestHandler(h RequestHandler)
- type ControlResp
- type Daemon
- func (d *Daemon) AllPanes() ([]PaneInfo, bool)
- func (d *Daemon) FindPaneView(name string) (PaneView, bool)
- func (d *Daemon) HandleExtended(conn net.Conn, req IPCRequest, rawJSON []byte) bool
- func (d *Daemon) HandleSend(conn net.Conn, req IPCRequest)
- func (d *Daemon) NotifyConfig() (webhookURL, project string)
- func (d *Daemon) Timers() *TimerStore
- type DaemonConfig
- type Divider
- type ErrorMsg
- type EventType
- type HelloMsg
- type HelloOKMsg
- type IPCHost
- type IPCRequest
- type IPCResponse
- type JournalEntry
- type LayoutMode
- type LayoutState
- type LiveEngine
- type MultiSink
- type Pane
- func (p *Pane) ActiveRunBytes() int64
- func (p *Pane) ActiveRunStart() time.Time
- func (p *Pane) Activity() ActivityState
- func (p *Pane) AgentType() string
- func (p *Pane) BeadID() string
- func (p *Pane) BeadIDs() []string
- func (p *Pane) BeadTitle() string
- 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) FlushPaste(content []byte)
- func (p *Pane) ForwardMouse(ev uv.MouseEvent)
- func (p *Pane) GetRegion() Region
- func (p *Pane) Host() string
- func (p *Pane) InResumeGrace() bool
- func (p *Pane) InScrollback() bool
- func (p *Pane) IsAlive() bool
- func (p *Pane) IsProtected() bool
- func (p *Pane) IsSuspended() bool
- func (p *Pane) LastEventTime() time.Time
- func (p *Pane) LastMessageReceived() time.Time
- 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) 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) SetBeads(ids []string)
- func (p *Pane) SetNetworkSink(w io.Writer)
- func (p *Pane) SetProtected(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) SubmitKey() string
- func (p *Pane) Subscribe(id string) chan []byte
- func (p *Pane) Unsubscribe(id string)
- func (p *Pane) Visible() bool
- type PaneConfig
- type PaneInfo
- type PaneRender
- type PaneView
- type PeerInfo
- type PersistentLayout
- type QueuedMessage
- type Region
- type RemotePane
- func (rp *RemotePane) ActiveRunBytes() int64
- func (rp *RemotePane) ActiveRunStart() time.Time
- func (rp *RemotePane) Activity() ActivityState
- func (rp *RemotePane) AgentType() string
- func (rp *RemotePane) BeadID() string
- func (rp *RemotePane) BeadIDs() []string
- func (rp *RemotePane) Close()
- func (rp *RemotePane) DrainData()
- func (rp *RemotePane) Emulator() *vt.SafeEmulator
- func (rp *RemotePane) GetRegion() Region
- func (rp *RemotePane) Host() string
- func (rp *RemotePane) IsAlive() bool
- func (rp *RemotePane) IsProtected() bool
- func (rp *RemotePane) IsSuspended() bool
- func (rp *RemotePane) LastEventTime() time.Time
- func (rp *RemotePane) LastMessageReceived() time.Time
- func (rp *RemotePane) LastOutputTime() time.Time
- func (rp *RemotePane) Mux() *ControlMux
- 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) SetBeads(ids []string)
- func (rp *RemotePane) SetVisible(v bool)
- func (rp *RemotePane) Start()
- func (rp *RemotePane) SubmitKey() string
- func (rp *RemotePane) Visible() bool
- type RenderPlan
- type RequestHandler
- type RestartAgentCmd
- type RingBuf
- type Selection
- type StopAgentCmd
- type StreamAddedMsg
- type StreamMapMsg
- type TUI
- func (t *TUI) AllPanes() ([]PaneInfo, bool)
- func (t *TUI) FindPaneView(name string) (PaneView, bool)
- func (t *TUI) HandleExtended(conn net.Conn, req IPCRequest, rawJSON []byte) bool
- func (t *TUI) HandleSend(conn net.Conn, req IPCRequest)
- func (t *TUI) InterruptAgent(name string, hard bool) error
- func (t *TUI) NotifyConfig() (webhookURL, project string)
- func (t *TUI) PressureThreshold() int
- func (t *TUI) Timers() *TimerStore
- 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.
const IPCScanBufSize = 256 * 1024
IPCScanBufSize is the buffer limit for all IPC and control-stream scanners. Must exceed maxSendTextLen plus JSON framing overhead so that a legal near-limit send is tokenized successfully before the explicit size check runs. 256 KB gives ~4x headroom over the 64 KB text limit (ini-piyb.2).
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 GenerateToken ¶ added in v1.20.0
GenerateToken returns a cryptographically random 32-byte token encoded as base64.
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 LANIPv4 ¶ added in v1.21.0
func LANIPv4() string
LANIPv4 returns the first non-loopback IPv4 address from the host's network interfaces, suitable for displaying in a connection snippet. Returns "0.0.0.0" if no usable address is found (e.g., disconnected machine).
func NewIPCScanner ¶ added in v0.25.31
NewIPCScanner creates a bufio.Scanner with a buffer large enough to handle the largest supported IPC/control message (maxSendTextLen + JSON framing).
func ReadOrCreateToken ¶ added in v1.20.0
ReadOrCreateToken reads a persisted token from dir/token, or generates a new one and writes it. The dir is created with 0700 if it doesn't exist. The token file has 0600 permissions.
func ReadOrCreateTokenStatus ¶ added in v1.21.0
ReadOrCreateTokenStatus is like ReadOrCreateToken but also reports whether the token was newly generated (true) or read from an existing file (false). Used by 'initech serve' to decide whether to print the connection snippet.
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 SetConfigureAgentBuilder ¶ added in v1.20.0
func SetConfigureAgentBuilder(b configureAgentBuilder)
SetConfigureAgentBuilder registers the function used by pushRolesToPeer to construct configure_agent payloads. The cmd layer calls this once at startup with a builder that has access to role templates and project state.
func SocketPath ¶
SocketPath returns the IPC endpoint path for a project. On Unix this is a domain socket inside .initech/; on Windows it is a named pipe.
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
Protected bool // True when agent is protected from auto-suspend.
LivePinned bool // True when agent is pinned to a live mode slot.
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.
WebPort int // Port for the web companion server. 0 = disabled.
WebhookURL string // HTTP endpoint for agent event POSTs. Empty = disabled.
SlackAppToken string // Slack app-level token for Socket Mode. Empty = disabled.
SlackBotToken string // Slack bot token for Web API calls. Empty = disabled.
McpPort int // Port for the MCP server. 0 = disabled.
McpToken string // Bearer token for MCP auth. Empty = auto-generate.
McpBind string // Bind address for MCP server. Empty = "0.0.0.0".
}
Config controls what agents the TUI launches.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a config with standard shell-only agents.
type ConfigureAgentCmd ¶ added in v1.20.0
type ConfigureAgentCmd struct {
ID string `json:"id,omitempty"`
Action string `json:"action"` // "configure_agent"
Name string `json:"name"`
Command []string `json:"command"`
Dir string `json:"dir"`
Env []string `json:"env,omitempty"`
AgentType string `json:"agent_type,omitempty"`
AutoApprove bool `json:"auto_approve,omitempty"`
NoBracketedPaste bool `json:"no_bracketed_paste,omitempty"`
SubmitKey string `json:"submit_key,omitempty"`
ClaudeMD string `json:"claude_md,omitempty"` // Role-level CLAUDE.md content.
RootClaudeMD string `json:"root_claude_md,omitempty"` // Project-root CLAUDE.md content.
}
ConfigureAgentCmd is sent by a client to push an agent configuration to a zero-config daemon. The daemon creates the workspace, writes CLAUDE.md files, creates a Pane, and starts the process.
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.
func (*ControlMux) RequestRaw ¶ added in v1.20.0
func (m *ControlMux) RequestRaw(payload any) (ControlResp, error)
RequestRaw sends an arbitrary JSON-encodable payload on the control stream and waits for the correlated response. The payload must serialise to a JSON object with a top-level "id" field; if the field is empty, RequestRaw generates a fresh ID and overwrites it via a marshal-then-merge pass.
Used for control commands whose payload struct is not ControlCmd (for example, ConfigureAgentCmd and StopAgentCmd).
func (*ControlMux) SetRequestHandler ¶ added in v0.25.31
func (m *ControlMux) SetRequestHandler(h RequestHandler)
SetRequestHandler registers a callback for incoming commands (messages with both an ID and an Action field). The handler processes the command and returns a response that is written back with the same ID.
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"`
Action string `json:"action,omitempty"` // Set for unsolicited commands (e.g. "forward_send", "stream_added").
Target string `json:"target,omitempty"` // Agent name for forward_send.
Text string `json:"text,omitempty"` // Message text for forward_send.
Enter bool `json:"enter,omitempty"` // Append Enter for forward_send.
StreamID uint32 `json:"stream_id,omitempty"` // yamux stream ID for stream_added.
Name string `json:"name,omitempty"` // Agent name for stream_added.
}
ControlResp is the response to a control command. It also carries unsolicited server-pushed commands (e.g. forward_send, stream_added) when Action is set.
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.
func (*Daemon) FindPaneView ¶ added in v0.23.53
func (*Daemon) HandleExtended ¶ added in v0.23.53
func (*Daemon) HandleSend ¶ added in v0.23.53
func (d *Daemon) HandleSend(conn net.Conn, req IPCRequest)
func (*Daemon) NotifyConfig ¶ added in v1.10.0
func (*Daemon) Timers ¶ added in v0.23.53
func (d *Daemon) Timers() *TimerStore
type DaemonConfig ¶ added in v0.23.18
type DaemonConfig struct {
Project *config.Project
Agents []PaneConfig
Version string
Verbose bool
WebPort int // Web companion port. 0 = disabled.
}
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. EventBeadAssigned // Agent received work via initech assign. EventBeadDelivered // Agent completed work via initech deliver (pass or fail). EventAgentStalled // No output for configurable threshold (warning). EventAgentStuck // Extended inactivity or error loop detected. 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. EventPeerConnected // Remote daemon connected. EventPeerDisconnected // Remote daemon disconnected. EventLiveSwap // Live mode swapped an agent into/out of a slot. )
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 IPCHost ¶ added in v0.23.53
type IPCHost interface {
// FindPaneView looks up a pane by name. Returns (nil, true) if not found.
// Returns (nil, false) if the host is shutting down and the lookup could
// not be performed.
FindPaneView(name string) (PaneView, bool)
// AllPanes returns status info for all managed panes. The bool is false
// if the host is shutting down.
AllPanes() ([]PaneInfo, bool)
// HandleSend processes the "send" action. Each runtime has different
// send semantics (TUI: suspended pane resume, remote forwarding;
// Daemon: client routing, auto-forward).
HandleSend(conn net.Conn, req IPCRequest)
// Timers returns the timer store, or nil if timers are not available.
Timers() *TimerStore
// NotifyConfig returns the webhook URL and project name for posting
// notifications. Returns empty strings if webhook is not configured.
NotifyConfig() (webhookURL, project string)
// HandleExtended processes runtime-specific actions not covered by
// the shared dispatch (e.g. TUI lifecycle commands). Returns true if
// the action was handled, false if it should fall through to "unknown".
HandleExtended(conn net.Conn, req IPCRequest, rawJSON []byte) bool
}
IPCHost provides the runtime-specific capabilities needed by the shared IPC dispatch. Both TUI and Daemon implement this interface.
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. LayoutLive // Dynamic pane rotation by activity conviction score. )
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 key, not index.
Hidden map[string]bool `yaml:"hidden,omitempty"` // Pane keys that are hidden.
Protected map[string]bool `yaml:"protected,omitempty"` // Pane keys protected from auto-suspend.
Order []string `yaml:"order,omitempty"` // Pane keys in display order (from show command).
Overlay bool `yaml:"overlay"`
// GridExplicit is true when the user chose grid dimensions via :grid CxR
// or Alt+2/Alt+3. When set, recalcGrid skips auto-recalculation so peer
// updates and hot-adds don't overwrite the user's choice.
GridExplicit bool `yaml:"grid_explicit,omitempty"`
// 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"`
// Live mode: dynamic pane rotation by conviction score.
LivePinned map[string]int `yaml:"live_pinned,omitempty"` // Agent name -> slot index.
LiveSlots []string `yaml:"live_slots,omitempty"` // Current agent name per slot (updated by live engine).
LiveAuto bool `yaml:"live_auto,omitempty"` // True = auto-size grid from active agent count.
}
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, paneKeys []string) (LayoutState, bool)
LoadLayout reads .initech/layout.yaml and merges it into a LayoutState. The caller passes the currently known pane keys. Unknown remote pane keys (host:name) are preserved so delayed peer reconnects can reuse saved hidden and order preferences, while stale local-only names are filtered out. Returns false if the file doesn't exist, is empty, contains invalid YAML, or would result in all currently known panes hidden.
type LiveEngine ¶ added in v1.13.0
type LiveEngine struct {
Slots []string // Current agent per slot.
Pinned map[string]int // Agent name -> fixed slot index.
RolesOrder []string // Config roles list for stable ordering in auto mode.
// contains filtered or unexported fields
}
LiveEngine manages dynamic slot assignments for Live Mode. It ranks agents by conviction score and assigns them to slots, respecting pinned assignments. Anti-thrashing mechanisms (hold time, hysteresis, one-swap-per-tick) prevent flickering when agent scores change rapidly.
func NewLiveEngine ¶ added in v1.13.0
func NewLiveEngine(numSlots int, pinned map[string]int, rolesOrder []string) *LiveEngine
NewLiveEngine creates a LiveEngine with the given number of slots and pinned assignments. rolesOrder provides stable ordering for auto mode; pass nil for fixed-slot mode where order is determined by slot index.
func (*LiveEngine) Tick ¶ added in v1.13.0
func (le *LiveEngine) Tick(panes []PaneView, now time.Time) []string
Tick computes slot assignments from the current pane states.
Pinned agents are placed in their fixed slots unconditionally. Dynamic slots use anti-thrashing rules:
- Hold time: a slot keeps its agent for at least liveHoldDuration after assignment.
- Hysteresis: displacing a strong occupant (>= keepThreshold) requires score >= claimThreshold and beating it by claimMargin. Displacing a weak occupant (< keepThreshold or dead) only requires score >= keepThreshold. Keeping a slot requires >= keepThreshold.
- One-swap-per-tick: at most one displacement per call, preventing full-screen flashes.
Filling an empty slot is not a displacement and is always allowed. Returns the ordered list of pane names, one per slot. Empty strings indicate unfilled slots.
func (*LiveEngine) TickAuto ¶ added in v1.14.0
func (le *LiveEngine) TickAuto(panes []PaneView, now time.Time) []string
TickAuto computes the visible agent list for Live Auto mode. Unlike Tick (fixed slot count), TickAuto dynamically grows and shrinks the visible set based on conviction scores:
- Pinned agents are always visible regardless of score.
- Other agents are visible if score >= liveKeepThreshold.
- Hold time: a newly visible agent stays visible for liveHoldDuration even if its score drops below threshold.
- One change per tick: at most one agent added or removed per call, preventing the grid from jumping sizes instantly.
Returns the ordered list of visible agent names (pinned first, then by score descending).
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) ActiveRunBytes ¶ added in v1.13.0
ActiveRunBytes returns bytes received during the current running streak.
func (*Pane) ActiveRunStart ¶ added in v1.13.0
ActiveRunStart returns when the current running streak began.
func (*Pane) Activity ¶
func (p *Pane) Activity() ActivityState
Activity returns the current activity state based on JSONL session tailing.
func (*Pane) AgentType ¶ added in v0.25.21
AgentType returns the configured semantic agent type for this pane.
func (*Pane) BeadTitle ¶ added in v1.16.2
BeadTitle returns the title of the primary bead, or empty string.
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) FlushPaste ¶ added in v1.12.2
FlushPaste writes the entire paste content to the PTY in a single operation, wrapped in bracketed paste markers (unless noBracketedPaste is set). Uses sendMu to serialize with concurrent IPC sends and prevent interleaving. For large pastes (>64KB), the content is written in chunks to avoid blocking the PTY write buffer for extended periods.
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) 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) IsProtected ¶ added in v1.17.0
IsProtected reports whether the operator has protected this pane from auto-suspension. Protected 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) LastEventTime ¶ added in v1.13.0
LastEventTime returns when an AgentEvent last fired for this pane.
func (*Pane) LastMessageReceived ¶ added in v1.13.0
LastMessageReceived returns when a message was last delivered to this pane.
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 PTY and emulator dimensions. Resizes the PTY first so the child process receives the size change before the emulator buffer reorganizes. Holds renderMu across both operations to prevent readLoop from writing old-geometry PTY output into a new-geometry emulator buffer (ini-yah).
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 using the harness-appropriate local delivery path. Claude panes use bracketed paste; raw-input panes like Codex write the body directly to the PTY and delay submit to avoid paste-burst suppression. The Codex ready-wait runs before acquiring sendMu so it does not block concurrent sends.
func (*Pane) SessionDesc ¶
SessionDesc returns the session description extracted from Claude's cursor row.
func (*Pane) SetBead ¶
SetBead sets a single bead ID (backward compat). Pass "" to clear. When assigning a non-empty bead, resets the idle-with-bead grace window so the notification doesn't fire on stale lastOutputTime (ini-t42).
func (*Pane) SetBeads ¶ added in v1.16.0
SetBeads sets multiple bead IDs. Pass nil to clear. When assigning non-empty beads, resets the idle-with-bead grace window so the notification doesn't fire on stale lastOutputTime (ini-t42).
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) SetProtected ¶ added in v1.17.0
SetProtected marks the pane as protected (true) or unprotected (false).
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.
func (*Pane) Start ¶
func (p *Pane) Start()
Start launches the pane's background goroutines (PTY reader, response loop, JSONL watcher). Must be called after safeGo and eventCh are wired. If safeGo is nil, falls back to bare goroutine launches.
func (*Pane) SubmitKey ¶ added in v0.25.9
SubmitKey returns the configured submit key sequence for this pane.
func (*Pane) Subscribe ¶ added in v1.0.0
Subscribe registers a new subscriber for PTY byte fan-out and returns a buffered channel that receives copies of all bytes read from the PTY. The channel has a 64KB buffer; if a slow consumer falls behind, the oldest entry is dropped to prevent blocking the readLoop. Callers must eventually call Unsubscribe to release resources.
func (*Pane) Unsubscribe ¶ added in v1.0.0
Unsubscribe removes a subscriber and closes its channel. Safe to call with an ID that was never subscribed or was already unsubscribed.
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.
AgentType string // Semantic agent type: claude-code (default), codex, or generic.
AutoApprove bool // When true, auto-approve matching permission prompts.
NoBracketedPaste bool // Final resolved injection mode. True uses typed input instead of bracketed paste.
BeadsEnabled bool // When false, skip bead detection (detectBeadClaim, detectCompletion, detectStall).
SubmitKey string // Key sequence to submit input: "enter" (default) or "ctrl+enter".
}
PaneConfig describes how to launch a pane's process.
type PaneInfo ¶ added in v0.23.53
type PaneInfo struct {
Name string `json:"name"`
Host string `json:"host,omitempty"`
Activity string `json:"activity"`
Alive bool `json:"alive"`
Visible bool `json:"visible"`
}
PaneInfo is the JSON structure returned by the "list" IPC action.
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
IsProtected() bool
Activity() ActivityState
LastOutputTime() time.Time
BeadID() string
BeadIDs() []string
SessionDesc() string
Emulator() *vt.SafeEmulator
GetRegion() Region
SetBead(id, title string)
SetBeads(ids []string)
SendKey(ev *tcell.EventKey)
SendText(text string, enter bool)
AgentType() string
SubmitKey() string // "" or "enter" (default), "ctrl+enter".
ActiveRunStart() time.Time
ActiveRunBytes() int64
LastMessageReceived() time.Time
LastEventTime() time.Time
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"
GridExplicit bool `yaml:"grid_explicit,omitempty"` // True = user chose CxR explicitly; don't auto-resize.
Hidden []string `yaml:"hidden,omitempty"` // Pane keys: name for local, host:name for remote.
Protected []string `yaml:"protected,omitempty"` // Pane keys protected from auto-suspend.
DepPinned []string `yaml:"pinned,omitempty"` // Deprecated: migration shim for old layout.yaml files.
Order []string `yaml:"order,omitempty"` // Pane keys in display order (from show command).
Mode string `yaml:"mode"` // "grid", "focus", "main", "live"
LivePinned map[string]int `yaml:"live_pinned,omitempty"` // Agent name -> fixed slot index for live mode.
LiveAuto bool `yaml:"live_auto,omitempty"` // True = auto-size grid from active agent count.
}
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).
func (Region) InnerSize ¶
InnerSize returns the renderable content area (full width, minus 1 row for bottom ribbon).
func (Region) TerminalSize ¶ added in v1.17.12
TerminalSize returns the dimensions given to the VT emulator and PTY. Subtracts 2 rows from region height: 1 for the bottom ribbon, 1 for the top activity bar. The child process sees these dimensions via LINES and SIGWINCH, so content it renders fits entirely within the visible area.
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) ActiveRunBytes ¶ added in v1.13.0
func (rp *RemotePane) ActiveRunBytes() int64
func (*RemotePane) ActiveRunStart ¶ added in v1.13.0
func (rp *RemotePane) ActiveRunStart() time.Time
func (*RemotePane) Activity ¶ added in v0.23.19
func (rp *RemotePane) Activity() ActivityState
func (*RemotePane) AgentType ¶ added in v0.25.21
func (rp *RemotePane) AgentType() string
func (*RemotePane) BeadID ¶ added in v0.23.19
func (rp *RemotePane) BeadID() string
func (*RemotePane) BeadIDs ¶ added in v1.16.0
func (rp *RemotePane) BeadIDs() []string
func (*RemotePane) Close ¶ added in v0.23.19
func (rp *RemotePane) Close()
Close terminates the yamux stream and stops background goroutines. Uses a timeout to prevent hanging on dead yamux streams during shutdown.
func (*RemotePane) DrainData ¶ added in v0.23.53
func (rp *RemotePane) DrainData()
DrainData moves pending byte chunks from dataCh into the emulator. Called by the TUI main loop for ALL remote panes (visible or hidden) so hidden panes don't accumulate stale data. Budget limits bytes per call to prevent stalls when the ring buffer replays megabytes into a new pane.
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) IsAlive ¶ added in v0.23.19
func (rp *RemotePane) IsAlive() bool
func (*RemotePane) IsProtected ¶ added in v1.17.0
func (rp *RemotePane) IsProtected() bool
func (*RemotePane) IsSuspended ¶ added in v0.23.19
func (rp *RemotePane) IsSuspended() bool
func (*RemotePane) LastEventTime ¶ added in v1.13.0
func (rp *RemotePane) LastEventTime() time.Time
func (*RemotePane) LastMessageReceived ¶ added in v1.13.0
func (rp *RemotePane) LastMessageReceived() time.Time
func (*RemotePane) LastOutputTime ¶ added in v0.23.19
func (rp *RemotePane) LastOutputTime() time.Time
func (*RemotePane) Mux ¶ added in v1.20.0
func (rp *RemotePane) Mux() *ControlMux
Mux exposes the shared control multiplexer for this RemotePane's peer connection. Callers (e.g. :remote-stop) use it to send control commands such as stop_agent that target the remote daemon directly.
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) SetBeads ¶ added in v1.16.0
func (rp *RemotePane) SetBeads(ids []string)
func (*RemotePane) SetVisible ¶ added in v0.26.2
func (rp *RemotePane) SetVisible(v bool)
SetVisible controls whether the remote pane appears in the layout.
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).
func (*RemotePane) SubmitKey ¶ added in v0.25.9
func (rp *RemotePane) SubmitKey() string
func (*RemotePane) Visible ¶ added in v0.26.2
func (rp *RemotePane) Visible() bool
Visible returns whether the remote pane should appear in the layout.
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 RequestHandler ¶ added in v0.25.31
type RequestHandler func(resp ControlResp) ControlResp
RequestHandler is called when the remote end sends a command (a message with both an ID and an Action). The handler processes the command and returns a response. Used by the TUI to handle forward_send from the daemon.
type RestartAgentCmd ¶ added in v1.20.0
type RestartAgentCmd struct {
ID string `json:"id,omitempty"`
Action string `json:"action"` // "restart_agent"
Name string `json:"name"`
}
RestartAgentCmd kills the existing process and starts a new one with the same config (command/dir/env/etc.).
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 StopAgentCmd ¶ added in v1.20.0
type StopAgentCmd struct {
ID string `json:"id,omitempty"`
Action string `json:"action"` // "stop_agent"
Name string `json:"name"`
}
StopAgentCmd stops a previously-pushed agent. Workspace files are preserved.
type StreamAddedMsg ¶ added in v1.21.0
type StreamAddedMsg struct {
Action string `json:"action"` // "stream_added"
StreamID uint32 `json:"stream_id"` // yamux stream ID for this agent.
Name string `json:"name"` // Agent name.
}
StreamAddedMsg announces a new agent stream created mid-session by a configure_agent push. The client opens a RemotePane bound to StreamID and adds it to the displayed pane list.
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) FindPaneView ¶ added in v0.23.53
func (*TUI) HandleExtended ¶ added in v0.23.53
func (*TUI) HandleSend ¶ added in v0.23.53
func (t *TUI) HandleSend(conn net.Conn, req IPCRequest)
func (*TUI) InterruptAgent ¶ added in v1.15.0
InterruptAgent sends a raw control byte to the named agent's PTY. Used by the MCP server. hard=true sends Ctrl+C, false sends Escape.
func (*TUI) NotifyConfig ¶ added in v1.10.0
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) Timers ¶ added in v0.23.53
func (t *TUI) Timers() *TimerStore
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. Missing files are treated as empty (first run). Corrupt files log a warning and start empty so the operator is aware of data loss.
func (*TimerStore) Add ¶ added in v0.23.23
Add creates a new timer and persists to disk. Returns the created timer and any persistence error. On save failure, the in-memory state is rolled back so it stays consistent with disk.
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 and any error (not-found or persistence failure). On save failure, the in-memory removal is rolled back.
func (*TimerStore) FireDue ¶ added in v0.23.23
func (ts *TimerStore) FireDue(now time.Time) ([]Timer, error)
FireDue returns and removes all timers where FireAt <= now. Persists after removal. Returns due timers and any save error. Even on save failure, the due timers are returned so they can still be fired (but the caller should log the error since the timers may resurrect after restart).
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
¶
- agents.go
- battery_linux.go
- branch.go
- control_mux.go
- crash.go
- daemon.go
- daemon_agent_ctrl.go
- daemon_web_bridge.go
- detect.go
- eventlog.go
- events.go
- help.go
- input_cmd.go
- input_core.go
- input_modals.go
- ipc.go
- ipc_dispatch.go
- ipc_lifecycle.go
- ipc_listen_unix.go
- keys.go
- lan_ip.go
- layout.go
- live.go
- logger.go
- mcp_bridge.go
- mcp_modal.go
- mouse.go
- multisink.go
- pane.go
- pane_cmd_unix.go
- pane_journal.go
- pane_render.go
- paste.go
- pid.go
- poll.go
- reconnect.go
- remote_conn.go
- remote_pane.go
- remote_push.go
- render.go
- render_common.go
- resource.go
- resource_linux.go
- ringbuf.go
- signals_unix.go
- slackchat_bridge.go
- stderr_linux.go
- timer.go
- token.go
- top.go
- tui.go
- watchdog.go
- web_bridge.go
- web_modal.go
- webhook.go