Skip to content

feat: experimental vfkit fast-boot engine (v0.9.5) - #53

Merged
enegalan merged 1 commit into
mainfrom
feat/vfkit-fast-boot
Jul 19, 2026
Merged

feat: experimental vfkit fast-boot engine (v0.9.5)#53
enegalan merged 1 commit into
mainfrom
feat/vfkit-fast-boot

Conversation

@enegalan

@enegalan enegalan commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add experimental macOS vfkit runtime (virtio-vsock Docker) with auto-select when a guest disk exists or vfkit is bundled next to the daemon
  • First-run download/extract of calf-vfkit-disk-<arch>.raw.zst from GitHub Releases; CI builds the guest asset on release
  • Faster Lima readiness + public benchmark updates; bump to 0.9.5

Test plan

  • CI backend + UI green
  • After merge, Release workflow publishes draft v0.9.5 including calf-vfkit-disk-*.raw.zst
  • Optional local: make guest-vfkit then make benchmarks-vfkit

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added an experimental fast-boot runtime for macOS using vfkit, with automatic selection and Lima fallback.
    • Added runtime startup through POST /v1/runtime/start.
    • macOS releases can include prebuilt vfkit guest disk and EFI assets.
    • Added automatic guest disk downloading, extraction, and Docker connectivity setup.
  • Bug Fixes

    • Improved Lima startup readiness so in-VM commands wait until the shell is available.
  • Documentation

    • Added vfkit benchmarks, usage guidance, release notes, and Phase 5 progress documentation.

Ship a direct VZ path that beats OrbStack on cold start and most public
benchmarks, with auto-select when a guest disk (or bundled vfkit +
release seed) is available, CI guest-disk assets, and v0.9.5.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds an experimental macOS vfkit runtime, Darwin runtime selection, guest disk creation and download flows, a runtime start API, release packaging, benchmark integration, and updated project documentation and version metadata.

Changes

Runtime entry points and selection

