import AppKit import Foundation enum LaunchdManager { private static func runLaunchctl(_ args: [String]) { let process = Process() process.launchPath = "/bin/launchctl" process.arguments = args try? process.run() } static func startClawdis() { let userTarget = "gui/\(getuid())/\(launchdLabel)" self.runLaunchctl(["kickstart", "-k", userTarget]) } static func stopClawdis() { let userTarget = "gui/\(getuid())/\(launchdLabel)" self.runLaunchctl(["stop", userTarget]) } } @MainActor enum CLIInstaller { static func install(statusHandler: @escaping @Sendable (String) async -> Void) async { let helper = Bundle.main.bundleURL.appendingPathComponent("Contents/MacOS/ClawdisCLI") guard FileManager.default.isExecutableFile(atPath: helper.path) else { await statusHandler("Helper missing in bundle; rebuild via scripts/package-mac-app.sh") return } let targets = ["/usr/local/bin/clawdis-mac", "/opt/homebrew/bin/clawdis-mac"] var messages: [String] = [] for target in targets { do { try FileManager.default.createDirectory( atPath: (target as NSString).deletingLastPathComponent, withIntermediateDirectories: true) try? FileManager.default.removeItem(atPath: target) try FileManager.default.createSymbolicLink(atPath: target, withDestinationPath: helper.path) messages.append("Linked \(target)") } catch { messages.append("Failed \(target): \(error.localizedDescription)") } } await statusHandler(messages.joined(separator: "; ")) } }