ghostline

package module
v0.6.7 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 26 Imported by: 0

README

ghostline

ghostline is an embeddable terminal engine for Go. It owns real pseudo-terminals, keeps sessions running independently of attached clients, stores raw output in append-only spools, and renders complete terminal replays with libghostty-vt.

It provides terminal mechanics rather than a transport or UI. Applications can build a local multiplexer, remote shell service, development agent, browser terminal, or their own session protocol on top.

Capabilities

  • Process-owned PTY sessions with input, resize, and exit reporting
  • Ghostty-compatible VT state, scrollback, colors, alternate screens, and synchronized output
  • Raw append-only output subscriptions with resumable byte offsets
  • Atomic checkpoints pairing a full VT replay with its exact spool boundary
  • Configurable VT scrollback budgets with a 2 MiB default
  • Detached-mode terminal query responses for TUIs
  • Rolling server upgrades that keep PTY children and emulator state alive, including a bounded spool-replay bridge for pre-0.6.0 sources
  • Local Hub and Unix-socket Server/Client with one Session API

Requirements

  • Go 1.25+
  • Unix-like system (macOS, Linux, BSD)
  • libghostty-vt; see libghostty-vt below

Quick start: local hub

hub, err := ghostline.New(ghostline.Options{
	OutputDir:   "/var/lib/my-app/terminals",
	DefaultSize: ghostline.Size{Columns: 120, Rows: 36},
})
if err != nil {
	return err
}
defer hub.Close()

session, err := hub.Start(ctx, ghostline.SessionOptions{
	Name:        "build-shell",
	Directory:   "/path/to/worktree",
	Command:     "bash",
	Environment: []string{"MY_APP=1"},
})
if err != nil {
	return err
}

watcher, err := session.WatchOutput(ghostline.WatchOptions{
	OnOutput: func(data []byte) {
		_, _ = os.Stdout.Write(data)
	},
})
if err != nil {
	return err
}
defer watcher.Close()

_ = session.Input(ctx, []byte("go test ./...\r"))
_ = session.Resize(ctx, ghostline.Size{Columns: 100, Rows: 30})

WatchOutput starts at a raw spool offset. Its callback receives a borrowed slice that is valid only until the callback returns; copy it if it must be retained. File notifications wake idle watchers when output arrives on Darwin and Linux; a low-frequency heartbeat covers filesystems that miss or coalesce notifications without continuously polling every Session.

VT scrollback and raw spool retention are separate. Configure the default VT scrollback for a Hub with Options.VTScrollbackMaxBytes, or override it for a single session with SessionOptions.VTScrollbackMaxBytes. See scrollback and output retention for the retention model, recommended values, and comparisons with other terminal runtimes.

Child processes inherit the embedding process's environment; SessionOptions.Environment overrides individual KEY=value entries. When the resulting environment has no non-empty TERM, ghostline sets one from Options.DefaultTerm, defaulting to xterm-256color, so detached daemons start shells without a terminal type warning.

Quick start: server and client

Run the standalone daemon:

go run ./cmd/ghostline serve --socket /tmp/ghostline.sock

Embed the server, or connect from another process:

client := ghostline.NewClient("/tmp/ghostline.sock")
if err := client.Check(ctx); err != nil {
	return err
}

session, err := client.Start(ctx, ghostline.SessionOptions{
	Name:      "remote-shell",
	Directory: "/srv/worktree",
	Command:   "bash",
})
if err != nil {
	return err
}

Client.Start returns a Session with the same methods as a local one, including Wait, Checkpoint, and Recover. Clients and the server must share the same filesystem because output watchers read the spool files directly.

Rolling server upgrades

The server can be upgraded without ending sessions. Both processes must speak the admin-socket protocol, and the new server must use the same output directory as the old one. A fresh server adopts every session from the old one over its management socket, then serves in place of it:

ghostline serve --socket /tmp/ghostline-new.sock --adopt-from /tmp/ghostline.sock.admin

