Documentation
¶
Index ¶
- Constants
- func ApplyDiskPatch(diskPath string, cfg InitConfig, pubKey string, obs Observer) error
- func ArtifactDir(home, cellName string) string
- func BuildExecCommand(spec ExecSpec) string
- func BuildPreflight(baseDisk string) error
- func BuildProvisionCommands(stack string, modules []string) []string
- func BuildSSHArgv(spec Spec, host string) []string
- func CellHome(home, cellName string) string
- func CollectSSHPubKeys(sshDir string) string
- func DeterministicMAC(cellName string) string
- func DownloadIPSW(ctx context.Context, path string, download DownloadFunc) error
- func DownloadIPSWObserved(ctx context.Context, path string, download DownloadFunc, obs Observer) error
- func EncodeKcpassword(password string) []byte
- func EnsureHomeDir(home, cellName string) (string, error)
- func EnsureNixVolume(home string) (string, error)
- func ExecuteBootCommands(client *VNCClient, commands []BootDirective) error
- func ExecuteBootCommandsObserved(client *VNCClient, commands []BootDirective, obs Observer) error
- func ExecuteBootCommandsWithScreenshots(client *VNCClient, commands []BootDirective, obs Observer, ...) error
- func FindLeaseByMAC(leases []DHCPLease, mac string) (string, bool)
- func FindTextOnScreen(_ *image.RGBA, _ string) (image.Rectangle, bool)
- func GenerateCheckProvisionedScript() string
- func GenerateCreateSessionUserScript(username string) string
- func GenerateGrantSSHdFDAScript() string
- func GenerateHomeMountScript(cellName, username string) string
- func GenerateNixDarwinActivateScript(stack, flakeDir string) string
- func GenerateNixDiskPrepScript(cellName string) string
- func GenerateNixInstallScript() string
- func GenerateNixStoreSwapScript(cellName string) string
- func GenerateNixVolumeMountScript(cellName string) string
- func GeneratePreflightDiagScript() string
- func GenerateProjectMountScript(tag, username, projectBasename string) string
- func GenerateProvisionedMarkerScript() string
- func GenerateSSHEnablementScript() string
- func GenerateSSHKeyPair(dir string) (string, error)
- func GenerateSSHKeyScript(pubKey string) string
- func GenerateSetupSessionHomeScript(username string) string
- func GenerateSudoersScript(username string) string
- func GenerateUserPlist(username, password string, uid, gid int) ([]byte, error)
- func GenerateVerifySSHdFDAScript() string
- func GenerateVirtioFSMountScript(tag, mountPoint string) string
- func IPSWCacheDir(home string) string
- func IPSWCachePath(home string) string
- func ImageName(stack string, modules []string) string
- func InstanceVMName(cellName string) string
- func NixVolumePath(home string) string
- func ParseTartOutput(r io.Reader, fn func(TartProgress)) error
- func PreflightCheck(goos, goarch string) error
- func PreflightCheckHost() error
- func PrepareArtifactDir(dir string) error
- func ProbeSSH(host string, port uint16) error
- func ProvisionCommands(cfg InitConfig, pubKey string) []string
- func ProvisionSSHCommands(stack string, modules []string) []string
- func RunSSHCommand(host string, port uint16, user, keyPath, command string, ...) error
- func RunSSHCommandPassword(host string, port uint16, user, password, command string, ...) error
- func ScreenBrightness(img *image.RGBA) float64
- func ScreenshotDir(projectDir string) string
- func SparseCopy(src, dst string) error
- func SparseCopyWithProgress(src, dst string, fn func(CopyProgress)) error
- func StackTag(stack string, modules []string) string
- func TartClone(ctx context.Context, ref, localName string) error
- func TartCloneWithProgress(ctx context.Context, ref, localName string, fn func(TartProgress), ...) error
- func TartCreate(ctx context.Context, name, ipswPath string, diskSizeGB int) error
- func TartDelete(ctx context.Context, name string) error
- func TartExec(ctx context.Context, name string, command []string, stdout, stderr *os.File) error
- func TartExecInteractive(ctx context.Context, name string, command []string) error
- func TartIP(ctx context.Context, name string) (string, error)
- func TartPreflight() (string, error)
- func TartSet(ctx context.Context, name string, cpus uint, memoryMB uint64) error
- func TartStop(ctx context.Context, name string) error
- func TartVersion(ctx context.Context) string
- func TemplateDir(home, stack string, modules []string) string
- func TemplateVMName(stack string, modules []string) string
- func UnmountDiskImage(mount *DiskMount) error
- func WaitForGuestIP(mac string, timeout, interval time.Duration, stateFunc ...VMStateFunc) (string, error)
- func WaitForSSH(host string, port uint16, timeout, interval time.Duration) error
- func WaitForSSHObserved(host string, port uint16, timeout, interval time.Duration, obs Observer, ...) error
- type AcquireDecision
- type AcquireInputs
- type AcquireResult
- type ArtifactPaths
- type BootDirective
- type BuildConfig
- type CellSSHPaths
- type ClickTextDirective
- type CopyProgress
- type DHCPLease
- type DiskMount
- type DownloadFunc
- type ExecSpec
- type InitConfig
- type InitPhase
- type KeyDirective
- type KeyDownDirective
- type KeyUpDirective
- type LaunchAction
- type LaunchInputs
- type NopObserver
- type Observer
- type PatchFile
- type PreflightResult
- type ProvisionStep
- type Spec
- type SpecialKey
- type TartConfig
- type TartDisplay
- type TartGetInfo
- type TartListEntry
- type TartProgress
- type TemplatePaths
- type TypeDirective
- type VM
- type VMStateFunc
- type VNCClient
- func (c *VNCClient) CaptureFramebuffer() (*image.RGBA, error)
- func (c *VNCClient) CaptureScreenshot(path string) error
- func (c *VNCClient) Click(x, y uint16) error
- func (c *VNCClient) Close() error
- func (c *VNCClient) Height() uint16
- func (c *VNCClient) SendKey(key SpecialKey) error
- func (c *VNCClient) SendKeyDown(key SpecialKey) error
- func (c *VNCClient) SendKeyEvent(event VNCKeyEvent) error
- func (c *VNCClient) SendKeyUp(key SpecialKey) error
- func (c *VNCClient) SendPointerEvent(buttonMask uint8, x, y uint16) error
- func (c *VNCClient) TypeString(s string) error
- func (c *VNCClient) Width() uint16
- type VNCKeyEvent
- type WaitDirective
- type WaitTextDirective
Constants ¶
const ( NixVolumeFileName = "nix.img" NixVolumeSizeGB = 30 NixVolumeLabel = "DevcellNix" )
const ProvisionedMarkerPath = "/private/var/devcell-provisioned"
ProvisionedMarkerPath is on the boot disk's writable Data volume. /private/var persists across tart clone. We use /private/var (not /var) to avoid any symlink indirection during early boot.
Variables ¶
This section is empty.
Functions ¶
func ApplyDiskPatch ¶
func ApplyDiskPatch(diskPath string, cfg InitConfig, pubKey string, obs Observer) error
ApplyDiskPatch is not available on non-darwin platforms.
func ArtifactDir ¶
ArtifactDir returns the path to VM artifacts for a given cell. Deprecated: use TemplateDir for per-template paths or CellHome for per-cell paths.
func BuildExecCommand ¶
BuildExecCommand constructs a shell command string for `tart exec <vm> bash -l -c <cmd>`. Sources the nix daemon profile, cds into the project dir, sets env vars, and runs the binary.
When RunAsUser is set, the entire command is wrapped with `sudo -u <user> -i bash -l -c '...'` so the session runs as the specified user (matching Docker's HOST_USER model).
func BuildPreflight ¶
BuildPreflight checks whether a build can proceed.
func BuildProvisionCommands ¶
BuildProvisionCommands returns the SSH commands to provision a build VM.
func BuildSSHArgv ¶
BuildSSHArgv constructs the SSH argv for running a command inside a macOS VM:
ssh -p <port> -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
<user>@<host> -t bash -l -c '<nix source; cd ~/project; env KEY=VAL binary flags>'
The remote command is wrapped in `bash -l -c "..."` so that the login shell sources profiles and puts home-manager-installed binaries on PATH.
When ProjectDir is set, the command cds into ~/basename(ProjectDir) first, mirroring Docker's --workdir behaviour.
It is a pure function: no I/O, no exec.
func CellHome ¶
CellHome returns the per-cell persistent home directory. Layout: ~/.devcell/<cellName>/ Same path on both Linux (bind-mount → /home/<user>) and macOS (VirtioFS → /Users/<user>).
func CollectSSHPubKeys ¶
CollectSSHPubKeys reads all *.pub files from sshDir and returns their contents concatenated (one key per line). Returns "" if the directory doesn't exist or contains no .pub files.
func DeterministicMAC ¶
DeterministicMAC derives a stable locally-administered MAC address from a cell name. Same cell → same MAC → same DHCP lease, avoiding lease accumulation across VM restarts and reinits.
func DownloadIPSW ¶
func DownloadIPSW(ctx context.Context, path string, download DownloadFunc) error
DownloadIPSW downloads a restore image with completion tracking and retry. A ".done" marker file signals that a previous download completed successfully; if present, the download is skipped. Partial files are left on disk for the DownloadFunc to resume via Range headers. On failure, retries up to 3 times with backoff.
func DownloadIPSWObserved ¶
func DownloadIPSWObserved(ctx context.Context, path string, download DownloadFunc, obs Observer) error
DownloadIPSWObserved is like DownloadIPSW but reports progress to obs.
func EncodeKcpassword ¶
EncodeKcpassword XOR-encodes a password using Apple's kcpassword scheme. The password is null-padded to a multiple of 12 bytes, then each byte is XORed with the corresponding byte of the 13-byte repeating key.
func EnsureHomeDir ¶
EnsureHomeDir creates the CellHome directory if it doesn't exist. Returns the path to the (existing or newly created) directory. Replaces EnsureHomeVolume — home is now a VirtioFS directory mount, not a disk image.
func EnsureNixVolume ¶
EnsureNixVolume creates a sparse nix store disk image if it doesn't exist. Returns the path to the (existing or newly created) image.
func ExecuteBootCommands ¶
func ExecuteBootCommands(client *VNCClient, commands []BootDirective) error
ExecuteBootCommands runs a sequence of boot directives against a VNC server. Returns an error annotated with the directive index if sending fails.
func ExecuteBootCommandsObserved ¶
func ExecuteBootCommandsObserved(client *VNCClient, commands []BootDirective, obs Observer) error
ExecuteBootCommandsObserved is like ExecuteBootCommands but reports progress to obs, including which directive is currently executing.
func ExecuteBootCommandsWithScreenshots ¶
func ExecuteBootCommandsWithScreenshots(client *VNCClient, commands []BootDirective, obs Observer, screenshotBefore func(idx int, label string)) error
ExecuteBootCommandsWithScreenshots runs boot directives with an optional pre-action screenshot callback. If screenshotBefore is non-nil, it is called before each KeyDirective, KeyDownDirective, and TypeDirective with the directive index and a short label describing the action.
func FindLeaseByMAC ¶
FindLeaseByMAC returns the IP address for the given MAC address. Comparison is case-insensitive.
func FindTextOnScreen ¶
FindTextOnScreen is a stub for non-Darwin platforms. OCR-based screen detection requires Apple Vision framework (macOS only).
func GenerateCheckProvisionedScript ¶
func GenerateCheckProvisionedScript() string
GenerateCheckProvisionedScript returns a script that checks for the provisioned marker. Exits 0 if present, 1 if not.
func GenerateCreateSessionUserScript ¶
GenerateCreateSessionUserScript returns a script that creates a macOS user matching the host's $USER, mirroring Docker's HOST_USER entrypoint model. The user gets admin group membership (for sudo) and a home directory. Idempotent: skips if the user already exists.
func GenerateGrantSSHdFDAScript ¶
func GenerateGrantSSHdFDAScript() string
GenerateGrantSSHdFDAScript returns a boot-time script that grants Full Disk Access to sshd in the macOS TCC database. Must run as a LaunchDaemon under launchd (not over SSH) — launchd has the TCC context to modify the database. After running, SSH sessions can call rename() on /etc/ files (required by the Nix installer).
Uses logger(1) to write structured status to the unified log — the serial console daemon's "composedMessage CONTAINS devcell" predicate picks these up, so the host sees progress via streamSerial() without SSH.
func GenerateHomeMountScript ¶
GenerateHomeMountScript returns a guest-side script that mounts the CellHome VirtioFS share at /Users/<username>. The host passes --dir home:<cellHome> to tart run.
func GenerateNixDarwinActivateScript ¶
GenerateNixDarwinActivateScript returns the nix-darwin activation command. nix-darwin manages system-level config (LaunchDaemons, /etc/) and user packages — a superset of home-manager. The flakeDir must contain a flake with darwinConfigurations.<stack>.
func GenerateNixDiskPrepScript ¶
GenerateNixDiskPrepScript returns a script that reformats the external VirtIO disk as JHFS+ with the "DevcellNix" label BEFORE the Nix installer runs. This prevents a label collision: the Determinate installer creates an APFS volume named "Nix Store" and then encrypts it by name. If a pre-existing HFS+ volume with the same label exists (from a previous build), diskutil finds the wrong volume and the encrypt step fails.
func GenerateNixInstallScript ¶
func GenerateNixInstallScript() string
GenerateNixInstallScript returns a script that installs Nix using the official multi-user installer. The installer creates an APFS volume named "Nix Store" on the boot disk — GenerateNixStoreSwapScript runs afterward to migrate the nix store to our external JHFS+ disk.
We use the official installer (not Determinate) because nix-darwin's activation checks for /usr/local/bin/determinate-nixd and aborts if found — the two daemon management layers conflict.
func GenerateNixStoreSwapScript ¶
GenerateNixStoreSwapScript returns a script that migrates the nix store from the Determinate installer's APFS volume to our external JHFS+ disk. Assumes GenerateNixDiskPrepScript already formatted the disk as JHFS+ "DevcellNix" and unmounted it. This script runs after "Install Nix":
- Mounts the pre-formatted "DevcellNix" volume
- Copies the initial nix store (small — daemon + profiles only)
- Swaps the /nix mount from installer's APFS to our JHFS+
- Installs a boot-time LaunchDaemon for clone VMs
- Restarts the nix daemon on the new mount
func GenerateNixVolumeMountScript ¶
GenerateNixVolumeMountScript returns a guest-side script that: 1. Finds the external VirtIO disk (non-boot, matching expected size) 2. Formats it as JHFS+ on first use, writes .devcell.json metadata 3. Mounts the JHFS+ volume 4. Creates the /nix firmlink via synthetic.conf and mounts the volume there
On subsequent runs, the disk is already formatted — it just mounts.
func GeneratePreflightDiagScript ¶
func GeneratePreflightDiagScript() string
GeneratePreflightDiagScript returns a diagnostic script that checks the VM environment before Nix installation. Output goes to the debug log via io.MultiWriter so failures are diagnosable without re-running.
func GenerateProjectMountScript ¶
GenerateProjectMountScript returns a script to mount the project VirtioFS share into the user's home directory, mirroring Docker's bind-mount behavior.
func GenerateProvisionedMarkerScript ¶
func GenerateProvisionedMarkerScript() string
GenerateProvisionedMarkerScript returns a script that stamps a marker file indicating provisioning completed successfully. Written to /private/var (boot disk) rather than ~ because VirtioFS may shadow the home directory at runtime.
func GenerateSSHEnablementScript ¶
func GenerateSSHEnablementScript() string
GenerateSSHEnablementScript returns a shell script to enable SSH on macOS.
func GenerateSSHKeyPair ¶
GenerateSSHKeyPair creates an ed25519 key pair and writes them to the artifact dir. Returns the public key in OpenSSH authorized_keys format.
func GenerateSSHKeyScript ¶
GenerateSSHKeyScript returns a script to inject an SSH public key.
func GenerateSetupSessionHomeScript ¶
GenerateSetupSessionHomeScript returns a script that symlinks the CellHome VirtioFS share into the session user's home directory, mirroring how the build-time "Mount home volume" step sets up /Users/admin.
func GenerateSudoersScript ¶
GenerateSudoersScript returns a script to enable passwordless sudo.
func GenerateUserPlist ¶
GenerateUserPlist builds a macOS dslocal user record as a binary plist. The record mirrors what Directory Services expects in /var/db/dslocal/nodes/Default/users/<username>.plist.
func GenerateVerifySSHdFDAScript ¶
func GenerateVerifySSHdFDAScript() string
GenerateVerifySSHdFDAScript returns a script that checks whether sshd has Full Disk Access in the TCC database. Run over SSH before Nix installation to confirm the boot-time grant succeeded. Exits 0 if granted, 1 if not.
func GenerateVirtioFSMountScript ¶
GenerateVirtioFSMountScript returns a script to mount a VirtioFS share.
Tart 2.30+ bundles --dir shares under Apple's automount VirtioFS device (tag "com.apple.virtio-fs.automount") instead of creating individual VirtioFS devices per share. macOS automounts these at /Volumes/My Shared Files/<tag>/. The script tries mount_virtiofs first (individual device), then falls back to symlinking from the automount path.
func IPSWCacheDir ¶
IPSWCacheDir returns the shared IPSW cache directory (not per-cell).
func IPSWCachePath ¶
IPSWCachePath returns the path to the cached restore.ipsw file.
func InstanceVMName ¶
InstanceVMName returns the tart VM name for a per-cell running instance.
func NixVolumePath ¶
NixVolumePath returns the path to the global nix store disk image. Layout: ~/.devcell/darwin/nix-store.img Shared across all cells — mirrors Docker's single devcell-nix-store volume.
func ParseTartOutput ¶
func ParseTartOutput(r io.Reader, fn func(TartProgress)) error
ParseTartOutput reads lines from r and calls fn for each parsed progress event.
func PreflightCheck ¶
PreflightCheck validates the host can run macOS VMs. Returns nil if all checks pass, or an error describing what's wrong. Pure function (takes OS/arch as params for testability).
func PreflightCheckHost ¶
func PreflightCheckHost() error
PreflightCheckHost calls PreflightCheck with runtime values.
func PrepareArtifactDir ¶
PrepareArtifactDir creates the artifact directory if it doesn't exist.
func ProvisionCommands ¶
func ProvisionCommands(cfg InitConfig, pubKey string) []string
ProvisionCommands returns the SSH commands to run after first boot.
func ProvisionSSHCommands ¶
ProvisionSSHCommands returns the SSH commands to provision a VM with a stack. Commands are run in order via SSH.
func RunSSHCommand ¶
func RunSSHCommand(host string, port uint16, user, keyPath, command string, stdout, stderr io.Writer) error
RunSSHCommand executes a command on the VM over SSH using key-based auth.
func RunSSHCommandPassword ¶
func RunSSHCommandPassword(host string, port uint16, user, password, command string, stdout, stderr io.Writer) error
RunSSHCommandPassword executes a command on the VM over SSH using password auth. Tries both keyboard-interactive (macOS default via PAM) and plain password.
func ScreenBrightness ¶
ScreenBrightness returns the mean brightness (0.0–1.0) of an RGBA image. 0.0 = fully black, 1.0 = fully white.
func ScreenshotDir ¶
ScreenshotDir returns the directory for debug VNC screenshots.
func SparseCopy ¶
SparseCopy copies src to dst, preserving sparseness where the OS supports it.
func SparseCopyWithProgress ¶
func SparseCopyWithProgress(src, dst string, fn func(CopyProgress)) error
SparseCopyWithProgress copies src to dst with progress reporting. The callback fn is called after each 1MB chunk is written.
func StackTag ¶
StackTag returns the canonical tag for a stack + optional modules. Shared naming logic between Docker images and tart VMs. Examples: "ultimate", "dev-linear-plex-a1b2c3d4".
func TartClone ¶
TartClone runs `tart clone <ref> <localName>`. Parallel to Docker: exec.Command("docker", "pull", tag).
func TartCloneWithProgress ¶
func TartCloneWithProgress(ctx context.Context, ref, localName string, fn func(TartProgress), errOut io.Writer) error
TartCloneWithProgress runs `tart clone` with CI=1 to get parseable progress, calling fn for each progress event. Remaining stderr is written to errOut.
func TartCreate ¶
TartCreate creates a VM from an IPSW file via `tart create`.
func TartDelete ¶
TartDelete runs `tart delete <name>`. Parallel to Docker: exec.Command("docker", "rm", name).
func TartExecInteractive ¶
TartExecInteractive runs an interactive PTY session via `tart exec -t -i`.
func TartPreflight ¶
TartPreflight verifies the tart binary is installed and returns its version. Parallel to Docker: exec.LookPath("docker") + `docker version`.
func TartVersion ¶
TartVersion returns the tart CLI version string.
func TemplateDir ¶
TemplateDir returns the path to per-template VM artifacts. Layout: ~/.devcell/darwin/<stackTag>/
func TemplateVMName ¶
TemplateVMName returns the tart VM name for a built template image.
func UnmountDiskImage ¶
UnmountDiskImage is not available on non-darwin platforms.
func WaitForGuestIP ¶
func WaitForGuestIP(mac string, timeout, interval time.Duration, stateFunc ...VMStateFunc) (string, error)
WaitForGuestIP is not available on non-darwin platforms.
func WaitForSSH ¶
WaitForSSH polls a TCP connection to host:port until it succeeds or the timeout elapses. Returns nil on success, or an error describing the failure. Pure network check — no authentication, just verifies the port is accepting.
func WaitForSSHObserved ¶
func WaitForSSHObserved(host string, port uint16, timeout, interval time.Duration, obs Observer, stateFunc ...VMStateFunc) error
WaitForSSHObserved is like WaitForSSH but reports each poll attempt to obs. An optional VMStateFunc checks VM liveness each iteration — if the VM enters "stopped" or "error" state, polling aborts immediately instead of waiting the full timeout.
Types ¶
type AcquireDecision ¶
type AcquireDecision int
AcquireDecision describes what AcquireDarwinVM will do.
const ( DecisionExternal AcquireDecision = iota // external VM — just wait for SSH DecisionAlreadyRunning // managed VM already accepting connections DecisionStartVM // need to start managed VM DecisionCloneTemplate // clone from template, then start )
func DecideAcquire ¶
func DecideAcquire(external bool, alreadyRunning bool) AcquireDecision
DecideAcquire is the pure-function decision: what should AcquireDarwinVM do?
func DecideAcquireEx ¶
func DecideAcquireEx(external, alreadyRunning, hasTemplate bool) AcquireDecision
DecideAcquireEx extends DecideAcquire with template awareness.
func (AcquireDecision) String ¶
func (d AcquireDecision) String() string
type AcquireInputs ¶
type AcquireInputs struct {
VMName string // tart VM name (instance, e.g. "DIMM-tart")
TemplateName string // template VM to clone from if instance doesn't exist
Disks []string // raw disk image paths (VirtIO block devices via --disk)
SSHHost string
SSHPort uint16
ExternalVM bool // user explicitly configured SSH target — skip lifecycle
SSHTimeout time.Duration
InitFunc func() error // called to auto-init when VM doesn't exist; nil = error instead
}
AcquireInputs are the parameters for AcquireDarwinVM.
func (*AcquireInputs) ApplyDefaults ¶
func (a *AcquireInputs) ApplyDefaults()
ApplyDefaults fills zero values.
func (*AcquireInputs) Validate ¶
func (a *AcquireInputs) Validate() error
Validate checks required fields.
type AcquireResult ¶
type AcquireResult struct {
VM *VM // non-nil only if we started a managed VM (caller must shut it down)
SSHHost string // resolved SSH host (guest IP or external)
SSHPort uint16 // resolved SSH port
Managed bool // true if we started the VM (vs. external/already-running)
}
AcquireResult holds the outcome of AcquireDarwinVM.
func AcquireDarwinVM ¶
func AcquireDarwinVM(_ context.Context, _ AcquireInputs) (*AcquireResult, error)
AcquireDarwinVM is not available on this platform.
type ArtifactPaths ¶
type ArtifactPaths struct {
Dir string // parent directory
Disk string // disk.img
AuxStorage string // aux-storage.img
HWModel string // hardware-model.json
MachineID string // machine-id.json
SSHPrivateKey string // id_ed25519 (per-cell generated key)
SSHPublicKey string // id_ed25519.pub
}
ArtifactPaths holds the paths to all VM artifact files. Deprecated: use TemplatePaths + CellSSHPaths instead.
func LoadArtifacts ¶
func LoadArtifacts(home, cellName string) (ArtifactPaths, error)
LoadArtifacts loads artifact paths and validates they exist. Returns an error with a helpful message if any are missing.
func NewArtifactPaths ¶
func NewArtifactPaths(home, cellName string) ArtifactPaths
NewArtifactPaths returns paths for a cell's Darwin VM artifacts. Deprecated: use NewTemplatePaths + NewCellSSHPaths instead.
func (ArtifactPaths) Exists ¶
func (a ArtifactPaths) Exists() bool
Exists checks if all required artifact files exist.
func (ArtifactPaths) MissingFiles ¶
func (a ArtifactPaths) MissingFiles() []string
MissingFiles returns a list of artifact files that don't exist on disk.
type BootDirective ¶
type BootDirective interface {
// contains filtered or unexported methods
}
BootDirective represents one step in the boot command sequence.
func GenerateBootCommands ¶
func GenerateBootCommands(username, password string) []BootDirective
GenerateBootCommands returns the boot command sequence for macOS Setup Assistant automation. Uses OCR-based screen detection for timing and the Tart-proven keystroke sequence for navigation.
func ParseBootToken ¶
func ParseBootToken(token string) (BootDirective, error)
ParseBootToken parses a single boot command token.
type BuildConfig ¶
type BuildConfig struct {
CellName string
HomeDir string
Stack string
Modules []string
CPUs uint
MemoryGB uint64
SSHPort uint16
Username string
}
BuildConfig holds the parameters for building a macOS VM image.
func (*BuildConfig) ApplyDefaults ¶
func (c *BuildConfig) ApplyDefaults()
ApplyDefaults fills zero-value fields.
func (*BuildConfig) ArtifactDir ¶
func (c *BuildConfig) ArtifactDir() string
ArtifactDir returns the VM artifacts path.
func (*BuildConfig) BaseImagePath ¶
func (c *BuildConfig) BaseImagePath() string
BaseImagePath returns the path to the base disk image (from init).
func (*BuildConfig) BuildImagePath ¶
func (c *BuildConfig) BuildImagePath() string
BuildImagePath returns the path for the ephemeral build image.
func (*BuildConfig) FinalImagePath ¶
func (c *BuildConfig) FinalImagePath() string
FinalImagePath returns the path for the final built image.
func (*BuildConfig) Validate ¶
func (c *BuildConfig) Validate() error
Validate checks required fields.
type CellSSHPaths ¶
type CellSSHPaths struct {
Dir string // ~/.devcell/<cellName>/.ssh/
PrivateKey string // id_ed25519
PublicKey string // id_ed25519.pub
}
CellSSHPaths holds paths to per-cell SSH keys. Layout: ~/.devcell/<cellName>/.ssh/
func NewCellSSHPaths ¶
func NewCellSSHPaths(home, cellName string) CellSSHPaths
NewCellSSHPaths returns paths for a cell's SSH keys.
type ClickTextDirective ¶
ClickTextDirective finds text on screen via OCR and clicks its center. Polls until the text appears or Timeout expires.
type CopyProgress ¶
CopyProgress reports bytes copied vs total during a sparse copy.
func (CopyProgress) Percent ¶
func (p CopyProgress) Percent() int
func (CopyProgress) String ¶
func (p CopyProgress) String() string
type DHCPLease ¶
type DHCPLease struct {
Name string
IPAddress string
HWAddress string // MAC address without type prefix (e.g. "aa:bb:cc:dd:ee:ff")
}
DHCPLease represents a single entry from macOS /var/db/dhcpd_leases.
func ParseDHCPLeases ¶
ParseDHCPLeases parses the macOS DHCP lease file format. Each entry is enclosed in { } and contains key=value pairs. hw_address may have a type prefix (e.g. "1,aa:bb:cc:dd:ee:ff") which is stripped.
type DiskMount ¶
DiskMount holds the result of mounting a disk image.
func MountDiskImage ¶
MountDiskImage is not available on non-darwin platforms.
type DownloadFunc ¶
DownloadFunc fetches a macOS restore image to the given path. The implementation may resume a partial download if the file already exists (e.g., vz uses HTTP Range headers based on existing file size).
type ExecSpec ¶
type ExecSpec struct {
Binary string // binary to run (e.g. "zsh", "claude")
Flags []string // default flags for the binary
UserArgs []string // user-provided args
EnvVars []string // KEY=VAL pairs to set in the environment
ProjectDir string // host project path — basename is used for cd ~/basename
RunAsUser string // if set, wrap command with sudo -u <user> -i
}
ExecSpec describes a command to run inside a tart VM via `tart exec`.
type InitConfig ¶
type InitConfig struct {
CellName string
HomeDir string
Stack string
Username string
Password string
CPUs uint
MemoryGB uint64
DiskGB uint64
SSHPort uint16
}
InitConfig holds the parameters for a full VM initialization.
func (*InitConfig) ApplyDefaults ¶
func (c *InitConfig) ApplyDefaults()
ApplyDefaults fills zero-value fields with sensible defaults.
func (*InitConfig) ArtifactDir ¶
func (c *InitConfig) ArtifactDir() string
ArtifactDir returns the path where VM artifacts will be stored.
func (*InitConfig) DiskSizeBytes ¶
func (c *InitConfig) DiskSizeBytes() int64
DiskSizeBytes returns the disk image size in bytes.
func (*InitConfig) Validate ¶
func (c *InitConfig) Validate() error
Validate checks that all required fields are set.
type KeyDirective ¶
type KeyDirective struct {
Key SpecialKey
}
KeyDirective sends a single special key press (down + up).
type KeyDownDirective ¶
type KeyDownDirective struct {
Key SpecialKey
}
KeyDownDirective sends a key-down event without a corresponding key-up. Used for modifier key holds (Shift+Tab, Alt+Space, etc.).
type KeyUpDirective ¶
type KeyUpDirective struct {
Key SpecialKey
}
KeyUpDirective sends a key-up event. Pairs with a prior KeyDownDirective.
type LaunchAction ¶
type LaunchAction int
LaunchAction is one VM-acquisition step.
const ( ActionUseLocal LaunchAction = iota // disk image exists locally ActionBuild // build from IPSW (full init + provision) ActionDryRun // dry-run mode, no VM work ActionPullTart // pull pre-built image from Tart OCI registry )
func DecideLaunchActions ¶
func DecideLaunchActions(in LaunchInputs) []LaunchAction
DecideLaunchActions returns the ordered fallback sequence.
DryRun → [DryRun] ExplicitBuild → [Build] DiskExists → [UseLocal] TartRef (cold start) → [PullTart] cold start → [Build]
type LaunchInputs ¶
type LaunchInputs struct {
DryRun bool // --dry-run set
ExplicitBuild bool // --build set, force rebuild
DiskExists bool // disk image exists at expected path
TartRef string // OCI image ref for Tart pull (e.g. ghcr.io/cirruslabs/macos-sequoia-base:latest)
}
LaunchInputs are the inputs to DecideLaunchActions.
type NopObserver ¶
type NopObserver struct{}
NopObserver silently discards all events.
func (NopObserver) Logf ¶
func (NopObserver) Logf(string, ...any)
func (NopObserver) Progress ¶
func (NopObserver) Progress(float64, string)
type Observer ¶
type Observer interface {
// Logf emits a debug-level message.
Logf(format string, args ...any)
// Progress reports a step's completion fraction (0.0–1.0) with a message.
Progress(fraction float64, message string)
}
Observer receives progress events from long-running tart operations. Methods are called synchronously on the caller's goroutine.
type PatchFile ¶
type PatchFile struct {
Path string // absolute path relative to Data volume mount point
Perms fs.FileMode // e.g. 0400, 0600, 0644
Owner string // "root:wheel" or "user:staff"
Content []byte // file content (nil = empty file / touch)
MkdirP bool // create parent directories if missing
}
PatchFile describes a single file to write during offline disk injection.
func PatchManifest ¶
func PatchManifest(cfg InitConfig, pubKey string) []PatchFile
PatchManifest returns the ordered list of files to write for offline disk injection. All paths are relative to the Data volume mount point.
type PreflightResult ¶
type PreflightResult struct {
VMExists bool
}
PreflightResult holds the outcome of InitPreflight.
func InitPreflight ¶
func InitPreflight(goos, goarch string, artifactDir string) (PreflightResult, error)
InitPreflight checks whether initialization can proceed. Returns a PreflightResult with VMExists=true if disk.img already exists (callers decide whether to prompt, force-overwrite, or abort). Returns an error only for hard blockers (wrong OS/arch).
type ProvisionStep ¶
type ProvisionStep struct {
Name string
Command string
NeedsPassword bool // true = use password auth (before SSH key is injected)
}
ProvisionStep pairs a human-readable phase name with the SSH command to run.
func ProvisionSteps ¶
func ProvisionSteps(cfg InitConfig, pubKey string, offlineProvisioned bool) []ProvisionStep
ProvisionSteps returns the SSH provisioning commands with human-readable names. Steps before key injection use NeedsPassword=true since the generated SSH key isn't in authorized_keys yet.
When offlineProvisioned is true, SSH enablement, key injection, and sudo configuration are skipped — they were written directly to the disk image by ApplyDiskPatch. Only Nix install and home-manager activation remain.
type Spec ¶
type Spec struct {
VMName string
CPUs uint
MemoryGB uint64
DiskPath string // path to disk.img
AuxPath string // path to aux-storage.img
HWModelPath string // path to hardware-model.json
MachineIDPath string // path to machine-id.json
SSHPort uint16 // forwarded port for SSH (default 22)
SSHUser string // guest username (default "devcell")
MACAddr string // reuse a specific MAC (colon-separated); empty = random
Binary string // agent binary (claude, zsh, etc.)
DefaultFlags []string
UserArgs []string
EnvVars []string // KEY=VALUE pairs
ProjectDir string // host project directory
SSHKeyPath string // path to SSH private key (optional; adds -i flag)
}
Spec holds everything needed to configure and connect to a macOS VM.
func (*Spec) ApplyDefaults ¶
func (s *Spec) ApplyDefaults()
ApplyDefaults fills in zero-value fields with sensible defaults.
type SpecialKey ¶
type SpecialKey int
SpecialKey is a named key for VNC key events.
const ( KeySpace SpecialKey = iota KeyTab KeyReturn KeyEscape KeyLeftShift KeyLeftAlt KeyLeftCtrl KeyLeft KeyRight KeyUp KeyDown KeyF2 KeyF5 )
func (SpecialKey) VNCKeyCode ¶
func (k SpecialKey) VNCKeyCode() uint32
VNCKeyCode returns the X11 keysym for a SpecialKey.
type TartConfig ¶
type TartConfig struct {
OS string `json:"os"`
Arch string `json:"arch"`
CPUCount int `json:"cpuCount"`
MemorySize uint64 `json:"memorySize"`
Display TartDisplay `json:"display"`
MACAddress string `json:"macAddress"`
}
TartConfig represents the VM configuration from a Tart config.json.
func AcquireFromTart ¶
AcquireFromTart clones a Tart OCI image to local storage and returns the parsed VM config plus the VM directory path (containing disk.img, nvram.bin, config.json). The caller uses ToSpec(vmDir) to build a Spec for booting.
Parallel to the old ExtractTartImage which pulled OCI layers via go-containerregistry. This shells out to `tart clone` — same pattern as Docker's exec.Command("docker", "pull", tag) in runner.go.
func ParseTartConfig ¶
func ParseTartConfig(data []byte) (TartConfig, error)
ParseTartConfig parses a Tart VM config JSON blob.
func (TartConfig) MemoryGB ¶
func (c TartConfig) MemoryGB() uint64
MemoryGB returns memory size in whole gigabytes.
func (TartConfig) ToSpec ¶
func (c TartConfig) ToSpec(artifactDir string) Spec
ToSpec converts a TartConfig to a tart Spec.
type TartDisplay ¶
TartDisplay holds display resolution from a Tart config.
type TartGetInfo ¶
type TartGetInfo struct {
OS string `json:"OS"`
CPU int `json:"CPU"`
Memory uint64 `json:"Memory"`
Disk int `json:"Disk"`
DiskFormat string `json:"DiskFormat"`
Size string `json:"Size"`
Display string `json:"Display"`
Running bool `json:"Running"`
State string `json:"State"`
}
TartGetInfo is the JSON output of `tart get <name> --format json`. Parallel to Docker: `docker image inspect <tag>`.
type TartListEntry ¶
type TartListEntry struct {
Name string `json:"Name"`
State string `json:"State"`
Source string `json:"Source"`
Disk int `json:"Disk"`
}
TartListEntry represents one VM in `tart list` output.
type TartProgress ¶
TartProgress represents a single progress event parsed from tart CLI output. When CI=1, tart's SimpleConsoleLogger emits one line per update: "pulling manifest...", "0%", "42%", "100%", etc.
func ParseTartProgressLine ¶
func ParseTartProgressLine(line string) (TartProgress, bool)
ParseTartProgressLine parses a single line of tart output. Returns the parsed progress and true, or zero value and false for empty lines.
type TemplatePaths ¶
type TemplatePaths struct {
Dir string // parent directory
Disk string // disk.img
AuxStorage string // aux-storage.img
HWModel string // hardware-model.json
MachineID string // machine-id.json
}
TemplatePaths holds paths to per-template VM platform artifacts. Layout: ~/.devcell/darwin/<stackTag>/
func NewTemplatePaths ¶
func NewTemplatePaths(home, stack string, modules []string) TemplatePaths
NewTemplatePaths returns paths for a template's VM artifacts.
func (TemplatePaths) Exists ¶
func (tp TemplatePaths) Exists() bool
Exists checks if all required template artifact files exist.
func (TemplatePaths) MissingFiles ¶
func (tp TemplatePaths) MissingFiles() []string
MissingFiles returns a list of template artifact files that don't exist on disk.
type TypeDirective ¶
type TypeDirective struct {
Text string
}
TypeDirective types a string of characters.
type VM ¶
type VM struct {
Name string
// contains filtered or unexported fields
}
VM wraps a tart VM managed via the tart CLI.
func TartRun ¶
TartRun starts a VM headlessly via `tart run --no-graphics`. dirs are VirtioFS shared directories (tag → host path). disks are raw disk image paths attached as VirtIO block devices. The returned VM holds the background process; the caller must call Stop().
type VMStateFunc ¶
type VMStateFunc func() string
VMStateFunc returns the current VM state (e.g. "running", "stopped", "error"). Passed to polling functions so they can fail fast if the VM crashes.
type VNCClient ¶
type VNCClient struct {
// contains filtered or unexported fields
}
VNCClient is a minimal VNC (RFB) client for sending keystrokes and pointer events. It implements just enough of the RFB protocol for Setup Assistant automation, including OCR-based screen detection.
func DialVNC ¶
DialVNC connects to a VNC server with no authentication and completes the RFB handshake.
func DialVNCAuth ¶
DialVNCAuth connects to a VNC server with VNC Authentication (RFB security type 2).
func NewVNCClient ¶
NewVNCClient wraps an existing connection (for testing with mock servers).
func (*VNCClient) CaptureFramebuffer ¶
CaptureFramebuffer grabs the current screen as an in-memory RGBA image without writing to disk. Used for screen-content analysis (brightness polling).
func (*VNCClient) CaptureScreenshot ¶
CaptureScreenshot requests a full framebuffer update from the VNC server and saves it as a PNG file. The VNC client must already be connected.
Uses the server's default pixel format (from ServerInit) — does NOT send SetPixelFormat or SetEncodings, because Apple's _VZVNCServer crashes (SIGTRAP) when it receives a SetEncodings with only RAW encoding.
func (*VNCClient) Click ¶
Click sends a left mouse button press and release at the given coordinates.
func (*VNCClient) SendKey ¶
func (c *VNCClient) SendKey(key SpecialKey) error
SendKey sends a key-down then key-up event for a special key.
func (*VNCClient) SendKeyDown ¶
func (c *VNCClient) SendKeyDown(key SpecialKey) error
SendKeyDown sends a key-down event without a corresponding key-up.
func (*VNCClient) SendKeyEvent ¶
func (c *VNCClient) SendKeyEvent(event VNCKeyEvent) error
SendKeyEvent sends a single VNC key event.
func (*VNCClient) SendKeyUp ¶
func (c *VNCClient) SendKeyUp(key SpecialKey) error
SendKeyUp sends a key-up event. Pairs with a prior SendKeyDown.
func (*VNCClient) SendPointerEvent ¶
SendPointerEvent sends a VNC pointer event (mouse movement / button press). buttonMask bit 0 = left button, bit 1 = middle, bit 2 = right.
func (*VNCClient) TypeString ¶
TypeString sends key events for each character in the string.
type VNCKeyEvent ¶
VNCKeyEvent represents a single VNC key press or release.
func EncodeCharacter ¶
func EncodeCharacter(c rune) []VNCKeyEvent
EncodeCharacter returns the key events for typing a single character. Uppercase letters include shift key events.
func EncodeSpecialKey ¶
func EncodeSpecialKey(k SpecialKey) []VNCKeyEvent
EncodeSpecialKey returns the down+up pair for a special key.
func EncodeString ¶
func EncodeString(s string) []VNCKeyEvent
EncodeString returns key events for typing a full string.
type WaitDirective ¶
WaitDirective pauses for a duration before the next step.
type WaitTextDirective ¶
WaitTextDirective polls the VNC framebuffer via OCR until the given text appears on screen. Times out after Timeout.
Source Files
¶
- acquire.go
- acquire_stub.go
- artifacts.go
- boot_command.go
- build.go
- dhcp_leases.go
- dhcp_leases_stub.go
- diskpatch.go
- diskpatch_stub.go
- download.go
- home_volume.go
- image.go
- init.go
- launch_decision.go
- nix_volume.go
- observer.go
- provision.go
- spec.go
- ssh.go
- ssh_exec.go
- ssh_ready.go
- tart_cli.go
- tart_progress.go
- tart_pull.go
- vnc_client.go
- vnc_ocr_stub.go
- vnc_screenshot.go