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

Making Code Changes: Step-by-Step

Step 4: Implement Your Feature

When contributing code changes to vorssaint-utils, follow these conventions:

  1. Add functionality to Services — Create or modify files under Sources/Vorssaint/Services/
  2. Expose state via Combine — Use ObservableObject, @Published, and a static let shared singleton
  3. Build UI that observes only — Place views under Sources/Vorssaint/UI/; never call service logic directly from views
  4. Localize all strings — Add entries to Core/Localization.swift and provide translations in Core/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
  • 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 shared instances, @Published state, Localization.swift for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →