# nanako0129/syrtis architecture

> Architecture diagram of the GitHub repository nanako0129/syrtis, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/nanako0129/syrtis
- Repository: https://github.com/nanako0129/syrtis

## Overview

Syrtis is a local-first macOS menu-bar monitor for AI coding usage and subscription quotas. The main workflow reads tool session logs, obtains usage data through the Rust/C interface, derives reports and charts, then presents them in the menu-bar dashboard. Separate quota integrations supply provider windows; settings control presentation and quota choices. The README documents capabilities not fully represented in the sampled excerpts, so links to those features rely on the documented architecture rather than inspected call sites.

Main entry points: [`Sources/Syrtis/DashboardModel.swift`](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/DashboardModel.swift) (Dashboard model), [`crates/tb_core_ffi/src/lib.rs`](https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/lib.rs) (Rust C interface), [`crates/tb_core_ffi/src/agent_quota_history.rs`](https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/agent_quota_history.rs) (Quota adapters), [`Sources/Syrtis/StatusItemController.swift`](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/StatusItemController.swift) (Menu-bar shell)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_collection["Usage collection"]
  node_usage_source["Usage data source"]
  node_ffi["Rust C interface<br/>[lib.rs]"]
  node_agent_usage["Agent usage adapters<br/>[agent_usage.rs]"]
  node_quota_ffi["Quota adapters"]
end

subgraph group_analysis["Usage and quota analysis"]
  node_dashboard_model["Dashboard model"]
  node_core_reports["Usage reports<br/>[TBCore.swift]"]
  node_quota_analysis["Quota analysis"]
  node_attribution["Usage attribution"]
  node_trace["Session trace<br/>[UsageTrace.swift]"]
  node_snapshots[("Last-known snapshots")]
end

subgraph group_presentation["Menu bar and dashboard"]
  node_app_entry["App entry<br/>[main.swift]"]
  node_app_delegate["App lifecycle<br/>[AppDelegate.swift]"]
  node_status_item["Menu-bar shell"]
  node_dashboard_views["Dashboard lenses"]
  node_activity_charts["Activity charts"]
end

subgraph group_configuration["Settings and updates"]
  node_settings["Settings UI"]
  node_client_tray["Client tray options<br/>[ClientTray.swift]"]
  node_updater["Update service"]
end

node_user(("Mac user"))
node_session_logs["Tool session logs"]
node_quota_providers{{"Quota providers"}}
node_sparkle{{"Sparkle updates"}}

node_user -->|"launches"| node_app_entry
node_session_logs -->|"reads"| node_usage_source
node_usage_source -->|"requests usage"| node_ffi
node_ffi -->|"dispatches"| node_agent_usage
node_agent_usage -->|"returns usage"| node_dashboard_model
node_dashboard_model -->|"builds reports"| node_core_reports
node_dashboard_model -->|"derives attribution"| node_attribution
node_dashboard_model -->|"builds trace"| node_trace
node_quota_providers -.->|"serves quota data"| node_quota_ffi
node_ffi -->|"dispatches"| node_quota_ffi
node_quota_ffi -->|"returns windows"| node_quota_analysis
node_dashboard_model -->|"resolves quotas"| node_quota_analysis
node_dashboard_model -->|"retains readings"| node_snapshots
node_snapshots -->|"restores readings"| node_dashboard_model
node_app_entry -->|"starts app"| node_app_delegate
node_app_delegate -->|"sets up"| node_status_item
node_status_item -->|"requests dashboard"| node_dashboard_model
node_dashboard_model -->|"supplies data"| node_dashboard_views
node_core_reports -->|"supplies reports"| node_dashboard_views
node_dashboard_views -->|"renders activity"| node_activity_charts
node_user -->|"opens dashboard"| node_status_item
node_user -->|"opens settings"| node_settings
node_settings -->|"configures tracks"| node_client_tray
node_user -->|"requests update"| node_updater
node_updater -.->|"checks updates"| node_sparkle

