usage-cli 0.31.3__tar.gz → 0.31.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. {usage_cli-0.31.3 → usage_cli-0.31.5}/PKG-INFO +37 -34
  2. {usage_cli-0.31.3 → usage_cli-0.31.5}/README.md +36 -33
  3. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/claude.py +9 -2
  4. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/reporter.py +1 -1
  5. {usage_cli-0.31.3 → usage_cli-0.31.5}/i18n.json +10 -5
  6. {usage_cli-0.31.3 → usage_cli-0.31.5}/installer/session_hooks.py +40 -2
  7. {usage_cli-0.31.3 → usage_cli-0.31.5}/installer/setup_hook.py +1 -1
  8. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/history_loader.py +11 -5
  9. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/app.py +1 -1
  10. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/notify.py +10 -0
  11. {usage_cli-0.31.3 → usage_cli-0.31.5}/pricing.py +12 -0
  12. {usage_cli-0.31.3 → usage_cli-0.31.5}/pyproject.toml +1 -1
  13. {usage_cli-0.31.3 → usage_cli-0.31.5}/setup_app.py +1 -0
  14. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_adapters_claude.py +52 -0
  15. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_history_loader.py +26 -0
  16. usage_cli-0.31.5/tests/test_menubar_notify.py +37 -0
  17. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_pricing.py +7 -0
  18. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_session_resume.py +160 -2
  19. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_setup_hook_resume.py +43 -3
  20. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_statusline.py +7 -7
  21. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/tables.py +1 -0
  22. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.egg-info/PKG-INFO +37 -34
  23. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.egg-info/SOURCES.txt +1 -0
  24. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_session_resume.py +98 -14
  25. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_statusline.py +22 -30
  26. {usage_cli-0.31.3 → usage_cli-0.31.5}/LICENSE +0 -0
  27. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/__init__.py +0 -0
  28. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/agy.py +0 -0
  29. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/codex.py +0 -0
  30. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/grok.py +0 -0
  31. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/muse.py +0 -0
  32. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/rate_limits.py +0 -0
  33. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/registry.py +0 -0
  34. {usage_cli-0.31.3 → usage_cli-0.31.5}/adapters/types.py +0 -0
  35. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/__init__.py +0 -0
  36. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/aggregator.py +0 -0
  37. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/blocks.py +0 -0
  38. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/diagnoser.py +0 -0
  39. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/dispatch_ledger.py +0 -0
  40. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/insights.py +0 -0
  41. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/persona_loader.py +0 -0
  42. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/subscription.py +0 -0
  43. {usage_cli-0.31.3 → usage_cli-0.31.5}/analyzer/usage_snapshot.py +0 -0
  44. {usage_cli-0.31.3 → usage_cli-0.31.5}/doctor.py +0 -0
  45. {usage_cli-0.31.3 → usage_cli-0.31.5}/fsevents_watch.py +0 -0
  46. {usage_cli-0.31.3 → usage_cli-0.31.5}/i18n.py +0 -0
  47. {usage_cli-0.31.3 → usage_cli-0.31.5}/installer/__init__.py +0 -0
  48. {usage_cli-0.31.3 → usage_cli-0.31.5}/installer/login_item.py +0 -0
  49. {usage_cli-0.31.3 → usage_cli-0.31.5}/installer/statusline_settings.py +0 -0
  50. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/__init__.py +0 -0
  51. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/agy_disk_cache.py +0 -0
  52. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/agy_loader.py +0 -0
  53. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/agy_quota_probe.py +0 -0
  54. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/cache_quarantine.py +0 -0
  55. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/claude_paths.py +0 -0
  56. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/codex_disk_cache.py +0 -0
  57. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/codex_events.py +0 -0
  58. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/codex_fork_replay.py +0 -0
  59. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/codex_loader.py +0 -0
  60. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/codex_paths.py +0 -0
  61. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/disk_cache_common.py +0 -0
  62. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/disk_cache_lifecycle.py +0 -0
  63. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/grok_loader.py +0 -0
  64. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/grok_quota_probe.py +0 -0
  65. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/history_disk_cache.py +0 -0
  66. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/jsonl_limits.py +0 -0
  67. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/jsonl_utils.py +0 -0
  68. {usage_cli-0.31.3 → usage_cli-0.31.5}/loaders/muse_loader.py +0 -0
  69. {usage_cli-0.31.3 → usage_cli-0.31.5}/main.py +0 -0
  70. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/__init__.py +0 -0
  71. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/actions.py +0 -0
  72. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/agy.py +0 -0
  73. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/chrome.py +0 -0
  74. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/grok.py +0 -0
  75. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/menu.py +0 -0
  76. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/popover.py +0 -0
  77. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/prefs.py +0 -0
  78. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/refresh.py +0 -0
  79. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/state.py +0 -0
  80. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/title.py +0 -0
  81. {usage_cli-0.31.3 → usage_cli-0.31.5}/menubar/update.py +0 -0
  82. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/__init__.py +0 -0
  83. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/base.py +0 -0
  84. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/dynamic_height.py +0 -0
  85. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/panel_scale.py +0 -0
  86. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/panel_window.py +0 -0
  87. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/panel_window_state.py +0 -0
  88. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/payload.py +0 -0
  89. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/web_panel.py +0 -0
  90. {usage_cli-0.31.3 → usage_cli-0.31.5}/panels/window_drag.py +0 -0
  91. {usage_cli-0.31.3 → usage_cli-0.31.5}/prefs.py +0 -0
  92. {usage_cli-0.31.3 → usage_cli-0.31.5}/project_resolver.py +0 -0
  93. {usage_cli-0.31.3 → usage_cli-0.31.5}/quota/__init__.py +0 -0
  94. {usage_cli-0.31.3 → usage_cli-0.31.5}/quota/agy_window_keeper.py +0 -0
  95. {usage_cli-0.31.3 → usage_cli-0.31.5}/quota/burn_rate.py +0 -0
  96. {usage_cli-0.31.3 → usage_cli-0.31.5}/quota/codex_window_keeper.py +0 -0
  97. {usage_cli-0.31.3 → usage_cli-0.31.5}/quota/usage_rate.py +0 -0
  98. {usage_cli-0.31.3 → usage_cli-0.31.5}/quota/window_keeper.py +0 -0
  99. {usage_cli-0.31.3 → usage_cli-0.31.5}/service_status.py +0 -0
  100. {usage_cli-0.31.3 → usage_cli-0.31.5}/setup.cfg +0 -0
  101. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_adapters_codex.py +0 -0
  102. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_adapters_rate_limits.py +0 -0
  103. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_aggregator.py +0 -0
  104. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_agy_adapter.py +0 -0
  105. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_agy_disk_cache.py +0 -0
  106. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_agy_loader.py +0 -0
  107. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_agy_quota_probe.py +0 -0
  108. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_agy_window_keeper.py +0 -0
  109. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_analyzer_blocks.py +0 -0
  110. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_analyzer_pipeline.py +0 -0
  111. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_burn_rate.py +0 -0
  112. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_cache_quarantine.py +0 -0
  113. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_claude_paths.py +0 -0
  114. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_codex_consistency.py +0 -0
  115. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_codex_loader.py +0 -0
  116. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_codex_window_keeper.py +0 -0
  117. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_diagnoser.py +0 -0
  118. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_disk_cache_shards.py +0 -0
  119. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_dispatch_ledger.py +0 -0
  120. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_doctor.py +0 -0
  121. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_dynamic_height.py +0 -0
  122. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_fsevents_watch.py +0 -0
  123. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_grok_loader.py +0 -0
  124. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_grok_quota_probe.py +0 -0
  125. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_hook_scripts_are_standalone.py +0 -0
  126. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_html_report_snapshot.py +0 -0
  127. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_i18n_format_fallback.py +0 -0
  128. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_i18n_key_parity.py +0 -0
  129. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_i18n_packaged_path.py +0 -0
  130. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_insights.py +0 -0
  131. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_jsonl_utils.py +0 -0
  132. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_login_item.py +0 -0
  133. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_main.py +0 -0
  134. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_menubar.py +0 -0
  135. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_menubar_agy.py +0 -0
  136. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_menubar_grok.py +0 -0
  137. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_menubar_prefs.py +0 -0
  138. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_menubar_state.py +0 -0
  139. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_muse_loader.py +0 -0
  140. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_packaged_resources.py +0 -0
  141. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_packaging.py +0 -0
  142. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_panel_footer_layout.py +0 -0
  143. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_panel_scale.py +0 -0
  144. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_panel_window_state.py +0 -0
  145. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_panels.py +0 -0
  146. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_panels_lazy_import.py +0 -0
  147. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_persona_loader.py +0 -0
  148. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_project_resolver.py +0 -0
  149. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_report_daily_chart.py +0 -0
  150. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_report_filter_js.py +0 -0
  151. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_reporter_build_data.py +0 -0
  152. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_service_status.py +0 -0
  153. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_setup_app.py +0 -0
  154. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_setup_hook.py +0 -0
  155. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_setup_hook_coexistence.py +0 -0
  156. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_setup_hook_terse.py +0 -0
  157. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_subprocess_utils.py +0 -0
  158. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_subscription.py +0 -0
  159. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_time_utils.py +0 -0
  160. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_tui.py +0 -0
  161. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_tui_sprite.py +0 -0
  162. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_ui_tables.py +0 -0
  163. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_update_checker.py +0 -0
  164. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_update_gate.py +0 -0
  165. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_update_release_notes.py +0 -0
  166. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_cli.py +0 -0
  167. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_client.py +0 -0
  168. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_diagnosis_snapshot.py +0 -0
  169. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_dir_sweeper.py +0 -0
  170. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_lang.py +0 -0
  171. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_logging.py +0 -0
  172. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_notifications.py +0 -0
  173. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_rate.py +0 -0
  174. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_snapshot.py +0 -0
  175. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_snapshot_replay.py +0 -0
  176. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_statusline_agy.py +0 -0
  177. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_statusline_forwarder.py +0 -0
  178. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_statusline_grok.py +0 -0
  179. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_terse_mode.py +0 -0
  180. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_usage_terse_reminder.py +0 -0
  181. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_web_panel_payload.py +0 -0
  182. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_wheel_packaging.py +0 -0
  183. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_win_login_item.py +0 -0
  184. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_window_keeper.py +0 -0
  185. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_windows_manifest.py +0 -0
  186. {usage_cli-0.31.3 → usage_cli-0.31.5}/tests/test_wintray.py +0 -0
  187. {usage_cli-0.31.3 → usage_cli-0.31.5}/tui/__init__.py +0 -0
  188. {usage_cli-0.31.3 → usage_cli-0.31.5}/tui/app.py +0 -0
  189. {usage_cli-0.31.3 → usage_cli-0.31.5}/tui/sprite.py +0 -0
  190. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/__init__.py +0 -0
  191. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/html_report.py +0 -0
  192. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/report_charts.py +0 -0
  193. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/report_daily_chart.py +0 -0
  194. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/report_filter.py +0 -0
  195. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/report_ledger.py +0 -0
  196. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/report_scripts.py +0 -0
  197. {usage_cli-0.31.3 → usage_cli-0.31.5}/ui/report_styles.py +0 -0
  198. {usage_cli-0.31.3 → usage_cli-0.31.5}/updates/__init__.py +0 -0
  199. {usage_cli-0.31.3 → usage_cli-0.31.5}/updates/checker.py +0 -0
  200. {usage_cli-0.31.3 → usage_cli-0.31.5}/updates/gate.py +0 -0
  201. {usage_cli-0.31.3 → usage_cli-0.31.5}/updates/release_notes.py +0 -0
  202. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.egg-info/dependency_links.txt +0 -0
  203. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.egg-info/entry_points.txt +0 -0
  204. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.egg-info/requires.txt +0 -0
  205. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.egg-info/top_level.txt +0 -0
  206. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_cli.py +0 -0
  207. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_client.py +0 -0
  208. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_common/__init__.py +0 -0
  209. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_common/subprocess_utils.py +0 -0
  210. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_common/time_utils.py +0 -0
  211. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_common/usage_dir_sweeper.py +0 -0
  212. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_common/usage_lang.py +0 -0
  213. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_common/usage_logging.py +0 -0
  214. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_diagnosis_snapshot.py +0 -0
  215. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_notifications.py +0 -0
  216. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_statusline_agy.py +0 -0
  217. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_statusline_forwarder.py +0 -0
  218. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_statusline_grok.py +0 -0
  219. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_terse_mode.py +0 -0
  220. {usage_cli-0.31.3 → usage_cli-0.31.5}/usage_terse_reminder.py +0 -0
  221. {usage_cli-0.31.3 → usage_cli-0.31.5}/wintray/__init__.py +0 -0
  222. {usage_cli-0.31.3 → usage_cli-0.31.5}/wintray/app.py +0 -0
  223. {usage_cli-0.31.3 → usage_cli-0.31.5}/wintray/login_item.py +0 -0
  224. {usage_cli-0.31.3 → usage_cli-0.31.5}/wintray/menu.py +0 -0
  225. {usage_cli-0.31.3 → usage_cli-0.31.5}/wintray/watch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usage-cli
