Skip to content

v3.8.1 — daemon picks up new code after PyPI upgrade

Choose a tag to compare

@leeguooooo leeguooooo released this 21 May 05:45
· 243 commits to main since this release

Fixes a long-standing daemon staleness bug: after pip install -U claude-statusbar, the long-lived daemon kept serving old renders until manual cs daemon stop && cs daemon start.

Why it happened

The fast-mode daemon process is launched once (via cs --setup --fast or launchd) and reuses its in-memory imports for as long as it lives. After a PyPI upgrade:

  • The thin client cs render reads ~/.cache/claude-statusbar/sessions/<sid>/rendered.meta.json, sees generated_at is fresh (< 5 s), and serves the daemon's pre-rendered output — which is generated by old code.
  • _spawn_daemon_async refuses to start a new daemon because the old one's pidfile is still valid.
  • Result: users had to manually restart the daemon to see any updates after a PyPI upgrade.

How v3.8.1 fixes it

  1. Daemon records daemon_started_at = time.time() when it boots and writes that into rendered.meta.json every tick.
  2. Thin client computes max(*.py mtime) of the installed claude_statusbar/ package directory via a single os.scandir.
  3. New gate in _is_fresh(): if pkg_mtime > daemon_started_at, the daemon is older than the code on disk → treat meta as stale.
  4. When stale due to code drift, thin client SIGTERMs the daemon pid recorded in the meta. The existing inline-fallback + _spawn_daemon_async path brings up a fresh daemon on the next render tick.
  5. Pre-3.8.1 daemons don't write daemon_started_at; the new gate skips them so the v3.8.0 → v3.8.1 rollout is smooth (the daemon restart after the upgrade is what activates the new behavior).

Performance

  • os.scandir over the ~30 .py files in the package: ~50–100 μs per render tick. Negligible against the < 5 ms thin-client budget.
  • No new top-level imports — signal is lazy-imported inside _signal_outdated_daemon so test_import_perf invariants stay green.

Stats

394 → 399 tests (5 new in tests/test_daemon_freshness.py). All passing.

Upgrading

  • New installs: nothing to do.
  • Existing fast-mode users on v3.8.0: PyPI auto-updater will pull v3.8.1 within a day. The first cs render after the upgrade kills the old daemon and respawns. Worst case 1 s of inline rendering during the transition.