Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ features = [
"Win32_Graphics_DirectComposition",
"Win32_Graphics_Dxgi",
"Win32_Graphics_Dxgi_Common",
"Win32_Security_Credentials",
"Win32_Storage_FileSystem",
]

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ In the default theme, left-click a provider tray icon to show or hide the widget
| Grok Build | Run `grok login` in the Grok Build CLI, then enable Grok in **Providers**. The signed-in session is detected automatically. |
| GitHub Copilot | Sign in with the Copilot CLI (`copilot`, then `/login`) or the GitHub CLI (`gh auth login`), then enable Copilot in **Providers**. The stored login is detected automatically. |

For OpenRouter, create a Management API key at `https://openrouter.ai/settings/management-keys`,
then paste it in **Settings → Providers → OpenRouter → Connection** and press **Test** to verify
the connection. The key is stored securely in Windows Credential Manager and never written to
`settings.json`. The environment variable `OPENROUTER_MANAGEMENT_KEY` still works as a fallback
if you prefer not to use the credential store.

For OpenCode Go, set `OPENCODE_GO_WORKSPACE_ID` and `OPENCODE_GO_AUTH_COOKIE`, or create `%APPDATA%\opencode-go\config.json`:

```json
Expand Down
54 changes: 54 additions & 0 deletions src/app_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,27 @@ pub const POLL_1_HOUR: u32 = POLL_1_HOUR_SECONDS * 1_000;
// SetTimer clamps longer intervals to USER_TIMER_MAXIMUM (i32::MAX ms).
pub const MAX_POLL_MINUTES: u32 = i32::MAX as u32 / POLL_1_MIN;

/// Period used for the OpenRouter budget amount and its monitoring window.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum BudgetPeriod {
Daily,
Weekly,
#[default]
Monthly,
}

impl BudgetPeriod {
/// Days covered by one period, given the days in the current calendar month.
pub fn days(self, month_days: u32) -> f64 {
match self {
BudgetPeriod::Daily => 1.0,
BudgetPeriod::Weekly => 7.0,
BudgetPeriod::Monthly => f64::from(month_days),
}
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SettingsFile {
#[serde(default)]
Expand Down Expand Up @@ -66,6 +87,30 @@ pub struct SettingsFile {
show_grok: bool,
#[serde(default)]
show_copilot: bool,
#[serde(default)]
show_openrouter: bool,
/// Personal spending cap (USD). When set, OpenRouter's gauge measures spend
/// against this cap, converted from `openrouter_budget_period` to the
/// `openrouter_monitor_period` window.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub openrouter_budget_amount: Option<f64>,
/// Period the budget amount is defined for (the "rate").
#[serde(default)]
pub openrouter_budget_period: BudgetPeriod,
/// Period the OpenRouter gauge displays and measures spend for.
#[serde(default)]
pub openrouter_monitor_period: BudgetPeriod,
/// Whether the OpenRouter display shows the cap next to the spend.
#[serde(default)]
pub openrouter_show_cap: bool,
/// Credits manually entered as added in the current month (USD). When set,
/// the balance line shows what is left of this deposit, not the lifetime
/// account balance (the OpenRouter API has no per-month deposit endpoint).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub openrouter_monthly_deposit: Option<f64>,
/// Whether the balance line also prints the monthly deposit next to it.
#[serde(default)]
pub openrouter_show_deposit: bool,
#[serde(default = "default_true")]
pub custom_theme_enabled: bool,
/// Show what is left of each allowance instead of what has been spent, so
Expand Down Expand Up @@ -137,6 +182,13 @@ impl Default for SettingsFile {
show_cursor: false,
show_grok: false,
show_copilot: false,
show_openrouter: false,
openrouter_budget_amount: None,
openrouter_budget_period: BudgetPeriod::Monthly,
openrouter_monitor_period: BudgetPeriod::Monthly,
openrouter_show_cap: false,
openrouter_monthly_deposit: None,
openrouter_show_deposit: false,
custom_theme_enabled: true,
usage_countdown: false,
active_theme_path: None,
Expand Down Expand Up @@ -235,6 +287,7 @@ impl SettingsFile {
ProviderId::Cursor => self.show_cursor,
ProviderId::Grok => self.show_grok,
ProviderId::Copilot => self.show_copilot,
ProviderId::OpenRouter => self.show_openrouter,
}
}

Expand Down Expand Up @@ -283,6 +336,7 @@ impl SettingsFile {
ProviderId::Cursor => self.show_cursor = enabled,
ProviderId::Grok => self.show_grok = enabled,
ProviderId::Copilot => self.show_copilot = enabled,
ProviderId::OpenRouter => self.show_openrouter = enabled,
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/context_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,13 @@ pub fn classic_context_menu() -> ContextMenuDocument {
provider: Provider::Copilot,
},
),
ContextMenuItem::action(
"provider-openrouter",
"OpenRouter",
Action::ToggleProvider {
provider: Provider::OpenRouter,
},
),
],
);
let languages = std::iter::once(ContextMenuItem::action(
Expand Down
Binary file modified src/icons/brand-marks.ttf
Binary file not shown.
46 changes: 46 additions & 0 deletions src/localization/locales/de.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ copilot_window_title = "Copilot-Nutzungsmonitor"
"Collect usage from GitHub" = "Nutzungsdaten von GitHub abrufen"
"Collect usage from Google" = "Nutzungsdaten von Google abrufen"
"Collect usage from OpenAI" = "Nutzungsdaten von OpenAI abrufen"
"Collect usage from OpenRouter" = "Nutzungsdaten von OpenRouter abrufen"
"Show cap in the monitor" = "Limit im Monitor anzeigen"
"Monthly credits deposit" = "Monatliche Guthaben-Einzahlung"
"Show credits deposit in the monitor" = "Guthaben-Einzahlung im Monitor anzeigen"
"0 uses the accumulated account balance" = "0 nutzt das kumulierte Kontoguthaben"
"OpenRouter counts daily spend in UTC: the day rolls over at 00:00 UTC, which is {time} on this device, so the daily value starts over then." = "OpenRouter zählt Tagesausgaben in UTC: Der Tag wechselt um 00:00 UTC, was in Ihrer Zeitzone {time} entspricht; danach beginnt der Tageswert neu."
"Budget" = "Budget"
"Cap amount" = "Limitbetrag"
"Cap period" = "Limitzeitraum"
"Monitor period" = "Überwachungszeitraum"
"0 turns the spending cap off" = "0 deaktiviert die Ausgabenobergrenze"
"Daily" = "Täglich"
"Weekly" = "Wöchentlich"
"Monthly" = "Monatlich"
"Collect usage from xAI" = "Nutzungsdaten von xAI abrufen"
"Colour" = "Farbe"
"Column" = "Column"
Expand Down Expand Up @@ -457,3 +471,35 @@ copilot_window_title = "Copilot-Nutzungsmonitor"
"Lock in taskbar" = "Lock in taskbar"
"Keep the widget docked; never float automatically" = "Keep the widget docked; never float automatically"
"Locked" = "Locked"
"Accounts" = "Konten"
"Themes use the default account unless they specify an account. Custom themes can display multiple accounts." = "Designs verwenden das Standardkonto, sofern sie kein Konto angeben. Eigene Designs können mehrere Konten anzeigen."
"Default account" = "Standardkonto"
"Account name" = "Kontoname"
"Remove" = "Entfernen"
"Config directory" = "Konfigurationsverzeichnis"
"Custom credentials file" = "Eigene Anmeldedatendatei"
"Optional; overrides the config directory" = "Optional; überschreibt das Konfigurationsverzeichnis"
"Browse..." = "Durchsuchen..."
"Select credentials file" = "Anmeldedatendatei auswählen"
"Theme binding" = "Design-Bindung"
"Uses CLAUDE_CONFIG_DIR when set; otherwise detects CLI, Desktop or WSL credentials." = "Verwendet CLAUDE_CONFIG_DIR, wenn gesetzt; sonst werden CLI-, Desktop- oder WSL-Anmeldedaten erkannt."
"Uses CODEX_HOME when set; otherwise ~/.codex/auth.json." = "Verwendet CODEX_HOME, wenn gesetzt; sonst ~/.codex/auth.json."
"Monitoring disabled" = "Überwachung deaktiviert"
"Last known usage" = "Zuletzt bekannter Verbrauch"
"Session" = "Sitzung"
"Credits" = "Guthaben"
"Resets in" = "Zurücksetzung in"
"Waiting for usage" = "Warte auf Verbrauchsdaten"
"Add account" = "Konto hinzufügen"
"Connection" = "Verbindung"
"Management key" = "Management-Schlüssel"
"Test" = "Testen"
"Remove stored key" = "Gespeicherten Schlüssel entfernen"
"Credential stored in Windows Credential Manager" = "Anmeldedaten in der Windows-Anmeldeinformationsverwaltung gespeichert"
"No key configured. Create a Management API key on OpenRouter and paste it here." = "Kein Schlüssel konfiguriert. Erstellen Sie einen Management API key auf OpenRouter und fügen Sie ihn hier ein."
"Get OpenRouter management key" = "OpenRouter-Verwaltungsschlüssel abrufen"
"Testing..." = "Teste läuft..."
"Connected" = "Verbunden"
"BALANCE" = "GUTHABEN"
"USED" = "VERWENDET"
"Add a Management API key in Settings → Providers → OpenRouter → Connection, then refresh this monitor." = "Fügen Sie einen Management-API-Schlüssel unter Einstellungen → Anbieter → OpenRouter → Verbindung hinzu und aktualisieren Sie diesen Monitor."
46 changes: 46 additions & 0 deletions src/localization/locales/en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ copilot_window_title = "Copilot Usage Monitor"
"Collect usage from GitHub" = "Collect usage from GitHub"
"Collect usage from Google" = "Collect usage from Google"
"Collect usage from OpenAI" = "Collect usage from OpenAI"
"Collect usage from OpenRouter" = "Collect usage from OpenRouter"
"Show cap in the monitor" = "Show cap in the monitor"
"Monthly credits deposit" = "Monthly credits deposit"
"Show credits deposit in the monitor" = "Show credits deposit in the monitor"
"0 uses the accumulated account balance" = "0 uses the accumulated account balance"
"OpenRouter counts daily spend in UTC: the day rolls over at 00:00 UTC, which is {time} on this device, so the daily value starts over then." = "OpenRouter counts daily spend in UTC: the day rolls over at 00:00 UTC, which is {time} on this device, so the daily value starts over then."
"Budget" = "Budget"
"Cap amount" = "Cap amount"
"Cap period" = "Cap period"
"Monitor period" = "Monitor period"
"0 turns the spending cap off" = "0 turns the spending cap off"
"Daily" = "Daily"
"Weekly" = "Weekly"
"Monthly" = "Monthly"
"Collect usage from xAI" = "Collect usage from xAI"
"Colour" = "Colour"
"Column" = "Column"
Expand Down Expand Up @@ -457,3 +471,35 @@ copilot_window_title = "Copilot Usage Monitor"
"Lock in taskbar" = "Lock in taskbar"
"Keep the widget docked; never float automatically" = "Keep the widget docked; never float automatically"
"Locked" = "Locked"
"Accounts" = "Accounts"
"Themes use the default account unless they specify an account. Custom themes can display multiple accounts." = "Themes use the default account unless they specify an account. Custom themes can display multiple accounts."
"Default account" = "Default account"
"Account name" = "Account name"
"Remove" = "Remove"
"Config directory" = "Config directory"
"Custom credentials file" = "Custom credentials file"
"Optional; overrides the config directory" = "Optional; overrides the config directory"
"Browse..." = "Browse..."
"Select credentials file" = "Select credentials file"
"Theme binding" = "Theme binding"
"Uses CLAUDE_CONFIG_DIR when set; otherwise detects CLI, Desktop or WSL credentials." = "Uses CLAUDE_CONFIG_DIR when set; otherwise detects CLI, Desktop or WSL credentials."
"Uses CODEX_HOME when set; otherwise ~/.codex/auth.json." = "Uses CODEX_HOME when set; otherwise ~/.codex/auth.json."
"Monitoring disabled" = "Monitoring disabled"
"Last known usage" = "Last known usage"
"Session" = "Session"
"Credits" = "Credits"
"Resets in" = "Resets in"
"Waiting for usage" = "Waiting for usage"
"Add account" = "Add account"
"Connection" = "Connection"
"Management key" = "Management key"
"Test" = "Test"
"Remove stored key" = "Remove stored key"
"Credential stored in Windows Credential Manager" = "Credential stored in Windows Credential Manager"
"No key configured. Create a Management API key on OpenRouter and paste it here." = "No key configured. Create a Management API key on OpenRouter and paste it here."
"Get OpenRouter management key" = "Get OpenRouter management key"
"Testing..." = "Testing..."
"Connected" = "Connected"
"BALANCE" = "BALANCE"
"USED" = "USED"
"Add a Management API key in Settings → Providers → OpenRouter → Connection, then refresh this monitor." = "Add a Management API key in Settings → Providers → OpenRouter → Connection, then refresh this monitor."
46 changes: 46 additions & 0 deletions src/localization/locales/es.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ copilot_window_title = "Monitor de uso de Copilot"
"Collect usage from GitHub" = "Recopilar uso de GitHub"
"Collect usage from Google" = "Recopilar uso de Google"
"Collect usage from OpenAI" = "Recopilar uso de OpenAI"
"Collect usage from OpenRouter" = "Recopilar uso de OpenRouter"
"Show cap in the monitor" = "Mostrar límite en el monitor"
"Monthly credits deposit" = "Depósito de créditos (mensual)"
"Show credits deposit in the monitor" = "Mostrar depósito de créditos en el monitor"
"0 uses the accumulated account balance" = "0 usa el saldo acumulado de la cuenta"
"OpenRouter counts daily spend in UTC: the day rolls over at 00:00 UTC, which is {time} on this device, so the daily value starts over then." = "OpenRouter cuenta el gasto diario en UTC: el día cambia a las 00:00 UTC, que en tu zona horaria es {time}, así que el valor diario se reinicia a esa hora."
"Budget" = "Presupuesto"
"Cap amount" = "Monto del límite"
"Cap period" = "Período del límite"
"Monitor period" = "Período monitorizado"
"0 turns the spending cap off" = "0 desactiva el límite de gasto"
"Daily" = "Diario"
"Weekly" = "Semanal"
"Monthly" = "Mensual"
"Collect usage from xAI" = "Recopilar uso de xAI"
"Colour" = "Color"
"Column" = "Column"
Expand Down Expand Up @@ -457,3 +471,35 @@ copilot_window_title = "Monitor de uso de Copilot"
"Lock in taskbar" = "Fijar en la barra"
"Keep the widget docked; never float automatically" = "Mantener el widget acoplado; no flotar automáticamente"
"Locked" = "Fijado"
"Accounts" = "Cuentas"
"Themes use the default account unless they specify an account. Custom themes can display multiple accounts." = "Los temas usan la cuenta predeterminada a menos que especifiquen una cuenta. Los temas personalizados pueden mostrar varias cuentas."
"Default account" = "Cuenta predeterminada"
"Account name" = "Nombre de la cuenta"
"Remove" = "Quitar"
"Config directory" = "Directorio de configuración"
"Custom credentials file" = "Archivo de credenciales personalizado"
"Optional; overrides the config directory" = "Opcional; reemplaza el directorio de configuración"
"Browse..." = "Examinar..."
"Select credentials file" = "Seleccionar archivo de credenciales"
"Theme binding" = "Vinculación de tema"
"Uses CLAUDE_CONFIG_DIR when set; otherwise detects CLI, Desktop or WSL credentials." = "Usa CLAUDE_CONFIG_DIR cuando está definido; de lo contrario, detecta credenciales de la CLI, el Escritorio o WSL."
"Uses CODEX_HOME when set; otherwise ~/.codex/auth.json." = "Usa CODEX_HOME cuando está definido; de lo contrario, ~/.codex/auth.json."
"Monitoring disabled" = "Supervisión desactivada"
"Last known usage" = "Último consumo conocido"
"Session" = "Sesión"
"Credits" = "Créditos"
"Resets in" = "Se restablece en"
"Waiting for usage" = "Esperando datos de uso"
"Add account" = "Agregar cuenta"
"Connection" = "Conexión"
"Management key" = "Clave de administración"
"Test" = "Probar"
"Remove stored key" = "Eliminar clave almacenada"
"Credential stored in Windows Credential Manager" = "Credencial almacenada en el Administrador de credenciales de Windows"
"No key configured. Create a Management API key on OpenRouter and paste it here." = "Sin clave configurada. Crea una Management API key en OpenRouter y pégala aquí."
"Get OpenRouter management key" = "Obtener clave de gestión de OpenRouter"
"Testing..." = "Probando..."
"Connected" = "Conectado"
"BALANCE" = "SALDO"
"USED" = "USADO"
"Add a Management API key in Settings → Providers → OpenRouter → Connection, then refresh this monitor." = "Añade una Management API key en Ajustes → Proveedores → OpenRouter → Conexión y actualiza este monitor."
46 changes: 46 additions & 0 deletions src/localization/locales/fr.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ copilot_window_title = "Moniteur d'utilisation Copilot"
"Collect usage from GitHub" = "Collecter l'utilisation depuis GitHub"
"Collect usage from Google" = "Collecter l'utilisation depuis Google"
"Collect usage from OpenAI" = "Collecter l'utilisation depuis OpenAI"
"Collect usage from OpenRouter" = "Collecter l'utilisation depuis OpenRouter"
"Show cap in the monitor" = "Afficher le plafond dans le moniteur"
"Monthly credits deposit" = "Dépôt de crédits (mensuel)"
"Show credits deposit in the monitor" = "Afficher le dépôt de crédits dans le moniteur"
"0 uses the accumulated account balance" = "0 utilise le solde cumulé du compte"
"OpenRouter counts daily spend in UTC: the day rolls over at 00:00 UTC, which is {time} on this device, so the daily value starts over then." = "OpenRouter compte les dépenses quotidiennes en UTC : le jour bascule à 00:00 UTC, soit {time} dans votre fuseau, le montant quotidien repart donc à ce moment-là."
"Budget" = "Budget"
"Cap amount" = "Montant du plafond"
"Cap period" = "Période du plafond"
"Monitor period" = "Période surveillée"
"0 turns the spending cap off" = "0 désactive le plafond de dépenses"
"Daily" = "Quotidien"
"Weekly" = "Hebdomadaire"
"Monthly" = "Mensuel"
"Collect usage from xAI" = "Collecter l'utilisation depuis xAI"
"Colour" = "Couleur"
"Column" = "Column"
Expand Down Expand Up @@ -457,3 +471,35 @@ copilot_window_title = "Moniteur d'utilisation Copilot"
"Lock in taskbar" = "Lock in taskbar"
"Keep the widget docked; never float automatically" = "Keep the widget docked; never float automatically"
"Locked" = "Locked"
"Accounts" = "Comptes"
"Themes use the default account unless they specify an account. Custom themes can display multiple accounts." = "Les thèmes utilisent le compte par défaut sauf s'ils spécifient un compte. Les thèmes personnalisés peuvent afficher plusieurs comptes."
"Default account" = "Compte par défaut"
"Account name" = "Nom du compte"
"Remove" = "Supprimer"
"Config directory" = "Répertoire de configuration"
"Custom credentials file" = "Fichier d'identifiants personnalisé"
"Optional; overrides the config directory" = "Facultatif ; remplace le répertoire de configuration"
"Browse..." = "Parcourir..."
"Select credentials file" = "Sélectionner le fichier d'identifiants"
"Theme binding" = "Liaison de thème"
"Uses CLAUDE_CONFIG_DIR when set; otherwise detects CLI, Desktop or WSL credentials." = "Utilise CLAUDE_CONFIG_DIR lorsqu'il est défini ; sinon, détecte les identifiants de la CLI, du Bureau ou de WSL."
"Uses CODEX_HOME when set; otherwise ~/.codex/auth.json." = "Utilise CODEX_HOME lorsqu'il est défini ; sinon ~/.codex/auth.json."
"Monitoring disabled" = "Surveillance désactivée"
"Last known usage" = "Dernière consommation connue"
"Session" = "Session"
"Credits" = "Crédits"
"Resets in" = "Réinitialisation dans"
"Waiting for usage" = "En attente des données d'utilisation"
"Add account" = "Ajouter un compte"
"Connection" = "Connexion"
"Management key" = "Clé de gestion"
"Test" = "Tester"
"Remove stored key" = "Supprimer la clé enregistrée"
"Credential stored in Windows Credential Manager" = "Identifiant stocké dans le Gestionnaire d'informations d'identification Windows"
"No key configured. Create a Management API key on OpenRouter and paste it here." = "Aucune clé configurée. Créez une Management API key sur OpenRouter et collez-la ici."
"Get OpenRouter management key" = "Obtenir la clé de gestion OpenRouter"
"Testing..." = "Test en cours..."
"Connected" = "Connecté"
"BALANCE" = "SOLDE"
"USED" = "UTILISÉ"
"Add a Management API key in Settings → Providers → OpenRouter → Connection, then refresh this monitor." = "Ajoutez une Management API key dans Paramètres → Fournisseurs → OpenRouter → Connexion, puis actualisez ce moniteur."
Loading