Skip to content

Latest commit

 

History

History

README.md

Codenotch for Windows

A Windows port of Codenotch — the usage notch that sits on the edge of your screen and answers two questions at a glance: how much of my AI allowance is left, and is Claude still working.

Same design language as the macOS original (inverse-rounded pill, colour-graded rings, hover card with per-window bars), rebuilt for Windows in Rust + Tauri 2 / WebView2. No code is copied from the Swift app; the providers are reimplemented from their documented behaviour and the wire formats.

What it shows

Cell Source How it reads it
Claude GET https://api.anthropic.com/api/oauth/usage with the token Claude Code keeps in ~/.claude/.credentials.json Session / weekly windows, 429 back-off with a persisted deadline, stale readings dimmed with their age. Renews that token by running the standalone claude -p shortly before it expires (Claude Code inside the desktop app never writes this file), and never sends an expired one. A thin arc spins inside the ring while a Claude session is working, and pulses amber when one is waiting on you (Claude Code hooks + transcript watcher, desktop app included).
Codex The local Codex sign-in in ~/.codex/auth.json (read only, never refreshed), falling back to the newest session snapshot Live primary/secondary windows (5h + weekly on paid plans, a monthly window on free) while Codex is signed in; Spark and Code review appear on the hover card when Codex reports them; otherwise the last snapshot, marked stale by its own timestamp.
Cursor The editor's own session from state.vscdbcursor.com/api/usage-summary Included usage / API usage / on-demand, reset at billing-cycle end. Nothing to sign into: it borrows the editor's session, so there is only ever one account.
Grok The Grok CLI's own session in ~/.grok/auth.json (read only, never refreshed) → cli-chat-proxy.grok.com/v1/billing?format=credits, the endpoint that CLI's own /usage asks The weekly Grok Build allowance, with the account on the hover card. Only a session minted by auth.x.ai is used — the file can also hold a customer IdP token meant for that customer's private proxy. A fresh weekly period reads 0 %, not "unmetered".
Antigravity Official agy CLI /usage print when installed; otherwise the existing local language_server bridge, Google Cloud Code API, or transcript model count Official four quota rows (Gemini & Claude/GPT 5h/weekly) without running the full IDE. When CLI is absent, falls back to legacy local bridge/API.

Providers that are not installed simply do not get a cell.

Codex quota recovery

The direct usage endpoint remains the first choice. If it fails, Codenotch can ask an installed native codex.exe via the documented account/rateLimits/read app-server method before falling back to a rollout snapshot. The desktop's %LOCALAPPDATA%\OpenAI\Codex\bin installation is checked as well as native CLI candidates. No .cmd/Node wrapper is launched. The owned process is hidden, limited to 20 seconds, and terminated/reaped after the read; no inference or login command is sent. Existing HTTP 429 backoff and five-minute polling remain.

The main ring/tray selects only core primary, never a weekly, Spark or code-review replacement. If primary is absent the headline stays blank; secondary remains available to the separate weekly ring. App-server multi-bucket replies prefer codex. Rollout fallback ignores explicitly different bucket ids and, like macOS, reads the latest eight non-archived paths from state_5.sqlite using a read-only, WAL-aware connection (50 ms busy timeout). This finds resumed threads without scanning every session file. If the index is unavailable, the original three-date-directory scan remains the fallback; old resumed threads cannot be discovered through that scan alone. Missing data is not a zero. Percentages retain the existing used semantics; this is quota utilization, not an exact token count or a model-specific allowance.

Why launch a process at all? A borrowed stored-token HTTP read can fail while the installed Codex client can still authenticate. The native client owns its managed OAuth lifecycle and can recover live quotas without Codenotch copying its refresh logic. This is not guaranteed for externally managed credentials that require a host app: if it cannot read the quota, the usual stale/missing rollout status remains. Unlike the old unconditional wrapper-based path, this recovery runs only after HTTP failure, directly owns a native executable, and does not use taskkill or launch a Node/cmd tree. Codenotch sends no login or explicit token-refresh request; Codex may perform its own normal managed refresh.

Regression checks: cargo test --locked and node --test test-codex-headline.cjs from windows/. Tests use synthetic quota fixtures, not account credentials. The optional cargo test --release --locked codex::tests::live_native_quota -- --ignored checks the actual native transport against an already signed-in local client; it prints no account credentials or quota values and is not run by CI.