Layer / File(s) Summary
Runtime entry points and selection
backend/internal/api/*, backend/internal/runtime/runtime.go, backend/internal/runtime/select_*.go, backend/internal/runtime/lima.go, backend/internal/runtime/lima.yaml
Adds POST /v1/runtime/start, Darwin vfkit/Lima selection, Lima shell-readiness synchronization, and provisioning guards for already-active services.

vfkit engine and guest disk

Layer / File(s) Summary
vfkit engine and guest disk
backend/internal/runtime/vfkit_darwin.go, backend/internal/runtime/vfkit_disk_fetch_darwin.go, backend/internal/constants/constants.go, backend/test/runtime/*, backend/go.mod
Implements the Darwin vfkit runtime, Docker-over-vsock operations, guest disk extraction/downloads, EFI handling, atomic HTTP downloads, and zstd round-trip validation.

Guest image and release pipeline

Layer / File(s) Summary
Guest image and release pipeline
scripts/guest-image/*, .github/workflows/*, Makefile, ui/macos/Runner.xcodeproj/project.pbxproj
Builds and packages vfkit guest disks, optionally embeds vfkit in the macOS app, and publishes guest disk artifacts through CI and releases.

vfkit benchmark orchestration

Layer / File(s) Summary
vfkit benchmark orchestration
scripts/benchmarks/*
Adds vfkit-specific daemon readiness, runtime start, shutdown, Lima autostart control, process cleanup, polling, and RSS measurement behavior.

Documentation and release metadata

Layer / File(s) Summary
Documentation and release metadata
BENCHMARKS.md, docs/phase5-race.md, ROADMAP.md, CHANGELOG.md, CLAUDE.md, .cursor/rules/*, backend/version/version.go, ui/pubspec.yaml
Documents vfkit benchmarks, implementation stages, runtime selection, remaining work, release notes, and version 0.9.5 metadata.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CalfDaemon
  participant Vfkit
  participant GuestDisk
  participant Docker
  User->>CalfDaemon: POST /v1/runtime/start
  CalfDaemon->>Vfkit: Start runtime
  Vfkit->>GuestDisk: Ensure or download disk
  Vfkit->>Docker: Boot guest and poll /_ping
  Docker-->>Vfkit: Ready
  Vfkit-->>CalfDaemon: Runtime status
  CalfDaemon-->>User: JSON status
Loading

Possibly related PRs

  • enegalan/calf#51: Introduced the benchmark framework modified here for vfkit-specific startup, shutdown, and readiness flows.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: an experimental vfkit fast-boot engine and the 0.9.5 release.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vfkit-fast-boot

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@enegalan
enegalan merged commit fcf2192 into main Jul 19, 2026
2 of 3 checks passed
@enegalan
enegalan deleted the feat/vfkit-fast-boot branch July 19, 2026 12:44

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/internal/runtime/lima.go (1)

120-133: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Background limactl start goroutine uses the request-scoped ctx, not the already-available lifeCtx — gets killed once the caller's timeout context is cancelled.

lifeCtx (line 120) exists precisely so that work started here can outlive this Start() call (it's used for ensureBuildxAsync and the proxy-apply goroutine). But startVMUntilDockerReady(ctx) (line 130) passes the caller's ctx instead. EnsureRuntimeRunning (backend/internal/daemon/runtime_ready.go) calls s.Runtime.Start(startCtx) with startCtx, cancel := context.WithTimeout(ctx, 3*time.Minute); defer cancel(). As soon as Start() returns success and EnsureRuntimeRunning's own polling loop sees Running, cancel() fires — killing the still-in-flight limactl start process (and the goroutine at lines 208-213 watching it) even though Docker became reachable before limactl start fully finished. This can abort VM provisioning mid-flight and spuriously flips shellReady back to false.

🔧 Proposed fix: use `lifeCtx` for work that must survive the call
 	running, err := l.vmIsRunning(ctx)
 	if err != nil {
 		return err
 	}
 
 	if running {
 		l.shellReady.Store(true)
 	} else {
-		if err := l.startVMUntilDockerReady(ctx); err != nil {
+		if err := l.startVMUntilDockerReady(ctx, lifeCtx); err != nil {
 			return err
 		}
 	}

And inside startVMUntilDockerReady, run the two background goroutines against lifeCtx instead of ctx (keeping ctx for the synchronous instanceExists/create calls and for the select's <-ctx.Done() early-return), so cancelling the caller's short-lived context no longer kills the in-flight limactl start.

Also applies to: 160-216

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/runtime/lima.go` around lines 120 - 133, Use the lifecycle
context for VM startup work that must outlive Start: pass lifeCtx from Start
into startVMUntilDockerReady, and use lifeCtx for both background goroutines
that launch or monitor limactl start. Keep the request-scoped ctx for
synchronous instanceExists/create operations and the select’s ctx.Done early
return.
🧹 Nitpick comments (4)
scripts/benchmarks/_common.sh (1)

223-235: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a shared "force-stop vfkit guest" helper. Both sites independently implement the same disable-autostart → kill-limactl → kill-vfkit-pid → pkill-vfkit → wait-for-exit sequence; any future change (e.g., an extra cleanup step) risks drifting between the two copies.

  • scripts/benchmarks/_common.sh#L223-L235: extract this sequence (lines 224-233) into a helper, e.g. force_stop_vfkit_calf, and call it here before stop_calf_daemon.
  • scripts/benchmarks/run-all.sh#L121-L152: call the same force_stop_vfkit_calf helper (lines 129-137) instead of re-inlining the sequence, then keep the rm -f docker.sock / wait_for_docker_host_down steps that are specific to this call site.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/benchmarks/_common.sh` around lines 223 - 235, Extract the duplicated
disable-autostart and force-stop sequence into a shared force_stop_vfkit_calf
helper in scripts/benchmarks/_common.sh, and call it from the _common.sh cleanup
site before stop_calf_daemon. In scripts/benchmarks/run-all.sh, replace the
inlined sequence with the same helper while retaining the site-specific rm -f
docker.sock and wait_for_docker_host_down steps.
.github/workflows/release.yml (1)

80-104: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated vfkit-guest CI job body across two workflow files. The build/pack/upload steps for the guest disk asset are copy-pasted between the two files with no shared definition, so any future change (paths, artifact name, tool versions) risks drifting out of sync between them.

  • .github/workflows/release.yml#L80-L104: extract this job body into a reusable workflow (workflow_call) or composite action and have this job call it.
  • .github/workflows/vfkit-guest.yml#L16-L38: have this workflow call the same reusable workflow/action instead of duplicating the steps.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 80 - 104, Extract the duplicated
vfkit guest build, packaging, and upload steps into one reusable workflow or
composite action. Update .github/workflows/release.yml lines 80-104 and
.github/workflows/vfkit-guest.yml lines 16-38 so both vfkit-guest jobs invoke
that shared definition, preserving the existing runner, tooling, artifact name,
and asset paths.
backend/internal/runtime/vfkit_disk_fetch_darwin.go (1)

118-144: 🔒 Security & Privacy | 🔵 Trivial | ⚖️ Poor tradeoff

Consider verifying downloaded disk integrity.

downloadGuestDisk fetches a multi-GB guest disk over HTTPS and extracts it without any checksum/signature verification. A corrupted or truncated download that still returns HTTP 200 will be extracted and booted. If the release pipeline can publish a checksum asset, validate it after downloadFile before extractGuestSeed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/runtime/vfkit_disk_fetch_darwin.go` around lines 118 - 144,
The downloadGuestDisk flow currently accepts the guest disk without integrity
validation. Add checksum or signature asset resolution and validate dest after
downloadFile succeeds, before the disk reaches extractGuestSeed; return a
descriptive error and reject or remove the artifact when verification fails,
while preserving the existing optional EFI behavior.
backend/internal/runtime/vfkit_darwin.go (1)

249-581: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add doc comments to exported and unexported methods/functions. Several new Go declarations have no immediately preceding // doc comment, which the project requires. As per coding guidelines: "Add a doc comment to every function and method: // immediately above Go declarations."

  • backend/internal/runtime/vfkit_darwin.go#L249-L581: document stopProcess, processAlive, waitForDockerAPI, dockerAPIReady, runLocal, runLocalWithStdin, and the Runtime interface implementations (ListContainers, ListImages, … RegistryLogout).
  • backend/internal/runtime/vfkit_disk_fetch_darwin.go#L170-L218: document releaseAssetURL, latestReleaseAssetURL, getJSON, and downloadFile.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/runtime/vfkit_darwin.go` around lines 249 - 581, Add
immediately preceding Go doc comments for every listed declaration in
backend/internal/runtime/vfkit_darwin.go lines 249-581: stopProcess,
processAlive, waitForDockerAPI, dockerAPIReady, runLocal, runLocalWithStdin, and
all Runtime implementations through RegistryLogout, using comments that describe
each method’s behavior and begin with its declaration name. Also document
releaseAssetURL, latestReleaseAssetURL, getJSON, and downloadFile in
backend/internal/runtime/vfkit_disk_fetch_darwin.go lines 170-218; no other
changes are needed.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/api/runtime.go`:
- Around line 10-21: Update handleRuntimeStart to route both
EnsureRuntimeRunning and Runtime.Status errors through httpkit.WriteRuntimeError
instead of directly calling httpkit.WriteError with err.Error(), preserving the
existing early returns and successful status response.

In `@backend/internal/runtime/vfkit_darwin.go`:
- Line 389: Protect the shared proxy configuration with v.mu: update ApplyProxy
to lock while assigning v.proxy, and update runLocal to read/copy v.proxy under
the same mutex before constructing the environment. Preserve the existing proxy
behavior while ensuring all accesses use the shared lock.

In `@CHANGELOG.md`:
- Around line 8-21: Rewrite the 0.9.5 entries in CHANGELOG.md to describe
user-visible benefits only: fast startup on supported macOS systems and the
ability to start the container runtime while the daemon remains running. Remove
implementation details, library and binary names, artifact filenames, build
commands, documentation references, and HTTP endpoint/protocol terminology.

In `@scripts/benchmarks/_common.sh`:
- Around line 264-288: Remove the second duplicate definition of
enable_lima_autostart_calf, retaining the first implementation and its existing
behavior. Keep disable_lima_autostart_calf unchanged.

In `@scripts/guest-image/unpack-vfkit-disk.sh`:
- Around line 23-26: Update the EFI archive lookup in the unpack flow around
EFI_ZST so it supports the release asset naming pattern
calf-vfkit-efi-<arch>.zst alongside the existing efi-store.zst name. Mirror the
runtime extractGuestSeed lookup behavior, selecting an available sibling archive
before running the existing zstd extraction.

In `@ui/macos/Runner.xcodeproj/project.pbxproj`:
- Line 341: Ensure the macOS release workflow installs or exposes vfkit before
packaging so the Xcode shellScript can bundle it. Update
.github/workflows/release.yml lines 21-25 and 66-68 to install vfkit with
Homebrew or set CALF_VFKIT_BIN; ui/macos/Runner.xcodeproj/project.pbxproj lines
341-341 requires no direct change because its existing lookup and copy logic
will then include the binary.

---

Outside diff comments:
In `@backend/internal/runtime/lima.go`:
- Around line 120-133: Use the lifecycle context for VM startup work that must
outlive Start: pass lifeCtx from Start into startVMUntilDockerReady, and use
lifeCtx for both background goroutines that launch or monitor limactl start.
Keep the request-scoped ctx for synchronous instanceExists/create operations and
the select’s ctx.Done early return.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 80-104: Extract the duplicated vfkit guest build, packaging, and
upload steps into one reusable workflow or composite action. Update
.github/workflows/release.yml lines 80-104 and .github/workflows/vfkit-guest.yml
lines 16-38 so both vfkit-guest jobs invoke that shared definition, preserving
the existing runner, tooling, artifact name, and asset paths.

In `@backend/internal/runtime/vfkit_darwin.go`:
- Around line 249-581: Add immediately preceding Go doc comments for every
listed declaration in backend/internal/runtime/vfkit_darwin.go lines 249-581:
stopProcess, processAlive, waitForDockerAPI, dockerAPIReady, runLocal,
runLocalWithStdin, and all Runtime implementations through RegistryLogout, using
comments that describe each method’s behavior and begin with its declaration
name. Also document releaseAssetURL, latestReleaseAssetURL, getJSON, and
downloadFile in backend/internal/runtime/vfkit_disk_fetch_darwin.go lines
170-218; no other changes are needed.

In `@backend/internal/runtime/vfkit_disk_fetch_darwin.go`:
- Around line 118-144: The downloadGuestDisk flow currently accepts the guest
disk without integrity validation. Add checksum or signature asset resolution
and validate dest after downloadFile succeeds, before the disk reaches
extractGuestSeed; return a descriptive error and reject or remove the artifact
when verification fails, while preserving the existing optional EFI behavior.

In `@scripts/benchmarks/_common.sh`:
- Around line 223-235: Extract the duplicated disable-autostart and force-stop
sequence into a shared force_stop_vfkit_calf helper in
scripts/benchmarks/_common.sh, and call it from the _common.sh cleanup site
before stop_calf_daemon. In scripts/benchmarks/run-all.sh, replace the inlined
sequence with the same helper while retaining the site-specific rm -f
docker.sock and wait_for_docker_host_down steps.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 204a85a4-97b0-4558-8bae-74b670dc13bd

📥 Commits

Reviewing files that changed from the base of the PR and between 7968380 and c1133e3.

⛔ Files ignored due to path filters (1)
  • backend/go.sum is excluded by !**/*.sum
