This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
BushelKit is an open-source Swift framework that provides the core components for Bushel, a macOS virtual machine application for developers. It's designed to be modular and reusable, allowing developers to build macOS virtual machine applications and command-line tools.
Tech Stack:
- Swift 6.0+ (with Swift Package Manager)
- Supports: macOS, iOS, watchOS, tvOS, and Linux
- Uses async/await for concurrency
- Sendable-conforming types for thread safety
- Modern Swift features: noncopyable generics, variadic generics
Requirements:
- macOS: Xcode 16.0+, Swift 6.0+, macOS 15+ deployment target
- Linux: Ubuntu 20.04+, Swift 6.0+
# Build the package
swift build
# Run all tests
swift test
# Run tests with code coverage
swift test --enable-code-coverage
# Build documentation
swift package generate-documentation --platform "name=macos,version=15.1" --transform-for-static-hosting --hosting-base-path "swift-docc" --disable-indexing --enable-experimental-combined-documentationThe project uses Mint to manage linting tools (SwiftLint, swift-format, StringsLint). Linting configuration is in .swiftlint.yml, .swift-format, and .stringslint.yml.
# Run all linters and formatters
./Scripts/lint.sh
# Lint in strict mode (used in CI)
LINT_MODE=STRICT ./Scripts/lint.sh
# Format only (skip lint checks)
FORMAT_ONLY=1 ./Scripts/lint.shMint tools used:
swiftlang/swift-format@602.0.0- Code formattingrealm/SwiftLint@0.61.0- Swift lintingdral3x/StringsLint@0.1.9- String lintingperipheryapp/periphery@3.2.0- Unused code detection
IMPORTANT: The Package.swift file is generated from source files in the Package/ directory. Do not edit Package.swift directly.
# Regenerate Package.swift from Package/ source files
./Scripts/package.sh .
# Regenerate with specific Swift tools version
./Scripts/package.sh --version 6.0 .
# Regenerate with minimized output
./Scripts/package.sh --minimize .The package definition uses a custom result builder DSL defined in Package/Sources/ that allows for declarative product and target definitions. After modifying files in Package/Sources/, always regenerate Package.swift.
The BushelKit framework follows a layered, modular architecture organized around domain concerns. The design emphasizes:
- Separation of Concerns - Each module has a specific responsibility
- Protocol-Based Design - Heavy use of protocols for abstraction and extensibility
- Async-First - Comprehensive async/await throughout the codebase
- Type Safety - Strong typing with enums, structs, and generics
- Cross-Platform Support - Abstraction layers to support multiple platforms
BushelFoundation (Core abstractions)
- Location:
/Sources/BushelFoundation/ - Purpose: Provides fundamental types and abstractions for virtual machine management
- Key Types:
VirtualizationData- Represents essential VM data (machine identifier, hardware model)MachineIdentifier- Unique 64-bit identifier for virtual machinesHardwareModel- Hardware configuration descriptorVersion- Version management and comparisonVMSystemError- Virtual machine system error typesImageMetadata- Metadata about OS imagesBookmarkError- File system bookmark errors
BushelUtilities (Helper utilities)
- Location:
/Sources/BushelUtilities/ - Purpose: Common utilities used across the framework
- Key Features:
ByteCountFormatter- Human-readable file size formattingDirectoryExists- File system utilitiesEnvironmentProperty- Environment variable accessIPv6Address- Network address handlingTaskextensions - Async task utilities- Extensions for standard types (Array, URL, String, etc.)
BushelLogging (Logging abstraction)
- Location:
/Sources/BushelLogging/ - Purpose: Unified logging interface
- Key Types:
Loggableprotocol - Types that support logging- Structured logging capabilities
BushelMachine (Virtual machine management)
- Location:
/Sources/BushelMachine/ - Purpose: Core VM lifecycle and state management
- Key Types:
Machineprotocol - Defines VM behavior (start, stop, pause, resume, snapshot, etc.)MachineStateenum - VM state machine (stopped, running, paused, error, starting, pausing, resuming, stopping, saving, restoring)MachineConfiguration- VM configuration specificationMachineSystemprotocol - Platform-specific VM management (e.g., macOS Virtualization)MachineBuilder- Builder pattern for VM creationMachineRegistration- VM registry entryMachineChange- State change notifications- Subdirectories:
Building/- Machine creation and builder logicConfiguration/- Configuration managementMedia/- Video/image capture handlingSnapshots/- Snapshot managementFileVersionSnapshotter/- File versioning system
BushelLibrary (Image library management)
- Location:
/Sources/BushelLibrary/ - Purpose: Management of OS installation images and libraries
- Key Types:
Library- Collection ofLibraryImageFileitemsLibrarySystemprotocol - Platform-specific image library operationsLibraryImageFile- Represents a stored OS imageLibraryError- Library-specific errorsLibraryFile- File wrapper for library items
BushelFactory (VM creation factory)
- Location:
/Sources/BushelFactory/ - Purpose: High-level factory for creating and configuring VMs
- Key Types:
MachineConfiguration- Configuration builder (integrates with BushelMachine)SpecificationConfiguration- Template-based configurationInstallerImage- OS installer image referenceReleaseCollection- Collection of available OS releasesCalculationParameters- Compute specifications (CPU, memory, storage)
BushelMacOSCore (macOS-specific implementation)
- Location:
/Sources/BushelMacOSCore/ - Purpose: macOS Virtualization framework integration
- Key Types:
MacOSVirtualization- macOS-specific implementation ofMachineSystemMacOSRelease- macOS release informationVZMacOSRestoreImage- Virtualization framework restore image wrapperVMSystemID- System identifier for macOS machines
BushelHub (Hub/aggregation services)
- Location:
/Sources/BushelHub/ - Purpose: Central management and aggregation of library and machine resources
BushelHubIPSW (IPSW image management)
- Location:
/Sources/BushelHubIPSW/ - Purpose: Integration with IPSW (Apple's signed OS image format)
BushelHubMacOS (macOS-specific hub services)
- Location:
/Sources/BushelHubMacOS/ - Purpose: macOS-specific hub implementations
BushelGuestProfile (Guest VM configuration)
- Location:
/Sources/BushelGuestProfile/ - Purpose: Guest OS configuration and profile management
BushelVirtualBuddy (Companion/helper services)
- Location:
/Sources/BushelVirtualBuddy/ - Purpose: Supporting services for VM management
Wax modules provide platform-specific wrappers and extensions for core modules:
- BushelFoundationWax - macOS/platform-specific extensions to BushelFoundation
- BushelLibraryWax - macOS/platform-specific library operations
- BushelMachineWax - macOS/platform-specific machine operations
Purpose of Wax Pattern: Isolates platform-specific code from core logic, allowing the same interfaces to work across platforms with different implementations.
BushelDocs (Documentation)
- Location:
/Sources/BushelDocs/ - Purpose: DocC documentation bundle
BushelUT (Unit Testing)
- Location:
/Sources/BushelUT/ - Purpose: Testing utilities and test helpers
BushelTestUtilities (Test Support)
- Location:
/Sources/BushelTestUtilities/ - Purpose: Mock objects and test doubles for testing
BushelArgs (CLI Arguments)
- Location:
/Sources/BushelArgs/ - Purpose: Command-line argument parsing and handling
bushel (Executable)
- Location: Package entry in
/Package/Sources/Products/BushelCommand.swift - Purpose: Command-line tool executable using BushelArgs
BushelKit/
├── Sources/ # Main source code
│ ├── BushelFoundation/ # Core VM abstractions
│ │ ├── Configuration/ # Config file paths and managers
│ │ ├── MachineBuilding/ # Build request types
│ │ └── SigVerification/ # Image signature verification
│ ├── BushelMachine/ # VM lifecycle management
│ │ ├── Building/ # Machine builder implementations
│ │ ├── Configuration/ # Setup configuration
│ │ ├── Media/ # Screen recording/capture
│ │ └── Snapshots/ # VM state snapshots
│ ├── BushelLibrary/ # Image library management
│ ├── BushelFactory/ # VM factory & specifications
│ ├── BushelMacOSCore/ # macOS Virtualization integration
│ ├── BushelUtilities/ # Shared utilities
│ │ ├── Extensions/ # Standard type extensions
│ │ └── FileManager/ # File system utilities
│ ├── BushelLogging/ # Logging abstractions
│ ├── *Wax/ # Platform-specific layers
│ └── [Other domain modules...]
├── Tests/ # Integration tests
│ ├── BushelFoundationTests/
│ ├── BushelMachineTests/
│ ├── BushelLibraryTests/
│ ├── BushelFactoryTests/
│ └── [Other test suites...]
├── Package/ # Swift Package definition
│ └── Sources/
│ ├── Products/ # Product definitions
│ ├── Dependencies/ # Package dependencies
│ ├── Targets/ # Target definitions
│ └── Platforms/ # Platform specifications
└── Package.swift # Main package manifest
CRITICAL: BushelKit uses a generated Package.swift file. The source files are in Package/Sources/ and the generation is done via ./Scripts/package.sh.
The package uses a custom Swift Package builder pattern with result builders:
// Example product definition in Package/Sources/Products/
struct BushelMachine: Product, Target {
var dependencies: any Dependencies {
BushelFoundation()
BushelDocs()
BushelLogging()
}
}
// Products are collected in Package/Sources/Index.swift
let package = Package(
name: "BushelKit",
entries: {
BushelCommand() // Executable
BushelFoundation() // Libraries
BushelMachine()
// ... other products
},
testTargets: {
BushelFoundationTests()
BushelMachineTests()
// ... other tests
}
)Key Pattern Features:
- Uses result builders (@ProductsBuilder, @DependencyBuilder) for declarative syntax
- Custom Protocol hierarchy:
Product,Target,Dependencies - Automatic dependency resolution and transitive dependency management
- Swift Settings applied globally (async, generics features, etc.)
- Always regenerate
Package.swiftafter editing files inPackage/Sources/
The framework heavily uses protocols for abstraction:
public protocol Machine: Loggable, Sendable {
var machineIdentifer: UInt64? { get }
var initialConfiguration: MachineConfiguration { get }
func start() async throws
func stop() async throws
// ... more methods
}
public protocol MachineSystem: Sendable {
associatedtype RestoreImageType: Sendable
func createBuilder(...) async throws -> any MachineBuilder
func machine(at url: URL, ...) async throws -> MachineRegistration
}
public protocol LibrarySystem: Sendable {
var id: VMSystemID { get }
func metadata(fromURL url: URL, verifier: any SigVerifier) async throws -> ImageMetadata
}Benefits:
- Multiple implementations per protocol (e.g., macOS, Linux, testable mocks)
- Loose coupling between modules
- Easy testing via mock implementations
Used extensively for complex object creation:
// MachineBuilder protocol defines the construction process
public protocol MachineBuilder: Sendable {
// Build machine step-by-step
}
// MachineSystem creates builders for specific platforms
let builder = try await macOSSystem.createBuilder(for: configuration, at: url)MachineState enum implements state management:
public enum MachineState: Int, Sendable {
case stopped = 0
case running = 1
case paused = 2
case starting = 4
case pausing = 5
case resuming = 6
case stopping = 7
// ... transitions defined by Machine protocol methods
}All I/O operations are async:
// VM operations
func start() async throws
func pause() async throws
func stop() async throws
func beginSnapshot() throws -> SnapshotPaths
func finishedWithSnapshot(_ snapshot: Snapshot, by difference: SnapshotDifference) async
// Configuration retrieval
var updatedConfiguration: MachineConfiguration { get async }Types are designed to be thread-safe:
public struct VirtualizationData: Sendable { ... }
public protocol Machine: Sendable { ... }
public enum MachineState: Sendable { ... }Flexible implementations via associated types:
public protocol MachineSystem: Sendable {
associatedtype RestoreImageType: Sendable
func restoreImage(from: any InstallerImage) async throws -> RestoreImageType
}Abstracts different data sources:
package protocol VirtualizationDataSet {
func data(from name: KeyPath<any VirtualizationData.Paths, String>) throws -> Data
}
// Can be implemented by:
// - Filesystem directories
// - Network sources
// - In-memory data
// - Test fixturesCore types extended with features (following Swift conventions):
extension Machine {
func saveCaptureVideo(with closure: ...) async rethrows -> RecordedVideo
func deleteCapturedVideoWithID(_ id: UUID) async throws
}
extension MachineSystem {
func createBuilder(for configuration: MachineSetupConfiguration, ...) async throws -> any MachineBuilder
}The module dependency graph (top to bottom):
bushel (executable)
└── BushelArgs
└── [depends on various modules]
BushelCommand (executable)
└── BushelArgs
BushelFactory
├── BushelFoundation
├── BushelMachine
├── BushelLibrary
└── BushelLogging
BushelMachine
├── BushelFoundation
├── BushelDocs
└── BushelLogging
BushelLibrary
├── BushelLogging
├── BushelFoundation
├── BushelMacOSCore
└── RadiantKit (external)
BushelFoundation
├── BushelUtilities
├── OSVer (external)
└── RadiantKit (external)
BushelUtilities
└── OSVer (external)
BushelMacOSCore
└── [Foundation, macOS-specific]
Encapsulates core VM data that must persist:
public struct VirtualizationData: Sendable {
public let machineIdentifier: MachineIdentifier
public let hardwareModel: HardwareModel
}Complete VM specification:
struct MachineConfiguration {
let restoreImageFile: any InstallerImage identifier
let vmSystemID: VMSystemID
let snapshotSystemID: SnapshotterID
let operatingSystemVersion: OSVer
let buildVersion: String
let storage: [MachineStorageSpecification]
let cpuCount: Int
let memory: Int
}Manages collections of VM images:
public struct Library: Codable, Equatable, Sendable {
public var items: [LibraryImageFile]
}BushelKit has comprehensive test coverage organized by module:
- BushelFoundationTests - Core abstractions testing
- BushelMachineTests - VM state and lifecycle testing
- BushelLibraryTests - Library operations testing
- BushelFactoryTests - Factory and configuration testing
- BushelUtlitiesTests - Utility function testing
Tests use:
- Mock objects from BushelTestUtilities
- Protocol conformances for testing
- Async test support
The framework uses typed errors following Swift conventions:
VMSystemError- Virtual machine system errorsMachineError- Machine-specific errors with detailed contextLibraryError- Library operation errorsBuilderError- Machine building process errorsBookmarkError- File system bookmark errors
Errors include detailed context and recovery suggestions.
The framework abstracts platform differences:
- macOS - Primary target with full virtualization support
- iOS/watchOS/tvOS - Limited support (library operations only)
- Linux - Community support for core modules
Platform abstraction achieved through:
- Wax layers for platform-specific code
- Protocol-based platform implementations
- Conditional compilation where needed
- Async/Await Throughout - Non-blocking operations for long-running tasks (VM operations, image loading)
- Lazy Loading - Configuration and metadata loaded on-demand
- Snapshots - Efficient VM state snapshots for quick restore
- Sendable Types - Safe concurrent access without locks
- DocC Bundles - Each major module has associated DocC documentation
- Inline Documentation - Comprehensive doc comments on public APIs
- Tutorials - Planned tutorials for common workflows (roadmap shows v2.x releases will add these)
- Swift 6.0+ - Latest Swift features with strict concurrency checking
- Strict Compiler Flags - Various safety flags enabled in Package.swift
- Code Formatting - .swiftformat and .swiftlint configuration
- CI/CD - GitHub Actions workflows
The project uses GitHub Actions with multiple workflows:
-
BushelKit.yml - Main CI workflow
- Builds on Ubuntu (Swift 6.0, 6.1, 6.2, nightly builds)
- Builds on macOS (multiple Xcode versions, iOS, watchOS, visionOS simulators)
- Runs linting (calls
./Scripts/lint.sh) - Generates and uploads DocC documentation
- Uploads code coverage to Codecov
-
claude.yml - Claude Code integration workflow
- Triggers on issue comments, PR comments containing
@claude - Requires
CLAUDE_CODE_OAUTH_TOKENsecret - Allows the
claudebot to trigger workflows
- Triggers on issue comments, PR comments containing
-
claude-code-review.yml - Automated code review
-
codeql.yml - CodeQL security scanning
Important Notes:
- Commit messages containing
[skip ci]orci skipwill skip CI runs - Coverage is tracked per platform/Swift version with flags
- The main branch triggers documentation deployment to BushelDocs repository
BushelKit is a well-architected, modular framework following Swift best practices:
- Modular Design - Clear separation of concerns with independent, composable modules
- Protocol-Driven - Extensive use of protocols for flexibility and testability
- Async-First - Modern concurrent programming with async/await
- Type-Safe - Strong typing with enums, structs, and generics
- Platform-Aware - Abstractions for cross-platform support while enabling platform-specific optimizations
- Test-Focused - Comprehensive test coverage and mock infrastructure
- Well-Documented - DocC bundles and inline documentation
The framework is designed to be both a complete solution for Bushel's needs and a reusable library for developers building macOS VM applications.