## Vibeviewer

English | [简体中文](README.zh-CN.md)

![Swift](https://img.shields.io/badge/Swift-5.10-orange?logo=swift)
![Xcode](https://img.shields.io/badge/Xcode-15.4%2B-blue?logo=xcode)
![macOS](https://img.shields.io/badge/macOS-14%2B-black?logo=apple)
![License](https://img.shields.io/badge/License-MIT-green)
![Release](https://img.shields.io/badge/Release-DMG-purple)

![Preview](Images/image.png)

**Tags**: `swift`, `swiftui`, `xcode`, `tuist`, `macos`, `menu-bar`, `release`

An open-source macOS menu bar app that surfaces workspace/team usage and spend at a glance, with sign-in, settings, auto-refresh, and sharing capabilities. The project follows a modular Swift Package architecture and a pure SwiftUI MV (not MVVM) approach, emphasizing clear boundaries and replaceability.

### Features
- **Menu bar summary**: Popover shows key metrics and recent activity:
  - **Billing overview**, **Free usage** (when available), **On‑demand** (when available)
  - **Total credits usage** with smooth numeric transitions
  - **Requests compare (Today vs Yesterday)** and **Usage events**
  - Top actions: **Open Dashboard** and **Log out**
- **Sign-in & Settings**: Dedicated windows with persisted credentials and preferences.
- **Power-aware refresh**: Smart refresh strategy reacting to screen power/activity state.
- **Modular architecture**: One-way dependencies Core ← Model ← API ← Feature; DTO→Domain mapping lives in API only.
- **Sharing components**: Built-in fonts and assets to generate shareable views.

### Notes
- Currently developed and tested against **team accounts** only. Individual/free accounts are not yet verified — contributions for compatibility are welcome.
- Thanks to the modular layered design, although Cursor is the present data source, other similar apps can be integrated by implementing the corresponding data-layer interfaces — PRs are welcome.
- The app currently has no logo — designers are welcome to contribute one.

> Brand and data sources are for demonstration. The UI never sees concrete networking implementations — only service protocols and default implementations are exposed.

---

## Architecture & Structure

Workspace with multiple Swift Packages (one-way dependency: Core ← Model ← API ← Feature):

```
Vibeviewer/
├─ Vibeviewer.xcworkspace           # Open this workspace
├─ Vibeviewer/                      # Thin app shell (entry only)
├─ Packages/
│  ├─ VibeviewerCore/               # Core: utilities/extensions/shared services
│  ├─ VibeviewerModel/              # Model: pure domain entities (value types/Sendable)
│  ├─ VibeviewerAPI/                # API: networking/IO + DTO→Domain mapping (protocols exposed)
│  ├─ VibeviewerAppEnvironment/     # Environment injection & cross-feature services
│  ├─ VibeviewerStorage/            # Storage (settings, credentials, etc.)
│  ├─ VibeviewerLoginUI/            # Feature: login UI
│  ├─ VibeviewerMenuUI/             # Feature: menu popover UI (main)
│  ├─ VibeviewerSettingsUI/         # Feature: settings UI
│  └─ VibeviewerShareUI/            # Feature: sharing components & assets
└─ Scripts/ & Makefile              # Tuist generation, clean, DMG packaging
```

Key rules (see also `./.cursor/rules/architecture.mdc`):
- **Placement & responsibility**
  - Core/Shared → utilities & extensions
  - Model → pure domain data
  - API/Service → networking/IO/3rd-party orchestration and DTO→Domain mapping
  - Feature/UI → SwiftUI views & interactions consuming service protocols and domain models only
- **Dependency direction**: Core ← Model ← API ← Feature (no reverse dependencies)
- **Replaceability**: API exposes service protocols + default impl; UI injects via `@Environment`, never references networking libs directly
- **SwiftUI MV**:
  - Use `@State`/`@Observable`/`@Environment`/`@Binding` for state
  - Side effects in `.task`/`.onChange` (lifecycle-aware cancellation)
  - Avoid default ViewModel layer (no MVVM by default)

---

## Requirements

- macOS 14.0+
- Xcode 15.4+ (`SWIFT_VERSION = 5.10`)
- Tuist

Install Tuist if needed:

```bash
brew tap tuist/tuist && brew install tuist
```

---

## Getting Started

1) Generate the Xcode workspace:

```bash
make generate
# or
Scripts/generate.sh
```

2) Open and run:

```bash
open Vibeviewer.xcworkspace
# In Xcode: scheme = Vibeviewer, destination = My Mac (macOS), then Run
```

3) Build/package via CLI (optional):

```bash
make build        # Release build (macOS)
make dmg          # Create DMG package
make release      # Clean → Generate → Build → Package
make release-full # Full automated release (build + tag + GitHub release)
```

4) Release process:

See [Scripts/RELEASE_GUIDE.md](Scripts/RELEASE_GUIDE.md) for detailed release instructions.

Quick release:
```bash
./Scripts/release.sh [VERSION]  # Automated release workflow
```

---

## Run & Debug

- The menu bar shows the icon and key metrics; click to open the popover.
- Sign-in and Settings windows are provided via environment-injected window managers (see `.environment(...)` in `VibeviewerApp.swift`).
- Auto-refresh starts on app launch and reacts to screen power/activity changes.

---

## Testing

Each package ships its own tests. Run from Xcode or via CLI per package:

```bash
swift test --package-path Packages/VibeviewerCore
swift test --package-path Packages/VibeviewerModel
swift test --package-path Packages/VibeviewerAPI
swift test --package-path Packages/VibeviewerAppEnvironment
swift test --package-path Packages/VibeviewerStorage
swift test --package-path Packages/VibeviewerLoginUI
swift test --package-path Packages/VibeviewerMenuUI
swift test --package-path Packages/VibeviewerSettingsUI
swift test --package-path Packages/VibeviewerShareUI
```

> Tip: after adding/removing packages, run `make generate` first.

---

## Contributing

Issues and PRs are welcome. To keep the codebase consistent and maintainable:

1) Branch & commits
- Use branches like `feat/...` or `fix/...`.
- Prefer Conventional Commits (e.g., `feat: add dashboard refresh service`).

2) Architecture agreements
- Read `./.cursor/rules/architecture.mdc` and this README before changes.
- Place new code in the proper layer (UI/Service/Model/Core). One primary type per file.
- API layer exposes service protocols + default impl only; DTOs stay internal; UI uses domain models only.

3) Self-check
- `make generate` works and the workspace opens
- `make build` succeeds (or Release build in Xcode)
- `swift test` passes for related packages
- No reverse dependencies; UI never imports networking implementations

4) PR
- Describe motivation, touched modules, and impacts
- Include screenshots/clips for UI changes
- Prefer small, focused PRs

---

## FAQ

- Q: Missing targets or workspace won’t open?
  - A: Run `make generate` (or `Scripts/generate.sh`).

- Q: Tuist command not found?
  - A: Install via Homebrew as above.

- Q: Swift version mismatch during build?
  - A: Use Xcode 15.4+ (Swift 5.10). If issues persist, run `Scripts/clear.sh` then `make generate`.

---

## License

This project is open-sourced under the MIT License. See `LICENSE` for details.

---

## Acknowledgements

Thanks to the community for contributions to modular Swift packages, SwiftUI, and developer tooling — and thanks for helping improve Vibeviewer!

UI inspiration from X user @hi_caicai — see [Minto: Vibe Coding Tracker](https://apps.apple.com/ca/app/minto-vibe-coding-tracker/id6749605275?mt=12).


