- Windows desktop tray app for AI-provider usage and limits (Win-CodexBar port of CodexBar).
- Default product surface: Tauri 2 desktop shell in
apps/desktop-tauri, not the CLI. - Shared domain/backend and CLI live in the
rust/cratecodexbar. - Material under
docs/that describes the upstream macOS/Swift project is historical unless the task is explicitly about upstream parity. - When repo docs conflict, trust active sources:
apps/desktop-tauriplusrust/src.
- Cargo workspace (root
Cargo.toml): membersrust,apps/desktop-tauri/src-tauri; default-member is the Tauri crate. - Path dependency:
codexbar-desktop-tauri→codexbar = { path = "../../../rust" }. - Frontend: React 18 + Vite in
apps/desktop-tauri/src/. Typed invoke bridge insrc/lib/tauri.ts; DTOs insrc/types/bridge.ts. - Surfaces: the hidden
mainwebview routes by window label / surface mode — TrayPanel, PopOut, Settings, FloatBar. Settings, float bar, and flyout use detached windows where needed. - Provider refresh:
codexbar::core::instantiate_provider(rust/src/core/provider_factory.rs) →Provider::fetch_usage→ shellcommands/providers.rs(semaphore + timeout) →AppState.provider_cache→ events → ReactuseProviders. - Settings:
%config%/CodexBar/settings.jsonviaSettings::load/saveandsecure_file(DPAPI-capable on Windows). FrontendupdateSettingspatch → save →codexbar:settings-updated/ float-bar config events. - Tray:
tray_bridge+tray_menu. Icon pixels from sharedcodexbar::tray::{render_bar_icon_rgba, render_percent_icon_rgba}. - Float bar:
floatbar/owns the auxiliary always-on-top window. The builder must pin.theme(Some(tauri::Theme::Dark))— WebView2 resolvesprefers-color-schemeon a shared process profile; an unpinned window flips other webviews under themeauto. - Proof harness: env
CODEXBAR_PROOF_MODE(e.g.settings:menu) opens a target surface and suppresses blur-dismiss for automation / CUA capture.
apps/desktop-tauri/src/— React UI (surfaces, hooks, i18n, bridge types)apps/desktop-tauri/src-tauri/src/— Tauri shell (main, tray, floatbar, shell windows, commands, proof_harness)rust/src/core/—ProviderId,Providertrait,instantiate_provider, fetch contextrust/src/providers/— one module per provider (fetch/parse/auth)rust/src/settings/— settings model and load/saverust/src/browser/— Windows browser detection + cookie extractionrust/src/tray/— shared tray-icon rendererrust/src/cli/— CLI subcommands (codexbarbinary)scripts/—dev.ps1,local-check.ps1, release and smoke scriptsdocs/— Windows port docs (ARCHITECTURE,CLI,CONFIGURATION,PROVIDERS,BUILDING,COOKIES,WINDOWS_PROOF, ADRs). Upstream macOS docs are read-only reference only..github/workflows/—pr-check.yml(hosted gate),interaction-guard.yml
# Local CI slice (mirrors hosted PR check)
.\scripts\local-check.ps1
# Rust backend / CLI
cargo test --manifest-path rust/Cargo.toml
cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
cargo build -p codexbar
cargo run -p codexbar -- --help
# Tauri shell crate
cargo test --manifest-path apps/desktop-tauri/src-tauri/Cargo.toml
cargo clippy --manifest-path apps/desktop-tauri/src-tauri/Cargo.toml --all-targets -- -D warnings
# Frontend (cwd apps/desktop-tauri) — use pnpm, not npm
pnpm install
pnpm test
pnpm run build
pnpm run tauri:dev
pnpm run tauri:build:debug
pnpm run tauri:build
# Dev launch helpers (repo root)
.\scripts\dev.ps1
.\scripts\dev.ps1 -SkipBuild
./dev.sh
- Raw
cargo build --releaseon the Tauri crate can still embed the dev URL. Preferpnpm run tauri:build/tauri:build:debugorscripts/dev.ps1. - Binaries:
codexbar.exe(CLI),codexbar-desktop-tauri.exe(desktop). - Default desktop work runs from the repo root (default-member). Use
cd rustonly for CLI/backend-only focus. - There is no active root
Scripts/(capital S) pipeline — usescripts/. - Format before handoff when Rust changed:
cargo fmt --all. Clippy both manifests with-D warnings(or explain skips).
- Prefer small, typed structs/enums and focused modules; keep changes local.
- Provider-specific logic stays inside
rust/src/providers/<name>/(or that module). Do not add cross-provider branching in shared paths. - New provider: (1)
ProviderIdvariant + metadata methods (cli_name,display_name, …), (2) provider module implementingProvider, (3) match arm incore/provider_factory.rs::instantiate. The factory is exhaustive — missing arms fail to compile. Never duplicate factories in the shell or CLI. - Errors:
thiserror(ProviderError) andanyhowwhere already used; keep user-facing messages friendly. - Logging:
tracingonly. Never log secrets, cookies, tokens, or raw API keys. - Frontend tests are co-located
*.test.ts/*.test.tsx. Bridge types intypes/bridge.tsmust stay aligned with Rust command payloads (including settings tab ids). - Settings tab ids (case-sensitive; backend whitelist in
surface_target.rsmust mirror frontendSettingsTabId/TAB_META):general,providers,notifications,menuBar,menu,usageSpend,advanced,about. Unknown ids fall back to General in the UI. Old idsdisplay/apiKeys/cookiesare not valid settings tabs. - Cookie import UX uses explicit browser selection in Preferences — do not assume Chrome-only.
- Claude CLI output is user-configurable; do not treat a customizable status line as the usage source of truth.
- Keep provider data siloed: never show identity / plan / email from provider A in provider B UI.
- Secrets (manual cookies, API keys, token accounts): use existing redaction,
secure_file, and keyring helpers. - Do not add dependencies or tooling without confirmation.
- Do not open issues or PRs against upstream
steipete/CodexBarunless the user explicitly asks. This repo is Win-CodexBar only.
apps/desktop-tauri/src-tauri/src/main.rs— shell entry, command registration, setupapps/desktop-tauri/src/App.tsx— surface routing by window labelapps/desktop-tauri/src/lib/tauri.ts— frontend invoke bridgeapps/desktop-tauri/src/types/bridge.ts— DTOs +SettingsTabIdrust/src/core/provider_factory.rs— sole provider factoryrust/src/core/provider.rs—ProviderId+Providertraitapps/desktop-tauri/src-tauri/src/commands/providers.rs— refresh engineapps/desktop-tauri/src-tauri/src/tray_bridge.rs— tray icon and menuapps/desktop-tauri/src-tauri/src/surface_target.rs— proof / settings tab whitelistapps/desktop-tauri/src-tauri/tauri.conf.json— active Tauri configscripts/local-check.ps1— local CI slice.github/workflows/pr-check.yml— hosted PR gate.github/workflows/release.yml— hosted release/draft gateCONTEXT.md— CI context (official GitHub runners only)
- Package manager: pnpm@10.18.1 (
packageManagerinapps/desktop-tauri/package.json+ lockfile). Do not introduce npm or yarn lockfiles. - Node: CI uses Node 20; no
.nvmrcin repo — prefer Node 20 locally for parity. - Rust: edition 2024, stable toolchain; CI target
x86_64-pc-windows-msvc. No committedrust-toolchain.toml/rustfmt.toml/clippy.toml— defaults plus CI flags (clippy -- -D warnings). - Tray / DPAPI / browser-cookie behavior: validate on Windows-native hosts. WSL/Linux is insufficient for those paths.
- CUA (computer-use) for UI proof — see Testing & QA. Project: trycua/cua. On this machine the Windows driver is typically
%LOCALAPPDATA%\Programs\Cua\cua-driver\bin\cua-driver.exe.
- Rust: prefer focused
#[cfg(test)]unit tests near the changed module. Run both manifests after Rust changes. - Frontend: Vitest 3 + jsdom + Testing Library. From
apps/desktop-tauri:pnpm test(src/**/*.{test,spec}.{ts,tsx}). - Hosted PR check (official
windows-2025runner):cargo fmt --check, clippy both crates with-D warnings, cargo test both crates,pnpm --dir apps/desktop-tauri test,pnpm --dir apps/desktop-tauri run build, boundary scan, production dependency audit, license audit, and Tauri x64 production build. Details:.github/CI.md. - Local mirror:
.\scripts\local-check.ps1(default Rust + Tauri + Frontend). Does not run full installer / smoke unless you pass the matching flags. - Parser / fetcher changes: add deterministic samples or fixtures where practical.
- No coverage thresholds are configured — do not invent any.
UI validation with CUA (trycua/cua)
Unit tests and local-check do not prove tray, settings, float bar, theme, or WebView2 behavior. For UI / tray / settings / float-bar / visual changes, agents must retest on a real Windows desktop build using Cua Drivers (background computer-use: click, type, screenshot, UIA) from the open-source trycua/cua project. Docs: cua.ai/docs, driver install: install guide, CLI reference: cua-driver CLI.
Install (Windows PowerShell, from upstream README):
irm https://cua.ai/driver/install.ps1 | iexThen follow post-install instructions (permissions / accessibility as prompted).
Typical layout after install:
- Driver binary:
%LOCALAPPDATA%\Programs\Cua\cua-driver\bin\cua-driver.exe - Long-lived daemon:
cua-driver serve(often over a named pipe). One-shot tools:cua-driver call <tool> '<json>'(e.g.list_windows,get_window_state,click, screenshots via--screenshot-out-file).
Required retest loop after UI-affecting code changes:
- Rebuild a local desktop binary that includes the change (
pnpm --dir apps/desktop-tauri run tauri:build:debugor.\scripts\dev.ps1). Do not validate against a stale pre-change exe. - Close any already-running CodexBar instance (single-instance plugin may hand off to the old process).
- Launch the new binary. For stable automation (no blur-dismiss), set proof mode, e.g.
$env:CODEXBAR_PROOF_MODE = 'settings:menu'
(settings tab ids:general,providers,notifications,menuBar,menu,usageSpend,advanced,about— float bar section is onmenu). - Drive with CUA: start the driver daemon if needed, then list windows / UIA tree, click the control under test, wait for UI settle, capture before/after screenshots.
- Assert observables (pixels, window list, checked toggle state, theme still dark under
auto, float bar window present, etc.) — not only “command exited 0”. - Attach proof to the PR (screenshots or short note + paths). If CUA cannot run, say why and attach equivalent manual proof (PR template).
Do not treat Vitest/jsdom or cargo test alone as sufficient for tray icon, DWM, WebView2 theme, float bar z-order, or settings chrome. Do not open issues/PRs against trycua/cua unless the user explicitly asks; use it as tooling.
- Short imperative commit messages (e.g.
Fix Claude CLI parser,Improve cookie import errors). - Keep commits scoped to one change.
- In PRs / patches include:
- Summary of behavior changes
- Commands run (
cargo test,pnpm test,.\scripts\local-check.ps1, etc.) - Screenshots / GIFs for UI changes (Windows)
- Linked issue / reference when relevant
- Hosted PR check exists (
.github/workflows/pr-check.yml); still run and report the local slice. Do not claim there is no CI. - UI / tray / settings / float-bar / visual PRs: CUA Driver proof is the default (trycua/cua) after a fresh local rebuild — see UI validation with CUA. If CUA cannot be used, explain why and attach equivalent manual proof (PR template checkboxes).
- Before non-trivial merge: thermo-nuclear structure review when the project process requires it.
- Treat Winget updates as a normal release step after GitHub release artifacts are stable.
- Winget does not track "latest" GitHub releases; every version needs its own immutable manifest folder in
microsoft/winget-pkgs, for examplemanifests/f/Finesssee/Win-CodexBar/0.23.6/. - For routine version bumps, copy the previous approved manifest folder and change only version-specific fields:
PackageVersion,InstallerUrl,InstallerSha256,DisplayName,DisplayVersion,ReleaseNotes, andReleaseNotesUrl. - Keep stable package identity and installer behavior unchanged unless there is a real packaging reason:
PackageIdentifier,InstallerType,Scope,ProductCode,Publisher, package URLs, and silent install behavior. - Before opening a Winget PR, verify the release installer URL resolves and recompute the SHA-256 from the downloaded asset. On Windows, run
winget validatewhen available. - The first Winget package submission was approved in
microsoft/winget-pkgs#366653; the v0.23.5 update was approved inmicrosoft/winget-pkgs#366794. Future updates should be faster, but still expect Microsoft validation/review.