Show HN: Claude Fleet – Session Manager Widget Always on Top for CC (Windows) Shalom Borohov released Claude Fleet, a Windows widget that tracks multiple Claude Code sessions in an always-on-top strip, sorting them by urgency so users can see which session is waiting on them. The tool, which requires Python 3.11+ and Claude Code, uses hooks to receive events and displays states like PERMISSION, WAITING, RUNNING, and DONE, with features such as click-to-open in VS Code and Windows toasts for notifications. One glanceable widget for every Claude Code session you have running. Running one Claude Code session is easy to follow. Running five is not. The moment you go parallel, the useful question stops being "what is Claude doing?" and becomes "which of these is stuck waiting on me?" — and the answer is invisible. A session blocked on a permission prompt looks exactly like a session busy thinking: both are just another terminal behind another window. So you alt-tab through all of them, find the one showing a prompt, answer it, and discover a second one has been idle for six minutes. claude-fleet puts all of them in one small always-on-top strip, sorted so the one that needs you is always on top. Each session is one row: a coloured dot, the repository name, and the branch narrowed to its two significant words web-client :dark-mode . Rows are sorted by urgency, not by name. | State | Colour | Meaning | |---|---|---| PERMISSION | red | Claude is blocked asking to run something | WAITING | amber | A notification is waiting on you | RUNNING | green | Working — nothing needed from you | DONE | grey | Finished or idle | When a session raises a permission prompt it jumps to the top, turns red, the window pulses once, and the prompt text appears beneath the row. When every session is done, the widget dims and gets out of your way. Three things the demo above cannot show, because the capture records only the widget itself: Left-click a row to open that project in VS Code. If a window is already open on that folder it is focused rather than duplicated. Right-click a row for Open in VS Code , plus Hide session on finished rows. Hover a row for a tooltip with the full working directory, elapsed time, and either the full notification text or the prompt the session was given. The widget is pinned across virtual desktops, hidden from alt-tab, and Windows toasts fire on notifications, so a session on another desktop still reaches you. - Windows 10 or 11 the widget, the toasts and the hook script are all Windows-specific - Python 3.11 or newer tomllib - Claude Code - VS Code, optional — only for click-to-focus Clone and install in editable mode. This is the supported install path : the hook script has to exist on disk for Claude Code to invoke it, and it lives in the repository rather than inside the Python package. git clone https://github.com/shalom-borohov/claude-fleet.git cd claude-fleet py -3 -m venv .venv .venv\Scripts\pip install -e ". dev " Check it runs: .venv\Scripts\fleet status It will print No active agents. until the hooks are wired up. claude-fleet has no daemon and does not watch Claude Code. Claude Code pushes events to it through hooks, so nothing appears until you register them. .venv\Scripts\fleet print-hooks That prints a ready-made JSON block covering six events — SessionStart , UserPromptSubmit , PostToolUse , Notification , Stop and SessionEnd — each pointing at the absolute path of your clone's hooks/record event.ps1 . Merge it into the "hooks" object of ~/.claude/settings.json : { "hooks": { "SessionStart": { "hooks": { "type": "command", "command": "& 'C:\\path\\to\\claude-fleet\\hooks\\record event.ps1'", "shell": "powershell", "timeout": 10 } } } } TheIf you already use one, merge the two commands into a single entry rather than overwriting it. Notification entry replaces any existing Notification hook you have. Start a Claude Code session, then run the widget: .venv\Scripts\fleet watch | Command | Does | |---|---| fleet watch | The always-on-top widget | fleet status | Prints current state as text, no GUI | fleet print-hooks | Prints the settings.json block to merge | bash $ fleet status PERMISSION web-client:dark-mode 14s Claude needs your permission to run npm publish RUNNING payments-api:stripe-webhook 92s DONE infra:terraform-drift 431s Drag the header to move the widget; it snaps to screen edges and remembers where you left it. Press Esc or click ✕ to close it. Optional TOML at %LOCALAPPDATA%\claude-fleet\config.toml . Unknown keys are ignored. poll interval sec = 1.5 stale after minutes = 480 exclude projects = "scratch", "dotfiles" | Key | Default | Meaning | |---|---|---| poll interval sec | 1.5 | How often the widget re-reads session state | stale after minutes | 480 | Records older than this stop being displayed | data dir | %LOCALAPPDATA%\claude-fleet | Where session state and widget position live | exclude projects | | Folder names to never display | exclude projects matches the last path segment of the session's working directory — the folder Claude Code was launched in, not the repository name shown on the row. The two halves never call each other; they are decoupled through the filesystem. Claude Code ──hook event JSON on stdin ── record event.ps1 │ writes one JSON file per session │ %LOCALAPPDATA%\claude-fleet\sessions\ │ polled every 1.5s │ fleet watch / status Each event overwrites that session's file, so what is on disk is always the current state rather than a history. SessionEnd deletes it. Sessions that crash without firing SessionEnd simply age out once they pass stale after minutes . CLAUDE.md /Shalom-Borohov/claude-fleet/blob/main/CLAUDE.md documents the design in depth — the state machine, why the branch label is narrowed to two words, and why clicking opens a matched ancestor folder instead of the raw working directory. The widget is empty. Hooks are not registered, or every session is stale. Run fleet status to check without the GUI, and confirm the path in ~/.claude/settings.json points at a record event.ps1 that actually exists. A session is missing. Its record is older than stale after minutes , or its folder name is in exclude projects , or you hid it from the right-click menu. Hidden sessions come back on their own as soon as the session does anything again. No toasts. Toasts only fire on Notification events. Check Windows notification settings, and make sure the Notification hook was not overwritten by another tool. Clicking a row opens a second VS Code window. Windows are matched by folder name off the VS Code window title, so two open windows whose folders share a leaf name are indistinguishable, and a folder that is not currently open cannot be matched at all. Rows for sessions that already ended. State is only written when a hook fires. A killed terminal never sends SessionEnd , so its row stays until it goes stale. .venv\Scripts\python -m pytest Tests live in test/unit/ . To re-record the demo after a UI change: .venv\Scripts\pip install -e ". demo " .venv\Scripts\python tools\capture demo.py That drives the real widget with synthetic sessions and writes docs/demo.gif . It moves the mouse pointer aside and shows a window for about twelve seconds while it records. This is an unofficial community project. It is not affiliated with, endorsed by, or supported by Anthropic.