# How to Contribute Code Changes to vorssaint-utils: A Complete Contributor's Guide

> Learn how to contribute code changes to vorssaint-utils. Follow this guide to fork, build, verify, and submit your PRs for the vorssaint-utils repository.

- Repository: [vorssaint/vorssaint-utils](https://github.com/vorssaint/vorssaint-utils)
- Tags: how-to-guide
- Published: 2026-09-05

---

**Fork the repository, run [`./Tools/setup-signing.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/./Tools/setup-signing.sh), build with [`./build.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/./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:

```bash
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:

```bash
./Tools/setup-signing.sh

```

The script generates a local certificate that [`build.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/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:

```bash
./build.sh                     # Compiles with swiftc directly

./build/Vorssaint --selftest   # Must output "SELFTEST OK"

```

The [`build.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/build.sh) script in the repository root handles compilation, signing, and optional notarisation. No Xcode project exists—everything is driven by [`Package.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/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`](https://github.com/vorssaint/vorssaint-utils/blob/main/Package.swift)** — SwiftPM manifest enabling editor indexing
- **[`Sources/Vorssaint/App/main.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/App/main.swift)** — Entry point setting up the menu-bar status item
- **[`Sources/Vorssaint/Core/Localization.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Core/Localization.swift)** — Centralized string catalog; all user-facing text lives here
- **`Sources/Vorssaint/Services/`** — Feature implementations like `SystemMonitor`, `WindowLayout`, `FanControlHelper`
- **[`Tools/setup-signing.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/Tools/setup-signing.sh)** — Creates stable signing identity
- **[`CONTRIBUTING.md`](https://github.com/vorssaint/vorssaint-utils/blob/main/CONTRIBUTING.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:

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`](https://github.com/vorssaint/vorssaint-utils/blob/main/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`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/BatteryHealth.swift)):

```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`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/UI/Settings/BatteryHealthView.swift)):

```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`](https://github.com/vorssaint/vorssaint-utils/blob/main/Core/Localization.swift) with new string keys.

### Step 5: Test Your Changes

After modifying code, always re-verify:

```bash
./build.sh
./build/Vorssaint --selftest

```

For manual UI testing:

```bash
./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`](https://github.com/vorssaint/vorssaint-utils/blob/main/CHANGELOG.md)** — Maintainers handle release notes

The PR template at [`.github/PULL_REQUEST_TEMPLATE.md`](https://github.com/vorssaint/vorssaint-utils/blob/main/.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`](https://github.com/vorssaint/vorssaint-utils/blob/main/./Tools/setup-signing.sh), build with [`./build.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/./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`](https://github.com/vorssaint/vorssaint-utils/blob/main/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`](https://github.com/vorssaint/vorssaint-utils/blob/main/build.sh). [`Package.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/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`](https://github.com/vorssaint/vorssaint-utils/blob/main/./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`](https://github.com/vorssaint/vorssaint-utils/blob/main/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.