The SDK defines Runtime Protocol v1. Hosts launch runtimes through go-plugin over gRPC. Runtimes manage workspaces and run commands.
Go 1.26+:
go get github.com/devsy-org/devsy-runtime-sdkImplement runtimev1.RuntimeDriverServer, embedding UnimplementedRuntimeDriverServer by value. Call server.Serve from main. Implement Info, lifecycle RPCs, Exec, and Logs when Info.Capabilities.logs is true. Hosts call runtimev1.ValidateInfo.
Hosts configure plugin.Handshake(), plugin.ProtocolVersion, and plugin.ClientPlugins() under go-plugin.ProtocolGRPC, then call Client.Kill(). The handshake is not authentication or sandboxing.
Exec frames carry stdout and stderr bytes, followed by one exit frame. Reject output after exit. See Exec conformance for chunk limits and exit rules. Cancel commands and release resources; send diagnostics to stderr.
API 1.1: remote_user owns workspaces; user selects the process user. API 1.2: ReusePreflight requires reuse_preflight. API 1.3: RECREATE_MODE_ON_RUN requires InfoRequest.supports_recreate_on_run. Only RunImageRequest.allow_recreate=true authorizes replacement; validate before removal. Otherwise duplicates return AlreadyExists without mutation.
runtime.proto specifies RPCs.
Pass Connect, Workspace, and Command to conformance.Run. Command returns *runtimev1.ExecStart with matching workspace_id, tty=false, and nonempty argv. Map scenarios:
Echo: stdin to stdout untilCloseStdin; exit 0.Arguments: eachArgumentValues()value then NUL on stdout; exit 0.Shell:shell stdout\non stdout; exit 0.Stderr: stdin to stderr; exit 0.Duplex: stdin to stdout and stderr; exit 0.Nonzero:diagnosticon stderr; nonzero exit.Signal: report a signal.EarlyExit: exit 0 without reading stdin.Block:ready\non stdout; wait for cancellation.
Use cmd/devsy-fake-runtime for integration tests. supervisor is not a sandbox. Verify executable paths. On Unix, children that leave the process group need another owner.
mise install
mise exec -- prek run --all-files
mise exec -- go test -race ./...
mise exec -- go vet ./...Schema changes: mise exec -- go generate ./...; check for drift.