📒 Files selected for processing (31)
  • .cursor/rules/calf.mdc
  • .github/workflows/release.yml
  • .github/workflows/vfkit-guest.yml
  • BENCHMARKS.md
  • CHANGELOG.md
  • CLAUDE.md
  • Makefile
  • ROADMAP.md
  • backend/go.mod
  • backend/internal/api/gateway.go
  • backend/internal/api/runtime.go
  • backend/internal/constants/constants.go
  • backend/internal/runtime/lima.go
  • backend/internal/runtime/lima.yaml
  • backend/internal/runtime/runtime.go
  • backend/internal/runtime/select_darwin.go
  • backend/internal/runtime/select_other.go
  • backend/internal/runtime/vfkit_darwin.go
  • backend/internal/runtime/vfkit_disk_fetch_darwin.go
  • backend/test/runtime/vfkit_disk_zstd_test.go
  • backend/version/version.go
  • docs/phase5-race.md
  • scripts/benchmarks/_common.sh
  • scripts/benchmarks/run-all.sh
  • scripts/guest-image/build-vfkit-guest.sh
  • scripts/guest-image/lima-vfkit.yaml
  • scripts/guest-image/pack-vfkit-disk.sh
  • scripts/guest-image/prepare-vfkit-disk.sh
  • scripts/guest-image/unpack-vfkit-disk.sh
  • ui/macos/Runner.xcodeproj/project.pbxproj
  • ui/pubspec.yaml

