# How to Contribute to CodexBar: A Complete Guide for macOS Developers

> macOS developers learn how to contribute to CodexBar. Fork the repo, add features, run validations, and submit a clean pull request. Follow Swift 6 standards.

- Repository: [Peter Steinberger/CodexBar](https://github.com/steipete/CodexBar)
- Tags: how-to-guide
- Published: 2026-07-07

---

**To contribute to CodexBar, fork the repository, add your feature or provider implementation across the core and UI layers, run the validation scripts, and submit a clean pull request following the Swift 6 concurrency and linting standards.**

CodexBar is an open-source macOS menu-bar application written in Swift 6+ that aggregates usage quota data from dozens of AI coding providers. If you want to contribute to CodexBar, you'll work with a cleanly separated architecture comprising a core logic layer in `Sources/CodexBarCore` and a SwiftUI/AppKit UI layer in `Sources/CodexBar`. The project strictly follows Swift concurrency patterns with strict Sendable checking and uses a lightweight hidden-window pattern to keep the menu-bar app alive.

## Set Up Your Development Environment

Start by forking the `steipete/CodexBar` repository and cloning it locally. The project supports both Xcode and SwiftPM workflows, so you can open `CodexBar.xcodeproj` or build directly from the command line.

**Run the development scripts** to verify your setup:

```bash

# Build, test, and launch the app in one step

./Scripts/compile_and_run.sh

# Run only the test suite for fast feedback

./Scripts/compile_and_run.sh --test

# Or use the Makefile target

make test

```

Before writing code, run `make check` to execute `swiftformat` and `swiftlint --strict`. The CI pipeline enforces these checks, so formatting your code upfront prevents rework later.

## Understanding the Architecture

CodexBar follows a strict three-tier architecture that separates network logic from UI presentation. Understanding these boundaries is essential before you contribute to CodexBar.

**Core Logic Layer** (`Sources/CodexBarCore/`): Contains provider-specific fetchers under `Sources/CodexBarCore/Providers/`. The `UsageFetcher` class in [`Sources/CodexBarCore/UsageFetcher.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarCore/UsageFetcher.swift) drives background refresh, executes provider probes in parallel using Swift concurrency, and writes results to the shared store.

**UI Layer** (`Sources/CodexBar/`): Manages the menu-bar interface using `NSStatusBar` and a hidden 1×1 window (with `LSUIElement = true` in the Info.plist) to keep the SwiftUI lifecycle active. The `UsageStore` in [`Sources/CodexBar/UsageStore.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/UsageStore.swift) holds the latest snapshots, publishes updates via `@Observable`, and drives the status item UI.

**Provider Registration**: All supported providers are enumerated in [`Sources/CodexBarCore/Providers/Providers.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarCore/Providers/Providers.swift), which acts as the factory registry connecting core fetchers to their UI adapters.

## The Contribution Workflow

When you contribute to CodexBar, most changes require touching three specific areas: the provider descriptor, the fetch implementation, and the App-side UI adapter.

### Adding a New AI Provider

To add support for a new AI coding provider, first extend the provider enum in [`Sources/CodexBarCore/Providers/Providers.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarCore/Providers/Providers.swift):

```swift
public enum Provider: String, CaseIterable {
    // existing cases…
    case newprovider               // <-- add your case
}

```

Next, create a new directory under `Sources/CodexBarCore/Providers/<YourProvider>/` and implement the `UsageProvider` protocol. Your implementation must use Swift concurrency (`async/await`) and return a `ProviderUsage` struct:

```swift
// Sources/CodexBarCore/Providers/NewProvider/NewProvider.swift
import Foundation

public final class NewProvider: UsageProvider {
    public func fetchUsage() async throws -> ProviderUsage {
        let url = URL(string: "https://api.newprovider.com/v1/usage")!
        let (data, _) = try await URLSession.shared.data(from: url)
        let json = try JSONDecoder().decode(UsageResponse.self, from: data)
        return ProviderUsage(
            used: json.usedTokens,
            total: json.quotaTokens,
            reset: Date(timeIntervalSince1970: json.resetTimestamp)
        )
    }
}

```

### Creating the UI Adapter

Every core fetcher needs a corresponding UI adapter to map raw data to view models. Create a file under `Sources/CodexBar/Providers/<YourProvider>/` implementing the `ProviderAdapter` protocol:

```swift
// Sources/CodexBar/Providers/NewProvider/NewProviderAdapter.swift
import CodexBarCore

public struct NewProviderAdapter: ProviderAdapter {
    public init() {}

    public func toUsageModel(_ raw: ProviderUsage) -> UsageModel {
        UsageModel(
            provider: .newprovider,
            used: raw.used,
            total: raw.total,
            resetDate: raw.reset,
            status: raw.used < raw.total ? .ok : .over
        )
    }
}

```

Finally, register the adapter in [`Sources/CodexBar/UsageStore.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/UsageStore.swift):

```swift
private static let providerAdapters: [Provider: ProviderAdapter] = [
    // …existing mappings…
    .newprovider: NewProviderAdapter()
]

```

### Writing Tests and Documentation

Add unit tests under `Tests/CodexBarTests/` that exercise both the parsing logic and the UI-model conversion. The project uses XCTest and expects tests to run in the sharded test suite invoked by `./Scripts/compile_and_run.sh --test`.

Update the documentation for every new provider:

- Create a markdown file in `docs/` describing the provider's API requirements and authentication method.
- Add an entry to [`docs/providers.md`](https://github.com/steipete/CodexBar/blob/main/docs/providers.md) in the provider list.

## Code Standards and Validation

CodexBar uses **Swift concurrency** throughout with strict Sendable conformance and `@MainActor` hops for UI updates. All network operations must be `async` and run outside the MainActor to prevent blocking the UI thread.

**Validation checklist before submitting:**
- Run `make check` to apply `swiftformat` and verify `swiftlint --strict` passes.
- Ensure `make test` completes with zero failures.
- Verify your changes work end-to-end using [`./Scripts/compile_and_run.sh`](https://github.com/steipete/CodexBar/blob/main/./Scripts/compile_and_run.sh).
- Confirm `LSUIElement` behavior remains intact (the app should not appear in the Dock).

## Submitting Your Pull Request

When you contribute to CodexBar via pull request, follow these conventions:

1. **Title format**: Use concise, descriptive titles like "Add support for NewAI provider" or "Fix token parsing for OpenRouter".
2. **Scope**: Keep changes focused. If adding a provider, include the core fetcher, UI adapter, tests, and documentation in a single PR.
3. **CI**: Let the GitHub Actions workflow run the full validation pipeline. This executes the same checks as `make check` and `make test`.
4. **Description**: Reference the specific files modified (e.g., "[`Sources/CodexBarCore/Providers/Providers.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarCore/Providers/Providers.swift)", "[`Sources/CodexBar/UsageStore.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/UsageStore.swift)") to help reviewers navigate the architecture.

## Summary

- **Fork and clone** `steipete/CodexBar`, then use [`./Scripts/compile_and_run.sh`](https://github.com/steipete/CodexBar/blob/main/./Scripts/compile_and_run.sh) for the development loop.
- **Architecture**: Modify `Sources/CodexBarCore/Providers/` for fetch logic and `Sources/CodexBar/Providers/` for UI adapters.
- **Registration**: Update [`Sources/CodexBarCore/Providers/Providers.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBarCore/Providers/Providers.swift) and [`Sources/CodexBar/UsageStore.swift`](https://github.com/steipete/CodexBar/blob/main/Sources/CodexBar/UsageStore.swift) to wire new providers.
- **Quality**: Run `make check` and `make test` before submitting to ensure SwiftLint and SwiftFormat compliance.
- **Documentation**: Add provider-specific docs under `docs/` and update [`docs/providers.md`](https://github.com/steipete/CodexBar/blob/main/docs/providers.md) for every new integration.

## Frequently Asked Questions

### Do I need Xcode to contribute to CodexBar?

No. While you can open `CodexBar.xcodeproj` for GUI development, the project fully supports SwiftPM and command-line workflows. The [`./Scripts/compile_and_run.sh`](https://github.com/steipete/CodexBar/blob/main/./Scripts/compile_and_run.sh) script handles building, testing, and packaging from the terminal, making it possible to contribute to CodexBar using any text editor and the Swift CLI tools.

### What Swift version is required to build CodexBar?

CodexBar targets Swift 6 or later and uses strict concurrency checking. You must use Swift 6+ to compile the project, as the codebase relies on modern concurrency features like `async/await`, strict Sendable protocols, and `@MainActor` isolation for UI components.

### How do I test my provider implementation without a real API key?

The test suite in `Tests/CodexBarTests/` supports mocking network responses. Create unit tests that inject mock `Data` into your provider's decoding logic to verify parsing without making live HTTP requests. The `UsageFetcher` tests demonstrate how to validate provider behavior using stubbed JSON responses.

### Can I contribute improvements to the CLI or WidgetKit extension?

Yes. The repository includes a CLI wrapper in `Sources/CodexBarCLI/` and a WidgetKit extension in `Sources/CodexBarWidget/`. Both consume the same `UsageStore` snapshot as the main app. Follow the same testing and linting procedures when modifying these components, ensuring the widget and CLI remain synchronized with core model changes.