Release notes

BUGFIX

Fixed blank Codex panels and mangled project names

Your Codex panel will no longer mysteriously go blank just because you had a few brief sessions. Previously, if you ran several quick commands that were interrupted (like pressing Ctrl-C), the system would only check the last 5 logs. Since those short "dud" sessions lacked quota data, the system gave up and displayed "--"; it now looks much further back to find your actual rate limits and model info. Additionally, if your project folder name contained hyphens (like my-awesome-project), the system used to mangle it into an unrecognizable path; it now correctly decodes hyphens, displaying your project's true name. It's like checking your loyalty points: the cashier used to see five $0 transactions and claim you had no account while mispronouncing your name; now they flip back further to find your actual point balance and finally call you by the right name.

BUGFIX

Terminal language syncs automatically, and background memory bloat is fixed

When you open your usage tables in the terminal, the language now perfectly matches your menu bar. Previously, the terminal interface was a bit stubborn—it only understood Traditional Chinese and English, and would force English on you even if you had Japanese or Korean selected in the main app. Now, both interfaces speak the exact same language. At the same time, we've fixed a major resource leak in the background app. The system used to hoard every single chat history log you ever loaded in its memory forever, causing its memory footprint to endlessly balloon over time. We've now installed a strict "512-item limit" to its brain, automatically clearing out the oldest data when full. It's like a library front desk that used to pile up every returned book forever until the desk collapsed under the weight; now, the desk holds a strict limit of 512 books, automatically shelving the oldest ones when a new one arrives.

Original changelog

Original changelogFixed blank Codex panels and mangled project names
**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.
**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`.
Original changelogTerminal language syncs automatically, and background memory bloat is fixed
**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.
**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 `OrderedDict`s 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.