Documentation
¶
Overview ¶
Package ghostline provides embeddable pseudo-terminal sessions backed by libghostty-vt screen replays and append-only output spools.
Index ¶
- Variables
- func Ping(socketPath string) bool
- type Checkpoint
- type Client
- func (c *Client) ArchiveSpool(ctx context.Context, name string) error
- func (c *Client) Capture(ctx context.Context, name string) ([]byte, error)
- func (c *Client) Check(ctx context.Context) error
- func (c *Client) Checkpoint(ctx context.Context, name string) (Checkpoint, error)
- func (c *Client) Create(ctx context.Context, name, directory, command string) error
- func (c *Client) EnsurePipe(ctx context.Context, name string) error
- func (c *Client) Exists(ctx context.Context, name string) bool
- func (c *Client) Input(ctx context.Context, name string, data []byte) error
- func (c *Client) Kill(ctx context.Context, name string) error
- func (c *Client) List(ctx context.Context) (map[string]bool, error)
- func (c *Client) ListCreated(ctx context.Context) (map[string]time.Time, error)
- func (c *Client) Recover(ctx context.Context, name string, offset, end int64) ([]byte, error)
- func (c *Client) RemoveSpool(name string)
- func (c *Client) Resize(ctx context.Context, name string, columns, rows int) error
- func (c *Client) SpoolPath(name string) string
- func (c *Client) SpoolSize(ctx context.Context, name string) (int64, error)
- func (c *Client) Start(ctx context.Context, options SessionOptions) (*Session, error)
- func (c *Client) TruncateSpool(ctx context.Context, name string) error
- func (c *Client) WaitReady(ctx context.Context, timeout time.Duration) error
- type Hub
- func (p *Hub) ArchiveSpool(_ context.Context, runtimeName string) error
- func (p *Hub) Capture(_ context.Context, runtimeName string) ([]byte, error)
- func (p *Hub) Check(ctx context.Context) error
- func (p *Hub) Close() error
- func (p *Hub) Create(ctx context.Context, runtimeName, directory, command string) error
- func (p *Hub) CreatedPath(runtimeName string) string
- func (p *Hub) EnsurePipe(_ context.Context, runtimeName string) error
- func (p *Hub) Exists(_ context.Context, runtimeName string) bool
- func (p *Hub) Input(_ context.Context, runtimeName string, data []byte) error
- func (p *Hub) Kill(_ context.Context, runtimeName string) error
- func (p *Hub) List(context.Context) (map[string]bool, error)
- func (p *Hub) ListCreated(context.Context) (map[string]time.Time, error)
- func (p *Hub) PIDPath(runtimeName string) string
- func (p *Hub) Recover(_ context.Context, runtimeName string, offset, end int64) ([]byte, error)
- func (p *Hub) RemoveSpool(runtimeName string)
- func (p *Hub) Resize(_ context.Context, runtimeName string, columns, rows int) error
- func (p *Hub) Session(name string) (*Session, bool)
- func (p *Hub) Sessions() []*Session
- func (p *Hub) SpoolPath(runtimeName string) string
- func (p *Hub) SpoolSize(_ context.Context, runtimeName string) (int64, error)
- func (p *Hub) Start(ctx context.Context, options SessionOptions) (*Session, error)
- func (p *Hub) TruncateSpool(_ context.Context, runtimeName string) error
- type Options
- type PTY
- type QueryResponder
- type Server
- type Session
- func (s *Session) Checkpoint(ctx context.Context) (Checkpoint, error)
- func (s *Session) Close() error
- func (s *Session) Name() string
- func (s *Session) SpoolPath() string
- func (s *Session) SpoolSize(ctx context.Context) (int64, error)
- func (s *Session) WatchOutput(options WatchOptions) (*SpoolWatcher, error)
- type SessionOptions
- type Size
- type SpoolRecoverer
- type SpoolWatcher
- type VTTerminal
- type WatchOptions
Constants ¶
This section is empty.
Variables ¶
var ( ErrUnavailable = errors.New("ghostline is unavailable") // ErrClosed indicates that an operation requires an open hub. ErrClosed = errors.New("ghostline hub is closed") // ErrSessionExists indicates that a hub already owns the requested name. ErrSessionExists = errors.New("ghostline session already exists") // ErrSessionNotFound indicates that a hub does not own the requested name. ErrSessionNotFound = errors.New("ghostline session not found") // ErrSessionClosed indicates that a Session handle no longer refers to a // session owned by its hub. ErrSessionClosed = errors.New("ghostline session is closed") // ErrInvalidSessionName indicates that a name is empty or unsafe for use as // a spool filename. ErrInvalidSessionName = errors.New("invalid ghostline session name") )
Functions ¶
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. Bytes below Offset are represented by Replay; a paused watcher can SkipTo Offset before resuming without losing or duplicating output produced around the snapshot.
type Client ¶ added in v0.2.0
type Client struct {
Socket string
}
Client proxies Hub operations to a ghostline Server over a Unix socket. Sessions returned by Start are remote handles with the same API as local ones, so an embedding process can restart and reconnect without ending any session.
func (*Client) ArchiveSpool ¶ added in v0.2.0
func (*Client) Checkpoint ¶ added in v0.2.0
func (*Client) EnsurePipe ¶ added in v0.2.0
func (*Client) ListCreated ¶ added in v0.2.0
func (*Client) RemoveSpool ¶ added in v0.2.0
func (*Client) Start ¶ added in v0.2.0
Start creates a session on the server and returns its remote handle.
func (*Client) TruncateSpool ¶ added in v0.2.0
type Hub ¶ added in v0.2.0
type Hub struct {
// OutputDir is the directory used for spool and metadata files.
//
// Deprecated: configure Options.OutputDir when constructing the hub.
OutputDir string
// contains filtered or unexported fields
}
Hub owns a set of pseudo-terminal sessions. Sessions keep running while clients disconnect, but they remain children of the embedding process and therefore do not survive that process exiting.
func (*Hub) ArchiveSpool ¶ added in v0.2.0
ArchiveSpool compresses the current spool to a timestamped .gz file and prunes old archives. Best-effort diagnostics; truncation must not depend on archive success.
func (*Hub) Capture ¶ added in v0.2.0
Capture renders the current emulated screen (visible grid + scrollback) with SGR styles preserved, so the client can replay a complete snapshot at its own size. This replaces the raw spool replay, which could not restore the screen when the PTY history was produced at a different size.
func (*Hub) Check ¶ added in v0.2.0
Check reports whether the hub can construct a libghostty-vt terminal.
func (*Hub) Close ¶ added in v0.2.0
Close terminates every managed session and releases its resources. A closed runtime cannot create new sessions.
func (*Hub) CreatedPath ¶ added in v0.2.0
CreatedPath returns the persisted creation metadata path.
func (*Hub) EnsurePipe ¶ added in v0.2.0
EnsurePipe verifies that a session exists. It is retained for compatibility with adapters that install output pipes lazily; Hub owns its spool from session creation and therefore needs no additional setup.
func (*Hub) Kill ¶ added in v0.2.0
Kill terminates a named session. If the current hub does not own it, Kill uses persisted PID metadata to reclaim a process from an earlier run.
func (*Hub) ListCreated ¶ added in v0.2.0
ListCreated returns persisted session creation times. A restarted embedding process can use them to identify and reclaim children it no longer owns.
func (*Hub) Recover ¶ added in v0.2.0
Recover returns the spool bytes in [offset, end), the raw PTY output a client still needs after its anchor. Callers can prefer this over a full snapshot whenever the spool still covers the anchor, so switching back to a retained surface renders the missing tail without clearing the screen.
func (*Hub) RemoveSpool ¶ added in v0.2.0
RemoveSpool removes a session's spool, metadata, and archives. Callers must terminate the session and close its watchers first.
func (*Hub) Session ¶ added in v0.2.0
Session returns a handle for a managed session name, including sessions whose process has already exited but has not been closed or removed.
func (*Hub) Sessions ¶ added in v0.2.0
Sessions returns all managed sessions ordered by creation time and name, including sessions whose process has already exited.
func (*Hub) SpoolPath ¶ added in v0.2.0
SpoolPath returns the raw output spool path, or an empty string for an invalid session name.
func (*Hub) SpoolSize ¶ added in v0.2.0
SpoolSize returns the number of raw output bytes currently persisted.
func (*Hub) TruncateSpool ¶ added in v0.2.0
TruncateSpool compacts the live spool in place. The copyOutput goroutine keeps its O_APPEND file descriptor, so output continues into the same inode from byte zero. Consumers should reset their offsets and reanchor.
type Options ¶ added in v0.2.0
type Options struct {
// OutputDir stores append-only output spools and session metadata. 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
}
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 (*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 (for example a headless daemon) can restart without ending any session. The server writes raw PTY bytes to the same append-only spool files; clients read those files directly for incremental output and recovery.
The wire protocol is one JSON object per line on a Unix socket. Binary payloads (input, snapshots) are base64 fields.
type Session ¶ added in v0.2.0
type Session struct {
// contains filtered or unexported fields
}
Session is a stable handle to one pseudo-terminal session, local or remote.
func (*Session) Checkpoint ¶ added in v0.2.0
func (s *Session) Checkpoint(ctx context.Context) (Checkpoint, error)
Checkpoint captures a replay and its exact spool boundary atomically.
func (*Session) Close ¶ added in v0.2.0
Close terminates the session. It is idempotent for this handle.
func (*Session) SpoolPath ¶ added in v0.2.0
SpoolPath returns the append-only raw output spool path.
func (*Session) WatchOutput ¶ added in v0.2.0
func (s *Session) WatchOutput(options WatchOptions) (*SpoolWatcher, error)
WatchOutput subscribes to raw output and starts the watcher before returning.
type SessionOptions ¶ added in v0.2.0
type SessionOptions struct {
// Name identifies the session and its spool files. 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 terminal grid size. A zero value uses the hub's
// default size.
Size Size
// Environment entries use KEY=value form and override inherited values.
// TERM and COLORTERM default to xterm-256color and truecolor respectively.
Environment []string
}
SessionOptions configures one pseudo-terminal 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 SpoolRecoverer ¶
SpoolRecoverer reads a contiguous byte range from a session's append-only spool. Hub implements it so a consumer can recover an evicted client anchor without forcing a full screen reset and replay.
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 polling.
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 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 (*VTTerminal) Close ¶
func (v *VTTerminal) Close()
Close releases the native terminal state. It must be called at most once.
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) 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 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 output bytes. Copy the slice to retain it after
// the callback returns.
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.