Adoption is all-or-nothing:

  • The old server pauses each session at a stable point, drains pending PTY output into the spool and emulator, and transfers the master fd over SCM_RIGHTS together with the encoded terminal snapshot.
  • The new server prepares every session before committing any of them. If any session fails to prepare, the whole batch is aborted and the source server keeps serving unchanged. The new emulator restores each session's snapshot, including its grid, scrollback, cursor, and terminal modes.
  • After the batch commits, the new server binds its public socket and the old server is asked to retire. Retirement confirmation is best-effort; once the batch commits, the new server keeps serving the adopted sessions even if the source endpoint closes without a response. Children never see a disconnect, and spool offsets stay valid because the spool is never rewound.

The embedding daemon coordinates the switch and retires the old process; see docs/rfc/0002-serve-rolling-upgrade.md.

Server bootstrap

Connect starts the server when the socket is missing:

client, err := ghostline.Connect(ctx, ghostline.ConnectOptions{
	Socket: "/tmp/ghostline.sock",
})
if err != nil {
	return err
}
defer client.Close()

The default spawn command is ghostline serve --socket <path>. Spawn can override it, with {socket} replaced by the socket path; Env and Log configure the spawned process. Ensure pre-warms the server without an operation. A spawn that exits before becoming ready is reported immediately, including its output. Concurrent Connect calls are safe: the first server to bind wins, and the other clients attach to it without owning it.

Recovery is lazy and restricted: read-only calls and Start may respawn and retry once after a dead socket. Input, Resize, Close, Remove, and spool maintenance are never retried automatically. Close stops only the server this client spawned; connecting to an existing server is a no-op.

Checkpoints

For a lossless reattach or window switch, pause the watcher and use an atomic checkpoint:

watcher.Pause()
checkpoint, err := session.Checkpoint(ctx)
if err == nil {
	err = watcher.SkipTo(checkpoint.Offset)
}
if err == nil {
	_, err = client.Write(checkpoint.Replay)
}
watcher.Resume()

Bytes below Checkpoint.Offset are represented by Checkpoint.Replay; bytes written afterwards remain available to the resumed watcher.

minimux example

examples/minimux is a small in-process terminal multiplexer built on the public Hub and Session APIs:

cd examples/minimux && go run .
cd examples/minimux && go run . -- htop

It demonstrates multiple live windows, background TUI query responses, terminal resizing, output subscriptions, and atomic VT replay on window switches.

Key Action
Ctrl-B c Create a shell window
Ctrl-B n Switch to the next window
Ctrl-B p Switch to the previous window
Ctrl-B x Close the current window
Ctrl-B q Quit and terminate all windows
Ctrl-B Ctrl-B Send a literal Ctrl-B

libghostty-vt

The repository includes the Ghostty C headers and a prebuilt macOS arm64 library. Other platforms must build libghostty-vt from Ghostty source with Zig 0.16.0 or newer:

The bundled copy is built from Ghostty commit 5851d986 (1.3.2-dev) with Zig 0.16.0 and ReleaseFast optimization.

brew install zig@0.16
git clone https://github.com/ghostty-org/ghostty
cd ghostty
/opt/homebrew/opt/zig@0.16/bin/zig build \
  -Doptimize=ReleaseFast -Demit-lib-vt=true

Point the external linker and runtime loader at that build on platforms that do not use the bundled macOS arm64 library:

export GHOSTTY_VT_DIR="$HOME/Workspace/gh/ghostty/zig-out"
export CGO_LDFLAGS="-L$GHOSTTY_VT_DIR/lib"
export DYLD_LIBRARY_PATH="$GHOSTTY_VT_DIR/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}" # macOS
# export LD_LIBRARY_PATH="$GHOSTTY_VT_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"   # Linux

Builds with CGO_ENABLED=0 compile, but Hub.Check and Start return ErrUnavailable because VT emulation requires libghostty-vt.

Protocol and security

The server speaks JSON-lines over a Unix socket and creates the socket with mode 0600. The rolling-upgrade management socket (<socket>.admin) uses the same mode and is only ever connected to by a fresh server process, never by clients. The RPC enforces an idle deadline, a message size limit, and a concurrent connection cap. Both sockets are designed for same-machine, trusted callers; there is no authentication. Do not expose them to untrusted users.

