FanControl/holds the SwiftUI app sources. Key files includeContentView.swift(UI),FanVM.swift(view model), andSMCService.swift(SMC service wrapper)Shared/contains shared models and SMC access (Fan.swift,SMCClient.swift,FanControlXPC.swift) used by both the app and the helperFanControlHelper/is the privileged helper target (XPC listener entry inmain.swift)FanControl/LaunchDaemons/contains the launchd plist for SMAppService (dev.topscrech.FanControl.helper.plist)FanControl/Assets.xcassetsstores app assets/iconsFanControl.xcodeprojis the Xcode project. There is no separate test target orTests/directory in the repo
- Build (Debug):
xcodebuild -project FanControl.xcodeproj -scheme FanControl -configuration Debug -derivedDataPath ~/Library/Developer/Xcode/DerivedData/FanControl build - Build (Release):
xcodebuild -project FanControl.xcodeproj -scheme FanControl -configuration Release -derivedDataPath ~/Library/Developer/Xcode/DerivedData/FanControl build - Never use
-derivedDataPath ./build(or any project-relative path) because it creates local DerivedData/build artifacts inside the repo - Publish all new GitHub releases as pre-releases first so they can be manually validated before general availability
- Swift standard style: 4-space indentation, braces on the same line, trailing commas allowed in multi-line literals
- Naming:
UpperCamelCasefor types (structs/classes/enums),lowerCamelCasefor methods and properties, enum cases inlowerCamelCase - Keep UI updates on the main actor (
@Observable,@MainActor) and keep SMC access isolated inSMCClient - No formatter or linter is configured; match existing file formatting
- Current state: no automated tests
- If adding tests, create an Xcode test target (e.g.,
FanControlTests) and useXCTestwith files namedSomethingTests.swift - Prefer unit tests for SMC parsing and VM logic; avoid hardware writes in tests
- SMC writes require elevated privileges. Manual fan control uses a privileged helper registered via
SMAppService - The helper is installed from
FanControl/LaunchDaemonsand runs as root; keep the Mach service name inShared/FanControlXPC.swiftin sync with the plist - Avoid committing local paths, DerivedData artifacts, or credentials