// ArcBox API service protocol definitions.
//
// This file contains API-specific services and types that are used by
// arcbox CLI and other high-level clients communicating with the host daemon.
//
// Design sources:
// - internal-docs/architecture/cli-api.md
// - containerd API patterns
syntax = "proto3";
package arcbox.v1;
import "common.proto";
// =============================================================================
// Network Service
// =============================================================================
// NetworkService manages Docker networks.
service NetworkService {
// Creates a new network.
rpc Create(CreateNetworkRequest) returns (CreateNetworkResponse);
// Removes a network.
rpc Remove(RemoveNetworkRequest) returns (Empty);
// Lists networks.
rpc List(ListNetworksRequest) returns (ListNetworksResponse);
// Inspects a network.
rpc Inspect(InspectNetworkRequest) returns (NetworkInfo);
}
// Request to create a network.
message CreateNetworkRequest {
// Network name.
string name = 1;
// Driver (e.g., "bridge", "host", "none").
string driver = 2;
// Internal network (not connected to external network).
bool internal = 3;
// Labels.
map<string, string> labels = 4;
// Enable IPv6.
bool enable_ipv6 = 5;
// IPAM configuration.
IpamConfig ipam = 6;
}
// IPAM configuration.
message IpamConfig {
// Driver name.
string driver = 1;
// IPAM options.
map<string, string> options = 2;
// Subnet configurations.
repeated IpamSubnet subnets = 3;
}
// IPAM subnet configuration.
message IpamSubnet {
// Subnet in CIDR format.
string subnet = 1;
// Gateway address.
string gateway = 2;
// IP range for allocation.
string ip_range = 3;
}
// Response to create network.
message CreateNetworkResponse {
// Network ID.
string id = 1;
// Warning messages.
repeated string warnings = 2;
}
// Request to remove a network.
message RemoveNetworkRequest {
// Network ID or name.
string id = 1;
}
// Request to list networks.
message ListNetworksRequest {
// Filter by labels.
map<string, string> filters = 1;
}
// Response to list networks.
message ListNetworksResponse {
// List of networks.
repeated NetworkSummary networks = 1;
}
// Summary information about a network.
message NetworkSummary {
// Network ID.
string id = 1;
// Network name.
string name = 2;
// Driver.
string driver = 3;
// Scope (local, global).
string scope = 4;
// Created timestamp (RFC3339).
string created = 5;
// Internal network.
bool internal = 6;
// Attachable.
bool attachable = 7;
// Labels.
map<string, string> labels = 8;
}
// Request to inspect a network.
message InspectNetworkRequest {
// Network ID or name.
string id = 1;
// Verbose output.
bool verbose = 2;
}
// Detailed network information.
message NetworkInfo {
// Network ID.
string id = 1;
// Network name.
string name = 2;
// Driver.
string driver = 3;
// Scope.
string scope = 4;
// Created timestamp (RFC3339).
string created = 5;
// Internal network.
bool internal = 6;
// Attachable.
bool attachable = 7;
// Labels.
map<string, string> labels = 8;
// IPAM configuration.
IpamConfig ipam = 9;
// Connected containers.
map<string, NetworkContainer> containers = 10;
// Driver options.
map<string, string> options = 11;
}
// Container connected to a network.
message NetworkContainer {
// Container name.
string name = 1;
// Container endpoint ID.
string endpoint_id = 2;
// IPv4 address.
string ipv4_address = 3;
// IPv6 address.
string ipv6_address = 4;
// MAC address.
string mac_address = 5;
}
// =============================================================================
// System Service
// =============================================================================
// SystemService provides system-level operations.
service SystemService {
// Gets system information.
rpc GetInfo(GetInfoRequest) returns (GetInfoResponse);
// Gets version information.
rpc GetVersion(GetVersionRequest) returns (GetVersionResponse);
// Pings the server.
rpc Ping(SystemPingRequest) returns (SystemPingResponse);
// Gets system events.
rpc Events(EventsRequest) returns (stream Event);
// Prunes unused resources.
rpc Prune(PruneRequest) returns (PruneResponse);
// Gets current daemon setup status. Used by desktop app to show
// startup progress without managing the daemon lifecycle.
rpc GetSetupStatus(Empty) returns (SetupStatus);
// Streams setup status updates. The server pushes a new message
// each time the daemon phase changes (e.g. VM starting → ready).
rpc WatchSetupStatus(Empty) returns (stream SetupStatus);
// Gets the System VM's current hypervisor backend.
rpc GetSystemVmBackend(Empty) returns (SystemVmBackendInfo);
// Switches the System VM's hypervisor backend (HV <-> VZ). The choice is
// persisted; the System VM is restarted so it takes effect, which stops
// running containers. Returns the resulting backend.
rpc SetSystemVmBackend(SetSystemVmBackendRequest) returns (SystemVmBackendInfo);
// Dumps a diagnostic snapshot of the System VM's virtio devices:
// per-queue kick counters, live avail/used ring indices, EVENT_IDX
// slots, and pending interrupt state. Custom-VMM backends only —
// empty under VZ, where the devices belong to
// Virtualization.framework.
rpc GetVirtioDebug(Empty) returns (VirtioDebugInfo);
}
// Hypervisor backend for the single System VM.
enum SystemVmBackend {
// Unset; rejected by SetSystemVmBackend.
SYSTEM_VM_BACKEND_UNSPECIFIED = 0;
// Hypervisor.framework — ArcBox's custom VMM (amd64 via FEX). macOS 15+.
SYSTEM_VM_BACKEND_HV = 1;
// Virtualization.framework — Apple-managed execution. The default.
SYSTEM_VM_BACKEND_VZ = 2;
}
// The System VM's hypervisor backend.
message SystemVmBackendInfo {
SystemVmBackend backend = 1;
}
// Request to switch the System VM's hypervisor backend.
message SetSystemVmBackendRequest {
SystemVmBackend backend = 1;
}
// Diagnostic snapshot of the System VM's virtio devices and vCPUs.
message VirtioDebugInfo {
repeated VirtioDeviceDebug devices = 1;
// Per-vCPU exit counters (custom-VMM backends; empty under VZ).
repeated VcpuDebug vcpus = 2;
// Times any component broadcast hv_vcpus_exit to ALL vCPUs.
uint64 kick_broadcasts = 3;
// Times the IRQ callback unparked ALL vCPU threads on an SPI assertion.
uint64 unpark_broadcasts = 4;
}
// Cumulative exit counters for one vCPU.
message VcpuDebug {
uint32 vcpu = 1;
// MMIO read exits.
uint64 mmio_reads = 2;
// MMIO write exits (includes every virtio QUEUE_NOTIFY doorbell).
uint64 mmio_writes = 3;
// WFI exits — the guest going idle.
uint64 wfi = 4;
// HVC exits (PSCI + ArcBox hypercalls).
uint64 hvc = 5;
// SMC exits.
uint64 smc = 6;
// Virtual-timer activations.
uint64 vtimer = 7;
// Times this vCPU was kicked out of hv_vcpu_run by hv_vcpus_exit.
uint64 kicks_received = 8;
// Trapped system-register accesses (treated RAZ/WI).
uint64 sysreg = 9;
// Unhandled exception classes and unknown exits.
uint64 other = 10;
}
// Snapshot of one virtio MMIO device.
message VirtioDeviceDebug {
// Device ID within the VMM's device manager.
uint32 id = 1;
// Device type, e.g. "VirtioNet".
string device_type = 2;
// Device name.
string name = 3;
// MMIO device status register bits.
uint32 status = 4;
// Pending interrupt reasons not yet acknowledged by the guest.
uint32 interrupt_status = 5;
// Whether VIRTIO_F_EVENT_IDX was negotiated.
bool event_idx = 6;
// Cumulative interrupts raised by the device.
uint64 interrupts = 7;
// Configured queues.
repeated VirtioQueueDebug queues = 8;
}
// Snapshot of one virtqueue. Ring fields are only present when the ring
// address was configured and lies inside guest RAM.
message VirtioQueueDebug {
// Queue index within the device.
uint32 index = 1;
// Ring size negotiated by the driver.
uint32 size = 2;
// QUEUE_READY state.
bool ready = 3;
// Cumulative guest kicks (QUEUE_NOTIFY writes).
uint64 kicks = 4;
// avail.idx — where the guest has published up to.
optional uint32 avail_idx = 5;
// used.idx — where the device has completed up to. A persistent gap
// behind avail_idx means the queue is wedged.
optional uint32 used_idx = 6;
// avail.flags (bit 0 = VRING_AVAIL_F_NO_INTERRUPT).
optional uint32 avail_flags = 7;
// used.flags (bit 0 = VRING_USED_F_NO_NOTIFY).
optional uint32 used_flags = 8;
// used_event slot (guest → device kick threshold; EVENT_IDX only).
optional uint32 used_event = 9;
// avail_event slot (device → guest interrupt threshold; EVENT_IDX only).
optional uint32 avail_event = 10;
}
// Request to get system info.
message GetInfoRequest {}
// Response to get system info.
message GetInfoResponse {
// Number of containers.
int64 containers = 1;
// Running containers.
int64 containers_running = 2;
// Paused containers.
int64 containers_paused = 3;
// Stopped containers.
int64 containers_stopped = 4;
// Number of images.
int64 images = 5;
// Number of machines.
int64 machines = 6;
// Running machines.
int64 machines_running = 7;
// Server version.
string server_version = 8;
// Operating system.
string os = 9;
// Architecture.
string arch = 10;
// Total memory.
int64 mem_total = 11;
// Number of CPUs.
int32 ncpu = 12;
// Data directory.
string data_dir = 13;
// Kernel version.
string kernel_version = 14;
// Operating system type.
string os_type = 15;
// Logging driver.
string logging_driver = 16;
// Storage driver.
string storage_driver = 17;
}
// Request to get version.
message GetVersionRequest {}
// Response to get version.
message GetVersionResponse {
// Version string.
string version = 1;
// API version.
string api_version = 2;
// Minimum API version.
string min_api_version = 3;
// Git commit.
string git_commit = 4;
// Build time.
string build_time = 5;
// OS.
string os = 6;
// Architecture.
string arch = 7;
// Go version (for compatibility).
string go_version = 8;
}
// Request to ping the server.
message SystemPingRequest {}
// Response to ping.
message SystemPingResponse {
// API version.
string api_version = 1;
// Build version.
string build_version = 2;
}
// Request to get events.
message EventsRequest {
// Only events since this timestamp (Unix seconds).
int64 since = 1;
// Only events until this timestamp (Unix seconds).
int64 until = 2;
// Filters.
map<string, string> filters = 3;
}
// System event.
message Event {
// Event type (container, image, network, volume, daemon).
string type = 1;
// Action (create, start, stop, die, destroy, etc.).
string action = 2;
// Actor that generated the event.
EventActor actor = 3;
// Timestamp (Unix nanoseconds).
int64 time_nano = 4;
}
// Event actor.
message EventActor {
// ID of the object.
string id = 1;
// Attributes.
map<string, string> attributes = 2;
}
// Request to prune resources.
message PruneRequest {
// Types to prune: containers, images, networks, volumes, all.
repeated string types = 1;
// Remove all unused resources, not just dangling ones.
bool all = 2;
// Filters.
map<string, string> filters = 3;
}
// Response to prune.
message PruneResponse {
// Space reclaimed in bytes.
uint64 space_reclaimed = 1;
// Deleted containers.
repeated string containers_deleted = 2;
// Deleted images.
repeated string images_deleted = 3;
// Deleted networks.
repeated string networks_deleted = 4;
// Deleted volumes.
repeated string volumes_deleted = 5;
}
// =============================================================================
// Icon Service
// =============================================================================
// IconService provides container image icon lookups.
service IconService {
// Gets the icon URL for a container image reference.
rpc GetImageIcon(GetImageIconRequest) returns (GetImageIconResponse);
}
// Request to get the icon URL for a container image.
message GetImageIconRequest {
// Fully qualified image name (e.g., "nginx", "localstack/localstack", "ghcr.io/astral-sh/uv").
string fqin = 1;
}
// Response containing the icon URL.
message GetImageIconResponse {
// Icon URL, empty if not found.
string url = 1;
// Icon source (e.g., "docker_hub_logo", "docker_official_image", "ghcr_avatar").
string source = 2;
}
// =============================================================================
// Volume Service
// =============================================================================
// VolumeService manages Docker volumes.
service VolumeService {
// Creates a volume.
rpc Create(CreateVolumeRequest) returns (CreateVolumeResponse);
// Removes a volume.
rpc Remove(RemoveVolumeRequest) returns (Empty);
// Lists volumes.
rpc List(ListVolumesRequest) returns (ListVolumesResponse);
// Inspects a volume.
rpc Inspect(InspectVolumeRequest) returns (VolumeInfo);
}
// Request to create a volume.
message CreateVolumeRequest {
// Volume name.
string name = 1;
// Driver name.
string driver = 2;
// Driver options.
map<string, string> driver_opts = 3;
// Labels.
map<string, string> labels = 4;
}
// Response to create volume.
message CreateVolumeResponse {
// Volume name.
string name = 1;
// Driver.
string driver = 2;
// Mountpoint.
string mountpoint = 3;
}
// Request to remove a volume.
message RemoveVolumeRequest {
// Volume name.
string name = 1;
// Force removal.
bool force = 2;
}
// Request to list volumes.
message ListVolumesRequest {
// Filters.
map<string, string> filters = 1;
}
// Response to list volumes.
message ListVolumesResponse {
// List of volumes.
repeated VolumeInfo volumes = 1;
// Warnings.
repeated string warnings = 2;
}
// Request to inspect a volume.
message InspectVolumeRequest {
// Volume name.
string name = 1;
}
// Volume information.
message VolumeInfo {
// Volume name.
string name = 1;
// Driver.
string driver = 2;
// Mountpoint.
string mountpoint = 3;
// Created timestamp (RFC3339).
string created = 4;
// Status.
map<string, string> status = 5;
// Labels.
map<string, string> labels = 6;
// Scope (local, global).
string scope = 7;
// Driver options.
map<string, string> options = 8;
// Usage data.
VolumeUsage usage = 9;
}
// Volume usage data.
message VolumeUsage {
// Size in bytes.
int64 size = 1;
// Reference count.
int64 ref_count = 2;
}
// =============================================================================
// Migration Service
// =============================================================================
// MigrationService plans and runs host-side runtime migrations.
service MigrationService {
// Prepares a migration plan for a supported external runtime.
rpc PrepareMigration(PrepareMigrationRequest) returns (PrepareMigrationResponse);
// Runs a prepared migration plan and streams execution progress.
rpc RunMigration(RunMigrationRequest) returns (stream RunMigrationEvent);
}
// Request to prepare a migration.
message PrepareMigrationRequest {
// Stable source runtime identifier (for example, "docker-desktop" or "orbstack").
string source_kind = 1;
// Optional override for the source Docker-compatible socket path.
string source_socket_path = 2;
// Allow prepare to include replace actions in the plan.
bool allow_replacements = 3;
}
// Prepared migration summary.
message PrepareMigrationResponse {
// Opaque identifier for the prepared plan.
string plan_id = 1;
// Source runtime identifier used for the plan.
string source_kind = 2;
// Resolved source socket path used for the plan.
string source_socket_path = 3;
// Number of images included in the plan.
uint32 image_count = 4;
// Number of volumes included in the plan.
uint32 volume_count = 5;
// Number of networks included in the plan.
uint32 network_count = 6;
// Number of containers included in the plan.
uint32 container_count = 7;
// Whether the plan would replace existing ArcBox resources (images, volumes,
// networks, or containers that already exist on the target). When true,
// RunMigrationRequest.allow_replacements must be set to confirm.
bool replacements_required = 8;
// Non-fatal warnings discovered during preparation (for example, volume
// blockers that will require stopping running source containers).
repeated string warnings = 9;
}
// Request to run a prepared migration.
message RunMigrationRequest {
// Opaque identifier returned by PrepareMigration.
string plan_id = 1;
// Confirms that the caller accepts any replace actions in the plan.
bool allow_replacements = 2;
}
// Streaming migration progress event.
message RunMigrationEvent {
// Opaque identifier of the plan being executed.
string plan_id = 1;
// High-level execution phase (for example, "prepare", "images", or "containers").
string phase = 2;
// Optional resource name currently being processed.
string resource = 3;
// Human-readable progress detail.
string message = 4;
// Number of completed work items in the current phase.
uint32 completed = 5;
// Total work items expected in the current phase.
uint32 total = 6;
// Indicates that no more events will follow for this run.
bool done = 7;
// Indicates whether the run completed successfully.
bool success = 8;
}
// =============================================================================
// Shell/Interactive Session Types
// =============================================================================
// Shell input for interactive sessions.
message ShellInput {
// Input data.
bytes data = 1;
// Resize terminal.
TerminalSize resize = 2;
}
// Shell output for interactive sessions.
message ShellOutput {
// Output data.
bytes data = 1;
// Exit code (only set when done).
int32 exit_code = 2;
// Is this the final message.
bool done = 3;
}
// Terminal size.
message TerminalSize {
// Terminal width.
uint32 width = 1;
// Terminal height.
uint32 height = 2;
}
// =============================================================================
// Setup Status
// =============================================================================
// Daemon startup progress and infrastructure health.
// Allows the desktop app (or any gRPC client) to observe daemon readiness
// without managing its lifecycle.
message SetupStatus {
// Daemon startup phases, ordered by progression.
enum Phase {
PHASE_UNSPECIFIED = 0;
INITIALIZING = 1;
ASSETS_READY = 2;
VM_STARTING = 3;
VM_READY = 4;
NETWORK_READY = 5;
READY = 6;
DEGRADED = 7;
DOWNLOADING_ASSETS = 8;
CLEANING_UP = 9;
// Startup failed fatally; the daemon exits shortly after
// publishing this phase. See the `error` field for the cause.
FAILED = 10;
}
// Current daemon phase.
Phase phase = 1;
// Whether the DNS resolver file is installed.
bool dns_resolver_installed = 2;
// Whether /var/run/docker.sock is symlinked to ArcBox.
bool docker_socket_linked = 3;
// Whether the container subnet route is installed.
bool route_installed = 4;
// Whether the default VM is running.
bool vm_running = 5;
// Human-readable status message.
string message = 6;
// Whether Docker CLI tools are installed.
bool docker_tools_installed = 7;
// Fatal startup error description. Set only when phase == FAILED,
// so streaming clients learn the cause instead of seeing a bare
// disconnect when the daemon exits.
string error = 8;
}