First off, thank you for considering contributing to Claude Usage Tracker! 🎉
This document provides guidelines and information about contributing to this project. We welcome contributions of all kinds: bug reports, feature requests, documentation improvements, and code contributions.
- Code of Conduct
- Getting Started
- How to Contribute
- Development Guidelines
- Pull Request Process
- Release Process
- Getting Help
This project adheres to a code of conduct that all contributors are expected to follow. Please be respectful, inclusive, and considerate in all interactions.
Our Standards:
- Be welcoming and inclusive
- Be respectful of differing viewpoints
- Accept constructive criticism gracefully
- Focus on what's best for the community
- Show empathy towards other community members
Before you begin, ensure you have the following installed:
- macOS 14.0+ (Sonoma or later)
- Xcode 15.0+ (latest stable recommended)
- Git for version control
- A Claude AI account for testing (to obtain a session key)
-
Fork the repository
Click the "Fork" button on GitHub to create your own copy.
-
Clone your fork
git clone https://github.com/YOUR_USERNAME/Claude-Usage-Tracker.git cd Claude-Usage-Tracker -
Add upstream remote
git remote add upstream https://github.com/hamed-elfayome/Claude-Usage-Tracker.git
-
Open in Xcode
open "Claude Usage.xcodeproj" -
Build and run
- Select the "Claude Usage" scheme
- Press
⌘Rto build and run - The app will appear in your menu bar
-
Configure for testing
- Extract your session key from claude.ai (see README for instructions)
- The app will guide you through setup on first launch
Claude Usage/
├── App/
│ ├── AppDelegate.swift # App lifecycle, notifications setup
│ └── ClaudeUsageTrackerApp.swift # SwiftUI app entry point
│
├── MenuBar/
│ ├── MenuBarManager.swift # Status item, popover management
│ └── PopoverContentView.swift # Main UI for usage display
│
├── Views/
│ ├── SettingsView.swift # Settings window with tabs
│ └── SetupWizardView.swift # First-run configuration
│
├── Shared/
│ ├── Extensions/ # Date, UserDefaults extensions
│ ├── Models/
│ │ ├── ClaudeUsage.swift # Usage data model
│ │ └── ClaudeStatus.swift # API status model
│ ├── Services/
│ │ ├── ClaudeAPIService.swift # API communication
│ │ ├── ClaudeStatusService.swift
│ │ ├── NotificationManager.swift
│ │ └── StatuslineService.swift # Claude Code integration
│ ├── Storage/
│ │ └── DataStore.swift # UserDefaults wrapper
│ └── Utilities/
│ ├── Constants.swift # App-wide constants
│ └── FormatterHelper.swift # Formatting utilities
│
├── Assets.xcassets/ # Images, colors, icons
└── Resources/
└── Info.plist # App configuration
Before submitting a bug report:
- Check existing issues to avoid duplicates
- Ensure you're running the latest version
When reporting a bug, include:
- macOS version (e.g., macOS 14.2)
- App version (found in Settings → About)
- Steps to reproduce the issue
- Expected behavior vs. actual behavior
- Screenshots if applicable
- Relevant Console.app logs (filter by "Claude Usage")
We love feature suggestions! Please:
- Check existing issues and discussions first
- Describe the problem your feature would solve
- Explain your proposed solution
- Consider alternative approaches
- Find or create an issue for what you want to work on
- Comment on the issue to let others know you're working on it
- Fork and create a branch (see Branch Naming)
- Make your changes following our guidelines
- Test thoroughly on macOS 14.0+
- Submit a pull request
We follow Swift API Design Guidelines and standard SwiftUI practices.
Key conventions:
// MARK: - Use MARK comments to organize code sections
// MARK: - Properties
// MARK: - Initialization
// MARK: - Public Methods
// MARK: - Private Methods
// Use descriptive names
func fetchUsageData() async throws -> ClaudeUsage // ✅ Good
func getData() async throws -> ClaudeUsage // ❌ Avoid
// Document public APIs
/// Fetches the current usage data from Claude's API
/// - Returns: A `ClaudeUsage` object with current session and weekly usage
/// - Throws: `APIError` if the request fails
func fetchUsageData() async throws -> ClaudeUsage
// Use Swift's type inference where clear
let usage = ClaudeUsage.empty // ✅ Good
let usage: ClaudeUsage = ClaudeUsage.empty // ❌ Redundant
// Prefer structs for data models
struct ClaudeUsage: Codable, Equatable { ... }
// Use enums for constants and configurations
enum Constants {
static let sessionWindow: TimeInterval = 5 * 60 * 60
}SwiftUI specific:
// Extract complex views into separate structs
struct SmartUsageCard: View {
let title: String
let percentage: Double
var body: some View {
// Keep body focused and readable
}
}
// Use @State for local view state
// Use @Published in ObservableObject for shared state
// Use @Environment for system values
// Prefer declarative modifiers over imperative code
Text("Usage")
.font(.headline)
.foregroundColor(.primary)This project follows the MVVM (Model-View-ViewModel) pattern:
- Models (
Shared/Models/): Data structures, pure Swift - Views (
Views/,MenuBar/): SwiftUI views, presentation only - ViewModels/Managers (
MenuBar/MenuBarManager.swift): Business logic, state management - Services (
Shared/Services/): API calls, system interactions
Guidelines:
- Keep views "dumb" - they should only display data
- Put business logic in managers/services
- Use dependency injection where possible
- Prefer
async/awaitover completion handlers
We follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Formatting, no code changerefactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementtest: Adding or updating testschore: Build process, dependencies, etc.
Examples:
feat(api): add support for Opus weekly usage tracking
fix(menubar): resolve icon not updating on appearance change
docs(readme): add Claude Code statusline setup instructions
refactor(services): extract notification logic to NotificationManager
Use descriptive branch names with prefixes:
| Prefix | Use Case | Example |
|---|---|---|
feat/ |
New features | feat/historical-data-chart |
fix/ |
Bug fixes | fix/session-reset-notification |
docs/ |
Documentation | docs/add-contributing-guide |
refactor/ |
Code refactoring | refactor/extract-api-service |
chore/ |
Maintenance | chore/update-dependencies |
-
Update your fork
git fetch upstream git rebase upstream/main
-
Create your branch
git checkout -b feat/your-feature-name
-
Make your changes
- Write clean, documented code
- Follow the style guidelines
- Test on macOS 14.0+
-
Commit your changes
git add . git commit -m "feat(scope): description of changes"
-
Push to your fork
git push origin feat/your-feature-name
-
Open a Pull Request
- Use a clear, descriptive title
- Reference any related issues (
Closes #123) - Describe what changes you made and why
- Include screenshots for UI changes
- List any breaking changes
-
Code Review
- Respond to feedback promptly
- Make requested changes
- Keep the PR focused - one feature/fix per PR
PR Checklist:
- Code follows project style guidelines
- Self-reviewed my own code
- Added comments for complex logic
- Updated documentation if needed
- Tested on macOS 14.0+
- No new warnings in Xcode
- UI changes include screenshots
Releases are automated via GitHub Actions. See .github/README.md for technical details.
Quick reference:
# 1. Bump MARKETING_VERSION in project.pbxproj
# 2. Update CHANGELOG.md
# 3. Commit and tag
git commit -am "chore: bump version to X.Y.Z"
git tag vX.Y.Z
git push origin main --tags
# 4. Workflow creates draft release with assets
# 5. Review and publish at github.com/.../releases- Questions? Open a Discussion
- Found a bug? Open an Issue
- Want to chat? Reach out to maintainers
Contributors are recognized in:
- The GitHub contributors graph
- Release notes for significant contributions
- README acknowledgments for major features
Thank you for helping make Claude Usage Tracker better! 🙏