# How to Contribute to the FluidVoice Project: A Complete Guide for Open-Source Contributors

> Learn how to contribute to the FluidVoice project. Follow our guide to fork the repo, run tests, implement changes, and submit a pull request to join our open-source community.

- Repository: [ALTIC/FluidVoice](https://github.com/altic-dev/FluidVoice)
- Tags: how-to-guide
- Published: 2026-08-16

---

**To contribute to FluidVoice, fork the repository, open `Fluid.xcodeproj` in Xcode, run the test suite with `xcodebuild test`, implement your changes in the relevant Swift files, run [`./scripts/format-and-lint.sh`](https://github.com/altic-dev/FluidVoice/blob/main/./scripts/format-and-lint.sh), and submit a pull request following the repository's guidelines.**

FluidVoice is an open-source macOS dictation application built with **SwiftUI** and a modular architecture of Swift services. Understanding how its components interact will help you make effective contributions that get merged quickly. This guide walks through the contribution workflow while explaining the core architecture you need to navigate.

## Understanding the FluidVoice Architecture

Before writing code, familiarize yourself with how the application is structured. The codebase follows a layered pattern with clear separation between UI, services, and providers.

### App Entry Point and Global State

The application launches through `FluidApp` in [`Sources/Fluid/fluidApp.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/fluidApp.swift). This file sets up global state objects including `MenuBarManager` and `AppServices`, then injects them into the SwiftUI view hierarchy. This is the first place to check when tracing how data flows through the app.

### The Service Container Pattern

`AppServices` in [`Sources/Fluid/Services/AppServices.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/AppServices.swift) implements a **lazy singleton** pattern. It holds heavyweight services—the audio observer, ASR (automatic speech recognition), and microphone coordinator—and protects the launch sequence with a "UI-ready" gate. Understanding this pattern matters because race conditions here are a common source of bugs.

### Menu Bar and Overlay Coordination

`MenuBarManager` in [`Sources/Fluid/Services/MenuBarManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/MenuBarManager.swift) creates the status bar item, forwards ASR state changes to the UI, and coordinates notch overlay visibility. This becomes especially important during **AI post-processing** when the overlay displays transcription status.

### Speech and AI Provider System

Multiple providers implement the `TranscriptionProvider` protocol:

| Provider | Purpose | Location |
|----------|---------|----------|
| `AppleSpeechProvider` | Native macOS speech recognition | `Sources/Fluid/Services/` |
| `ParakeetRealtimeProvider` | Real-time streaming ASR | `Sources/Fluid/Services/` |
| `NemotronProvider` | AI-powered text processing | `Sources/Fluid/Services/` |
| `LLMClient` | General language model interface | `Sources/Fluid/Services/` |

These providers feed raw transcripts to `ASRService` in [`Sources/Fluid/Services/ASRService.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/ASRService.swift), which drives the overlay UI. Adding new speech model support typically means creating a new provider implementation.

### UI View Layer

The main window is hosted in `ContentView`, with specialized sub-views for different interaction modes:

- `CommandModeView` — voice command interface
- `RewriteModeView` — text rewriting functionality  
- `BottomOverlayView` — live transcription display
- `AutomaticDictionaryCorrectionOverlay` —dictionary correction UI

Each view file in `Sources/Fluid/Views/` demonstrates a distinct interaction pattern worth studying before making UI changes.

### Persistence and Analytics

`SettingsStore` (a shared `ObservableObject`) handles user preferences, while `AnalyticsService` in [`Sources/Fluid/Analytics/AnalyticsService.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Analytics/AnalyticsService.swift) manages optional anonymous telemetry. Both use standard Swift concurrency patterns.

### Testing Infrastructure

Integration tests live under `Tests/FluidDictationIntegrationTests/` and verify audio pipelines, hotkey handling, and AI post-processing. The test [`TypingServiceTransientPasteboardTests.swift`](https://github.com/altic-dev/FluidVoice/blob/main/TypingServiceTransientPasteboardTests.swift) shows how to structure new test cases.

## Step-by-Step Contribution Workflow

### 1. Fork and Clone the Repository

```bash
git clone https://github.com/<your-username>/FluidVoice.git
cd FluidVoice

```

Replace `<your-username>` with your GitHub username.

### 2. Open in Xcode

FluidVoice uses **Swift Package Manager** for dependencies. Opening the project file pulls everything automatically:

```bash
open Fluid.xcodeproj

```

### 3. Run the Application Locally

Press **⌘R** in Xcode to build and run. The first launch requests two critical permissions:

- **Microphone access** — required for audio capture
- **Accessibility access** — required for system-wide dictation

Grant both in System Settings under Privacy & Security.

### 4. Verify the Test Suite Passes

Run tests before making changes to establish a baseline:

```bash
xcodebuild test -project Fluid.xcodeproj -scheme Fluid -destination 'platform=macOS'

```

All tests must pass before submitting a pull request.

### 5. Implement Your Changes

Scope each contribution to **one feature or bug fix**. Common contribution types include:

- **New speech provider**: Add a file in `Sources/Fluid/Services/` following existing `*Provider.swift` patterns
- **UI improvements**: Modify the relevant view in `Sources/Fluid/Views/`
- **Race condition fixes**: Target `AppServices` or `MenuBarManager` synchronization
- **New integration tests**: Add files under `Tests/FluidDictationIntegrationTests/`

### 6. Run Linting and Formatting

The repository enforces consistent code style. Run the provided script before committing:

```bash
./scripts/format-and-lint.sh

```

This prevents CI failures due to formatting issues.

### 7. Submit a Pull Request

Push your branch and open a PR on the upstream repository. The PR template requires:

- Clear description of the change
- Linked issue or discussion reference
- Screenshots or screen recordings for UI changes

**Critical security rule**: Never commit personal team IDs or API keys. Automated CI checks will reject such pull requests.

### 8. Respond to Review Feedback

Maintainers may request changes. Update your branch and push—the PR updates automatically. Quick response to feedback accelerates merge time.

## Key Files Every Contributor Should Study

| File | Purpose | Why It Matters |
|------|---------|--------------|
| [`Sources/Fluid/fluidApp.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/fluidApp.swift) | App launch and dependency injection | Shows how global objects are wired together |
| [`Sources/Fluid/Services/AppServices.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/AppServices.swift) | Lazy service initialization | Model for managing expensive resources |
| [`Sources/Fluid/Services/MenuBarManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/MenuBarManager.swift) | Status bar and overlay coordination | Critical for UI state synchronization |
| [`Sources/Fluid/Services/ASRService.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/ASRService.swift) | Core speech-to-text pipeline | Understanding this unlocks provider contributions |
| [`Sources/Fluid/Views/CommandModeView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Views/CommandModeView.swift) | Primary interaction view | Reference for SwiftUI patterns in the codebase |
| `Tests/FluidDictationIntegrationTests/` | Integration test suite | Template for verifying your changes |

## Summary

- **Fork and clone** the FluidVoice repository to your GitHub account
- **Open `Fluid.xcodeproj`** to automatically resolve Swift Package Manager dependencies
- **Run `xcodebuild test`** to verify all tests pass before making changes
- **Scope contributions narrowly** — one feature or fix per pull request
- **Execute [`./scripts/format-and-lint.sh`](https://github.com/altic-dev/FluidVoice/blob/main/./scripts/format-and-lint.sh)** before committing to satisfy CI requirements
- **Study key files** in `Sources/Fluid/Services/` and `Sources/Fluid/Views/` to understand architectural patterns
- **Never include personal credentials** — team IDs and API keys will cause automatic PR rejection

The complete contribution guidelines are maintained in the repository's [[`CONTRIBUTING.md`](https://github.com/altic-dev/FluidVoice/blob/main/CONTRIBUTING.md)](https://github.com/altic-dev/FluidVoice/blob/main/CONTRIBUTING.md).

## Frequently Asked Questions

### What programming skills do I need to contribute to FluidVoice?

You need proficiency in **Swift** and familiarity with **SwiftUI** and **Combine** frameworks. Experience with macOS development, AVFoundation for audio, and natural language processing helps for specific contributions, but the codebase follows standard patterns that intermediate iOS/macOS developers can learn quickly.

### Can I contribute without a paid Apple Developer account?

Yes. You can build and run FluidVoice locally with a free Apple ID for development and testing. However, you won't be able to notarize or distribute builds, which is only necessary for maintainers preparing releases.

### How do I add support for a new speech recognition provider?

Create a new file in `Sources/Fluid/Services/` that implements the `TranscriptionProvider` protocol. Follow the pattern in [`AppleSpeechProvider.swift`](https://github.com/altic-dev/FluidVoice/blob/main/AppleSpeechProvider.swift) or [`ParakeetRealtimeProvider.swift`](https://github.com/altic-dev/FluidVoice/blob/main/ParakeetRealtimeProvider.swift). Your provider must handle audio stream input, emit transcription events, and properly manage lifecycle states. Add corresponding tests in `Tests/FluidDictationIntegrationTests/` before submitting your PR.

### Where should I report bugs or request features?

FluidVoice uses GitHub Issues. Check existing issues first to avoid duplicates. For feature requests, describe the use case clearly—specifically how it improves the dictation workflow. For bugs, include macOS version, hardware details, and steps to reproduce with any relevant crash logs from the Console app.