Documentation
¶
Overview ¶
Package ghostline provides a local-first terminal session runtime for Go.
A Hub owns pseudo-terminals and child processes in the embedding process. A Server and Client provide the same concrete Session contract over a same-host Unix socket. Session identity accessors are cached; every operation that can perform process, storage, or network I/O accepts a context and returns an error.
Raw PTY output is stored in immutable generations plus one active segment. Output returns a bounded reader positioned by an opaque Cursor. Checkpoint atomically pairs a terminal replay with the cursor of the first raw byte not represented by that replay. AtomicState provides the same boundary for a complete, versioned VT emulator state when the consumer can install the advertised opaque format. Callers own reader cancellation, goroutines, archive format, and retention policy.
Sessions survive client detach and successful same-version daemon adoption. They do not survive daemon crashes that lose PTY ownership, host reboot, or cross-machine migration.
Index ¶
- Constants
- Variables
- func TagVersion() string
- type AdoptReport
- type AtomicState
- type Checkpoint
- type Client
- func (c *Client) Check(ctx context.Context) error
- func (c *Client) Close() error
- func (c *Client) Ensure(ctx context.Context) error
- func (c *Client) Get(ctx context.Context, name string) (*Session, error)
- func (c *Client) List(ctx context.Context) ([]*Session, error)
- func (c *Client) PID() int
- func (c *Client) Socket() string
- func (c *Client) Start(ctx context.Context, options SessionOptions) (*Session, error)
- func (c *Client) Version(ctx context.Context) (string, error)
- func (c *Client) VersionInfo(ctx context.Context) (VersionInfo, error)
- type ColorQueryCallback
- type ColorQueryKind
- type Cursor
- type ExitError
- type Hub
- type ManagedClientOptions
- type Options
- type OutputReader
- type ProcessSpec
- type ProtocolLimits
- type QueryResponder
- type Server
- func (s *Server) Adopt(ctx context.Context, adminSocket string) (int, error)
- func (s *Server) AdoptWithReport(ctx context.Context, adminSocket string) (AdoptReport, error)
- func (s *Server) Close() error
- func (s *Server) Serve(ctx context.Context, socketPath string) error
- func (s *Server) Shutdown(ctx context.Context) error
- type Session
- func (s *Session) AtomicState(ctx context.Context) (AtomicState, error)
- func (s *Session) Checkpoint(ctx context.Context) (Checkpoint, error)
- func (s *Session) CreatedAt() time.Time
- func (s *Session) Delete(ctx context.Context) error
- func (s *Session) Info() SessionInfo
- func (s *Session) Metadata(ctx context.Context) (SessionMetadata, error)
- func (s *Session) Name() string
- func (s *Session) Output(ctx context.Context, from Cursor) (*OutputReader, error)
- func (s *Session) OutputCursor(ctx context.Context) (Cursor, error)
- func (s *Session) PruneOutput(ctx context.Context, before Cursor) error
- func (s *Session) Replay(ctx context.Context) ([]byte, error)
- func (s *Session) Resize(ctx context.Context, size Size) error
- func (s *Session) RotateOutput(ctx context.Context) (Cursor, error)
- func (s *Session) Signal(ctx context.Context, signal os.Signal) error
- func (s *Session) Size(ctx context.Context) (Size, error)
- func (s *Session) Status(ctx context.Context) (Status, error)
- func (s *Session) Terminate(ctx context.Context) error
- func (s *Session) Wait(ctx context.Context) error
- func (s *Session) WriteInput(ctx context.Context, data []byte) error
- type SessionInfo
- type SessionMetadata
- type SessionOptions
- type Size
- type Status
- type VersionInfo
Constants ¶
const ( // CapabilityRawPayload indicates that envelopes may be followed by an // exact-length unencoded payload. CapabilityRawPayload = "raw-payload-v1" // CapabilityStreams indicates support for the v1 pull-stream state machine. CapabilityStreams = "pull-stream-v1" // CapabilityAtomicState indicates support for the atomic native VT state // stream. Its payload format is advertised separately by blob open results. CapabilityAtomicState = "atomic-state-v1" )
const AtomicStateFormat = "ghostty-vt-snapshot-v1"
AtomicStateFormat identifies the opaque payload encoding returned by Session.AtomicState. The format is tied to ghostline's bundled VT implementation and is deliberately separate from the RPC wire version. Consumers must treat Payload as opaque and reject formats they do not understand.
const DefaultServerMaxClientConnections = 1024
DefaultServerMaxClientConnections is the maximum number of active client socket connections accepted by a Server when Options.ServerMaxClientConnections is zero. It leaves room for hundreds of long-lived output streams and their concurrent control calls on a trusted same-host socket.
const DefaultVTScrollbackMaxBytes uint64 = 2 << 20
DefaultVTScrollbackMaxBytes is the default logical scrollback budget for each embedded VT terminal. libghostty stores history in page-sized units, so the physical allocation can be somewhat larger than this value.
const ProtocolVersion = "1.0.0"
ProtocolVersion identifies the RPC protocol spoken by the server. Clients use it to detect an outdated server process during upgrades instead of failing on unknown methods.
const V0HandoffProtocolVersion = "ghostline-v0-to-v1-1"
V0HandoffProtocolVersion identifies the final v0 compatibility contract accepted by the v1 migration consumer. It is separate from ProtocolVersion so v1 never treats a v0 source as a native same-version daemon.
Variables ¶
var ( ErrUnavailable = errors.New("ghostline: libghostty-vt unavailable") // ErrClosed indicates that the hub is closed. ErrClosed = errors.New("ghostline: hub closed") // ErrSessionExists indicates that the name is already taken. ErrSessionExists = errors.New("ghostline: session already exists") // ErrSessionNotFound indicates that no session has the requested name. ErrSessionNotFound = errors.New("ghostline: session not found") // ErrSessionClosed indicates that a session handle is no longer usable. ErrSessionClosed = errors.New("ghostline: session closed") // ErrInvalidSessionName indicates that a name cannot identify session // storage safely. ErrInvalidSessionName = errors.New("ghostline: invalid session name") // ErrInvalidSignal indicates that Signal received nil, zero, or a signal // value that is not backed by syscall.Signal. ErrInvalidSignal = errors.New("ghostline: invalid process signal") // ErrInvalidCursor indicates a malformed cursor or a position beyond the // output currently available in its generation. ErrInvalidCursor = errors.New("ghostline: invalid output cursor") // ErrCursorExpired indicates that retention pruned the cursor's generation. ErrCursorExpired = errors.New("ghostline: output cursor expired") // ErrFrameTooLarge indicates that one RPC frame exceeded the protocol // limit. Large protocol payloads must use a chunked stream instead. ErrFrameTooLarge = errors.New("ghostline: RPC frame too large") // ErrProtocolMismatch indicates that peers use incompatible wire framing. ErrProtocolMismatch = errors.New("ghostline: RPC protocol mismatch") )
Functions ¶
func TagVersion ¶ added in v0.6.3
func TagVersion() string
TagVersion returns the Ghostline module version embedded in the running binary. Development builds and local replacements intentionally report an empty value because they do not carry a release tag.
Types ¶
type AdoptReport ¶ added in v1.1.1
AdoptReport contains per-session details for an adoption that could not recover the complete source inventory. A non-empty Skipped map means the destination committed no sessions and the source remains authoritative.
type AtomicState ¶ added in v1.1.0
type AtomicState struct {
// Format identifies Payload's serialization format.
Format string
// Payload is the opaque serialized VT state.
Payload []byte
// Cursor is the first raw output byte not represented by Payload.
Cursor Cursor
}
AtomicState is a complete terminal emulator state paired with the first raw output byte not represented by that state. It is suitable for an atomic reattach when the consumer can install the advertised Ghostty VT snapshot format.
Payload is not a VT replay stream. It is an opaque serialized state stream whose interpretation is selected by Format. The v1 format is the native Ghostty snapshot record stream and may contain scrollback, cursor, modes, parser continuation state, READY, and FINISH records. The payload and cursor are captured while the session output lock is held, so opening Output at Cursor after installing Payload cannot duplicate or omit bytes at the boundary.
type Checkpoint ¶ added in v0.2.0
type Checkpoint struct {
// Replay is a full VT replay of the visible grid and scrollback.
Replay []byte
// Cursor is the first raw output byte not covered by Replay.
Cursor Cursor
}
Checkpoint is an atomic screen replay and raw output position.
type Client ¶ added in v0.2.0
type Client struct {
// contains filtered or unexported fields
}
Client proxies Hub operations to a Server over a Unix socket.
func ConnectManaged ¶ added in v1.0.0
func ConnectManaged(ctx context.Context, options ManagedClientOptions) (*Client, error)
ConnectManaged returns a client, spawning the server when the socket is missing. The returned client owns the spawned process; Close stops it. This lifecycle behavior is intentionally separate from plain NewClient.
func (*Client) Close ¶ added in v0.3.0
Close stops the server that this client spawned. Clients that connected to an existing server have nothing to stop.
func (*Client) Ensure ¶ added in v0.3.0
Ensure starts the server if it is missing and waits until it is ready.
func (*Client) Get ¶ added in v1.0.0
Get returns a daemon-owned session handle or ErrSessionNotFound.
func (*Client) List ¶ added in v0.2.0
List returns daemon-owned sessions in the server's stable order.
func (*Client) PID ¶ added in v0.3.4
PID returns the process ID of the server spawned by this client, or zero when the client attached to an existing server.
func (*Client) Start ¶ added in v0.2.0
Start creates a session on the server and returns its remote handle.
func (*Client) Version ¶ added in v0.3.3
Version returns the server's RPC protocol version. Use VersionInfo when the release tag is also needed.
func (*Client) VersionInfo ¶ added in v0.6.3
func (c *Client) VersionInfo(ctx context.Context) (VersionInfo, error)
VersionInfo returns the server's RPC protocol version and release tag.
type ColorQueryCallback ¶ added in v0.6.2
type ColorQueryCallback func(ColorQueryKind) (color string, ok bool)
ColorQueryCallback supplies a color for an OSC 10 or OSC 11 query.
The callback should return a six-digit RGB value with an optional leading '#'. It returns false when the requested color is not available. A callback is optional; without one, unknown colors receive no reply. Feed invokes the callback synchronously without holding the responder's internal lock. The callback may re-enter the responder. Concurrent Feed calls may invoke it concurrently.
type ColorQueryKind ¶ added in v0.6.2
type ColorQueryKind uint8
ColorQueryKind identifies the terminal color requested by an OSC query.
const ( // ColorQueryForeground is the default text color (OSC 10). ColorQueryForeground ColorQueryKind = 10 // ColorQueryBackground is the default background color (OSC 11). ColorQueryBackground ColorQueryKind = 11 )
type Cursor ¶ added in v1.0.0
type Cursor struct {
// contains filtered or unexported fields
}
Cursor identifies a position in a session's output log. Its representation is intentionally opaque; cursors may be compared, stored as text, and passed back to Output, but their fields are not independently meaningful. The zero Cursor asks Output to start at the earliest retained byte.
func ParseCursor ¶ added in v1.0.0
ParseCursor parses the stable text representation produced by Cursor.String.
func (Cursor) MarshalText ¶ added in v1.0.0
MarshalText implements encoding.TextMarshaler.
func (Cursor) String ¶ added in v1.0.0
String returns the stable text form of c. The zero Cursor is encoded as an empty string.
func (*Cursor) UnmarshalText ¶ added in v1.0.0
UnmarshalText implements encoding.TextUnmarshaler.
type ExitError ¶ added in v0.3.0
type ExitError struct {
// Code is the process exit status, or -1 when the process was signaled.
Code int
// Signal names the terminating signal when the process was signaled.
Signal string
// Unknown is true when a migrated child exited after its original parent
// had already gone away. In that case the new server can observe the PTY
// closing, but the operating system cannot provide the original wait
// status to a different parent process.
Unknown bool
}
ExitError describes a terminated child process.
type Hub ¶ added in v0.2.0
type Hub struct {
// contains filtered or unexported fields
}
Hub owns local pseudo-terminal sessions.
func (*Hub) Close ¶ added in v0.2.0
Close terminates every session and prevents further Start calls.
type ManagedClientOptions ¶ added in v1.0.0
type ManagedClientOptions struct {
// Socket is the Unix socket path the server listens on.
Socket string
// Spawn is the command used to start the server when the socket is
// missing. Arguments may contain {socket}, replaced by Socket. Empty uses
// ["ghostline", "serve", "--socket", socket].
Spawn []string
// Env overrides the spawned server's environment.
Env []string
// ReadyTimeout bounds how long ConnectManaged waits for the socket. Zero
// uses 5s.
ReadyTimeout time.Duration
// Log receives serialized writes from the spawned server's stdout and
// stderr. Empty discards them after retaining bounded diagnostics.
Log io.Writer
}
ManagedClientOptions configures how ConnectManaged starts a missing server. Use NewClient when process lifecycle is owned by the caller or a service manager.
type Options ¶ added in v0.2.0
type Options struct {
// OutputDir stores segmented session output. An empty value uses
// $HOME/.ghostline/output.
OutputDir string
// DefaultSize is used when SessionOptions.Size is zero. The default is
// 120 columns by 36 rows.
DefaultSize Size
// DefaultTerm is used for pty children whose environment has no
// non-empty TERM. An empty value defaults to xterm-256color.
DefaultTerm string
// VTScrollbackMaxBytes is the default logical scrollback budget for new
// sessions. Zero uses DefaultVTScrollbackMaxBytes.
VTScrollbackMaxBytes uint64
// ProbeForeground enables OS-level foreground process metadata (name and
// command line). Disabled by default; Session.Metadata reports an empty
// process and command line without spawning any OS probes. The OSC 7
// working directory is parsed from the output stream regardless of this
// setting.
ProbeForeground bool
// ServerMaxClientConnections limits concurrently active client socket
// connections when these options are passed to NewServer. A connection is
// active for the life of an Output, Replay, or Checkpoint stream. Zero uses
// DefaultServerMaxClientConnections. Hub ignores this field.
ServerMaxClientConnections int
}
Options configures a Hub. Zero values select documented defaults.
type OutputReader ¶ added in v1.0.0
type OutputReader struct {
// contains filtered or unexported fields
}
OutputReader streams raw PTY output from a cursor. Read applies natural backpressure: it returns at most len(p) bytes and does not buffer the rest in memory. Close unblocks a pending Read. Cursor returns the next unread byte.
func (*OutputReader) Close ¶ added in v1.0.0
func (r *OutputReader) Close() error
Close implements io.Closer. It is safe to call more than once.
func (*OutputReader) Cursor ¶ added in v1.0.0
func (r *OutputReader) Cursor() Cursor
Cursor returns the next raw output position Read will deliver.
type ProcessSpec ¶ added in v1.0.0
type ProcessSpec struct {
// Path is the executable path. Empty starts the user's shell when
// ShellCommand and Args are also empty.
Path string
// Args are passed directly to Path without shell evaluation.
Args []string
// Directory is the child process working directory. Empty inherits the
// parent process working directory.
Directory string
// Environment overrides inherited variables using KEY=VALUE entries.
Environment []string
// ShellCommand is evaluated by "sh -lc" and cannot be combined with Path
// or Args.
ShellCommand string
}
ProcessSpec describes the process started inside a session. Path and Args are the primary, shell-free form. ShellCommand is explicit opt-in shell evaluation and cannot be combined with Path or Args. A zero ProcessSpec starts $SHELL, falling back to sh.
func Shell ¶ added in v1.0.0
func Shell(command string) ProcessSpec
Shell returns a process specification evaluated by "sh -lc".
type ProtocolLimits ¶ added in v1.0.0
type ProtocolLimits struct {
MaxHeaderBytes int `json:"maxHeaderBytes"`
MaxPayloadBytes int `json:"maxPayloadBytes"`
MaxChunkBytes int `json:"maxChunkBytes"`
}
ProtocolLimits are the framing limits advertised by VersionInfo.
type QueryResponder ¶
type QueryResponder struct {
// contains filtered or unexported fields
}
QueryResponder answers terminal capability queries while a session has no attached terminal client. TUIs such as Codex send DA/DSR/OSC/kitty keyboard queries at startup. A raw PTY has nobody to answer until a client attaches, so the application may downgrade itself (for example disabling colors). Replies are written back into the PTY as input, never into output. Feed and Resize are safe for concurrent use. The responder starts no goroutines.
func NewQueryResponder ¶
func NewQueryResponder() *QueryResponder
NewQueryResponder returns a responder initialized to a 120x36 terminal.
func NewQueryResponderWithColorQuery ¶ added in v0.6.2
func NewQueryResponderWithColorQuery(callback ColorQueryCallback) *QueryResponder
NewQueryResponderWithColorQuery returns a responder that uses callback to answer OSC 10 and OSC 11 color queries.
func (*QueryResponder) Feed ¶
func (r *QueryResponder) Feed(data []byte) [][]byte
Feed scans output bytes for complete terminal queries and returns the replies to write back into the PTY. Queries split across chunks are buffered until complete or until they prove not to be queries. Color callbacks run synchronously after parsing and outside the internal lock.
func (*QueryResponder) Resize ¶
func (r *QueryResponder) Resize(columns, rows int)
Resize updates the window size reported in XTWINOPS replies.
type Server ¶ added in v0.2.0
type Server struct {
// contains filtered or unexported fields
}
Server owns PTY sessions in a standalone process so clients can restart without ending any session. The wire protocol uses bounded JSON envelopes with optional exact-length raw payloads over a Unix socket.
func (*Server) Adopt ¶ added in v0.3.4
Adopt migrates sessions into this server. Call it before Serve so the target never accepts a client while its session map is being rebuilt.
func (*Server) AdoptWithReport ¶ added in v1.1.1
AdoptWithReport migrates sessions and reports per-session skips separately so control-plane callers can surface failures that could not be recovered. Native snapshot errors are handled as lossy recovery and do not appear in Skipped when the PTY and a target terminal can still be created.
type Session ¶ added in v0.2.0
type Session struct {
// contains filtered or unexported fields
}
Session is a concrete handle to one local or daemon-owned terminal session. Immutable identity is cached in the handle. Every method that can perform process, storage, or network I/O accepts a context and returns an error.
func (*Session) AtomicState ¶ added in v1.1.0
func (s *Session) AtomicState(ctx context.Context) (AtomicState, error)
AtomicState captures the terminal's complete emulator state and output cursor at one synchronization boundary. Payload is an opaque, versioned VT state envelope. Consumers must install it as one unit before applying raw output beginning at Cursor; they must not interleave that output with state installation.
func (*Session) Checkpoint ¶ added in v0.2.0
func (s *Session) Checkpoint(ctx context.Context) (Checkpoint, error)
Checkpoint atomically captures a replay and its output position.
func (*Session) CreatedAt ¶ added in v0.3.0
CreatedAt returns when the child process started without performing I/O.
func (*Session) Delete ¶ added in v1.0.0
Delete ends the process tree and removes the session record and output storage. Callers that need retained output must archive it before Delete.
func (*Session) Info ¶ added in v1.0.0
func (s *Session) Info() SessionInfo
Info returns the session's immutable identity without performing I/O.
func (*Session) Metadata ¶ added in v1.0.0
func (s *Session) Metadata(ctx context.Context) (SessionMetadata, error)
Metadata reports presentation metadata for the session. The working directory is the path the program reported through OSC 7 and is always collected from the parsed output stream. The foreground process name and command line require Options.ProbeForeground; both are best-effort and empty when probing is disabled or the foreground process cannot be resolved.
func (*Session) Name ¶ added in v0.2.0
Name returns the session's unique name without performing I/O.
func (*Session) Output ¶ added in v1.0.0
Output streams raw PTY output beginning at from. The zero Cursor starts at the earliest retained byte. The caller must close the returned reader.
func (*Session) OutputCursor ¶ added in v1.0.0
OutputCursor returns the current end of retained raw output without capturing a VT replay. Bytes may be appended immediately after it returns. Use Checkpoint when the cursor must be atomically paired with a replay.
func (*Session) PruneOutput ¶ added in v1.0.0
PruneOutput removes immutable generations strictly before before. before must be a generation-boundary cursor returned by RotateOutput.
func (*Session) Replay ¶ added in v1.0.0
Replay renders the visible grid and scrollback as terminal bytes.
func (*Session) RotateOutput ¶ added in v1.0.0
RotateOutput completes the active output segment and returns the boundary cursor at the beginning of the new generation.
func (*Session) Signal ¶ added in v1.0.0
Signal sends signal to the session's process group. signal must be a non-zero syscall.Signal, such as os.Interrupt or syscall.SIGTERM.
func (*Session) Status ¶ added in v0.3.0
Status reports whether the session is running and, when stopped, why. A fatal session runtime or storage failure is returned as an error.
func (*Session) Terminate ¶ added in v1.0.0
Terminate ends the process tree but keeps the session record and output.
type SessionInfo ¶ added in v1.0.0
SessionInfo is immutable session identity returned by List.
type SessionMetadata ¶ added in v0.5.0
type SessionMetadata struct {
// Process is the foreground process name. It is empty when foreground
// probing is disabled or the process cannot be resolved.
Process string `json:"process,omitempty"`
// CommandLine is the foreground process command line including arguments.
// It is empty when foreground probing is disabled or the process cannot be
// resolved.
CommandLine string `json:"commandLine,omitempty"`
// Directory is the working directory the program reported through OSC 7.
// It is empty until a valid report is parsed.
Directory string `json:"directory,omitempty"`
}
SessionMetadata is presentation metadata for one session. It is not lifecycle state, and every field is best-effort.
type SessionOptions ¶ added in v0.2.0
type SessionOptions struct {
// Name identifies the session and its output storage. It must be a single,
// non-empty path component.
Name string
// Process describes the child process. Its zero value starts the user's
// shell without evaluating a command string.
Process ProcessSpec
// Size is the initial grid size. A zero value uses the hub's default.
Size Size
// VTScrollbackMaxBytes overrides the Hub default for this session. Zero
// inherits the Hub setting.
VTScrollbackMaxBytes uint64
}
SessionOptions configures one session.
type Size ¶ added in v0.2.0
type Size struct {
// Columns is the number of character cells per line.
Columns int
// Rows is the number of lines in the grid.
Rows int
}
Size is a terminal grid size in cells.
type Status ¶ added in v0.3.0
type Status struct {
// Alive is true while the child process is running.
Alive bool `json:"alive"`
// Exit describes the termination when Alive is false.
Exit *ExitError `json:"exit,omitempty"`
}
Status describes whether a session is running and, when stopped, why.
type VersionInfo ¶ added in v0.6.3
type VersionInfo struct {
// ProtocolVersion is the server's RPC protocol identifier.
ProtocolVersion string
// TagVersion is the server module's release tag, or empty for a
// development build or local replacement.
TagVersion string
// Capabilities contains stable feature names understood by the server.
// Clients must ignore names they do not recognize.
Capabilities []string
// Limits contains the server's enforced wire framing limits.
Limits ProtocolLimits
// MaxClientConnections is the maximum number of active client sockets the
// daemon accepts. Long-lived streams count against this limit.
MaxClientConnections int
}
VersionInfo describes the protocol and release tag reported by a v1 server.