vsockclient

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package vsockclient is the Mac-side end of the vsock PTY transport.

Architecture overview:

┌───────────┐ Unix sock ┌─────────────┐  vsock  ┌─────────────┐
│  iTerm2   │◀─────────▶│   vzd    │◀───────▶│ guest agent │
│ (claude)  │  framed   │ (host proxy │  framed │ (clawk-pty- │
└───────────┘  proto    └─────────────┘  proto  │   agent)    │
                                                └─────────────┘

The client speaks vsockproto over a host-side Unix domain socket. vzd's proxy (internal/cli/agent_proxy_darwin.go) bridges that Unix socket to the guest's AF_VSOCK listener via the vz backend's Machine.VSock(). The wire protocol is identical on both sides — the proxy doesn't parse or modify frames, it just shovels bytes.

Sleep/wake survival is the whole point: vsock has no TCP timeouts or keepalives, so an idle connection survives a laptop nap intact — the host proxy and guest agent simply resume where they left off when the VM's vCPU is rescheduled after wake.

Index

Constants

View Source
const DefaultDialTimeout = 10 * time.Second

DefaultDialTimeout is how long Run waits for the agent socket to become connectable. The proxy comes up early in vzd, so we shouldn't normally have to wait, but right after `clawk up` the socket can lag the daemon by a moment.

Variables

View Source
var ErrAgentUnavailable = errors.New("vsockclient: agent socket unavailable")

ErrAgentUnavailable is returned when the agent socket isn't there or refuses connections. Callers distinguish it from a live-connection error to decide whether to retry or fall back to another path.

Functions

func Output

func Output(ctx context.Context, sockPath string, connectPort uint32, user, cmd string, args ...string) (string, int, error)

Output runs one command through the agent and returns its combined output and exit code. Non-interactive: nothing touches the local terminal — frames only — so it's safe from daemons, diagnostics, and anything that must not disturb tty state. The context bounds the whole session.

func Ping

func Ping(ctx context.Context, sockPath string, connectPort uint32, timeout time.Duration) error

Ping runs a trivial command through the whole agent path — host Unix socket → vzd proxy → guest vsock → clawk-pty-agent → exec — and waits for the exit frame. It is the boot-readiness probe for sshd-free (OCI) sandboxes: success proves the guest kernel booted, clawk-init ran, and the agent is accepting sessions.

/bin/sh is the probe command because it is the one path POSIX guarantees in any bootable image; the exit code is irrelevant, only that the round trip completes.

func Run

func Run(ctx context.Context, cfg Config) (exitCode int, err error)

Run dials the agent, allocates a PTY-like raw mode on os.Stdin/ Stdout, and pumps bytes until the child exits or stdin closes.

On exit — successful or not — the local terminal state is fully restored. Even if the connection dies mid-session, the client re-emits the standard terminal-mode-disable escape sequences so iTerm2 doesn't end up wedged with focus reporting / bracketed paste / alternate-screen left enabled.

Returns the child's exit code, or a non-nil error if the session failed before a clean exit. The exit code is meaningful only when err == nil.

Types

type Config

type Config struct {
	// SocketPath is the host-side Unix socket vzd exposes for this
	// VM. Conventionally <vmDir>/agent.sock. Must exist when Run is
	// called; the daemon creates it during VM start.
	SocketPath string

	// Cmd is the program to exec inside the guest PTY. Empty → the
	// guest agent uses /bin/bash.
	Cmd string

	// Args are the args to Cmd.
	Args []string

	// Env is extra environment forwarded to the child. Use this for
	// LANG, COLORTERM, anything user-specific. PATH/HOME/USER are set
	// by the agent based on User.
	Env []string

	// Cwd, if non-empty, is the child's working directory. Empty falls
	// back to the resolved user's home.
	Cwd string

	// User is the OS user inside the guest to drop to (typically
	// "agent"). Empty leaves the agent running as itself (root).
	User string

	// ClearScreen asks Run to clear the terminal before relaying, so a
	// full-screen TUI child (claude, codex, pi, opencode) starts on a clean
	// canvas instead of overdrawing whatever the CLI printed first (boot
	// progress, hints): such TUIs position with absolute cursor moves and
	// don't erase the cells they skip, so stale text shows through.
	//
	// Leave it false for a plain interactive shell: a login shell is
	// line-oriented, draws at the cursor, and clearing would needlessly
	// wipe the user's scrollback — the shell should read as a continuation
	// of the terminal it was launched from, not a fresh screen.
	ClearScreen bool

	// ConnectPort selects firecracker's hybrid-vsock transport. 0 (vz):
	// SocketPath is a per-guest-port channel; speak the framed protocol
	// immediately. Non-zero (firecracker): SocketPath is firecracker's
	// shared vsock UDS and Run first does a "CONNECT <ConnectPort>"
	// handshake — typically the guest pty-agent's port, 1024.
	ConnectPort uint32
}

Config describes one Run() invocation.

Jump to

Keyboard shortcuts

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