click node_usage_source "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/UsageDataSource.swift"
click node_ffi "https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/lib.rs"
click node_agent_usage "https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/agent_usage.rs"
click node_quota_ffi "https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/agent_quota_history.rs"
click node_dashboard_model "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/DashboardModel.swift"
click node_core_reports "https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/TBCore.swift"
click node_quota_analysis "https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/QuotaResolver.swift"
click node_attribution "https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/UsageAttribution.swift"
click node_trace "https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/UsageTrace.swift"
click node_snapshots "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/SnapshotStore.swift"
click node_app_entry "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/main.swift"
click node_app_delegate "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/AppDelegate.swift"
click node_status_item "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/StatusItemController.swift"
click node_dashboard_views "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/Views/DashboardTabs.swift"
click node_activity_charts "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/Charts/ContributionGraph3D.swift"
click node_settings "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/SettingsWindowController.swift"
click node_client_tray "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/ClientTray.swift"
click node_updater "https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/UpdaterService.swift"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_usage_source,node_ffi,node_agent_usage,node_quota_ffi,node_user toneBlue
class node_dashboard_model,node_core_reports,node_quota_analysis,node_attribution,node_trace,node_snapshots toneAmber
class node_app_entry,node_app_delegate,node_status_item,node_dashboard_views,node_activity_charts toneMint
class node_settings,node_client_tray,node_updater toneRose
class node_session_logs,node_quota_providers,node_sparkle toneIndigo
```

## Components

### Usage collection

- [Usage data source](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/UsageDataSource.swift): `Sources/Syrtis/UsageDataSource.swift`
- [Rust C interface](https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/lib.rs): `crates/tb_core_ffi/src/lib.rs`
- [Agent usage adapters](https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/agent_usage.rs): `crates/tb_core_ffi/src/agent_usage.rs`
- [Quota adapters](https://github.com/nanako0129/syrtis/blob/main/crates/tb_core_ffi/src/agent_quota_history.rs): `crates/tb_core_ffi/src/agent_quota_history.rs`

### Usage and quota analysis

- [Dashboard model](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/DashboardModel.swift): `Sources/Syrtis/DashboardModel.swift`
- [Usage reports](https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/TBCore.swift): `Sources/TokenBarCore/TBCore.swift`
- [Quota analysis](https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/QuotaResolver.swift): `Sources/TokenBarCore/QuotaResolver.swift`
- [Usage attribution](https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/UsageAttribution.swift): `Sources/TokenBarCore/UsageAttribution.swift`
- [Session trace](https://github.com/nanako0129/syrtis/blob/main/Sources/TokenBarCore/UsageTrace.swift): `Sources/TokenBarCore/UsageTrace.swift`
- [Last-known snapshots](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/SnapshotStore.swift): `Sources/Syrtis/SnapshotStore.swift`

### Menu bar and dashboard

- [App entry](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/main.swift): `Sources/Syrtis/main.swift`
- [App lifecycle](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/AppDelegate.swift): `Sources/Syrtis/AppDelegate.swift`
- [Menu-bar shell](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/StatusItemController.swift): `Sources/Syrtis/StatusItemController.swift`
- [Dashboard lenses](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/Views/DashboardTabs.swift): `Sources/Syrtis/Views/DashboardTabs.swift`
- [Activity charts](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/Charts/ContributionGraph3D.swift): `Sources/Syrtis/Charts/ContributionGraph3D.swift`

### Settings and updates

- [Settings UI](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/SettingsWindowController.swift): `Sources/Syrtis/SettingsWindowController.swift`
- [Client tray options](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/ClientTray.swift): `Sources/Syrtis/ClientTray.swift`
- [Update service](https://github.com/nanako0129/syrtis/blob/main/Sources/Syrtis/UpdaterService.swift): `Sources/Syrtis/UpdaterService.swift`

### Other components

- **Mac user**
- **Tool session logs**
- **Quota providers**
- **Sparkle updates**

## Connections

- Mac user → App entry: launches
- Tool session logs → Usage data source: reads
- Usage data source → Rust C interface: requests usage
- Rust C interface → Agent usage adapters: dispatches
- Agent usage adapters → Dashboard model: returns usage
- Dashboard model → Usage reports: builds reports
- Dashboard model → Usage attribution: derives attribution
- Dashboard model → Session trace: builds trace
- Quota providers → Quota adapters: serves quota data
- Rust C interface → Quota adapters: dispatches
- Quota adapters → Quota analysis: returns windows
- Dashboard model → Quota analysis: resolves quotas
- Dashboard model → Last-known snapshots: retains readings
- Last-known snapshots → Dashboard model: restores readings
- App entry → App lifecycle: starts app
- App lifecycle → Menu-bar shell: sets up
- Menu-bar shell → Dashboard model: requests dashboard
- Dashboard model → Dashboard lenses: supplies data
- Usage reports → Dashboard lenses: supplies reports
- Dashboard lenses → Activity charts: renders activity
- Mac user → Menu-bar shell: opens dashboard
- Mac user → Settings UI: opens settings
- Settings UI → Client tray options: configures tracks
- Mac user → Update service: requests update
- Update service → Sparkle updates: checks updates