Lifecycle

  • Start rejects names that are already known; call Remove before reusing a name.
  • Close terminates a session but keeps its record and spool for inspection.
  • Remove deletes the in-memory record; spool files stay on disk.
  • Hub.Close terminates every session.
  • Session.Wait returns an ExitError with the exit code or signal. A child that exits after a rolling upgrade may report ExitError.Unknown, because its new owner cannot recover the old process's wait status. Context cancellation stops waiting but does not terminate the child.
  • Status distinguishes a stopped session from a remote network failure; Alive is a best-effort convenience.
  • Sessions implement MetadataProvider.Metadata, reporting the OS-level foreground process and working directory. It is opt-in: construct the Hub/Server with ProbeForeground: true (or pass --probe-foreground to ghostline serve). The probe resolves the PTY's foreground process group with TIOCGPGRP and reads the process from /proc on Linux or ps/lsof on macOS. Disabled by default; Metadata returns empty values without probing.
  • Spool maintenance lives on Session: Recover, TruncateSpool, ArchiveSpool, and RemoveSpool.
  • Use errors.Is with ErrUnavailable, ErrClosed, ErrSessionExists, ErrSessionNotFound, ErrSessionClosed, and ErrInvalidSessionName; error identity is preserved across the RPC boundary.

Layout

  • hub.go - session hub and start options
  • session.go - local and remote session API
  • process.go - PTY child lifecycle
  • migrate.go - rolling-upgrade admin protocol and session adoption
  • spool.go - append-only output watcher
  • query.go - detached-mode terminal query responder
  • terminal.go - libghostty-vt CGo wrapper
  • rpc.go, client.go, server.go - Unix-socket protocol
  • cmd/ghostline - standalone server command
  • examples/minimux - runnable terminal multiplexer example

Documentation

Overview

Package ghostline provides embeddable Unix pseudo-terminal sessions backed by libghostty-vt screen replays and append-only output spools. A Hub runs sessions in-process; a Server and Client expose the same Session API over a Unix socket.

Index

Constants

View Source
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.

View Source
const ProtocolVersion = "0.6.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.

Variables

View Source
var (
	// ErrUnavailable indicates that libghostty-vt cannot be used by this build.
	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 a spool file.
	ErrInvalidSessionName = errors.New("ghostline: invalid session name")
)

Functions

func Adopt added in v0.3.4

func Adopt(ctx context.Context, adminSocket string, h *Hub) (int, error)

Adopt migrates every session from the server listening on adminSocket into h. The old server pauses a complete batch, the new server prepares every state locally, and only then does either side change ownership.

func Ping added in v0.2.0

func Ping(socketPath string) bool

Ping reports whether a ghostline server is accepting connections on socketPath.

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 Checkpoint added in v0.2.0

type Checkpoint struct {
	// Replay is a full VT replay of the visible grid and scrollback.
	Replay []byte
	// Offset is the raw spool byte position covered by Replay.
	Offset int64
}

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 Connect added in v0.3.0

func Connect(ctx context.Context, options ConnectOptions) (*Client, error)

Connect returns a client, spawning the server when the socket is missing. The returned client owns the spawned process; Close stops it.

func NewClient added in v0.2.0

func NewClient(socketPath string) *Client

NewClient returns a client for the server at socketPath.

func (*Client) Check added in v0.2.0

func (c *Client) Check(ctx context.Context) error

Check verifies that the server socket accepts connections.

func (*Client) Close added in v0.3.0

func (c *Client) Close() error

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

func (c *Client) Ensure(ctx context.Context) error

Ensure starts the server if it is missing and waits until it is ready.

func (*Client) List added in v0.2.0

func (c *Client) List(ctx context.Context) ([]string, error)

List returns the names of all sessions known to the server.

func (*Client) PID added in v0.3.4

func (c *Client) PID() int

PID returns the process ID of the server spawned by this client, or zero when the client attached to an existing server.

