Showing preview only (1,677K chars total). Download the full file or copy to clipboard to get everything.
Repository: insidegui/VirtualBuddy
Branch: main
Commit: 6a331eb4ef8c
Files: 410
Total size: 1.5 MB
Directory structure:
gitextract_fi8xynku/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── DeepLinkSecurity/
│ ├── DeepLinkSecurity.h
│ └── Source/
│ ├── Base/
│ │ └── DeepLinkSecurityDefines.swift
│ ├── DeepLinkSentinel.swift
│ ├── Models/
│ │ ├── DeepLinkClient.swift
│ │ ├── DeepLinkClientDescriptor.swift
│ │ ├── Extensions/
│ │ │ ├── DeepLinkClient+Crypto.swift
│ │ │ └── DeepLinkClientDescriptor+.swift
│ │ └── OpenDeepLinkRequest.swift
│ ├── Storage/
│ │ ├── DeepLinkAuthStore.swift
│ │ ├── DeepLinkManagementStore.swift
│ │ ├── KeychainDeepLinkAuthStore.swift
│ │ ├── MemoryDeepLinkAuthStore.swift
│ │ └── UserDefaultsDeepLinkManagementStore.swift
│ └── UI/
│ └── DeepLinkAuthUI.swift
├── LICENSE
├── README.md
├── ReleaseNotes/
│ ├── VirtualBuddy 1.2 Release Nodes.md
│ ├── VirtualBuddy 1.2.1 Release Notes.md
│ └── VirtualBuddy 1.2.2 Release Notes.md
├── VirtualBuddy/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Default.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Dev.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-zBeta.appiconset/
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Automation/
│ │ ├── DeepLinkHandler.swift
│ │ ├── Support/
│ │ │ └── DeepLinkAuthDialog.swift
│ │ └── VirtualBuddyDeepLinks.swift
│ ├── Bootstrap/
│ │ ├── SoftwareUpdateController.swift
│ │ ├── VirtualBuddyApp.swift
│ │ ├── VirtualBuddyAppDelegate.swift
│ │ └── VirtualBuddyEntryPoint.swift
│ ├── CommandLine/
│ │ ├── VirtualBuddyCLI.swift
│ │ └── vctool/
│ │ ├── BlurHashCommand.swift
│ │ ├── CatalogCommand.swift
│ │ ├── Core/
│ │ │ ├── BuildManifest+Fetch.swift
│ │ │ ├── BuildManifest.swift
│ │ │ ├── Helpers.swift
│ │ │ ├── TreeStringConvertible.swift
│ │ │ └── URL+ContentLength.swift
│ │ ├── GroupCommand.swift
│ │ ├── IPSWCommand.swift
│ │ ├── ImageCommand.swift
│ │ ├── MigrateCommand.swift
│ │ ├── MobileDeviceCommand.swift
│ │ ├── ResolveCommand.swift
│ │ └── VCTool.swift
│ ├── Config/
│ │ ├── AppTarget.xcconfig
│ │ ├── Entitlements/
│ │ │ ├── VirtualBuddy.entitlements
│ │ │ └── VirtualBuddy_Managed.entitlements
│ │ ├── Features.xcconfig
│ │ ├── InfoPlist.xcconfig
│ │ ├── Main.xcconfig
│ │ ├── Paths.xcconfig
│ │ ├── Signing.xcconfig
│ │ └── Versions.xcconfig
│ ├── Info.plist
│ └── Preview Content/
│ └── Preview Assets.xcassets/
│ └── Contents.json
├── VirtualBuddy.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm/
│ │ └── Package.resolved
│ └── xcshareddata/
│ ├── xcdebugger/
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes/
│ ├── DeepLinkSecurity.xcscheme
│ ├── VirtualBuddy (Dev Release).xcscheme
│ ├── VirtualBuddy (Managed - Beta).xcscheme
│ ├── VirtualBuddy (Managed).xcscheme
│ ├── VirtualBuddy.xcscheme
│ ├── VirtualBuddyGuest.xcscheme
│ ├── VirtualCore.xcscheme
│ ├── VirtualUI.xcscheme
│ ├── VirtualWormhole.xcscheme
│ └── vctool.xcscheme
├── VirtualBuddyGuest/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── StatusItem.imageset/
│ │ └── Contents.json
│ ├── Dashboard/
│ │ ├── GuestDashboard.swift
│ │ ├── GuestDefaultsImportView.swift
│ │ ├── GuestSharedFoldersManager.swift
│ │ ├── HostConnectionStateProvider.swift
│ │ └── Support/
│ │ ├── GuestLaunchAtLoginManager.swift
│ │ └── VirtualBuddyGuest-Bridging-Header.h
│ ├── GuestAppDelegate.swift
│ ├── GuestAppInstaller.swift
│ ├── Main.storyboard
│ ├── Preview Content/
│ │ └── Preview Assets.xcassets/
│ │ └── Contents.json
│ └── VirtualBuddyGuest.entitlements
├── VirtualBuddyGuestHelper/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj/
│ │ └── Main.storyboard
│ ├── GuestHelperAppDelegate.swift
│ └── VirtualBuddyGuestHelper.entitlements
├── VirtualCore/
│ ├── Source/
│ │ ├── Definitions/
│ │ │ ├── Logging.swift
│ │ │ ├── PreviewSupport.swift
│ │ │ └── VirtualCoreConstants.swift
│ │ ├── GuestSupport/
│ │ │ ├── CreateGuestImage.sh
│ │ │ └── GuestAdditionsDiskImage.swift
│ │ ├── Headers/
│ │ │ └── VirtualizationPrivate.h
│ │ ├── Import/
│ │ │ ├── UTM/
│ │ │ │ ├── UTMAppleConfiguration.swift
│ │ │ │ └── UTMImporter.swift
│ │ │ ├── VMImporter+Helpers.swift
│ │ │ ├── VMImporter.swift
│ │ │ └── VMImporterRegistry.swift
│ │ ├── Models/
│ │ │ ├── BlurHashToken.swift
│ │ │ ├── Configuration/
│ │ │ │ ├── ConfigurationModels+Summary.swift
│ │ │ │ ├── ConfigurationModels+Validation.swift
│ │ │ │ ├── ConfigurationModels.swift
│ │ │ │ ├── DecodableDefault.swift
│ │ │ │ └── VBMacDevice+Storage.swift
│ │ │ ├── SavedState/
│ │ │ │ ├── VBSavedStateMetadata+Clone.swift
│ │ │ │ ├── VBSavedStateMetadata.swift
│ │ │ │ ├── VBSavedStatePackage+VM.swift
│ │ │ │ ├── VBSavedStatePackage.swift
│ │ │ │ └── VMLibraryController+SavedState.swift
│ │ │ ├── VBError.swift
│ │ │ ├── VBNVRAMVariable.swift
│ │ │ ├── VBStorageDeviceContainer.swift
│ │ │ ├── VBVirtualMachine+Metadata.swift
│ │ │ ├── VBVirtualMachine+Screenshot.swift
│ │ │ └── VBVirtualMachine.swift
│ │ ├── ReleaseTrains/
│ │ │ ├── AppUpdateChannel.swift
│ │ │ └── VBBuildType.swift
│ │ ├── Resources/
│ │ │ ├── Preview/
│ │ │ │ ├── FakeRestoreImage.ipsw
│ │ │ │ ├── PreviewLinux.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ ├── Metadata.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewLinuxBlurHash.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewLinuxNoArtwork.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewMac.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ ├── Metadata.plist
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewMacBlurHash.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewMacNoArtwork.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewSavedStates/
│ │ │ │ │ ├── Save-2024-03-27_16;06;24.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ ├── Save-2024-03-27_16;07;04.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ ├── Save-2024-03-27_16;08;06.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ ├── Save-2024-03-27_16;08;28.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ └── Save-2024-03-27_16;08;51.vbst/
│ │ │ │ │ ├── Info.plist
│ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ └── Thumbnail.heic
│ │ │ │ └── _Downloads/
│ │ │ │ ├── UniversalMac_13.3.1_22E261_Restore.ipsw
│ │ │ │ ├── UniversalMac_14.0_23A344_Restore.ipsw
│ │ │ │ ├── UniversalMac_14.5_23F79_Restore.ipsw
│ │ │ │ ├── UniversalMac_15.3_24D60_Restore.ipsw
│ │ │ │ └── UniversalMac_15.5_24F74_Restore.ipsw
│ │ │ └── VirtualCore.xcassets/
│ │ │ ├── Adjectives.dataset/
│ │ │ │ ├── Adjectives.txt
│ │ │ │ └── Contents.json
│ │ │ ├── Animals.dataset/
│ │ │ │ ├── Animals.txt
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Restore/
│ │ │ ├── Download/
│ │ │ │ ├── DownloadBackend.swift
│ │ │ │ ├── SimulatedDownloadBackend.swift
│ │ │ │ └── URLSessionDownloadBackend.swift
│ │ │ └── Installation/
│ │ │ ├── RestoreBackend.swift
│ │ │ ├── SimulatedRestoreBackend.swift
│ │ │ └── VirtualizationRestoreBackend.swift
│ │ ├── Restore Images/
│ │ │ ├── Models/
│ │ │ │ ├── VBRestoreImageInfo.swift
│ │ │ │ └── VBRestoreImagesResponse.swift
│ │ │ └── VBAPIClient.swift
│ │ ├── Settings/
│ │ │ ├── VBSettings+CatalogDownload.swift
│ │ │ ├── VBSettings.swift
│ │ │ └── VBSettingsContainer.swift
│ │ ├── Utilities/
│ │ │ ├── Bundle+Version.swift
│ │ │ ├── LogStreamer.swift
│ │ │ ├── PreventTerminationAssertion.swift
│ │ │ ├── ProcessInfo+ECID.swift
│ │ │ ├── VBMemoryLeakDebugAssertions.swift
│ │ │ ├── VolumeUtils.swift
│ │ │ └── WeakReference.swift
│ │ ├── VirtualCatalog/
│ │ │ ├── LegacyCatalog.swift
│ │ │ ├── MobileDeviceFramework.swift
│ │ │ ├── README.md
│ │ │ ├── ResolvedCatalog.swift
│ │ │ ├── SoftwareCatalog+DownloadMatching.swift
│ │ │ ├── SoftwareCatalog.swift
│ │ │ └── Utilities/
│ │ │ ├── BlurHashEncode.swift
│ │ │ ├── String+AppleOSBuild.swift
│ │ │ └── URL+ExtendedAttributes.swift
│ │ └── Virtualization/
│ │ ├── Helpers/
│ │ │ ├── CatalogExtensions.swift
│ │ │ ├── DirectoryObserver.swift
│ │ │ ├── DiskImageGenerator.swift
│ │ │ ├── LinuxVirtualMachineConfigurationHelper.swift
│ │ │ ├── MacOSVirtualMachineConfigurationHelper.swift
│ │ │ ├── RandomNameGenerator.swift
│ │ │ ├── VBDebugUtil.h
│ │ │ ├── VBDebugUtil.m
│ │ │ ├── VZVirtualMachineConfiguration+NVRAM.swift
│ │ │ └── VirtualMachineConfigurationHelper.swift
│ │ ├── Screenshot/
│ │ │ ├── NSImage+DRMProtected.swift
│ │ │ └── NSImage+HEIC.swift
│ │ ├── VBVirtualMachine+Virtualization.swift
│ │ ├── VMController.swift
│ │ ├── VMInstance.swift
│ │ ├── VMLibraryController.swift
│ │ └── VMSavedStatesController.swift
│ └── VirtualCore.h
├── VirtualUI/
│ ├── Resources/
│ │ ├── CatalogGroupPlaceholder.heic
│ │ └── VirtualUI.xcassets/
│ │ ├── Contents.json
│ │ ├── FirstLaunchExperience.dataset/
│ │ │ ├── Contents.json
│ │ │ └── FirstLaunchExperience.caar
│ │ ├── FullBleedBlurHash.dataset/
│ │ │ ├── Contents.json
│ │ │ └── FullBleedBlurHash.caar
│ │ ├── GuestSymbol.imageset/
│ │ │ └── Contents.json
│ │ ├── StatusItemPanelChromeBorder.colorset/
│ │ │ └── Contents.json
│ │ ├── ThumbnailPlaceholder.imageset/
│ │ │ └── Contents.json
│ │ ├── VBGuestType/
│ │ │ ├── Contents.json
│ │ │ ├── linux.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── mac.imageset/
│ │ │ └── Contents.json
│ │ ├── VirtualBuddyMono.imageset/
│ │ │ └── Contents.json
│ │ ├── VirtualBuddyMonoHappy.imageset/
│ │ │ └── Contents.json
│ │ └── VirtualBuddyMonoSad.imageset/
│ │ └── Contents.json
│ ├── Source/
│ │ ├── Building Blocks/
│ │ │ ├── CGFloat+OnePixel.swift
│ │ │ ├── ChromeBorderModifier.swift
│ │ │ ├── Configuration Controls/
│ │ │ │ ├── EphemeralTextField.swift
│ │ │ │ ├── NumericPropertyControl.swift
│ │ │ │ ├── NumericValueField.swift
│ │ │ │ ├── PropertyControl.swift
│ │ │ │ └── SharedFocusEnvironment.swift
│ │ │ ├── ControlGroupChrome.swift
│ │ │ └── SliderConversion.swift
│ │ ├── Components/
│ │ │ ├── Array+Navigation.swift
│ │ │ ├── BackportedContentUnavailableView.swift
│ │ │ ├── BlurHash/
│ │ │ │ └── BlurHashDecoding.swift
│ │ │ ├── CALayer+Asset.swift
│ │ │ ├── DecentFormView.swift
│ │ │ ├── EqualWidthHStack.swift
│ │ │ ├── HostingWindowController/
│ │ │ │ ├── FB18383725Window.swift
│ │ │ │ ├── HostingWindowController.swift
│ │ │ │ ├── OpenCocoaWindowAction.swift
│ │ │ │ ├── VBRestorableWindow+Resizing.swift
│ │ │ │ ├── VBRestorableWindow.swift
│ │ │ │ └── WindowEnvironment.swift
│ │ │ ├── KeyboardNavigationModifier.swift
│ │ │ ├── LogConsole.swift
│ │ │ ├── MaterialView.swift
│ │ │ ├── NSAlert+Confirmation.swift
│ │ │ ├── OnAppearOnce.swift
│ │ │ ├── OpenSavePanelUtils.swift
│ │ │ ├── RemoteImage/
│ │ │ │ └── RemoteImage.swift
│ │ │ ├── SelfSizingGroupedForm.swift
│ │ │ ├── SwiftUI Status Item/
│ │ │ │ ├── Components/
│ │ │ │ │ ├── Cocoa/
│ │ │ │ │ │ ├── StatusBarContentPanel.swift
│ │ │ │ │ │ ├── StatusBarHighlightView.swift
│ │ │ │ │ │ ├── StatusItemMenuBarExtraView.swift
│ │ │ │ │ │ ├── StatusItemPanelContentController.swift
│ │ │ │ │ │ └── VUIAppKitViewControllerHost.swift
│ │ │ │ │ ├── ObjC/
│ │ │ │ │ │ ├── NSApplication+MenuBar.h
│ │ │ │ │ │ ├── NSApplication+MenuBar.m
│ │ │ │ │ │ ├── NSStatusBarPrivate.h
│ │ │ │ │ │ ├── NSStatusItem+.h
│ │ │ │ │ │ └── NSStatusItem+.m
│ │ │ │ │ ├── ScreenChangeModifier.swift
│ │ │ │ │ ├── StatusBarPanelChrome.swift
│ │ │ │ │ ├── StatusItemButton.swift
│ │ │ │ │ └── StatusItemProviderProtocol.swift
│ │ │ │ └── StatusItemManager.swift
│ │ │ └── VMArtworkView.swift
│ │ ├── Definitions/
│ │ │ ├── PreviewSupport-VirtualUI.swift
│ │ │ └── VirtualUIConstants.swift
│ │ ├── Installer/
│ │ │ ├── Components/
│ │ │ │ ├── AuthenticatingWebView.swift
│ │ │ │ ├── InstallationConsole.swift
│ │ │ │ ├── InstallationWizardTitle.swift
│ │ │ │ ├── RestoreImageURLInputView.swift
│ │ │ │ ├── VirtualBuddyInstallerInputView.swift
│ │ │ │ └── VirtualMachineNameInputView.swift
│ │ │ ├── Steps/
│ │ │ │ ├── GuestTypePicker.swift
│ │ │ │ ├── InstallConfigurationStepView.swift
│ │ │ │ ├── InstallMethod.swift
│ │ │ │ ├── InstallMethodPicker.swift
│ │ │ │ ├── InstallProgressStepView.swift
│ │ │ │ ├── Restore Image Selection/
│ │ │ │ │ ├── Components/
│ │ │ │ │ │ ├── BlurHashFullBleedBackground.swift
│ │ │ │ │ │ ├── CatalogGroupPicker.swift
│ │ │ │ │ │ ├── CatalogGroupView.swift
│ │ │ │ │ │ ├── InstallProgressDisplayView.swift
│ │ │ │ │ │ ├── RestoreImageBrowser.swift
│ │ │ │ │ │ ├── SoftwareCatalog+Placeholder.swift
│ │ │ │ │ │ ├── VirtualBuddyMonoIcon.swift
│ │ │ │ │ │ ├── VirtualBuddyMonoProgressView.swift
│ │ │ │ │ │ └── VirtualDisplayView.swift
│ │ │ │ │ ├── RestoreImageSelectionController.swift
│ │ │ │ │ └── RestoreImageSelectionStep.swift
│ │ │ │ └── RestoreImageDownloadView.swift
│ │ │ ├── VMInstallData.swift
│ │ │ ├── VMInstallationViewModel.swift
│ │ │ └── VMInstallationWizard.swift
│ │ ├── Library/
│ │ │ ├── Components/
│ │ │ │ ├── FirstLaunchExperienceView.swift
│ │ │ │ └── LibraryItemView.swift
│ │ │ └── LibraryView.swift
│ │ ├── Session/
│ │ │ ├── Components/
│ │ │ │ ├── ContinuousProgressIndicator.swift
│ │ │ │ ├── MaskProgressView.swift
│ │ │ │ ├── NumberDisplayMode.swift
│ │ │ │ ├── SavedStatePicker.swift
│ │ │ │ ├── SwiftUIVMView.swift
│ │ │ │ ├── VMProgressOverlay.swift
│ │ │ │ └── VirtualMachineControls.swift
│ │ │ ├── Configuration/
│ │ │ │ └── VMSessionConfigurationView.swift
│ │ │ ├── VirtualMachineSessionUI.swift
│ │ │ ├── VirtualMachineSessionUIManager.swift
│ │ │ └── VirtualMachineSessionView.swift
│ │ ├── Settings/
│ │ │ ├── AutomationSettingsView.swift
│ │ │ ├── Components/
│ │ │ │ ├── BackwardsCompatibility.swift
│ │ │ │ ├── FileSystemPathFormControl.swift
│ │ │ │ ├── OpenVirtualBuddySettingsAction.swift
│ │ │ │ ├── SettingsFooter.swift
│ │ │ │ └── VerticalLabeledContentStyle.swift
│ │ │ ├── GeneralSettingsView.swift
│ │ │ ├── SettingsScreen.swift
│ │ │ └── VirtualizationSettingsView.swift
│ │ └── VM Configuration/
│ │ ├── Components/
│ │ │ ├── ConfigurationSection.swift
│ │ │ └── GroupedList.swift
│ │ ├── Sections/
│ │ │ ├── DisplayConfigurationView.swift
│ │ │ ├── GuestAppConfigurationView.swift
│ │ │ ├── HardwareConfigurationView.swift
│ │ │ ├── KeyboardDeviceConfigurationView.swift
│ │ │ ├── NetworkConfigurationView.swift
│ │ │ ├── PointingDeviceConfigurationView.swift
│ │ │ ├── Sharing/
│ │ │ │ ├── SharedFolderListItem.swift
│ │ │ │ ├── SharedFoldersManagementView.swift
│ │ │ │ └── SharingConfigurationView.swift
│ │ │ ├── SoundConfigurationView.swift
│ │ │ └── Storage/
│ │ │ ├── ManagedDiskImageEditor.swift
│ │ │ ├── StorageConfigurationView.swift
│ │ │ └── StorageDeviceDetailView.swift
│ │ ├── VMConfigurationSheet.swift
│ │ ├── VMConfigurationView.swift
│ │ └── VMConfigurationViewModel.swift
│ └── VirtualUI.h
├── VirtualWormhole/
│ ├── Source/
│ │ ├── Definitions/
│ │ │ └── VirtualWormholeConstants.swift
│ │ ├── Services/
│ │ │ ├── Base/
│ │ │ │ ├── WormholeServiceClient.swift
│ │ │ │ └── WormholeServiceProtocol.swift
│ │ │ ├── DarwinNotifications/
│ │ │ │ ├── SystemNotification.swift
│ │ │ │ └── WHDarwinNotificationsService.swift
│ │ │ ├── DefaultsImport/
│ │ │ │ ├── Implementation/
│ │ │ │ │ ├── DefaultsDomain+ExportImport.swift
│ │ │ │ │ ├── DefaultsDomainDescriptor.swift
│ │ │ │ │ └── DefaultsImportController.swift
│ │ │ │ ├── Resources/
│ │ │ │ │ └── DefaultsDomains.plist
│ │ │ │ ├── WHDefaultsImportClient.swift
│ │ │ │ └── WHDefaultsImportService.swift
│ │ │ ├── DesktopPicture/
│ │ │ │ ├── CGImage+FullyTransparent.swift
│ │ │ │ ├── NSImage+DesktopPicture.h
│ │ │ │ ├── NSImage+DesktopPicture.m
│ │ │ │ └── WHDesktopPictureService.swift
│ │ │ └── WHSharedClipboardService.swift
│ │ ├── WireProtocol/
│ │ │ ├── WHPayload.swift
│ │ │ ├── WHPing.swift
│ │ │ └── WormholePacket.swift
│ │ └── WormholeManager.swift
│ └── VirtualWormhole.h
├── VirtualWormholeTests/
│ └── WormholePacketTests.swift
└── data/
├── images/
│ ├── debian-dark-thumbnail.heic
│ ├── debian-dark.heic
│ ├── debian-thumbnail.heic
│ ├── debian.heic
│ ├── fedora-dark-thumbnail.heic
│ ├── fedora-dark.heic
│ ├── fedora-thumbnail.heic
│ ├── fedora.heic
│ ├── jammyjellyfish-dark-thumbnail.heic
│ ├── jammyjellyfish-dark.heic
│ ├── jammyjellyfish-thumbnail.heic
│ ├── jammyjellyfish.heic
│ ├── kali-dark-thumbnail.heic
│ ├── kali-dark.heic
│ ├── kali-thumbnail.heic
│ ├── kali.heic
│ ├── monterey-dark-thumbnail.heic
│ ├── monterey-dark.heic
│ ├── monterey-thumbnail.heic
│ ├── monterey.heic
│ ├── sequoia-dark-thumbnail.heic
│ ├── sequoia-dark.heic
│ ├── sequoia-thumbnail.heic
│ ├── sequoia.heic
│ ├── sonoma-dark-thumbnail.heic
│ ├── sonoma-dark.heic
│ ├── sonoma-thumbnail.heic
│ ├── sonoma.heic
│ ├── tahoe-dark-thumbnail.heic
│ ├── tahoe-dark.heic
│ ├── tahoe-thumbnail.heic
│ ├── tahoe.heic
│ ├── ventura-dark-thumbnail.heic
│ ├── ventura-dark.heic
│ ├── ventura-thumbnail.heic
│ └── ventura.heic
├── ipsws_v1.json
├── ipsws_v2.json
├── linux_v1.json
└── linux_v2.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
github: insidegui
================================================
FILE: .gitignore
================================================
.DS_Store
__MACOSX
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
Crashlytics.sh
generatechangelog.sh
Pods/
Carthage
Provisioning
Crashlytics.sh
Sharing.h
Tests/Private
Design/Icon
Build/
MockServer/
================================================
FILE: DeepLinkSecurity/DeepLinkSecurity.h
================================================
//
// DeepLinkSecurity.h
// DeepLinkSecurity
//
// Created by Guilherme Rambo on 12/10/23.
//
#import <Foundation/Foundation.h>
//! Project version number for DeepLinkSecurity.
FOUNDATION_EXPORT double DeepLinkSecurityVersionNumber;
//! Project version string for DeepLinkSecurity.
FOUNDATION_EXPORT const unsigned char DeepLinkSecurityVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <DeepLinkSecurity/PublicHeader.h>
================================================
FILE: DeepLinkSecurity/Source/Base/DeepLinkSecurityDefines.swift
================================================
import Foundation
import OSLog
struct DeepLinkSecurityDefines {
static let subsystem = "codes.rambo.DeepLinkSecurity"
}
struct DeepLinkError: LocalizedError {
var errorDescription: String?
init(_ errorDescription: String) {
self.errorDescription = errorDescription
}
}
extension Logger {
static func deepLinkLogger<T>(for type: T.Type) -> Logger {
Logger(subsystem: DeepLinkSecurityDefines.subsystem, category: String(describing: type))
}
}
================================================
FILE: DeepLinkSecurity/Source/DeepLinkSentinel.swift
================================================
import Cocoa
import OSLog
public final class DeepLinkSentinel: ObservableObject {
private lazy var logger = Logger.deepLinkLogger(for: Self.self)
public let authUI: DeepLinkAuthUI
public let authStore: DeepLinkAuthStore
public let managementStore: DeepLinkManagementStore
public init(authUI: DeepLinkAuthUI, authStore: DeepLinkAuthStore, managementStore: DeepLinkManagementStore) {
self.authUI = authUI
self.authStore = authStore
self.managementStore = managementStore
}
/// Sets the sentinel as the handler for URL scheme Apple Events.
public func installAppleEventHandler() {
NSAppleEventManager.shared().setEventHandler(
self,
andSelector: #selector(DeepLinkSentinel.handleURLEvent(_:replyEvent:)),
forEventClass: AEEventClass(kInternetEventClass),
andEventID: AEEventID(kAEGetURL)
)
}
/// Delivers open URL events once they've been authenticated.
/// Open URL requests that fail authentication are not delivered.
public private(set) lazy var openURL: AsyncStream<URL> = {
AsyncStream { [weak self] continuation in
self?.onOpenURL = { url in
continuation.yield(url)
}
}
}()
private var onOpenURL: (URL) -> Void = { _ in }
@objc func handleURLEvent(_ event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
logger.debug(#function)
guard let urlStr = event.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))?.stringValue else {
logger.fault("Failed to get string from URL open event")
return
}
logger.debug("Handling URL \(urlStr)")
guard let tokenDescriptor = event.attributeDescriptor(forKeyword: AEKeyword(keySenderAuditTokenAttr))?.copy() as? NSAppleEventDescriptor else {
logger.error("Missing Apple Event sender audit token in URL event")
return
}
guard let url = URL(string: urlStr) else {
logger.error("Invalid deep link URL: \"\(urlStr)\"")
return
}
Task {
await authenticate(descriptor: tokenDescriptor, url: url)
}
}
func storeDescriptor(_ descriptor: DeepLinkClientDescriptor, with authorization: DeepLinkClientAuthorization = .undetermined) async {
do {
var updatedDescriptor = descriptor
updatedDescriptor.authorization = authorization
try await managementStore.insert(updatedDescriptor)
} catch {
logger.warning("Failed to store management descriptor: \(error, privacy: .public)")
}
}
func setAuthorization(_ result: DeepLinkClientAuthorization, for client: DeepLinkClient, descriptor: DeepLinkClientDescriptor) async {
do {
try await authStore.setAuthorization(result, for: client)
/// Update the client management descriptor with the new authorization.
await storeDescriptor(descriptor, with: result)
} catch {
logger.warning("Failed to store authorization decision: \(error, privacy: .public)")
}
}
public func setAuthorization(_ result: DeepLinkClientAuthorization, for descriptor: DeepLinkClientDescriptor) async throws {
let client = try DeepLinkClient(url: descriptor.url)
try await authStore.setAuthorization(result, for: client)
/// Update the client management descriptor with the new authorization.
await storeDescriptor(descriptor, with: result)
}
private func authenticate(descriptor: NSAppleEventDescriptor, url: URL) async {
do {
let client = try DeepLinkClient(auditTokenDescriptor: descriptor)
let clientDescriptor = DeepLinkClientDescriptor(client: client)
do {
/// Store an initial entry for the client descriptor if it doesn't exist yet.
let descriptorExists = await managementStore.hasDescriptor(with: clientDescriptor.id)
if !descriptorExists {
try await managementStore.insert(clientDescriptor)
}
} catch {
logger.warning("Failed to store management descriptor before auth: \(error, privacy: .public)")
}
let request = OpenDeepLinkRequest(url: url, client: clientDescriptor)
do {
var authorization = await existingAuthorization(for: client)
switch authorization {
case .undetermined:
logger.debug("No existing authorization for \(client.designatedRequirement), prompting")
authorization = try await authUI.presentDeepLinkAuth(for: request)
guard authorization != .undetermined else {
logger.warning("Auth UI ended with undetermined authorization, denying current request without modifying auth store")
return
}
await setAuthorization(authorization, for: client, descriptor: clientDescriptor)
case .authorized:
logger.debug("Got existing client authorization for \(client.designatedRequirement)")
case .denied:
logger.warning("Denying open URL: client authorization denied for \(client.designatedRequirement)")
return
}
/// Just being extra paranoid here.
guard authorization != .denied else { return }
logger.notice("Successfully authenticated deep link request for opening \(url)")
await MainActor.run {
onOpenURL(url)
}
} catch {
logger.error("Deep link authentication failed: \(error, privacy: .public)")
}
} catch {
logger.error("Failed to get client information: \(error, privacy: .public)")
}
}
private func existingAuthorization(for client: DeepLinkClient) async -> DeepLinkClientAuthorization {
let auth = await authStore.authorization(for: client)
guard auth == .authorized else { return auth }
do {
try await client.validate()
return .authorized
} catch {
logger.warning("Client signature validated for \(client.designatedRequirement), prompting again. Error: \(error, privacy: .public)")
return .undetermined
}
}
}
extension NSAppleEventDescriptor: @retroactive @unchecked Sendable { }
================================================
FILE: DeepLinkSecurity/Source/Models/DeepLinkClient.swift
================================================
import Foundation
import CryptoKit
/// Represents an app/process that's attempting to open a deep link in the app.
public struct DeepLinkClient: Identifiable {
/// The client ID is a SHA256 hash of its designated CS requirement.
public var id: String
/// The bundle URL for the app or executable URL for the process.
public var url: URL
/// The designated code signing requirement for the client.
/// This is hashed and used as a key to store the user's decision,
/// and it's also used in order to verify that the client's code signature is valid.
public var designatedRequirement: String
public init(url: URL, designatedRequirement: String) {
self.url = url
self.designatedRequirement = designatedRequirement
self.id = SHA256.hash(data: Data(designatedRequirement.utf8))
.map { String(format: "%02X", $0) }
.joined()
}
}
================================================
FILE: DeepLinkSecurity/Source/Models/DeepLinkClientDescriptor.swift
================================================
import Cocoa
/// Describes metadata for a client that's previously requested deep link authorization.
/// See ``DeepLinkManagementStore``.
public struct DeepLinkClientDescriptor: Identifiable, Hashable, Codable {
public struct Icon: Hashable, Codable {
public var image: NSImage
}
/// Unique identifier for the client.
public var id: String
/// The client's main bundle or executable URL.
public var url: URL
/// The client's bundle identifier, if available.
public var bundleIdentifier: String?
/// A user-friendly name for the client.
public var displayName: String
/// Icon image representing the client app or executable.
public var icon: Icon
/// The current authorization state for the client.
public var authorization: DeepLinkClientAuthorization
/// Will be `false` if the descriptor's client could no longer be found on the filesystem.
public var isValid: Bool
}
================================================
FILE: DeepLinkSecurity/Source/Models/Extensions/DeepLinkClient+Crypto.swift
================================================
import Cocoa
public extension DeepLinkClient {
init(auditTokenDescriptor: NSAppleEventDescriptor) throws {
let attrs = [kSecGuestAttributeAudit: auditTokenDescriptor.data]
var client: SecCode!
try checkSecError(SecCodeCopyGuestWithAttributes(nil, attrs as CFDictionary, .default, &client), task: "copy client cs attributes")
var staticCode: SecStaticCode!
try checkSecError(SecCodeCopyStaticCode(client, .default, &staticCode), task: "copy client static code")
var url: CFURL!
try checkSecError(SecCodeCopyPath(staticCode, .default, &url), task: "copy client path")
var requirement: SecRequirement!
try checkSecError(SecCodeCopyDesignatedRequirement(staticCode, .default, &requirement), task: "copy client designated requirement")
var requirementText: CFString!
try checkSecError(SecRequirementCopyString(requirement, .default, &requirementText), task: "copy client designated requirement text")
self.init(url: url as URL, designatedRequirement: requirementText as String)
}
init(url: URL) throws {
var staticCode: SecStaticCode!
try checkSecError(SecStaticCodeCreateWithPath(url as CFURL, .default, &staticCode), task: "load client static code")
var requirement: SecRequirement!
try checkSecError(SecCodeCopyDesignatedRequirement(staticCode, .default, &requirement), task: "copy client designated requirement")
var requirementText: CFString!
try checkSecError(SecRequirementCopyString(requirement, .default, &requirementText), task: "copy client designated requirement text")
self.init(url: url, designatedRequirement: requirementText as String)
}
/// Validates the client's static code against the designated requirement,
/// throwing an error if the signature doesn't match.
func validate() async throws {
var requirement: SecRequirement!
try checkSecError(SecRequirementCreateWithString(designatedRequirement as CFString, .default, &requirement), task: "create client designated requirement")
var staticCode: SecStaticCode!
try checkSecError(SecStaticCodeCreateWithPath(url as CFURL, .default, &staticCode), task: "load client static code")
var errors: Unmanaged<CFError>?
guard SecStaticCodeCheckValidityWithErrors(staticCode, .default, requirement, &errors) == noErr else {
let errorMessage = errors?.takeUnretainedValue().localizedDescription ?? "Unknown error"
throw DeepLinkError("Client code signature validation failed with: \(errorMessage)")
}
}
}
private func checkSecError(_ closure: @autoclosure () -> OSStatus, task: String) throws {
let err = closure()
guard err != noErr else { return }
let msg = SecCopyErrorMessageString(err, nil) as String?
throw DeepLinkError("Failed to \(task). Error code \(err): \(msg ?? "<unknown>")")
}
extension SecCSFlags {
static let `default` = SecCSFlags([])
}
================================================
FILE: DeepLinkSecurity/Source/Models/Extensions/DeepLinkClientDescriptor+.swift
================================================
import Cocoa
public extension DeepLinkClientDescriptor {
init(client: DeepLinkClient, authorization: DeepLinkClientAuthorization = .undetermined) {
self.init(clientID: client.id, clientURL: client.url, authorization: authorization)
}
init(clientID: DeepLinkClient.ID, clientURL: URL, authorization: DeepLinkClientAuthorization = .undetermined) {
let bundle = Bundle(url: clientURL)
self.init(
id: clientID,
url: clientURL,
bundleIdentifier: bundle.flatMap(\.bundleIdentifier),
displayName: bundle.flatMap(\.bestEffortAppName) ?? clientURL.fileNameWithoutExtension,
icon: Icon(clientURL: clientURL),
authorization: authorization,
isValid: FileManager.default.fileExists(atPath: clientURL.path)
)
}
/// Checks if the descriptor's client is still present at its original filesystem location,
/// attempting to update the client if it's been moved or deleted.
func resolved() -> DeepLinkClientDescriptor {
guard let bundleIdentifier else { return self }
guard !FileManager.default.fileExists(atPath: url.path) else { return self }
guard let updatedURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) else { return self.invalidated() }
return DeepLinkClientDescriptor(clientID: id, clientURL: updatedURL, authorization: authorization)
}
func invalidated() -> DeepLinkClientDescriptor {
var mSelf = self
mSelf.isValid = false
return mSelf
}
func withAuthorization(_ authorization: DeepLinkClientAuthorization) -> DeepLinkClientDescriptor {
var mSelf = self
mSelf.authorization = authorization
return mSelf
}
}
public extension DeepLinkClientDescriptor.Icon {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let data = try container.decode(Data.self)
let image = NSImage(data: data) ?? NSWorkspace.shared.icon(for: .application)
self.init(image: image)
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
guard let png = image.pngData() else {
throw EncodingError.invalidValue(0, .init(codingPath: [], debugDescription: "Failed to get icon PNG data"))
}
try container.encode(png)
}
}
private extension DeepLinkClientDescriptor.Icon {
init(clientURL: URL) {
let image: NSImage
if FileManager.default.fileExists(atPath: clientURL.path) {
image = NSWorkspace.shared.icon(forFile: clientURL.path)
} else {
image = NSWorkspace.shared.icon(for: .application)
}
image.size = NSSize(width: 64, height: 64)
self.init(image: image)
}
}
private extension NSImage {
func pngData() -> Data? {
guard let cgImage = cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil }
let rep = NSBitmapImageRep(cgImage: cgImage)
guard let png = rep.representation(using: .png, properties: [:]) else { return nil }
return png
}
}
private extension Bundle {
var bestEffortAppName: String? {
guard let info = infoDictionary else { return bundleURL.fileNameWithoutExtension }
return info["CFBundleDisplayName"] as? String ?? info["CFBundleName"] as? String ?? bundleURL.fileNameWithoutExtension
}
}
private extension URL {
var fileNameWithoutExtension: String { deletingPathExtension().lastPathComponent }
}
================================================
FILE: DeepLinkSecurity/Source/Models/OpenDeepLinkRequest.swift
================================================
import Foundation
/// Represents a client's request for opening a deep link in the app.
public struct OpenDeepLinkRequest {
/// The URL for the deep link the client is trying to open.
public var url: URL
/// The client model used for authentication.
public var client: DeepLinkClientDescriptor
public init(url: URL, client: DeepLinkClientDescriptor) {
self.url = url
self.client = client
}
}
================================================
FILE: DeepLinkSecurity/Source/Storage/DeepLinkAuthStore.swift
================================================
import Cocoa
/// Describes a user's decision about a client opening deep links in the app.
public enum DeepLinkClientAuthorization: Int, Codable, CustomStringConvertible {
/// The user has not granted/rejected the client yet.
/// Also used as a fallback when something goes wrong in the process of
/// authenticating a previously authorized/denied client.
case undetermined
/// The user has granted authorization to the client.
case authorized
/// The user has denied authorization for the client.
case denied
}
public extension DeepLinkClientAuthorization {
var description: String {
switch self {
case .undetermined:
return "undetermined"
case .authorized:
return "authorized"
case .denied:
return "denied"
}
}
}
/// Implemented by types that can provide persistence for user's decision regarding the opening of deep links from other apps.
/// See ``MemoryDeepLinkAuthStore`` and ``KeychainDeepLinkAuthStore``.
public protocol DeepLinkAuthStore {
func authorization(for client: DeepLinkClient) async -> DeepLinkClientAuthorization
func setAuthorization(_ authorization: DeepLinkClientAuthorization, for client: DeepLinkClient) async throws
}
================================================
FILE: DeepLinkSecurity/Source/Storage/DeepLinkManagementStore.swift
================================================
import Foundation
/// Implemented by types that can provide persistence for a list of authorized/denied deep link clients,
/// so that a UI can be assembled showing the user their previous decisions and allowing users to change their mind.
public protocol DeepLinkManagementStore {
/// Returns deep link client descriptors previously added using ``insert(_:)``.
var currentClientDescriptors: [DeepLinkClientDescriptor] { get }
/// Streams deep link client descriptors previously added using ``insert(_:)`` as they're updated.
func clientDescriptors() -> AsyncStream<[DeepLinkClientDescriptor]>
/// Whether the store currently has a descriptor with the specified identifier.
func hasDescriptor(with id: DeepLinkClientDescriptor.ID) async -> Bool
/// Upserts a client descriptor.
func insert(_ descriptor: DeepLinkClientDescriptor) async throws
/// Deletes an existing descriptor.
func delete(_ descriptor: DeepLinkClientDescriptor) async throws
}
================================================
FILE: DeepLinkSecurity/Source/Storage/KeychainDeepLinkAuthStore.swift
================================================
import Foundation
import Security
import OSLog
import CryptoKit
/// A robust auth store that uses signed keychain items for storing the user's authorization decisions.
public final actor KeychainDeepLinkAuthStore: DeepLinkAuthStore {
private lazy var logger = Logger.deepLinkLogger(for: Self.self)
private let namespace: String
private let keyID: String
public init(namespace: String, keyID: String) {
self.namespace = namespace
self.keyID = keyID
}
private let encoder = PropertyListEncoder()
private let decoder = PropertyListDecoder()
public func authorization(for client: DeepLinkClient) async -> DeepLinkClientAuthorization {
do {
guard let authData = try readKeychainItem(id: client.id) else {
return .undetermined
}
do {
/// Fetch the existing response item from the keychain.
let response = try decoder.decode(KeychainAuthorizationResponse.self, from: authData)
do {
/// The mere existence of the response in the keychain doesn't automatically mean the decision should be honored.
/// When written to the keychain, responses are signed with a private key.
/// When read from the keychain, the app verifies the stored signature against the corresponding public key,
/// ensuring that this response was written by an app that has permission to access this app's private key item from the keychain.
/// If another app attempts to write fake permissions to the keychain, they'll only be valid if the app can also sign the responses using our private key,
/// but in order to do that, the app would need the user's permission to access our keychain item, which triggers a permission prompt on macOS.
try validate(response: response)
logger.debug("Validated authorization response")
return response.authorization
} catch {
logger.error("Failed to validate authorization response: \(error, privacy: .public)")
throw error
}
} catch {
logger.fault("Error decoding authorization from Keychain entry: \(error, privacy: .public)")
throw error
}
} catch {
return .undetermined
}
}
public func setAuthorization(_ authorization: DeepLinkClientAuthorization, for client: DeepLinkClient) async throws {
let clientID = client.id
let signingKey = try fetchSigningKey()
let payload = KeychainAuthorizationResponse.signingPayload(clientID: clientID, authorization: authorization)
let signature = try signingKey.sign(payload)
let response = KeychainAuthorizationResponse(
authorization: authorization,
clientID: clientID,
signingKeyID: keyID,
signature: signature
)
guard let authData = try? encoder.encode(response) else {
throw DeepLinkError("Failed to encode authorization")
}
try writeKeychainItem(id: clientID, data: authData)
logger.debug("Stored authorization \(authorization) for \(client.designatedRequirement) (id = \(clientID, privacy: .public))")
}
private func validate(response: KeychainAuthorizationResponse) throws {
let key = try fetchSigningKey()
guard try key.verify(response.signature, for: response.signingPayload) else {
throw DeepLinkError("Invalid authorization signature for client \(response.clientID)")
}
}
private func fetchSigningKey() throws -> KeychainAuthorizationSigningKey {
func createNewKey() throws -> KeychainAuthorizationSigningKey {
logger.debug("Creating new authorization signing key")
let newKey = KeychainAuthorizationSigningKey(id: keyID)
let keyData = try encoder.encode(newKey)
try writeKeychainItem(id: keyID, data: keyData)
return newKey
}
if let data = try readKeychainItem(id: keyID) {
logger.debug("Found existing authorization signing key")
do {
let key = try decoder.decode(KeychainAuthorizationSigningKey.self, from: data)
return key
} catch {
logger.fault("Error reading existing authorization signing key, will generate new one. \(error, privacy: .public)")
return try createNewKey()
}
} else {
return try createNewKey()
}
}
/// Simple helper for reading an item's data from the keychain.
private func readKeychainItem(id: String) throws -> Data? {
let query = [
kSecClass: kSecClassGenericPassword,
kSecReturnData: true,
kSecMatchLimit: kSecMatchLimitOne,
kSecAttrService: namespace as CFString,
kSecAttrAccount: id as CFString
] as [CFString: Any] as CFDictionary
var result: CFTypeRef?
let res = SecItemCopyMatching(query, &result)
guard res != errSecItemNotFound else { return nil }
try check(res)
guard let data = result as? Data else {
throw DeepLinkError("Failed to cast security query result to data")
}
return data
}
/// Simple helper for writing an item to the keychain.
private func writeKeychainItem(id: String, data: Data) throws {
let query = [
kSecClass: kSecClassGenericPassword,
kSecAttrService: namespace as CFString,
kSecAttrAccount: id as CFString
] as [CFString: Any]
var attrs = query
attrs[kSecValueData] = data as CFData
var result: CFTypeRef?
var res = SecItemAdd(attrs as CFDictionary, &result)
if res == errSecDuplicateItem {
logger.debug("Keychain item \(id) already exists, updating")
res = SecItemUpdate(query as CFDictionary, [kSecValueData: data as CFData] as CFDictionary)
}
try check(res)
}
/// Simple helper for removing an item from the keychain.
private func deleteKeychainItem(id: String) throws {
let query = [
kSecClass: kSecClassGenericPassword,
kSecMatchLimit: kSecMatchLimitOne,
kSecAttrService: namespace as CFString,
kSecAttrAccount: id as CFString
] as [CFString: Any] as CFDictionary
let res = SecItemDelete(query)
guard res != errSecItemNotFound else { return }
try check(res)
}
}
/// This is the payload that's stored as the value for a keychain item representing the user's decision
/// regarding an app's permission to open deep links within this app.
private struct KeychainAuthorizationResponse: Codable {
/// The user's decision (allow/deny).
var authorization: DeepLinkClientAuthorization
/// The SHA256 hash of the designated CS requirement for the app the decision is for.
var clientID: String
/// The identifier for the key used to generate the ECDSA signature.
var signingKeyID: String
/// The ECDSA signature for the payload, which is composed of the client ID and the user's decision.
var signature: Data
}
private extension KeychainAuthorizationResponse {
/// The payload that gets signed when storing the response on the keychain.
var signingPayload: Data { Self.signingPayload(clientID: clientID, authorization: authorization) }
static func signingPayload(clientID: String, authorization: DeepLinkClientAuthorization) -> Data {
Data("\(clientID)-\(authorization.rawValue)".utf8)
}
}
// MARK: - Crypto
private struct KeychainAuthorizationSigningKey: Codable {
var id: String
var keyData: Data
}
private extension KeychainAuthorizationSigningKey {
init(id: String = UUID().uuidString) {
let key = P521.Signing.PrivateKey()
self.init(id: id, keyData: key.rawRepresentation)
}
}
private extension KeychainAuthorizationSigningKey {
var privateKey: P521.Signing.PrivateKey {
get throws {
try P521.Signing.PrivateKey(rawRepresentation: keyData)
}
}
var publicKey: P521.Signing.PublicKey {
get throws {
try privateKey.publicKey
}
}
}
private extension KeychainAuthorizationSigningKey {
func sign(_ digest: some DataProtocol) throws -> Data {
try privateKey.signature(for: digest).rawRepresentation
}
func verify(_ signature: Data, for digest: some DataProtocol) throws -> Bool {
let signature = try P521.Signing.ECDSASignature(rawRepresentation: signature)
return try publicKey.isValidSignature(signature, for: digest)
}
}
// MARK: - Helpers
private func check(_ res: OSStatus) throws {
guard res != errSecSuccess else { return }
if let str = SecCopyErrorMessageString(res, nil) {
throw DeepLinkError("Security error code \(res): \"\(str)\"")
} else {
throw DeepLinkError("Security error code \(res)")
}
}
================================================
FILE: DeepLinkSecurity/Source/Storage/MemoryDeepLinkAuthStore.swift
================================================
import Foundation
import OSLog
/// A very basic store that uses an in-memory dictionary and is destroyed when the app terminates. Useful for testing.
public final actor MemoryDeepLinkAuthStore: DeepLinkAuthStore {
private lazy var logger = Logger.deepLinkLogger(for: Self.self)
private var authorizationByClientRequirement = [String: DeepLinkClientAuthorization]()
public init() { }
public func authorization(for client: DeepLinkClient) async -> DeepLinkClientAuthorization {
if let result = authorizationByClientRequirement[client.designatedRequirement] {
logger.debug("Found existing authorization \(result) for \(client.designatedRequirement)")
return result
} else {
logger.debug("No authorization in store for \(client.designatedRequirement), returning undetermined")
return .undetermined
}
}
public func setAuthorization(_ authorization: DeepLinkClientAuthorization, for client: DeepLinkClient) async throws {
logger.debug("Setting authorization \(authorization) for \(client.designatedRequirement)")
authorizationByClientRequirement[client.designatedRequirement] = authorization
}
}
================================================
FILE: DeepLinkSecurity/Source/Storage/UserDefaultsDeepLinkManagementStore.swift
================================================
import Foundation
import OSLog
/// A management store that persists client descriptors in `UserDefaults`.
public final actor UserDefaultsDeepLinkManagementStore: DeepLinkManagementStore {
private let logger = Logger.deepLinkLogger(for: UserDefaultsDeepLinkManagementStore.self)
private let defaults: UserDefaults
private let storageKey: String
public init(namespace: String = "DeepLinkSecurity", suiteName: String? = nil, inMemory: Bool = false) {
self.storageKey = "\(namespace)-Management"
if let suiteName {
if let instance = UserDefaults(suiteName: suiteName) {
self.defaults = instance
} else {
assertionFailure("Failed to initialize user defaults with suite name \"\(suiteName)\"")
self.defaults = .standard
}
} else if inMemory {
self.defaults = UserDefaults()
} else {
self.defaults = .standard
}
Task {
let existingDescriptors = readDescriptors()
await cacheDescriptors(existingDescriptors)
}
}
public func hasDescriptor(with id: DeepLinkClientDescriptor.ID) -> Bool { cachedDescriptors[id] != nil }
public nonisolated var currentClientDescriptors: [DeepLinkClientDescriptor] {
Self.descriptorsArray(from: readDescriptors())
}
public nonisolated func clientDescriptors() -> AsyncStream<[DeepLinkClientDescriptor]> {
let stream = AsyncStream { [weak self] continuation in
guard let self = self else { return }
Task {
await self.onStoreChanged { descriptorsByID in
let descriptors = Self.descriptorsArray(from: descriptorsByID)
continuation.yield(descriptors)
}
}
}
Task {
let snapshot = readDescriptors()
await storeChangeHandler(snapshot)
}
return stream
}
private static func descriptorsArray(from descriptorsByID: [DeepLinkClientDescriptor.ID: DeepLinkClientDescriptor]) -> [DeepLinkClientDescriptor] {
descriptorsByID
.values
.map { $0.resolved() }
.sorted(by: { $0.displayName.localizedStandardCompare($1.displayName) == .orderedAscending })
}
public func insert(_ descriptor: DeepLinkClientDescriptor) async throws {
await update(id: descriptor.id, with: descriptor)
cacheDescriptors(readDescriptors())
}
public func delete(_ descriptor: DeepLinkClientDescriptor) async throws {
await update(id: descriptor.id, with: nil)
cacheDescriptors(readDescriptors())
}
private var cachedDescriptors = DescriptorStorage()
private var storeChangeHandler: (DescriptorStorage) async -> Void = { _ in }
private func onStoreChanged(perform block: @escaping (DescriptorStorage) async -> Void) {
storeChangeHandler = block
}
private func cacheDescriptors(_ descriptors: DescriptorStorage) {
self.cachedDescriptors = descriptors
}
private func update(id: DeepLinkClientDescriptor.ID, with descriptor: DeepLinkClientDescriptor?) async {
do {
var snapshot = readDescriptors()
snapshot[id] = descriptor
let data = try encoder.encode(snapshot)
defaults.set(data, forKey: storageKey)
defaults.synchronize()
if let descriptor {
logger.debug("Inserted descriptor \(descriptor.id, privacy: .public)")
} else {
logger.debug("Deleted descriptor \(id, privacy: .public)")
}
await storeChangeHandler(snapshot)
} catch {
logger.error("Failed to insert descriptor: \(error, privacy: .public)")
}
}
private typealias DescriptorStorage = [DeepLinkClientDescriptor.ID: DeepLinkClientDescriptor]
nonisolated private func readDescriptors() -> DescriptorStorage {
logger.debug(#function)
guard let data = defaults.data(forKey: storageKey) else {
logger.debug("No data for \(self.storageKey)")
return [:]
}
do {
let descriptorsByID = try decoder.decode(DescriptorStorage.self, from: data)
logger.debug("Fetched \(descriptorsByID.count, privacy: .public) client descriptor(s)")
return descriptorsByID
} catch {
logger.error("Failed to decode management store data: \(error, privacy: .public)")
return [:]
}
}
private let encoder = PropertyListEncoder()
private let decoder = PropertyListDecoder()
}
extension UserDefaults: @retroactive @unchecked Sendable { }
================================================
FILE: DeepLinkSecurity/Source/UI/DeepLinkAuthUI.swift
================================================
import SwiftUI
public protocol DeepLinkAuthUI: AnyObject {
/// Return ``DeepLinkClientAuthorization/authorized`` if the user has allowed the client to open deep links in the app.
///
/// If this method throws, then the auth store is not modified and the user will be prompted again the next time the same client
/// attempts to open a deep link in the app.
///
/// If this method returns ``DeepLinkClientAuthorization/denied``, then the auth store will be modified and future
/// requests from the same client will be rejected without a prompt.
@MainActor
func presentDeepLinkAuth(for request: OpenDeepLinkRequest) async throws -> DeepLinkClientAuthorization
}
================================================
FILE: LICENSE
================================================
Copyright (c) 2022 Guilherme Rambo
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.md
================================================
<img src="./assets/VirtualBuddyIcon.png" width="128" />
# VirtualBuddy
VirtualBuddy can virtualize macOS 12 and later on Apple Silicon, with the goal of offering features that are useful to developers who need to test their apps on multiple versions of macOS, especially betas.

## System Requirements
- **Apple Silicon Mac**
- macOS 13 or later
### Installing macOS
To install a macOS virtual machine, you can select from a list of macOS versions provided by VirtualBuddy, which will automatically download and install the selected version. You may also provide your own IPSW link or select from an IPSW you have already downloaded.
### Installing macOS Betas
If you’d like to run a virtual machine with a macOS beta that’s more recent than the one you’re currently running, such as a macOS 15 virtual machine running in a macOS 14 host, then you’ll need the latest device support package from Apple.
Device support packages are sometimes made available by Apple directly, but they’re always included and installed automatically with the latest Xcode beta. These can be obtained from the [Apple Developer portal](https://developer.apple.com/download).

## Download
VirtualBuddy is free and open-source. If you’d like to support its development, [you may purchase it on Gumroad](https://insidegui.gumroad.com/l/virtualbuddy) or [sponsor my work on GitHub](https://github.com/sponsors/insidegui).
If you’d just like to download the latest version, [go to GitHub releases](https://github.com/insidegui/VirtualBuddy/releases/latest).
### Feature Checklist
- [x] Ability to boot any version of macOS 12 or macOS 13, including betas
- [x] Ability to boot some ARM-based Linux distros (tested with Ubuntu Server and Ubuntu Desktop)
- [x] Built-in installation wizard
- [x] Select from a collection of restore images available on Apple’s servers
- [x] Install the latest stable version of macOS
- [x] Local restore image IPSW file
- [x] Custom restore image URL
- [x] Install a Linux distro from a local .iso file
- [x] Select from a collection of Linux distros
- [x] Install Linux from URL
- [x] Boot into recovery mode (in order to disable SIP, for example)
- [x] Networking and file sharing support
- [x] Clipboard sharing
- [x] Customize virtual machine hardware configuration
- [x] Save and restore macOS virtual machine state
### Tips and Tricks
#### VirtualBuddyGuest app
VirtualBuddy automatically mounts a disk image with the VirtualBuddyGuest app when you boot up a virtual machine running macOS. To install the VirtualBuddyGuest app, just select the “Guest” disk on Finder’s side bar then double-click the “VirtualBuddyGuest” app icon.
VirtualBuddyGuest enables clipboard sharing between host and guest and automatic mounting of the shared folders configured for the virtual machine.

#### Taking Advantage of APFS
Sometimes when trying things out in the OS installed in one of the virtual machines, things might break, requiring a full install of the guest operating system again, which is a pain.
Thanks to APFS cloning though, you can just duplicate a virtual machine within your library folder (using Command + D in Finder), and the copy will take almost no additional disk space. This way you can have a “clean” copy of your VM, do whatever you want with a duplicate of it, and then throw the copy away and re-duplicate the clean version if things break.
#### Sharing Folders Between Host and Virtual Machine
You can share folders from your Mac to the Virtual Machine and vice-versa using regular macOS file sharing that can be configured in System Preferences/Settings.
When both the Virtual Machine and the host are running macOS 13 or later, it’s possible to share folders directly by configuring them in the VM settings within VirtualBuddy before booting up the VM.
To mount shared folders in the VM, run the following command in the VM’s Terminal:
```bash
mkdir -p ~/Desktop/VirtualBuddyShared && mount -t virtiofs VirtualBuddyShared ~/Desktop/VirtualBuddyShared
```
## Building
**Xcode 16** is required for building on `main`.
- Open the `VirtualBuddy/Config/Signing.xcconfig` file
- Set the `VB_BUNDLE_ID_PREFIX` variable to something unique like `com.yourname.`
- Select the VirtualBuddy project in the Xcode sidebar
- Under "Targets", select "VirtualBuddy"
- Go to the Signing & Capabilities tab and select your development team under Signing > Team
- Repeat the same process for the "VirtualBuddyGuest" target
- Build the `VirtualBuddy` scheme (the one that **doesn't** have `(Managed)` in its name)
================================================
FILE: ReleaseNotes/VirtualBuddy 1.2 Release Nodes.md
================================================
# What's new in VirtualBuddy 1.2
- Managing virtual machines can now be done entirely within the library view, the contextual menu offers options for renaming, deleting, duplicating, and showing the VM in Finder
- The library now sorts virtual machines by creation date, in reverse chronological order
- Virtual machines can now be configured with custom CPU, RAM, storage devices, network devices, displays, and many other options
- The option to capture system keyboard shortcuts is now persisted for each virtual machine in the library
- Adds support for shared folders to share specific directories from your Mac with the virtual machine
- Adds support for bridged networking, allowing a physical network interface from your Mac to be exposed to the virtual machine
- Additional storage can now be added to virtual machines by creating new disk images from within VirtualBuddy
- A new debug console showing logs related to the installation process is now available while installing macOS in a new virtual machine
- The default library directory for new installs is now ~/Library/Application Support/VirtualBuddy (this is where VirtualBuddy stores virtual machines and downloads)
- Clicking a virtual machine that's already open in the library will now correctly focus the existing window for that virtual machine
================================================
FILE: ReleaseNotes/VirtualBuddy 1.2.1 Release Notes.md
================================================
# New in VirtualBuddy 1.2.1
### General improvements to the installer user interface:
- Addresses an issue that caused the installer to clip the configuration user interface, hiding the "continue" button
- It is now possible to navigate using the arrow keys when selecting the installation method
- Text fields now use the same consistent style
- The virtual machine name button is automatically focused as expected
- Command + R can be used to generate a new random name while editing the virtual machine's name during installation
================================================
FILE: ReleaseNotes/VirtualBuddy 1.2.2 Release Notes.md
================================================
# Fixed in VirtualBuddy 1.2.2
- Makes custom IPSW URL validation less strict, allowing downloads from plain HTTP URLs and URLs that don't end in .ipsw
- Addresses an issue that caused audio input to not work in virtual machines; VirtualBuddy will ask for microphone access the first time audio input is used within a virtual machine
================================================
FILE: VirtualBuddy/Assets.xcassets/AccentColor.colorset/Contents.json
================================================
{
"colors" : [
{
"color" : {
"platform" : "universal",
"reference" : "systemOrangeColor"
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: VirtualBuddy/Assets.xcassets/AppIcon-Default.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "icon_16x16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "icon_16x16@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "icon_32x32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "icon_32x32@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "icon_128x128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "icon_128x128@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "icon_256x256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "icon_256x256@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "icon_512x512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "icon_512x512@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: VirtualBuddy/Assets.xcassets/AppIcon-Dev.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "icon_16x16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "icon_16x16@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "icon_32x32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "icon_32x32@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "icon_128x128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "icon_128x128@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "icon_256x256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "icon_256x256@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "icon_512x512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "icon_512x512@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: VirtualBuddy/Assets.xcassets/AppIcon-zBeta.appiconset/Contents.json
================================================
{
"images" : [
{
"filename" : "icon_16x16.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"filename" : "icon_16x16@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"filename" : "icon_32x32.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"filename" : "icon_32x32@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"filename" : "icon_128x128.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"filename" : "icon_128x128@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"filename" : "icon_256x256.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"filename" : "icon_256x256@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "icon_512x512.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "icon_512x512@2x@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: VirtualBuddy/Assets.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: VirtualBuddy/Automation/DeepLinkHandler.swift
================================================
import SwiftUI
import VirtualCore
import VirtualUI
import OSLog
import DeepLinkSecurity
typealias WindowUpdatingClosure = (_ perform: () -> Void) -> Void
final class DeepLinkHandler {
private let settingsContainer: VBSettingsContainer
private let updateController: SoftwareUpdateController
private let library: VMLibraryController
private let sessionManager: VirtualMachineSessionUIManager
let runner: ActionRunner
static var shared: DeepLinkHandler {
guard let _shared else {
fatalError("Attempting to access DeepLinkHandler instance before calling bootstrap()")
}
return _shared
}
private static var _shared: DeepLinkHandler!
@MainActor
static func bootstrap(library: VMLibraryController) {
DeepLinkHandler._shared = DeepLinkHandler(library: library)
DeepLinkHandler.shared.install()
}
@MainActor
private init(library: VMLibraryController) {
self.settingsContainer = VBSettingsContainer.current
self.updateController = SoftwareUpdateController.shared
self.library = library
self.sessionManager = VirtualMachineSessionUIManager.shared
self.runner = ActionRunner(
settingsContainer: settingsContainer,
updateController: updateController,
library: library,
sessionManager: sessionManager
)
}
private lazy var logger = Logger(subsystem: kShellAppSubsystem, category: String(describing: Self.self))
private let namespace = "VirtualBuddy"
private let keyID = "c3bfea24ee1ca95700a4e56d73097aac"
private(set) lazy var sentinel = DeepLinkSentinel(
authUI: DeepLinkAuthUIPresenter(),
authStore: KeychainDeepLinkAuthStore(namespace: namespace, keyID: keyID),
managementStore: UserDefaultsDeepLinkManagementStore()
)
func actions() -> AsyncCompactMapSequence<AsyncStream<URL>, DeepLinkAction> {
sentinel.openURL.compactMap { url in
do {
let action = try DeepLinkAction(url)
self.logger.debug("Action: \(String(describing: action))")
return action
} catch {
self.logger.error("Error processing deep link URL \"\(url)\": \(error, privacy: .public)")
return nil
}
}
}
func install() {
sentinel.installAppleEventHandler()
Task {
for await action in DeepLinkHandler.shared.actions() {
await runner.run(action)
}
}
}
@MainActor
final class ActionRunner {
private let settingsContainer: VBSettingsContainer
private let updateController: SoftwareUpdateController
private let library: VMLibraryController
private let sessionManager: VirtualMachineSessionUIManager
private let openWindow = OpenCocoaWindowAction.default
init(settingsContainer: VBSettingsContainer,
updateController: SoftwareUpdateController,
library: VMLibraryController,
sessionManager: VirtualMachineSessionUIManager)
{
self.settingsContainer = settingsContainer
self.updateController = updateController
self.library = library
self.sessionManager = sessionManager
}
func run(_ action: DeepLinkAction) async {
do {
switch action {
case .open(let params):
try openVM(named: params.name, options: nil)
case .boot(let params):
var effectiveOptions = params.options ?? VMSessionOptions.default
effectiveOptions.autoBoot = true
try openVM(named: params.name, options: effectiveOptions)
case .stop(let params):
try await stopVM(named: params.name)
}
} catch {
let alert = NSAlert(error: error)
alert.runModal()
}
}
func openVM(named name: String, options: VMSessionOptions?) throws {
let vm = try getVM(named: name)
sessionManager.launch(vm, library: library, options: options)
}
func stopVM(named name: String) async throws {
let controller = try getController(forVMNamed: name)
switch controller.state {
case .idle, .stopped:
throw Failure("Can't stop virtual machine \(name.wrappedInSmartQuotes) because it's not running.")
default:
try await controller.stop()
}
}
func getVM(named name: String) throws -> VBVirtualMachine {
guard let vm = library.virtualMachine(named: name) else {
throw Failure("Couldn't find a virtual machine with the name \(name.wrappedInSmartQuotes).")
}
return vm
}
func getController(forVMNamed name: String) throws -> VMController {
let vm = try getVM(named: name)
guard let controller = library.activeController(for: vm.id) else {
throw Failure("Couldn't find active instance of virtual machine with the name \(name.wrappedInSmartQuotes).")
}
return controller
}
}
}
private final class DeepLinkAuthUIPresenter: DeepLinkAuthUI {
func presentDeepLinkAuth(for request: OpenDeepLinkRequest) async throws -> DeepLinkClientAuthorization {
try await DeepLinkAuthPanel.run(for: request)
}
}
extension String {
var wrappedInSmartQuotes: String { "“\(self)”" }
}
================================================
FILE: VirtualBuddy/Automation/Support/DeepLinkAuthDialog.swift
================================================
import SwiftUI
import DeepLinkSecurity
final class DeepLinkAuthPanel: NSPanel {
private static var panelInstances = NSHashTable<NSPanel>(options: [.strongMemory, .objectPointerPersonality])
@MainActor
static func run(for request: OpenDeepLinkRequest) async throws -> DeepLinkClientAuthorization {
try await withCheckedThrowingContinuation { continuation in
let panel = DeepLinkAuthPanel(request: request) { panelInstance, decision in
defer { panelInstances.remove(panelInstance) }
continuation.resume(returning: decision)
panelInstance.close()
}
panelInstances.add(panel)
panel.makeKeyAndOrderFront(nil)
panel.center()
}
}
private init(request: OpenDeepLinkRequest, completion: @escaping (DeepLinkAuthPanel, DeepLinkClientAuthorization) -> Void) {
super.init(contentRect: .zero, styleMask: [.borderless, .titled, .fullSizeContentView], backing: .buffered, defer: false)
titleVisibility = .hidden
titlebarAppearsTransparent = true
animationBehavior = .alertPanel
let dialog = DeepLinkAuthDialog(request: request) { [weak self] granted in
guard let self = self else { return }
completion(self, granted ? .authorized : .denied)
}
contentViewController = NSHostingController(rootView: dialog)
}
override var canBecomeKey: Bool { true }
override var canBecomeMain: Bool { true }
}
struct DeepLinkAuthDialog: View {
var request: OpenDeepLinkRequest
var response: (Bool) -> Void
private var appName: String
private var appIcon: Image
init(request: OpenDeepLinkRequest, response: @escaping (Bool) -> Void) {
self.request = request
self.response = response
self.appName = request.client.displayName
self.appIcon = Image(nsImage: request.client.icon.image)
}
private var iconContainerSize: CGFloat { 58 }
private var handIconSizeMultiplier: CGFloat { 0.5 }
private var appIconSizeMultiplier: CGFloat { 0.432 }
var body: some View {
VStack(spacing: 22) {
ZStack {
RoundedRectangle(cornerRadius: 16, style: .continuous)
.fill(LinearGradient(colors: [.cyan, .blue], startPoint: .top, endPoint: .bottom))
.frame(width: iconContainerSize, height: iconContainerSize)
Image(systemName: "hand.raised.fill")
.foregroundStyle(Color.white)
.imageScale(.large)
.font(.system(size: iconContainerSize * handIconSizeMultiplier, weight: .medium, design: .rounded))
.shadow(color: .black.opacity(0.3), radius: 1, x: 0.5, y: 0.5)
}
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
.shadow(color: .black.opacity(0.3), radius: 1, x: 0, y: 1)
.overlay(alignment: .bottomTrailing) {
appIcon
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: iconContainerSize * appIconSizeMultiplier, height: iconContainerSize * appIconSizeMultiplier)
.offset(x: 8, y: 8)
}
Text("\"\(appName)\" would like to access and control your virtual machines in VirtualBuddy.")
.lineLimit(nil)
.font(.headline)
.multilineTextAlignment(.center)
.fixedSize(horizontal: false, vertical: true)
Spacer()
HStack {
Button(role: .cancel) {
response(false)
} label: {
Text("Don't Allow")
.frame(maxWidth: .infinity)
}
.keyboardShortcut(.cancelAction)
Button {
response(true)
} label: {
Text("Allow")
.frame(maxWidth: .infinity)
}
.keyboardShortcut(.defaultAction)
}
.controlSize(.large)
.frame(maxWidth: .infinity)
}
.padding()
.frame(minWidth: 260, minHeight: 230)
}
}
#if DEBUG
extension DeepLinkClient {
static let preview = DeepLinkClient(
url: URL(fileURLWithPath: "/System/Applications/Notes.app"),
designatedRequirement: "identifier \"com.apple.Notes\" and anchor apple"
)
}
extension DeepLinkClientDescriptor {
static let preview = DeepLinkClientDescriptor(client: .preview)
}
extension OpenDeepLinkRequest {
static let preview = OpenDeepLinkRequest(url: URL(string: "x-test-link-auth://test1")!, client: .preview)
}
#Preview {
DeepLinkAuthDialog(request: .preview) { response in
print("Response: \(response)")
}
.frame(width: 320)
}
#endif
================================================
FILE: VirtualBuddy/Automation/VirtualBuddyDeepLinks.swift
================================================
import Foundation
import URLQueryItemCoder
import DeepLinkSecurity
import OSLog
import VirtualCore
struct OpenVMParameters: Codable {
var name: String
}
struct BootVMParameters: Codable {
var name: String
var options: VMSessionOptions?
}
struct StopVMParameters: Codable {
var name: String
}
enum DeepLinkAction {
case open(OpenVMParameters)
case boot(BootVMParameters)
case stop(StopVMParameters)
}
extension DeepLinkAction {
init(_ url: URL) throws {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
throw Failure("Invalid URL: failed to construct URLComponents")
}
guard let host = components.host else {
throw Failure("Invalid URL: missing host")
}
switch host {
case "open":
let params = try Self.decodeParameters(OpenVMParameters.self, from: components)
self = .open(params)
case "boot":
let params = try Self.decodeParameters(BootVMParameters.self, from: components)
self = .boot(params)
case "stop":
let params = try Self.decodeParameters(StopVMParameters.self, from: components)
self = .stop(params)
default:
throw Failure("Unrecognized URL action \"\(host)\"")
}
}
private static func decodeParameters<T>(_ type: T.Type, from components: URLComponents) throws -> T where T: Decodable {
let items = components.queryItems ?? []
return try URLQueryItemDecoder.deepLink.decode(type, from: items)
}
}
private extension URLQueryItemDecoder {
static let deepLink = URLQueryItemDecoder()
}
================================================
FILE: VirtualBuddy/Bootstrap/SoftwareUpdateController.swift
================================================
//
// SoftwareUpdateController.swift
// VirtualBuddy
//
// Created by Guilherme Rambo on 25/06/22.
//
import SwiftUI
import VirtualCore
import OSLog
#if ENABLE_SPARKLE
import Sparkle
#endif
final class SoftwareUpdateController: NSObject, ObservableObject {
private let logger = Logger(subsystem: kShellAppSubsystem, category: "SoftwareUpdateController")
static let shared = SoftwareUpdateController()
private var settings: VBSettings { VBSettingsContainer.current.settings }
@Published var automaticUpdatesEnabled = true {
didSet {
#if ENABLE_SPARKLE
guard automaticUpdatesEnabled != oldValue else { return }
logger.debug("Setting \(#function, privacy: .public) to \(self.automaticUpdatesEnabled, privacy: .public)")
updateController.updater.automaticallyChecksForUpdates = automaticUpdatesEnabled
#endif
}
}
var automaticUpdatesBinding: Binding<Bool> {
Binding { [self] in
automaticUpdatesEnabled
} set: { [self] newValue in
automaticUpdatesEnabled = newValue
}
}
#if ENABLE_SPARKLE
private lazy var updateController: SPUStandardUpdaterController = {
SPUStandardUpdaterController(
startingUpdater: false,
updaterDelegate: self,
userDriverDelegate: self
)
}()
#endif
func activate() {
#if ENABLE_SPARKLE
logger.debug(#function)
updateController.startUpdater()
automaticUpdatesEnabled = updateController.updater.automaticallyChecksForUpdates
registerForUpdateChannelChanges()
#endif
}
@objc func checkForUpdates(_ sender: Any?) {
#if ENABLE_SPARKLE
logger.debug(#function)
updateController.checkForUpdates(sender)
#else
let alert = NSAlert()
alert.messageText = "Updating Disabled"
alert.informativeText = "This build doesn't include Sparkle updates."
alert.runModal()
#endif
}
private func registerForUpdateChannelChanges() {
NotificationCenter.default.addObserver(
self,
selector: #selector(handleUpdateChannelChanged),
name: VBSettings.updateChannelDidChangeNotification,
object: nil
)
}
/// Check for updates when switching from release to beta channel.
@objc private func handleUpdateChannelChanged(_ note: Notification) {
guard let channel = note.object as? AppUpdateChannel else { return }
guard channel != .release else { return }
checkForUpdates(nil)
}
}
#if ENABLE_SPARKLE
extension SoftwareUpdateController: SPUUpdaterDelegate, SPUStandardUserDriverDelegate {
func feedURLString(for updater: SPUUpdater) -> String? {
settings.updateChannel.appCastURL.absoluteString
}
func allowedChannels(for updater: SPUUpdater) -> Set<String> {
[settings.updateChannel.id]
}
}
#endif
================================================
FILE: VirtualBuddy/Bootstrap/VirtualBuddyApp.swift
================================================
//
// VirtualBuddyApp.swift
// VirtualBuddy
//
// Created by Guilherme Rambo on 07/04/22.
//
import SwiftUI
import VirtualCore
import VirtualUI
let kShellAppSubsystem = "codes.rambo.VirtualBuddy"
struct VirtualBuddyApp: App {
@NSApplicationDelegateAdaptor
var appDelegate: VirtualBuddyAppDelegate
private var settingsContainer: VBSettingsContainer { appDelegate.settingsContainer }
private var updateController: SoftwareUpdateController { appDelegate.updateController }
private var library: VMLibraryController { appDelegate.library }
private var sessionManager: VirtualMachineSessionUIManager { appDelegate.sessionManager }
@Environment(\.openWindow)
private var openWindow
@StateObject private var updatesController = SoftwareUpdateController.shared
private let mainWindowTitle: String = Bundle.main.vbFullVersionDescription
var body: some Scene {
Window(Text(mainWindowTitle), id: .vb_libraryWindowID) {
LibraryView()
.onAppearOnce(perform: updateController.activate)
.environmentObject(library)
.environmentObject(sessionManager)
.handlesExternalEvents(preferring: ["*"], allowing: ["*"])
.onOpenURL { url in
UILog("OPEN URL \(url.path(percentEncoded: false))")
sessionManager.open(fileURL: url, library: library)
}
.environment(\.openVirtualBuddySettings, appDelegate.openSettingsAction)
.background { TransparentWindowTitleBarView() }
}
.windowToolbarStyle(.unified)
.commands {
#if ENABLE_SPARKLE
CommandGroup(after: .appInfo) {
Button("Check for Updates…") {
updateController.checkForUpdates(nil)
}
}
#endif
CommandGroup(replacing: .appSettings) {
Button("Settings…") {
appDelegate.openSettingsAction()
}
.keyboardShortcut(",", modifiers: .command)
}
CommandGroup(before: .windowSize) {
VirtualMachineWindowCommands()
.environmentObject(sessionManager)
}
CommandGroup(after: .windowArrangement) {
Button("Library") {
openWindow(id: .vb_libraryWindowID)
}
.keyboardShortcut(KeyEquivalent("0"), modifiers: .command)
}
}
.handlesExternalEvents(matching: ["*"])
}
}
// TODO: Remove this after moving to AppKit lifecycle
private struct TransparentWindowTitleBarView: NSViewRepresentable {
typealias NSViewType = _MakeWindowTitleBarTransparentView
func makeNSView(context: Context) -> _MakeWindowTitleBarTransparentView {
_MakeWindowTitleBarTransparentView(frame: .zero)
}
func updateNSView(_ nsView: _MakeWindowTitleBarTransparentView, context: Context) {
}
final class _MakeWindowTitleBarTransparentView: NSView {
override func viewDidMoveToWindow() {
super.viewDidMoveToWindow()
window?.titlebarAppearsTransparent = true
}
}
}
================================================
FILE: VirtualBuddy/Bootstrap/VirtualBuddyAppDelegate.swift
================================================
//
// VirtualBuddyNSApp.swift
// VirtualBuddy
//
// Created by Guilherme Rambo on 07/04/22.
//
import Cocoa
@_exported import VirtualCore
@_exported import VirtualUI
import VirtualWormhole
import DeepLinkSecurity
import OSLog
import Combine
import SwiftUI
#if BUILDING_NON_MANAGED_RELEASE
#error("Trying to build for release without using the managed scheme. This build won't include managed entitlements. This error is here for Rambo, you may safely comment it out and keep going.")
#endif
@MainActor
@objc final class VirtualBuddyAppDelegate: NSObject, NSApplicationDelegate {
private let logger = Logger(for: VirtualBuddyAppDelegate.self)
let settingsContainer = VBSettingsContainer.current
let updateController = SoftwareUpdateController.shared
let library = VMLibraryController()
let sessionManager = VirtualMachineSessionUIManager.shared
func applicationWillFinishLaunching(_ notification: Notification) {
DeepLinkHandler.bootstrap(library: library)
NSApp?.appearance = NSAppearance(named: .darkAqua)
}
private var cancellables = Set<AnyCancellable>()
func applicationDidFinishLaunching(_ notification: Notification) {
GuestAdditionsDiskImage.current.$state.sink { state in
switch state {
case .ready:
self.logger.debug("Guest disk image ready")
case .installing:
self.logger.debug("Guest disk image installing")
case .installFailed(let error):
self.logger.debug("Guest disk image installation failed - \(error, privacy: .public)")
}
}
.store(in: &cancellables)
Task {
try? await GuestAdditionsDiskImage.current.installIfNeeded()
}
#if DEBUG
runLaunchDebugTasks()
#endif
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { false }
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
if let firstValidAssertion = sender.assertionsPreventingAppTermination.first {
logger.debug("Preventing app termination due to active assertions: \(sender.assertionsPreventingAppTermination.map(\.reason).formatted(.list(type: .and)), privacy: .public)")
let reply: NSApplication.TerminateReply
if let assertionReply = firstValidAssertion.handleShouldTerminate() {
logger.debug("Assertion handles should terminate, returning its reply \(assertionReply)")
reply = assertionReply
} else {
logger.debug("Assertion doesn't handle should terminate, performing default handling")
let alert = NSAlert()
alert.messageText = "Quit VirtualBuddy?"
alert.informativeText = "VirtualBuddy is currently \(firstValidAssertion.reason). This will be cancelled if you quit the app."
let button = alert.addButton(withTitle: "Quit")
button.hasDestructiveAction = true
let button2 = alert.addButton(withTitle: "Quit When Done")
button2.keyEquivalent = "\r"
alert.addButton(withTitle: "Cancel")
let response = alert.runModal()
reply = switch response {
case .alertFirstButtonReturn: .terminateNow
case .alertSecondButtonReturn: .terminateLater
default: .terminateCancel
}
}
switch reply {
case .terminateCancel:
logger.info("User cancelled termination request. Good.")
case .terminateNow:
logger.info("User decided to terminate now despite assertions :(")
case .terminateLater:
logger.info("User wants app to terminate when assertions preventing termination are invalidated.")
/// Note that there's no point in resetting this to `false` in any other case because once `.terminateLater`
/// has been returned from this method, any attempt to terminate the app will no longer trigger it.
sender.shouldTerminateWhenLastAssertionInvalidated = true
@unknown default:
logger.fault("Unknown terminate reply \(reply, privacy: .public)")
}
return reply
} else {
return .terminateNow
}
}
private var settingsWindow: NSWindow?
private(set) lazy var openSettingsAction = OpenVirtualBuddySettingsAction { [weak self] in
self?.openSettingsWindow()
}
private func openSettingsWindow() {
if let settingsWindow {
logger.debug("Settings window already available, showing")
settingsWindow.makeKeyAndOrderFront(self)
return
}
let rootView = SettingsScreen(
enableAutomaticUpdates: updateController.automaticUpdatesBinding,
deepLinkSentinel: DeepLinkHandler.shared.sentinel
)
.environmentObject(settingsContainer)
let window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: SettingsScreen.width, height: SettingsScreen.minHeight),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView, .unifiedTitleAndToolbar],
backing: .buffered,
defer: false
)
window.isReleasedWhenClosed = false
window.contentViewController = NSHostingController(rootView: rootView)
window.makeKeyAndOrderFront(self)
window.center()
self.settingsWindow = window
}
}
extension NSWindow {
/// At least as of macOS 14.4, a SwiftUI window's `identifier` matches the `id` that's set in SwiftUI.
var isVirtualBuddyLibraryWindow: Bool { identifier?.rawValue == .vb_libraryWindowID }
}
#if DEBUG
// MARK: - Debugging Helpers
private extension VirtualBuddyAppDelegate {
func runLaunchDebugTasks() {
RunLoop.main.perform { [self] in
MainActor.assumeIsolated {
VirtualMachineSessionUIManager.shared.testImportVMIfEnabled(library: library)
}
}
}
}
#endif
================================================
FILE: VirtualBuddy/Bootstrap/VirtualBuddyEntryPoint.swift
================================================
import SwiftUI
import VirtualCore
import VirtualUI
import BuddyFoundation
/**
Main entry point for the VirtualBuddy app and all supported command-line tools.
Command-line tools are implemented using ArgumentParser and declared in ``VirtualBuddyCLI``.
The app target symlinks the VirtualBuddy app executable with the names of each supported command-line tool
as part of a run script build phase.
This entry point uses ``VirtualBuddyCLI`` to check if the current executable name matches that of a supported command-line tool.
If that's the case, ``VirtualBuddyCLI`` will invoke the tool's implementation and skip running the app itself.
*/
@main
struct VirtualBuddyEntryPoint {
static func main() async throws {
let name: String
#if DEBUG
/**
`VB_TOOL` environment variable can be used to test command-line tools when running from within Xcode,
where it is inconvenient to deal with running the symlinked variants.
Each tool should have an aggregate target set up in the project that has this environment variable set.
*/
if let overrideName = ProcessInfo.processInfo.environment["VB_TOOL"] {
name = overrideName
} else {
name = ProcessInfo.processInfo.processName
}
#else
name = ProcessInfo.processInfo.processName
#endif
/// Only attempt to process commands if the executable name doesn't match the name in the app bundle.
guard name != Bundle.main.executableName else {
return VirtualBuddyApp.main()
}
await VirtualBuddyCLI.runCommand(named: name)
VirtualBuddyApp.main()
}
}
private extension Bundle {
/**
For the purposes of checking whether the user is running the VirtualBuddy app or a command-line tool,
the actual bundle executable declared in the `Info.plist` must be compared against the process name.
The `Bundle.executableURL` property will return the URL of the actual executable symlink instead of the one declared.
*/
var executableName: String { infoDictionary?["CFBundleExecutable"] as? String ?? "VirtualBuddy" }
}
================================================
FILE: VirtualBuddy/CommandLine/VirtualBuddyCLI.swift
================================================
import Foundation
import ArgumentParser
/**
Declares supported `ParsableCommand`s that VirtualBuddy provides.
Commands are implemented in the main app binary, but the app's entry point checks the process name
in order to determine whether a command-line tool should be run instead of the app itself.
*/
struct VirtualBuddyCLI {
static let supportedEntryPoints: [ParsableCommand.Type] = [
VCTool.self,
]
static func runCommand(named name: String) async {
guard let command = supportedEntryPoints.first(where: { $0.configuration.commandName == name }) else {
return
}
/// Remove any arguments injected by Xcode (such as `-NSDocumentRevisionsDebugMode`).
/// Also remove first argument, which is the name of the command itself.
let sanitizedArguments: [String] = CommandLine.arguments
.suffix(from: 1)
.filter { !$0.hasPrefix("-NS") && $0 != "YES" && $0 != "NO" }
if let asyncCommand = command as? AsyncParsableCommand.Type {
await asyncCommand.main(sanitizedArguments)
} else {
command.main(sanitizedArguments)
}
/**
For non-async commands, we have to exit explicitly if the command didn't do it for us,
otherwise this function will return and the app could end up running from the command-line.
Placed at the end here just in case the behavior changes for async commands in the future.
**/
exit(0)
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/BlurHashCommand.swift
================================================
import Foundation
import ArgumentParser
import VirtualCore
import VirtualUI
import BuddyFoundation
struct BlurHashCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "blurhash",
abstract: "Encodes or decodes blur hashes.",
subcommands: [
BlurHashEncodeCommand.self,
BlurHashDecodeCommand.self,
]
)
}
private struct BlurHashEncodeCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "encode",
abstract: "Encodes an image into a blur hash."
)
@Argument(help: "Path to input image.")
var input: String
@Option(name: .shortAndLong, help: "Number of blur hash components.")
var components: Int = 4
@Option(name: .shortAndLong, help: "Size of thumbnail used to generate the blur hash.")
var size: Int = 128
@Option(name: .shortAndLong, help: "HEIC compression quality of thumbnail used to generate the blur hash.")
var quality: Double = 0.6
func run() async throws {
let inputURL = try URL(fileURLWithPath: (input as NSString).expandingTildeInPath)
.ensureExistingFile()
let blurHashComponents: (Int, Int) = (Int(CGSize.vbBlurHashSize.width), Int(CGSize.vbBlurHashSize.height))
let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent("\(UUID()).heic")
try inputURL.vctool_encodeHEIC(to: tempURL, maxSize: size, quality: quality)
let image = try NSImage(contentsOf: tempURL)
.require("Error loading input image.")
let blurHash = try image.blurHash(numberOfComponents: blurHashComponents)
.require("Error generating blur hash.")
try? FileManager.default.removeItem(at: tempURL)
print(blurHash)
}
}
private struct BlurHashDecodeCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "decode",
abstract: "Decodes a blur hash into an image."
)
@Argument(help: "Blur hash string.")
var input: String
@Option(name: .shortAndLong, help: "Path to output image file.", completion: .file())
var output: String
@Option(name: .shortAndLong, help: "Number of blur hash components.")
var components: Int = 4
@Option(name: .shortAndLong, help: "The punch parameter for the blur hash.")
var punch: Float = 1.0
func run() async throws {
let image = try NSImage(blurHash: input, size: CGSize(width: components, height: components), punch: punch)
.require("Error decoding blur hash into image.")
try image.vb_encodeHEIC(to: output.resolvedURL, options: [
kCGImageDestinationLossyCompressionQuality: 1,
kCGImageDestinationImageMaxPixelSize: components
] as CFDictionary)
print("✅ Blur hash image saved to \(output.quoted)\n")
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/CatalogCommand.swift
================================================
import Foundation
import ArgumentParser
import FragmentZip
struct CatalogCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "catalog",
abstract: "Manipulates the VirtualBuddy software catalog",
subcommands: [
ImageCommand.self,
GroupCommand.self,
MigrateCommand.self
]
)
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/Core/BuildManifest+Fetch.swift
================================================
import Foundation
import FragmentZip
extension BuildManifest {
init(remoteIPSWURL url: URL, build: String) async throws {
let manifestFileName = "BuildManifest-\(build).plist"
let cachedManifestURL = try URL.vctoolBuildManifestCache.appending(path: manifestFileName)
let manifestURL: URL
if cachedManifestURL.exists {
fputs("Using cached build manifest for \(build)\n", stderr)
manifestURL = cachedManifestURL
} else {
fputs("Retrieving build manifest for \(build)\n", stderr)
let ipsw = FragmentZip(url: url)
let downloadedManifestURL = try await ipsw.download(filePath: "BuildManifest.plist", as: manifestFileName)
do {
try FileManager.default.copyItem(at: downloadedManifestURL, to: cachedManifestURL)
} catch {
fputs("WARN: Failed to cache build manifest: \(error)\n", stderr)
}
manifestURL = downloadedManifestURL
}
try self.init(contentsOf: manifestURL)
}
}
extension URL {
static var vctoolBuildManifestCache: URL {
get throws {
try URL.vctoolCache
.appending(path: "BuildManifests", directoryHint: .isDirectory)
.ensureExistingDirectory(createIfNeeded: true)
}
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/Core/BuildManifest.swift
================================================
import Foundation
import BuddyFoundation
struct BuildManifest: Decodable, TreeStringConvertible {
var manifestVersion: Int
var productBuildVersion: String
var productVersion: SoftwareVersion
var supportedProductTypes: [String]
var buildIdentities: [BuildIdentity]
enum CodingKeys: String, CodingKey {
case manifestVersion = "ManifestVersion"
case productBuildVersion = "ProductBuildVersion"
case productVersion = "ProductVersion"
case supportedProductTypes = "SupportedProductTypes"
case buildIdentities = "BuildIdentities"
}
}
struct BuildIdentity: Decodable, TreeStringConvertible {
var productMarketingVersion: SoftwareVersion
var boardID: String
var chipID: String
var uniqueBuildID: Data
var info: BuildInfo
enum CodingKeys: String, CodingKey {
case productMarketingVersion = "ProductMarketingVersion"
case boardID = "ApBoardID"
case chipID = "ApChipID"
case uniqueBuildID = "UniqueBuildID"
case info = "Info"
}
}
struct BuildInfo: Decodable, TreeStringConvertible {
var buildNumber: String
var buildTrain: String
var deviceClass: String
var restoreBehavior: String
var variant: String
var mobileDeviceMinVersion: SoftwareVersion
var virtualMachineMinCPUCount: Int?
var virtualMachineMinHostOS: SoftwareVersion?
var virtualMachineMinMemorySizeMB: Int?
enum CodingKeys: String, CodingKey {
case buildNumber = "BuildNumber"
case buildTrain = "BuildTrain"
case deviceClass = "DeviceClass"
case restoreBehavior = "RestoreBehavior"
case variant = "Variant"
case virtualMachineMinCPUCount = "VirtualMachineMinCPUCount"
case virtualMachineMinHostOS = "VirtualMachineMinHostOS"
case virtualMachineMinMemorySizeMB = "VirtualMachineMinMemorySizeMB"
case mobileDeviceMinVersion = "MobileDeviceMinVersion"
}
}
// MARK: - Parsing
extension BuildManifest {
private static let decoder: PropertyListDecoder = {
let d = PropertyListDecoder()
return d
}()
init(contentsOf url: URL) throws {
let data = try Data(contentsOf: url, options: .mappedIfSafe)
try self.init(data: data)
}
init(data: Data) throws {
self = try Self.decoder.decode(Self.self, from: data)
}
}
// MARK: - Filtering
extension BuildManifest {
mutating func filterBuildIdentities(using predicate: (BuildIdentity) -> Bool) {
buildIdentities.removeAll(where: { !predicate($0) })
}
func filteringBuildIdentities(using predicate: (BuildIdentity) -> Bool) -> BuildManifest {
var mSelf = self
mSelf.filterBuildIdentities(using: predicate)
return mSelf
}
}
extension BuildInfo {
/// `true` if the information indicates that the associated build identity is for a Mac VM.
var hasVMInformation: Bool {
virtualMachineMinHostOS != nil
|| virtualMachineMinCPUCount != nil
|| virtualMachineMinMemorySizeMB != nil
|| deviceClass.caseInsensitiveCompare("vma2macosap") == .orderedSame
}
}
extension BuildIdentity {
/// `true` if the information indicates that this build identity is for a Mac VM.
var hasVMInformation: Bool { info.hasVMInformation }
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/Core/Helpers.swift
================================================
import Foundation
import ArgumentParser
import BuddyFoundation
extension URL {
init(validating string: String) throws {
guard let url = URL(string: string) else {
throw "Invalid URL: \"\(string)\""
}
self = url
}
}
extension ProcessInfo {
nonisolated(unsafe) private static var _sessionID: String?
var sessionID: String {
if let id = Self._sessionID { return id }
let newID = UUID().uuidString
Self._sessionID = newID
return newID
}
}
extension URL {
var exists: Bool { FileManager.default.fileExists(atPath: path) }
var isExistingDirectory: Bool {
var isDir = ObjCBool(false)
guard FileManager.default.fileExists(atPath: path, isDirectory: &isDir) else { return false }
return isDir.boolValue
}
func ensureExistingFile() throws -> URL {
try requireExistingFile()
return self
}
func ensureExistingDirectory(createIfNeeded: Bool = false) throws -> URL {
try requireExistingDirectory(createIfNeeded: createIfNeeded)
return self
}
func requireExistingFile() throws {
guard exists else {
throw "File doesn't exist at \(path)"
}
guard !isExistingDirectory else {
throw "Expected a file, but found a directory at \(path)"
}
}
func requireExistingDirectory(createIfNeeded: Bool = false) throws {
if exists {
guard isExistingDirectory else {
throw "Expected a directory, but found a regular file at \(path)"
}
} else {
guard createIfNeeded else {
throw "Directory doesn't exist at \(path)"
}
try FileManager.default.createDirectory(at: self, withIntermediateDirectories: true)
}
}
static var baseTempURL: URL {
get throws {
let tempBase = FileManager.default.temporaryDirectory
let sessionBase = tempBase.appendingPathComponent(ProcessInfo.processInfo.sessionID)
if !FileManager.default.fileExists(atPath: sessionBase.path) {
try FileManager.default.createDirectory(at: sessionBase, withIntermediateDirectories: true)
}
return sessionBase
}
}
static func tempFileURL(name: String, create: Bool = false) throws -> URL {
let fileURL = try baseTempURL.appendingPathComponent(name)
if create, !fileURL.exists {
FileManager.default.createFile(atPath: fileURL.path, contents: nil)
}
return fileURL
}
static func tempDirURL(name: String, create: Bool = false) throws -> URL {
let dirURL = try baseTempURL.appendingPathComponent(name)
if create, !dirURL.exists {
try FileManager.default.createDirectory(at: dirURL, withIntermediateDirectories: true)
}
return dirURL
}
static var vctoolCache: URL {
get throws {
try FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appending(path: "vctool", directoryHint: .isDirectory)
}
}
}
extension String {
var resolvedPath: String { (self as NSString).expandingTildeInPath }
var resolvedURL: URL { URL(filePath: resolvedPath) }
}
extension CatalogGuestPlatform: @retroactive EnumerableFlag { }
extension ResolvedFeatureStatus {
var cliDescription: String {
switch self {
case .supported:
return "✅ Supported"
case .warning(_, let message):
return "⚠️ Warning: \(message)"
case .unsupported(_, let message):
return "🛑 Not Supported: \(message)"
}
}
}
extension SoftwareVersion: @retroactive ExpressibleByArgument {
public init?(argument: String) {
self.init(string: argument)
}
}
extension RequirementSet {
func matches(info: BuildInfo) -> Bool {
guard let manifestMinVersionHost = info.virtualMachineMinHostOS else { return true }
guard manifestMinVersionHost == self.minVersionHost else { return false }
guard let manifestMinMemory = info.virtualMachineMinMemorySizeMB else { return true }
guard manifestMinMemory == self.minMemorySizeMB else { return false }
guard let manifestMinCPU = info.virtualMachineMinCPUCount else { return true }
return manifestMinCPU == self.minCPUCount
}
}
extension BuildInfo {
var requirementsDescription: String {
let minVer = virtualMachineMinHostOS?.description ?? "?"
let minMem = virtualMachineMinMemorySizeMB.flatMap({ String($0) }) ?? "?"
let minCPU = virtualMachineMinCPUCount.flatMap({ String($0) }) ?? "?"
return "minHostVersion: \(minVer) | minMemory: \(minMem) | minCPU: \(minCPU)"
}
}
extension RestoreImage: TreeStringConvertible, @retroactive CustomStringConvertible {
public var description: String { description(level: 0) }
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/Core/TreeStringConvertible.swift
================================================
import Foundation
protocol TreeStringConvertible: CustomStringConvertible {
func description(level: Int) -> String
}
extension TreeStringConvertible {
func indentation(for level: Int) -> String { String(repeating: " ", count: level * 2) }
func description(level: Int) -> String {
let prefix = indentation(for: level)
let mirror = Mirror(reflecting: self)
var output = [String]()
for child in mirror.children {
let name = "- " + (child.label ?? "???")
let item: String
if let convertibleChild = child.value as? TreeStringConvertible {
let childDescription = convertibleChild.description(level: level + 1)
if childDescription.contains("\n") {
output.append(prefix + name)
item = childDescription
} else {
item = prefix + "\(name) = \(childDescription)"
}
} else {
let value = String(describing: child.value)
item = prefix + "\(name) = \(value)"
}
output.append(item)
}
return output.joined(separator: "\n")
}
var description: String { description(level: 0) }
}
extension Array: TreeStringConvertible {
func description(level: Int) -> String {
let prefix = indentation(for: level)
return enumerated().map {
let elementPrefix = prefix + "- [\($0.offset)] "
if let convertibleElement = $0.element as? TreeStringConvertible {
return elementPrefix + "\n" + convertibleElement.description(level: level + 1)
} else {
return elementPrefix + String(describing: $0.element)
}
}.joined(separator: "\n")
}
}
extension Optional: @retroactive CustomStringConvertible {}
extension Optional: TreeStringConvertible {
func description(level: Int) -> String {
switch self {
case .none:
return "<nil>"
case .some(let value):
if let convertibleValue = value as? TreeStringConvertible {
return convertibleValue.description(level: level + 1)
} else {
return String(describing: value)
}
}
}
public var description: String { description(level: 0) }
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/Core/URL+ContentLength.swift
================================================
import Foundation
extension URL {
func contentLength() async throws -> Int64 {
var request = URLRequest(url: self)
request.httpMethod = "HEAD"
request.timeoutInterval = 10
let (_, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
throw "Invalid response"
}
guard httpResponse.statusCode < 300 else {
throw "HTTP \(httpResponse.statusCode)"
}
guard let stringValue = httpResponse.value(forHTTPHeaderField: "content-length"),
let length = Int64(stringValue)
else {
throw "Missing or invalid Content-Length header"
}
return length
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/GroupCommand.swift
================================================
import Foundation
import ArgumentParser
import AppKit
import BuddyFoundation
import VirtualUI
extension CatalogCommand {
struct GroupCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "group",
abstract: "View or modify groups.",
subcommands: [
AddCommand.self
]
)
struct AddCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "add",
abstract: "Adds a new group to the catalog."
)
@Option(help: "Unique identifier for the group (ex: \"sequoia\").")
var id: String
@Option(help: "The major version for releases in the group (ex: 15).")
var version: SoftwareVersion
@Option(help: "User-friendly name for the group (ex: \"macOS Sequoia\").")
var name: String
@Option(help: "Path to an image representing the group (usually that release's default wallpaper).")
var image: String
@Option(name: [.short, .long], help: "Path to an existing catalog JSON file that will be updated with the new group.")
var output: String
@Option(help: "Remote base URL where catalog will be served from.")
var baseURL: String = "https://api.virtualbuddy.app/v2"
func run() async throws {
let catalogURL = try output.resolvedURL.ensureExistingFile()
var catalog = try SoftwareCatalog(contentsOf: catalogURL)
guard let remoteBaseURL = URL(string: baseURL) else {
throw "Invalid base URL: \"\(baseURL)\""
}
guard !catalog.groups.contains(where: { $0.id.caseInsensitiveCompare(id) == .orderedSame }) else {
throw "A group already exists with id \"\(id)\""
}
let imageURL = try image.resolvedURL.ensureExistingFile()
/// Dark image is expected to be named the same as the image but with the "-dark" suffix.
let darkImageURL = try imageURL
.deletingLastPathComponent()
.appendingPathComponent(imageURL.deletingPathExtension().lastPathComponent + "-dark")
.appendingPathExtension(imageURL.pathExtension)
.ensureExistingFile()
let localImagesBaseURL = try catalogURL
.deletingLastPathComponent()
.appending(path: "images", directoryHint: .isDirectory)
.ensureExistingDirectory(createIfNeeded: true)
let localImageURL = localImagesBaseURL
.appendingPathComponent(id, conformingTo: .heic)
let localThumbnailURL = localImagesBaseURL
.appendingPathComponent(id + "-thumbnail", conformingTo: .heic)
let localDarkImageURL = localImagesBaseURL
.appendingPathComponent(id + "-dark", conformingTo: .heic)
let localDarkThumbnailURL = localImagesBaseURL
.appendingPathComponent(id + "-dark-thumbnail", conformingTo: .heic)
let remoteImageURL = remoteBaseURL.appendingPathComponent("images/" + localImageURL.lastPathComponent)
let remoteThumbnailImageURL = remoteBaseURL.appendingPathComponent("images/" + localThumbnailURL.lastPathComponent)
let remoteDarkImageURL = remoteBaseURL.appendingPathComponent("images/" + localDarkImageURL.lastPathComponent)
let remoteDarkThumbnailImageURL = remoteBaseURL.appendingPathComponent("images/" + localDarkThumbnailURL.lastPathComponent)
try imageURL.vctool_encodeHEIC(to: localImageURL, maxSize: 2048, quality: 0.9)
try imageURL.vctool_encodeHEIC(to: localThumbnailURL, maxSize: 720, quality: 0.8)
try darkImageURL.vctool_encodeHEIC(to: localDarkImageURL, maxSize: 2048, quality: 0.9)
try darkImageURL.vctool_encodeHEIC(to: localDarkThumbnailURL, maxSize: 720, quality: 0.8)
let blurHashComponents: (Int, Int) = (Int(CGSize.vbBlurHashSize.width), Int(CGSize.vbBlurHashSize.height))
guard let thumbnailImage = NSImage(contentsOf: localThumbnailURL) else {
throw "Failed to load generated thumbnail image from \(localThumbnailURL.path)"
}
guard let blurHash = thumbnailImage.blurHash(numberOfComponents: blurHashComponents) else {
throw "Failed to generate blur hash from generated thumbnail image at \(localThumbnailURL.path)"
}
guard let darkThumbnailImage = NSImage(contentsOf: localDarkThumbnailURL) else {
throw "Failed to load generated thumbnail dark image from \(localDarkThumbnailURL.path)"
}
guard let darkBlurHash = darkThumbnailImage.blurHash(numberOfComponents: blurHashComponents) else {
throw "Failed to generate blur hash from generated dark thumbnail image at \(localDarkThumbnailURL.path)"
}
let image = CatalogGraphic(
id: id,
url: remoteImageURL,
thumbnail: CatalogGraphic.Thumbnail(
url: remoteThumbnailImageURL,
width: Int(thumbnailImage.size.width),
height: Int(thumbnailImage.size.height),
blurHash: blurHash
)
)
let darkImage = CatalogGraphic(
id: id,
url: remoteDarkImageURL,
thumbnail: CatalogGraphic.Thumbnail(
url: remoteDarkThumbnailImageURL,
width: Int(darkThumbnailImage.size.width),
height: Int(darkThumbnailImage.size.height),
blurHash: darkBlurHash
)
)
let group = CatalogGroup(
id: id,
name: name,
majorVersion: version,
image: image,
darkImage: darkImage
)
catalog.groups.insert(group, at: 0)
try catalog.write(to: catalogURL)
}
}
}
}
// MARK: - Helpers
extension URL {
func vctool_encodeHEIC(to outputURL: URL, maxSize: Int, quality: Double) throws {
guard let image = NSImage(contentsOf: self) else {
throw "Image couldn't be loaded from \(self.path)"
}
guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else {
throw "Couldn't get CGImage from input image"
}
guard let destination = CGImageDestinationCreateWithURL(outputURL as CFURL, "public.heic" as CFString, 1, nil) else {
throw "Failed to create image destination"
}
let imageOptions = [
kCGImageDestinationLossyCompressionQuality: quality,
kCGImageDestinationImageMaxPixelSize: maxSize
] as CFDictionary
CGImageDestinationAddImage(destination, cgImage, imageOptions)
CGImageDestinationFinalize(destination)
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/IPSWCommand.swift
================================================
import Foundation
import ArgumentParser
import FragmentZip
struct IPSWCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "ipsw",
abstract: "Tools for exploring IPSW packages.",
subcommands: [
InspectCommand.self,
ManifestCommand.self
]
)
struct ManifestOptions: ParsableArguments {
@Flag(help: "List only the build identities containing virtual machine information.")
var vm = false
}
// MARK: - Inspect Command
struct InspectCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "inspect",
abstract: "Inspects an IPSW file, retrieving information that's relevant to VirtualBuddy."
)
@Argument(help: "URL to the IPSW file.")
var ipsw: String
@OptionGroup
var options: ManifestOptions
func run() async throws {
let url = try URL(validating: ipsw)
let zip = FragmentZip(url: url)
let fileURL = try await zip.download(filePath: "BuildManifest.plist")
let manifestCommand = ManifestCommand(manifestPath: fileURL.path, options: options)
try await manifestCommand.run()
}
}
// MARK: - Manifest Command
struct ManifestCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "manifest",
abstract: "Parses properties from a local BuildManifest.plist file."
)
@Argument(help: "Path to a BuildManifest.plist file.")
var manifestPath: String
@OptionGroup
var options: ManifestOptions
init() { }
// This initializer is needed because this command is run by InspectCommand.
init(manifestPath: String, options: ManifestOptions) {
self.manifestPath = manifestPath
self.options = options
}
func run() async throws {
let url = try manifestPath.resolvedURL.ensureExistingFile()
var manifest = try BuildManifest(contentsOf: url)
manifest.filterBuildIdentities { identity in
options.vm ? identity.hasVMInformation : true
}
print(manifest)
}
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/ImageCommand.swift
================================================
import Foundation
import ArgumentParser
import FragmentZip
import BuddyFoundation
import VirtualCore
extension CatalogCommand {
struct ImageCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "image",
abstract: "Manipulates restore images in the VirtualBuddy catalog.",
subcommands: [
AddCommand.self
]
)
// MARK: - Add Command
struct AddCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "add",
abstract: "Adds a new macOS release to a VirtualBuddy software catalog based on an IPSW URL."
)
@Option(name: [.short, .long], help: "URL to the IPSW file.")
var ipsw: String
@Option(name: [.short, .long], help: "ID of the release channel (devbeta or regular).")
var channel: String
@Option(name: [.short, .long], help: "User-facing name for the release (ex: \"macOS 15.0 Developer Beta 4\").")
var name: String
@Option(name: [.short, .long], help: "Path to the software catalog JSON file that will be updated.")
var output: String
@Flag(name: .shortAndLong, help: "Replace existing build if it already exists in the catalog.")
var force = false
func run() async throws {
let ipswURL = try URL(validating: ipsw)
let catalogURL = try output.resolvedURL.ensureExistingFile()
fputs("Detecting download size...\n", stderr)
let contentLength = try await ipswURL.contentLength()
var catalog = try SoftwareCatalog(contentsOf: catalogURL)
fputs("Reading build manifest from remote IPSW...\n", stderr)
let zip = FragmentZip(url: ipswURL)
let fileURL = try await zip.download(filePath: "BuildManifest.plist")
let manifest = try BuildManifest(contentsOf: fileURL)
guard let identity = manifest.buildIdentities.first(where: { $0.hasVMInformation }) else {
throw "Couldn't find a build identity with VM information in the specified IPSW. Are you sure this IPSW supports macOS VMs?"
}
let majorVersion = SoftwareVersion(majorVersionFrom: manifest.productVersion)
guard let group = catalog.groups.first(where: { $0.majorVersion == majorVersion }) else {
throw "Couldn't find a group with majorVersion = \(majorVersion). If this is a new major version of macOS, a new group must be added to the catalog manually before running this command."
}
guard catalog.channels.contains(where: { $0.id == channel }) else {
throw "Couldn't find \"\(channel)\" channel in the catalog. Catalog channels: \(catalog.channels.map(\.id).joined(separator: ", "))"
}
fputs("Found group \(group.name)\n", stderr)
let requirementSet: RequirementSet
if let existingSet = catalog.requirementSets.first(where: { $0.matches(info: identity.info) }) {
fputs("Found existing requirement set \(existingSet.id)\n", stderr)
requirementSet = existingSet
} else {
fputs("Found no existing requirement set matching properties from manifest, will create a new one: \(identity.info.requirementsDescription)\n", stderr)
requirementSet = RequirementSet(
id: UUID().uuidString,
minCPUCount: identity.info.virtualMachineMinCPUCount ?? 2,
minMemorySizeMB: identity.info.virtualMachineMinMemorySizeMB ?? 4096,
minVersionHost: identity.info.virtualMachineMinHostOS ?? SoftwareVersion(major: 12, minor: 0, patch: 0)
)
catalog.requirementSets.insert(requirementSet, at: 0)
}
let image = RestoreImage(
id: manifest.productBuildVersion,
group: group.id,
channel: channel,
requirements: requirementSet.id,
name: name,
build: manifest.productBuildVersion,
version: manifest.productVersion,
mobileDeviceMinVersion: identity.info.mobileDeviceMinVersion,
url: ipswURL,
downloadSize: UInt64(contentLength)
)
let index = catalog.index(forInserting: image)
let isUpdate = catalog.restoreImages[index].id == image.id
/// Replacing an existing image requires a flag.
if isUpdate {
guard force else {
fputs("\n❌ Build \(image.id) already exists in the catalog. Use --force flag to update it.\n\n", stderr)
Darwin.exit(1)
}
catalog.restoreImages.remove(at: index)
}
catalog.restoreImages.insert(image, at: index)
let successMessage = isUpdate ? "Updated image in catalog" : "Added image to catalog"
fputs("✅ \(successMessage):\n\n", stderr)
fputs("\(image)\n\n", stderr)
try catalog.write(to: catalogURL)
fputs("✅ Done!\n\n", stderr)
}
}
}
}
private extension SoftwareCatalog {
func index(forInserting image: RestoreImage) -> Int {
if let existingIndex = restoreImages.firstIndex(where: { $0.id == image.id }) {
existingIndex /// Replace image at its current index (client must delete existing one before replacing)
} else if let placementIndex = restoreImages.firstIndex(where: { $0.group == image.group && $0.version <= image.version }) {
placementIndex /// Place image before the first image of the same release group and OS version
} else {
0 /// Place image in first slot
}
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/MigrateCommand.swift
================================================
import Foundation
import ArgumentParser
import FragmentZip
import BuddyFoundation
extension CatalogCommand {
struct MigrateCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "migrate",
abstract: "Migrates a version 1 restore image catalog to version 2.",
discussion: "This command will fetch metadata for each IPSW in the legacy catalog, so it requires an internet connection and may take a while to run."
)
@Option(name: [.short, .long], help: "Path to version 1 catalog.")
var inputPath: String?
@Flag(help: "Migrate from live API catalog instead of a local file.")
var live = false
@Option(name: [.short, .long], help: "Path where to save the migrated version 2 catalog. If a catalog already exists at this path, all restore images will be removed from it and replaced by the migrated ones from the version 1 catalog, but groups and channels will be retained.")
var outputPath: String
private func fetchLegacyCatalog() async throws -> LegacyCatalog {
if let inputPath {
return try LegacyCatalog(contentsOf: inputPath.resolvedURL.ensureExistingFile())
} else {
fputs("Downloading live v1 catalog...\n", stderr)
let (data, _) = try await URLSession.shared.data(from: URL(string: "https://api.virtualbuddy.app/restore/mac?apiKey=15A25D48-4A34-4EE4-A293-C22B0DE1B54E")!)
return try LegacyCatalog(data: data)
}
}
func run() async throws {
/// Any channels not listed here will be excluded from the output catalog.
let channelIdentifiers: Set<String> = ["devbeta", "regular"]
let outputURL = outputPath.resolvedURL
let legacyCatalog = try await fetchLegacyCatalog()
var catalog: SoftwareCatalog
/// If there's an existing version 2 catalog at the output path, then use that catalog as a template, migrating only the restore images from the v1 catalog.
if outputURL.exists {
fputs("Using existing version 2 catalog for migration\n", stderr)
catalog = try SoftwareCatalog(contentsOf: outputURL)
catalog.restoreImages.removeAll()
} else {
fputs("Creating empty version 2 catalog for migration\n", stderr)
catalog = SoftwareCatalog(apiVersion: 2, minAppVersion: .init(string: "2.0.0")!, channels: [], groups: [], restoreImages: [], features: [], requirementSets: [], deviceSupportVersions: [])
}
for legacyChannel in legacyCatalog.channels {
guard channelIdentifiers.contains(legacyChannel.id), !catalog.channels.contains(where: { $0.id == legacyChannel.id }) else { continue }
let channel = CatalogChannel(id: legacyChannel.id, name: legacyChannel.name, note: legacyChannel.note, icon: legacyChannel.icon)
catalog.channels.append(channel)
}
if catalog.groups.isEmpty {
for legacyGroup in legacyCatalog.groups {
let group = CatalogGroup(id: legacyGroup.id, name: legacyGroup.name, majorVersion: legacyGroup.majorVersion, image: .placeholder, darkImage: .placeholder)
catalog.groups.append(group)
}
}
let requirement_min_host_13 = catalog.requirementSets.first(where: { $0.id == "min_host_13" }) ?? RequirementSet(
id: "min_host_13",
minCPUCount: 2,
minMemorySizeMB: 4096,
minVersionHost: SoftwareVersion(string: "13.0")!
)
let requirement_min_host_12 = catalog.requirementSets.first(where: { $0.id == "min_host_12" }) ?? RequirementSet(
id: "min_host_12",
minCPUCount: 2,
minMemorySizeMB: 4096,
minVersionHost: SoftwareVersion(string: "12.0")!
)
if !catalog.requirementSets.contains(where: { $0.id == requirement_min_host_13.id }) {
catalog.requirementSets.append(requirement_min_host_13)
}
if !catalog.requirementSets.contains(where: { $0.id == requirement_min_host_12.id }) {
catalog.requirementSets.append(requirement_min_host_12)
}
for legacyImage in legacyCatalog.images {
do {
let contentLength = try await legacyImage.url.contentLength()
let manifest = try await BuildManifest(remoteIPSWURL: legacyImage.url, build: legacyImage.build)
/// Version 13.3 started requiring macOS 13 host, all versions higher than that require macOS 13 host, all versions below that support macOS 12 host.
let requirements: RequirementSet = manifest.productVersion >= SoftwareVersion(string: "13.3")! ? requirement_min_host_13 : requirement_min_host_12
guard let vmIdentity = manifest.buildIdentities.first(where: { $0.hasVMInformation }) else {
throw "Couldn't find a build identity with VM properties"
}
let image = RestoreImage(
id: legacyImage.id,
group: legacyImage.group.id,
channel: legacyImage.channel.id,
requirements: requirements.id,
name: legacyImage.name,
build: legacyImage.build,
version: manifest.productVersion,
mobileDeviceMinVersion: vmIdentity.info.mobileDeviceMinVersion,
url: legacyImage.url,
downloadSize: UInt64(contentLength)
)
catalog.restoreImages.append(image)
try catalog.write(to: outputURL)
} catch {
fputs("Error processing restore image \(legacyImage.id): \(error)\n", stderr)
}
}
print("Migrated catalog written to \(outputURL.path)")
print("")
}
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/MobileDeviceCommand.swift
================================================
import Foundation
import ArgumentParser
struct MobileDeviceCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "mobiledevice",
abstract: "Interacts with the MobileDevice framework on the host.",
subcommands: [
VersionCommand.self
]
)
struct VersionCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "version",
abstract: "Retrieves the version of the MobileDevice framework that's currently installed."
)
func run() async throws {
guard let framework = MobileDeviceFramework.current else {
throw "Couldn't find MobileDevice.framework"
}
print(framework.version)
}
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/ResolveCommand.swift
================================================
import Foundation
import ArgumentParser
import BuddyFoundation
extension CatalogCommand {
struct ResolveCommand: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "resolve",
abstract: "Resolves a VirtualBuddy software catalog for a given environment."
)
@Option(name: [.short, .long], help: "Path to the catalog JSON file.")
var input: String
@Option(help: "Custom host version.")
var host: SoftwareVersion?
@Option(help: "Custom MobileDevice version.")
var mobileDevice: SoftwareVersion?
@Flag(help: "Specify guest platform.")
var guestPlatform: CatalogGuestPlatform = .mac
@Option(help: "Show results for a specific build.")
var build: String?
func run() async throws {
let url = try input.resolvedURL.ensureExistingFile()
let catalog = try SoftwareCatalog(contentsOf: url)
var env = CatalogResolutionEnvironment.current
if let host {
env.hostVersion = host
}
if let mobileDevice {
env.mobileDeviceVersion = mobileDevice
}
env.guestPlatform = guestPlatform
let resolved = ResolvedCatalog(environment: env, catalog: catalog)
if let build {
guard let targetImage = resolved.groups.flatMap(\.restoreImages).first(where: { $0.image.build == build }) else {
throw "Build not found: \(build)"
}
printResult(for: targetImage)
} else {
for group in resolved.groups {
print("## \(group.name)")
print()
for resolvedImage in group.restoreImages {
printResult(for: resolvedImage)
}
}
}
}
func printResult(for resolvedImage: ResolvedRestoreImage) {
let image = resolvedImage.image
print("### \(image.name) (\(image.build))")
print(" - Guest: \(resolvedImage.status.cliDescription)")
print(" - Host: \(resolvedImage.requirements.status.cliDescription)")
print(" - Features:")
for feature in resolvedImage.features {
print(" - \(feature.feature.name)")
print(" - \(feature.status.cliDescription)")
}
print()
}
}
}
================================================
FILE: VirtualBuddy/CommandLine/vctool/VCTool.swift
================================================
import Foundation
import ArgumentParser
import AppKit
struct VCTool: AsyncParsableCommand {
static let configuration = CommandConfiguration(
commandName: "vctool",
abstract: "Tools for updating the VirtualBuddy software catalog.",
subcommands: [
CatalogCommand.self,
IPSWCommand.self,
MobileDeviceCommand.self,
BlurHashCommand.self,
]
)
}
================================================
FILE: VirtualBuddy/Config/AppTarget.xcconfig
================================================
#include "Paths.xcconfig"
// Settings in this file only apply to the main VirtualBuddy.app target
// Entitlement Settings
// Name of the provisioning profile used for all managed builds (debug, beta, release, dev release).
MANAGED_PROFILE = VirtualBuddy Dev Mid 2025
CODE_SIGN_ENTITLEMENTS[config=Debug][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy.entitlements
CODE_SIGN_ENTITLEMENTS[config=Release][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy.entitlements
CODE_SIGN_ENTITLEMENTS[config=Debug_Managed][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy_Managed.entitlements
CODE_SIGN_ENTITLEMENTS[config=Release_Managed][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy_Managed.entitlements
CODE_SIGN_ENTITLEMENTS[config=Dev_Release][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy_Managed.entitlements
CODE_SIGN_ENTITLEMENTS[config=Beta_Debug][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy_Managed.entitlements
CODE_SIGN_ENTITLEMENTS[config=Beta_Release][sdk=*][arch=*] = $(ENTITLEMENTS_DIR)/VirtualBuddy_Managed.entitlements
PROVISIONING_PROFILE_SPECIFIER[config=Debug][sdk=*][arch=*] =
PROVISIONING_PROFILE_SPECIFIER[config=Release][sdk=*][arch=*] =
PROVISIONING_PROFILE_SPECIFIER[config=Debug_Managed][sdk=*][arch=*] = $(MANAGED_PROFILE)
PROVISIONING_PROFILE_SPECIFIER[config=Release_Managed][sdk=*][arch=*] = $(MANAGED_PROFILE)
PROVISIONING_PROFILE_SPECIFIER[config=Dev_Release][sdk=*][arch=*] = $(MANAGED_PROFILE)
PROVISIONING_PROFILE_SPECIFIER[config=Beta_Debug][sdk=*][arch=*] = $(MANAGED_PROFILE)
PROVISIONING_PROFILE_SPECIFIER[config=Beta_Release][sdk=*][arch=*] = $(MANAGED_PROFILE)
CODE_SIGN_STYLE[config=Debug][sdk=*][arch=*] = Automatic
CODE_SIGN_STYLE[config=Release][sdk=*][arch=*] = Automatic
CODE_SIGN_STYLE[config=Debug_Managed][sdk=*][arch=*] = Manual
CODE_SIGN_STYLE[config=Release_Managed][sdk=*][arch=*] = Manual
CODE_SIGN_STYLE[config=Dev_Release][sdk=*][arch=*] = Manual
CODE_SIGN_STYLE[config=Beta_Debug][sdk=*][arch=*] = Manual
CODE_SIGN_STYLE[config=Beta_Release][sdk=*][arch=*] = Manual
OTHER_SWIFT_FLAGS[config=Release][sdk=*][arch=*] = -D BUILDING_NON_MANAGED_RELEASE
OTHER_SWIFT_FLAGS[config=Dev_Release][sdk=*][arch=*] = -D BUILDING_DEV_RELEASE
// Release Train Settings
// Special app icon for development releases. Note that Xcode uses the first icon when sorted alphabetically, hence why the default icon has the -Default suffix.
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Default
ASSETCATALOG_COMPILER_APPICON_NAME[config=Dev_Release][sdk=*][arch=*] = AppIcon-Dev
ASSETCATALOG_COMPILER_APPICON_NAME[config=Beta_Debug][sdk=*][arch=*] = AppIcon-zBeta
ASSETCATALOG_COMPILER_APPICON_NAME[config=Beta_Release][sdk=*][arch=*] = AppIcon-zBeta
PRODUCT_NAME = $(TARGET_NAME)
// Development releases named VirtualBuddy-Dev.app
PRODUCT_NAME[config=Dev_Release][sdk=*][arch=*] = $(TARGET_NAME)-Dev
================================================
FILE: VirtualBuddy/Config/Entitlements/VirtualBuddy.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.virtualization</key>
<true/>
</dict>
</plist>
================================================
FILE: VirtualBuddy/Config/Entitlements/VirtualBuddy_Managed.entitlements
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.virtualization</key>
<true/>
<key>com.apple.vm.networking</key>
<true/>
</dict>
</plist>
================================================
FILE: VirtualBuddy/Config/Features.xcconfig
================================================
// ENABLE_SPARKLE = Enables building with Sparkle for automatic updates
// ENABLE_USERDEFAULTS_SYNC = Enables the user defaults sync feature
OTHER_SWIFT_FLAGS = -D ENABLE_SPARKLE $(inherited)
// The BETA flag must be present in all targets, hence why these are here instead of in AppTarget.xcconfig
OTHER_SWIFT_FLAGS[config=Beta_Debug][sdk=*][arch=*] = -D BETA $(inherited)
OTHER_SWIFT_FLAGS[config=Beta_Release][sdk=*][arch=*] = -D BETA $(inherited)
VB_SPARKLE_PUBLIC_ED_KEY=dj8ljUPnwoLj/dLs6HyJg5Ayw+t8zWtgjQUfQsH56ww=
VB_SPARKLE_CHECK_INTERVAL=86400
================================================
FILE: VirtualBuddy/Config/InfoPlist.xcconfig
================================================
INFOPLIST_KEY_NSHumanReadableCopyright = © 2024 Buddy Software LTD
INFOPLIST_KEY_NSMicrophoneUsageDescription = Enable audio input for your virtual machines. Without this permission, virtual machines won't be able to record any audio.
================================================
FILE: VirtualBuddy/Config/Main.xcconfig
================================================
#include "Paths.xcconfig"
#include "Versions.xcconfig"
#include "Signing.xcconfig"
#include "Features.xcconfig"
#include "InfoPlist.xcconfig"
ARCHS=arm64
================================================
FILE: VirtualBuddy/Config/Paths.xcconfig
================================================
ENTITLEMENTS_DIR=VirtualBuddy/Config/Entitlements
VB_APP_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks
VB_FRAMEWORK_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/Frameworks
VB_CLI_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @executable_path/Frameworks @executable_path
================================================
FILE: VirtualBuddy/Config/Signing.xcconfig
================================================
CODE_SIGN_IDENTITY = Apple Development
VB_BUNDLE_ID_PREFIX =
GUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID = $(VB_BUNDLE_ID_PREFIX)codes.rambo.VirtualBuddyGuestHelper
GUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID_STR=@"$(GUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID)"
GCC_PREPROCESSOR_DEFINITIONS=$(inherited) GUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID='$(GUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID_STR)'
================================================
FILE: VirtualBuddy/Config/Versions.xcconfig
================================================
MARKETING_VERSION = 2.1
CURRENT_PROJECT_VERSION = 284
DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION)
VERSIONING_SYSTEM = apple-generic
MACOSX_DEPLOYMENT_TARGET = 13.0
================================================
FILE: VirtualBuddy/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>vbvm</string>
</array>
<key>CFBundleTypeName</key>
<string>VirtualBuddy VM</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>codes.rambo.VirtualBuddy.VM</string>
</array>
<key>LSTypeIsPackage</key>
<true/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>vbst</string>
</array>
<key>CFBundleTypeName</key>
<string>VirtualBuddy Saved State</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>codes.rambo.VirtualBuddy.SavedState</string>
</array>
<key>LSTypeIsPackage</key>
<true/>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>UTM virtual machine</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.utmapp.utm</string>
</array>
<key>LSTypeIsPackageLSTypeIsPackage</key>
<true/>
</dict>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>codes.rambo.VirtualBuddy.Action</string>
<key>CFBundleURLSchemes</key>
<array>
<string>virtualbuddy</string>
</array>
</dict>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>SUPublicEDKey</key>
<string>$(VB_SPARKLE_PUBLIC_ED_KEY)</string>
<key>SUScheduledCheckInterval</key>
<string>$(VB_SPARKLE_CHECK_INTERVAL)</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.composite-content</string>
<string>com.apple.package</string>
</array>
<key>UTTypeDescription</key>
<string>VirtualBuddy VM</string>
<key>UTTypeIcons</key>
<dict/>
<key>UTTypeIdentifier</key>
<string>codes.rambo.VirtualBuddy.VM</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>vbvm</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.composite-content</string>
<string>com.apple.package</string>
</array>
<key>UTTypeDescription</key>
<string>VirtualBuddy Saved State</string>
<key>UTTypeIcons</key>
<dict/>
<key>UTTypeIdentifier</key>
<string>codes.rambo.VirtualBuddy.SavedState</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>vbst</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>com.apple.package</string>
</array>
<key>UTTypeDescription</key>
<string>UTM virtual machine</string>
<key>UTTypeIcons</key>
<dict/>
<key>UTTypeIdentifier</key>
<string>com.utmapp.utm</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>utm</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>
================================================
FILE: VirtualBuddy/Preview Content/Preview Assets.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: VirtualBuddy.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 55;
objects = {
/* Begin PBXAggregateTarget section */
F453C44F2DF0BCE3007EAD5F /* vctool */ = {
isa = PBXAggregateTarget;
buildConfigurationList = F453C4502DF0BCE3007EAD5F /* Build configuration list for PBXAggregateTarget "vctool" */;
buildPhases = (
);
dependencies = (
F453C4592DF0BCEB007EAD5F /* PBXTargetDependency */,
);
name = vctool;
packageProductDependencies = (
);
productName = vctool;
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
0196B45329292B2A00614EF1 /* LinuxVirtualMachineConfigurationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0196B45229292B2A00614EF1 /* LinuxVirtualMachineConfigurationHelper.swift */; };
4BA6BE7D293D22E500F396AE /* VirtualMachineConfigurationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA6BE7C293D22E500F396AE /* VirtualMachineConfigurationHelper.swift */; };
F40A1E9D2C1873CA0033E47D /* VBBuildType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F40A1E9C2C1873C60033E47D /* VBBuildType.swift */; };
F413696229916F6E002CE8D3 /* StatusItemButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695129916F6E002CE8D3 /* StatusItemButton.swift */; };
F413696329916F6E002CE8D3 /* StatusBarPanelChrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695229916F6E002CE8D3 /* StatusBarPanelChrome.swift */; };
F413696429916F6E002CE8D3 /* StatusItemProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695329916F6E002CE8D3 /* StatusItemProviderProtocol.swift */; };
F413696529916F6E002CE8D3 /* StatusItemPanelContentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695529916F6E002CE8D3 /* StatusItemPanelContentController.swift */; };
F413696729916F6E002CE8D3 /* VUIAppKitViewControllerHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695729916F6E002CE8D3 /* VUIAppKitViewControllerHost.swift */; };
F413696829916F6E002CE8D3 /* StatusItemMenuBarExtraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695829916F6E002CE8D3 /* StatusItemMenuBarExtraView.swift */; };
F413696929916F6E002CE8D3 /* StatusBarContentPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695929916F6E002CE8D3 /* StatusBarContentPanel.swift */; };
F413696A29916F6E002CE8D3 /* StatusBarHighlightView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413695A29916F6E002CE8D3 /* StatusBarHighlightView.swift */; };
F413696B29916F6E002CE8D3 /* NSStatusItem+.h in Headers */ = {isa = PBXBuildFile; fileRef = F413695C29916F6E002CE8D3 /* NSStatusItem+.h */; settings = {ATTRIBUTES = (Public, ); }; };
F413696C29916F6E002CE8D3 /* NSApplication+MenuBar.h in Headers */ = {isa = PBXBuildFile; fileRef = F413695D29916F6E002CE8D3 /* NSApplication+MenuBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
F413696D29916F6E002CE8D3 /* NSStatusBarPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F413695E29916F6E002CE8D3 /* NSStatusBarPrivate.h */; };
F413696E29916F6E002CE8D3 /* NSApplication+MenuBar.m in Sources */ = {isa = PBXBuildFile; fileRef = F413695F29916F6E002CE8D3 /* NSApplication+MenuBar.m */; };
F413696F29916F6E002CE8D3 /* NSStatusItem+.m in Sources */ = {isa = PBXBuildFile; fileRef = F413696029916F6E002CE8D3 /* NSStatusItem+.m */; };
F413697029916F6E002CE8D3 /* StatusItemManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413696129916F6E002CE8D3 /* StatusItemManager.swift */; };
F413697929917135002CE8D3 /* CGFloat+OnePixel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F413697829917135002CE8D3 /* CGFloat+OnePixel.swift */; };
F4136999299179B1002CE8D3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F4136998299179B1002CE8D3 /* Main.storyboard */; };
F413699A299179F8002CE8D3 /* VirtualCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4BE9C6527FF053A00B648F8 /* VirtualCore.framework */; };
F413699B299179F8002CE8D3 /* VirtualCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F4BE9C6527FF053A00B648F8 /* VirtualCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F41369A329917FA0002CE8D3 /* ScreenChangeModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41369A229917FA0002CE8D3 /* ScreenChangeModifier.swift */; };
F41369A6299183C8002CE8D3 /* GuestLaunchAtLoginManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41369A5299183C8002CE8D3 /* GuestLaunchAtLoginManager.swift */; };
F41369AE29918576002CE8D3 /* GuestHelperAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41369AD29918576002CE8D3 /* GuestHelperAppDelegate.swift */; };
F41369B229918576002CE8D3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F41369B129918576002CE8D3 /* Assets.xcassets */; };
F41369B529918576002CE8D3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F41369B329918576002CE8D3 /* Main.storyboard */; };
F41369BF2991863A002CE8D3 /* VirtualBuddyGuestHelper.app in Embed Login Item */ = {isa = PBXBuildFile; fileRef = F41369AB29918576002CE8D3 /* VirtualBuddyGuestHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
F41369CA2991A492002CE8D3 /* HostConnectionStateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41369C92991A492002CE8D3 /* HostConnectionStateProvider.swift */; };
F41369CC2991A68F002CE8D3 /* GuestSharedFoldersManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41369CB2991A68F002CE8D3 /* GuestSharedFoldersManager.swift */; };
F417255D288604A8004FF8A7 /* SoundConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417255C288604A8004FF8A7 /* SoundConfigurationView.swift */; };
F417255F28861604004FF8A7 /* DecodableDefault.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417255E28861604004FF8A7 /* DecodableDefault.swift */; };
F417256128861A05004FF8A7 /* SharingConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417256028861A05004FF8A7 /* SharingConfigurationView.swift */; };
F41725632886DD37004FF8A7 /* SharedFolderListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41725622886DD37004FF8A7 /* SharedFolderListItem.swift */; };
F41725662886DF58004FF8A7 /* OpenSavePanelUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41725652886DF58004FF8A7 /* OpenSavePanelUtils.swift */; };
F41725682886E5AD004FF8A7 /* MaterialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41725672886E5AD004FF8A7 /* MaterialView.swift */; };
F417256C2887500F004FF8A7 /* StorageConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417256B2887500F004FF8A7 /* StorageConfigurationView.swift */; };
F417256F2887544A004FF8A7 /* StorageDeviceDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417256E2887544A004FF8A7 /* StorageDeviceDetailView.swift */; };
F417257128877121004FF8A7 /* DiskImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417257028877121004FF8A7 /* DiskImageGenerator.swift */; };
F417257428877478004FF8A7 /* VirtualCore.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F417257328877478004FF8A7 /* VirtualCore.xcassets */; };
F41725762887758A004FF8A7 /* RandomNameGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41725752887758A004FF8A7 /* RandomNameGenerator.swift */; };
F417CB882E0EDECD0065B5D6 /* BackportedContentUnavailableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417CB872E0EDECD0065B5D6 /* BackportedContentUnavailableView.swift */; };
F417CB8A2E0EDF1A0065B5D6 /* EqualWidthHStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417CB892E0EDF1A0065B5D6 /* EqualWidthHStack.swift */; };
F417CBB92E0F3D2E0065B5D6 /* FirstLaunchExperienceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F417CBB82E0F3D2E0065B5D6 /* FirstLaunchExperienceView.swift */; };
F422586D2885CC9F009420AE /* SharedFocusEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F422586C2885CC9F009420AE /* SharedFocusEnvironment.swift */; };
F42258702885D537009420AE /* EphemeralTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = F422586F2885D537009420AE /* EphemeralTextField.swift */; };
F42258722885E100009420AE /* VMConfigurationSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42258712885E100009420AE /* VMConfigurationSheet.swift */; };
F42258742885E10B009420AE /* VMConfigurationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42258732885E10B009420AE /* VMConfigurationViewModel.swift */; };
F42258782885E14A009420AE /* DisplayConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42258772885E14A009420AE /* DisplayConfigurationView.swift */; };
F422587A2885E17D009420AE /* ConfigurationSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42258792885E17D009420AE /* ConfigurationSection.swift */; };
F422587C2885E1CE009420AE /* NetworkConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F422587B2885E1CE009420AE /* NetworkConfigurationView.swift */; };
F422587E2885E2ED009420AE /* HardwareConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F422587D2885E2ED009420AE /* HardwareConfigurationView.swift */; };
F42258802885E71D009420AE /* PropertyControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F422587F2885E71D009420AE /* PropertyControl.swift */; };
F428622D2AE8726D0052F029 /* VirtualMachineControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = F428622C2AE8726D0052F029 /* VirtualMachineControls.swift */; };
F428622E2AE87D7E0052F029 /* DeepLinkSecurity.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F43B01152AD858FE00164CD1 /* DeepLinkSecurity.framework */; };
F428622F2AE87D7E0052F029 /* DeepLinkSecurity.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F43B01152AD858FE00164CD1 /* DeepLinkSecurity.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F42862372AE947C90052F029 /* WHPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42862362AE947C90052F029 /* WHPayload.swift */; };
F42C014A2888C2F800EB15CD /* InstallationConsole.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01492888C2F800EB15CD /* InstallationConsole.swift */; };
F42C014C2888C34B00EB15CD /* LogConsole.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C014B2888C34B00EB15CD /* LogConsole.swift */; };
F42C014E2888CBCB00EB15CD /* InstallProgressStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C014D2888CBCB00EB15CD /* InstallProgressStepView.swift */; };
F42C015A2888FC0C00EB15CD /* LibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01512888FC0C00EB15CD /* LibraryView.swift */; };
F42C015B2888FC0C00EB15CD /* VMSessionConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01542888FC0C00EB15CD /* VMSessionConfigurationView.swift */; };
F42C015C2888FC0C00EB15CD /* VirtualMachineSessionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01552888FC0C00EB15CD /* VirtualMachineSessionView.swift */; };
F42C015D2888FC0C00EB15CD /* SwiftUIVMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01572888FC0C00EB15CD /* SwiftUIVMView.swift */; };
F42C015E2888FC0C00EB15CD /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01592888FC0C00EB15CD /* SettingsScreen.swift */; };
F42C01612888FC3500EB15CD /* LibraryItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42C01602888FC3500EB15CD /* LibraryItemView.swift */; };
F42CF4A82DF5FEC3001DE049 /* BlurHashToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42CF4A72DF5FEC3001DE049 /* BlurHashToken.swift */; };
F43B01182AD858FE00164CD1 /* DeepLinkSecurity.h in Headers */ = {isa = PBXBuildFile; fileRef = F43B01172AD858FE00164CD1 /* DeepLinkSecurity.h */; settings = {ATTRIBUTES = (Public, ); }; };
F43B011B2AD858FE00164CD1 /* DeepLinkSecurity.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F43B01152AD858FE00164CD1 /* DeepLinkSecurity.framework */; };
F43B011C2AD858FE00164CD1 /* DeepLinkSecurity.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F43B01152AD858FE00164CD1 /* DeepLinkSecurity.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F43B01352AD8590F00164CD1 /* DeepLinkAuthUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01242AD8590F00164CD1 /* DeepLinkAuthUI.swift */; };
F43B01362AD8590F00164CD1 /* DeepLinkSentinel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01252AD8590F00164CD1 /* DeepLinkSentinel.swift */; };
F43B01372AD8590F00164CD1 /* OpenDeepLinkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01272AD8590F00164CD1 /* OpenDeepLinkRequest.swift */; };
F43B01382AD8590F00164CD1 /* DeepLinkClientDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01282AD8590F00164CD1 /* DeepLinkClientDescriptor.swift */; };
F43B01392AD8590F00164CD1 /* DeepLinkClient+Crypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B012A2AD8590F00164CD1 /* DeepLinkClient+Crypto.swift */; };
F43B013A2AD8590F00164CD1 /* DeepLinkClientDescriptor+.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B012B2AD8590F00164CD1 /* DeepLinkClientDescriptor+.swift */; };
F43B013B2AD8590F00164CD1 /* DeepLinkClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B012C2AD8590F00164CD1 /* DeepLinkClient.swift */; };
F43B013C2AD8590F00164CD1 /* KeychainDeepLinkAuthStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B012E2AD8590F00164CD1 /* KeychainDeepLinkAuthStore.swift */; };
F43B013D2AD8590F00164CD1 /* MemoryDeepLinkAuthStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B012F2AD8590F00164CD1 /* MemoryDeepLinkAuthStore.swift */; };
F43B013E2AD8590F00164CD1 /* DeepLinkManagementStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01302AD8590F00164CD1 /* DeepLinkManagementStore.swift */; };
F43B013F2AD8590F00164CD1 /* UserDefaultsDeepLinkManagementStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01312AD8590F00164CD1 /* UserDefaultsDeepLinkManagementStore.swift */; };
F43B01402AD8590F00164CD1 /* DeepLinkAuthStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01322AD8590F00164CD1 /* DeepLinkAuthStore.swift */; };
F43B01412AD8590F00164CD1 /* DeepLinkSecurityDefines.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01342AD8590F00164CD1 /* DeepLinkSecurityDefines.swift */; };
F43B01442AD85A6500164CD1 /* VirtualBuddyDeepLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01432AD85A6500164CD1 /* VirtualBuddyDeepLinks.swift */; };
F43B01472AD85A7D00164CD1 /* URLQueryItemCoder in Frameworks */ = {isa = PBXBuildFile; productRef = F43B01462AD85A7D00164CD1 /* URLQueryItemCoder */; };
F43B014B2AD85ABB00164CD1 /* DeepLinkAuthDialog.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B01492AD85ABB00164CD1 /* DeepLinkAuthDialog.swift */; };
F43B014E2AD86BFA00164CD1 /* DeepLinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43B014D2AD86BFA00164CD1 /* DeepLinkHandler.swift */; };
F443620A29B7947A00745B43 /* GuestAdditionsDiskImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F443620929B7947A00745B43 /* GuestAdditionsDiskImage.swift */; };
F443620C29B79A6800745B43 /* VirtualBuddyGuest.app in Embed Guest App */ = {isa = PBXBuildFile; fileRef = F4C18A4228491B8500335EC7 /* VirtualBuddyGuest.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
F443620F29B7A0C600745B43 /* CreateGuestImage.sh in Resources */ = {isa = PBXBuildFile; fileRef = F443620E29B7A0C600745B43 /* CreateGuestImage.sh */; };
F444D0CA2DF321CD0086537A /* CatalogGroupPlaceholder.heic in Resources */ = {isa = PBXBuildFile; fileRef = F444D0C92DF321CD0086537A /* CatalogGroupPlaceholder.heic */; };
F444D0CC2DF322B90086537A /* SoftwareCatalog+Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0CB2DF322B50086537A /* SoftwareCatalog+Placeholder.swift */; };
F444D0CE2DF32E100086537A /* BlurHashFullBleedBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0CD2DF32E100086537A /* BlurHashFullBleedBackground.swift */; };
F444D0F42DF34BE80086537A /* CALayer+Asset.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0F32DF34BE40086537A /* CALayer+Asset.swift */; };
F444D0F62DF37D170086537A /* VirtualBuddyMonoIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0F52DF37D170086537A /* VirtualBuddyMonoIcon.swift */; };
F444D0F82DF37D410086537A /* VirtualDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0F72DF37D410086537A /* VirtualDisplayView.swift */; };
F444D0FA2DF37DFB0086537A /* InstallProgressDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0F92DF37DFB0086537A /* InstallProgressDisplayView.swift */; };
F444D0FC2DF37EF80086537A /* VirtualBuddyMonoProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D0FB2DF37EF80086537A /* VirtualBuddyMonoProgressView.swift */; };
F444D1342BB478AD00AB786F /* VBMemoryLeakDebugAssertions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F444D1332BB478AD00AB786F /* VBMemoryLeakDebugAssertions.swift */; };
F4450CCA2ACB0DB500092618 /* KeyboardDeviceConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4450CC92ACB0DB500092618 /* KeyboardDeviceConfigurationView.swift */; };
F44C00FB2889CE1600640BF5 /* VBVirtualMachine+Virtualization.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44C00FA2889CE1600640BF5 /* VBVirtualMachine+Virtualization.swift */; };
F4510A782AE2A16F00E24DD9 /* WeakReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4510A772AE2A16F00E24DD9 /* WeakReference.swift */; };
F4510A7B2AE2B3B300E24DD9 /* DeepLinkSecurity.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F43B01152AD858FE00164CD1 /* DeepLinkSecurity.framework */; };
F453C4122DF0B1ED007EAD5F /* BuddyKit in Frameworks */ = {isa = PBXBuildFile; productRef = F453C4112DF0B1ED007EAD5F /* BuddyKit */; };
F453C41D2DF0B43D007EAD5F /* ResolvedCatalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C41A2DF0B43D007EAD5F /* ResolvedCatalog.swift */; };
F453C41E2DF0B43D007EAD5F /* LegacyCatalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4182DF0B43D007EAD5F /* LegacyCatalog.swift */; };
F453C41F2DF0B43D007EAD5F /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4162DF0B43D007EAD5F /* BlurHashEncode.swift */; };
F453C4202DF0B43D007EAD5F /* SoftwareCatalog.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C41B2DF0B43D007EAD5F /* SoftwareCatalog.swift */; };
F453C4212DF0B43D007EAD5F /* MobileDeviceFramework.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4192DF0B43D007EAD5F /* MobileDeviceFramework.swift */; };
F453C4232DF0B5B1007EAD5F /* VirtualBuddyEntryPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4222DF0B5B1007EAD5F /* VirtualBuddyEntryPoint.swift */; };
F453C4242DF0B602007EAD5F /* VirtualUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F498ACFE2884BF13006F1C00 /* VirtualUI.framework */; };
F453C4252DF0B602007EAD5F /* VirtualUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F498ACFE2884BF13006F1C00 /* VirtualUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F453C42B2DF0B792007EAD5F /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = F453C42A2DF0B792007EAD5F /* ArgumentParser */; };
F453C43B2DF0B7A5007EAD5F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C42E2DF0B7A5007EAD5F /* Helpers.swift */; };
F453C43C2DF0B7A5007EAD5F /* VCTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4392DF0B7A5007EAD5F /* VCTool.swift */; };
F453C43D2DF0B7A5007EAD5F /* URL+ContentLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4302DF0B7A5007EAD5F /* URL+ContentLength.swift */; };
F453C43E2DF0B7A5007EAD5F /* IPSWCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4352DF0B7A5007EAD5F /* IPSWCommand.swift */; };
F453C43F2DF0B7A5007EAD5F /* ImageCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4342DF0B7A5007EAD5F /* ImageCommand.swift */; };
F453C4402DF0B7A5007EAD5F /* BuildManifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C42C2DF0B7A5007EAD5F /* BuildManifest.swift */; };
F453C4412DF0B7A5007EAD5F /* GroupCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4332DF0B7A5007EAD5F /* GroupCommand.swift */; };
F453C4422DF0B7A5007EAD5F /* MobileDeviceCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4372DF0B7A5007EAD5F /* MobileDeviceCommand.swift */; };
F453C4432DF0B7A5007EAD5F /* BuildManifest+Fetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C42D2DF0B7A5007EAD5F /* BuildManifest+Fetch.swift */; };
F453C4442DF0B7A5007EAD5F /* TreeStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C42F2DF0B7A5007EAD5F /* TreeStringConvertible.swift */; };
F453C4452DF0B7A5007EAD5F /* MigrateCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4362DF0B7A5007EAD5F /* MigrateCommand.swift */; };
F453C4462DF0B7A5007EAD5F /* ResolveCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4382DF0B7A5007EAD5F /* ResolveCommand.swift */; };
F453C4472DF0B7A5007EAD5F /* CatalogCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4322DF0B7A5007EAD5F /* CatalogCommand.swift */; };
F453C44A2DF0B7F6007EAD5F /* FragmentZip in Frameworks */ = {isa = PBXBuildFile; productRef = F453C4492DF0B7F6007EAD5F /* FragmentZip */; };
F453C44C2DF0B835007EAD5F /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F453C44B2DF0B835007EAD5F /* libcurl.tbd */; };
F453C44E2DF0B870007EAD5F /* VirtualBuddyCLI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C44D2DF0B869007EAD5F /* VirtualBuddyCLI.swift */; };
F453C45B2DF0C4BE007EAD5F /* BuddyKit in Frameworks */ = {isa = PBXBuildFile; productRef = F453C45A2DF0C4BE007EAD5F /* BuddyKit */; };
F453C45D2DF0D28A007EAD5F /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = F453C45C2DF0D286007EAD5F /* README.md */; };
F453C4632DF0E609007EAD5F /* BuddyKit in Frameworks */ = {isa = PBXBuildFile; productRef = F453C4622DF0E609007EAD5F /* BuddyKit */; };
F453C4682DF10181007EAD5F /* BlurHashCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4672DF10181007EAD5F /* BlurHashCommand.swift */; };
F453C4892DF1CDA0007EAD5F /* DownloadBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4882DF1CDA0007EAD5F /* DownloadBackend.swift */; };
F453C4922DF1D213007EAD5F /* FakeRestoreImage.ipsw in Resources */ = {isa = PBXBuildFile; fileRef = F453C4912DF1D213007EAD5F /* FakeRestoreImage.ipsw */; };
F453C49B2DF1D768007EAD5F /* SimulatedDownloadBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C49A2DF1D768007EAD5F /* SimulatedDownloadBackend.swift */; };
F453C4A02DF1D7C0007EAD5F /* RestoreBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C49F2DF1D7C0007EAD5F /* RestoreBackend.swift */; };
F453C4A22DF1D7F6007EAD5F /* SimulatedRestoreBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4A12DF1D7F6007EAD5F /* SimulatedRestoreBackend.swift */; };
F453C4A42DF1D861007EAD5F /* VirtualizationRestoreBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4A32DF1D85C007EAD5F /* VirtualizationRestoreBackend.swift */; };
F453C4B42DF20301007EAD5F /* RestoreImageURLInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4B32DF20301007EAD5F /* RestoreImageURLInputView.swift */; };
F453C4B92DF21985007EAD5F /* VMInstallData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4B82DF21985007EAD5F /* VMInstallData.swift */; };
F453C4BB2DF231BB007EAD5F /* PreventTerminationAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F453C4BA2DF231B7007EAD5F /* PreventTerminationAssertion.swift */; };
F45502142DF394DC005582A4 /* VirtualBuddyInstallerInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45502132DF394DC005582A4 /* VirtualBuddyInstallerInputView.swift */; };
F45502162DF45E53005582A4 /* VBSettings+CatalogDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45502152DF45E4D005582A4 /* VBSettings+CatalogDownload.swift */; };
F45502232DF463A1005582A4 /* UniversalMac_13.3.1_22E261_Restore.ipsw in Copy Preview Library Downloads */ = {isa = PBXBuildFile; fileRef = F45502182DF46368005582A4 /* UniversalMac_13.3.1_22E261_Restore.ipsw */; };
F45502242DF463A1005582A4 /* UniversalMac_14.0_23A344_Restore.ipsw in Copy Preview Library Downloads */ = {isa = PBXBuildFile; fileRef = F45502192DF46368005582A4 /* UniversalMac_14.0_23A344_Restore.ipsw */; };
F45502252DF463A1005582A4 /* UniversalMac_14.5_23F79_Restore.ipsw in Copy Preview Library Downloads */ = {isa = PBXBuildFile; fileRef = F455021A2DF46368005582A4 /* UniversalMac_14.5_23F79_Restore.ipsw */; };
F45502262DF463A1005582A4 /* UniversalMac_15.3_24D60_Restore.ipsw in Copy Preview Library Downloads */ = {isa = PBXBuildFile; fileRef = F455021B2DF46368005582A4 /* UniversalMac_15.3_24D60_Restore.ipsw */; };
F45502272DF463A1005582A4 /* UniversalMac_15.5_24F74_Restore.ipsw in Copy Preview Library Downloads */ = {isa = PBXBuildFile; fileRef = F455021C2DF46368005582A4 /* UniversalMac_15.5_24F74_Restore.ipsw */; };
F4561A6828981B4100055289 /* VirtualMachineNameInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4561A6728981B4100055289 /* VirtualMachineNameInputView.swift */; };
F462C9422E0C96D300C172E2 /* FB18383725Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = F462C9412E0C96D300C172E2 /* FB18383725Window.swift */; };
F465C3AE284F93A5006E9ED4 /* VBAPIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F465C3AD284F93A5006E9ED4 /* VBAPIClient.swift */; };
F465C3B0284F9660006E9ED4 /* VBRestoreImagesResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = F465C3AF284F9660006E9ED4 /* VBRestoreImagesResponse.swift */; };
F465C3B2284F9666006E9ED4 /* VBRestoreImageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = F465C3B1284F9666006E9ED4 /* VBRestoreImageInfo.swift */; };
F465C3B8284FA252006E9ED4 /* URLSessionDownloadBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = F465C3B7284FA252006E9ED4 /* URLSessionDownloadBackend.swift */; };
F46FFBA82804F07400D61023 /* VBNVRAMVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46FFBA72804F07400D61023 /* VBNVRAMVariable.swift */; };
F46FFBAA2804F0A000D61023 /* VZVirtualMachineConfiguration+NVRAM.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46FFBA92804F0A000D61023 /* VZVirtualMachineConfiguration+NVRAM.swift */; };
F46FFBAC28059FF600D61023 /* VMInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46FFBAB28059FF600D61023 /* VMInstance.swift */; };
F47BCDA12C5BE8FF00165191 /* ipsws_v2.json in Copy Software Catalog Feeds */ = {isa = PBXBuildFile; fileRef = F47BCD9F2C5BE8EF00165191 /* ipsws_v2.json */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
F47BCDA22C5BE8FF00165191 /* linux_v2.json in Copy Software Catalog Feeds */ = {isa = PBXBuildFile; fileRef = F47BCDA02C5BE8EF00165191 /* linux_v2.json */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
F47BCDCB2C5C01D100165191 /* BlurHashDecoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDCA2C5C01CE00165191 /* BlurHashDecoding.swift */; };
F47BCDCD2C5C01EF00165191 /* RemoteImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDCC2C5C01EF00165191 /* RemoteImage.swift */; };
F47BCDCF2C5C023E00165191 /* CatalogGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDCE2C5C023900165191 /* CatalogGroupView.swift */; };
F47BCDD12C5C06CE00165191 /* CatalogGroupPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDD02C5C06C900165191 /* CatalogGroupPicker.swift */; };
F47BCDD32C5C0AB300165191 /* KeyboardNavigationModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDD22C5C0AB300165191 /* KeyboardNavigationModifier.swift */; };
F47BCDD52C5C0B8F00165191 /* Array+Navigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDD42C5C0B8C00165191 /* Array+Navigation.swift */; };
F47BCDD72C5D2B4600165191 /* CatalogExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDD62C5D2B4300165191 /* CatalogExtensions.swift */; };
F47BCDD92C5D2EE300165191 /* RestoreImageBrowser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47BCDD82C5D2EDB00165191 /* RestoreImageBrowser.swift */; };
F485B91B2BB22D2D004B3C2B /* VBSavedStateMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F485B91A2BB22D2D004B3C2B /* VBSavedStateMetadata.swift */; };
F485B91D2BB2F0D9004B3C2B /* ProcessInfo+ECID.swift in Sources */ = {isa = PBXBuildFile; fileRef = F485B91C2BB2F0D9004B3C2B /* ProcessInfo+ECID.swift */; };
F485B91F2BB2F4AC004B3C2B /* Bundle+Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = F485B91E2BB2F4AC004B3C2B /* Bundle+Version.swift */; };
F485B9222BB306AF004B3C2B /* VBDebugUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = F485B9202BB306AF004B3C2B /* VBDebugUtil.h */; settings = {ATTRIBUTES = (Public, ); }; };
F485B9232BB306AF004B3C2B /* VBDebugUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = F485B9212BB306AF004B3C2B /* VBDebugUtil.m */; };
F48E0D03288858E00080DDFA /* ManagedDiskImageEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D02288858DF0080DDFA /* ManagedDiskImageEditor.swift */; };
F48E0D0728885E140080DDFA /* PreviewSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D0628885E140080DDFA /* PreviewSupport.swift */; };
F48E0D0C2888760D0080DDFA /* VBMacDevice+Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D0B2888760D0080DDFA /* VBMacDevice+Storage.swift */; };
F48E0D1A288882BD0080DDFA /* InstallationWizardTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D14288882BD0080DDFA /* InstallationWizardTitle.swift */; };
F48E0D1B288882BD0080DDFA /* InstallMethodPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D15288882BD0080DDFA /* InstallMethodPicker.swift */; };
F48E0D1C288882BD0080DDFA /* RestoreImageSelectionStep.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D16288882BD0080DDFA /* RestoreImageSelectionStep.swift */; };
F48E0D1D288882BD0080DDFA /* AuthenticatingWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D17288882BD0080DDFA /* AuthenticatingWebView.swift */; };
F48E0D1E288882BD0080DDFA /* VMInstallationWizard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D18288882BD0080DDFA /* VMInstallationWizard.swift */; };
F48E0D1F288882BD0080DDFA /* VMInstallationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D19288882BD0080DDFA /* VMInstallationViewModel.swift */; };
F48E0D23288882E50080DDFA /* DecentFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D20288882E50080DDFA /* DecentFormView.swift */; };
F48E0D24288882E50080DDFA /* NSAlert+Confirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D21288882E50080DDFA /* NSAlert+Confirmation.swift */; };
F48E0D25288882E50080DDFA /* OnAppearOnce.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D22288882E50080DDFA /* OnAppearOnce.swift */; };
F48E0D2A288883150080DDFA /* OpenCocoaWindowAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D27288883150080DDFA /* OpenCocoaWindowAction.swift */; };
F48E0D2B288883150080DDFA /* HostingWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D28288883150080DDFA /* HostingWindowController.swift */; };
F48E0D2C288883150080DDFA /* WindowEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D29288883150080DDFA /* WindowEnvironment.swift */; };
F48E0D2F2888835A0080DDFA /* VirtualUIConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D2E2888835A0080DDFA /* VirtualUIConstants.swift */; };
F48E0D32288884A10080DDFA /* RestoreImageDownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D31288884A10080DDFA /* RestoreImageDownloadView.swift */; };
F48E0D34288889E60080DDFA /* InstallConfigurationStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E0D33288889E60080DDFA /* InstallConfigurationStepView.swift */; };
F4959F3C2992A284001DF4CB /* GuestAppInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4959F3B2992A284001DF4CB /* GuestAppInstaller.swift */; };
F498AD012884BF13006F1C00 /* VirtualUI.h in Headers */ = {isa = PBXBuildFile; fileRef = F498AD002884BF13006F1C00 /* VirtualUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
F498AD042884BF13006F1C00 /* VirtualUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F498ACFE2884BF13006F1C00 /* VirtualUI.framework */; };
F498AD052884BF13006F1C00 /* VirtualUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F498ACFE2884BF13006F1C00 /* VirtualUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F498AD0C2884BF67006F1C00 /* VirtualCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4BE9C6527FF053A00B648F8 /* VirtualCore.framework */; };
F498AD0E2884BF9D006F1C00 /* VMConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F498AD0D2884BF9D006F1C00 /* VMConfigurationView.swift */; };
F498AD142884C36A006F1C00 /* NumericValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = F498AD112884C36A006F1C00 /* NumericValueField.swift */; };
F498AD162884C36A006F1C00 /* ControlGroupChrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = F498AD132884C36A006F1C00 /* ControlGroupChrome.swift */; };
F498AD182884C593006F1C00 /* NumericPropertyControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F498AD172884C593006F1C00 /* NumericPropertyControl.swift */; };
F498AD1A2884C5FF006F1C00 /* SliderConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F498AD192884C5FF006F1C00 /* SliderConversion.swift */; };
F49A68E12884917E00A17582 /* ConfigurationModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49A68E02884917E00A17582 /* ConfigurationModels.swift */; };
F49AA2C329BA22A5009625F7 /* VBRestorableWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49AA2C229BA22A5009625F7 /* VBRestorableWindow.swift */; };
F49AA2C529BA31CC009625F7 /* VirtualMachineSessionUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49AA2C429BA31CC009625F7 /* VirtualMachineSessionUI.swift */; };
F49AA2C729BA3F2B009625F7 /* VBRestorableWindow+Resizing.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49AA2C629BA3F2B009625F7 /* VBRestorableWindow+Resizing.swift */; };
F49B82982E02F5A900395F87 /* VMArtworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49B82972E02F5A300395F87 /* VMArtworkView.swift */; };
F49B82A82E0304D400395F87 /* PreviewMac.vbvm in Copy Preview Library */ = {isa = PBXBuildFile; fileRef = F49B829F2E02FCB100395F87 /* PreviewMac.vbvm */; };
F49B82A92E0304D400395F87 /* PreviewMacBlurHash.vbvm in Copy Preview Library */ = {isa = PBXBuildFile; fileRef = F49B829D2E02FCB100395F87 /* PreviewMacBlurHash.vbvm */; };
F49B82AA2E0304D400395F87 /* PreviewMacNoArtwork.vbvm in Copy Preview Library */ = {isa = PBXBuildFile; fileRef = F49B82A32E02FCF400395F87 /* PreviewMacNoArtwork.vbvm */; };
F49B82AB2E0304D400395F87 /* PreviewLinux.vbvm in Copy Preview Library */ = {isa = PBXBuildFile; fileRef = F49B829E2E02FCB100395F87 /* PreviewLinux.vbvm */; };
F49B82AC2E0304D400395F87 /* PreviewLinuxBlurHash.vbvm in Copy Preview Library */ = {isa = PBXBuildFile; fileRef = F49B82A52E03049C00395F87 /* PreviewLinuxBlurHash.vbvm */; };
F49B82AD2E0304D400395F87 /* PreviewLinuxNoArtwork.vbvm in Copy Preview Library */ = {isa = PBXBuildFile; fileRef = F49B82A62E03049C00395F87 /* PreviewLinuxNoArtwork.vbvm */; };
F49B82FC2E034EAD00395F87 /* WHDesktopPictureService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49B82FB2E034EAD00395F87 /* WHDesktopPictureService.swift */; };
F49B83002E034F6800395F87 /* NSImage+DesktopPicture.m in Sources */ = {isa = PBXBuildFile; fileRef = F49B82FF2E034F6800395F87 /* NSImage+DesktopPicture.m */; };
F49B83012E034F6800395F87 /* NSImage+DesktopPicture.h in Headers */ = {isa = PBXBuildFile; fileRef = F49B82FE2E034F6800395F87 /* NSImage+DesktopPicture.h */; settings = {ATTRIBUTES = (Public, ); }; };
F49B832B2E04593A00395F87 /* NSImage+DRMProtected.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49B832A2E04593100395F87 /* NSImage+DRMProtected.swift */; };
F49B832D2E046B8D00395F87 /* GuestAppConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49B832C2E046B8D00395F87 /* GuestAppConfigurationView.swift */; };
F49B83712E04837400395F87 /* CGImage+FullyTransparent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49B83702E04837400395F87 /* CGImage+FullyTransparent.swift */; };
F49FD87D2DFB68F50019D638 /* VMImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49FD87C2DFB68F20019D638 /* VMImporter.swift */; };
F49FD87F2DFB6B670019D638 /* VMImporterRegistry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49FD87E2DFB6B630019D638 /* VMImporterRegistry.swift */; };
F49FD8812DFB6CDD0019D638 /* UTMImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49FD8802DFB6CD80019D638 /* UTMImporter.swift */; };
F49FD8842DFB727B0019D638 /* VMImporter+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49FD8832DFB72790019D638 /* VMImporter+Helpers.swift */; };
F49FD8862DFB728A0019D638 /* UTMAppleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49FD8852DFB728A0019D638 /* UTMAppleConfiguration.swift */; };
F4A21BF228032FD8001072B8 /* VMLibraryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A21BF128032FD8001072B8 /* VMLibraryController.swift */; };
F4A21BF428033102001072B8 /* VBError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A21BF328033102001072B8 /* VBError.swift */; };
F4A7FB3B2BB5E79100E4C12A /* DirectoryObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A7FB3A2BB5E79100E4C12A /* DirectoryObserver.swift */; };
F4A7FB3D2BB5E8A200E4C12A /* VMSavedStatesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A7FB3C2BB5E8A200E4C12A /* VMSavedStatesController.swift */; };
F4A7FB3F2BB5EBEF00E4C12A /* SavedStatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A7FB3E2BB5EBEF00E4C12A /* SavedStatePicker.swift */; };
F4A7FB472BB5ED7E00E4C12A /* Save-2024-03-27_16;06;24.vbst in Copy Preview Saved States */ = {isa = PBXBuildFile; fileRef = F4A7FB402BB5ED4A00E4C12A /* Save-2024-03-27_16;06;24.vbst */; };
F4A7FB482BB5ED7E00E4C12A /* Save-2024-03-27_16;07;04.vbst in Copy Preview Saved States */ = {isa = PBXBuildFile; fileRef = F4A7FB412BB5ED4A00E4C12A /* Save-2024-03-27_16;07;04.vbst */; };
F4A7FB492BB5ED7E00E4C12A /* Save-2024-03-27_16;08;06.vbst in Copy Preview Saved States */ = {isa = PBXBuildFile; fileRef = F4A7FB422BB5ED4A00E4C12A /* Save-2024-03-27_16;08;06.vbst */; };
F4A7FB4A2BB5ED7E00E4C12A /* Save-2024-03-27_16;08;28.vbst in Copy Preview Saved States */ = {isa = PBXBuildFile; fileRef = F4A7FB432BB5ED4A00E4C12A /* Save-2024-03-27_16;08;28.vbst */; };
F4A7FB4B2BB5ED7E00E4C12A /* Save-2024-03-27_16;08;51.vbst in Copy Preview Saved States */ = {isa = PBXBuildFile; fileRef = F4A7FB442BB5ED4A00E4C12A /* Save-2024-03-27_16;08;51.vbst */; };
F4A7FB6E2BB7206C00E4C12A /* SelfSizingGroupedForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A7FB6D2BB7206C00E4C12A /* SelfSizingGroupedForm.swift */; };
F4A7FB732BB7238A00E4C12A /* SwiftUIIntrospect-Static in Frameworks */ = {isa = PBXBuildFile; productRef = F4A7FB722BB7238A00E4C12A /* SwiftUIIntrospect-Static */; };
F4A7FB752BB7252A00E4C12A /* PreviewSupport-VirtualUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A7FB742BB7252A00E4C12A /* PreviewSupport-VirtualUI.swift */; };
F4B5C5D32886FA8D005AA632 /* SharedFoldersManagementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B5C5D22886FA8D005AA632 /* SharedFoldersManagementView.swift */; };
F4B5C5D52886FFB5005AA632 /* PointingDeviceConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B5C5D42886FFB5005AA632 /* PointingDeviceConfigurationView.swift */; };
F4B5C5D728870619005AA632 /* ConfigurationModels+Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B5C5D628870619005AA632 /* ConfigurationModels+Validation.swift */; };
F4B5C5D928870BBF005AA632 /* ConfigurationModels+Summary.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B5C5D828870BBF005AA632 /* ConfigurationModels+Summary.swift */; };
F4B5C5DB28873628005AA632 /* GroupedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B5C5DA28873628005AA632 /* GroupedList.swift */; };
F4BE580E29BA6C8D00C5525C /* DefaultsDomains.plist in Resources */ = {isa = PBXBuildFile; fileRef = F4BE580D29BA6C8D00C5525C /* DefaultsDomains.plist */; };
F4BE581129BA6DFC00C5525C /* DefaultsImportController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE581029BA6DFC00C5525C /* DefaultsImportController.swift */; };
F4BE581329BA6E0D00C5525C /* DefaultsDomainDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE581229BA6E0D00C5525C /* DefaultsDomainDescriptor.swift */; };
F4BE584029BA7B7A00C5525C /* DefaultsDomain+ExportImport.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE583F29BA7B7A00C5525C /* DefaultsDomain+ExportImport.swift */; };
F4BE584229BA7BDB00C5525C /* WHDefaultsImportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE584129BA7BDB00C5525C /* WHDefaultsImportService.swift */; };
F4BE9C5227FF052100B648F8 /* VirtualBuddyApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE9C5127FF052100B648F8 /* VirtualBuddyApp.swift */; };
F4BE9C5627FF052100B648F8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4BE9C5527FF052100B648F8 /* Assets.xcassets */; };
F4BE9C5927FF052100B648F8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4BE9C5827FF052100B648F8 /* Preview Assets.xcassets */; };
F4BE9C6827FF053A00B648F8 /* VirtualCore.h in Headers */ = {isa = PBXBuildFile; fileRef = F4BE9C6727FF053A00B648F8 /* VirtualCore.h */; settings = {ATTRIBUTES = (Public, ); }; };
F4BE9C6B27FF053A00B648F8 /* VirtualCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4BE9C6527FF053A00B648F8 /* VirtualCore.framework */; };
F4BE9C6C27FF053A00B648F8 /* VirtualCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F4BE9C6527FF053A00B648F8 /* VirtualCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F4BE9C7627FF055100B648F8 /* VBVirtualMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE9C7327FF055100B648F8 /* VBVirtualMachine.swift */; };
F4BE9C7827FF055100B648F8 /* MacOSVirtualMachineConfigurationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE9C7527FF055100B648F8 /* MacOSVirtualMachineConfigurationHelper.swift */; };
F4BE9C7A27FF05B900B648F8 /* VMController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE9C7927FF05B900B648F8 /* VMController.swift */; };
F4BE9C8127FF111100B648F8 /* VirtualBuddyAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BE9C8027FF111100B648F8 /* VirtualBuddyAppDelegate.swift */; };
F4BE9C8627FF140F00B648F8 /* VirtualizationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F4BE9C8527FF13FF00B648F8 /* VirtualizationPrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
F4C189E32848F59F00335EC7 /* VirtualWormhole.h in Headers */ = {isa = PBXBuildFile; fileRef = F4C189E22848F59F00335EC7 /* VirtualWormhole.h */; settings = {ATTRIBUTES = (Public, ); }; };
F4C189E62848F59F00335EC7 /* VirtualWormhole.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C189E02848F59F00335EC7 /* VirtualWormhole.framework */; };
F4C189E72848F59F00335EC7 /* VirtualWormhole.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F4C189E02848F59F00335EC7 /* VirtualWormhole.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F4C189EE2848F5B500335EC7 /* WormholeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C189ED2848F5B500335EC7 /* WormholeManager.swift */; };
F4C189F22848F5F500335EC7 /* VirtualWormhole.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C189E02848F59F00335EC7 /* VirtualWormhole.framework */; settings = {ATTRIBUTES = (Required, ); }; };
F4C189F72848F6A600335EC7 /* VirtualCoreConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C189F62848F6A600335EC7 /* VirtualCoreConstants.swift */; };
F4C189FA2848F6F700335EC7 /* VirtualWormholeConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C189F92848F6F700335EC7 /* VirtualWormholeConstants.swift */; };
F4C189FD2848F8F600335EC7 /* WHSharedClipboardService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C189FC2848F8F600335EC7 /* WHSharedClipboardService.swift */; };
F4C189FF2848FB3F00335EC7 /* WormholeServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C189FE2848FB3F00335EC7 /* WormholeServiceProtocol.swift */; };
F4C18A4528491B8500335EC7 /* GuestAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C18A4428491B8500335EC7 /* GuestAppDelegate.swift */; };
F4C18A4728491B8500335EC7 /* GuestDashboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C18A4628491B8500335EC7 /* GuestDashboard.swift */; };
F4C18A4928491B8500335EC7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4C18A4828491B8500335EC7 /* Assets.xcassets */; };
F4C18A4C28491B8500335EC7 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4C18A4B28491B8500335EC7 /* Preview Assets.xcassets */; };
F4C18A5228491B9D00335EC7 /* VirtualWormhole.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C189E02848F59F00335EC7 /* VirtualWormhole.framework */; };
F4C18A5328491B9D00335EC7 /* VirtualWormhole.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F4C189E02848F59F00335EC7 /* VirtualWormhole.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F4C2374D2888A462001FF286 /* VolumeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C2374C2888A462001FF286 /* VolumeUtils.swift */; };
F4C237502888AF67001FF286 /* LogStreamer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C2374F2888AF67001FF286 /* LogStreamer.swift */; };
F4C947BF2E0B0F71001ACC91 /* URL+ExtendedAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C947BE2E0B0F71001ACC91 /* URL+ExtendedAttributes.swift */; };
F4C947D62E0B12D0001ACC91 /* String+AppleOSBuild.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C947D52E0B12D0001ACC91 /* String+AppleOSBuild.swift */; };
F4C947DA2E0B1E5D001ACC91 /* SoftwareCatalog+DownloadMatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C947D92E0B1E5D001ACC91 /* SoftwareCatalog+DownloadMatching.swift */; };
F4CD13202E05A5780067DC75 /* FileSystemPathFormControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD131F2E05A5780067DC75 /* FileSystemPathFormControl.swift */; };
F4CD133C2E05A9DF0067DC75 /* OpenVirtualBuddySettingsAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD133B2E05A9DF0067DC75 /* OpenVirtualBuddySettingsAction.swift */; };
F4CD133E2E05AB280067DC75 /* BackwardsCompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD133D2E05AB280067DC75 /* BackwardsCompatibility.swift */; };
F4CD13402E05AB8F0067DC75 /* GeneralSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD133F2E05AB8F0067DC75 /* GeneralSettingsView.swift */; };
F4CD13442E05AD400067DC75 /* VerticalLabeledContentStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD13432E05AD400067DC75 /* VerticalLabeledContentStyle.swift */; };
F4CD13462E05B4DE0067DC75 /* VirtualizationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD13452E05B4DE0067DC75 /* VirtualizationSettingsView.swift */; };
F4CD13482E05B67E0067DC75 /* SettingsFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD13472E05B67E0067DC75 /* SettingsFooter.swift */; };
F4CD134A2E05CB390067DC75 /* AutomationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CD13492E05CB390067DC75 /* AutomationSettingsView.swift */; };
F4D0F71528667984004D5782 /* VBVirtualMachine+Screenshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D0F71428667984004D5782 /* VBVirtualMachine+Screenshot.swift */; };
F4D0F71828674E4B004D5782 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = F4D0F71728674E4B004D5782 /* Sparkle */; };
F4D0F71A28674E76004D5782 /* SoftwareUpdateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D0F71928674E76004D5782 /* SoftwareUpdateController.swift */; };
F4D0F71F2867517A004D5782 /* AppUpdateChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D0F71E2867517A004D5782 /* AppUpdateChannel.swift */; };
F4D3059729B8D9D30006E748 /* WormholePacket.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D3059629B8D9D30006E748 /* WormholePacket.swift */; };
F4D3059F29B8DB700006E748 /* WormholePacketTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D3059E29B8DB700006E748 /* WormholePacketTests.swift */; };
F4D305A029B8DB700006E748 /* VirtualWormhole.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C189E02848F59F00335EC7 /* VirtualWormhole.framework */; };
F4D305AA29B8E7120006E748 /* TestStream.bin in Resources */ = {isa = PBXBuildFile; fileRef = F4D305A929B8E7120006E748 /* TestStream.bin */; };
F4D305AC29B8FEE90006E748 /* WHDarwinNotificationsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D305AB29B8FEE90006E748 /* WHDarwinNotificationsService.swift */; };
F4D305B029B900860006E748 /* SystemNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D305AF29B900860006E748 /* SystemNotification.swift */; };
F4D305B229B907A10006E748 /* WHPing.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D305B129B907A10006E748 /* WHPing.swift */; };
F4D725FE286677B8001818F7 /* VBVirtualMachine+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D725FD286677B8001818F7 /* VBVirtualMachine+Metadata.swift */; };
F4DE1C0B2D6F54E700603527 /* VBSavedStateMetadata+Clone.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DE1C0A2D6F54E000603527 /* VBSavedStateMetadata+Clone.swift */; };
F4DE1C0F2D6F603300603527 /* VBSavedStatePackage+VM.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DE1C0E2D6F603300603527 /* VBSavedStatePackage+VM.swift */; };
F4DE1C112D6F642E00603527 /* VBStorageDeviceContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DE1C102D6F642E00603527 /* VBStorageDeviceContainer.swift */; };
F4E4F6C52DEF96C200B3B8BA /* ChromeBorderModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E4F6C42DEF96C200B3B8BA /* ChromeBorderModifier.swift */; };
F4E4F7202DF080FC00B3B8BA /* RestoreImageSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E4F71F2DF080FC00B3B8BA /* RestoreImageSelectionController.swift */; };
F4E4F7262DF0A1CB00B3B8BA /* BuddyKit in Frameworks */ = {isa = PBXBuildFile; productRef = F4E4F7252DF0A1CB00B3B8BA /* BuddyKit */; };
F4E7680A29B64C590075A897 /* GuestTypePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E7680929B64C590075A897 /* GuestTypePicker.swift */; };
F4E7680D29B651220075A897 /* VirtualUI.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4E7680C29B651220075A897 /* VirtualUI.xcassets */; };
F4E7680F29B655DD0075A897 /* InstallMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E7680E29B655DD0075A897 /* InstallMethod.swift */; };
F4E7DF922BB3338900C459FC /* NSImage+HEIC.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E7DF912BB3338900C459FC /* NSImage+HEIC.swift */; };
F4E7DF952BB336F600C459FC /* VBSavedStatePackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E7DF942BB336F600C459FC /* VBSavedStatePackage.swift */; };
F4E7DF972BB33E1700C459FC /* VMLibraryController+SavedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E7DF962BB33E1700C459FC /* VMLibraryController+SavedState.swift */; };
F4E7DFCF2BB3587D00C459FC /* VirtualMachineSessionUIManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E7DFCE2BB3587D00C459FC /* VirtualMachineSessionUIManager.swift */; };
F4ECC6D52C63BFD5001DAC1D /* NumberDisplayMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4ECC6D42C63BFD5001DAC1D /* NumberDisplayMode.swift */; };
F4F9B416284CE0F900F21737 /* VBSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F9B415284CE0F900F21737 /* VBSettings.swift */; };
F4F9B418284CE12000F21737 /* VBSettingsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F9B417284CE12000F21737 /* VBSettingsContainer.swift */; };
F4F9B41A284CE37C00F21737 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F9B419284CE37C00F21737 /* Logging.swift */; };
F4FC276729BBAE350012CB65 /* WormholeServiceClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FC276629BBAE350012CB65 /* WormholeServiceClient.swift */; };
F4FC276A29BBAE590012CB65 /* WHDefaultsImportClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FC276929BBAE590012CB65 /* WHDefaultsImportClient.swift */; };
F4FC276C29BBB3030012CB65 /* GuestDefaultsImportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FC276B29BBB3030012CB65 /* GuestDefaultsImportView.swift */; };
F4FC98392BB386A000E511C9 /* ContinuousProgressIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FC98382BB386A000E511C9 /* ContinuousProgressIndicator.swift */; };
F4FC983B2BB386B500E511C9 /* MaskProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FC983A2BB386B500E511C9 /* MaskProgressView.swift */; };
F4FC983D2BB386DD00E511C9 /* VMProgressOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FC983C2BB386DD00E511C9 /* VMProgressOverlay.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
F413699C299179F8002CE8D3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4BE9C6427FF053A00B648F8;
remoteInfo = VirtualCore;
};
F41369BC29918617002CE8D3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F41369AA29918576002CE8D3;
remoteInfo = VirtualBuddyGuestHelper;
};
F42862302AE87D7E0052F029 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F43B01142AD858FE00164CD1;
remoteInfo = DeepLinkSecurity;
};
F4510A792AE2B3AB00E24DD9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F43B01142AD858FE00164CD1;
remoteInfo = DeepLinkSecurity;
};
F453C4262DF0B602007EAD5F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F498ACFD2884BF13006F1C00;
remoteInfo = VirtualUI;
};
F453C4582DF0BCEB007EAD5F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4BE9C4D27FF052100B648F8;
remoteInfo = VirtualBuddy;
};
F498AD022884BF13006F1C00 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F498ACFD2884BF13006F1C00;
remoteInfo = VirtualUI;
};
F498AD0A2884BF60006F1C00 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4BE9C6427FF053A00B648F8;
remoteInfo = VirtualCore;
};
F4C189EF2848F5F100335EC7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4C189DF2848F59F00335EC7;
remoteInfo = VirtualWormhole;
};
F4C18A5428491B9D00335EC7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4C189DF2848F59F00335EC7;
remoteInfo = VirtualWormhole;
};
F4C18A5728491C0D00335EC7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4C18A4128491B8500335EC7;
remoteInfo = VirtualBuddyGuest;
};
F4D305A129B8DB700006E748 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F4BE9C4627FF052100B648F8 /* Project object */;
proxyType = 1;
remoteGlobalIDString = F4C189DF2848F59F00335EC7;
remoteInfo = VirtualWormhole;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
F41369BE2991861C002CE8D3 /* Embed Login Item */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = Contents/Library/LoginItems;
dstSubfolderSpec = 1;
files = (
F41369BF2991863A002CE8D3 /* VirtualBuddyGuestHelper.app in Embed Login Item */,
);
name = "Embed Login Item";
runOnlyForDeploymentPostprocessing = 0;
};
F443620B29B79A5800745B43 /* Embed Guest App */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 12;
files = (
F443620C29B79A6800745B43 /* VirtualBuddyGuest.app in Embed Guest App */,
);
name = "Embed Guest App";
runOnlyForDeploymentPostprocessing = 0;
};
F45502222DF46386005582A4 /* Copy Preview Library Downloads */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = PreviewLibrary/_Downloads;
dstSubfolderSpec = 7;
files = (
F45502232DF463A1005582A4 /* UniversalMac_13.3.1_22E261_Restore.ipsw in Copy Preview Library Downloads */,
F45502242DF463A1005582A4 /* UniversalMac_14.0_23A344_Restore.ipsw in Copy Preview Library Downloads */,
F45502252DF463A1005582A4 /* UniversalMac_14.5_23F79_Restore.ipsw in Copy Preview Library Downloads */,
F45502262DF463A1005582A4 /* UniversalMac_15.3_24D60_Restore.ipsw in Copy Preview Library Downloads */,
F45502272DF463A1005582A4 /* UniversalMac_15.5_24F74_Restore.ipsw in Copy Preview Library Downloads */,
);
name = "Copy Preview Library Downloads";
runOnlyForDeploymentPostprocessing = 0;
};
F47BCD9C2C5BE89E00165191 /* Copy Software Catalog Feeds */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = SoftwareCatalog;
dstSubfolderSpec = 7;
files = (
F47BCDA12C5BE8FF00165191 /* ipsws_v2.json in Copy Software Catalog Feeds */,
F47BCDA22C5BE8FF00165191 /* linux_v2.json in Copy Software Catalog Feeds */,
);
name = "Copy Software Catalog Feeds";
runOnlyForDeploymentPostprocessing = 0;
};
F4A7FB462BB5ED6400E4C12A /* Copy Preview Saved States */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = PreviewLibrary/_SavedStates;
dstSubfolderSpec = 7;
files = (
F4A7FB472BB5ED7E00E4C12A /* Save-2024-03-27_16;06;24.vbst in Copy Preview Saved States */,
F4A7FB482BB5ED7E00E4C12A /* Save-2024-03-27_16;07;04.vbst in Copy Preview Saved States */,
F4A7FB492BB5ED7E00E4C12A /* Save-2024-03-27_16;08;06.vbst in Copy Preview Saved States */,
F4A7FB4A2BB5ED7E00E4C12A /* Save-2024-03-27_16;08;28.vbst in Copy Preview Saved States */,
F4A7FB4B2BB5ED7E00E4C12A /* Save-2024-03-27_16;08;51.vbst in Copy Preview Saved States */,
);
name = "Copy Preview Saved States";
runOnlyForDeploymentPostprocessing = 0;
};
F4A7FB4C2BB5F0B700E4C12A /* Copy Preview Library */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = PreviewLibrary;
dstSubfolderSpec = 7;
files = (
F49B82A82E0304D400395F87 /* PreviewMac.vbvm in Copy Preview Library */,
F49B82A92E0304D400395F87 /* PreviewMacBlurHash.vbvm in Copy Preview Library */,
F49B82AA2E0304D400395F87 /* PreviewMacNoArtwork.vbvm in Copy Preview Library */,
F49B82AB2E0304D400395F87 /* PreviewLinux.vbvm in Copy Preview Library */,
F49B82AC2E0304D400395F87 /* PreviewLinuxBlurHash.vbvm in Copy Preview Library */,
F49B82AD2E0304D400395F87 /* PreviewLinuxNoArtwork.vbvm in Copy Preview Library */,
);
name = "Copy Preview Library";
runOnlyForDeploymentPostprocessing = 0;
};
F4BE9C7027FF053A00B648F8 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
F4BE9C6C27FF053A00B648F8 /* VirtualCore.framework in Embed Frameworks */,
F498AD052884BF13006F1C00 /* VirtualUI.framework in Embed Frameworks */,
F43B011C2AD858FE00164CD1 /* DeepLinkSecurity.framework in Embed Frameworks */,
F4C189E72848F59F00335EC7 /* VirtualWormhole.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
F4C18A5628491B9D00335EC7 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
F453C4252DF0B602007EAD5F /* VirtualUI.framework in Embed Frameworks */,
F4C18A5328491B9D00335EC7 /* VirtualWormhole.framework in Embed Frameworks */,
F428622F2AE87D7E0052F029 /* DeepLinkSecurity.framework in Embed Frameworks */,
F413699B299179F8002CE8D3 /* VirtualCore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0196B45229292B2A00614EF1 /* LinuxVirtualMachineConfigurationHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxVirtualMachineConfigurationHelper.swift; sourceTree = "<group>"; };
4BA6BE7C293D22E500F396AE /* VirtualMachineConfigurationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VirtualMachineConfigurationHelper.swift; sourceTree = "<group>"; };
F40A1E9C2C1873C60033E47D /* VBBuildType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VBBuildType.swift; sourceTree = "<group>"; };
F413695129916F6E002CE8D3 /* StatusItemButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusItemButton.swift; sourceTree = "<group>"; };
F413695229916F6E002CE8D3 /* StatusBarPanelChrome.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = s
gitextract_fi8xynku/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── DeepLinkSecurity/
│ ├── DeepLinkSecurity.h
│ └── Source/
│ ├── Base/
│ │ └── DeepLinkSecurityDefines.swift
│ ├── DeepLinkSentinel.swift
│ ├── Models/
│ │ ├── DeepLinkClient.swift
│ │ ├── DeepLinkClientDescriptor.swift
│ │ ├── Extensions/
│ │ │ ├── DeepLinkClient+Crypto.swift
│ │ │ └── DeepLinkClientDescriptor+.swift
│ │ └── OpenDeepLinkRequest.swift
│ ├── Storage/
│ │ ├── DeepLinkAuthStore.swift
│ │ ├── DeepLinkManagementStore.swift
│ │ ├── KeychainDeepLinkAuthStore.swift
│ │ ├── MemoryDeepLinkAuthStore.swift
│ │ └── UserDefaultsDeepLinkManagementStore.swift
│ └── UI/
│ └── DeepLinkAuthUI.swift
├── LICENSE
├── README.md
├── ReleaseNotes/
│ ├── VirtualBuddy 1.2 Release Nodes.md
│ ├── VirtualBuddy 1.2.1 Release Notes.md
│ └── VirtualBuddy 1.2.2 Release Notes.md
├── VirtualBuddy/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Default.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-Dev.appiconset/
│ │ │ └── Contents.json
│ │ ├── AppIcon-zBeta.appiconset/
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Automation/
│ │ ├── DeepLinkHandler.swift
│ │ ├── Support/
│ │ │ └── DeepLinkAuthDialog.swift
│ │ └── VirtualBuddyDeepLinks.swift
│ ├── Bootstrap/
│ │ ├── SoftwareUpdateController.swift
│ │ ├── VirtualBuddyApp.swift
│ │ ├── VirtualBuddyAppDelegate.swift
│ │ └── VirtualBuddyEntryPoint.swift
│ ├── CommandLine/
│ │ ├── VirtualBuddyCLI.swift
│ │ └── vctool/
│ │ ├── BlurHashCommand.swift
│ │ ├── CatalogCommand.swift
│ │ ├── Core/
│ │ │ ├── BuildManifest+Fetch.swift
│ │ │ ├── BuildManifest.swift
│ │ │ ├── Helpers.swift
│ │ │ ├── TreeStringConvertible.swift
│ │ │ └── URL+ContentLength.swift
│ │ ├── GroupCommand.swift
│ │ ├── IPSWCommand.swift
│ │ ├── ImageCommand.swift
│ │ ├── MigrateCommand.swift
│ │ ├── MobileDeviceCommand.swift
│ │ ├── ResolveCommand.swift
│ │ └── VCTool.swift
│ ├── Config/
│ │ ├── AppTarget.xcconfig
│ │ ├── Entitlements/
│ │ │ ├── VirtualBuddy.entitlements
│ │ │ └── VirtualBuddy_Managed.entitlements
│ │ ├── Features.xcconfig
│ │ ├── InfoPlist.xcconfig
│ │ ├── Main.xcconfig
│ │ ├── Paths.xcconfig
│ │ ├── Signing.xcconfig
│ │ └── Versions.xcconfig
│ ├── Info.plist
│ └── Preview Content/
│ └── Preview Assets.xcassets/
│ └── Contents.json
├── VirtualBuddy.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata/
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm/
│ │ └── Package.resolved
│ └── xcshareddata/
│ ├── xcdebugger/
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes/
│ ├── DeepLinkSecurity.xcscheme
│ ├── VirtualBuddy (Dev Release).xcscheme
│ ├── VirtualBuddy (Managed - Beta).xcscheme
│ ├── VirtualBuddy (Managed).xcscheme
│ ├── VirtualBuddy.xcscheme
│ ├── VirtualBuddyGuest.xcscheme
│ ├── VirtualCore.xcscheme
│ ├── VirtualUI.xcscheme
│ ├── VirtualWormhole.xcscheme
│ └── vctool.xcscheme
├── VirtualBuddyGuest/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── StatusItem.imageset/
│ │ └── Contents.json
│ ├── Dashboard/
│ │ ├── GuestDashboard.swift
│ │ ├── GuestDefaultsImportView.swift
│ │ ├── GuestSharedFoldersManager.swift
│ │ ├── HostConnectionStateProvider.swift
│ │ └── Support/
│ │ ├── GuestLaunchAtLoginManager.swift
│ │ └── VirtualBuddyGuest-Bridging-Header.h
│ ├── GuestAppDelegate.swift
│ ├── GuestAppInstaller.swift
│ ├── Main.storyboard
│ ├── Preview Content/
│ │ └── Preview Assets.xcassets/
│ │ └── Contents.json
│ └── VirtualBuddyGuest.entitlements
├── VirtualBuddyGuestHelper/
│ ├── Assets.xcassets/
│ │ ├── AccentColor.colorset/
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj/
│ │ └── Main.storyboard
│ ├── GuestHelperAppDelegate.swift
│ └── VirtualBuddyGuestHelper.entitlements
├── VirtualCore/
│ ├── Source/
│ │ ├── Definitions/
│ │ │ ├── Logging.swift
│ │ │ ├── PreviewSupport.swift
│ │ │ └── VirtualCoreConstants.swift
│ │ ├── GuestSupport/
│ │ │ ├── CreateGuestImage.sh
│ │ │ └── GuestAdditionsDiskImage.swift
│ │ ├── Headers/
│ │ │ └── VirtualizationPrivate.h
│ │ ├── Import/
│ │ │ ├── UTM/
│ │ │ │ ├── UTMAppleConfiguration.swift
│ │ │ │ └── UTMImporter.swift
│ │ │ ├── VMImporter+Helpers.swift
│ │ │ ├── VMImporter.swift
│ │ │ └── VMImporterRegistry.swift
│ │ ├── Models/
│ │ │ ├── BlurHashToken.swift
│ │ │ ├── Configuration/
│ │ │ │ ├── ConfigurationModels+Summary.swift
│ │ │ │ ├── ConfigurationModels+Validation.swift
│ │ │ │ ├── ConfigurationModels.swift
│ │ │ │ ├── DecodableDefault.swift
│ │ │ │ └── VBMacDevice+Storage.swift
│ │ │ ├── SavedState/
│ │ │ │ ├── VBSavedStateMetadata+Clone.swift
│ │ │ │ ├── VBSavedStateMetadata.swift
│ │ │ │ ├── VBSavedStatePackage+VM.swift
│ │ │ │ ├── VBSavedStatePackage.swift
│ │ │ │ └── VMLibraryController+SavedState.swift
│ │ │ ├── VBError.swift
│ │ │ ├── VBNVRAMVariable.swift
│ │ │ ├── VBStorageDeviceContainer.swift
│ │ │ ├── VBVirtualMachine+Metadata.swift
│ │ │ ├── VBVirtualMachine+Screenshot.swift
│ │ │ └── VBVirtualMachine.swift
│ │ ├── ReleaseTrains/
│ │ │ ├── AppUpdateChannel.swift
│ │ │ └── VBBuildType.swift
│ │ ├── Resources/
│ │ │ ├── Preview/
│ │ │ │ ├── FakeRestoreImage.ipsw
│ │ │ │ ├── PreviewLinux.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ ├── Metadata.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewLinuxBlurHash.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewLinuxNoArtwork.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewMac.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ ├── Metadata.plist
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewMacBlurHash.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewMacNoArtwork.vbvm/
│ │ │ │ │ ├── .vbdata/
│ │ │ │ │ │ ├── Config.plist
│ │ │ │ │ │ └── Metadata.plist
│ │ │ │ │ └── Disk.img
│ │ │ │ ├── PreviewSavedStates/
│ │ │ │ │ ├── Save-2024-03-27_16;06;24.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ ├── Save-2024-03-27_16;07;04.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ ├── Save-2024-03-27_16;08;06.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ ├── Save-2024-03-27_16;08;28.vbst/
│ │ │ │ │ │ ├── Info.plist
│ │ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ │ └── Thumbnail.heic
│ │ │ │ │ └── Save-2024-03-27_16;08;51.vbst/
│ │ │ │ │ ├── Info.plist
│ │ │ │ │ ├── Screenshot.heic
│ │ │ │ │ └── Thumbnail.heic
│ │ │ │ └── _Downloads/
│ │ │ │ ├── UniversalMac_13.3.1_22E261_Restore.ipsw
│ │ │ │ ├── UniversalMac_14.0_23A344_Restore.ipsw
│ │ │ │ ├── UniversalMac_14.5_23F79_Restore.ipsw
│ │ │ │ ├── UniversalMac_15.3_24D60_Restore.ipsw
│ │ │ │ └── UniversalMac_15.5_24F74_Restore.ipsw
│ │ │ └── VirtualCore.xcassets/
│ │ │ ├── Adjectives.dataset/
│ │ │ │ ├── Adjectives.txt
│ │ │ │ └── Contents.json
│ │ │ ├── Animals.dataset/
│ │ │ │ ├── Animals.txt
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── Restore/
│ │ │ ├── Download/
│ │ │ │ ├── DownloadBackend.swift
│ │ │ │ ├── SimulatedDownloadBackend.swift
│ │ │ │ └── URLSessionDownloadBackend.swift
│ │ │ └── Installation/
│ │ │ ├── RestoreBackend.swift
│ │ │ ├── SimulatedRestoreBackend.swift
│ │ │ └── VirtualizationRestoreBackend.swift
│ │ ├── Restore Images/
│ │ │ ├── Models/
│ │ │ │ ├── VBRestoreImageInfo.swift
│ │ │ │ └── VBRestoreImagesResponse.swift
│ │ │ └── VBAPIClient.swift
│ │ ├── Settings/
│ │ │ ├── VBSettings+CatalogDownload.swift
│ │ │ ├── VBSettings.swift
│ │ │ └── VBSettingsContainer.swift
│ │ ├── Utilities/
│ │ │ ├── Bundle+Version.swift
│ │ │ ├── LogStreamer.swift
│ │ │ ├── PreventTerminationAssertion.swift
│ │ │ ├── ProcessInfo+ECID.swift
│ │ │ ├── VBMemoryLeakDebugAssertions.swift
│ │ │ ├── VolumeUtils.swift
│ │ │ └── WeakReference.swift
│ │ ├── VirtualCatalog/
│ │ │ ├── LegacyCatalog.swift
│ │ │ ├── MobileDeviceFramework.swift
│ │ │ ├── README.md
│ │ │ ├── ResolvedCatalog.swift
│ │ │ ├── SoftwareCatalog+DownloadMatching.swift
│ │ │ ├── SoftwareCatalog.swift
│ │ │ └── Utilities/
│ │ │ ├── BlurHashEncode.swift
│ │ │ ├── String+AppleOSBuild.swift
│ │ │ └── URL+ExtendedAttributes.swift
│ │ └── Virtualization/
│ │ ├── Helpers/
│ │ │ ├── CatalogExtensions.swift
│ │ │ ├── DirectoryObserver.swift
│ │ │ ├── DiskImageGenerator.swift
│ │ │ ├── LinuxVirtualMachineConfigurationHelper.swift
│ │ │ ├── MacOSVirtualMachineConfigurationHelper.swift
│ │ │ ├── RandomNameGenerator.swift
│ │ │ ├── VBDebugUtil.h
│ │ │ ├── VBDebugUtil.m
│ │ │ ├── VZVirtualMachineConfiguration+NVRAM.swift
│ │ │ └── VirtualMachineConfigurationHelper.swift
│ │ ├── Screenshot/
│ │ │ ├── NSImage+DRMProtected.swift
│ │ │ └── NSImage+HEIC.swift
│ │ ├── VBVirtualMachine+Virtualization.swift
│ │ ├── VMController.swift
│ │ ├── VMInstance.swift
│ │ ├── VMLibraryController.swift
│ │ └── VMSavedStatesController.swift
│ └── VirtualCore.h
├── VirtualUI/
│ ├── Resources/
│ │ ├── CatalogGroupPlaceholder.heic
│ │ └── VirtualUI.xcassets/
│ │ ├── Contents.json
│ │ ├── FirstLaunchExperience.dataset/
│ │ │ ├── Contents.json
│ │ │ └── FirstLaunchExperience.caar
│ │ ├── FullBleedBlurHash.dataset/
│ │ │ ├── Contents.json
│ │ │ └── FullBleedBlurHash.caar
│ │ ├── GuestSymbol.imageset/
│ │ │ └── Contents.json
│ │ ├── StatusItemPanelChromeBorder.colorset/
│ │ │ └── Contents.json
│ │ ├── ThumbnailPlaceholder.imageset/
│ │ │ └── Contents.json
│ │ ├── VBGuestType/
│ │ │ ├── Contents.json
│ │ │ ├── linux.imageset/
│ │ │ │ └── Contents.json
│ │ │ └── mac.imageset/
│ │ │ └── Contents.json
│ │ ├── VirtualBuddyMono.imageset/
│ │ │ └── Contents.json
│ │ ├── VirtualBuddyMonoHappy.imageset/
│ │ │ └── Contents.json
│ │ └── VirtualBuddyMonoSad.imageset/
│ │ └── Contents.json
│ ├── Source/
│ │ ├── Building Blocks/
│ │ │ ├── CGFloat+OnePixel.swift
│ │ │ ├── ChromeBorderModifier.swift
│ │ │ ├── Configuration Controls/
│ │ │ │ ├── EphemeralTextField.swift
│ │ │ │ ├── NumericPropertyControl.swift
│ │ │ │ ├── NumericValueField.swift
│ │ │ │ ├── PropertyControl.swift
│ │ │ │ └── SharedFocusEnvironment.swift
│ │ │ ├── ControlGroupChrome.swift
│ │ │ └── SliderConversion.swift
│ │ ├── Components/
│ │ │ ├── Array+Navigation.swift
│ │ │ ├── BackportedContentUnavailableView.swift
│ │ │ ├── BlurHash/
│ │ │ │ └── BlurHashDecoding.swift
│ │ │ ├── CALayer+Asset.swift
│ │ │ ├── DecentFormView.swift
│ │ │ ├── EqualWidthHStack.swift
│ │ │ ├── HostingWindowController/
│ │ │ │ ├── FB18383725Window.swift
│ │ │ │ ├── HostingWindowController.swift
│ │ │ │ ├── OpenCocoaWindowAction.swift
│ │ │ │ ├── VBRestorableWindow+Resizing.swift
│ │ │ │ ├── VBRestorableWindow.swift
│ │ │ │ └── WindowEnvironment.swift
│ │ │ ├── KeyboardNavigationModifier.swift
│ │ │ ├── LogConsole.swift
│ │ │ ├── MaterialView.swift
│ │ │ ├── NSAlert+Confirmation.swift
│ │ │ ├── OnAppearOnce.swift
│ │ │ ├── OpenSavePanelUtils.swift
│ │ │ ├── RemoteImage/
│ │ │ │ └── RemoteImage.swift
│ │ │ ├── SelfSizingGroupedForm.swift
│ │ │ ├── SwiftUI Status Item/
│ │ │ │ ├── Components/
│ │ │ │ │ ├── Cocoa/
│ │ │ │ │ │ ├── StatusBarContentPanel.swift
│ │ │ │ │ │ ├── StatusBarHighlightView.swift
│ │ │ │ │ │ ├── StatusItemMenuBarExtraView.swift
│ │ │ │ │ │ ├── StatusItemPanelContentController.swift
│ │ │ │ │ │ └── VUIAppKitViewControllerHost.swift
│ │ │ │ │ ├── ObjC/
│ │ │ │ │ │ ├── NSApplication+MenuBar.h
│ │ │ │ │ │ ├── NSApplication+MenuBar.m
│ │ │ │ │ │ ├── NSStatusBarPrivate.h
│ │ │ │ │ │ ├── NSStatusItem+.h
│ │ │ │ │ │ └── NSStatusItem+.m
│ │ │ │ │ ├── ScreenChangeModifier.swift
│ │ │ │ │ ├── StatusBarPanelChrome.swift
│ │ │ │ │ ├── StatusItemButton.swift
│ │ │ │ │ └── StatusItemProviderProtocol.swift
│ │ │ │ └── StatusItemManager.swift
│ │ │ └── VMArtworkView.swift
│ │ ├── Definitions/
│ │ │ ├── PreviewSupport-VirtualUI.swift
│ │ │ └── VirtualUIConstants.swift
│ │ ├── Installer/
│ │ │ ├── Components/
│ │ │ │ ├── AuthenticatingWebView.swift
│ │ │ │ ├── InstallationConsole.swift
│ │ │ │ ├── InstallationWizardTitle.swift
│ │ │ │ ├── RestoreImageURLInputView.swift
│ │ │ │ ├── VirtualBuddyInstallerInputView.swift
│ │ │ │ └── VirtualMachineNameInputView.swift
│ │ │ ├── Steps/
│ │ │ │ ├── GuestTypePicker.swift
│ │ │ │ ├── InstallConfigurationStepView.swift
│ │ │ │ ├── InstallMethod.swift
│ │ │ │ ├── InstallMethodPicker.swift
│ │ │ │ ├── InstallProgressStepView.swift
│ │ │ │ ├── Restore Image Selection/
│ │ │ │ │ ├── Components/
│ │ │ │ │ │ ├── BlurHashFullBleedBackground.swift
│ │ │ │ │ │ ├── CatalogGroupPicker.swift
│ │ │ │ │ │ ├── CatalogGroupView.swift
│ │ │ │ │ │ ├── InstallProgressDisplayView.swift
│ │ │ │ │ │ ├── RestoreImageBrowser.swift
│ │ │ │ │ │ ├── SoftwareCatalog+Placeholder.swift
│ │ │ │ │ │ ├── VirtualBuddyMonoIcon.swift
│ │ │ │ │ │ ├── VirtualBuddyMonoProgressView.swift
│ │ │ │ │ │ └── VirtualDisplayView.swift
│ │ │ │ │ ├── RestoreImageSelectionController.swift
│ │ │ │ │ └── RestoreImageSelectionStep.swift
│ │ │ │ └── RestoreImageDownloadView.swift
│ │ │ ├── VMInstallData.swift
│ │ │ ├── VMInstallationViewModel.swift
│ │ │ └── VMInstallationWizard.swift
│ │ ├── Library/
│ │ │ ├── Components/
│ │ │ │ ├── FirstLaunchExperienceView.swift
│ │ │ │ └── LibraryItemView.swift
│ │ │ └── LibraryView.swift
│ │ ├── Session/
│ │ │ ├── Components/
│ │ │ │ ├── ContinuousProgressIndicator.swift
│ │ │ │ ├── MaskProgressView.swift
│ │ │ │ ├── NumberDisplayMode.swift
│ │ │ │ ├── SavedStatePicker.swift
│ │ │ │ ├── SwiftUIVMView.swift
│ │ │ │ ├── VMProgressOverlay.swift
│ │ │ │ └── VirtualMachineControls.swift
│ │ │ ├── Configuration/
│ │ │ │ └── VMSessionConfigurationView.swift
│ │ │ ├── VirtualMachineSessionUI.swift
│ │ │ ├── VirtualMachineSessionUIManager.swift
│ │ │ └── VirtualMachineSessionView.swift
│ │ ├── Settings/
│ │ │ ├── AutomationSettingsView.swift
│ │ │ ├── Components/
│ │ │ │ ├── BackwardsCompatibility.swift
│ │ │ │ ├── FileSystemPathFormControl.swift
│ │ │ │ ├── OpenVirtualBuddySettingsAction.swift
│ │ │ │ ├── SettingsFooter.swift
│ │ │ │ └── VerticalLabeledContentStyle.swift
│ │ │ ├── GeneralSettingsView.swift
│ │ │ ├── SettingsScreen.swift
│ │ │ └── VirtualizationSettingsView.swift
│ │ └── VM Configuration/
│ │ ├── Components/
│ │ │ ├── ConfigurationSection.swift
│ │ │ └── GroupedList.swift
│ │ ├── Sections/
│ │ │ ├── DisplayConfigurationView.swift
│ │ │ ├── GuestAppConfigurationView.swift
│ │ │ ├── HardwareConfigurationView.swift
│ │ │ ├── KeyboardDeviceConfigurationView.swift
│ │ │ ├── NetworkConfigurationView.swift
│ │ │ ├── PointingDeviceConfigurationView.swift
│ │ │ ├── Sharing/
│ │ │ │ ├── SharedFolderListItem.swift
│ │ │ │ ├── SharedFoldersManagementView.swift
│ │ │ │ └── SharingConfigurationView.swift
│ │ │ ├── SoundConfigurationView.swift
│ │ │ └── Storage/
│ │ │ ├── ManagedDiskImageEditor.swift
│ │ │ ├── StorageConfigurationView.swift
│ │ │ └── StorageDeviceDetailView.swift
│ │ ├── VMConfigurationSheet.swift
│ │ ├── VMConfigurationView.swift
│ │ └── VMConfigurationViewModel.swift
│ └── VirtualUI.h
├── VirtualWormhole/
│ ├── Source/
│ │ ├── Definitions/
│ │ │ └── VirtualWormholeConstants.swift
│ │ ├── Services/
│ │ │ ├── Base/
│ │ │ │ ├── WormholeServiceClient.swift
│ │ │ │ └── WormholeServiceProtocol.swift
│ │ │ ├── DarwinNotifications/
│ │ │ │ ├── SystemNotification.swift
│ │ │ │ └── WHDarwinNotificationsService.swift
│ │ │ ├── DefaultsImport/
│ │ │ │ ├── Implementation/
│ │ │ │ │ ├── DefaultsDomain+ExportImport.swift
│ │ │ │ │ ├── DefaultsDomainDescriptor.swift
│ │ │ │ │ └── DefaultsImportController.swift
│ │ │ │ ├── Resources/
│ │ │ │ │ └── DefaultsDomains.plist
│ │ │ │ ├── WHDefaultsImportClient.swift
│ │ │ │ └── WHDefaultsImportService.swift
│ │ │ ├── DesktopPicture/
│ │ │ │ ├── CGImage+FullyTransparent.swift
│ │ │ │ ├── NSImage+DesktopPicture.h
│ │ │ │ ├── NSImage+DesktopPicture.m
│ │ │ │ └── WHDesktopPictureService.swift
│ │ │ └── WHSharedClipboardService.swift
│ │ ├── WireProtocol/
│ │ │ ├── WHPayload.swift
│ │ │ ├── WHPing.swift
│ │ │ └── WormholePacket.swift
│ │ └── WormholeManager.swift
│ └── VirtualWormhole.h
├── VirtualWormholeTests/
│ └── WormholePacketTests.swift
└── data/
├── images/
│ ├── debian-dark-thumbnail.heic
│ ├── debian-dark.heic
│ ├── debian-thumbnail.heic
│ ├── debian.heic
│ ├── fedora-dark-thumbnail.heic
│ ├── fedora-dark.heic
│ ├── fedora-thumbnail.heic
│ ├── fedora.heic
│ ├── jammyjellyfish-dark-thumbnail.heic
│ ├── jammyjellyfish-dark.heic
│ ├── jammyjellyfish-thumbnail.heic
│ ├── jammyjellyfish.heic
│ ├── kali-dark-thumbnail.heic
│ ├── kali-dark.heic
│ ├── kali-thumbnail.heic
│ ├── kali.heic
│ ├── monterey-dark-thumbnail.heic
│ ├── monterey-dark.heic
│ ├── monterey-thumbnail.heic
│ ├── monterey.heic
│ ├── sequoia-dark-thumbnail.heic
│ ├── sequoia-dark.heic
│ ├── sequoia-thumbnail.heic
│ ├── sequoia.heic
│ ├── sonoma-dark-thumbnail.heic
│ ├── sonoma-dark.heic
│ ├── sonoma-thumbnail.heic
│ ├── sonoma.heic
│ ├── tahoe-dark-thumbnail.heic
│ ├── tahoe-dark.heic
│ ├── tahoe-thumbnail.heic
│ ├── tahoe.heic
│ ├── ventura-dark-thumbnail.heic
│ ├── ventura-dark.heic
│ ├── ventura-thumbnail.heic
│ └── ventura.heic
├── ipsws_v1.json
├── ipsws_v2.json
├── linux_v1.json
└── linux_v2.json
Condensed preview — 410 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,714K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 18,
"preview": "github: insidegui\n"
},
{
"path": ".gitignore",
"chars": 324,
"preview": ".DS_Store\n__MACOSX\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!def"
},
{
"path": "DeepLinkSecurity/DeepLinkSecurity.h",
"chars": 504,
"preview": "//\n// DeepLinkSecurity.h\n// DeepLinkSecurity\n//\n// Created by Guilherme Rambo on 12/10/23.\n//\n\n#import <Foundation/Fo"
},
{
"path": "DeepLinkSecurity/Source/Base/DeepLinkSecurityDefines.swift",
"chars": 484,
"preview": "import Foundation\nimport OSLog\n\nstruct DeepLinkSecurityDefines {\n static let subsystem = \"codes.rambo.DeepLinkSecurit"
},
{
"path": "DeepLinkSecurity/Source/DeepLinkSentinel.swift",
"chars": 6631,
"preview": "import Cocoa\nimport OSLog\n\npublic final class DeepLinkSentinel: ObservableObject {\n private lazy var logger = Logger."
},
{
"path": "DeepLinkSecurity/Source/Models/DeepLinkClient.swift",
"chars": 913,
"preview": "import Foundation\nimport CryptoKit\n\n/// Represents an app/process that's attempting to open a deep link in the app.\npubl"
},
{
"path": "DeepLinkSecurity/Source/Models/DeepLinkClientDescriptor.swift",
"chars": 946,
"preview": "import Cocoa\n\n/// Describes metadata for a client that's previously requested deep link authorization.\n/// See ``DeepLin"
},
{
"path": "DeepLinkSecurity/Source/Models/Extensions/DeepLinkClient+Crypto.swift",
"chars": 3014,
"preview": "import Cocoa\n\npublic extension DeepLinkClient {\n init(auditTokenDescriptor: NSAppleEventDescriptor) throws {\n "
},
{
"path": "DeepLinkSecurity/Source/Models/Extensions/DeepLinkClientDescriptor+.swift",
"chars": 3604,
"preview": "import Cocoa\n\npublic extension DeepLinkClientDescriptor {\n init(client: DeepLinkClient, authorization: DeepLinkClient"
},
{
"path": "DeepLinkSecurity/Source/Models/OpenDeepLinkRequest.swift",
"chars": 434,
"preview": "import Foundation\n\n/// Represents a client's request for opening a deep link in the app.\npublic struct OpenDeepLinkReque"
},
{
"path": "DeepLinkSecurity/Source/Storage/DeepLinkAuthStore.swift",
"chars": 1271,
"preview": "import Cocoa\n\n/// Describes a user's decision about a client opening deep links in the app.\npublic enum DeepLinkClientAu"
},
{
"path": "DeepLinkSecurity/Source/Storage/DeepLinkManagementStore.swift",
"chars": 991,
"preview": "import Foundation\n\n/// Implemented by types that can provide persistence for a list of authorized/denied deep link clien"
},
{
"path": "DeepLinkSecurity/Source/Storage/KeychainDeepLinkAuthStore.swift",
"chars": 9224,
"preview": "import Foundation\nimport Security\nimport OSLog\nimport CryptoKit\n\n/// A robust auth store that uses signed keychain items"
},
{
"path": "DeepLinkSecurity/Source/Storage/MemoryDeepLinkAuthStore.swift",
"chars": 1222,
"preview": "import Foundation\nimport OSLog\n\n/// A very basic store that uses an in-memory dictionary and is destroyed when the app t"
},
{
"path": "DeepLinkSecurity/Source/Storage/UserDefaultsDeepLinkManagementStore.swift",
"chars": 4766,
"preview": "import Foundation\nimport OSLog\n\n/// A management store that persists client descriptors in `UserDefaults`.\npublic final "
},
{
"path": "DeepLinkSecurity/Source/UI/DeepLinkAuthUI.swift",
"chars": 699,
"preview": "import SwiftUI\n\npublic protocol DeepLinkAuthUI: AnyObject {\n /// Return ``DeepLinkClientAuthorization/authorized`` if"
},
{
"path": "LICENSE",
"chars": 1276,
"preview": "Copyright (c) 2022 Guilherme Rambo\n\nRedistribution and use in source and binary forms, with or without\nmodification, are"
},
{
"path": "README.md",
"chars": 4698,
"preview": "<img src=\"./assets/VirtualBuddyIcon.png\" width=\"128\" />\n\n# VirtualBuddy\n\nVirtualBuddy can virtualize macOS 12 and later "
},
{
"path": "ReleaseNotes/VirtualBuddy 1.2 Release Nodes.md",
"chars": 1317,
"preview": "# What's new in VirtualBuddy 1.2\n\n- Managing virtual machines can now be done entirely within the library view, the cont"
},
{
"path": "ReleaseNotes/VirtualBuddy 1.2.1 Release Notes.md",
"chars": 534,
"preview": "# New in VirtualBuddy 1.2.1\n\n### General improvements to the installer user interface:\n\n- Addresses an issue that caused"
},
{
"path": "ReleaseNotes/VirtualBuddy 1.2.2 Release Notes.md",
"chars": 334,
"preview": "# Fixed in VirtualBuddy 1.2.2\n\n- Makes custom IPSW URL validation less strict, allowing downloads from plain HTTP URLs a"
},
{
"path": "VirtualBuddy/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 226,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"platform\" : \"universal\",\n \"reference\" : \"systemOrangeColor\"\n "
},
{
"path": "VirtualBuddy/Assets.xcassets/AppIcon-Default.appiconset/Contents.json",
"chars": 1316,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_16x16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" : "
},
{
"path": "VirtualBuddy/Assets.xcassets/AppIcon-Dev.appiconset/Contents.json",
"chars": 1316,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_16x16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" : "
},
{
"path": "VirtualBuddy/Assets.xcassets/AppIcon-zBeta.appiconset/Contents.json",
"chars": 1316,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_16x16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" : "
},
{
"path": "VirtualBuddy/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualBuddy/Automation/DeepLinkHandler.swift",
"chars": 5656,
"preview": "import SwiftUI\nimport VirtualCore\nimport VirtualUI\nimport OSLog\nimport DeepLinkSecurity\n\ntypealias WindowUpdatingClosure"
},
{
"path": "VirtualBuddy/Automation/Support/DeepLinkAuthDialog.swift",
"chars": 4941,
"preview": "import SwiftUI\nimport DeepLinkSecurity\n\nfinal class DeepLinkAuthPanel: NSPanel {\n\n private static var panelInstances "
},
{
"path": "VirtualBuddy/Automation/VirtualBuddyDeepLinks.swift",
"chars": 1690,
"preview": "import Foundation\nimport URLQueryItemCoder\nimport DeepLinkSecurity\nimport OSLog\nimport VirtualCore\n\nstruct OpenVMParamet"
},
{
"path": "VirtualBuddy/Bootstrap/SoftwareUpdateController.swift",
"chars": 3010,
"preview": "//\n// SoftwareUpdateController.swift\n// VirtualBuddy\n//\n// Created by Guilherme Rambo on 25/06/22.\n//\n\nimport SwiftUI"
},
{
"path": "VirtualBuddy/Bootstrap/VirtualBuddyApp.swift",
"chars": 3261,
"preview": "//\n// VirtualBuddyApp.swift\n// VirtualBuddy\n//\n// Created by Guilherme Rambo on 07/04/22.\n//\n\nimport SwiftUI\nimport V"
},
{
"path": "VirtualBuddy/Bootstrap/VirtualBuddyAppDelegate.swift",
"chars": 6225,
"preview": "//\n// VirtualBuddyNSApp.swift\n// VirtualBuddy\n//\n// Created by Guilherme Rambo on 07/04/22.\n//\n\nimport Cocoa\n@_export"
},
{
"path": "VirtualBuddy/Bootstrap/VirtualBuddyEntryPoint.swift",
"chars": 2169,
"preview": "import SwiftUI\nimport VirtualCore\nimport VirtualUI\nimport BuddyFoundation\n\n/**\n Main entry point for the VirtualBuddy ap"
},
{
"path": "VirtualBuddy/CommandLine/VirtualBuddyCLI.swift",
"chars": 1512,
"preview": "import Foundation\nimport ArgumentParser\n\n/**\n Declares supported `ParsableCommand`s that VirtualBuddy provides.\n\n Comman"
},
{
"path": "VirtualBuddy/CommandLine/vctool/BlurHashCommand.swift",
"chars": 2927,
"preview": "import Foundation\nimport ArgumentParser\nimport VirtualCore\nimport VirtualUI\nimport BuddyFoundation\n\nstruct BlurHashComma"
},
{
"path": "VirtualBuddy/CommandLine/vctool/CatalogCommand.swift",
"chars": 393,
"preview": "import Foundation\nimport ArgumentParser\nimport FragmentZip\n\nstruct CatalogCommand: AsyncParsableCommand {\n static let"
},
{
"path": "VirtualBuddy/CommandLine/vctool/Core/BuildManifest+Fetch.swift",
"chars": 1355,
"preview": "import Foundation\nimport FragmentZip\n\nextension BuildManifest {\n init(remoteIPSWURL url: URL, build: String) async th"
},
{
"path": "VirtualBuddy/CommandLine/vctool/Core/BuildManifest.swift",
"chars": 3326,
"preview": "import Foundation\nimport BuddyFoundation\n\nstruct BuildManifest: Decodable, TreeStringConvertible {\n var manifestVersi"
},
{
"path": "VirtualBuddy/CommandLine/vctool/Core/Helpers.swift",
"chars": 5009,
"preview": "import Foundation\nimport ArgumentParser\nimport BuddyFoundation\n\nextension URL {\n init(validating string: String) thro"
},
{
"path": "VirtualBuddy/CommandLine/vctool/Core/TreeStringConvertible.swift",
"chars": 2372,
"preview": "import Foundation\n\nprotocol TreeStringConvertible: CustomStringConvertible {\n func description(level: Int) -> String\n"
},
{
"path": "VirtualBuddy/CommandLine/vctool/Core/URL+ContentLength.swift",
"chars": 762,
"preview": "import Foundation\n\nextension URL {\n func contentLength() async throws -> Int64 {\n var request = URLRequest(url"
},
{
"path": "VirtualBuddy/CommandLine/vctool/GroupCommand.swift",
"chars": 7439,
"preview": "import Foundation\nimport ArgumentParser\nimport AppKit\nimport BuddyFoundation\nimport VirtualUI\n\nextension CatalogCommand "
},
{
"path": "VirtualBuddy/CommandLine/vctool/IPSWCommand.swift",
"chars": 2347,
"preview": "import Foundation\nimport ArgumentParser\nimport FragmentZip\n\nstruct IPSWCommand: AsyncParsableCommand {\n static let co"
},
{
"path": "VirtualBuddy/CommandLine/vctool/ImageCommand.swift",
"chars": 6240,
"preview": "import Foundation\nimport ArgumentParser\nimport FragmentZip\nimport BuddyFoundation\nimport VirtualCore\n\nextension CatalogC"
},
{
"path": "VirtualBuddy/CommandLine/vctool/MigrateCommand.swift",
"chars": 6269,
"preview": "import Foundation\nimport ArgumentParser\nimport FragmentZip\nimport BuddyFoundation\n\nextension CatalogCommand {\n struct"
},
{
"path": "VirtualBuddy/CommandLine/vctool/MobileDeviceCommand.swift",
"chars": 824,
"preview": "import Foundation\nimport ArgumentParser\n\nstruct MobileDeviceCommand: AsyncParsableCommand {\n static let configuration"
},
{
"path": "VirtualBuddy/CommandLine/vctool/ResolveCommand.swift",
"chars": 2531,
"preview": "import Foundation\nimport ArgumentParser\nimport BuddyFoundation\n\nextension CatalogCommand {\n\n struct ResolveCommand: A"
},
{
"path": "VirtualBuddy/CommandLine/vctool/VCTool.swift",
"chars": 428,
"preview": "import Foundation\nimport ArgumentParser\nimport AppKit\n\nstruct VCTool: AsyncParsableCommand {\n static let configuratio"
},
{
"path": "VirtualBuddy/Config/AppTarget.xcconfig",
"chars": 2855,
"preview": "#include \"Paths.xcconfig\"\n\n// Settings in this file only apply to the main VirtualBuddy.app target\n\n// Entitlement Setti"
},
{
"path": "VirtualBuddy/Config/Entitlements/VirtualBuddy.entitlements",
"chars": 302,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualBuddy/Config/Entitlements/VirtualBuddy_Managed.entitlements",
"chars": 347,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualBuddy/Config/Features.xcconfig",
"chars": 555,
"preview": "// ENABLE_SPARKLE = Enables building with Sparkle for automatic updates\n// ENABLE_USERDEFAULTS_SYNC = Enables the user d"
},
{
"path": "VirtualBuddy/Config/InfoPlist.xcconfig",
"chars": 235,
"preview": "INFOPLIST_KEY_NSHumanReadableCopyright = © 2024 Buddy Software LTD\nINFOPLIST_KEY_NSMicrophoneUsageDescription = Enable a"
},
{
"path": "VirtualBuddy/Config/Main.xcconfig",
"chars": 155,
"preview": "#include \"Paths.xcconfig\"\n#include \"Versions.xcconfig\"\n#include \"Signing.xcconfig\"\n#include \"Features.xcconfig\"\n#include"
},
{
"path": "VirtualBuddy/Config/Paths.xcconfig",
"chars": 348,
"preview": "ENTITLEMENTS_DIR=VirtualBuddy/Config/Entitlements\n\nVB_APP_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Framew"
},
{
"path": "VirtualBuddy/Config/Signing.xcconfig",
"chars": 379,
"preview": "CODE_SIGN_IDENTITY = Apple Development\nVB_BUNDLE_ID_PREFIX =\n\nGUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID = $(VB_BUNDLE_ID_PR"
},
{
"path": "VirtualBuddy/Config/Versions.xcconfig",
"chars": 171,
"preview": "MARKETING_VERSION = 2.1\nCURRENT_PROJECT_VERSION = 284\nDYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION)\nVERSIONING_SYST"
},
{
"path": "VirtualBuddy/Info.plist",
"chars": 3579,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualBuddy/Preview Content/Preview Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualBuddy.xcodeproj/project.pbxproj",
"chars": 291926,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 55;\n\tobjects = {\n\n/* Begin PBXAggregateTarget sec"
},
{
"path": "VirtualBuddy.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 135,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:\">\n </FileRef"
},
{
"path": "VirtualBuddy.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
"chars": 238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualBuddy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved",
"chars": 1779,
"preview": "{\n \"originHash\" : \"3fd24967a48b127010a1cab40c41fd70176878f897a946d6404561fee4decff1\",\n \"pins\" : [\n {\n \"identit"
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist",
"chars": 140,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n uuid = \"F8D26811-F4BF-47A8-98F0-596926D6C20D\"\n type = \"4\"\n version"
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/DeepLinkSecurity.xcscheme",
"chars": 2429,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.7\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualBuddy (Dev Release).xcscheme",
"chars": 3565,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualBuddy (Managed - Beta).xcscheme",
"chars": 3558,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualBuddy (Managed).xcscheme",
"chars": 6822,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualBuddy.xcscheme",
"chars": 3237,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualBuddyGuest.xcscheme",
"chars": 3396,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualCore.xcscheme",
"chars": 2407,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualUI.xcscheme",
"chars": 2399,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/VirtualWormhole.xcscheme",
"chars": 2874,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "VirtualBuddy.xcodeproj/xcshareddata/xcschemes/vctool.xcscheme",
"chars": 3230,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"1640\"\n version = \"1.7\">\n <BuildAction\n "
},
{
"path": "VirtualBuddyGuest/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 335,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"display-p3\",\n \"components\" : {\n \"alpha"
},
{
"path": "VirtualBuddyGuest/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1316,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon_16x16.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" : "
},
{
"path": "VirtualBuddyGuest/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualBuddyGuest/Assets.xcassets/StatusItem.imageset/Contents.json",
"chars": 336,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"menubar.png\",\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\"\n },\n {\n "
},
{
"path": "VirtualBuddyGuest/Dashboard/GuestDashboard.swift",
"chars": 3178,
"preview": "//\n// ContentView.swift\n// VirtualBuddyGuest\n//\n// Created by Guilherme Rambo on 02/06/22.\n//\n\nimport SwiftUI\nimport "
},
{
"path": "VirtualBuddyGuest/Dashboard/GuestDefaultsImportView.swift",
"chars": 2764,
"preview": "#if ENABLE_USERDEFAULTS_SYNC\nimport SwiftUI\nimport VirtualCore\nimport VirtualUI\nimport VirtualWormhole\nimport Combine\n\nf"
},
{
"path": "VirtualBuddyGuest/Dashboard/GuestSharedFoldersManager.swift",
"chars": 3567,
"preview": "import Foundation\nimport VirtualCore\nimport OSLog\n\nfinal class GuestSharedFoldersManager: ObservableObject {\n\n privat"
},
{
"path": "VirtualBuddyGuest/Dashboard/HostConnectionStateProvider.swift",
"chars": 195,
"preview": "import Foundation\nimport VirtualWormhole\n\nprotocol HostConnectionStateProvider: ObservableObject {\n var isConnected: "
},
{
"path": "VirtualBuddyGuest/Dashboard/Support/GuestLaunchAtLoginManager.swift",
"chars": 1598,
"preview": "import Foundation\nimport ServiceManagement\nimport OSLog\n\nfinal class GuestLaunchAtLoginManager: ObservableObject {\n\n "
},
{
"path": "VirtualBuddyGuest/Dashboard/Support/VirtualBuddyGuest-Bridging-Header.h",
"chars": 84,
"preview": "#define kGuestAppLaunchAtLoginHelperBundleID GUEST_LAUNCH_AT_LOGIN_HELPER_BUNDLE_ID\n"
},
{
"path": "VirtualBuddyGuest/GuestAppDelegate.swift",
"chars": 3522,
"preview": "import Cocoa\nimport SwiftUI\nimport VirtualUI\nimport VirtualWormhole\nimport OSLog\n\n@NSApplicationMain\nfinal class GuestAp"
},
{
"path": "VirtualBuddyGuest/GuestAppInstaller.swift",
"chars": 6213,
"preview": "import Cocoa\nimport OSLog\n\nfinal class GuestAppInstaller {\n\n private lazy var logger = Logger(subsystem: Bundle.main."
},
{
"path": "VirtualBuddyGuest/Main.storyboard",
"chars": 58454,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB\" version=\"3.0\" t"
},
{
"path": "VirtualBuddyGuest/Preview Content/Preview Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualBuddyGuest/VirtualBuddyGuest.entitlements",
"chars": 181,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualBuddyGuestHelper/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 123,
"preview": "{\n \"colors\" : [\n {\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }"
},
{
"path": "VirtualBuddyGuestHelper/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 904,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"mac\",\n \"scale\" : \"1x\",\n \"size\" : \"16x16\"\n },\n {\n \"idiom\" : "
},
{
"path": "VirtualBuddyGuestHelper/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualBuddyGuestHelper/Base.lproj/Main.storyboard",
"chars": 58502,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB\" version=\"3.0\" t"
},
{
"path": "VirtualBuddyGuestHelper/GuestHelperAppDelegate.swift",
"chars": 1323,
"preview": "import Cocoa\nimport os.log\n\n@main\nfinal class GuestHelperAppDelegate: NSObject, NSApplicationDelegate {\n\n private let"
},
{
"path": "VirtualBuddyGuestHelper/VirtualBuddyGuestHelper.entitlements",
"chars": 240,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualCore/Source/Definitions/Logging.swift",
"chars": 593,
"preview": "//\n// Logging.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 05/06/22.\n//\n\nimport Foundation\nimport OSLog\n\n"
},
{
"path": "VirtualCore/Source/Definitions/PreviewSupport.swift",
"chars": 7024,
"preview": "#if DEBUG\n\nimport Foundation\nimport Virtualization\n\nlet previewLibraryDirName = \"PreviewLibrary\"\n\npublic extension VBVir"
},
{
"path": "VirtualCore/Source/Definitions/VirtualCoreConstants.swift",
"chars": 384,
"preview": "//\n// VirtualCoreConstants.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 02/06/22.\n//\n\nimport Foundation\ni"
},
{
"path": "VirtualCore/Source/GuestSupport/CreateGuestImage.sh",
"chars": 3554,
"preview": "#!/bin/sh\n\n: '\nThis script is used by VirtualBuddy to dynamically generate a disk image that can be mounted in a virtual"
},
{
"path": "VirtualCore/Source/GuestSupport/GuestAdditionsDiskImage.swift",
"chars": 12838,
"preview": "//\n// GuestAdditionsDiskImage.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/03/23.\n//\n\nimport Foundatio"
},
{
"path": "VirtualCore/Source/Headers/VirtualizationPrivate.h",
"chars": 3157,
"preview": "//\n// VirtualizationPrivate.h\n// VirtualBuddy\n//\n// Created by Guilherme Rambo on 07/04/22.\n//\n\n#import <Virtualizati"
},
{
"path": "VirtualCore/Source/Import/UTM/UTMAppleConfiguration.swift",
"chars": 17803,
"preview": "/*\nCode in this file is based on source code from the UTM project (https://github.com/utmapp/UTM)\n\nApache License\nVersio"
},
{
"path": "VirtualCore/Source/Import/UTM/UTMImporter.swift",
"chars": 7731,
"preview": "import Foundation\nimport BuddyFoundation\nimport UniformTypeIdentifiers\nimport OSLog\n\nprivate let logger = Logger(subsyst"
},
{
"path": "VirtualCore/Source/Import/VMImporter+Helpers.swift",
"chars": 698,
"preview": "import Foundation\nimport BuddyFoundation\n\nextension VMImporter {\n func createBundle(forImportedVMPath path: FilePath,"
},
{
"path": "VirtualCore/Source/Import/VMImporter.swift",
"chars": 847,
"preview": "import Foundation\nimport BuddyFoundation\nimport UniformTypeIdentifiers\n\n/// Adopted by types that can import virtual mac"
},
{
"path": "VirtualCore/Source/Import/VMImporterRegistry.swift",
"chars": 1318,
"preview": "import Foundation\nimport BuddyFoundation\nimport OSLog\nimport UniformTypeIdentifiers\n\nprivate let logger = Logger(subsyst"
},
{
"path": "VirtualCore/Source/Models/BlurHashToken.swift",
"chars": 1240,
"preview": "import Foundation\n\n/// Combination of blur hash number of components with the blur hash string itself.\n///\n/// This is u"
},
{
"path": "VirtualCore/Source/Models/Configuration/ConfigurationModels+Summary.swift",
"chars": 1664,
"preview": "//\n// ConfigurationModels+Summary.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 19/07/22.\n//\n\nimport Found"
},
{
"path": "VirtualCore/Source/Models/Configuration/ConfigurationModels+Validation.swift",
"chars": 6547,
"preview": "//\n// ConfigurationModels+Validation.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 19/07/22.\n//\n\nimport Co"
},
{
"path": "VirtualCore/Source/Models/Configuration/ConfigurationModels.swift",
"chars": 26964,
"preview": "//\n// ConfigurationModels.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 17/07/22.\n//\n\nimport Foundation\nim"
},
{
"path": "VirtualCore/Source/Models/Configuration/DecodableDefault.swift",
"chars": 3190,
"preview": "import Foundation\n\npublic protocol DecodableDefaultSource {\n associatedtype Value: Decodable\n static var defaultVa"
},
{
"path": "VirtualCore/Source/Models/Configuration/VBMacDevice+Storage.swift",
"chars": 413,
"preview": "//\n// VBMacDevice+Storage.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 20/07/22.\n//\n\nimport Foundation\n\np"
},
{
"path": "VirtualCore/Source/Models/SavedState/VBSavedStateMetadata+Clone.swift",
"chars": 1257,
"preview": "import Foundation\n\nextension VBSavedStateMetadata {\n static func createStorageDeviceClones(packageURL: URL, model: VB"
},
{
"path": "VirtualCore/Source/Models/SavedState/VBSavedStateMetadata.swift",
"chars": 2386,
"preview": "import Foundation\nimport BuddyFoundation\n\npublic struct VBSavedStateMetadata: Identifiable, Hashable, Codable {\n publ"
},
{
"path": "VirtualCore/Source/Models/SavedState/VBSavedStatePackage+VM.swift",
"chars": 194,
"preview": "import Foundation\n\nextension VBSavedStatePackage: VBStorageDeviceContainer {\n public var bundleURL: URL { url }\n p"
},
{
"path": "VirtualCore/Source/Models/SavedState/VBSavedStatePackage.swift",
"chars": 5938,
"preview": "import Foundation\nimport UniformTypeIdentifiers\nimport OSLog\n\npublic extension UTType {\n static let virtualBuddySaved"
},
{
"path": "VirtualCore/Source/Models/SavedState/VMLibraryController+SavedState.swift",
"chars": 1969,
"preview": "import Foundation\n\n@MainActor\npublic extension VMLibraryController {\n\n nonisolated static let savedStateDirectoryName"
},
{
"path": "VirtualCore/Source/Models/VBError.swift",
"chars": 263,
"preview": "//\n// VBError.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 10/04/22.\n//\n\nimport Foundation\n\npublic struct"
},
{
"path": "VirtualCore/Source/Models/VBNVRAMVariable.swift",
"chars": 386,
"preview": "//\n// VBNVRAMVariable.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 11/04/22.\n//\n\nimport Foundation\n\npubli"
},
{
"path": "VirtualCore/Source/Models/VBStorageDeviceContainer.swift",
"chars": 2000,
"preview": "import Foundation\n\n/// Adopted by ``VMVirtualMachine`` and ``VBSavedStatePackage``\n/// in order to help resolve storage "
},
{
"path": "VirtualCore/Source/Models/VBVirtualMachine+Metadata.swift",
"chars": 2065,
"preview": "//\n// VBVirtualMachine+Metadata.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 24/06/22.\n//\n\nimport Cocoa\n\n"
},
{
"path": "VirtualCore/Source/Models/VBVirtualMachine+Screenshot.swift",
"chars": 1073,
"preview": "import Cocoa\n\npublic extension VBVirtualMachine {\n\n var screenshot: NSImage? {\n guard let imageData = metadata"
},
{
"path": "VirtualCore/Source/Models/VBVirtualMachine.swift",
"chars": 11087,
"preview": "import Foundation\nimport UniformTypeIdentifiers\nimport Combine\n\npublic typealias VoidSubject = PassthroughSubject<(), Ne"
},
{
"path": "VirtualCore/Source/ReleaseTrains/AppUpdateChannel.swift",
"chars": 1214,
"preview": "//\n// AppUpdateChannel.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 25/06/22.\n//\n\nimport Foundation\n\npubl"
},
{
"path": "VirtualCore/Source/ReleaseTrains/VBBuildType.swift",
"chars": 1918,
"preview": "import Foundation\n\n/// Represents the type of app build, such as beta vs. release.\npublic enum VBBuildType: String, Case"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewLinux.vbvm/Disk.img",
"chars": 5,
"preview": "Fake\n"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewLinuxBlurHash.vbvm/Disk.img",
"chars": 5,
"preview": "Fake\n"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewLinuxNoArtwork.vbvm/Disk.img",
"chars": 5,
"preview": "Fake\n"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewMac.vbvm/Disk.img",
"chars": 5,
"preview": "Fake\n"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewMacBlurHash.vbvm/Disk.img",
"chars": 5,
"preview": "Fake\n"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewMacNoArtwork.vbvm/Disk.img",
"chars": 5,
"preview": "Fake\n"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewSavedStates/Save-2024-03-27_16;06;24.vbst/Info.plist",
"chars": 534,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewSavedStates/Save-2024-03-27_16;07;04.vbst/Info.plist",
"chars": 534,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewSavedStates/Save-2024-03-27_16;08;06.vbst/Info.plist",
"chars": 534,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewSavedStates/Save-2024-03-27_16;08;28.vbst/Info.plist",
"chars": 534,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualCore/Source/Resources/Preview/PreviewSavedStates/Save-2024-03-27_16;08;51.vbst/Info.plist",
"chars": 534,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "VirtualCore/Source/Resources/Preview/_Downloads/UniversalMac_13.3.1_22E261_Restore.ipsw",
"chars": 5,
"preview": "dummy"
},
{
"path": "VirtualCore/Source/Resources/Preview/_Downloads/UniversalMac_14.0_23A344_Restore.ipsw",
"chars": 5,
"preview": "dummy"
},
{
"path": "VirtualCore/Source/Resources/Preview/_Downloads/UniversalMac_14.5_23F79_Restore.ipsw",
"chars": 5,
"preview": "dummy"
},
{
"path": "VirtualCore/Source/Resources/Preview/_Downloads/UniversalMac_15.3_24D60_Restore.ipsw",
"chars": 5,
"preview": "dummy"
},
{
"path": "VirtualCore/Source/Resources/Preview/_Downloads/UniversalMac_15.5_24F74_Restore.ipsw",
"chars": 5,
"preview": "dummy"
},
{
"path": "VirtualCore/Source/Resources/VirtualCore.xcassets/Adjectives.dataset/Adjectives.txt",
"chars": 9684,
"preview": "Able\nAbove\nAbsent\nAbsolute\nAbstract\nAbundant\nAcademic\nAcceptable\nAccepted\nAccessible\nAccurate\nAccused\nActive\nActual\nAcut"
},
{
"path": "VirtualCore/Source/Resources/VirtualCore.xcassets/Adjectives.dataset/Contents.json",
"chars": 215,
"preview": "{\n \"data\" : [\n {\n \"filename\" : \"Adjectives.txt\",\n \"idiom\" : \"universal\",\n \"universal-type-identifier\""
},
{
"path": "VirtualCore/Source/Resources/VirtualCore.xcassets/Animals.dataset/Animals.txt",
"chars": 1605,
"preview": "Aardvark\nAlbatross\nAlligator\nAlpaca\nAnt\nAnteater\nAntelope\nApe\nArmadillo\nDonkey\nBaboon\nBadger\nBarracuda\nBat\nBear\nBeaver\nB"
},
{
"path": "VirtualCore/Source/Resources/VirtualCore.xcassets/Animals.dataset/Contents.json",
"chars": 155,
"preview": "{\n \"data\" : [\n {\n \"filename\" : \"Animals.txt\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" "
},
{
"path": "VirtualCore/Source/Resources/VirtualCore.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualCore/Source/Restore/Download/DownloadBackend.swift",
"chars": 504,
"preview": "import Foundation\nimport Combine\n\npublic enum DownloadState: Hashable {\n case idle\n case preCheck(_ message: Strin"
},
{
"path": "VirtualCore/Source/Restore/Download/SimulatedDownloadBackend.swift",
"chars": 1309,
"preview": "import Foundation\nimport Combine\n\n#if DEBUG\npublic final class SimulatedDownloadBackend: NSObject, DownloadBackend {\n "
},
{
"path": "VirtualCore/Source/Restore/Download/URLSessionDownloadBackend.swift",
"chars": 6984,
"preview": "//\n// URLSessionDownloadBackend.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/06/22.\n//\n\nimport Foundat"
},
{
"path": "VirtualCore/Source/Restore/Installation/RestoreBackend.swift",
"chars": 286,
"preview": "import Foundation\nimport Virtualization\nimport BuddyKit\n\n@MainActor\npublic protocol RestoreBackend: AnyObject {\n init"
},
{
"path": "VirtualCore/Source/Restore/Installation/SimulatedRestoreBackend.swift",
"chars": 1253,
"preview": "import Foundation\nimport Virtualization\nimport BuddyKit\nimport Combine\n\n#if DEBUG\npublic final class SimulatedRestoreBac"
},
{
"path": "VirtualCore/Source/Restore/Installation/VirtualizationRestoreBackend.swift",
"chars": 3241,
"preview": "import Foundation\nimport Virtualization\nimport BuddyKit\nimport OSLog\nimport Combine\n\npublic final class VirtualizationRe"
},
{
"path": "VirtualCore/Source/Restore Images/Models/VBRestoreImageInfo.swift",
"chars": 2653,
"preview": "//\n// VBRestoreImageInfo.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/06/22.\n//\n\nimport Foundation\nimp"
},
{
"path": "VirtualCore/Source/Restore Images/Models/VBRestoreImagesResponse.swift",
"chars": 332,
"preview": "//\n// VBRestoreImagesResponse.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/06/22.\n//\n\nimport Foundatio"
},
{
"path": "VirtualCore/Source/Restore Images/VBAPIClient.swift",
"chars": 8123,
"preview": "//\n// VBAPIClient.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/06/22.\n//\n\nimport Foundation\nimport OSL"
},
{
"path": "VirtualCore/Source/Settings/VBSettings+CatalogDownload.swift",
"chars": 2273,
"preview": "import Foundation\nimport BuddyKit\nimport OSLog\n\nprivate let logger = Logger(subsystem: VirtualCoreConstants.subsystemNam"
},
{
"path": "VirtualCore/Source/Settings/VBSettings.swift",
"chars": 7386,
"preview": "//\n// VBSettings.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 05/06/22.\n//\n\nimport Foundation\nimport OSLo"
},
{
"path": "VirtualCore/Source/Settings/VBSettingsContainer.swift",
"chars": 1453,
"preview": "//\n// VBSettingsContainer.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 05/06/22.\n//\n\nimport Foundation\nim"
},
{
"path": "VirtualCore/Source/Utilities/Bundle+Version.swift",
"chars": 442,
"preview": "import Foundation\nimport BuddyFoundation\n\npublic extension Bundle {\n var vbShortVersionString: String {\n infoD"
},
{
"path": "VirtualCore/Source/Utilities/LogStreamer.swift",
"chars": 5552,
"preview": "import Foundation\nimport OSLog\nimport Combine\n\npublic struct LogEntry: Identifiable, Hashable, Codable, CustomStringConv"
},
{
"path": "VirtualCore/Source/Utilities/PreventTerminationAssertion.swift",
"chars": 6412,
"preview": "import Cocoa\nimport BuddyKit\nimport OSLog\n\n/// An assertion that prevents the app from being terminated during its lifet"
},
{
"path": "VirtualCore/Source/Utilities/ProcessInfo+ECID.swift",
"chars": 705,
"preview": "import Foundation\nimport IOKit\n\nextension ProcessInfo {\n\n var machineECID: UInt64? {\n let entry = IORegistryEn"
},
{
"path": "VirtualCore/Source/Utilities/VBMemoryLeakDebugAssertions.swift",
"chars": 1918,
"preview": "import Foundation\n\npublic final class VBMemoryLeakDebugAssertions {\n @inlinable\n public static func vb_objectShoul"
},
{
"path": "VirtualCore/Source/Utilities/VolumeUtils.swift",
"chars": 2989,
"preview": "//\n// VolumeUtils.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 20/07/22.\n//\n\nimport Foundation\n\npublic ex"
},
{
"path": "VirtualCore/Source/Utilities/WeakReference.swift",
"chars": 467,
"preview": "import Foundation\n\n/// Wraps a reference type as a weak reference.\n/// Useful as value type in collections when holding "
},
{
"path": "VirtualCore/Source/VirtualCatalog/LegacyCatalog.swift",
"chars": 1442,
"preview": "import Foundation\nimport BuddyFoundation\n\npublic struct LegacyCatalog: Decodable {\n public let channels: [LegacyCatal"
},
{
"path": "VirtualCore/Source/VirtualCatalog/MobileDeviceFramework.swift",
"chars": 1669,
"preview": "import Foundation\nimport BuddyFoundation\n\n/// A representation of the MobileDevice framework and its properties.\npublic "
},
{
"path": "VirtualCore/Source/VirtualCatalog/README.md",
"chars": 3589,
"preview": "# VirtualCatalog\n\nThis directory includes models and associated logic used by VirtualBuddy to inspect and resolve downlo"
},
{
"path": "VirtualCore/Source/VirtualCatalog/ResolvedCatalog.swift",
"chars": 19163,
"preview": "import Foundation\nimport BuddyFoundation\nimport OSLog\n\nprivate let logger = Logger(subsystem: VirtualCoreConstants.subsy"
},
{
"path": "VirtualCore/Source/VirtualCatalog/SoftwareCatalog+DownloadMatching.swift",
"chars": 10542,
"preview": "import Foundation\nimport BuddyFoundation\nimport OSLog\n\nprivate let matchLogger = Logger(subsystem: VirtualCoreConstants."
},
{
"path": "VirtualCore/Source/VirtualCatalog/SoftwareCatalog.swift",
"chars": 11513,
"preview": "import Foundation\nimport BuddyFoundation\n\n/// Adopted by all models present in a VirtualBuddy software catalog.\npublic p"
},
{
"path": "VirtualCore/Source/VirtualCatalog/Utilities/BlurHashEncode.swift",
"chars": 5296,
"preview": "#if canImport(AppKit)\nimport AppKit\n\npublic extension NSImage {\n func draw(at point: CGPoint) {\n draw(in: CGRe"
},
{
"path": "VirtualCore/Source/VirtualCatalog/Utilities/String+AppleOSBuild.swift",
"chars": 694,
"preview": "import Foundation\nimport BuddyFoundation\n\nextension String {\n static let appleOSBuildRegex = /[0-9]{2}[A-Z][0-9]{2,}["
},
{
"path": "VirtualCore/Source/VirtualCatalog/Utilities/URL+ExtendedAttributes.swift",
"chars": 1952,
"preview": "import Foundation\nimport BuddyFoundation\n\nextension URL {\n func vb_encodeExtendedAttribute<T: Encodable>(_ value: T, "
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/CatalogExtensions.swift",
"chars": 2611,
"preview": "//\n// CatalogExtensions.swift\n// VirtualBuddy\n//\n// Created by Guilherme Rambo on 02/08/24.\n//\n\nimport Foundation\n\n@M"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/DirectoryObserver.swift",
"chars": 1443,
"preview": "import Foundation\nimport Combine\nimport OSLog\n\nfinal class DirectoryObserver: NSObject, NSFilePresenter {\n\n private l"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/DiskImageGenerator.swift",
"chars": 4089,
"preview": "//\n// DiskImageGenerator.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 19/07/22.\n//\n\nimport Foundation\n\nfi"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/LinuxVirtualMachineConfigurationHelper.swift",
"chars": 2370,
"preview": "/*\nSee LICENSE folder for this sample’s licensing information.\n\nAbstract:\nHelper that creates various configuration obje"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/MacOSVirtualMachineConfigurationHelper.swift",
"chars": 2272,
"preview": "/*\nSee LICENSE folder for this sample’s licensing information.\n\nAbstract:\nHelper that creates various configuration obje"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/RandomNameGenerator.swift",
"chars": 1088,
"preview": "//\n// RandomNameGenerator.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 19/07/22.\n//\n\nimport Foundation\n\np"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/VBDebugUtil.h",
"chars": 479,
"preview": "#if DEBUG\n\n#import <Foundation/Foundation.h>\n\n@class VZVirtualMachine;\n\nNS_ASSUME_NONNULL_BEGIN\n\n/// This is used to sto"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/VBDebugUtil.m",
"chars": 1073,
"preview": "#if DEBUG\n\n#import \"VBDebugUtil.h\"\n\n@import Virtualization;\n\n#import <VirtualCore/VirtualizationPrivate.h>\n\n@implementat"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/VZVirtualMachineConfiguration+NVRAM.swift",
"chars": 956,
"preview": "//\n// VZVirtualMachineConfiguration+NVRAM.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 11/04/22.\n//\n\nimpo"
},
{
"path": "VirtualCore/Source/Virtualization/Helpers/VirtualMachineConfigurationHelper.swift",
"chars": 8940,
"preview": "/*\nSee LICENSE folder for this sample’s licensing information.\n\nAbstract:\nHelper that creates various configuration obje"
},
{
"path": "VirtualCore/Source/Virtualization/Screenshot/NSImage+DRMProtected.swift",
"chars": 1481,
"preview": "import Cocoa\nimport BuddyKit\nimport Vision\n\n@available(macOS 15.0, *)\nextension NSImage {\n /// This is kinda silly.\n "
},
{
"path": "VirtualCore/Source/Virtualization/Screenshot/NSImage+HEIC.swift",
"chars": 2943,
"preview": "import Cocoa\nimport struct AVFoundation.AVFileType\n\npublic extension NSImage {\n static let defaultThumbnailProperties"
},
{
"path": "VirtualCore/Source/Virtualization/VBVirtualMachine+Virtualization.swift",
"chars": 4154,
"preview": "//\n// VBVirtualMachine+Virtualization.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 21/07/22.\n//\n\nimport F"
},
{
"path": "VirtualCore/Source/Virtualization/VMController.swift",
"chars": 15137,
"preview": "//\n// VMController.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/04/22.\n//\n\nimport Cocoa\nimport Foundat"
},
{
"path": "VirtualCore/Source/Virtualization/VMInstance.swift",
"chars": 19098,
"preview": "//\n// VMInstance.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 12/04/22.\n//\n\nimport Cocoa\nimport Foundatio"
},
{
"path": "VirtualCore/Source/Virtualization/VMLibraryController.swift",
"chars": 23526,
"preview": "//\n// VMLibraryController.swift\n// VirtualCore\n//\n// Created by Guilherme Rambo on 10/04/22.\n//\n\nimport SwiftUI\nimpor"
},
{
"path": "VirtualCore/Source/Virtualization/VMSavedStatesController.swift",
"chars": 2492,
"preview": "import SwiftUI\nimport Combine\nimport OSLog\n\n@MainActor\npublic final class VMSavedStatesController: ObservableObject {\n\n "
},
{
"path": "VirtualCore/VirtualCore.h",
"chars": 550,
"preview": "//\n// VirtualCore.h\n// VirtualCore\n//\n// Created by Guilherme Rambo on 07/04/22.\n//\n\n#import <Foundation/Foundation.h"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/FirstLaunchExperience.dataset/Contents.json",
"chars": 241,
"preview": "{\n \"data\" : [\n {\n \"filename\" : \"FirstLaunchExperience.caar\",\n \"idiom\" : \"universal\",\n \"universal-type"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/FullBleedBlurHash.dataset/Contents.json",
"chars": 166,
"preview": "{\n \"data\" : [\n {\n \"filename\" : \"FullBleedBlurHash.caar\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n "
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/GuestSymbol.imageset/Contents.json",
"chars": 276,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"GuestSymbol.svg\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"au"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/StatusItemPanelChromeBorder.colorset/Contents.json",
"chars": 695,
"preview": "{\n \"colors\" : [\n {\n \"color\" : {\n \"color-space\" : \"srgb\",\n \"components\" : {\n \"alpha\" : \"1"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/ThumbnailPlaceholder.imageset/Contents.json",
"chars": 437,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"ThumbnailPlaceholder.png\",\n \"idiom\" : \"universal\",\n \"scale\" : \"1x\"\n"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/VBGuestType/Contents.json",
"chars": 119,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n },\n \"properties\" : {\n \"provides-namespace\" : true\n }\n}\n"
},
{
"path": "VirtualUI/Resources/VirtualUI.xcassets/VBGuestType/linux.imageset/Contents.json",
"chars": 275,
"preview": "{\n \"images\" : [\n {\n \"filename\" : \"icon-linux.pdf\",\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"aut"
}
]
// ... and 210 more files (download for full content)
About this extraction
This page contains the full source code of the insidegui/VirtualBuddy GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 410 files (1.5 MB), approximately 409.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.