You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Recovered Claude history is rebuilt from message timestamps: a prompt starts a turn and the last answer or Stop hook ends it, like Codex tasks. Tool results, subagent, meta and compaction rows never start a turn, unanswered prompts and silences over 30 minutes are not counted, and neither is the wait for your answer to a question or a plan approval. Long autonomous turns count in full, as live work does. Recovered time keeps its ≈ mark. The import version changes, so existing history is re-imported automatically once; the re-import reads only logs that can hold records from before live observation started.
"From available records" appears only when coverage was actually lost (read budget, unreadable or missing logs, symbolic links). Skipped individual records stay in the import report as information, and widgets no longer show the info badge.
Live collection tolerates a slow observation of up to three poll steps plus 5 seconds. Sleep and wake always start a new measurement. Longer gaps in running work are counted under History and data accuracy instead of disappearing silently.
Activity is written less often: history once a minute while work runs, project/session details every five minutes without a forced disk flush (flushed at quit and before the Mac sleeps), and phase changes after a 15-second quiet period. Changes that do not affect measured activity no longer rewrite files. Quitting waits at most 3 seconds for an unresponsive disk.
An unreadable statistics file no longer stops collection for good: Keep a copy and start over keeps it beside the original and starts a new history. Only that button does this; Refresh history and connecting a provider leave the file untouched. Details stay below the read limit by dropping the oldest records first, overlapping detail intervals are repaired instead of discarding the breakdown, and abandoned temporary files are removed at launch.
Quota updates no longer reload the activity widget; it reloads when its history or its shared settings change. The installed app re-confirms its widget registration 5 seconds and 2 minutes after launch. When another copy of Lunavect is installed, Settings → Widgets names it and asks you to keep one; the app still confirms its own widgets unless macOS uses the other copy's.
Find data from a previous installation lists copies left by the App Group migration, with their paths and last changes, and can move them to the Trash. Copies written within the last week, which a development build may still use, are not offered. The privacy page lists these copies, recovery backups and the IDE bridge files.
The glass widget background can be turned off without a rebuild through a hidden setting; it relies on a private macOS interface and blocks Mac App Store distribution.
After the clock is set far ahead and corrected, activity keeps being recorded instead of stopping until real time catches up.
On a slow disk, activity saving keeps only the newest waiting state: memory no longer grows with a backlog and quitting writes the last state within its time limit. Retention trims only expired history from its start instead of scanning all of it on every observation.
The small limits widget and the combined widget show a plan without limits as ∞, a used-up or not yet started window like the menu bar, and no false warning mark.
A failed App Group migration removes only the copies it made, so the next installation can migrate again.
Navigation to sessions
Opening a terminal session no longer selects an unrelated tab that macOS gave the closed session's terminal device. Lunavect checks that Claude or Codex still runs there first; iTerm2 also restores a minimized window. A session whose CLI binary an update replaced, or that runs under another file name, is not mistaken for a closed one, and the terminal behind Terminal's login (including Alacritty) is named.
The first macOS permission prompt for controlling Terminal or iTerm2 can be answered without a false timeout: Lunavect asks before searching tabs and waits up to a minute. When both terminals run, they share the 10-second search.
Ghostty, Warp, kitty, WezTerm, Alacritty, tmux, screen, ssh sessions and VS Code forks such as Cursor are named as not supported instead of Lunavect searching Terminal tabs. A Codex CLI without TERM_PROGRAM no longer opens Codex Desktop.
A live session whose tab cannot be focused is reported as possibly open even while its CLI is missing or being updated.
Editor navigation distinguishes a busy editor, a companion that is installed but not answering, an incompatible companion and a window macOS refuses to activate from a missing session, and names the JetBrains product. Every JetBrains 2026.2 IDE and EAP build is recognized.
VS Code companion 0.1.2: reports its version, keeps its socket in your private temporary folder, recreates it after the folder is cleaned and warns when it cannot start. An editor started with a different TMPDIR (a shell profile, nix develop, devbox or none) is still found, as long as the socket folder is private to you. Settings → Connections shows when an installed companion is older than the bundled one. Reinstall the companion to receive these fixes. The JetBrains companion 0.1.2 is prepared in source; the bundled JetBrains installer stays 0.1.1 until it is rebuilt with the IntelliJ SDK.
Stale editor connection records left by forced quits are removed after a day. Installed 0.1.0 and 0.1.1 companions keep working.
A stopped Claude session no longer opens another Claude session that received the same terminal device: when the session's hook recorded its process, only that process identifies the tab.
The VS Code companion recognizes the Claude Code panel by the tab type VS Code reports, so opening such a session no longer ends with a false "VS Code did not respond in time".
Sessions
Lunavect's own /usage quota check no longer appears as a Claude session. Its run could show "quotaprobe-00 · Input needed", raise the menu-bar waiting count, play a notification sound, add activity minutes, start automatic Keep Awake and speed up polling.
Automatic hiding no longer fills Hidden sessions with finished or dormant Claude background tasks that claude agents --all keeps listing, or with sessions that ended before the panel showed them. The listing of such history no longer keeps hidden entries from expiring after 35 days.
A subagent finishing can no longer raise a session's background task count, and an empty list no longer clears it; the end of each reply sets it. Commands moved to the background while running are counted. Sessions that started no background work no longer show a task badge.
Closing Claude right after interrupting a reply no longer announces Response ready. A finished claude -p or Agent SDK reply is announced once even when its end and the session's end arrive together.
A Claude session in a terminal or editor whose client was killed or crashed mid-reply shows Stopped at once instead of working or waiting for up to ten minutes, and no longer adds activity or holds Keep Awake. One failed session-list read no longer shows it working again, and resuming it with claude --resume starts Idle instead of repeating the killed reply.
A hook event that arrives while a session list is being read is no longer overridden by that list, and one failed or slow read no longer empties the list. A project on a disconnected network volume no longer stalls reading the list.
Hidden-session expiry and ordering cleanup wait until the session lists have answered, instead of running once without them after launch.
Answered MCP forms return the session to working, and a background agent asking for input shows Input needed.
A resumed or forked Claude session appears as Idle before its first prompt, and a hidden one is shown again.
A system clock correction no longer hides every idle session at once.
Session records that can no longer be read are kept aside for diagnosis and removed after a day instead of being read again on every refresh.
If claude agents --json changes its format, Connections reports an unsupported response instead of showing an empty Claude list.
A subagent finishing now reaches Lunavect: its list can lower a session's background task count and never raises it.
Response ready and error notifications are announced once, even when Claude's session list still reports the session as busy while Stop hooks run.
A new session that Lunavect first sees already waiting for permission or input, or already answered, is announced. Sessions present at launch stay silent.
A burst of hook events causes one read of the session records instead of about two reads per event.
Usage limits
Limits are requested by window state instead of every five minutes. A verified value is reused for 15 minutes during work and an hour when idle; an exhausted window is not requested before its reset; one confirming request follows each reset; failures back off from 5 to 60 minutes. Finished Claude and Codex responses reported by hooks trigger a debounced request. Wake waits for the network. The same policy applies to Codex.
While a window is used up, no request runs before its own reset, even when the other window's reset passes meanwhile; previously an unreadable screen at 100% could bring a visible probe every hour until the weekly reset. Claude's "limit reached" screen pauses requests until the earliest known reset. Wake and a restored network retry at once only after a network, timeout or loading failure; a workspace trust question, sign-in, API billing or unsupported screen keeps its backoff until you refresh. A request right after a reset that still shows the old window keeps "Reset at HH:MM, waiting for the new window's first data" and is repeated after 5, 10, 20 minutes and so on. A timer, reset or session event that arrives during another refresh is evaluated after it instead of being dropped.
A /usage screen still loading at the deadline is reported as a timeout instead of "window not started". Values Claude Code shows next to "Could not refresh usage data" or "Failed to load usage data" are no longer saved as a fresh reading. Cursor and spinner redraws no longer keep a failed probe open for 25 seconds.
A failed Claude /usage probe ends two seconds after its screen stops changing instead of keeping Claude Code open for 25 seconds, and reports a specific reason: limit reached, usage data failed to load, window not started, workspace trust required (previously shown as a sign-in problem) or subscription limits unavailable (API billing or no subscription sign-in).
After a weekly reset, an unstarted window is shown as 100% with "Starts with the first request" instead of "Unsupported response format". An exhausted window shows 0% with its countdown and no asterisk; after a passed reset without new data every surface shows the same "Reset at HH:MM, waiting for the new window's first data".
Codex shows "No limits" when it reports unlimited credits without rate-limit windows, instead of waiting forever. An answer without any known window otherwise stays unknown and is asked again with the failure backoff, not every five minutes. Codex's reached-limit flag counts as 100%.
Connections and Limits explain when Claude Desktop sessions cannot update limits through the status line.
--probe prints the result of a real /usage probe; --usage-probe prints its screen. LUNAVECT_PROBE_DUMP_DIR saves failed probe screens for diagnosis (opt-in).
"Limit available again" is no longer sent up to a minute early. /usage shows resets truncated to the minute ("11:59pm" for a reset at midnight); Lunavect now stores the end of the shown minute, so a Claude window no longer shows a dash or counts as reset during that minute, and a saved /usage reading from an earlier version is read the same way, including model limits that a 0.2.4 snapshot kept next to status-line data. When two sources report the same reset, the later time counts.
More /usage reset forms are understood instead of failing the probe: a date without a time, "in 2h 15m", "today/tomorrow at …", 12-hour times with a space or capitals, 24-hour times, abbreviated time zones such as "CEST", a reset on the percentage line and model blocks such as "Current week (Sonnet only)". An "Extra usage" block is no longer read as the weekly window. Dated resets in the daylight-saving change are handled like clock times: a repeated hour counts from its later occurrence, a skipped hour is rejected.
A Claude status-line window without a reset time no longer discards the other window; at 0% it is shown as not started ("Starts with the first request"), like the same state from /usage. "No model usage data available" is reported as usage data that failed to load, and a Claude Code path that became a folder is reported as missing at once.
When Claude Code in Terminal is not signed in to a Claude account, its /usage shows "API Usage Billing" and no plan limits. Lunavect now says that Claude Code is not signed in and how to sign in (Sign in again, or claude then /login in Terminal), instead of "the client's response format is not supported".
A failed /usage check keeps its reason in Connections instead of reporting the connection as working after a few seconds.
An unfamiliar block after an inactive window no longer gives that window its reset time or rejects the whole screen.
Running an older copy of Lunavect alongside no longer shifts saved reset times by a minute each time.
Lunavect's status line waits at most 10 seconds for your previous status line command and reads at most 1 MB from Claude.
Connections explains why checks are unavailable while limits are updating, says when a check can run again, and no longer promises an update next to an unsupported response. The limits popover's refresh button explains why it is off.
Keep Awake and connections
Keep Awake shows when the system helper is still registered from an earlier build or signing team and macOS does not start it, instead of reporting a generic timeout. Renew registration repairs it; if macOS refuses, the panel offers the maintenance command of this installation and Login Items. The first lease in a new build pings the helper for three seconds and renews its registration once when it does not answer.
The helper's launch definition no longer asks launchd to restart it after every exit. A helper whose program is missing no longer makes launchd retry every 30 seconds indefinitely. The first launch of this build renews the registration so installed helpers pick up the new definition. A helper that cannot restore sleep keeps retrying while it runs, and Lunavect starts a new helper instance when the previous one stops answering during a lease.
Claude Code and Codex settings name the hook helper through a link in Lunavect's support folder that every launch points at the running app. Moving, renaming or updating Lunavect no longer leaves the status line and event handlers pointing at a missing file. A copy that macOS runs from a temporary download location asks to be moved to Applications instead of writing its temporary path. Existing entries move to the link at the next launch, and the session panel says so.
Launch repair changes only Lunavect's own entries that point elsewhere. It no longer adds back an event handler you removed, and disableAllHooks is shown as paused instead of a failed repair after moving the app.
Turn off events is shown as your choice with a Turn on events button, not as unfinished setup. A command pointing at a deleted file is shown with its path.
Settings files with comments or trailing commas are left untouched. Rewritten files end with a newline, are flushed to disk before they replace the original, and keep a link to a settings file even when its file does not exist yet. Disconnecting keeps a settings file Lunavect created, without its entries. Older backups of client settings become private to your user.
A second installed copy of Lunavect is reported on the session panel. weekleft:// links open the same pages as lunavect://. Updates are checked once a day instead of every hour.
After an update, a helper that stopped while sleep was turned off is started once to restore normal sleep before its registration is renewed. The panel says that sleep is off instead of claiming the helper is retrying.
When macOS refuses to renew the helper registration, the panel keeps the manual repair steps instead of offering a retry that repeats the refusal. A refused connection renews the registration at most once per launch.
In automatic mode Keep Awake reads the helper status at most every 5 seconds instead of on every session update.
A malformed hook command no longer opens Lunavect's window, and --probe and --usage-probe exit with an error after a timeout.
Resetting settings is not applied partly when one part fails. VoiceOver reads each connection step with its state. Spanish uses the informal tú throughout.
Development and checks
Version 0.2.5 (192), so a local build of this branch cannot be mistaken for 0.2.4 (191).
Tests can no longer reach the user's applications, clipboard, Finder, client CLIs, login items or widget registration: navigation, process launches and system features refuse under XCTest unless a live test opts in, and every write guard now covers directory creation, recovery moves and cleanup. Native fixture cleanup never signals a reused process ID.
check.sh verifies that the app, widget and both helpers contain arm64 and x86_64 slices. The iCloud copy check covers .github, docs and design.
Packaging tools refuse test overrides without --test-fixture, and release preflight refuses a VERSION that differs from project.yml.
The weekly native render comparison fails when its baseline cannot be compared instead of passing without a comparison.
The privacy notes list the Automation permission used to focus Terminal and iTerm2 tabs.