func (*Client) Session added in v0.3.2

func (c *Client) Session(name string) (Session, bool)

Session returns a handle for a session known to the server, mirroring Hub.Session. The handle is lazy; operations fail with the server's error if the session disappears.

func (*Client) Sessions added in v0.3.2

func (c *Client) Sessions() []Session

Sessions returns handles for all sessions known to the server, ordered by name, mirroring Hub.Sessions.

func (*Client) Socket added in v0.2.0

func (c *Client) Socket() string

Socket returns the server socket path.

func (*Client) Start added in v0.2.0

func (c *Client) Start(ctx context.Context, options SessionOptions) (Session, error)

Start creates a session on the server and returns its remote handle.

func (*Client) Version added in v0.3.3

func (c *Client) Version(ctx context.Context) (string, error)

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. An error means the server predates version reporting or is unreachable.

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.

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 ConnectOptions added in v0.3.0

type ConnectOptions 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 Connect waits for the socket. Zero uses 5s.
	ReadyTimeout time.Duration
	// Log receives the spawned server's stdout and stderr. Empty discards it.
	Log io.Writer
}

ConnectOptions configures how Connect starts a missing server.

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.

func (*ExitError) Error added in v0.3.0

func (e *ExitError) Error() string

type Hub added in v0.2.0

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

Hub owns local pseudo-terminal sessions.

func New added in v0.2.0

func New(options Options) (*Hub, error)

New constructs a session hub.

func (*Hub) Check added in v0.2.0

func (h *Hub) Check(ctx context.Context) error

Check verifies that libghostty-vt can create a terminal.

func (*Hub) Close added in v0.2.0

func (h *Hub) Close() error

Close terminates every session and prevents further Start calls.

func (*Hub) Session added in v0.2.0

func (h *Hub) Session(name string) (Session, bool)

Session returns a handle for a known session name.

func (*Hub) Sessions added in v0.2.0

func (h *Hub) Sessions() []Session

Sessions returns all known sessions ordered by creation time and name.

func (*Hub) Start added in v0.2.0

func (h *Hub) Start(ctx context.Context, options SessionOptions) (Session, error)

Start creates and starts a session.

type MetadataProvider added in v0.5.0

type MetadataProvider interface {
	// Metadata reports OS-level foreground process metadata when the hub was
	// created with ProbeForeground enabled. When probing is disabled it
	// returns zero values; otherwise it may return an error when the
	// foreground process cannot be resolved.
	Metadata(ctx context.Context) (SessionMetadata, error)
}

MetadataProvider is implemented by sessions that can report OS-level foreground process metadata. It is kept separate from Session so existing Session implementations and test doubles continue to compile.

type Options added in v0.2.0

type Options struct {
	// OutputDir stores session spools. 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/cwd metadata.
	// Disabled by default; Session.Metadata returns empty values without
	// spawning any OS probes.
	ProbeForeground bool
}

Options configures a Hub. Zero values select documented defaults.

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.

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.

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 is one JSON object per line on a Unix socket; []byte fields use JSON base64 encoding automatically.

func NewServer added in v0.2.0

func NewServer(options Options) (*Server, error)

NewServer constructs a server with its own hub.

func (*Server) Adopt added in v0.3.4

func (s *Server) Adopt(ctx context.Context, adminSocket string) (int, error)

Server.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) Close added in v0.2.0

func (s *Server) Close() error

Close stops accepting connections. Sessions keep running.

func (*Server) Serve added in v0.2.0

func (s *Server) Serve(ctx context.Context, socketPath string) error

Serve listens on socketPath and handles requests until ctx is canceled or the listener fails. The socket is created with mode 0600.

func (*Server) Shutdown added in v0.3.0

func (s *Server) Shutdown(ctx context.Context) error

Shutdown stops accepting connections and terminates every session.

type Session added in v0.2.0

