Skip to content

Contributing to VaulType

Last Updated: 2026-02-13

How to contribute to VaulType — code, documentation, bug reports, and feature requests.


VaulType follows the Contributor Covenant Code of Conduct. By participating, you agree to:

  • Be respectful — Treat everyone with kindness and empathy
  • Be constructive — Focus on what’s best for the project and community
  • Be inclusive — Welcome people of all backgrounds and experience levels
  • No harassment — Personal attacks, trolling, and discriminatory language are not tolerated

Report violations to the maintainers via email or GitHub issues.


  1. Fork the repository
  2. Clone your fork locally
  3. Set up the development environment (see below)
  4. Create a feature branch
  5. Make changes and add tests
  6. Run the test suite
  7. Submit a pull request
TypeDescriptionGood First Issue?
Bug fixesFix reported issuesOften yes
DocumentationImprove or add docsYes
Processing modesAdd new LLM modesYes
Voice commandsAdd new commandsYes
TranslationsAdd/improve i18nYes
PerformanceOptimize inferenceUsually no
Core featuresNew major featuresUsually no
C bridgingwhisper.cpp/llama.cpp updatesNo

Look for issues labeled good first issue to get started.


ToolVersionRequired
macOS14.0 (Sonoma)+Yes
Xcode15.0+Yes
CMake3.20+Yes
Git2.30+Yes
SwiftLintLatestRecommended
create-dmgLatestFor packaging only
Terminal window
# Fork on GitHub, then:
git clone https://github.com/YOUR_USERNAME/vaultype.git
cd vaultype
# Add upstream remote
git remote add upstream https://github.com/vaultype/vaultype.git
# Install build tools
brew install cmake swiftlint
# Build C/C++ dependencies (whisper.cpp, llama.cpp)
./scripts/build-deps.sh
# Open in Xcode
open VaulType.xcodeproj
# Build and run (⌘R)
Terminal window
# Download Whisper tiny model for testing (~75MB)
./scripts/download-model.sh whisper-tiny
# (Optional) Download a small LLM for testing LLM features
./scripts/download-model.sh qwen2.5-0.5b-q4

See SETUP_GUIDE.md for detailed environment setup.


VaulType follows the Swift API Design Guidelines with these project conventions:

Enforced via SwiftLint:

.swiftlint.yml
opt_in_rules:
- closure_spacing
- empty_count
- explicit_init
- fatal_error_message
- first_where
- implicitly_unwrapped_optional
- modifier_order
- multiline_arguments
- multiline_parameters
- operator_usage_whitespace
- overridden_super_call
- private_outlet
- prohibited_super_call
- redundant_nil_coalescing
- sorted_imports
- unneeded_parentheses_in_closure_argument
- vertical_parameter_alignment_on_call
disabled_rules:
- trailing_whitespace
line_length:
warning: 120
error: 150
type_body_length:
warning: 300
error: 500
function_body_length:
warning: 50
error: 100
identifier_name:
min_length: 2
max_length: 50
excluded:
- id
- x
- y
- i
excluded:
- vendor/
- build/
- .build/
// 1. Use async/await, not completion handlers
// GOOD
func transcribe(audio: [Float]) async throws -> String
// BAD
func transcribe(audio: [Float], completion: @escaping (Result<String, Error>) -> Void)
// 2. Use structured concurrency
// GOOD
let result = try await whisperService.transcribe(audio: audioData)
// BAD
Task.detached { ... } // Avoid unless you have a specific reason
// 3. Use os_log, not print
// GOOD
Logger.whisper.info("Transcription completed in \(elapsed)ms")
// BAD
print("Transcription completed in \(elapsed)ms")
// 4. Use early returns
// GOOD
guard let model = selectedModel else {
Logger.whisper.error("No model selected")
return
}
// BAD
if let model = selectedModel {
// deeply nested code...
}
// 5. Mark protocol conformances in extensions
// GOOD
extension WhisperService: TranscriptionService {
func transcribe(...) { }
}
// BAD (don't put conformance in the main declaration for large protocols)
class WhisperService: TranscriptionService { ... }

Follow Conventional Commits:

<type>(<scope>): <description>
[optional body]
[optional footer(s)]

Types:

TypeUse For
featNew features
fixBug fixes
perfPerformance improvements
refactorCode refactoring (no behavior change)
testAdding or updating tests
docsDocumentation changes
choreBuild, CI, dependency updates
styleFormatting, SwiftLint fixes

Examples:

feat(modes): add Email processing mode
fix(injection): restore clipboard after paste injection
perf(whisper): enable batch decoding for shorter latency
docs(api): add WhisperService API examples
test(parser): add voice command edge cases
chore(deps): bump whisper.cpp to v1.7.3

  1. Sync with upstream:

    Terminal window
    git fetch upstream
    git rebase upstream/main
  2. Run the full lint and test suite:

    Terminal window
    swiftlint lint --strict
    xcodebuild test -scheme VaulType -destination "platform=macOS,arch=arm64"
  3. Check that your changes build in Release configuration:

    Terminal window
    xcodebuild build -scheme VaulType -configuration Release \
    CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO

