Goal
Move the macOS experience toward a SwiftUI-first shell while keeping the existing web frontend and backend behavior intact until parity is proven.
Non-negotiables
- Keep the menu bar icon and native macOS app feel.
- Keep the web frontend available during the migration.
- Keep the backend behavior stable while implementation details move.
- Keep the fixed loopback port behavior stable for the launcher.
Phases
-
Audit Python usage
- Identify Python code that is core app logic versus deployment glue.
- Classify each script by whether it can be replaced immediately, later, or not at all.
-
SwiftUI app shell
- Build a native SwiftUI shell for the menu bar app, preferences, and onboarding.
- Preserve the current open-on-launch and auto-open browser behavior.
-
Swift launcher and preferences
- Move startup, restart, port checks, and settings persistence into Swift.
- Keep the runtime contract identical until the UI is fully stable.
-
Replace Python glue
- Convert deployment helpers and maintenance scripts one by one.
- Keep the backend observable behavior unchanged while swapping implementations.
-
Parity validation
- Verify scan start, scan completion, reports, and local UI behavior.
- Verify launch-at-login, restart, timeout handling, and browser auto-open.
Parity checks
- App launches from the macOS bundle.
- Menu bar icon appears.
- Browser opens automatically after readiness.
http://127.0.0.1:9000 stays the default UI entrypoint.
- First scan completes successfully.
- Reports and settings still persist correctly.
Recommended first slice
- Extract the current launcher and settings into a SwiftUI-friendly shell.
- Keep the web frontend untouched.
- Replace the brittle Python deployment helpers after the shell is stable.
Goal
Move the macOS experience toward a SwiftUI-first shell while keeping the existing web frontend and backend behavior intact until parity is proven.
Non-negotiables
Phases
Audit Python usage
SwiftUI app shell
Swift launcher and preferences
Replace Python glue
Parity validation
Parity checks
http://127.0.0.1:9000stays the default UI entrypoint.Recommended first slice