type Session interface {
	// Name returns the session's unique name.
	Name() string
	// CreatedAt returns when the child process started.
	CreatedAt() time.Time
	// Done is closed after the child exits and all output is consumed.
	Done() <-chan struct{}
	// Wait waits for the child and returns its exit error. Context
	// cancellation stops waiting but does not terminate the child.
	Wait(ctx context.Context) error
	// Alive reports whether the session is currently running.
	Alive() bool
	// Status distinguishes a running session from a stopped one and reports
	// the exit reason when stopped.
	Status(ctx context.Context) (Status, error)
	// Input writes bytes to the PTY verbatim.
	Input(ctx context.Context, data []byte) error
	// Resize updates the real PTY and the emulated grid.
	Resize(ctx context.Context, size Size) error
	// Snapshot returns a full VT replay of the visible grid and scrollback.
	Snapshot(ctx context.Context) ([]byte, error)
	// Checkpoint captures a replay and its exact spool boundary atomically.
	Checkpoint(ctx context.Context) (Checkpoint, error)
	// Recover reads the raw spool range [offset, end).
	Recover(ctx context.Context, offset, end int64) ([]byte, error)
	// SpoolPath returns the append-only raw output spool path.
	SpoolPath() string
	// SpoolSize returns the current raw output spool size.
	SpoolSize(ctx context.Context) (int64, error)
	// WatchOutput subscribes to raw output and starts the watcher.
	WatchOutput(options WatchOptions) (*SpoolWatcher, error)
	// Close terminates the session. The record stays visible until Remove.
	Close() error
	// Remove deletes the session record. Spool files stay on disk.
	Remove() error
	// TruncateSpool compacts the live spool in place.
	TruncateSpool(ctx context.Context) error
	// ArchiveSpool compresses the spool and prunes old archives.
	ArchiveSpool(ctx context.Context) error
	// RemoveSpool deletes the spool and its archives.
	RemoveSpool()
}

Session is a stable handle to one session, local or remote.

type SessionMetadata added in v0.5.0

type SessionMetadata struct {
	// Process is the foreground process name.
	Process string `json:"process"`
	// Directory is the foreground process working directory.
	Directory string `json:"directory"`
}

SessionMetadata is the OS-level foreground process snapshot for one session. It is presentation metadata, not lifecycle state.

type SessionOptions added in v0.2.0

