# Claude Code Tray

Windows · Tray app · Windows Native · Agent Workbench

Claude Code will tell you your rate-limit percentage if you stop and ask it. This puts the number where you already glance: a native tray icon that redraws itself crisply at any DPI and updates on its own. It reads the session files already on your disk, so there is no account and no service.

- Platform: Windows 10 / 11
- Licence: Apache-2.0
- Product site: https://alegauss.github.io/claude-tray/
- Download: https://github.com/alegauss/claude-tray/releases/latest
- Source: https://github.com/alegauss/claude-tray

Public numbers as of 2026-10-20: latest release v1.7.2 (2026-08-26), 347 downloads.

## Install

winget:

```
winget install alegauss.ClaudeCodeTray
```

## What comes next

From ROADMAP.md at bbe2cd2.

### Block AM — Danger is said, not only coloured

- 📋 the tray sees a window running out before its reset and only turns the bar red, which nobody sees unless looking

### Block AN — The site on the shared design system

- 📋 the site keeps its own copy of the template that eight product sites share

## Recently shipped

- 2026-08-26 · T387: The refusal check's skip is listed, with the sentence that says which machine is expected to produce it: elevation satisfies the emitted preflight on its own, so the branch cannot be reached at all - expected on CI, whose Windows runner is an administrator, and never on a developer's machine, where it means the suite ran from an elevated shell and the one assertion this project has that is weaker on CI went unchecked. Found before it reached CI rather than by a red build: an unlisted skip exits 1 by T218's rule, and the check had been written one task earlier with no entry. Both directions were driven - forcing the elevated branch shows the skip printed with its allowance and no UNEXPECTED line, and removing the entry while it fires reports 1 UNEXPECTED and exits 1. The mirror of the entry above it, which is why these carry a sentence about a machine rather than a restatement of the condition.
- 2026-08-26 · T386: The refusal fires in a run now: the plan carries the registry key the emitted preflight reads, so the check composes a script that cannot pass its own preflight, runs it, and asserts what the branch actually promises - an untouched tree. Not an exit code, because a run that relinked three entries and then threw also exits non-zero. Its own fresh pair, since "nothing moved" cannot be read over directories an earlier half of the section already linked and unlinked. Skipped rather than failed when the process is elevated, the condition's other half, which a check must not grant itself. The premise was wrong and the CI log said so: the branch was believed covered by hosted runners having no Developer Mode, and they allow an unprivileged mklink too - so both machines took the linking path and the refusal fired nowhere. Neutralising the seam turns five assertions red and shows the counterfactual in full: done, 4 changes, the copies moved aside, the file replaced. Unlinking is unconditional after that run left a scratch tree behind.
- 2026-08-26 · T385: update-release ... upload now closes by naming the half it did not do, with the wingetcreate submit command and the SHA-matching reason it is safe: the manifests were bumped and committed, which looks exactly like they were sent, and the only thing that opens the PR to microsoft/winget-pkgs is a build.yml step that is workflow_dispatch only and so does not fire on a tag push. Found by publishing v1.7.2 and then asking where the winget PR was. The notice also states the trap, because reaching for the workflow afterwards is the obvious move and the wrong one: it recompiles the installer - Inno Setup stamps a time, so a different binary - and gh release upload --clobber swaps the asset out from under anybody who already has it, leaving the committed manifest describing a file the release no longer carries. A release has one binary. The release discipline carries the same two paragraphs, and the cmd escaping of the token placeholder was rendered rather than assumed.
- 2026-08-26 · T384: The paragraph closes on what a reader does with the list - if something you keep in one of those folders matters to you, that line is where you will see it - instead of on what the developers' own list had been missing and for how long. The sentence was off-register in a section where every other line says what the feature does, and its "four releases" was not even true: nothing shipped between those tasks. Left alone deliberately: the two older "used to" sentences elsewhere in the README, which describe a change in product behaviour a returning user would notice and are a defensible call, not the same thing as an omission in our own list. The reusable part is how it got there. Five tasks each appended a bolded paragraph to one section without re-reading the four above it; the result reads coherently, and the last one drifted because there was nothing left to say about the feature and something left to say about the work.
- 2026-08-26 · T383: The claim goes through Repo like the twenty-eight beside it, so an installed copy reports 0 failed and 30 skipped where it reported 1 failed and 29 - and a half-missing checkout stays red, which is Repo's needs argument and the distinction that made hand-rolling the guard look reasonable. Inside a checkout it is unchanged: 7 files, both the precondition and the result printed. The interesting half is why nobody could have seen it. build.yml publishes into the checkout and runs the exe from there, so RepoFile walks up, finds AGENTS.md, and the whole repository family runs; running it from the repo root does the same; and every developer command is inside the tree. It takes copying the single file somewhere else - which is exactly what the installer does - and nothing in the loop did that. So the release discipline now says to, with the command, because the gap was the loop rather than the guard: one publish a release already pays for, and the only path that exercises what an installed copy actually is.
- 2026-08-26 · T382: Acquire-Main hands the shared window back to the state --main opens in before the next case reads it, and asserts that it did - so -Case All reports DEGRADED for two machine-state preconditions where it reported FAILED with five assertions, and every case still passes alone on its own process. Resetting in one place rather than restoring in five is what stops the sixth case forgetting, which is how this happened: T195's comment said the three cases it gave one window to left it in a state the next would accept, and that was true of those three until Sessions drilled into a row and Link navigated to a settings panel. The window turned out to carry two independent pieces of state, and fixing only the shell destination left three of Names' assertions failing - the Settings page keeps its own sidebar panel, and a collapsed page's children are not in the automation tree at all, so the reset visits it blind and says so rather than leaving the gap for somebody to rediscover. Breaking the reset puts the named cause in front of every symptom it used to produce.
- 2026-08-26 · T381: The suite is seven partial files of one class, the largest 2,204 lines where it was 9,330: Run and the vocabulary in the original file, then Usage (the quota arithmetic, pure over synthetic readings), Transcripts (the byte cursor, the grid, sessions - it builds a projects tree and walks it), Docs, Lang, Ui and Profiles. Verified three ways rather than by reading the diff: it compiled first try, the member multiset before and after is identical - 205 to 205, nothing lost - and the run reports the same 1,051 passed and 0 failed at every step. Moving it also found a latent defect, which is the argument for having done it: two source scans skip the suite because a scanner naming the string it looks for reports itself, both keyed on the filename SelfTestCli.cs, and one went red on the split. They key on the stem now, the rule the file map already uses to resolve a partial to its row, so a seventh file costs nothing - and the claim that the scan reaches the end of the largest file is over all seven rather than whichever happens to be biggest.
- 2026-08-26 · T380: Six pairs of config dirs, one script composed per branch, and eight invariants run over all of them - each reported once, naming the plans that broke it. The coverage is asserted rather than hoped for: every verdict and per-entry state is enumerated from the enums, so a fifth verdict demands a fixture the day it is added, and a branch no fixture produced is named. Removing one fixture reports "Withheld/same" by name, which is the point. It found a defect on its first run, and not the one expected: the plural refusal fired on Bash(a) and Bash(b) - the user's own permission rules, echoed verbatim into the widening report, which are exactly that shape and are not ours to rewrite. So the script now marks a quoted rule as quoted, both scans skip those lines through the one constant that prints the marker, and a parenthesised plural in our own heading is still red. Reading better for a person too: the rules are visibly theirs. Seven junctions are unlinked before the temp tree goes, which the run before the fix reported it could not do.

All entries: https://alegauss.github.io/changelog/claude-tray/
