native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #3 from onevcat/rebrand/prowl

Rebrand user-facing identity from Supacode to Prowl

authored by

Wei Wang and committed by
GitHub
02ae8a54 12487feb

+180 -71
+3 -3
AGENTS.md
··· 11 11 make lint # Run swiftlint only (fix + lint) 12 12 make check # Run both format and lint 13 13 make test # Run all tests 14 - make log-stream # Stream app logs (subsystem: app.supabit.supacode) 14 + make log-stream # Stream app logs (subsystem: com.onevcat.prowl) 15 15 make bump-version # Bump patch version and create git tag 16 16 make bump-and-release # Bump version and push to trigger release 17 17 ``` ··· 27 27 28 28 ## Architecture 29 29 30 - Supacode is a macOS orchestrator for running multiple coding agents in parallel, using GhosttyKit as the underlying terminal. 30 + Prowl is a macOS orchestrator for running multiple coding agents in parallel, using GhosttyKit as the underlying terminal. 31 31 32 32 ### Core Data Flow 33 33 ··· 120 120 ## Submodules 121 121 122 122 - `ThirdParty/ghostty` (`https://github.com/ghostty-org/ghostty`): Source dependency used to build `Frameworks/GhosttyKit.xcframework` and terminal resources. 123 - - `Resources/git-wt` (`https://github.com/khoi/git-wt.git`): Bundled `wt` CLI used by Supacode Git worktree flows at runtime. 123 + - `Resources/git-wt` (`https://github.com/khoi/git-wt.git`): Bundled `wt` CLI used by Prowl Git worktree flows at runtime.
+1 -1
Makefile
··· 83 83 check: format lint # Format and lint 84 84 85 85 log-stream: # Stream logs from the app via log stream 86 - log stream --predicate 'subsystem == "app.supabit.supacode"' --style compact --color always 86 + log stream --predicate 'subsystem == "com.onevcat.prowl"' --style compact --color always 87 87 88 88 bump-version: # Bump app version (usage: make bump-version [VERSION=x.x.x] [BUILD=123]) 89 89 @if [ -z "$(VERSION)" ]; then \
+2 -4
README.md
··· 1 - # Supacode 2 - 3 - Native terminal coding agents command center. 1 + # Prowl 4 2 5 - ![screenshot](https://www.supacode.sh/screenshot.png) 3 + Native terminal coding agents command center. Fork of [Supacode](https://github.com/supabitapp/supacode). 6 4 7 5 ## Technical Stack 8 6
+1 -1
doc-onevcat/change-list.md
··· 16 16 | Execute Terminal Input custom commands by injecting return key so the command runs immediately. | `562042f` | Fork only | 17 17 | Disable push-triggered `tip` release workflow in fork to avoid expected CI failures. | `85b3fd7` | Fork only | 18 18 | Enforce notarized-only fork releases; block non-notarized publishing path in release script and docs. | `2ab70fd` | Fork only | 19 - | Move repo-scoped settings files to `~/.supacode/repo/<repo-last-path>/` with legacy migration from repo root files. | `ea9259f` | Fork only | 19 + | Move repo-scoped settings files to `~/.prowl/repo/<repo-last-path>/` (was `~/.supacode/repo/…`) with legacy migration from repo root files. | `ea9259f` | Fork only | 20 20 | Add `/fork-release` slash command for upstream sync and private release workflow. | `64829dc` | Fork only | 21 21 | Add diff window with file tree sidebar and YiTong DiffView for viewing worktree changes. | `0d03848`, `09194c4` | Fork only | 22 22 | Wire up diff badge click in worktree row, `Cmd+]` shortcut, and Show Diff menu item. | `59dc4f6` | Fork only |
+10 -8
supacode.xcodeproj/project.pbxproj
··· 468 468 "-lc++", 469 469 ); 470 470 OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -Wno-incomplete-umbrella"; 471 - PRODUCT_BUNDLE_IDENTIFIER = app.supabit.supacode; 472 - PRODUCT_NAME = "$(TARGET_NAME)"; 471 + PRODUCT_BUNDLE_IDENTIFIER = com.onevcat.prowl; 472 + PRODUCT_MODULE_NAME = supacode; 473 + PRODUCT_NAME = Prowl; 473 474 REGISTER_APP_GROUPS = YES; 474 475 RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO; 475 476 RUNTIME_EXCEPTION_ALLOW_JIT = NO; ··· 524 525 "-lc++", 525 526 ); 526 527 OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -Wno-incomplete-umbrella"; 527 - PRODUCT_BUNDLE_IDENTIFIER = app.supabit.supacode; 528 - PRODUCT_NAME = "$(TARGET_NAME)"; 528 + PRODUCT_BUNDLE_IDENTIFIER = com.onevcat.prowl; 529 + PRODUCT_MODULE_NAME = supacode; 530 + PRODUCT_NAME = Prowl; 529 531 REGISTER_APP_GROUPS = YES; 530 532 RUNTIME_EXCEPTION_ALLOW_DYLD_ENVIRONMENT_VARIABLES = NO; 531 533 RUNTIME_EXCEPTION_ALLOW_JIT = NO; ··· 553 555 GENERATE_INFOPLIST_FILE = YES; 554 556 MACOSX_DEPLOYMENT_TARGET = 26.1; 555 557 MARKETING_VERSION = 0.6.8; 556 - PRODUCT_BUNDLE_IDENTIFIER = app.supabit.supacodeTests; 558 + PRODUCT_BUNDLE_IDENTIFIER = com.onevcat.prowlTests; 557 559 PRODUCT_NAME = "$(TARGET_NAME)"; 558 560 STRING_CATALOG_GENERATE_SYMBOLS = NO; 559 561 SWIFT_APPROACHABLE_CONCURRENCY = YES; 560 562 SWIFT_EMIT_LOC_STRINGS = NO; 561 563 SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; 562 564 SWIFT_VERSION = 6.0; 563 - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/supacode.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/supacode"; 565 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Prowl.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Prowl"; 564 566 }; 565 567 name = Debug; 566 568 }; ··· 575 577 GENERATE_INFOPLIST_FILE = YES; 576 578 MACOSX_DEPLOYMENT_TARGET = 26.1; 577 579 MARKETING_VERSION = 0.6.8; 578 - PRODUCT_BUNDLE_IDENTIFIER = app.supabit.supacodeTests; 580 + PRODUCT_BUNDLE_IDENTIFIER = com.onevcat.prowlTests; 579 581 PRODUCT_NAME = "$(TARGET_NAME)"; 580 582 STRING_CATALOG_GENERATE_SYMBOLS = NO; 581 583 SWIFT_APPROACHABLE_CONCURRENCY = YES; 582 584 SWIFT_EMIT_LOC_STRINGS = NO; 583 585 SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; 584 586 SWIFT_VERSION = 6.0; 585 - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/supacode.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/supacode"; 587 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Prowl.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Prowl"; 586 588 }; 587 589 name = Release; 588 590 };
+91
supacode.xcodeproj/xcshareddata/xcschemes/supacode.xcscheme
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <Scheme 3 + LastUpgradeVersion = "1630" 4 + version = "1.7"> 5 + <BuildAction 6 + parallelizeBuildables = "YES" 7 + buildImplicitDependencies = "YES" 8 + runPostActionsOnFailure = "NO"> 9 + <BuildActionEntries> 10 + <BuildActionEntry 11 + buildForTesting = "YES" 12 + buildForRunning = "YES" 13 + buildForProfiling = "YES" 14 + buildForArchiving = "YES" 15 + buildForAnalyzing = "YES"> 16 + <BuildableReference 17 + BuildableIdentifier = "primary" 18 + BlueprintIdentifier = "D69CE0492F1F378200584C57" 19 + BuildableName = "Prowl.app" 20 + BlueprintName = "supacode" 21 + ReferencedContainer = "container:supacode.xcodeproj"> 22 + </BuildableReference> 23 + </BuildActionEntry> 24 + </BuildActionEntries> 25 + </BuildAction> 26 + <TestAction 27 + buildConfiguration = "Debug" 28 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 29 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 30 + shouldUseLaunchSchemeArgsEnv = "YES" 31 + shouldAutocreateTestPlan = "YES"> 32 + <Testables> 33 + <TestableReference 34 + skipped = "NO" 35 + parallelizable = "YES"> 36 + <BuildableReference 37 + BuildableIdentifier = "primary" 38 + BlueprintIdentifier = "D6F821002F1FCBC1004B4174" 39 + BuildableName = "supacodeTests.xctest" 40 + BlueprintName = "supacodeTests" 41 + ReferencedContainer = "container:supacode.xcodeproj"> 42 + </BuildableReference> 43 + </TestableReference> 44 + </Testables> 45 + </TestAction> 46 + <LaunchAction 47 + buildConfiguration = "Debug" 48 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" 49 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" 50 + launchStyle = "0" 51 + useCustomWorkingDirectory = "NO" 52 + ignoresPersistentStateOnLaunch = "NO" 53 + debugDocumentVersioning = "YES" 54 + debugServiceExtension = "internal" 55 + allowLocationSimulation = "YES"> 56 + <BuildableProductRunnable 57 + runnableDebuggingMode = "0"> 58 + <BuildableReference 59 + BuildableIdentifier = "primary" 60 + BlueprintIdentifier = "D69CE0492F1F378200584C57" 61 + BuildableName = "Prowl.app" 62 + BlueprintName = "supacode" 63 + ReferencedContainer = "container:supacode.xcodeproj"> 64 + </BuildableReference> 65 + </BuildableProductRunnable> 66 + </LaunchAction> 67 + <ProfileAction 68 + buildConfiguration = "Release" 69 + shouldUseLaunchSchemeArgsEnv = "YES" 70 + savedToolIdentifier = "" 71 + useCustomWorkingDirectory = "NO" 72 + debugDocumentVersioning = "YES"> 73 + <BuildableProductRunnable 74 + runnableDebuggingMode = "0"> 75 + <BuildableReference 76 + BuildableIdentifier = "primary" 77 + BlueprintIdentifier = "D69CE0492F1F378200584C57" 78 + BuildableName = "Prowl.app" 79 + BlueprintName = "supacode" 80 + ReferencedContainer = "container:supacode.xcodeproj"> 81 + </BuildableReference> 82 + </BuildableProductRunnable> 83 + </ProfileAction> 84 + <AnalyzeAction 85 + buildConfiguration = "Debug"> 86 + </AnalyzeAction> 87 + <ArchiveAction 88 + buildConfiguration = "Release" 89 + revealArchiveInOrganizer = "YES"> 90 + </ArchiveAction> 91 + </Scheme>
+1 -1
supacode/App/ContentView.swift
··· 64 64 .repositories( 65 65 .presentAlert( 66 66 title: "Unable to open folders", 67 - message: "Supacode could not read the selected folders." 67 + message: "Prowl could not read the selected folders." 68 68 ) 69 69 ) 70 70 )
+3 -3
supacode/App/supacodeApp.swift
··· 159 159 } 160 160 161 161 var body: some Scene { 162 - Window("Supacode", id: "main") { 162 + Window("Prowl", id: "main") { 163 163 GhosttyColorSchemeSyncView(ghostty: ghostty) { 164 164 ContentView(store: store, terminalManager: terminalManager) 165 165 .environment(ghosttyShortcuts) ··· 202 202 ) 203 203 } 204 204 CommandGroup(replacing: .appTermination) { 205 - Button("Quit Supacode") { 205 + Button("Quit Prowl") { 206 206 store.send(.requestQuit) 207 207 } 208 208 .keyboardShortcut("q") 209 - .help("Quit Supacode (⌘Q)") 209 + .help("Quit Prowl (⌘Q)") 210 210 } 211 211 } 212 212 }
supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-1024x1024@1x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-128x128@1x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-16x16@1x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-16x16@2x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-256x256@1x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-32x32@1x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-32x32@2x.png

This is a binary file and will not be displayed.

supacode/Assets.xcassets/AppIcon.appiconset/appicon-macOS-Dark-512x512@1x.png

This is a binary file and will not be displayed.

+3 -3
supacode/Features/App/Reducer/AppFeature.swift
··· 393 393 } 394 394 } 395 395 state.alert = AlertState { 396 - TextState("Quit Supacode?") 396 + TextState("Quit Prowl?") 397 397 } actions: { 398 398 ButtonState(action: .confirmQuit) { 399 399 TextState("Quit") ··· 616 616 let message: String 617 617 if let errorMessage, !errorMessage.isEmpty { 618 618 message = 619 - "Supacode cannot send system notifications.\n\n" 619 + "Prowl cannot send system notifications.\n\n" 620 620 + "Error: \(errorMessage)" 621 621 } else { 622 - message = "Supacode cannot send system notifications while permission is denied." 622 + message = "Prowl cannot send system notifications while permission is denied." 623 623 } 624 624 state.alert = AlertState { 625 625 TextState("Enable Notifications in System Settings")
+10 -10
supacode/Features/Repositories/Reducer/RepositoriesFeature.swift
··· 2184 2184 return .send( 2185 2185 .presentAlert( 2186 2186 title: "Pull request not available", 2187 - message: "Supacode could not find a pull request for this worktree." 2187 + message: "Prowl could not find a pull request for this worktree." 2188 2188 ) 2189 2189 ) 2190 2190 } ··· 2204 2204 return .send( 2205 2205 .presentAlert( 2206 2206 title: "Invalid pull request URL", 2207 - message: "Supacode could not open the pull request URL." 2207 + message: "Prowl could not open the pull request URL." 2208 2208 ) 2209 2209 ) 2210 2210 } ··· 2217 2217 return .send( 2218 2218 .presentAlert( 2219 2219 title: "Failing check not found", 2220 - message: "Supacode could not find a failing check URL." 2220 + message: "Prowl could not find a failing check URL." 2221 2221 ) 2222 2222 ) 2223 2223 } ··· 2234 2234 return .send( 2235 2235 .presentAlert( 2236 2236 title: "Failing check not found", 2237 - message: "Supacode could not find a failing check with details." 2237 + message: "Prowl could not find a failing check with details." 2238 2238 ) 2239 2239 ) 2240 2240 } ··· 2350 2350 await send( 2351 2351 .presentAlert( 2352 2352 title: "Branch name unavailable", 2353 - message: "Supacode could not determine the pull request branch." 2353 + message: "Prowl could not determine the pull request branch." 2354 2354 ) 2355 2355 ) 2356 2356 return ··· 2362 2362 await send( 2363 2363 .presentAlert( 2364 2364 title: "No workflow runs found", 2365 - message: "Supacode could not find any workflow runs for this branch." 2365 + message: "Prowl could not find any workflow runs for this branch." 2366 2366 ) 2367 2367 ) 2368 2368 return ··· 2372 2372 await send( 2373 2373 .presentAlert( 2374 2374 title: "No failing workflow run", 2375 - message: "Supacode could not find a failing workflow run to copy logs from." 2375 + message: "Prowl could not find a failing workflow run to copy logs from." 2376 2376 ) 2377 2377 ) 2378 2378 return ··· 2427 2427 await send( 2428 2428 .presentAlert( 2429 2429 title: "Branch name unavailable", 2430 - message: "Supacode could not determine the pull request branch." 2430 + message: "Prowl could not determine the pull request branch." 2431 2431 ) 2432 2432 ) 2433 2433 return ··· 2439 2439 await send( 2440 2440 .presentAlert( 2441 2441 title: "No workflow runs found", 2442 - message: "Supacode could not find any workflow runs for this branch." 2442 + message: "Prowl could not find any workflow runs for this branch." 2443 2443 ) 2444 2444 ) 2445 2445 return ··· 2449 2449 await send( 2450 2450 .presentAlert( 2451 2451 title: "No failing workflow run", 2452 - message: "Supacode could not find a failing workflow run to re-run." 2452 + message: "Prowl could not find a failing workflow run to re-run." 2453 2453 ) 2454 2454 ) 2455 2455 return
+1 -1
supacode/Features/Repositories/Views/SidebarFooterView.swift
··· 24 24 Spacer() 25 25 Menu { 26 26 Button("Submit GitHub issue", systemImage: "exclamationmark.bubble") { 27 - if let url = URL(string: "https://github.com/supabitapp/supacode/issues/new") { 27 + if let url = URL(string: "https://github.com/onevcat/supacode/issues/new") { 28 28 openURL(url) 29 29 } 30 30 }
+5 -5
supacode/Features/Settings/Views/AdvancedSettingsView.swift
··· 10 10 Section("Advanced") { 11 11 VStack(alignment: .leading) { 12 12 Toggle( 13 - "Share analytics with Supacode", 13 + "Share analytics with Prowl", 14 14 isOn: $store.analyticsEnabled 15 15 ) 16 - .help("Share anonymous usage data with Supacode (requires restart)") 17 - Text("Anonymous usage data helps improve Supacode.") 16 + .help("Share anonymous usage data with Prowl (requires restart)") 17 + Text("Anonymous usage data helps improve Prowl.") 18 18 .foregroundStyle(.secondary) 19 19 .font(.callout) 20 20 Text("Requires app restart.") ··· 24 24 .frame(maxWidth: .infinity, alignment: .leading) 25 25 VStack(alignment: .leading) { 26 26 Toggle( 27 - "Share crash reports with Supacode", 27 + "Share crash reports with Prowl", 28 28 isOn: $store.crashReportsEnabled 29 29 ) 30 - .help("Share anonymous crash reports with Supacode (requires restart)") 30 + .help("Share anonymous crash reports with Prowl (requires restart)") 31 31 Text("Anonymous crash reports help improve stability.") 32 32 .foregroundStyle(.secondary) 33 33 .font(.callout)
+1 -1
supacode/Features/Terminal/Views/TerminalSplitTreeView.swift
··· 7 7 var pinnedSize: CGSize? 8 8 let action: (Operation) -> Void 9 9 10 - private static let dragType = UTType(exportedAs: "sh.supacode.ghosttySurfaceId") 10 + private static let dragType = UTType(exportedAs: "com.onevcat.prowl.ghosttySurfaceId") 11 11 private static func dragProvider(for surfaceView: GhosttySurfaceView) -> NSItemProvider { 12 12 let provider = NSItemProvider() 13 13 let data = surfaceView.id.uuidString.data(using: .utf8) ?? Data()
+17 -21
supacode/Info.plist
··· 3 3 <plist version="1.0"> 4 4 <dict> 5 5 <key>NSAppleEventsUsageDescription</key> 6 - <string>A program running within Supacode would like to use AppleScript.</string> 6 + <string>A program running within Prowl would like to use AppleScript.</string> 7 7 <key>NSBluetoothAlwaysUsageDescription</key> 8 - <string>A program running within Supacode would like to use Bluetooth.</string> 8 + <string>A program running within Prowl would like to use Bluetooth.</string> 9 9 <key>NSCalendarsUsageDescription</key> 10 - <string>A program running within Supacode would like to access your Calendar.</string> 10 + <string>A program running within Prowl would like to access your Calendar.</string> 11 11 <key>NSCameraUsageDescription</key> 12 - <string>A program running within Supacode would like to use the camera.</string> 12 + <string>A program running within Prowl would like to use the camera.</string> 13 13 <key>NSContactsUsageDescription</key> 14 - <string>A program running within Supacode would like to access your Contacts.</string> 14 + <string>A program running within Prowl would like to access your Contacts.</string> 15 15 <key>NSLocalNetworkUsageDescription</key> 16 - <string>A program running within Supacode would like to access the local network.</string> 16 + <string>A program running within Prowl would like to access the local network.</string> 17 17 <key>NSLocationUsageDescription</key> 18 - <string>A program running within Supacode would like to access your location information.</string> 18 + <string>A program running within Prowl would like to access your location information.</string> 19 19 <key>NSMicrophoneUsageDescription</key> 20 - <string>A program running within Supacode would like to use your microphone.</string> 20 + <string>A program running within Prowl would like to use your microphone.</string> 21 21 <key>NSMotionUsageDescription</key> 22 - <string>A program running within Supacode would like to access motion data.</string> 22 + <string>A program running within Prowl would like to access motion data.</string> 23 23 <key>NSPhotoLibraryUsageDescription</key> 24 - <string>A program running within Supacode would like to access your Photo Library.</string> 24 + <string>A program running within Prowl would like to access your Photo Library.</string> 25 25 <key>NSRemindersUsageDescription</key> 26 - <string>A program running within Supacode would like to access your reminders.</string> 26 + <string>A program running within Prowl would like to access your reminders.</string> 27 27 <key>NSSpeechRecognitionUsageDescription</key> 28 - <string>A program running within Supacode would like to use speech recognition.</string> 28 + <string>A program running within Prowl would like to use speech recognition.</string> 29 29 <key>NSSystemAdministrationUsageDescription</key> 30 - <string>A program running within Supacode requires elevated privileges.</string> 31 - <key>SUFeedURL</key> 32 - <string>https://supacode.sh/download/latest/appcast.xml</string> 33 - <key>SUPublicEDKey</key> 34 - <string>eBdTbl+6sR8gxO1zyzyvdQHuJrXMLxD31oCc+JoW5jo=</string> 30 + <string>A program running within Prowl requires elevated privileges.</string> 35 31 <key>SUEnableAutomaticChecks</key> 36 - <true/> 32 + <false/> 37 33 <key>SUAutomaticallyUpdate</key> 38 - <true/> 34 + <false/> 39 35 <key>UTExportedTypeDeclarations</key> 40 36 <array> 41 37 <dict> 42 38 <key>UTTypeIdentifier</key> 43 - <string>sh.supacode.ghosttySurfaceId</string> 39 + <string>com.onevcat.prowl.ghosttySurfaceId</string> 44 40 <key>UTTypeDescription</key> 45 - <string>Supacode Ghostty Surface Identifier</string> 41 + <string>Prowl Ghostty Surface Identifier</string> 46 42 <key>UTTypeConformsTo</key> 47 43 <array> 48 44 <string>public.data</string>
+27 -5
supacode/Support/SupacodePaths.swift
··· 2 2 3 3 nonisolated enum SupacodePaths { 4 4 static var baseDirectory: URL { 5 - FileManager.default.homeDirectoryForCurrentUser 6 - .appending(path: ".supacode", directoryHint: .isDirectory) 5 + let home = FileManager.default.homeDirectoryForCurrentUser 6 + let prowlDir = home.appending(path: ".prowl", directoryHint: .isDirectory) 7 + let legacyDir = home.appending(path: ".supacode", directoryHint: .isDirectory) 8 + // Migrate from legacy ~/.supacode to ~/.prowl on first access 9 + if !FileManager.default.fileExists(atPath: prowlDir.path(percentEncoded: false)), 10 + FileManager.default.fileExists(atPath: legacyDir.path(percentEncoded: false)) 11 + { 12 + try? FileManager.default.moveItem(at: legacyDir, to: prowlDir) 13 + } 14 + return prowlDir 7 15 } 8 16 9 17 static var repositorySettingsDirectory: URL { ··· 87 95 88 96 static func repositorySettingsURL(for rootURL: URL) -> URL { 89 97 repositorySettingsDirectory(for: rootURL) 90 - .appending(path: "supacode.json", directoryHint: .notDirectory) 98 + .appending(path: "prowl.json", directoryHint: .notDirectory) 91 99 } 92 100 93 101 static func onevcatRepositorySettingsURL(for rootURL: URL) -> URL { 94 102 repositorySettingsDirectory(for: rootURL) 95 - .appending(path: "supacode.onevcat.json", directoryHint: .notDirectory) 103 + .appending(path: "prowl.onevcat.json", directoryHint: .notDirectory) 96 104 } 97 105 106 + /// Legacy location: ~/.prowl/repo/<name>/supacode.json (pre-rename) 98 107 static func legacyRepositorySettingsURL(for rootURL: URL) -> URL { 99 - rootURL.standardizedFileURL.appending(path: "supacode.json", directoryHint: .notDirectory) 108 + repositorySettingsDirectory(for: rootURL) 109 + .appending(path: "supacode.json", directoryHint: .notDirectory) 100 110 } 101 111 112 + /// Legacy location: ~/.prowl/repo/<name>/supacode.onevcat.json (pre-rename) 102 113 static func legacyOnevcatRepositorySettingsURL(for rootURL: URL) -> URL { 114 + repositorySettingsDirectory(for: rootURL) 115 + .appending(path: "supacode.onevcat.json", directoryHint: .notDirectory) 116 + } 117 + 118 + /// Legacy location: <repo-root>/supacode.json (original upstream location) 119 + static func originalLegacyRepositorySettingsURL(for rootURL: URL) -> URL { 120 + rootURL.standardizedFileURL.appending(path: "supacode.json", directoryHint: .notDirectory) 121 + } 122 + 123 + /// Legacy location: <repo-root>/supacode.onevcat.json (original upstream location) 124 + static func originalLegacyOnevcatRepositorySettingsURL(for rootURL: URL) -> URL { 103 125 rootURL.standardizedFileURL.appending(path: "supacode.onevcat.json", directoryHint: .notDirectory) 104 126 } 105 127
+2 -2
supacodeTests/AppFeatureSystemNotificationTests.swift
··· 46 46 TextState("Cancel") 47 47 } 48 48 } message: { 49 - TextState("Supacode cannot send system notifications.\n\nError: Mock request error") 49 + TextState("Prowl cannot send system notifications.\n\nError: Mock request error") 50 50 } 51 51 52 52 #expect(authorizationRequests.value == 1) ··· 97 97 TextState("Cancel") 98 98 } 99 99 } message: { 100 - TextState("Supacode cannot send system notifications.\n\nError: Authorization status is denied.") 100 + TextState("Prowl cannot send system notifications.\n\nError: Authorization status is denied.") 101 101 } 102 102 103 103 #expect(authorizationRequests.value == 0)
+2 -2
supacodeTests/RepositoryPathsTests.swift
··· 46 46 let root = URL(fileURLWithPath: "/tmp/work/repo-alpha") 47 47 let settingsURL = SupacodePaths.repositorySettingsURL(for: root) 48 48 49 - #expect(settingsURL.lastPathComponent == "supacode.json") 49 + #expect(settingsURL.lastPathComponent == "prowl.json") 50 50 #expect(settingsURL.deletingLastPathComponent().lastPathComponent == "repo-alpha") 51 51 #expect(settingsURL.deletingLastPathComponent().deletingLastPathComponent().lastPathComponent == "repo") 52 52 } ··· 55 55 let root = URL(fileURLWithPath: "/tmp/work/repo-alpha/.bare") 56 56 let settingsURL = SupacodePaths.onevcatRepositorySettingsURL(for: root) 57 57 58 - #expect(settingsURL.lastPathComponent == "supacode.onevcat.json") 58 + #expect(settingsURL.lastPathComponent == "prowl.onevcat.json") 59 59 #expect(settingsURL.deletingLastPathComponent().lastPathComponent == ".bare") 60 60 #expect(settingsURL.deletingLastPathComponent().deletingLastPathComponent().lastPathComponent == "repo") 61 61 }