type SessionOptions struct {
	// Name identifies the session and its spool file. It must be a single,
	// non-empty path component.
	Name string
	// Directory is the child's working directory. An empty value inherits the
	// embedding process's working directory.
	Directory string
	// Command is evaluated by "sh -lc". An empty value starts $SHELL, falling
	// back to sh.
	Command string
	// Size is the initial grid size. A zero value uses the hub's default.
	Size Size
	// Environment entries use KEY=value form and override inherited values.
	Environment []string
	// 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 SpoolWatcher

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

SpoolWatcher reads an append-only spool from a persisted byte offset, draining to EOF whenever the file grows. The byte slice passed to onBytes is valid only for the duration of the callback; callers must copy it to retain it.

The watcher also detects in-place truncation (spool compaction). After a truncate the file size drops below the watcher offset; the watcher re-bases to offset zero and calls onRotate so the consumer can invalidate old offsets instead of silently skipping bytes.

func NewSpoolWatcher

func NewSpoolWatcher(path string, offset int64, onBytes func([]byte), onRotate func(), onOverflow func()) (*SpoolWatcher, error)

NewSpoolWatcher returns a watcher positioned at offset in the file at path. The callbacks may be nil. Start begins watching.

func (*SpoolWatcher) Close

func (w *SpoolWatcher) Close()

Close stops the watcher and releases its file descriptor. It is safe to call multiple times.

func (*SpoolWatcher) Offset

func (w *SpoolWatcher) Offset() int64

Offset returns the next byte position the watcher will deliver.

func (*SpoolWatcher) Pause

func (w *SpoolWatcher) Pause()

Pause blocks until any in-flight drain finishes, then prevents new drains. Use it while preparing a checkpoint replay so live reads cannot interleave.

func (*SpoolWatcher) Ping

func (w *SpoolWatcher) Ping()

Ping asks the watcher to check for output without waiting for its next poll.

func (*SpoolWatcher) Resume

func (w *SpoolWatcher) Resume()

Resume re-enables draining after Pause and asks the watcher to check immediately.

func (*SpoolWatcher) SetMaxBytes

func (w *SpoolWatcher) SetMaxBytes(maxBytes int64)

SetMaxBytes configures the spool size cap before Start. When the watcher passes the cap it calls onOverflow so the consumer can compact the spool.

func (*SpoolWatcher) SkipTo

func (w *SpoolWatcher) SkipTo(offset int64) error

SkipTo re-bases the watcher to a byte position covered by a snapshot. It must be called while paused and the offset must be within the current file; any unread bytes below the target were already rendered by the snapshot and must not be delivered again.

func (*SpoolWatcher) Start

func (w *SpoolWatcher) Start()

Start begins watching. Repeated calls are safe and have no effect.

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 VTTerminal

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

VTTerminal is a libghostty-vt terminal emulator that renders raw PTY bytes into a complete screen snapshot (visible grid + scrollback) with SGR styles preserved. It is the server-side counterpart of the Ghostty client, so a replayed snapshot matches exactly what the client would have rendered.

func NewVTTerminal

func NewVTTerminal(cols, rows int) (*VTTerminal, error)

NewVTTerminal creates a terminal emulator with the given grid size.

func NewVTTerminalWithOptions added in v0.6.1

func NewVTTerminalWithOptions(cols, rows int, options VTTerminalOptions) (*VTTerminal, error)

NewVTTerminalWithOptions creates a terminal emulator with the given grid size and VT configuration.

func (*VTTerminal) Close

func (v *VTTerminal) Close()

Close releases the native terminal state. It must be called at most once.

func (*VTTerminal) EncodeState added in v0.3.4

func (v *VTTerminal) EncodeState() ([]byte, error)

EncodeState encodes the full emulator state (visible grid, scrollback, cursor, and terminal modes) so a session can be migrated to another server process.

func (*VTTerminal) Feed

func (v *VTTerminal) Feed(data []byte)

Feed parses raw PTY bytes into the emulated terminal state.

func (*VTTerminal) Resize

func (v *VTTerminal) Resize(cols, rows int)

Resize reflows the emulated terminal. The caller keeps the real PTY size in sync so snapshots are rendered at the client's dimensions.

func (*VTTerminal) RestoreState added in v0.3.4

func (v *VTTerminal) RestoreState(snapshot []byte) error

RestoreState replaces the emulated state with bytes produced by EncodeState.

func (*VTTerminal) Snapshot

func (v *VTTerminal) Snapshot() ([]byte, error)

Snapshot renders the current emulated screen (visible grid + scrollback) as VT sequences that preserve colors and styles.

type VTTerminalOptions added in v0.6.1

type VTTerminalOptions struct {
	// ScrollbackMaxBytes is the maximum logical scrollback allocation. Zero
	// uses DefaultVTScrollbackMaxBytes.
	ScrollbackMaxBytes uint64
}

VTTerminalOptions configures the embedded VT terminal.

type VersionInfo added in v0.6.3

type VersionInfo struct {
	ProtocolVersion string
	TagVersion      string
}

VersionInfo describes the protocol and release tag reported by a server. Older servers may leave TagVersion empty because the field was added after protocol versioning; callers can still use ProtocolVersion for compatibility checks.

type WatchOptions added in v0.2.0

type WatchOptions struct {
	// Offset is the first spool byte to deliver.
	Offset int64
	// MaxBytes invokes OnOverflow after the watcher passes the limit. Zero
	// uses the watcher default.
	MaxBytes int64
	// OnOutput receives borrowed bytes; copy them to retain after return.
	OnOutput func([]byte)
	// OnTruncate runs when the spool is compacted in place.
	OnTruncate func()
	// OnOverflow runs when Offset passes MaxBytes.
	OnOverflow func()
}

WatchOptions configures an output subscription.

Directories

Path Synopsis
cmd
ghostline command

Jump to

Keyboard shortcuts

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