Claude sign-in

When Claude is signed out, its card offers Sign in, which opens the standalone Claude Code CLI's browser login (claude auth login --claudeai). It is offered on the default ~/.claude account only, since that is the one the CLI signs in. Finish in the browser; if it displays a code, paste it in the opened terminal, not in Codenotch. The card refreshes after the CLI exits without restarting the widget. The native CLI must already be installed; missing CLI, cancellation and launch errors are shown.

This explicit action shares a busy guard with automatic token renewal. Only the CLI handles OAuth and writes credentials; Codenotch does not receive login codes or expose tokens through UI IPC. The interactive child has a 15-minute timeout. To read Claude again, click its ring or choose Refresh now from the notch's right-click menu. HTTP 403 is reported as an access/network refusal rather than claiming that a still-valid login has expired. Existing automatic renewal is unchanged.

Antigravity

  • Official CLI (Preferred): When the official Antigravity CLI (agy.exe) is installed (%LOCALAPPDATA%\agy\bin\agy.exe or on PATH) and signed in, Codenotch reads official quotas directly without keeping the full IDE running.
  • Execution: Runs the official CLI in a hidden Windows pseudo-console, with a 70-second timeout and cleanup of its process tree. It does not need PowerShell scripts or a separate service.
  • Refresh: Checks at startup and on hover/explicit request when readings are at least five minutes old; failed attempts are also limited to once per five minutes. It keeps previous readings on failure, without switching to legacy APIs. The CLI is not launched periodically while idle.
  • Fallback: When the official CLI is not installed, Codenotch preserves the legacy local bridge (language_server), Credential Manager, and transcript model turn counting to maintain compatibility with existing installations.
  • Official CLI Reference: Standalone /usage printing is described in the official Antigravity CLI documentation. Note: no categorical Terms of Service guarantee is made.

Restart Codenotch after installing or removing agy: the source is selected at startup. The CLI's text report is parsed defensively; an unsupported format or failed sign-in shows an error or the last reading marked stale. Codenotch does not automate sign-in.

Install / build

Download Codenotch-Setup.exe from the latest release. It installs for the current user without administrator rights, puts codenotch-hook.exe beside the app where Install hooks looks for it, and fetches WebView2 if Windows does not already have it. The installer is not code-signed, so SmartScreen stops it the first time with Windows protected your PC: choose More info, then Run anyway.

Updates

Codenotch looks for a newer release about twenty seconds after it starts, and again whenever Check for updates is pressed in Settings → General. The feed is latest.json on the newest release, written by the Windows Package workflow beside the installer it describes, so publishing a release is the whole of shipping an update.

Nothing about this nags. A check that fails — no network, an unreachable feed — leaves the app as it was and says so only next to the version. There is no dialogue and no badge.

The download is a minisign-signed archive, and the signature is checked against the public key in tauri.conf.json before anything is run. This is what stands in for code signing here: the installer itself is unsigned, so SmartScreen still warns on a first manual install, but an update delivered to an already-installed copy is verified.

Before the first signed release, the key has to exist:

npx --yes @tauri-apps/cli@2.11.4 signer generate -w $env:USERPROFILE\.tauri\codenotch.key

Put the private key in the repository secret TAURI_SIGNING_PRIVATE_KEY and its password in TAURI_SIGNING_PRIVATE_KEY_PASSWORD, and paste the public key into plugins.updater.pubkey in codenotch/tauri.conf.json, replacing REPLACE_WITH_TAURI_PUBLIC_KEY. Until that is done the app skips the check entirely rather than reporting a failure nobody can act on; the packaging job builds an ordinary installer and warns that it made no feed, and a v* release fails loudly rather than going out with an update path nobody can use.

Keep the private key. Losing it means no installed copy can be updated again, because every one of them checks against the public key it shipped with — they would all have to reinstall by hand.

To build from source instead — prerequisites: Rust (MSVC toolchain), WebView2 runtime (ships with Windows 11).

# from this directory (the repo root here; `windows/` inside the upstream repo)
cargo build --release
.\target\release\codenotch.exe          # pill appears on the right edge of the primary monitor
.\target\release\codenotch.exe doctor   # self-diagnosis: credentials, data sources, icons, hooks