Comment on lines +10 to +21
func (g *Gateway) handleRuntimeStart(w http.ResponseWriter, r *http.Request) {
if err := g.backend.EnsureRuntimeRunning(r.Context()); err != nil {
httpkit.WriteError(w, http.StatusServiceUnavailable, err.Error())
return
}
status, err := g.backend.Runtime.Status(r.Context())
if err != nil {
httpkit.WriteError(w, http.StatusInternalServerError, err.Error())
return
}
httpkit.WriteJSON(w, http.StatusOK, status)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether writeRuntimeError exists and how other handlers report runtime errors.
rg -n -A5 -B2 'func writeRuntimeError' backend/internal/api backend/internal/httpkit
rg -n 'writeRuntimeError\(' backend/internal/api
rg -n -A3 'func WriteError' backend/internal/httpkit

Repository: enegalan/calf

Length of output: 442


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== runtime.go ==\n'
cat -n backend/internal/api/runtime.go

printf '\n== api error helpers/search ==\n'
rg -n -A3 -B3 'writeRuntimeError|WriteError\(|WriteJSON\(' backend/internal/api backend/internal/httpkit

printf '\n== httpkit response helper ==\n'
cat -n backend/internal/httpkit/response.go

Repository: enegalan/calf

Length of output: 41523


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== runtime-related symbols ==\n'
rg -n 'EnsureRuntimeRunning|Runtime\.Status|handleRuntimeStart|handleRuntime' backend/internal/api backend/internal -g '!**/*_test.go'

printf '\n== line counts for relevant files ==\n'
wc -l backend/internal/api/runtime.go backend/internal/httpkit/response.go

Repository: enegalan/calf

Length of output: 2719


Route runtime errors through httpkit.WriteRuntimeError here.

Both failures currently send err.Error() back to the client, which can leak wrapped internal details like Runtime.Status: .... httpkit.WriteRuntimeError already maps the runtime cases to safe HTTP responses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/api/runtime.go` around lines 10 - 21, Update
handleRuntimeStart to route both EnsureRuntimeRunning and Runtime.Status errors
through httpkit.WriteRuntimeError instead of directly calling httpkit.WriteError
with err.Error(), preserving the existing early returns and successful status
response.

Source: Coding guidelines

}
return removeNetwork(ctx, v.runLocal, name)
}
func (v *Vfkit) ApplyProxy(ctx context.Context, proxy ProxyConfig) error { v.proxy = proxy; return nil }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard v.proxy with the mutex to avoid a data race.

ApplyProxy writes v.proxy with no lock, while runLocal (Line 339) reads v.proxy on request-handler goroutines. Concurrent Docker operations and a proxy update produce a data race / torn read on the ProxyConfig struct. v.cmd is already guarded by v.mu; do the same for v.proxy.

🔒️ Proposed fix
-func (v *Vfkit) ApplyProxy(ctx context.Context, proxy ProxyConfig) error { v.proxy = proxy; return nil }
+func (v *Vfkit) ApplyProxy(ctx context.Context, proxy ProxyConfig) error {
+	v.mu.Lock()
+	v.proxy = proxy
+	v.mu.Unlock()
+	return nil
+}

runLocal should read the field under the same lock before building the env.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (v *Vfkit) ApplyProxy(ctx context.Context, proxy ProxyConfig) error { v.proxy = proxy; return nil }
func (v *Vfkit) ApplyProxy(ctx context.Context, proxy ProxyConfig) error {
v.mu.Lock()
v.proxy = proxy
v.mu.Unlock()
return nil
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/runtime/vfkit_darwin.go` at line 389, Protect the shared
proxy configuration with v.mu: update ApplyProxy to lock while assigning
v.proxy, and update runLocal to read/copy v.proxy under the same mutex before
constructing the environment. Preserve the existing proxy behavior while
ensuring all accesses use the shared lock.

Comment thread CHANGELOG.md
Comment on lines +8 to +21
## [Unreleased]

## [0.9.5] - 2026-07-19

### Added

- **Experimental fast-boot engine (macOS)** — when a provisioned vfkit guest disk (or release seed) and `vfkit` binary are present, Calf prefers that engine automatically; bundled apps download `calf-vfkit-disk-<arch>.raw.zst` from GitHub Releases on first start; build locally with `make guest-vfkit` (see `BENCHMARKS.md` and `docs/phase5-race.md`).
- **Runtime start API** — `POST /v1/runtime/start` boots the container runtime while the daemon stays up (used for fair VM-boot benches on vfkit).

### Changed

- **Lima startup** — the Docker API can become ready before Lima finishes its SSH/boot-script gates, so the engine is usable sooner after a full VM stop.

## [0.9.4] - 2026-07-18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Rewrite changelog entries to omit implementation details, file paths, and protocol jargon.

The current entries for version 0.9.5 contain implementation specifics (e.g., calf-vfkit-disk-<arch>.raw.zst, make guest-vfkit, BENCHMARKS.md, docs/phase5-race.md, and the POST /v1/runtime/start endpoint). As per coding guidelines, CHANGELOG.md entries must be written in user-facing terms, without implementation details, library names, file paths, or protocol jargon.

📝 Proposed fix
 ## [0.9.5] - 2026-07-19
 
 ### Added
 
-- **Experimental fast-boot engine (macOS)** — when a provisioned vfkit guest disk (or release seed) and `vfkit` binary are present, Calf prefers that engine automatically; bundled apps download `calf-vfkit-disk-<arch>.raw.zst` from GitHub Releases on first start; build locally with `make guest-vfkit` (see `BENCHMARKS.md` and `docs/phase5-race.md`).
-- **Runtime start API** — `POST /v1/runtime/start` boots the container runtime while the daemon stays up (used for fair VM-boot benches on vfkit).
+- **Experimental fast-boot engine (macOS)** — a new, significantly faster container engine is available on macOS and is selected automatically when prerequisites are met. The application will fetch the required components on first start.
+- **Runtime start API** — added an endpoint to start the container engine while the application daemon remains running, improving benchmark workflows.
 
 ### Changed
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## [Unreleased]
## [0.9.5] - 2026-07-19
### Added
- **Experimental fast-boot engine (macOS)**when a provisioned vfkit guest disk (or release seed) and `vfkit` binary are present, Calf prefers that engine automatically; bundled apps download `calf-vfkit-disk-<arch>.raw.zst` from GitHub Releases on first start; build locally with `make guest-vfkit` (see `BENCHMARKS.md` and `docs/phase5-race.md`).
- **Runtime start API**`POST /v1/runtime/start` boots the container runtime while the daemon stays up (used for fair VM-boot benches on vfkit).
### Changed
- **Lima startup** — the Docker API can become ready before Lima finishes its SSH/boot-script gates, so the engine is usable sooner after a full VM stop.
## [0.9.4] - 2026-07-18
## [Unreleased]
## [0.9.5] - 2026-07-19
### Added
- **Experimental fast-boot engine (macOS)**a new, significantly faster container engine is available on macOS and is selected automatically when prerequisites are met. The application will fetch the required components on first start.
- **Runtime start API**added an endpoint to start the container engine while the application daemon remains running, improving benchmark workflows.
### Changed
- **Lima startup** — the Docker API can become ready before Lima finishes its SSH/boot-script gates, so the engine is usable sooner after a full VM stop.
## [0.9.4] - 2026-07-18
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 8 - 21, Rewrite the 0.9.5 entries in CHANGELOG.md
to describe user-visible benefits only: fast startup on supported macOS systems
and the ability to start the container runtime while the daemon remains running.
Remove implementation details, library and binary names, artifact filenames,
build commands, documentation references, and HTTP endpoint/protocol
terminology.

Source: Coding guidelines

Comment on lines +264 to +288
# disable_lima_autostart_calf unloads the Lima start-at-login agent for the Calf VM.
disable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootout "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}

# enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
enable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}


# enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
enable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

enable_lima_autostart_calf is defined twice.

The block defines enable_lima_autostart_calf at lines 273-278 and again identically at 281-288. Shellcheck flags the first definition as unreachable/never invoked (SC2329), since the second silently shadows it. Remove the duplicate.

🧹 Proposed fix to remove the duplicate definition
 # enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
 enable_lima_autostart_calf() {
   local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
   if [[ -f "$plist" ]]; then
     launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
   fi
 }
-
-
-# enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
-enable_lima_autostart_calf() {
-  local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
-  if [[ -f "$plist" ]]; then
-    launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
-  fi
-}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# disable_lima_autostart_calf unloads the Lima start-at-login agent for the Calf VM.
disable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootout "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}
# enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
enable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}
# enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
enable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}
# disable_lima_autostart_calf unloads the Lima start-at-login agent for the Calf VM.
disable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootout "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}
# enable_lima_autostart_calf restores the Lima start-at-login agent if the plist exists.
enable_lima_autostart_calf() {
local plist="${HOME}/Library/LaunchAgents/io.lima-vm.autostart.${CALF_VM_NAME}.plist"
if [[ -f "$plist" ]]; then
launchctl bootstrap "gui/$(id -u)" "$plist" >/dev/null 2>&1 || true
fi
}
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 273-278: This function is never invoked. Check usage (or ignored if invoked indirectly).

