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
Codex usage panel no longer falls back to -- after a burst of short sessions: codex_loader.load_rate_limits() only scanned the 5 most recent jsonl files via _recent_jsonl_files() to find rate_limits. Codex CLI (observed on 0.134.0) writes payload.rate_limits == null for short or interrupted sessions (a quick codex exec run, Ctrl-C, etc.); when the latest 5 sessions all fall into that bucket, the genuinely-valid prior session gets evicted from the lookup window and the entire Codex block in the popover / TUI renders as --. The scan window is widened from 5 to 30 (covers a typical 1–2 day usage range); the first non-null result still early-returns, and the primary.used_percent / secondary.used_percent parsing path is unchanged. The new Codex CLI 0.134.0 schema fields (limit_id, limit_name, credits, plan_type, rate_limit_reached_type) are deliberately not parsed — UI doesn't use them. Three new tests cover the "5 null then 6th valid", "all 30 null returns None", and "pick most recent valid" scenarios.
Fixed
Dashed Claude Code project names now decode correctly: history_loader._project_from_path previously replaced every - in the encoded directory name with /, so Desktop-claude-tutorial-video would become /Desktop/claude/tutorial/video — a non-existent path. resolve_project_name's fallback then took the last segment, mis-labeling the project as "video" instead of "claude-tutorial-video". The decoder now tries the all-slash candidate first; on miss, it DFS-walks the segments, joining adjacent ones with - and preferring whichever variant actually exists on disk. When nothing matches, the encoded name (minus the leading -) is kept as-is so dashes round-trip (plain-project stays plain-project). For most users, the JSONL cwd field already overrides the project name, so this primarily fixes older entries that lack cwd.
TUI language detection routed through usage_lang.detect_lang: tui.py had its own detector that only returned zh-TW or en (treating simplified Chinese, Japanese, and Korean as English), and ignored USAGE_LANG / TT_LANG / LANG entirely. The menubar already used usage_lang.detect_lang(), so the same machine could show Japanese in the menubar and English in the TUI. The TUI now shares the same detector — all five languages render consistently.
Internal improvements
LRU cap on history / codex loader caches: _file_cache and _jsonl_cache were unbounded module-level dicts. As ~/.claude/projects/ and ~/.codex/sessions/ accumulated more jsonl files over time, the menubar's resident memory grew without bound — parsed UsageEntry lists never got released. Both caches are now OrderedDicts with a 512-entry ceiling: cache hits move_to_end to mark MRU, inserts on a full cache popitem(last=False) the oldest. The mtime/size invalidation logic and codex_loader's entry.model rebind on cache hit are unchanged.
Development
Significantly expanded test coverage: previously undercovered modules setup_app / ui/tables / usage_cli now have direct unit tests; the suite grew from 234 to 363 tests. No production code was changed.