To build the installer the way the Windows Package workflow does:

# the hook gets its own target dir, so the bundler never copies it onto itself
cargo build --release --locked -p codenotch-hook --target-dir target/hook
cd codenotch
npx @tauri-apps/cli@2 build --config tauri.bundle.conf.json
# → ..\target\release\bundle\nsis\Codenotch_<version>_x64-setup.exe

Tray menu: the readings themselves — a line per provider with its headline figure, and under it one line per limit window — then Refresh all, Settings… and Quit Codenotch. Clicking a provider's line re-reads that provider. Everything else is in the settings window: which rings the notch shows, its size, the weekly ring, which screen edge it sits on and which screen, start with Windows, the language, Claude Code hooks, reset position, and the data folder (%APPDATA%\codenotch — logs, persisted readings, icon overrides).

Notch: clicking a ring re-reads that provider, as on the Mac. Right-clicking the notch or its card offers Refresh now, the provider's usage page (Open claude.ai, Open chatgpt.com, …) and Quit Codenotch. Neither click, nor the tray, asks Claude again while its rate-limit wait runs.

Where the notch sits

The notch pins to one edge of one screen. The arc above the pill carries it: hold it, and the four places it can go are outlined on the screen; release on one and the notch lands there, centred. Appearance → Show move handle hides that arc. Appearance → Edge picks left, right, top or bottom: it stands upright on the left and right edges with the hover card opening sideways, and lies flat on the top and bottom ones with the card opening below or above. Appearance → Screen appears once more than one monitor is attached.

Dragging does both at once: pick the pill up, drop it anywhere, and it snaps to the nearest edge of the screen it was dropped on — across monitors, and across a change of DPI between them. The choice is stored as notch_edge, notch_monitor (the device name, e.g. \\.\DISPLAY2) and notch_y (the position along the edge, 0–1) in config.json. A monitor that is no longer attached falls back to the primary one, so unplugging a screen cannot strand the notch off-screen; Recentre centres it on the edge it is on, or on the primary screen's right-hand edge when the screen it was on is gone.

Icons

Provider marks are the SVGs from @lobehub/icons-static-svg (MIT), embedded unmodified — see codenotch/glyphs/NOTICE.md. Drop your own claude|codex|cursor|gemini.svg (or .png) into %APPDATA%\codenotch\glyphs\ to override. The marks remain the trademarks of their owners.

Translations

Three surfaces draw their own text, so each keeps its own table:

Surface Table Languages today
Tray menu codenotch/src/i18n.rs (tr), codenotch/src/traymenu.rs (label) en · ru · zh · ja · ko · uk
Hover card codenotch/ui/notch.html (TEXT, PATTERNS, UI) en · ru · zh
Settings window codenotch/ui/settings.html (STATIC_TEXT, STATUS_TEXT) en · ru · zh · ja · ko

Help is welcome on the gaps, which fall back to English rather than breaking anything:

  • the hover card has no Japanese, Korean or Ukrainian;
  • the settings window has no Ukrainian, although the tray menu and the language picker have had it since Ukrainian was added;
  • Korean has none of the window names the Mac's catalog carries — Current session, Weekly limit, Monthly limit, 5-hour Limit, Included usage, API usage — because the catalog has no Korean to take them from.

Keys are the exact English string. A string the Mac also shows should be taken from Sources/Localizable.xcstrings rather than translated afresh, so both platforms word it the same way. One catalog feeding all three tables is the intended fix; until then a test in traymenu.rs fails if the menu and the card stop naming the same window.

Layout

.
├── codenotch/          the Windows app (pill, hover card, settings, providers)
└── codenotch-hook/     tiny helper Claude Code calls to report session events

A pull request that touches this tree is built and tested; the check is skipped inside forks until the pull request is opened here.

Relationship to upstream

This port follows the upstream design and provider semantics. It is developed at Im-Midi/codenotch-windows and offered to the upstream project as its windows/ tree; the two are kept in sync. Session detection originated in Im-Midi/Pac-Man (MIT).

License

MIT — see LICENSE. The Codenotch design and name belong to the upstream author.