(SC2329)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/benchmarks/_common.sh` around lines 264 - 288, Remove the second
duplicate definition of enable_lima_autostart_calf, retaining the first
implementation and its existing behavior. Keep disable_lima_autostart_calf
unchanged.

Source: Linters/SAST tools

Comment on lines +23 to +26
EFI_ZST="$(dirname "$ARCHIVE")/efi-store.zst"
if [[ -f "$EFI_ZST" ]]; then
zstd -f -d -o "${DEST_DIR}/efi-store" "$EFI_ZST"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

EFI lookup only matches efi-store.zst, not the release asset name.

When users unpack a GitHub Release disk asset (calf-vfkit-disk-<arch>.raw.zst), its EFI sibling is named calf-vfkit-efi-<arch>.zst, but this script only probes efi-store.zst, so the EFI store is silently skipped. The runtime's extractGuestSeed handles both naming schemes; mirror that here.

🔧 Proposed fix
-EFI_ZST="$(dirname "$ARCHIVE")/efi-store.zst"
-if [[ -f "$EFI_ZST" ]]; then
-  zstd -f -d -o "${DEST_DIR}/efi-store" "$EFI_ZST"
-fi
+EFI_ZST="$(dirname "$ARCHIVE")/efi-store.zst"
+# Release assets name the EFI store per-arch, e.g. calf-vfkit-efi-arm64.zst.
+if [[ ! -f "$EFI_ZST" ]]; then
+  EFI_ZST="$(echo "$ARCHIVE" | sed 's/calf-vfkit-disk-\(.*\)\.raw\.zst/calf-vfkit-efi-\1.zst/')"
+fi
+if [[ -f "$EFI_ZST" ]]; then
+  zstd -f -d -o "${DEST_DIR}/efi-store" "$EFI_ZST"
+fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
EFI_ZST="$(dirname "$ARCHIVE")/efi-store.zst"
if [[ -f "$EFI_ZST" ]]; then
zstd -f -d -o "${DEST_DIR}/efi-store" "$EFI_ZST"
fi
EFI_ZST="$(dirname "$ARCHIVE")/efi-store.zst"
# Release assets name the EFI store per-arch, e.g. calf-vfkit-efi-arm64.zst.
if [[ ! -f "$EFI_ZST" ]]; then
EFI_ZST="$(echo "$ARCHIVE" | sed 's/calf-vfkit-disk-\(.*\)\.raw\.zst/calf-vfkit-efi-\1.zst/')"
fi
if [[ -f "$EFI_ZST" ]]; then
zstd -f -d -o "${DEST_DIR}/efi-store" "$EFI_ZST"
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/guest-image/unpack-vfkit-disk.sh` around lines 23 - 26, Update the
EFI archive lookup in the unpack flow around EFI_ZST so it supports the release
asset naming pattern calf-vfkit-efi-<arch>.zst alongside the existing
efi-store.zst name. Mirror the runtime extractGuestSeed lookup behavior,
selecting an available sibling archive before running the existing zstd
extraction.

runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "set -eu\nDEST_DIR=\"$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME/Contents/MacOS\"\nmkdir -p \"$DEST_DIR\"\n(cd \"$PROJECT_DIR/../../backend\" && CGO_ENABLED=0 go build -o \"$DEST_DIR/calf-daemon\" ./cmd/calf)\nchmod +x \"$DEST_DIR/calf-daemon\"\nif command -v codesign >/dev/null 2>&1; then codesign --force --sign - --identifier com.enegalan.calf.daemon \"$DEST_DIR/calf-daemon\" 2>/dev/null || true; fi\n";
shellScript = "set -eu\nDEST_DIR=\"$TARGET_BUILD_DIR/$FULL_PRODUCT_NAME/Contents/MacOS\"\nmkdir -p \"$DEST_DIR\"\n(cd \"$PROJECT_DIR/../../backend\" && CGO_ENABLED=0 go build -o \"$DEST_DIR/calf-daemon\" ./cmd/calf)\nchmod +x \"$DEST_DIR/calf-daemon\"\nif command -v codesign >/dev/null 2>&1; then codesign --force --sign - --identifier com.enegalan.calf.daemon \"$DEST_DIR/calf-daemon\" 2>/dev/null || true; fi\nVFKIT_SRC=\"${CALF_VFKIT_BIN:-}\"\nif [ -z \"$VFKIT_SRC\" ] && command -v vfkit >/dev/null 2>&1; then VFKIT_SRC=\"$(command -v vfkit)\"; fi\nif [ -n \"$VFKIT_SRC\" ] && [ -x \"$VFKIT_SRC\" ]; then\n cp \"$VFKIT_SRC\" \"$DEST_DIR/vfkit\"\n chmod +x \"$DEST_DIR/vfkit\"\n if command -v codesign >/dev/null 2>&1; then codesign --force --sign - --identifier com.enegalan.calf.vfkit \"$DEST_DIR/vfkit\" 2>/dev/null || true; fi\nfi\n";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== vfkit references ==\n'
rg -n --hidden --glob '!**/.git/**' 'vfkit|CALF_VFKIT_BIN|vfkitReady\(' .

