feat(macos): detect installed CLI helper

This commit is contained in:
Peter Steinberger
2025-12-07 04:35:22 +01:00
parent 1a10569f6d
commit 21dfbd0103
2 changed files with 60 additions and 6 deletions

View File

@@ -5,6 +5,8 @@ struct GeneralSettings: View {
@ObservedObject var state: AppState
@State private var isInstallingCLI = false
@State private var cliStatus: String?
@State private var cliInstalled = false
@State private var cliInstallLocation: String?
var body: some View {
VStack(alignment: .leading, spacing: 18) {
@@ -63,6 +65,7 @@ struct GeneralSettings: View {
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 22)
.onAppear { self.refreshCLIStatus() }
}
private var activeBinding: Binding<Bool> {
@@ -80,18 +83,37 @@ struct GeneralSettings: View {
if self.isInstallingCLI {
ProgressView().controlSize(.small)
} else {
Text("Install CLI helper")
Text(self.cliInstalled ? "Reinstall CLI helper" : "Install CLI helper")
}
}
.disabled(self.isInstallingCLI)
if let status = cliStatus {
Text(status)
.font(.caption)
if self.isInstallingCLI {
Text("Working...")
.font(.callout)
.foregroundStyle(.secondary)
} else if self.cliInstalled {
Label("Installed", systemImage: "checkmark.circle.fill")
.font(.callout)
.foregroundStyle(.secondary)
} else {
Text("Not installed")
.font(.callout)
.foregroundStyle(.secondary)
.lineLimit(2)
}
}
if let status = cliStatus {
Text(status)
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(2)
} else if let installLocation = self.cliInstallLocation {
Text("Found at \(installLocation)")
.font(.caption)
.foregroundStyle(.secondary)
.lineLimit(2)
}
Text("Symlink \"clawdis-mac\" into /usr/local/bin and /opt/homebrew/bin for scripts.")
.font(.callout)
.foregroundStyle(.secondary)
@@ -104,7 +126,16 @@ struct GeneralSettings: View {
self.isInstallingCLI = true
defer { isInstallingCLI = false }
await CLIInstaller.install { status in
await MainActor.run { self.cliStatus = status }
await MainActor.run {
self.cliStatus = status
self.refreshCLIStatus()
}
}
}
private func refreshCLIStatus() {
let installLocation = CLIInstaller.installedLocation()
self.cliInstallLocation = installLocation
self.cliInstalled = installLocation != nil
}
}

View File

@@ -90,6 +90,29 @@ enum LaunchAgentManager {
@MainActor
enum CLIInstaller {
static func installedLocation() -> String? {
let fm = FileManager.default
for basePath in cliHelperSearchPaths {
let candidate = URL(fileURLWithPath: basePath).appendingPathComponent("clawdis-mac").path
var isDirectory: ObjCBool = false
guard fm.fileExists(atPath: candidate, isDirectory: &isDirectory), !isDirectory.boolValue else {
continue
}
if fm.isExecutableFile(atPath: candidate) {
return candidate
}
}
return nil
}
static func isInstalled() -> Bool {
self.installedLocation() != nil
}
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 {