3
- Version: 0.31.3
3
+ Version: 0.31.5
4
4
  Summary: usage — 在 macOS menu bar 與 Windows 系統匣顯示 Claude Code、Codex、Antigravity 用量的小工具(也提供終端機 TUI)
5
5
  License-Expression: AGPL-3.0-only
6
6
  Requires-Python: >=3.13
@@ -24,9 +24,9 @@ Dynamic: license-file
24
24
 
25
25
  # usage
26
26
 
27
- ### Quota visibility for Claude Code, Codex, Antigravity, and Grok CLI, built into the macOS menu bar and Windows system tray.
27
+ ### Your Claude Code, Codex, Antigravity and Grok CLI quota, always on screen.
28
28
 
29
- Running out of quota mid-session is expensive — especially during a long refactor or debugging run that depends on Claude Code. `usage` surfaces 5-hour and weekly limits *before* you hit the wall, and keeps them visible the whole time. There's no command to run and no page to open; the answer is just there, where you already look.
29
+ `usage` puts your 5-hour and weekly limits in the macOS menu bar or Windows system tray, colored from green to red. Hitting the limit halfway through a long refactor is a bad way to find out you were running low. Now you see it coming. There's nothing to run and no page to open.
30
30
 
31
31
  [繁體中文](docs/README.zh-TW.md) · [简体中文](docs/README.zh-CN.md) · English · [日本語](docs/README.ja.md) · [한국어](docs/README.ko.md)  |  [Discussions](https://github.com/aqua5230/usage/discussions)  |  [Landing page](https://aqua5230.github.io/usage/)
32
32
 
@@ -43,7 +43,9 @@ Running out of quota mid-session is expensive — especially during a long refac
43
43
  <img src="docs/showcase-v3.en.png" alt="usage — Claude Code, Codex, and Antigravity quota pinned to the macOS menu bar" width="820">
44
44
  </p>
45
45
 
46
- Claude Code and Codex numbers are read passively from log files already on your machine, so **watching your quota never calls Anthropic or OpenAI's LLM APIs** and never costs you a token. Antigravity is the one exception: its quota comes from Google's official quota endpoint using the sign-in the Antigravity CLI already stores locally — a metadata call that doesn't consume your model quota either.
46
+ Claude Code and Codex numbers come from log files already on your machine. Antigravity quota comes from Google's official quota endpoint, using the sign-in the Antigravity CLI already stores locally.
47
+
48
+ `usage` also helps you spend less. The status line warns you before your context window bloats or your prompt cache goes cold, and a Token Saver toggle keeps replies short. In an A/B test on real sessions, late replies stayed ~40% shorter instead of growing 84% longer.
47
49
 
48
50
  ## Quick Start
49
51
 
@@ -51,10 +53,10 @@ Claude Code and Codex numbers are read passively from log files already on your
51
53
  brew install --cask aqua5230/usage/usage
52
54
  ```
53
55
 
54
- **Not on macOS?** `uvx usage-cli` runs the terminal interface anywhere, Linux included — no install, no menu bar.
55
-
56
56
  It lands in your Applications folder automatically. Open it once; if macOS 15 or later blocks it, go to System Settings → Privacy & Security, scroll down, and click **Open Anyway**. On macOS 14 or earlier, right-click **Open** once to pass Gatekeeper. Then click the menu bar icon. Prefer a direct download or want the full setup flow? See [Install](#install) below.
57
57
 
58
+ **Not on macOS?** `uvx usage-cli` runs the terminal interface anywhere, Linux included — no install, no menu bar.
59
+
58
60
  **Jump to:** [What You Get](#what-you-get) · [Privacy](#privacy--data-sources) · [Requirements](#requirements) · [Install](#install) · [Status Line](#first-launch-set-up-the-status-line) · [Windows](#windows-support) · [Themes](#theme-gallery) · [Troubleshooting](#troubleshooting) · [Comparison](#comparison) · [Not a Fit?](#when-usage-isnt-the-right-fit) · [Development](#development)
59
61
 
60
62
  ## What You Get
@@ -63,21 +65,22 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
63
65
 
64
66
  - **Always-on Monitor:** Your quota lives in the menu bar, color-coded from green to red. Click when you want the full session, weekly, and per-project breakdown.
65
67
  - **Antigravity Support:** Antigravity (Gemini) session and weekly quota show up as a third card in every theme except World Cup 2026, which stays a two-team HUD. Numbers come straight from the official quota API, using the sign-in the Antigravity CLI already keeps on your machine — refreshed every few minutes, with live reset countdowns. Antigravity keeps two separate quota pools: the card shows Gemini by default, and tapping the `Gemini ⇄` tag next to the title switches it to Claude / GPT — the choice is remembered.
66
- - **Grok CLI Support:** A fourth card reads Grok CLI's weekly credit percentage straight from its own local debug log — no network call. Grok CLI doesn't expose session or burn-rate data, so the card shows a single weekly bar; its per-request token usage still counts toward today's cost and project totals like Claude Code and Codex.
68
+ - **Grok CLI Support:** A fourth card reads Grok CLI's weekly credit percentage straight from its own local debug log. Grok CLI doesn't expose session or burn-rate data, so the card shows a single weekly bar; its per-request token usage still counts toward today's cost and project totals like Claude Code and Codex.
67
69
  - **Muse Code Spending:** Muse Code's per-request tokens and cost count toward today's cost, project totals, the HTML report, and the `usage` CLI, read from its own local session logs. Muse keeps no local quota data, so there is no Muse quota card.
68
- - **Service Status Alerts:** An orange-red banner appears when Claude Code, Claude API, or Codex API has an outage or degraded performance, read from their public Statuspage.io pages — never an LLM usage API. Antigravity isn't covered; it has no public status page.
70
+ - **Service Status Alerts:** An orange-red banner appears when Claude Code, Claude API, or Codex API has an outage or degraded performance, read from their public Statuspage.io pages. Antigravity isn't covered; it has no public status page.
69
71
  - **Context Nudges & Notifications:** When your context window hits 70% — or earlier when it is filling fast — the status line nudges you to `/clear` or `/compact` to prevent token waste. You can also opt-in to system notifications for quota limits and recoveries.
70
- - **Prompt Cache Health:** The status line shows Claude Code's prompt cache hit rate with a countdown to expiry, so you can tell at a glance whether finishing now still reuses the cached context or lets it go cold and re-sends everything. Needs Claude Code 2.1.251 or newer; on older versions the segment simply doesn't appear.
72
+ - **Prompt Cache Health:** The status line shows Claude Code's prompt cache hit rate with a countdown to expiry, so you can tell at a glance whether finishing now still reuses the cached context or lets it go cold and re-sends everything. Once it has gone cold, the countdown turns into how many tokens your next message will re-cache. Needs Claude Code 2.1.251 or newer; on older versions the segment simply doesn't appear.
71
73
  - **Hide Sections:** Only use one or two of the tools? Hide the Claude Code, Codex, Grok CLI, or Antigravity section from the menu bar and panels completely with a single click.
72
74
 
73
75
  ### Workflow Helpers
74
76
 
75
- - **Progress Concierge:** Open a new Claude Code session and `usage` hands your last progress straight to the AI, including your last request, uncommitted changes, and unfinished todos. No `/resume`, no recap. Fully local, off by default.
77
+ - **Progress Concierge:** Open a new Claude Code session and `usage` hands your last progress straight to the AI, including your last request, uncommitted changes, and unfinished todos. No `/resume`, no recap. When you do `/resume` a conversation that sat long enough for its cache to expire, it warns you how many tokens the next message will re-send and suggests `/compact` first. Off by default.
76
78
  - **Token Saver:** A menu-bar toggle asks Claude Code and Codex to answer more tersely and in plainer language, saving output tokens while keeping code and error messages byte-exact. A light reminder keeps long conversations from drifting back to verbose — in an A/B test on real sessions, late replies stayed ~40% shorter instead of drifting 84% longer.
77
- - **Terminal Integration:** `usage status --json` hands your Claude Code and Codex quota to any tool that can run a command — Starship, tmux, or your own scripts. Reads the same local files as the menu bar, no network call. [Ready-made snippets](docs/DEVELOPMENT.md#quota-status-for-other-tools-usage-status).
79
+ - **Auto-start 5-hour Session:** Off by default. Turn it on and, right after a 5-hour quota resets, `usage` sends one tiny message to each tool (Claude with Haiku, Antigravity with Gemini 3.5 Flash Low, Codex with its cheapest model) so the next 5-hour window starts counting right away. Those messages do use a little quota, but the amount is negligible. Checking your quota never sends a message; only this switch does.
80
+ - **Terminal Integration:** `usage status --json` hands your Claude Code and Codex quota to any tool that can run a command — Starship, tmux, or your own scripts. Reads the same local files as the menu bar. [Ready-made snippets](docs/DEVELOPMENT.md#quota-status-for-other-tools-usage-status).
78
81
  - **Token-waste Health Check:** A daily background diagnosis scans your logs for waste, including repeated file reads, polluter directories, and noisy Bash output. If it finds issues, a one-line heads-up appears; say "show me" and the AI walks you through fixes.
79
82
 
80
- ### AI Teamwork
83
+ ### Stay Current
81
84
 
82
85
  - **AI Update Daily:** Opens a daily-updated public [page](https://aqua5230.github.io/ai-updates/) covering Claude Code, Codex, and Antigravity, with the full history kept. Reviewed items get a plain-language summary in all five UI languages; unreviewed ones show the original source text.
83
86
 
@@ -88,20 +91,20 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
88
91
  ### Experience & Customization
89
92
 
90
93
  - **16 Visual Themes:** Switch between panel styles including Default, Matrix, Windows 95, Vintage Newspaper, Cloud Observation, Midnight Aquarium, Prism Arcade, Black Hole, World Cup 2026, Lepidoptera, Migration, Stained Glass, Origami, Sketchbook, Heart Monitor, and Catppuccin (official palette, all four flavors).
91
- - **Place the Panel Anywhere:** The panel is no longer pinned under the menu bar icon. Drag it from any empty spot to wherever you want it, and it reopens there next time. It stays put when another app takes focus — a second click on the menu bar icon, or Escape, closes it.
94
+ - **Place the Panel Anywhere:** Drag the panel from any empty spot to wherever you want it, and it reopens there next time. It stays put when another app takes focus — a second click on the menu bar icon, or Escape, closes it.
92
95
  - **Drag to Reorder:** Grab any quota card and drag it up or down to swap the order — the arrangement is shared across every theme with quota cards (all except World Cup 2026) and survives restarts.
93
96
  - **Automatic Localization:** UI text is available in Traditional Chinese, Simplified Chinese, English, Japanese, and Korean, automatically matching your system settings.
94
97
 
95
98
  ## Privacy & Data Sources
96
99
 
97
- - Claude Code and Codex numbers are read **only from local log files** on your machine; reading them **never calls Anthropic or OpenAI's LLM APIs**.
98
- - Antigravity quota requires network access, and only if you use it: quota is fetched from Google's official quota endpoint using the OAuth credential the Antigravity CLI already stored after sign-in — read from macOS Keychain, Windows Credential Manager, or a local token file depending on CLI version. `usage` reads that credential without writing it back and keeps any refreshed access token in memory only; the call itself only reads quota metadata and never consumes your model quota.
100
+ - Claude Code and Codex numbers are read from local log files on your machine.
101
+ - Antigravity quota requires network access, and only if you use it: quota is fetched from Google's official quota endpoint using the OAuth credential the Antigravity CLI already stored after sign-in — read from macOS Keychain, Windows Credential Manager, or a local token file depending on CLI version. `usage` reads that credential without writing it back and keeps any refreshed access token in memory only; the call itself reads quota metadata.
99
102
  - Background network activity: the Antigravity quota/token endpoints above, public Claude and Codex status pages to flag outages, a public model-pricing table to estimate cost (falls back to built-in prices offline), and occasionally checking GitHub for a new version. Claude Code and Codex log contents are never uploaded.
100
103
 
101
104
  ## Requirements
102
105
 
103
106
  - macOS 12 (Monterey) or newer, or Windows 10/11
104
- - Claude Code, Codex, or Antigravity has been used at least once (so local usage data exists).
107
+ - Claude Code, Codex, Antigravity, or Grok CLI has been used at least once (so local usage data exists).
105
108
  - (Source runs only) Python 3.13.
106
109
 
107
110
  ## Install
@@ -167,21 +170,22 @@ Privacy policy: this program will not transfer any information to other networke
167
170
  Switch between **16 visual themes** directly from the UI:
168
171
 
169
172
  <p align="center">
170
- <img src="docs/classic.en.png" width="32%" alt="Classic theme" />
171
- <img src="docs/matrix.en.png" width="32%" alt="Matrix theme" />
172
- <img src="docs/win95.en.png" width="32%" alt="Windows 95 theme" />
173
- <img src="docs/newspaper.en.png" width="32%" alt="Newspaper theme" />
174
- <img src="docs/cloud_observation.en.png" width="32%" alt="Cloud Observation theme" />
175
- <img src="docs/aquarium.en.png" width="32%" alt="Midnight Aquarium theme" />
176
- <img src="docs/prism_arcade.en.png" width="32%" alt="Prism Arcade theme" />
177
- <img src="docs/stained_glass.en.png" width="32%" alt="Stained Glass theme" />
178
- <img src="docs/origami.en.png" width="32%" alt="Origami theme" />
179
- <img src="docs/black_hole.en.png" width="32%" alt="Black Hole theme" />
180
- <img src="docs/lepidoptera.en.png" width="32%" alt="Lepidoptera theme" />
181
- <img src="docs/migration.en.png" width="32%" alt="Migration theme" />
182
- <img src="docs/catppuccin.en.png" width="32%" alt="Catppuccin theme" />
183
- <img src="docs/sketchbook.en.png" width="32%" alt="Sketchbook theme" />
184
- <img src="docs/heart_monitor.en.png" width="32%" alt="Heart Monitor theme" />
173
+ <img src="docs/classic.en.png" width="24%" alt="Classic theme" />
174
+ <img src="docs/matrix.en.png" width="24%" alt="Matrix theme" />
175
+ <img src="docs/win95.en.png" width="24%" alt="Windows 95 theme" />
176
+ <img src="docs/newspaper.en.png" width="24%" alt="Newspaper theme" />
177
+ <img src="docs/cloud_observation.en.png" width="24%" alt="Cloud Observation theme" />
178
+ <img src="docs/aquarium.en.png" width="24%" alt="Midnight Aquarium theme" />
179
+ <img src="docs/prism_arcade.en.png" width="24%" alt="Prism Arcade theme" />
180
+ <img src="docs/stained_glass.en.png" width="24%" alt="Stained Glass theme" />
181
+ <img src="docs/origami.en.png" width="24%" alt="Origami theme" />
182
+ <img src="docs/black_hole.en.png" width="24%" alt="Black Hole theme" />
183
+ <img src="docs/world_cup.en.png" width="24%" alt="World Cup 2026 theme" />
184
+ <img src="docs/lepidoptera.en.png" width="24%" alt="Lepidoptera theme" />
185
+ <img src="docs/migration.en.png" width="24%" alt="Migration theme" />
186
+ <img src="docs/catppuccin.en.png" width="24%" alt="Catppuccin theme" />
187
+ <img src="docs/sketchbook.en.png" width="24%" alt="Sketchbook theme" />
188
+ <img src="docs/heart_monitor.en.png" width="24%" alt="Heart Monitor theme" />
185
189
  </p>
186
190
 
187
191
  ## Troubleshooting
@@ -215,14 +219,13 @@ If the menu bar shows `--`, it's usually not broken — there's just no local da
215
219
  | AI Update Daily | ✅ | — | — |
216
220
  | Progress Concierge & Token Saver | ✅ | — | — |
217
221
  | Token-waste Health Check | ✅ | — | — |
218
- | No LLM API calls to read quota | ✅ | ✅ | ✅ |
219
222
  | Open-source license | AGPL-3.0 | MIT | — |
220
223
 
221
224
  ## When usage Isn't the Right Fit
222
225
 
223
226
  - You only live in the terminal and don't want another menu bar icon running in the background — a one-off CLI check fits better.
224
- - You don't use Claude Code, Codex, or Antigravity — there's no local usage data for `usage` to read.
225
- - You're on Linux — only macOS and Windows are supported today.
227
+ - You don't use Claude Code, Codex, Antigravity, or Grok CLI — there's no local usage data for `usage` to read.
228
+ - You want a menu bar on Linux. Only macOS and Windows have one today, though the terminal interface (`uvx usage-cli`) runs on Linux.
226
229
 
227
230
  ## Development
228
231
 
@@ -4,9 +4,9 @@
4
4
 
5
5
  # usage
6
6
 
7
- ### Quota visibility for Claude Code, Codex, Antigravity, and Grok CLI, built into the macOS menu bar and Windows system tray.
7
+ ### Your Claude Code, Codex, Antigravity and Grok CLI quota, always on screen.
8
8
 
9
- Running out of quota mid-session is expensive — especially during a long refactor or debugging run that depends on Claude Code. `usage` surfaces 5-hour and weekly limits *before* you hit the wall, and keeps them visible the whole time. There's no command to run and no page to open; the answer is just there, where you already look.
9
+ `usage` puts your 5-hour and weekly limits in the macOS menu bar or Windows system tray, colored from green to red. Hitting the limit halfway through a long refactor is a bad way to find out you were running low. Now you see it coming. There's nothing to run and no page to open.
10
10
 
11
11
  [繁體中文](docs/README.zh-TW.md) · [简体中文](docs/README.zh-CN.md) · English · [日本語](docs/README.ja.md) · [한국어](docs/README.ko.md) &nbsp;|&nbsp; [Discussions](https://github.com/aqua5230/usage/discussions) &nbsp;|&nbsp; [Landing page](https://aqua5230.github.io/usage/)
12
12
 
@@ -23,7 +23,9 @@ Running out of quota mid-session is expensive — especially during a long refac
23
23
  <img src="docs/showcase-v3.en.png" alt="usage — Claude Code, Codex, and Antigravity quota pinned to the macOS menu bar" width="820">
24
24
  </p>
25
25
 
26
- Claude Code and Codex numbers are read passively from log files already on your machine, so **watching your quota never calls Anthropic or OpenAI's LLM APIs** and never costs you a token. Antigravity is the one exception: its quota comes from Google's official quota endpoint using the sign-in the Antigravity CLI already stores locally — a metadata call that doesn't consume your model quota either.
26
+ Claude Code and Codex numbers come from log files already on your machine. Antigravity quota comes from Google's official quota endpoint, using the sign-in the Antigravity CLI already stores locally.
27
+
28
+ `usage` also helps you spend less. The status line warns you before your context window bloats or your prompt cache goes cold, and a Token Saver toggle keeps replies short. In an A/B test on real sessions, late replies stayed ~40% shorter instead of growing 84% longer.
27
29
 
28
30
  ## Quick Start
29
31
 
@@ -31,10 +33,10 @@ Claude Code and Codex numbers are read passively from log files already on your
31
33
  brew install --cask aqua5230/usage/usage
32
34
  ```
33
35
 
34
- **Not on macOS?** `uvx usage-cli` runs the terminal interface anywhere, Linux included — no install, no menu bar.
35
-
36
36
  It lands in your Applications folder automatically. Open it once; if macOS 15 or later blocks it, go to System Settings → Privacy & Security, scroll down, and click **Open Anyway**. On macOS 14 or earlier, right-click **Open** once to pass Gatekeeper. Then click the menu bar icon. Prefer a direct download or want the full setup flow? See [Install](#install) below.
37
37
 
38
+ **Not on macOS?** `uvx usage-cli` runs the terminal interface anywhere, Linux included — no install, no menu bar.
39
+
38
40
  **Jump to:** [What You Get](#what-you-get) · [Privacy](#privacy--data-sources) · [Requirements](#requirements) · [Install](#install) · [Status Line](#first-launch-set-up-the-status-line) · [Windows](#windows-support) · [Themes](#theme-gallery) · [Troubleshooting](#troubleshooting) · [Comparison](#comparison) · [Not a Fit?](#when-usage-isnt-the-right-fit) · [Development](#development)
39
41
 
40
42
  ## What You Get
@@ -43,21 +45,22 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
43
45
 
44
46
  - **Always-on Monitor:** Your quota lives in the menu bar, color-coded from green to red. Click when you want the full session, weekly, and per-project breakdown.
45
47
  - **Antigravity Support:** Antigravity (Gemini) session and weekly quota show up as a third card in every theme except World Cup 2026, which stays a two-team HUD. Numbers come straight from the official quota API, using the sign-in the Antigravity CLI already keeps on your machine — refreshed every few minutes, with live reset countdowns. Antigravity keeps two separate quota pools: the card shows Gemini by default, and tapping the `Gemini ⇄` tag next to the title switches it to Claude / GPT — the choice is remembered.
46
- - **Grok CLI Support:** A fourth card reads Grok CLI's weekly credit percentage straight from its own local debug log — no network call. Grok CLI doesn't expose session or burn-rate data, so the card shows a single weekly bar; its per-request token usage still counts toward today's cost and project totals like Claude Code and Codex.
48
+ - **Grok CLI Support:** A fourth card reads Grok CLI's weekly credit percentage straight from its own local debug log. Grok CLI doesn't expose session or burn-rate data, so the card shows a single weekly bar; its per-request token usage still counts toward today's cost and project totals like Claude Code and Codex.
47
49
  - **Muse Code Spending:** Muse Code's per-request tokens and cost count toward today's cost, project totals, the HTML report, and the `usage` CLI, read from its own local session logs. Muse keeps no local quota data, so there is no Muse quota card.
48
- - **Service Status Alerts:** An orange-red banner appears when Claude Code, Claude API, or Codex API has an outage or degraded performance, read from their public Statuspage.io pages — never an LLM usage API. Antigravity isn't covered; it has no public status page.
50
+ - **Service Status Alerts:** An orange-red banner appears when Claude Code, Claude API, or Codex API has an outage or degraded performance, read from their public Statuspage.io pages. Antigravity isn't covered; it has no public status page.
49
51
  - **Context Nudges & Notifications:** When your context window hits 70% — or earlier when it is filling fast — the status line nudges you to `/clear` or `/compact` to prevent token waste. You can also opt-in to system notifications for quota limits and recoveries.
50
- - **Prompt Cache Health:** The status line shows Claude Code's prompt cache hit rate with a countdown to expiry, so you can tell at a glance whether finishing now still reuses the cached context or lets it go cold and re-sends everything. Needs Claude Code 2.1.251 or newer; on older versions the segment simply doesn't appear.
52
+ - **Prompt Cache Health:** The status line shows Claude Code's prompt cache hit rate with a countdown to expiry, so you can tell at a glance whether finishing now still reuses the cached context or lets it go cold and re-sends everything. Once it has gone cold, the countdown turns into how many tokens your next message will re-cache. Needs Claude Code 2.1.251 or newer; on older versions the segment simply doesn't appear.
51
53
  - **Hide Sections:** Only use one or two of the tools? Hide the Claude Code, Codex, Grok CLI, or Antigravity section from the menu bar and panels completely with a single click.
52
54
 
53
55
  ### Workflow Helpers
54
56
 
55
- - **Progress Concierge:** Open a new Claude Code session and `usage` hands your last progress straight to the AI, including your last request, uncommitted changes, and unfinished todos. No `/resume`, no recap. Fully local, off by default.
57
+ - **Progress Concierge:** Open a new Claude Code session and `usage` hands your last progress straight to the AI, including your last request, uncommitted changes, and unfinished todos. No `/resume`, no recap. When you do `/resume` a conversation that sat long enough for its cache to expire, it warns you how many tokens the next message will re-send and suggests `/compact` first. Off by default.
56
58
  - **Token Saver:** A menu-bar toggle asks Claude Code and Codex to answer more tersely and in plainer language, saving output tokens while keeping code and error messages byte-exact. A light reminder keeps long conversations from drifting back to verbose — in an A/B test on real sessions, late replies stayed ~40% shorter instead of drifting 84% longer.
57
- - **Terminal Integration:** `usage status --json` hands your Claude Code and Codex quota to any tool that can run a command — Starship, tmux, or your own scripts. Reads the same local files as the menu bar, no network call. [Ready-made snippets](docs/DEVELOPMENT.md#quota-status-for-other-tools-usage-status).
59
+ - **Auto-start 5-hour Session:** Off by default. Turn it on and, right after a 5-hour quota resets, `usage` sends one tiny message to each tool (Claude with Haiku, Antigravity with Gemini 3.5 Flash Low, Codex with its cheapest model) so the next 5-hour window starts counting right away. Those messages do use a little quota, but the amount is negligible. Checking your quota never sends a message; only this switch does.
60
+ - **Terminal Integration:** `usage status --json` hands your Claude Code and Codex quota to any tool that can run a command — Starship, tmux, or your own scripts. Reads the same local files as the menu bar. [Ready-made snippets](docs/DEVELOPMENT.md#quota-status-for-other-tools-usage-status).
58
61
  - **Token-waste Health Check:** A daily background diagnosis scans your logs for waste, including repeated file reads, polluter directories, and noisy Bash output. If it finds issues, a one-line heads-up appears; say "show me" and the AI walks you through fixes.
59
62
 
60
- ### AI Teamwork
63
+ ### Stay Current
61
64
 
62
65
  - **AI Update Daily:** Opens a daily-updated public [page](https://aqua5230.github.io/ai-updates/) covering Claude Code, Codex, and Antigravity, with the full history kept. Reviewed items get a plain-language summary in all five UI languages; unreviewed ones show the original source text.
63
66
 
@@ -68,20 +71,20 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
68
71
  ### Experience & Customization
69
72
 
70
73
  - **16 Visual Themes:** Switch between panel styles including Default, Matrix, Windows 95, Vintage Newspaper, Cloud Observation, Midnight Aquarium, Prism Arcade, Black Hole, World Cup 2026, Lepidoptera, Migration, Stained Glass, Origami, Sketchbook, Heart Monitor, and Catppuccin (official palette, all four flavors).
71
- - **Place the Panel Anywhere:** The panel is no longer pinned under the menu bar icon. Drag it from any empty spot to wherever you want it, and it reopens there next time. It stays put when another app takes focus — a second click on the menu bar icon, or Escape, closes it.
74
+ - **Place the Panel Anywhere:** Drag the panel from any empty spot to wherever you want it, and it reopens there next time. It stays put when another app takes focus — a second click on the menu bar icon, or Escape, closes it.
72
75
  - **Drag to Reorder:** Grab any quota card and drag it up or down to swap the order — the arrangement is shared across every theme with quota cards (all except World Cup 2026) and survives restarts.
73
76
  - **Automatic Localization:** UI text is available in Traditional Chinese, Simplified Chinese, English, Japanese, and Korean, automatically matching your system settings.
74
77
 
75
78
  ## Privacy & Data Sources
76
79
 
77
- - Claude Code and Codex numbers are read **only from local log files** on your machine; reading them **never calls Anthropic or OpenAI's LLM APIs**.
78
- - Antigravity quota requires network access, and only if you use it: quota is fetched from Google's official quota endpoint using the OAuth credential the Antigravity CLI already stored after sign-in — read from macOS Keychain, Windows Credential Manager, or a local token file depending on CLI version. `usage` reads that credential without writing it back and keeps any refreshed access token in memory only; the call itself only reads quota metadata and never consumes your model quota.
80
+ - Claude Code and Codex numbers are read from local log files on your machine.
81
+ - Antigravity quota requires network access, and only if you use it: quota is fetched from Google's official quota endpoint using the OAuth credential the Antigravity CLI already stored after sign-in — read from macOS Keychain, Windows Credential Manager, or a local token file depending on CLI version. `usage` reads that credential without writing it back and keeps any refreshed access token in memory only; the call itself reads quota metadata.
79
82
  - Background network activity: the Antigravity quota/token endpoints above, public Claude and Codex status pages to flag outages, a public model-pricing table to estimate cost (falls back to built-in prices offline), and occasionally checking GitHub for a new version. Claude Code and Codex log contents are never uploaded.
80
83
 
81
84
  ## Requirements
82
85
 
83
86
  - macOS 12 (Monterey) or newer, or Windows 10/11
84
- - Claude Code, Codex, or Antigravity has been used at least once (so local usage data exists).
87
+ - Claude Code, Codex, Antigravity, or Grok CLI has been used at least once (so local usage data exists).
85
88
  - (Source runs only) Python 3.13.
86
89
 
87
90
  ## Install
@@ -147,21 +150,22 @@ Privacy policy: this program will not transfer any information to other networke
147
150
  Switch between **16 visual themes** directly from the UI:
148
151
 
149
152
  <p align="center">
150
- <img src="docs/classic.en.png" width="32%" alt="Classic theme" />
151
- <img src="docs/matrix.en.png" width="32%" alt="Matrix theme" />
152
- <img src="docs/win95.en.png" width="32%" alt="Windows 95 theme" />
153
- <img src="docs/newspaper.en.png" width="32%" alt="Newspaper theme" />
154
- <img src="docs/cloud_observation.en.png" width="32%" alt="Cloud Observation theme" />
155
- <img src="docs/aquarium.en.png" width="32%" alt="Midnight Aquarium theme" />
156
- <img src="docs/prism_arcade.en.png" width="32%" alt="Prism Arcade theme" />
157
- <img src="docs/stained_glass.en.png" width="32%" alt="Stained Glass theme" />
158
- <img src="docs/origami.en.png" width="32%" alt="Origami theme" />
159
- <img src="docs/black_hole.en.png" width="32%" alt="Black Hole theme" />
160
- <img src="docs/lepidoptera.en.png" width="32%" alt="Lepidoptera theme" />
161
- <img src="docs/migration.en.png" width="32%" alt="Migration theme" />
162
- <img src="docs/catppuccin.en.png" width="32%" alt="Catppuccin theme" />
163
- <img src="docs/sketchbook.en.png" width="32%" alt="Sketchbook theme" />
164
- <img src="docs/heart_monitor.en.png" width="32%" alt="Heart Monitor theme" />
153
+ <img src="docs/classic.en.png" width="24%" alt="Classic theme" />
154
+ <img src="docs/matrix.en.png" width="24%" alt="Matrix theme" />
155
+ <img src="docs/win95.en.png" width="24%" alt="Windows 95 theme" />
156
+ <img src="docs/newspaper.en.png" width="24%" alt="Newspaper theme" />
157
+ <img src="docs/cloud_observation.en.png" width="24%" alt="Cloud Observation theme" />
158
+ <img src="docs/aquarium.en.png" width="24%" alt="Midnight Aquarium theme" />
159
+ <img src="docs/prism_arcade.en.png" width="24%" alt="Prism Arcade theme" />
160
+ <img src="docs/stained_glass.en.png" width="24%" alt="Stained Glass theme" />
161
+ <img src="docs/origami.en.png" width="24%" alt="Origami theme" />
162
+ <img src="docs/black_hole.en.png" width="24%" alt="Black Hole theme" />
163
+ <img src="docs/world_cup.en.png" width="24%" alt="World Cup 2026 theme" />
164
+ <img src="docs/lepidoptera.en.png" width="24%" alt="Lepidoptera theme" />
165
+ <img src="docs/migration.en.png" width="24%" alt="Migration theme" />
166
+ <img src="docs/catppuccin.en.png" width="24%" alt="Catppuccin theme" />
167
+ <img src="docs/sketchbook.en.png" width="24%" alt="Sketchbook theme" />
168
+ <img src="docs/heart_monitor.en.png" width="24%" alt="Heart Monitor theme" />
165
169
  </p>
166
170
 
167
171
  ## Troubleshooting
@@ -195,14 +199,13 @@ If the menu bar shows `--`, it's usually not broken — there's just no local da
195
199
  | AI Update Daily | ✅ | — | — |
196
200
  | Progress Concierge & Token Saver | ✅ | — | — |
197
201
  | Token-waste Health Check | ✅ | — | — |
198
- | No LLM API calls to read quota | ✅ | ✅ | ✅ |
199
202
  | Open-source license | AGPL-3.0 | MIT | — |
200
203
 
201
204
  ## When usage Isn't the Right Fit
202
205
 
203
206
  - You only live in the terminal and don't want another menu bar icon running in the background — a one-off CLI check fits better.
204
- - You don't use Claude Code, Codex, or Antigravity — there's no local usage data for `usage` to read.
205
- - You're on Linux — only macOS and Windows are supported today.
207
+ - You don't use Claude Code, Codex, Antigravity, or Grok CLI — there's no local usage data for `usage` to read.
208
+ - You want a menu bar on Linux. Only macOS and Windows have one today, though the terminal interface (`uvx usage-cli`) runs on Linux.
206
209
 
207
210
  ## Development
208
211
 
@@ -137,16 +137,23 @@ def parse_jsonl(
137
137
  _file_cache.move_to_end(path)
138
138
  parsed_entries = cached[2]
139
139
  else:
140
- parsed_entries = []
140
+ by_key: dict[str, UsageEntry] = {}
141
141
  try:
142
142
  for data in iter_jsonl_dicts(path):
143
143
  if data.get("type") != "assistant":
144
144
  continue
145
145
 
146
- parsed_entries.extend(_parse_assistant_entry(data, project))
146
+ for entry in _parse_assistant_entry(data, project):
147
+ kept = by_key.setdefault(entry.dedup_key, entry)
148
+ # Subagent transcripts log one request several times while it streams,
149
+ # with output_tokens still growing, so keep the largest, not the first.
150
+ # Without ids the key cannot tell requests apart, so never merge those.
151
+ if entry.message_id or entry.request_id:
152
+ kept.output_tokens = max(kept.output_tokens, entry.output_tokens)
147
153
  except (OSError, PermissionError, UnicodeDecodeError) as exc:
148
154
  _debug_file_error("failed to read Claude log", path, exc)
149
155
  return
156
+ parsed_entries = list(by_key.values())
150
157
 
151
158
  if path not in _file_cache and len(_file_cache) >= _FILE_CACHE_MAXSIZE:
152
159
  _file_cache.popitem(last=False)
@@ -43,7 +43,7 @@ _YEAR_WEEKS = 53
43
43
  YEAR_CACHE_PATH = Path(os.path.expanduser("~/.usage/year_cache.json"))
44
44
  YEAR_LEDGER_PATH = YEAR_CACHE_PATH.with_name("year_ledger.json")
45
45
  YEAR_CACHE_TTL_SECONDS = 6 * 3600
46
- _YEAR_CACHE_SCHEMA = 4
46
+ _YEAR_CACHE_SCHEMA = 5
47
47
  _YEAR_LEDGER_SCHEMA = 1
48
48
  _YEAR_LEDGER_TRIM_BUFFER_DAYS = 60
49
49
 
@@ -104,7 +104,7 @@
104
104
  "grok_stale_tooltip": "資料來自 Grok CLI 本機 log,不是即時 API;請最近執行過 grok 指令後再查看,才會更新。",
105
105
  "codex_stale_minutes": "約 {minutes} 分鐘前",
106
106
  "codex_stale_hours": "約 {hours} 小時前",
107
- "codex_stale_tooltip": "Claude 有即時回報所以很準;Codex 沒有,usage 只能讀它本機偶爾留下的紀錄,可能比實際略舊。我們刻意不連網去補(連網會多燒你的 token)——繼續在終端機跑 Codex 就會自動更新。",
107
+ "codex_stale_tooltip": "Claude 有即時回報所以很準;Codex 沒有,usage 會讀它本機偶爾留下的紀錄,可能比實際略舊。繼續在終端機跑 Codex 就會自動更新。",
108
108
  "history_load_error_file": "讀不到使用紀錄檔",
109
109
  "history_load_error_parse": "使用紀錄格式異常",
110
110
  "history_load_error_unknown": "使用紀錄暫時無法讀取",
@@ -322,6 +322,7 @@
322
322
  "report_rw_inject_lead": "(這是進度交接。請在這次對話第一則回覆的最前面,先說一行「🐾 已接回上次進度,繼續吧!」,然後別照唸下面的線索,而是像聰明又貼心的搭檔那樣消化它:先判斷使用者最後真正在忙的是什麼(「最近在忙的」是新到舊排列,以最前面那筆為準,別被較舊的帶偏),用一兩句溫暖具體地說他上次做到哪、完成了什麼,再直接給出你判斷最該接著做的下一步——要具體,別反問「要做什麼」。只能根據下面線索講,沒有的別編;若線索太少看不出方向,就坦白說、並列出你看到的幾條線讓他挑。接著正常回應。)\n\n",
323
323
  "report_rw_empty": "(請在你這次對話的第一則回覆最前面,說一行「🐾 歡迎回來,這個專案目前沒有要接的進度。」,再正常回應。)",
324
324
  "report_rw_prompt": "專案:{project}(最後活動 {when})\n最近在忙的(新→舊):{last_request}\n完成的進度:{commits}\n未完成待辦:{todos}",
325
+ "report_rw_resume_cost": "這個對話放了 {idle},快取已過期,下一句會重送約 {tokens} token。想省額度可以先打 /compact 壓縮再聊。",
325
326
  "report_rw_uncommitted": "上次離開時還留著:{branch} 分支有 {count} 個檔案改了還沒提交({files})",
326
327
  "report_rw_diagnosis_reminder": "健檢提醒:最近約 {waste_pct}% 浪費在{cause}。跟我說「修」,完整診斷在 {path}。",
327
328
  "report_rw_diagnosis_reminder_explain": "健檢提醒:最近約 {waste_pct}% 浪費在{cause}。跟我說「看」,我會讀 {path} 的完整診斷,解釋給你聽並給具體建議。",
@@ -531,7 +532,7 @@
531
532
  "grok_stale_tooltip": "Data comes from Grok CLI's local log, not a live API. Run a grok command recently for it to update.",
532
533
  "codex_stale_minutes": "about {minutes} minutes ago",
533
534
  "codex_stale_hours": "about {hours} hours ago",
534
- "codex_stale_tooltip": "Claude is accurate because it reports in real time; Codex does not, so usage can only read the local records it leaves occasionally, which may be slightly older than reality. We intentionally do not go online to fill the gap (that would burn more of your tokens) — keep running Codex in the terminal and it will update automatically.",
535
+ "codex_stale_tooltip": "Claude is accurate because it reports in real time; Codex does not, so usage reads the local records it leaves occasionally, which may be slightly older than reality. Keep running Codex in the terminal and it will update automatically.",
535
536
  "history_load_error_file": "Couldn't read usage files",
536
537
  "history_load_error_parse": "Usage data format issue",
537
538
  "history_load_error_unknown": "Usage data temporarily unavailable",
@@ -749,6 +750,7 @@
749
750
  "report_rw_inject_lead": "(This is a resume handoff. At the very start of your first reply, lead with one line: \"🐾 Picked up where you left off — let's keep going!\", then, instead of reading the traces below aloud, digest them like a sharp, thoughtful partner: first work out what the user was actually in the middle of (\"Recently working on\" is newest-first, so trust the topmost item and don't get pulled back to older ones); in a sentence or two, warmly and concretely recap where they left off and what got done; then give the single concrete next step you would take — be specific, don't ask \"what should I do\". Use only what is below; invent nothing. If the traces are too thin to tell, say so plainly and list the threads you can see for them to pick. Then respond normally.)\n\n",
750
751
  "report_rw_empty": "(At the very start of your first reply in this session, say one line: \"🐾 Welcome back — nothing to pick up on this project yet.\", then respond normally.)",
751
752
  "report_rw_prompt": "Project: {project} (last active {when})\nRecently working on (newest first): {last_request}\nProgress made: {commits}\nOpen to-dos: {todos}",
753
+ "report_rw_resume_cost": "This conversation sat idle for {idle} and its prompt cache has expired, so your next message re-sends about {tokens} tokens. Run /compact first to use less quota.",
752
754
  "report_rw_uncommitted": "Left uncommitted last time: {count} changed file(s) on branch {branch} ({files})",
753
755
  "report_rw_diagnosis_reminder": "Health check: about {waste_pct}% waste came from {cause}. Say \"fix it\" and I'll read the full diagnosis at {path}.",
754
756
  "report_rw_diagnosis_reminder_explain": "Health check: about {waste_pct}% waste came from {cause}. Say \"show me\" and I'll walk you through the full diagnosis at {path}.",
@@ -958,7 +960,7 @@
958
960
  "grok_stale_tooltip": "资料来自 Grok CLI 本地日志,不是即时 API;请最近运行过 grok 指令后再查看,才会更新。",
959
961
  "codex_stale_minutes": "约 {minutes} 分钟前",
960
962
  "codex_stale_hours": "约 {hours} 小时前",
961
- "codex_stale_tooltip": "Claude 有实时回报所以很准;Codex 没有,usage 只能读取它本机偶尔留下的记录,可能比实际略旧。我们刻意不联网去补(联网会多消耗你的 token)——继续在终端运行 Codex 就会自动更新。",
963
+ "codex_stale_tooltip": "Claude 有实时回报所以很准;Codex 没有,usage 会读取它本机偶尔留下的记录,可能比实际略旧。继续在终端运行 Codex 就会自动更新。",
962
964
  "history_load_error_file": "读不到使用记录文件",
963
965
  "history_load_error_parse": "使用记录格式异常",
964
966
  "history_load_error_unknown": "使用记录暂时无法读取",
@@ -1176,6 +1178,7 @@
1176
1178
  "report_rw_inject_lead": "(这是进度交接。请在这次对话第一则回复的最前面,先说一行「🐾 已接回上次进度,继续吧!」,然后别照念下面的线索,而是像聪明又贴心的搭档那样消化它:先判断用户最后真正在忙的是什么(「最近在忙的」是新到旧排列,以最前面那笔为准,别被较旧的带偏),用一两句温暖具体地说他上次做到哪、完成了什么,再直接给出你判断最该接着做的下一步——要具体,别反问「要做什么」。只能根据下面线索讲,没有的别编;若线索太少看不出方向,就坦白说、并列出你看到的几条线让他挑。接着正常回应。)\n\n",
1177
1179
  "report_rw_empty": "(请在你这次对话的第一则回复最前面,说一行「🐾 欢迎回来,这个项目目前没有要接的进度。」,再正常回应。)",
1178
1180
  "report_rw_prompt": "项目:{project}(最后活动 {when})\n最近在忙的(新→旧):{last_request}\n完成的进度:{commits}\n未完成待办:{todos}",
1181
+ "report_rw_resume_cost": "这个对话放了 {idle},缓存已过期,下一句会重新发送约 {tokens} token。想省额度可以先输入 /compact 压缩再聊。",
1179
1182
  "report_rw_uncommitted": "上次离开时还留着:{branch} 分支有 {count} 个文件改了还没提交({files})",
1180
1183
  "report_rw_diagnosis_reminder": "健检提醒:最近约有 {waste_pct}% 的浪费来自{cause}。跟我说「修」,完整诊断在 {path}。",
1181
1184
  "report_rw_diagnosis_reminder_explain": "健检提醒:最近约有 {waste_pct}% 的浪费来自{cause}。跟我说「看」,我会读 {path} 的完整诊断,解释给你听并给具体建议。",
@@ -1385,7 +1388,7 @@
1385
1388
  "grok_stale_tooltip": "データは Grok CLI のローカルログから読み取るもので、リアルタイム API ではありません。更新するには最近 grok コマンドを実行してください。",
1386
1389
  "codex_stale_minutes": "約 {minutes} 分前",
1387
1390
  "codex_stale_hours": "約 {hours} 時間前",
1388
- "codex_stale_tooltip": "Claude はリアルタイムに報告するので正確です。Codex にはそれがないため、usage は Codex がローカルに時々残す記録だけを読み取り、実際より少し古い場合があります。補うために意図的にネット接続はしません(接続するとあなたの token を余分に消費します)——ターミナルで Codex を使い続けると自動的に更新されます。",
1391
+ "codex_stale_tooltip": "Claude はリアルタイムに報告するので正確です。Codex にはそれがないため、usage は Codex がローカルに時々残す記録を読み取り、実際より少し古い場合があります。ターミナルで Codex を使い続けると自動的に更新されます。",
1389
1392
  "history_load_error_file": "使用履歴ファイルを読み込めません",
1390
1393
  "history_load_error_parse": "使用履歴データの形式に問題があります",
1391
1394
  "history_load_error_unknown": "使用履歴データを一時的に取得できません",
@@ -1603,6 +1606,7 @@
1603
1606
  "report_rw_inject_lead": "(これは進捗の引き継ぎです。最初の返信の冒頭で、まず一行「🐾 前回の続きを引き継ぎました!そのまま続けましょう!」と述べ、下記の手がかりをそのまま読み上げるのではなく、賢く気の利いた相棒のように消化してください:まずユーザーが最後に実際に取り組んでいたことを見極め(「最近の作業」は新しい順なので、先頭の項目を信頼し、古いものに引きずられないこと)、前回どこまで進んだか・何が完了したかを一、二文で温かく具体的に振り返り、次に取るべき具体的な一歩を提示してください——具体的に述べ、「何をしますか」と聞き返さないこと。下記にある情報だけを使い、無いことは創作しないこと。手がかりが乏しくて判断できない場合は正直にそう述べ、見えるスレッドを挙げて選んでもらうこと。その後、通常どおり応答してください。)\n\n",
1604
1607
  "report_rw_empty": "(このセッションの最初の返信の冒頭に、一行「🐾 おかえりなさい!このプロジェクトはまだ引き継ぐ進捗がありません。」と述べてから、通常どおり応答してください。)",
1605
1608
  "report_rw_prompt": "プロジェクト:{project}(最終アクティブ {when})\n最近の作業(新しい順):{last_request}\n完了した進捗:{commits}\n未完了のToDo:{todos}",
1609
+ "report_rw_resume_cost": "この会話は {idle} 放置され、プロンプトキャッシュが切れています。次のメッセージで約 {tokens} トークンを再送信します。クォータを節約するには、先に /compact で圧縮してください。",
1606
1610
  "report_rw_uncommitted": "前回の終了時に未コミット:{branch} ブランチに変更済み未コミットのファイルが {count} 件({files})",
1607
1611
  "report_rw_diagnosis_reminder": "健診メモ: 直近では約 {waste_pct}% の無駄が{cause}から出ています。「直して」と言ってもらえれば、{path} の完全な診断を読んで対応します。",
1608
1612
  "report_rw_diagnosis_reminder_explain": "健診メモ: 直近では約 {waste_pct}% の無駄が{cause}から出ています。「見せて」と言ってもらえれば、{path} の完全な診断を読み解いて説明と対策をお伝えします。",
@@ -1812,7 +1816,7 @@
1812
1816
  "grok_stale_tooltip": "데이터는 Grok CLI의 로컬 로그에서 읽으며 실시간 API가 아닙니다. 업데이트하려면 최근에 grok 명령을 실행하세요.",
1813
1817
  "codex_stale_minutes": "약 {minutes}분 전",
1814
1818
  "codex_stale_hours": "약 {hours}시간 전",
1815
- "codex_stale_tooltip": "Claude는 실시간으로 보고하므로 정확합니다. Codex는 그렇지 않아 usage가 Codex가 로컬에 가끔 남기는 기록만 읽을 수 있고, 실제보다 조금 오래된 값일 수 있습니다. 우리는 이를 보완하려고 일부러 온라인 연결을 하지 않습니다(연결하면 token을 더 소비하게 됩니다)——터미널에서 Codex를 계속 실행하면 자동으로 업데이트됩니다.",
1819
+ "codex_stale_tooltip": "Claude는 실시간으로 보고하므로 정확합니다. Codex는 그렇지 않아 usage가 Codex가 로컬에 가끔 남기는 기록을 읽으며, 실제보다 조금 오래된 값일 수 있습니다. 터미널에서 Codex를 계속 실행하면 자동으로 업데이트됩니다.",
1816
1820
  "history_load_error_file": "사용 기록 파일을 읽을 수 없습니다",
1817
1821
  "history_load_error_parse": "사용 기록 형식에 문제가 있습니다",
1818
1822
  "history_load_error_unknown": "사용 기록을 일시적으로 불러올 수 없습니다",
@@ -2030,6 +2034,7 @@
2030
2034
  "report_rw_inject_lead": "(이것은 진행 상황 인수인계입니다. 첫 답변 맨 앞에 먼저 한 줄 \"🐾 지난 작업을 불러왔어요! 이어서 가볼까요?\"라고 말한 뒤, 아래 단서를 그대로 읽지 말고 똑똑하고 사려 깊은 동료처럼 소화하세요: 먼저 사용자가 마지막에 실제로 무엇을 하고 있었는지 파악하고(\"최근 작업한 내용\"은 최신순이므로 맨 위 항목을 신뢰하고 오래된 것에 끌려가지 마세요), 지난번에 어디까지 했고 무엇을 완료했는지 한두 문장으로 따뜻하고 구체적으로 짚어 준 뒤, 이어서 취해야 할 구체적인 다음 단계 하나를 제시하세요 — 구체적으로 말하고 \"무엇을 할까요\"라고 되묻지 마세요. 아래 있는 내용만 사용하고 없는 것은 지어내지 마세요. 단서가 너무 적어 판단하기 어려우면 솔직히 그렇게 말하고 보이는 갈래들을 나열해 고르게 하세요. 그런 다음 평소대로 응답하세요.)\n\n",
2031
2035
  "report_rw_empty": "(이 세션의 첫 답변 맨 앞에 한 줄 \"🐾 돌아오셨네요! 이 프로젝트는 아직 이어갈 내용이 없어요.\"라고 말한 뒤 평소대로 응답하세요.)",
2032
2036
  "report_rw_prompt": "프로젝트: {project} (마지막 활동 {when})\n최근 작업한 내용 (최신순): {last_request}\n완료한 진행: {commits}\n미완료 할 일: {todos}",
2037
+ "report_rw_resume_cost": "이 대화는 {idle} 동안 방치되어 프롬프트 캐시가 만료되었습니다. 다음 메시지에서 약 {tokens} 토큰을 다시 보냅니다. 할당량을 아끼려면 먼저 /compact로 압축하세요.",
2033
2038
  "report_rw_uncommitted": "지난번 종료 시 미커밋 파일: {branch} 브랜치에 {count}개 파일이 커밋되지 않은 채 남아 있었습니다 ({files})",
2034
2039
  "report_rw_diagnosis_reminder": "진단 알림: 최근 낭비 약 {waste_pct}%의 주된 원인은 {cause}입니다. \"고쳐줘\"라고 말하면 {path}의 전체 진단을 읽고 바로 처리할게요.",
2035
2040
  "report_rw_diagnosis_reminder_explain": "진단 알림: 최근 낭비 약 {waste_pct}%의 주된 원인은 {cause}입니다. \"보여줘\"라고 말하면 {path}의 전체 진단을 읽고 자세히 설명해 드릴게요.",
@@ -59,8 +59,8 @@ CODEX_CONFIG = setup_hook.CODEX_CONFIG
59
59
  # session. Off by default: enabled only via the menu toggle, never by self_heal.
60
60
  RESUME_HOOK_TARGET = Path(os.path.expanduser("~/.claude/usage-session-resume.py"))
61
61
  RESUME_PROMPT_SIDECAR = Path(os.path.expanduser("~/.claude/usage-resume-prompt.json"))
62
- RESUME_HOOK_VERSION = "1.9"
63
- RESUME_MATCHER = "startup|clear"
62
+ RESUME_HOOK_VERSION = "1.10"
63
+ RESUME_MATCHER = "startup|clear|resume"
64
64
  RESUME_LANGS = ("zh-TW", "zh-CN", "en", "ja", "ko")
65
65
  _RESUME_MARKER = "usage-session-resume"
66
66
  _RESUME_MARKERS = (_RESUME_MARKER, "usage_session_resume")
@@ -299,6 +299,7 @@ def _write_resume_sidecar() -> None:
299
299
  lead = table.get("report_rw_inject_lead") or en.get("report_rw_inject_lead") or ""
300
300
  empty = table.get("report_rw_empty") or en.get("report_rw_empty") or ""
301
301
  uncommitted = table.get("report_rw_uncommitted") or en.get("report_rw_uncommitted") or ""
302
+ resume_cost = table.get("report_rw_resume_cost") or en.get("report_rw_resume_cost") or ""
302
303
  diagnosis_reminder = (
303
304
  table.get("report_rw_diagnosis_reminder")
304
305
  or en.get("report_rw_diagnosis_reminder")
@@ -329,6 +330,7 @@ def _write_resume_sidecar() -> None:
329
330
  "lead": lead,
330
331
  "empty": empty,
331
332
  "uncommitted": uncommitted,
333
+ "resume_cost": resume_cost,
332
334
  "diagnosis_reminder": diagnosis_reminder,
333
335
  "diagnosis_reminder_explain": diagnosis_reminder_explain,
334
336
  "diagnosis_default_cause": diagnosis_default_cause,
@@ -837,6 +839,7 @@ def _self_heal_resume() -> None:
837
839
  script/sidecar and update a stale script. Never enables it on its own."""
838
840
  if not is_resume_enabled():
839
841
  return
842
+ _migrate_resume_matcher_if_needed()
840
843
  _migrate_resume_command_if_needed()
841
844
  missing = _missing_resume_artifacts()
842
845
  if missing:
@@ -919,6 +922,41 @@ def _self_heal_terse_reminder() -> None:
919
922
  )
920
923
 
921
924
 
925
+ def _migrate_resume_matcher_if_needed() -> None:
926
+ settings = _load_settings()
927
+ entries = _session_start_list(settings)
928
+ if not entries:
929
+ return
930
+ changed = False
931
+ updated: list[Any] = []
932
+ for entry in entries:
933
+ if not isinstance(entry, dict) or not _is_resume_entry(entry):
934
+ updated.append(entry)
935
+ continue
936
+ if entry.get("matcher") == RESUME_MATCHER:
937
+ updated.append(entry)
938
+ continue
939
+ hooks = entry.get("hooks")
940
+ if not isinstance(hooks, list):
941
+ updated.append(entry)
942
+ continue
943
+ ours = [
944
+ hook
945
+ for hook in hooks
946
+ if isinstance(hook, dict)
947
+ and isinstance(hook.get("command"), str)
948
+ and _command_owns_script(hook["command"], _RESUME_MARKERS)
949
+ ]
950
+ others = [hook for hook in hooks if hook not in ours]
951
+ if others:
952
+ updated.append({**entry, "hooks": others})
953
+ updated.append({**entry, "matcher": RESUME_MATCHER, "hooks": ours})
954
+ changed = True
955
+ if changed:
956
+ settings["hooks"]["SessionStart"] = updated
957
+ _save_settings(settings)
958
+
959
+
922
960
  def _migrate_resume_command_if_needed() -> None:
923
961
  settings = _load_settings()
924
962
  entries = _session_start_list(settings)
@@ -86,7 +86,7 @@ PREV_SL_KEY = "previousStatusLine"
86
86
  # Where the status-line switch parks the live statusLine while it is off, so it
87
87
  # never overwrites the pre-install backup under PREV_SL_KEY.
88
88
  DISABLED_SL_KEY = "disabledStatusLine"
89
- HOOK_VERSION = "1.6"
89
+ HOOK_VERSION = "1.8"
90
90
  FORWARDER_VERSION = "1.1"
91
91
  # Antigravity's Go runner hands its status-line command to cmd.exe unquoted, so
92
92
  # every character cmd.exe treats specially has to be kept out of the path.
@@ -15,7 +15,7 @@ import sys
15
15
  import time
16
16
  from collections import OrderedDict
17
17
  from collections.abc import Iterable
18
- from dataclasses import dataclass
18
+ from dataclasses import dataclass, replace
19
19
  from datetime import UTC, datetime, timedelta
20
20
  from pathlib import Path
21
21
  from typing import Any
@@ -55,7 +55,7 @@ class _FileCacheEntry:
55
55
  _file_cache: OrderedDict[Path, _FileCacheEntry] = OrderedDict()
56
56
 
57
57
  HISTORY_CACHE_PATH = Path(os.path.expanduser("~/.usage/history_jsonl_cache.json"))
58
- _HISTORY_JSONL_CACHE_SCHEMA = 4
58
+ _HISTORY_JSONL_CACHE_SCHEMA = 5
59
59
  _disk_cache_seeded = False
60
60
  _DISK_CACHE_FLUSH_INTERVAL_S = 300.0
61
61
  _disk_cache_dirty = False
@@ -319,7 +319,7 @@ def _parse_complete_lines(
319
319
  digest: Any,
320
320
  confirmed_offset: int,
321
321
  ) -> int:
322
- seen = {_dedup_key(entry) for entry in parsed_entries}
322
+ index = {_dedup_key(entry): i for i, entry in enumerate(parsed_entries)}
323
323
  while True:
324
324
  line_start = int(file.tell())
325
325
  line, too_long = read_bounded_jsonl_line(file)
@@ -337,9 +337,15 @@ def _parse_complete_lines(
337
337
  if parsed_entries_for_line is not None:
338
338
  for entry in parsed_entries_for_line:
339
339
  dedup_key = _dedup_key(entry)
340
- if dedup_key in seen:
340
+ kept_at = index.get(dedup_key)
341
+ if kept_at is not None:
342
+ # Subagent transcripts log one request several times while it streams,
343
+ # with output_tokens still growing, so keep the largest, not the first.
344
+ kept = parsed_entries[kept_at]
345
+ if entry.output_tokens > kept.output_tokens:
346
+ parsed_entries[kept_at] = replace(kept, output_tokens=entry.output_tokens)
341
347
  continue
342
- seen.add(dedup_key)
348
+ index[dedup_key] = len(parsed_entries)
343
349
  parsed_entries.append(entry)
344
350
 
345
351
 
@@ -960,7 +960,7 @@ class AppDelegate(NSObject):
960
960
  reset=row.reset_text,
961
961
  )
962
962
  )
963
- content.setSound_(sound_cls.defaultSound())
963
+ content.setSound_(menubar_notify.notification_sound(sound_cls, event.kind))
964
964
  request = request_cls.requestWithIdentifier_content_trigger_(
965
965
  f"usage.{event.channel}.{event.kind}.{int(time.time() * 1000)}",
966
966
  content,