When creating a pull request, use this template:

## Summary
Brief description of what this PR does and why.
## Changes
- [ ] Change 1
- [ ] Change 2
- [ ] Change 3
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated (if applicable)
- [ ] Manual testing performed (describe steps)
## Screenshots
(If applicable — for UI changes)
## Checklist
- [ ] Code follows project style guidelines
- [ ] SwiftLint passes with no warnings
- [ ] All existing tests pass
- [ ] New tests added for new functionality
- [ ] Documentation updated (if applicable)
- [ ] Commit messages follow Conventional Commits
- [ ] No sensitive data (API keys, credentials) in code
  1. Automated checks — CI runs build, lint, and tests
  2. Code review — At least one maintainer reviews the PR
  3. Feedback — Address review comments
  4. Approval — Maintainer approves
  5. Merge — Squash-merged to main by a maintainer
AreaWhat We Look For
CorrectnessDoes it work as intended? Edge cases handled?
TestsAre there adequate tests? Do they test the right things?
PerformanceNo unnecessary allocations, no main thread blocking
MemoryC bridging code properly frees resources
Thread safetyProper use of actors, Sendable, @MainActor
Swift styleFollows project conventions and SwiftLint rules
DocumentationPublic APIs documented, complex logic commented
SecurityNo hardcoded credentials, no unnecessary permissions

**Describe the bug**
A clear description of what the bug is.
**To Reproduce**
1. Go to '...'
2. Click on '...'
3. Speak '...'
4. See error
**Expected behavior**
What you expected to happen.
**Actual behavior**
What actually happened.
**Environment**
- VaulType version: [e.g., 0.1.0]
- macOS version: [e.g., 15.2]
- Mac model: [e.g., MacBook Pro M3, 16GB]
- Whisper model: [e.g., small]
- LLM model: [e.g., Qwen2.5-3B Q4]
**Diagnostics**
Attach the diagnostics export from Settings > Advanced > Export Diagnostics.
**Screenshots**
If applicable, add screenshots.
**Additional context**
Any other context about the problem.

🔒 Do not report security vulnerabilities via public GitHub issues. Email [email protected] with details. See SECURITY.md for the full responsible disclosure policy.


**Is your feature request related to a problem?**
A description of the problem. Example: "I'm frustrated when..."
**Describe the solution you'd like**
A clear description of what you want to happen.
**Describe alternatives you've considered**
Other solutions or features you've considered.
**Additional context**
Mockups, examples, or references.
**Target phase**
Which [roadmap phase](/docs/reference/roadmap/) does this fit into?

Features are prioritized based on:

  1. Alignment with roadmap — Does it fit the current phase?
  2. User impact — How many users would benefit?
  3. Implementation complexity — How much effort is required?
  4. Privacy preservation — Does it maintain the local-only philosophy?
  5. Maintainability — Can it be maintained long-term?

Every PR must include appropriate tests:

Change TypeRequired Tests
New processing modeUnit test for template, integration test for LLM output
New voice commandUnit test for parsing, test for all phrase variations
Bug fixTest that reproduces the bug and verifies the fix
UI changeUI test for the affected flow
C bridging changeIntegration test with real model
Performance changeBenchmark test showing improvement
Terminal window
# Unit tests (fast, no model needed)
xcodebuild test -scheme VaulType -testPlan UnitTests \
-destination "platform=macOS,arch=arm64" \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
# All tests including integration
xcodebuild test -scheme VaulType \
-destination "platform=macOS,arch=arm64" \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO

See TESTING.md for the full testing guide.



  1. Add a case to ProcessingMode enum
  2. Create a prompt template JSON in Resources/PromptTemplates/
  3. Register it in LLMService.process()
  4. Add unit tests for the template
  5. Verify it appears in the mode selector UI
  6. Update docs in LLM_PROCESSING.md

See the detailed walkthrough in DEVELOPMENT_GUIDE.md.


  1. Define the command in CommandRegistry
  2. Add regex patterns for natural language matching
  3. Implement the handler
  4. Add unit tests for parsing all phrase variations
  5. Update docs in VOICE_COMMANDS.md

See the detailed walkthrough in DEVELOPMENT_GUIDE.md.


Releases are managed by maintainers. The process:

  1. Update version in Xcode (CFBundleShortVersionString + CFBundleVersion)
  2. Update CHANGELOG.md
  3. Create a release tag: git tag v0.X.0
  4. Push the tag: git push origin v0.X.0
  5. CI automatically builds, signs, notarizes, and creates a GitHub Release

See DEPLOYMENT_GUIDE.md for the full release pipeline.


  • GitHub Issues — Bug reports and feature requests
  • GitHub Discussions — General questions and ideas
  • Pull Requests — Code and documentation contributions

All contributors are recognized in:

  • GitHub’s contributor graph
  • CHANGELOG.md release notes (for significant contributions)
  • README.md acknowledgments (for major contributors)