printf '\n== release workflow excerpt ==\n'
sed -n '1,140p' .github/workflows/release.yml

printf '\n== macOS Xcode build phase excerpt ==\n'
sed -n '300,380p' ui/macos/Runner.xcodeproj/project.pbxproj

Repository: enegalan/calf

Length of output: 29522


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Makefile macOS packaging target ==\n'
sed -n '60,95p' Makefile

printf '\n== release-macos / package-macos definitions ==\n'
rg -n '^release-macos:|^package-macos:|VFKIT_SRC|vfkit' Makefile

printf '\n== any workflow mention of vfkit install in release path ==\n'
rg -n 'brew install vfkit|CALF_VFKIT_BIN|release-macos|package-macos' .github/workflows Makefile docs BENCHMARKS.md ROADMAP.md CHANGELOG.md

Repository: enegalan/calf

Length of output: 4677


🌐 Web query:

GitHub Actions macOS runner vfkit preinstalled macos-latest

💡 Result:

GitHub-hosted macOS runners do not officially support nested virtualization, and as a result, they do not provide a preinstalled, supported environment for running tools like vfkit or other hypervisors [1][2][3]. While the command-line tool vfkit—which utilizes Apple's Virtualization framework—is often available for installation via Homebrew on GitHub-hosted macOS runners (or may be included in certain runner environment configurations), attempting to run it typically results in failure because the underlying runner environment does not permit nested virtualization [1][4][2]. Key points regarding this limitation: 1. No Nested Virtualization Support: GitHub Actions documentation explicitly states that nested virtualization is not supported on macOS runners [2]. This applies to both Intel and Apple Silicon (Arm64) architectures [1][2][5]. 2. Environment Constraints: GitHub-hosted runners themselves run on virtual machines, and the limitations of Apple's Virtualization framework (used by the hosting infrastructure) generally prevent users from spawning additional VMs or hypervisors inside the runner [1][6]. 3. vfkit Issues: Users attempting to use tools like Podman Machine or other software that relies on vfkit often report that it exits unexpectedly or throws "virtualization is not enabled" errors [1][4][5]. 4. Alternative Options: Because of these limitations, developers requiring native virtualization support are often directed to use bare-metal runners rather than GitHub-hosted virtualized runners [1]. As of July 19, 2026, the current macOS images (such as macOS 26 "Tahoe") maintain these same restrictions, regardless of the macOS version [7][4].

Citations:


Bundle vfkit during macOS packaging
.github/workflows/release.yml only installs create-dmg before make package-macos, but Makefile only embeds vfkit when it is on PATH or CALF_VFKIT_BIN is set. Add brew install vfkit (or export CALF_VFKIT_BIN) in the macOS release job so the shipped .dmg/.pkg includes the bundled binary.

📍 Affects 2 files
  • ui/macos/Runner.xcodeproj/project.pbxproj#L341-L341 (this comment)
  • .github/workflows/release.yml#L21-L25
  • .github/workflows/release.yml#L66-L68
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui/macos/Runner.xcodeproj/project.pbxproj` at line 341, Ensure the macOS
release workflow installs or exposes vfkit before packaging so the Xcode
shellScript can bundle it. Update .github/workflows/release.yml lines 21-25 and
66-68 to install vfkit with Homebrew or set CALF_VFKIT_BIN;
ui/macos/Runner.xcodeproj/project.pbxproj lines 341-341 requires no direct
change because its existing lookup and copy logic will then include the binary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant