This document describes how the code is organised today. Paths are relative to
Sources/MacOptimizer/.
- One SwiftPM
executableTarget(MacOptimizer) and onetestTarget(MacOptimizerTests). - swift-tools 6.0, Swift 6 language mode (strict concurrency), macOS 14 or later.
- No third-party dependencies. Localized resources live in
Resources/{en,tr}.lproj.
App/MacOptimizerApp.swift has a custom @main:
- If
CLICommandRunner.shouldHandleCLI()recognises a command (status,clean,version,help), the CLI runs and the process exits. - Otherwise the SwiftUI app starts with a main window (
MainView) and aMenuBarExtra.
graph TD
Views["SwiftUI views (Views/)"] --> AppState["AppState (@MainActor, user-driven state)"]
Views --> Metrics["LiveMetricsStore (live metrics only)"]
AppState --> Coordinator["MonitoringCoordinator (one owned sampling loop)"]
Coordinator --> Monitor["SystemMonitorService (Mach, sysctl, IOKit, getifaddrs, ps)"]
Coordinator --> Metrics
Coordinator --> Telemetry["TelemetryStore (SQLite, 1 row per minute, 48 h)"]
Coordinator --> Watchdog["AutonomousGuardService (alert rules)"]
AppState --> Services["Feature services (junk, apps, duplicates, startup, updates, maintenance, audit, AI)"]
Services --> Plan["CleaningPlan (preview)"]
Plan --> Executor["SafeOperationExecutor (confirmation, re-validation, Trash)"]
Executor --> Policy["SafetyPolicyEngine + protection policies"]
Services --> Runners["SandboxedCommandRunner / SystemCommandRunner"]
Runners --> ProcExec["ProcessExecutor (no shell, timeouts, bounded output)"]
| Folder | Contents |
|---|---|
App/ |
AppState: a @MainActor ObservableObject singleton holding navigation, scan results, alerts, chat and history. MacOptimizerApp and the menu bar view. |
Core/Monitoring/ |
MonitoringCoordinator (one owned async loop), MetricsSchedulePolicy (which metric tiers are due, depending on visibility and the watchdog), LiveMetricsStore (publishes only changed metric values). |
Core/Concurrency/ |
ProcessExecutor (child processes with concurrent pipe draining, output cap, SIGTERM then SIGKILL on timeout, cancellation), runBlocking, CancellationFlag, ProgressThrottle, RingBuffer. |
Core/Security/ |
PathProtectionPolicy, ProcessProtectionPolicy, ApplicationProtectionPolicy, LaunchItemProtectionPolicy, SafetyPolicyEngine, OperationRiskClassifier, SafeOperationExecutor. |
Core/Operations/ |
CleaningPlan, CLICommandRunner, SandboxedCommandRunner (allow-list of absolute executable paths). |
Core/Telemetry/ |
TelemetryStore: SQLite in WAL mode at ~/Library/Application Support/com.osmancagrigenc.MacOptimizer/telemetry.sqlite, downsampled in SQL when read. |
Services/ |
SystemMonitorService, JunkCleanerService, AppScannerService, AppUninstallerService, AppUpdateCheckerService, DuplicateFileFinderService, StartupManagerService, MaintenanceService, PrivacyAuditService, MemoryOptimizerService (process termination only), AutonomousGuardService, AIAssistantService, NvidiaNIMService. Most are actors; the scanners are stateless Sendable classes that do blocking I/O off the cooperative thread pool. Each has a .shared instance. |
Infrastructure/AI/ |
The AIProvider protocol with two implementations: LocalHeuristicProvider (offline, default) and NvidiaNIMProvider (cloud, opt-in). |
Infrastructure/Persistence/ |
KeychainManager (kSecAttrAccessibleWhenUnlockedThisDeviceOnly), used for the NVIDIA NIM API key. |
Helpers/ |
SafetyGuard (older checks still used for processes, apps and launch items), SystemCommandRunner (runs a given executable with arguments, no shell), XMLParserHelper (Sparkle appcasts), FileSizeCalculator, MachOArchitectureDetector, VersionComparator, ByteFormatter. |
Models/ |
Value types for metrics, junk items, apps, alerts, AI and watchdog configuration. |
Views/ |
Feature screens: Dashboard, Memory, Junk Cleaner, Duplicate Finder, App Manager, Updates, Startup, Maintenance, Security, History, Watchdog, AI, Settings, plus shared components. |
L10n.swift |
Localization helper over the per-area string tables (see docs/LOCALIZATION.md). |
MonitoringCoordinator runs a single loop. Each metric tier (core, disk, battery, telemetry,
hardware, processes) has its own interval, and the loop slows down when the window is hidden:
2.5 s for core metrics while visible, 10 s while hidden with the watchdog on, 60 s while hidden
and idle. /bin/ps runs only when a process list or the watchdog needs it. Details and the
measurements behind them are in docs/PERFORMANCE_REPORT.md.
The watchdog is AutonomousGuardService, evaluated by this loop. It therefore runs only while
the app process is running; there is no LaunchAgent or background helper.
- A scan builds a
CleaningPlan. Paths are canonicalised and classified; forbidden paths and Trash items are left out of the plan. - The UI shows the plan. The CLI prints it and needs
--execute --yes. SafeOperationExecutor.removeFileevaluates the path withSafetyPolicyEngine, throws when arequiresConfirmationdecision has no confirmation, re-resolves the path before acting, and moves the item to the Trash. Permanent removal is allowed only for paths accepted byPathProtectionPolicy.isCleanableCachePath.SafeOperationExecutor.emptyTrashpermanently removes entries that are directly inside~/.Trash, after a separate confirmation.
The junk cleaner, uninstaller, duplicate finder and startup manager all call the executor with
moveToTrash: true.
SandboxedCommandRunnerruns only executables from theApprovedExecutableallow-list (dscacheutil,killall,mdutil,qlmanage,lsregister,atsutil,launchctl,csrutil,spctl,defaults,socketfilterfw), drops arguments containing shell metacharacters, and has a 15 s default timeout.SystemCommandRunnerruns a fixed executable with an argument array (used for/bin/ps,/bin/killandbrew). There is no shell execution anywhere in the app.
| Data | Where |
|---|---|
| Settings, AI and watchdog configuration, operation history (last 500) | UserDefaults (MacOptimizer_NIMConfig, MacOptimizer_AutonomousConfig, MacOptimizer_History, …) |
| NVIDIA NIM API key | Keychain |
| Telemetry time series (1 row per minute, pruned after 48 h) | SQLite file above, not encrypted |
There is no audit log of file operations.
- NVIDIA NIM (
https://integrate.api.nvidia.com/v1), only when the user enabled it. Plain HTTP is refused except for localhost. - Sparkle appcasts of installed apps (plain HTTP feeds are allowed).
- The VS Code update API.
brew, which may contact its own servers.
Scripts/build_app.shbuilds a release binary and assemblesMacOptimizer.appwith a generated Info.plist. It does not sign the app.- GitHub Actions:
ci.yml(build, full test suite, host-state canary, app bundle),release.yml(DMG and build-provenance attestation on tags, no signing yet),security.yml(Gitleaks and a dependency inventory). - Developer ID signing, notarization and a single version source are being added for v3.1.0.
AppStateis large and several views call services directly.- Two safety layers overlap:
Helpers/SafetyGuardandCore/Security. - Services are singletons without dependency injection (tests inject runners and directories where needed).
- Homebrew update detection parses
brew outdated --json=v2and has not been verified against every Homebrew version.