This document provides guidance for GitHub Copilot when working on the Home Assistant iOS application.
Home Assistant for Apple Platforms is a native iOS, watchOS, and macOS application, with it's main interaction through a WKWebView displaying Home Assistant web app UI, written in Swift that provides a companion app for Home Assistant home automation. The project uses:
- Language: Swift 5.8+
- Minimum iOS version: Check deployment target in project settings
- Architecture: Multi-platform (iOS, watchOS, macOS, CarPlay)
- Dependencies: CocoaPods
- Build system: Xcode 15.3+
The project uses automated formatting tools. All code must pass these linters:
-
SwiftFormat: Enforces consistent code formatting (
.swiftformatconfiguration)- Max line width: 120 characters
- Use
before-firstwrapping style for arguments, parameters, and collections selfkeyword only in initializers- Guard else on same line
-
SwiftLint: Enforces Swift code quality rules (
.swiftlint.ymlconfiguration)- Enabled rules include: cyclomatic_complexity, force_cast, force_try, unused_optional_binding, weak_delegate
- Custom rule: Do not assign to
Currentenvironment variables outside of tests - Custom rule: Use
SFSafeSymbolsviasystemSymbolparameters instead of string-based system image names
-
Rubocop: For Ruby/Fastlane files
-
YamlLint: For YAML configuration files
- Use Swift's modern language features (async/await, Combine where appropriate)
- Prefer value types (structs) over reference types (classes) when appropriate
- Use proper access control (
private,fileprivate,internal,public) - Avoid force unwrapping (
!) and force casting unless absolutely necessary - Use guard statements for early returns
- Keep cyclomatic complexity low (use helper methods to break down complex logic)
Always use SFSafeSymbols library for type-safe SF Symbol references instead of string-based APIs:
// ❌ Avoid
Image(systemName: "house")
// ✅ Prefer
Image(systemSymbol: .house)Do not assign to Current environment variables outside of test code. This is enforced by a custom SwiftLint rule.
Sources/App- Main iOS applicationSources/Shared- Shared code between platforms (iOS, watchOS, macOS)Sources/Watch- watchOS specific codeSources/MacBridge- macOS specific codeSources/CarPlay- CarPlay integrationSources/Extensions- App Extensions (widgets, notifications, etc.)Tests/- Test filesConfiguration/- Build configuration files
# Install dependencies via Bundler and CocoaPods
bundle install
bundle exec pod install --repo-updateDebug builds use Automatic provisioning. Create Configuration/HomeAssistant.overrides.xcconfig:
DEVELOPMENT_TEAM = YourTeamID
BUNDLE_ID_PREFIX = some.bundle.prefix
# Check for linting problems
bundle exec fastlane lint
# Auto-fix linting problems
bundle exec fastlane autocorrectOpen HomeAssistant.xcworkspace in Xcode and run tests using the Test navigator (⌘U) or run scheme-specific tests.
The project uses a dependency injection pattern via the Current environment object for testability. Access shared services through this interface.
Use the existing HAConnectionInfo and related APIs for communicating with Home Assistant servers. Networking code is in Sources/Shared/Networking.
Use the existing database layer in Sources/Shared/Database for storing persistent data.
- Follow Apple's Human Interface Guidelines
- Support both light and dark mode
- Use SwiftUI where appropriate, UIKit where needed for older patterns
- Material Design Icons are available via the
MaterialDesignIconsintegration
- Write unit tests for business logic
- Follow existing test patterns in the
Tests/directory - Mock external dependencies using the test environment setup
- Tests exclude SwiftLint enforcement but should still follow Swift best practices
Dependencies are managed via CocoaPods. Add new dependencies sparingly and discuss in PR reviews.
CI runs on GitHub Actions:
- Linting (SwiftFormat, SwiftLint, Rubocop, YamlLint)
- Unit tests
- Build verification
- Deployment to App Store Connect (on release)
- Follow the pull request template
- Include screenshots for UI changes (light and dark mode)
- Ensure all linters pass
- Update documentation if adding/changing functionality
- Link related documentation PRs in companion.home-assistant repository