{"slug": "show-hn-claude-fleet-session-manager-widget-always-on-top-for-cc-windows", "title": "Show HN: Claude Fleet – Session Manager Widget Always on Top for CC (Windows)", "summary": "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.", "body_md": "One glanceable widget for every Claude Code session you have running.\n\nRunning one Claude Code session is easy to follow. Running five is not.\n\nThe moment you go parallel, the useful question stops being *\"what is Claude doing?\"* and becomes\n*\"which of these is stuck waiting on me?\"* — and the answer is invisible. A session blocked on a\npermission prompt looks exactly like a session busy thinking: both are just another terminal behind\nanother window. So you alt-tab through all of them, find the one showing a prompt, answer it, and\ndiscover a second one has been idle for six minutes.\n\n`claude-fleet`\n\nputs all of them in one small always-on-top strip, sorted so the one that needs you\nis always on top.\n\nEach session is one row: a coloured dot, the repository name, and the branch narrowed to its two\nsignificant words (`web-client :dark-mode`\n\n). Rows are sorted by urgency, not by name.\n\n| State | Colour | Meaning |\n|---|---|---|\n`PERMISSION` |\nred | Claude is blocked asking to run something |\n`WAITING` |\namber | A notification is waiting on you |\n`RUNNING` |\ngreen | Working — nothing needed from you |\n`DONE` |\ngrey | Finished or idle |\n\nWhen 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.\n\nThree things the demo above cannot show, because the capture records only the widget itself:\n\n**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.\n\nThe 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.\n\n- Windows 10 or 11 (the widget, the toasts and the hook script are all Windows-specific)\n- Python 3.11 or newer (\n`tomllib`\n\n) - Claude Code\n- VS Code, optional — only for click-to-focus\n\nClone and install in editable mode. **This is the supported install path**: the hook script has to\nexist on disk for Claude Code to invoke it, and it lives in the repository rather than inside the\nPython package.\n\n```\ngit clone https://github.com/shalom-borohov/claude-fleet.git\ncd claude-fleet\npy -3 -m venv .venv\n.venv\\Scripts\\pip install -e \".[dev]\"\n```\n\nCheck it runs:\n\n```\n.venv\\Scripts\\fleet status\n```\n\nIt will print `No active agents.`\n\nuntil the hooks are wired up.\n\n`claude-fleet`\n\nhas no daemon and does not watch Claude Code. Claude Code pushes events to it\nthrough hooks, so nothing appears until you register them.\n\n```\n.venv\\Scripts\\fleet print-hooks\n```\n\nThat prints a ready-made JSON block covering six events — `SessionStart`\n\n, `UserPromptSubmit`\n\n,\n`PostToolUse`\n\n, `Notification`\n\n, `Stop`\n\nand `SessionEnd`\n\n— each pointing at the absolute path of your\nclone's `hooks/record_event.ps1`\n\n. Merge it into the `\"hooks\"`\n\nobject of `~/.claude/settings.json`\n\n:\n\n```\n{\n  \"hooks\": {\n    \"SessionStart\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"& 'C:\\\\path\\\\to\\\\claude-fleet\\\\hooks\\\\record_event.ps1'\",\n            \"shell\": \"powershell\",\n            \"timeout\": 10\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\nTheIf you already use one, merge the two commands into a single entry rather than overwriting it.`Notification`\n\nentry replaces any existing`Notification`\n\nhook you have.\n\nStart a Claude Code session, then run the widget:\n\n```\n.venv\\Scripts\\fleet watch\n```\n\n| Command | Does |\n|---|---|\n`fleet watch` |\nThe always-on-top widget |\n`fleet status` |\nPrints current state as text, no GUI |\n`fleet print-hooks` |\nPrints the `settings.json` block to merge |\n\n``` bash\n$ fleet status\nPERMISSION  web-client:dark-mode     14s  Claude needs your permission to run npm publish\nRUNNING     payments-api:stripe-webhook 92s\nDONE        infra:terraform-drift    431s\n```\n\nDrag the header to move the widget; it snaps to screen edges and remembers where you left it.\nPress `Esc`\n\nor click `✕`\n\nto close it.\n\nOptional TOML at `%LOCALAPPDATA%\\claude-fleet\\config.toml`\n\n. Unknown keys are ignored.\n\n```\npoll_interval_sec = 1.5\nstale_after_minutes = 480\nexclude_projects = [\"scratch\", \"dotfiles\"]\n```\n\n| Key | Default | Meaning |\n|---|---|---|\n`poll_interval_sec` |\n`1.5` |\nHow often the widget re-reads session state |\n`stale_after_minutes` |\n`480` |\nRecords older than this stop being displayed |\n`data_dir` |\n`%LOCALAPPDATA%\\claude-fleet` |\nWhere session state and widget position live |\n`exclude_projects` |\n`[]` |\nFolder names to never display |\n\n`exclude_projects`\n\nmatches the last path segment of the session's working directory — the folder\nClaude Code was launched in, not the repository name shown on the row.\n\nThe two halves never call each other; they are decoupled through the filesystem.\n\n```\nClaude Code ──hook event (JSON on stdin)──> record_event.ps1\n                                                  │\n                              writes one JSON file per session\n                                                  │\n                          %LOCALAPPDATA%\\claude-fleet\\sessions\\\n                                                  │\n                                        polled every 1.5s\n                                                  │\n                                          fleet watch / status\n```\n\nEach event overwrites that session's file, so what is on disk is always the current state rather\nthan a history. `SessionEnd`\n\ndeletes it. Sessions that crash without firing `SessionEnd`\n\nsimply age\nout once they pass `stale_after_minutes`\n\n.\n\n[ CLAUDE.md](/Shalom-Borohov/claude-fleet/blob/main/CLAUDE.md) documents the design in depth — the state machine, why the branch label is\nnarrowed to two words, and why clicking opens a matched ancestor folder instead of the raw working\ndirectory.\n\n**The widget is empty.** Hooks are not registered, or every session is stale. Run `fleet status`\n\nto\ncheck without the GUI, and confirm the path in `~/.claude/settings.json`\n\npoints at a\n`record_event.ps1`\n\nthat actually exists.\n\n**A session is missing.** Its record is older than `stale_after_minutes`\n\n, or its folder name is in\n`exclude_projects`\n\n, or you hid it from the right-click menu. Hidden sessions come back on their own\nas soon as the session does anything again.\n\n**No toasts.** Toasts only fire on `Notification`\n\nevents. Check Windows notification settings, and\nmake sure the `Notification`\n\nhook was not overwritten by another tool.\n\n**Clicking a row opens a second VS Code window.** Windows are matched by folder *name* off the VS\nCode window title, so two open windows whose folders share a leaf name are indistinguishable, and a\nfolder that is not currently open cannot be matched at all.\n\n**Rows for sessions that already ended.** State is only written when a hook fires. A killed terminal\nnever sends `SessionEnd`\n\n, so its row stays until it goes stale.\n\n```\n.venv\\Scripts\\python -m pytest\n```\n\nTests live in `test/unit/`\n\n. To re-record the demo after a UI change:\n\n```\n.venv\\Scripts\\pip install -e \".[demo]\"\n.venv\\Scripts\\python tools\\capture_demo.py\n```\n\nThat drives the real widget with synthetic sessions and writes `docs/demo.gif`\n\n. It moves the mouse\npointer aside and shows a window for about twelve seconds while it records.\n\nThis is an unofficial community project. It is not affiliated with, endorsed by, or supported by Anthropic.", "url": "https://wpnews.pro/news/show-hn-claude-fleet-session-manager-widget-always-on-top-for-cc-windows", "canonical_source": "https://github.com/Shalom-Borohov/claude-fleet", "published_at": "2026-08-11 12:50:17+00:00", "updated_at": "2026-08-11 13:13:43.389796+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-agents"], "entities": ["Shalom Borohov", "Claude Fleet", "Claude Code", "VS Code", "Windows"], "alternates": {"html": "https://wpnews.pro/news/show-hn-claude-fleet-session-manager-widget-always-on-top-for-cc-windows", "markdown": "https://wpnews.pro/news/show-hn-claude-fleet-session-manager-widget-always-on-top-for-cc-windows.md", "text": "https://wpnews.pro/news/show-hn-claude-fleet-session-manager-widget-always-on-top-for-cc-windows.txt", "jsonld": "https://wpnews.pro/news/show-hn-claude-fleet-session-manager-widget-always-on-top-for-cc-windows.jsonld"}}