How to Contribute Code Changes to vorssaint-utils: A Complete Contributor's Guide
Fork the repository, run ./Tools/setup-signing.sh, build with ./build.sh, verify with --selftest, then submit a PR following the conventional commit format.
Contributing code changes to vorssaint-utils requires understanding its unique Swift-only architecture—this native macOS utility suite builds with swiftc alone, no Xcode project needed. The repository enforces strict layer separation between UI and services, uses Combine for state management, and maintains reproducible builds through stable code signing.
Prerequisites and Environment Setup
Before you can contribute code changes to vorssaint-utils, ensure you have:
- macOS 14+ running on Apple Silicon hardware
- Swift Command-Line Tools installed
- A GitHub account with fork access
Step 1: Fork and Clone
Create your personal copy of the repository and clone it locally:
git clone https://github.com/<your-username>/vorssaint-utils.git
cd vorssaint-utils
Step 2: Configure Stable Code Signing
Run the setup script to create a persistent self-signed identity. This preserves macOS permission grants across rebuilds:
./Tools/setup-signing.sh
The script generates a local certificate that build.sh uses automatically. Without this step, each build receives a new ad-hoc signature, forcing you to re-grant permissions repeatedly.
Step 3: Build and Verify
Compile the project and run the self-test to confirm your environment is ready:
./build.sh # Compiles with swiftc directly
./build/Vorssaint --selftest # Must output "SELFTEST OK"
The build.sh script in the repository root handles compilation, signing, and optional notarisation. No Xcode project exists—everything is driven by Package.swift and raw swiftc invocation.
Understanding the Architecture
The codebase follows a strict layered architecture that you must respect when contributing code changes to vorssaint-utils:
| Layer | Directory | Responsibility |
|---|---|---|
| App Lifecycle | Sources/Vorssaint/App |
Menu-bar status item, application startup |
| Core | Sources/Vorssaint/Core |
Localization, permissions, user defaults keys |
| Services | Sources/Vorssaint/Services |
All functional features—energy, system monitor, window layout |
| UI | Sources/Vorssaint/UI |
Pure SwiftUI views; never imports service logic |
| Support | Sources/Vorssaint/Support |
Diagnostic helpers for --selftest |
| Tools | Tools/ |
Icon generation, DMG packaging, signing scripts |
Critical boundary rule: UI layers observe services via Combine ObservableObject; services remain UI-agnostic. All singletons expose shared state through Type.shared and publish changes with @Published.
Key Files for Contributors
Package.swift— SwiftPM manifest enabling editor indexingSources/Vorssaint/App/main.swift— Entry point setting up the menu-bar status itemSources/Vorssaint/Core/Localization.swift— Centralized string catalog; all user-facing text lives hereSources/Vorssaint/Services/— Feature implementations likeSystemMonitor,WindowLayout,FanControlHelperTools/setup-signing.sh— Creates stable signing identityCONTRIBUTING.md— Full workflow and style conventions
Making Code Changes: Step-by-Step
Step 4: Implement Your Feature
When contributing code changes to vorssaint-utils, follow these conventions:
- Add functionality to Services — Create or modify files under
Sources/Vorssaint/Services/ - Expose state via Combine — Use
ObservableObject,@Published, and astatic let sharedsingleton - Build UI that observes only — Place views under
Sources/Vorssaint/UI/; never call service logic directly from views - Localize all strings — Add entries to
Core/Localization.swiftand provide translations inCore/Localizations/for every supported language
Practical Example: Adding a Battery Health Service
Here's how to add a new service and expose it to the UI, following the project's patterns.
Service implementation (Sources/Vorssaint/Services/BatteryHealth.swift):
import Combine
import Foundation
final class BatteryHealth: ObservableObject {
static let shared = BatteryHealth()
@Published var healthPercentage: Double = 100.0
private init() {
Timer.publish(every: 60, on: .main, in: .common)
.autoconnect()
.sink { _ in self.updateHealth() }
.store(in: &cancellables)
}
private var cancellables = Set<AnyCancellable>()
private func updateHealth() {
// Placeholder—actual implementation reads IOKit data
healthPercentage = max(0, healthPercentage - 0.1)
}
}
UI view (Sources/Vorssaint/UI/Settings/BatteryHealthView.swift):
import SwiftUI
struct BatteryHealthView: View {
@ObservedObject private var model = BatteryHealth.shared
var body: some View {
VStack {
Text("Battery Health: \(Int(model.healthPercentage)) %")
ProgressView(value: model.healthPercentage, total: 100)
}
.padding()
}
}
Then add the view to your settings navigation and update Core/Localization.swift with new string keys.
Step 5: Test Your Changes
After modifying code, always re-verify:
./build.sh
./build/Vorssaint --selftest
For manual UI testing:
./build.sh --install # Installs to /Applications and launches
Maintainers test on physical hardware, so confirm your changes work on real Apple Silicon Macs.
Submitting Your Contribution
Step 6: Open a Pull Request
The repository enforces specific PR conventions for contributing code changes to vorssaint-utils:
- One topic per PR — Atomic changes only
- Title format:
type(scope): lowercase imperative phrase- Valid types:
feat,fix,docs,refactor,test - Example:
feat(monitor): expose GPU temperature
- Valid types:
- Reference issues: Add
Refs #123(multiple:Refs #123, #456) - Do not edit
CHANGELOG.md— Maintainers handle release notes
The PR template at .github/PULL_REQUEST_TEMPLATE.md guides you through required sections. Describe before/after behavior clearly.
Step 7: Review and Merge
After maintainer review, your PR is squash-merged. Build verification happens on maintainer hardware, so ensure you've tested thoroughly locally.
Summary
- Environment: macOS 14+, Apple Silicon, Command-Line Tools—no Xcode needed
- Setup: Fork, clone, run
./Tools/setup-signing.sh, build with./build.sh, verify with--selftest - Architecture: Strict layers—Services contain logic, UI observes via Combine, Core holds localization
- Patterns: Singleton
sharedinstances,@Publishedstate,Localization.swiftfor all strings - PR requirements: Conventional commit titles, issue references, atomic changes, no CHANGELOG edits
Frequently Asked Questions
Do I need Xcode to contribute to vorssaint-utils?
No. The project builds purely with swiftc via build.sh. Package.swift provides editor support for indexing, but no .xcodeproj exists. This design keeps dependencies minimal and builds reproducible.
Why does the signing setup matter for local development?
Without ./Tools/setup-signing.sh, each build receives a fresh ad-hoc signature. macOS treats these as distinct applications, forcing you to re-grant permissions (accessibility, screen recording, etc.) after every compile. The setup script creates a stable identity that persists across rebuilds.
How do I add user-facing text to the application?
All strings live in Sources/Vorssaint/Core/Localization.swift. Add your key there, then provide translations in Sources/Vorssaint/Core/Localizations/ for every supported language. The Swift compiler enforces completeness—missing translations cause build failures.
What hardware do I need to test my changes?
You need an Apple Silicon Mac running macOS 14 or later. The self-test runs locally, but maintainers verify PRs on physical hardware. Features depending on system sensors (temperature, fan speed, power metrics) cannot be fully tested in virtualized environments.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →