usage-cli 0.33.1__tar.gz → 0.33.2__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 (269) hide show
  1. {usage_cli-0.33.1 → usage_cli-0.33.2}/PKG-INFO +10 -7
  2. {usage_cli-0.33.1 → usage_cli-0.33.2}/README.md +9 -6
  3. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/agy.py +1 -1
  4. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/claude.py +1 -1
  5. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/grok.py +1 -1
  6. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/muse.py +1 -1
  7. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/rate_limits.py +1 -1
  8. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/aggregator.py +1 -1
  9. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/blocks.py +1 -1
  10. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/persona_loader.py +1 -1
  11. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/reporter.py +1 -1
  12. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/usage_snapshot.py +1 -1
  13. {usage_cli-0.33.1 → usage_cli-0.33.2}/i18n.json +0 -25
  14. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/claude_pane.py +7 -6
  15. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/session_hooks.py +10 -10
  16. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/setup_hook.py +8 -12
  17. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/agy_loader.py +1 -1
  18. usage_cli-0.33.1/usage_client.py → usage_cli-0.33.2/loaders/claude_usage.py +1 -1
  19. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/codex_loader.py +1 -1
  20. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/grok_loader.py +1 -1
  21. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/history_loader.py +1 -1
  22. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/muse_loader.py +1 -1
  23. {usage_cli-0.33.1 → usage_cli-0.33.2}/main.py +6 -112
  24. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/actions.py +1 -1
  25. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/agy.py +1 -1
  26. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/app.py +7 -23
  27. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/grok.py +1 -1
  28. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/manual_refresh.py +1 -1
  29. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/menu.py +1 -1
  30. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/new_badge.py +3 -3
  31. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/notify.py +1 -1
  32. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/prefs.py +1 -1
  33. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/refresh.py +2 -2
  34. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/state.py +4 -4
  35. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/update.py +5 -8
  36. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/whats_new.py +1 -1
  37. usage_cli-0.33.2/panels/__init__.py +50 -0
  38. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/base.py +2 -2
  39. usage_cli-0.33.2/panels/catalog.py +225 -0
  40. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/payload.py +2 -23
  41. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/web_panel.py +1 -1
  42. {usage_cli-0.33.1 → usage_cli-0.33.2}/pyproject.toml +13 -32
  43. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/agy_window_keeper.py +0 -5
  44. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/codex_window_keeper.py +1 -1
  45. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/keeper_outcome.py +1 -1
  46. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/quota_snapshot.py +1 -1
  47. usage_cli-0.33.2/quota/status_payload.py +161 -0
  48. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/window_keeper.py +1 -1
  49. {usage_cli-0.33.1 → usage_cli-0.33.2}/setup_app.py +9 -13
  50. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_adapters_claude.py +2 -2
  51. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_agy_adapter.py +1 -1
  52. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_agy_window_keeper.py +2 -1
  53. usage_cli-0.33.2/tests/test_app_version.py +28 -0
  54. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_check_upstream.py +23 -0
  55. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_claude_pane.py +21 -9
  56. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_claude_paths.py +1 -1
  57. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_desktop_quota_display.py +10 -8
  58. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_desktop_quota_review.py +6 -6
  59. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_doctor.py +5 -5
  60. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_fsevents_watch.py +1 -1
  61. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_history_loader.py +2 -2
  62. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_hook_scripts_are_standalone.py +1 -2
  63. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_i18n_format_fallback.py +1 -1
  64. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_i18n_packaged_path.py +1 -1
  65. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_main.py +2 -2
  66. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_manual_refresh.py +1 -1
  67. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar.py +9 -9
  68. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar_agy.py +1 -1
  69. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar_grok.py +1 -1
  70. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar_prefs.py +1 -1
  71. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar_state.py +2 -2
  72. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar_update.py +3 -7
  73. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_muse_loader.py +2 -2
  74. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_new_badge.py +1 -1
  75. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_packaging.py +1 -1
  76. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_panels.py +1 -1
  77. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_persona_loader.py +1 -1
  78. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_pricing.py +14 -14
  79. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_project_resolver.py +58 -17
  80. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_quota_aware.py +4 -4
  81. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_quota_label.py +2 -3
  82. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_reporter_build_data.py +1 -1
  83. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_service_status.py +1 -1
  84. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_session_resume.py +1 -1
  85. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_setup_hook.py +10 -10
  86. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_setup_hook_coexistence.py +2 -94
  87. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_setup_hook_resume.py +1 -1
  88. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_setup_hook_terse.py +6 -6
  89. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_tui.py +6 -5
  90. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_update_checker.py +8 -6
  91. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_cli.py +31 -31
  92. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_client.py +17 -17
  93. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_diagnosis_snapshot.py +1 -1
  94. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_notifications.py +1 -1
  95. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_statusline.py +1 -1
  96. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_statusline_agy.py +3 -3
  97. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_statusline_forwarder.py +1 -1
  98. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_statusline_grok.py +2 -2
  99. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_terse_mode.py +1 -1
  100. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_terse_reminder.py +1 -1
  101. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_web_panel_payload.py +1 -1
  102. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_wheel_packaging.py +1 -1
  103. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_wintray.py +65 -30
  104. {usage_cli-0.33.1 → usage_cli-0.33.2}/tui/app.py +2 -17
  105. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/html_report.py +1 -20
  106. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/report_ledger.py +1 -1
  107. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/tables.py +1 -1
  108. {usage_cli-0.33.1 → usage_cli-0.33.2}/updates/checker.py +0 -4
  109. {usage_cli-0.33.1 → usage_cli-0.33.2}/updates/whats_new.py +1 -1
  110. usage_cli-0.33.1/usage_cli.py → usage_cli-0.33.2/usage_app/cli.py +3 -150
  111. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_app}/doctor.py +2 -18
  112. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_cli.egg-info/PKG-INFO +10 -7
  113. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_cli.egg-info/SOURCES.txt +25 -19
  114. usage_cli-0.33.2/usage_cli.egg-info/entry_points.txt +3 -0
  115. usage_cli-0.33.2/usage_cli.egg-info/top_level.txt +16 -0
  116. usage_cli-0.33.2/usage_common/app_version.py +24 -0
  117. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_common}/i18n.py +8 -6
  118. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_common}/pricing.py +0 -5
  119. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_common}/project_resolver.py +49 -32
  120. usage_cli-0.33.2/usage_hooks/__init__.py +0 -0
  121. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_quota_aware.py +8 -4
  122. usage_cli-0.33.2/wintray/__init__.py +0 -0
  123. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/app.py +24 -83
  124. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/prefs.py +1 -1
  125. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/quota_label.py +1 -1
  126. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/watch.py +0 -3
  127. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/whats_new.py +1 -1
  128. usage_cli-0.33.1/panels/__init__.py +0 -231
  129. usage_cli-0.33.1/usage_cli.egg-info/entry_points.txt +0 -3
  130. usage_cli-0.33.1/usage_cli.egg-info/top_level.txt +0 -33
  131. {usage_cli-0.33.1 → usage_cli-0.33.2}/LICENSE +0 -0
  132. {usage_cli-0.33.1 → usage_cli-0.33.2}/THIRD_PARTY_NOTICES.md +0 -0
  133. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/__init__.py +0 -0
  134. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/codex.py +0 -0
  135. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/registry.py +0 -0
  136. {usage_cli-0.33.1 → usage_cli-0.33.2}/adapters/types.py +0 -0
  137. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/__init__.py +0 -0
  138. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/diagnoser.py +0 -0
  139. /usage_cli-0.33.1/usage_diagnosis_snapshot.py → /usage_cli-0.33.2/analyzer/diagnosis_snapshot.py +0 -0
  140. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/dispatch_ledger.py +0 -0
  141. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/insights.py +0 -0
  142. {usage_cli-0.33.1 → usage_cli-0.33.2}/analyzer/subscription.py +0 -0
  143. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/__init__.py +0 -0
  144. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/codex_hook_trust.py +0 -0
  145. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/login_item.py +0 -0
  146. {usage_cli-0.33.1 → usage_cli-0.33.2}/installer/statusline_settings.py +0 -0
  147. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/__init__.py +0 -0
  148. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/_shared_cache_file.py +0 -0
  149. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/agy_disk_cache.py +0 -0
  150. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/agy_quota_probe.py +0 -0
  151. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/cache_quarantine.py +0 -0
  152. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/chromium_cache.py +0 -0
  153. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/claude_desktop.py +0 -0
  154. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/claude_paths.py +0 -0
  155. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/codex_disk_cache.py +0 -0
  156. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/codex_events.py +0 -0
  157. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/codex_fork_replay.py +0 -0
  158. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/codex_paths.py +0 -0
  159. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/disk_cache_common.py +0 -0
  160. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/disk_cache_lifecycle.py +0 -0
  161. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/grok_quota_probe.py +0 -0
  162. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/history_disk_cache.py +0 -0
  163. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/jsonl_limits.py +0 -0
  164. {usage_cli-0.33.1 → usage_cli-0.33.2}/loaders/jsonl_utils.py +0 -0
  165. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/__init__.py +0 -0
  166. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/chrome.py +0 -0
  167. {usage_cli-0.33.1 → usage_cli-0.33.2/menubar}/fsevents_watch.py +0 -0
  168. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/popover.py +0 -0
  169. {usage_cli-0.33.1 → usage_cli-0.33.2}/menubar/title.py +0 -0
  170. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/dynamic_height.py +0 -0
  171. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/panel_scale.py +0 -0
  172. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/panel_window.py +0 -0
  173. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/panel_window_state.py +0 -0
  174. {usage_cli-0.33.1 → usage_cli-0.33.2}/panels/window_drag.py +0 -0
  175. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/__init__.py +0 -0
  176. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/burn_rate.py +0 -0
  177. /usage_cli-0.33.1/usage_notifications.py → /usage_cli-0.33.2/quota/notifications.py +0 -0
  178. {usage_cli-0.33.1 → usage_cli-0.33.2}/quota/usage_rate.py +0 -0
  179. {usage_cli-0.33.1 → usage_cli-0.33.2}/setup.cfg +0 -0
  180. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_adapters_codex.py +0 -0
  181. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_adapters_rate_limits.py +0 -0
  182. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_aggregator.py +0 -0
  183. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_agy_disk_cache.py +0 -0
  184. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_agy_loader.py +0 -0
  185. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_agy_quota_probe.py +0 -0
  186. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_analyzer_blocks.py +0 -0
  187. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_analyzer_pipeline.py +0 -0
  188. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_burn_rate.py +0 -0
  189. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_cache_quarantine.py +0 -0
  190. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_chromium_cache.py +0 -0
  191. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_claude_desktop.py +0 -0
  192. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_codex_consistency.py +0 -0
  193. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_codex_hook_trust.py +0 -0
  194. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_codex_loader.py +0 -0
  195. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_codex_window_keeper.py +0 -0
  196. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_diagnoser.py +0 -0
  197. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_disk_cache_shards.py +0 -0
  198. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_dispatch_ledger.py +0 -0
  199. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_dynamic_height.py +0 -0
  200. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_grok_loader.py +0 -0
  201. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_grok_quota_probe.py +0 -0
  202. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_html_report_snapshot.py +0 -0
  203. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_i18n_key_parity.py +0 -0
  204. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_insights.py +0 -0
  205. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_jsonl_utils.py +0 -0
  206. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_keeper_menu.py +0 -0
  207. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_keeper_outcome.py +0 -0
  208. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_login_item.py +0 -0
  209. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_menubar_notify.py +0 -0
  210. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_packaged_resources.py +0 -0
  211. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_panel_footer_layout.py +0 -0
  212. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_panel_scale.py +0 -0
  213. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_panel_window_state.py +0 -0
  214. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_panels_lazy_import.py +0 -0
  215. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_report_daily_chart.py +0 -0
  216. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_report_filter_js.py +0 -0
  217. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_setup_app.py +0 -0
  218. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_subprocess_utils.py +0 -0
  219. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_subscription.py +0 -0
  220. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_taskbar_menu.py +0 -0
  221. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_time_utils.py +0 -0
  222. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_tui_sprite.py +0 -0
  223. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_ui_tables.py +0 -0
  224. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_update_gate.py +0 -0
  225. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_update_release_notes.py +0 -0
  226. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_dir_sweeper.py +0 -0
  227. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_lang.py +0 -0
  228. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_logging.py +0 -0
  229. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_rate.py +0 -0
  230. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_snapshot.py +0 -0
  231. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_usage_snapshot_replay.py +0 -0
  232. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_whats_new.py +0 -0
  233. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_win_login_item.py +0 -0
  234. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_window_keeper.py +0 -0
  235. {usage_cli-0.33.1 → usage_cli-0.33.2}/tests/test_windows_manifest.py +0 -0
  236. {usage_cli-0.33.1 → usage_cli-0.33.2}/tui/__init__.py +0 -0
  237. {usage_cli-0.33.1 → usage_cli-0.33.2}/tui/sprite.py +0 -0
  238. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/__init__.py +0 -0
  239. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/report_charts.py +0 -0
  240. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/report_daily_chart.py +0 -0
  241. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/report_filter.py +0 -0
  242. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/report_scripts.py +0 -0
  243. {usage_cli-0.33.1 → usage_cli-0.33.2}/ui/report_styles.py +0 -0
  244. {usage_cli-0.33.1 → usage_cli-0.33.2}/updates/__init__.py +0 -0
  245. {usage_cli-0.33.1 → usage_cli-0.33.2}/updates/gate.py +0 -0
  246. {usage_cli-0.33.1 → usage_cli-0.33.2}/updates/release_notes.py +0 -0
  247. {usage_cli-0.33.1/usage_common → usage_cli-0.33.2/usage_app}/__init__.py +0 -0
  248. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_cli.egg-info/dependency_links.txt +0 -0
  249. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_cli.egg-info/requires.txt +0 -0
  250. {usage_cli-0.33.1/wintray → usage_cli-0.33.2/usage_common}/__init__.py +0 -0
  251. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_common}/prefs.py +0 -0
  252. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_common}/service_status.py +0 -0
  253. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_common/subprocess_utils.py +0 -0
  254. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_common/time_utils.py +0 -0
  255. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_common/usage_dir_sweeper.py +0 -0
  256. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_common/usage_lang.py +0 -0
  257. {usage_cli-0.33.1 → usage_cli-0.33.2}/usage_common/usage_logging.py +0 -0
  258. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_session_resume.py +0 -0
  259. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_statusline.py +0 -0
  260. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_statusline_agy.py +0 -0
  261. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_statusline_forwarder.py +0 -0
  262. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_statusline_grok.py +0 -0
  263. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_terse_mode.py +0 -0
  264. {usage_cli-0.33.1 → usage_cli-0.33.2/usage_hooks}/usage_terse_reminder.py +0 -0
  265. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/login_item.py +0 -0
  266. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/menu.py +0 -0
  267. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/taskbar_menu.py +0 -0
  268. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/taskbar_obstacles.py +0 -0
  269. {usage_cli-0.33.1 → usage_cli-0.33.2}/wintray/taskbar_overlay.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: usage-cli
3
- Version: 0.33.1
3
+ Version: 0.33.2
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
@@ -70,7 +70,7 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
70
70
  - **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.
71
71
  - **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.
72
72
  - **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.
73
- - **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.
73
+ - **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. The context figure turns yellow at 50% or 200K tokens and red at 80% or 400K tokens, whichever comes first. When it changes color, the status line shows the image count and the estimated share of files and command output.
74
74
  - **Prompt Cache Health:** The status line shows Claude Code's prompt cache hit rate. For 10 minutes after the cache misses, it also says why — the model changed, the tools changed, you sat idle past the 5-minute TTL, and so on — so you can tell whether the extra tokens came from something you did. The hit rate needs Claude Code 2.1.251 or newer and the reason needs 2.1.260 or newer; on older versions those parts simply don't appear.
75
75
  - **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.
76
76
 
@@ -79,15 +79,16 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
79
79
  - **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.
80
80
  - **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.
81
81
  - **Claude Code side pane (macOS and Windows):** Quotas, conversations, and background jobs inside Claude Code. [See the side pane](#claude-code-side-pane).
82
- - **Beginner Mode (macOS):** Off by default. After Claude Code answers, up to three technical terms from that answer appear above the prompt, each with a one-line plain explanation in your UI language. Press 9 to mark them understood; terms you skip come back after 1, 3, then 7 days. Understood terms return as a one-question multiple-choice quiz 7, 21, then 60 days later, at most one a day; a wrong answer puts the term back in the hints. `/terms` opens your term history. Picking terms asks Claude Haiku through your Claude Code, so it uses a little Claude quota, and it pauses while your 5-hour quota is at 90% or more.
83
- - **Quota-Aware Mode (macOS):** Off by default. When a 5-hour quota passes 80%, 90%, or 95%, or a weekly quota passes 95%, Claude Code gets one line with what is left and when it resets. Before a big task, Claude then tells you and lets you pick a smaller part or wait for the reset. It covers Claude Code, Codex, and Antigravity quota, says each level once per conversation, and makes no extra model calls.
84
- - **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.
82
+ - **Beginner Mode (macOS and Windows):** Off by default. After Claude Code answers, up to three technical terms from that answer appear above the prompt, each with a one-line plain explanation in your UI language. Press 9 to mark them understood; terms you skip come back after 1, 3, then 7 days. Understood terms return as a one-question multiple-choice quiz 7, 21, then 60 days later, at most one a day; a wrong answer puts the term back in the hints. `/terms` opens your term history. Picking terms asks Claude Haiku through your Claude Code, so it uses a little Claude quota, and it pauses while your 5-hour quota is at 90% or more.
83
+ - **Quota-Aware Mode (macOS and Windows):** Off by default. When a 5-hour quota passes 80%, 90%, or 95%, or a weekly quota passes 95%, Claude Code gets one line with what is left and when it resets. Before a big task, Claude then tells you and lets you pick a smaller part or wait for the reset. It covers Claude Code, Codex, and Antigravity quota, says each level once per conversation, and makes no extra model calls.
84
+ - **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.8 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.
85
85
  - **Terminal Integration:** `usage status --json` hands your Claude Code, Codex, Antigravity, and Grok 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).
86
86
  - **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.
87
87
 
88
88
  ### Stay Current
89
89
 
90
90
  - **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.
91
+ - **Release Notes After an Update:** The first launch after an update shows what changed in that version in your UI language, once. Fresh installs skip it.
91
92
 
92
93
  ### Reporting & Insight
93
94
 
@@ -164,11 +165,13 @@ See your quota, other conversations, and background jobs without leaving Claude
164
165
 
165
166
  - **Quotas:** Your 5-hour and weekly limits.
166
167
  - **Claude conversations:** Conversations waiting for your permission or MCP input are marked in yellow.
168
+ - **Conversation notifications:** A notification appears when another Claude conversation finishes or starts waiting for you.
169
+ - **Latest reply:** Each conversation row shows the latest assistant reply on its second line.
167
170
  - **Background jobs:** Includes subagents started by Claude with the Agent tool and their status.
168
171
 
169
172
  **How to enable**
170
173
 
171
- 1. In the usage menu bar menu (macOS) or the system-tray panel menu (Windows), check **Claude Code side pane**. On macOS it sits under the **Claude Code** submenu as **Side pane**.
174
+ 1. In the usage menu bar menu (macOS) or system-tray menu (Windows), open the **Claude Code** submenu and check **Side pane**.
172
175
  2. Open a new conversation or run `/reload-plugins`.
173
176
  3. At terminal widths ≥144 columns, the pane opens on the right automatically. In narrower terminals, enter `/usage-dash`.
174
177
 
@@ -188,7 +191,7 @@ Windows has the full core experience: the system-tray UI, Claude Code status-lin
188
191
 
189
192
  The system-tray icon shows the remaining session quota percentage for Claude or Codex. Choose **Tray Display Source → Claude Code / Codex** in the right-click menu or panel menu; the change applies immediately and survives restarts (default: Claude). If Codex has no session window, the icon uses its weekly quota instead and the tooltip identifies that window. Missing quota data shows `--`. The tooltip summarizes both tools, with the selected source first. Left-click opens the same 16 quota themes available on macOS (Default plus the other fifteen) in WebView2. Right-click also provides Reset Panel Position and Quit; panel switching, refresh, launch at login, and update checks are in the panel menu.
190
193
 
191
- Enable **Show Taskbar Quota** in either menu for a transparent `Codex: 92%` label inside the taskbar, immediately left of the notification area. It follows taskbar position, scaling, and light/dark theme, and hides during fullscreen use or taskbar auto-hide. Click the label to open the panel. If buttons leave insufficient space, it moves just outside the taskbar. The normal app icon remains as a menu entry point; the label follows the selected source and quota window.
194
+ Enable **Show Taskbar Quota** in either menu for a transparent `Codex: 92%` label inside the taskbar, immediately left of the notification area. It follows taskbar position, scaling, and light/dark theme, and hides during fullscreen use or taskbar auto-hide. Click the label to open the panel. If buttons leave insufficient space, it moves just outside the taskbar. The normal app icon remains as a menu entry point; the label follows the selected source and quota window. Right-click the label to open the same menu as the tray icon.
192
195
 
193
196
  Windows differences: the panel opens at the bottom-right of the working area rather than next to the tray icon; update prompts use a system Yes/No dialog.
194
197
 
@@ -48,7 +48,7 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
48
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.
49
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.
50
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.
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.
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. The context figure turns yellow at 50% or 200K tokens and red at 80% or 400K tokens, whichever comes first. When it changes color, the status line shows the image count and the estimated share of files and command output.
52
52
  - **Prompt Cache Health:** The status line shows Claude Code's prompt cache hit rate. For 10 minutes after the cache misses, it also says why — the model changed, the tools changed, you sat idle past the 5-minute TTL, and so on — so you can tell whether the extra tokens came from something you did. The hit rate needs Claude Code 2.1.251 or newer and the reason needs 2.1.260 or newer; on older versions those parts simply don't appear.
53
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.
54
54
 
@@ -57,15 +57,16 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
57
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.
58
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.
59
59
  - **Claude Code side pane (macOS and Windows):** Quotas, conversations, and background jobs inside Claude Code. [See the side pane](#claude-code-side-pane).
60
- - **Beginner Mode (macOS):** Off by default. After Claude Code answers, up to three technical terms from that answer appear above the prompt, each with a one-line plain explanation in your UI language. Press 9 to mark them understood; terms you skip come back after 1, 3, then 7 days. Understood terms return as a one-question multiple-choice quiz 7, 21, then 60 days later, at most one a day; a wrong answer puts the term back in the hints. `/terms` opens your term history. Picking terms asks Claude Haiku through your Claude Code, so it uses a little Claude quota, and it pauses while your 5-hour quota is at 90% or more.
61
- - **Quota-Aware Mode (macOS):** Off by default. When a 5-hour quota passes 80%, 90%, or 95%, or a weekly quota passes 95%, Claude Code gets one line with what is left and when it resets. Before a big task, Claude then tells you and lets you pick a smaller part or wait for the reset. It covers Claude Code, Codex, and Antigravity quota, says each level once per conversation, and makes no extra model calls.
62
- - **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
+ - **Beginner Mode (macOS and Windows):** Off by default. After Claude Code answers, up to three technical terms from that answer appear above the prompt, each with a one-line plain explanation in your UI language. Press 9 to mark them understood; terms you skip come back after 1, 3, then 7 days. Understood terms return as a one-question multiple-choice quiz 7, 21, then 60 days later, at most one a day; a wrong answer puts the term back in the hints. `/terms` opens your term history. Picking terms asks Claude Haiku through your Claude Code, so it uses a little Claude quota, and it pauses while your 5-hour quota is at 90% or more.
61
+ - **Quota-Aware Mode (macOS and Windows):** Off by default. When a 5-hour quota passes 80%, 90%, or 95%, or a weekly quota passes 95%, Claude Code gets one line with what is left and when it resets. Before a big task, Claude then tells you and lets you pick a smaller part or wait for the reset. It covers Claude Code, Codex, and Antigravity quota, says each level once per conversation, and makes no extra model calls.
62
+ - **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.8 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.
63
63
  - **Terminal Integration:** `usage status --json` hands your Claude Code, Codex, Antigravity, and Grok 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).
64
64
  - **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.
65
65
 
66
66
  ### Stay Current
67
67
 
68
68
  - **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.
69
+ - **Release Notes After an Update:** The first launch after an update shows what changed in that version in your UI language, once. Fresh installs skip it.
69
70
 
70
71
  ### Reporting & Insight
71
72
 
@@ -142,11 +143,13 @@ See your quota, other conversations, and background jobs without leaving Claude
142
143
 
143
144
  - **Quotas:** Your 5-hour and weekly limits.
144
145
  - **Claude conversations:** Conversations waiting for your permission or MCP input are marked in yellow.
146
+ - **Conversation notifications:** A notification appears when another Claude conversation finishes or starts waiting for you.
147
+ - **Latest reply:** Each conversation row shows the latest assistant reply on its second line.
145
148
  - **Background jobs:** Includes subagents started by Claude with the Agent tool and their status.
146
149
 
147
150
  **How to enable**
148
151
 
149
- 1. In the usage menu bar menu (macOS) or the system-tray panel menu (Windows), check **Claude Code side pane**. On macOS it sits under the **Claude Code** submenu as **Side pane**.
152
+ 1. In the usage menu bar menu (macOS) or system-tray menu (Windows), open the **Claude Code** submenu and check **Side pane**.
150
153
  2. Open a new conversation or run `/reload-plugins`.
151
154
  3. At terminal widths ≥144 columns, the pane opens on the right automatically. In narrower terminals, enter `/usage-dash`.
152
155
 
@@ -166,7 +169,7 @@ Windows has the full core experience: the system-tray UI, Claude Code status-lin
166
169
 
167
170
  The system-tray icon shows the remaining session quota percentage for Claude or Codex. Choose **Tray Display Source → Claude Code / Codex** in the right-click menu or panel menu; the change applies immediately and survives restarts (default: Claude). If Codex has no session window, the icon uses its weekly quota instead and the tooltip identifies that window. Missing quota data shows `--`. The tooltip summarizes both tools, with the selected source first. Left-click opens the same 16 quota themes available on macOS (Default plus the other fifteen) in WebView2. Right-click also provides Reset Panel Position and Quit; panel switching, refresh, launch at login, and update checks are in the panel menu.
168
171
 
169
- Enable **Show Taskbar Quota** in either menu for a transparent `Codex: 92%` label inside the taskbar, immediately left of the notification area. It follows taskbar position, scaling, and light/dark theme, and hides during fullscreen use or taskbar auto-hide. Click the label to open the panel. If buttons leave insufficient space, it moves just outside the taskbar. The normal app icon remains as a menu entry point; the label follows the selected source and quota window.
172
+ Enable **Show Taskbar Quota** in either menu for a transparent `Codex: 92%` label inside the taskbar, immediately left of the notification area. It follows taskbar position, scaling, and light/dark theme, and hides during fullscreen use or taskbar auto-hide. Click the label to open the panel. If buttons leave insufficient space, it moves just outside the taskbar. The normal app icon remains as a menu entry point; the label follows the selected source and quota window. Right-click the label to open the same menu as the tray icon.
170
173
 
171
174
  Windows differences: the panel opens at the bottom-right of the working area rather than next to the tray icon; update prompts use a system Yes/No dialog.
172
175
 
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  from loaders import agy_loader as shared_agy_loader
10
10
 
11
- from i18n import t
11
+ from usage_common.i18n import t
12
12
 
13
13
  from .types import AgentInfo, UsageEntry
14
14
 
@@ -15,7 +15,7 @@ from typing import Any
15
15
 
16
16
  from loaders.claude_paths import claude_config_dirs
17
17
  from loaders.jsonl_utils import iter_jsonl_dicts
18
- from project_resolver import resolve_project_name
18
+ from usage_common.project_resolver import resolve_project_name
19
19
 
20
20
  from .types import AgentInfo
21
21
 
@@ -9,7 +9,7 @@ from __future__ import annotations
9
9
  from loaders import grok_loader as shared_grok_loader
10
10
  from loaders.history_loader import UsageEntry as GrokUsageEntry
11
11
 
12
- from i18n import t
12
+ from usage_common.i18n import t
13
13
 
14
14
  from .types import AgentInfo, UsageEntry
15
15
 
@@ -6,7 +6,7 @@ from __future__ import annotations
6
6
  from loaders import muse_loader
7
7
  from loaders.history_loader import UsageEntry as MuseUsageEntry
8
8
 
9
- from i18n import t
9
+ from usage_common.i18n import t
10
10
 
11
11
  from .types import AgentInfo, UsageEntry
12
12
 
@@ -10,7 +10,7 @@ import os
10
10
  from datetime import datetime, timezone
11
11
  from typing import Any
12
12
 
13
- import usage_client
13
+ from loaders import claude_usage as usage_client
14
14
 
15
15
  from .types import RateLimits
16
16
 
@@ -7,7 +7,7 @@
7
7
  from collections import defaultdict
8
8
 
9
9
  from adapters.types import DailyStats, MonthlyStats, SessionStats, UsageEntry, WeeklyStats
10
- from pricing import calculate_cost
10
+ from usage_common.pricing import calculate_cost
11
11
 
12
12
 
13
13
  def aggregate_daily(entries: list[UsageEntry]) -> list[DailyStats]:
@@ -8,7 +8,7 @@ from collections.abc import Sequence
8
8
  from datetime import datetime, timedelta, timezone
9
9
 
10
10
  from adapters.types import DailyStats, P90Limits, SessionBlock, UsageEntry
11
- from pricing import calculate_cost
11
+ from usage_common.pricing import calculate_cost
12
12
 
13
13
  BLOCK_DURATION = timedelta(hours=5)
14
14
 
@@ -17,7 +17,7 @@ from typing import Any
17
17
 
18
18
  from loaders.claude_paths import claude_config_dirs
19
19
  from loaders.jsonl_utils import iter_jsonl_dicts
20
- from project_resolver import project_from_encoded_path, resolve_project_name
20
+ from usage_common.project_resolver import project_from_encoded_path, resolve_project_name
21
21
  from usage_common.time_utils import parse_optional_iso8601_utc
22
22
 
23
23
  logger = logging.getLogger(__name__)
@@ -24,7 +24,7 @@ from analyzer import persona_loader
24
24
  from analyzer import subscription
25
25
  from adapters import agy, claude, codex, grok, muse
26
26
  from adapters.types import AgentInfo, UsageEntry
27
- from pricing import calculate_cost, is_model_priced
27
+ from usage_common.pricing import calculate_cost, is_model_priced
28
28
 
29
29
  from .aggregator import aggregate_sessions
30
30
  from . import diagnoser, dispatch_ledger, usage_snapshot
@@ -27,7 +27,7 @@ from typing import NotRequired, TypeGuard, TypedDict
27
27
 
28
28
  from adapters.types import UsageEntry
29
29
  from loaders import cache_quarantine
30
- from pricing import calculate_cost
30
+ from usage_common.pricing import calculate_cost
31
31
 
32
32
  logger = logging.getLogger(__name__)
33
33
 
@@ -52,11 +52,6 @@
52
52
  "hook_installed_restart": "已安裝完成,請重開 Claude Code 一次",
53
53
  "hook_install_failed": "安裝 hook 失敗",
54
54
  "hook_install_failed_default": "setup_hook.setup() 回傳失敗",
55
- "repair_dialog_title": "狀態列設定衝突",
56
- "repair_dialog_message": "偵測到其他工具佔用了 Claude Code 狀態列。\n要切換成共存模式嗎?usage app 與其他工具可以同時運作。",
57
- "repair_dialog_repair": "立即修復",
58
- "repair_dialog_skip": "稍後再說",
59
- "repair_dialog_never": "不要再問",
60
55
  "alert_forwarder_title": "啟用共存模式?",
61
56
  "alert_forwarder_body": "偵測到其他 Claude Code 狀態列工具。啟用共存模式後,usage 會透過轉發器與現有工具一起運作。",
62
57
  "alert_forwarder_enable": "啟用共存模式",
@@ -599,11 +594,6 @@
599
594
  "hook_installed_restart": "Hook installed. Restart Claude Code once.",
600
595
  "hook_install_failed": "Hook installation failed",
601
596
  "hook_install_failed_default": "setup_hook.setup() returned failure",
602
- "repair_dialog_title": "Status Line Conflict",
603
- "repair_dialog_message": "Another tool is using the Claude Code status line.\nSwitch to coexistence mode? usage app can run alongside other tools.",
604
- "repair_dialog_repair": "Repair Now",
605
- "repair_dialog_skip": "Later",
606
- "repair_dialog_never": "Do Not Ask Again",
607
597
  "alert_forwarder_title": "Enable coexistence mode?",
608
598
  "alert_forwarder_body": "Another Claude Code status line tool was detected. In coexistence mode, usage runs through a forwarder alongside your existing tool.",
609
599
  "alert_forwarder_enable": "Enable Coexistence Mode",
@@ -1146,11 +1136,6 @@
1146
1136
  "hook_installed_restart": "已安装完成,请重开 Claude Code 一次",
1147
1137
  "hook_install_failed": "安装 hook 失败",
1148
1138
  "hook_install_failed_default": "setup_hook.setup() 返回失败",
1149
- "repair_dialog_title": "状态栏设置冲突",
1150
- "repair_dialog_message": "检测到其他工具占用了 Claude Code 状态栏。\n要切换成共存模式吗?usage app 可以和其他工具同时运行。",
1151
- "repair_dialog_repair": "立即修复",
1152
- "repair_dialog_skip": "稍后再说",
1153
- "repair_dialog_never": "不要再问",
1154
1139
  "alert_forwarder_title": "启用共存模式?",
1155
1140
  "alert_forwarder_body": "检测到其他 Claude Code 状态栏工具。启用共存模式后,usage 会通过转发器和现有工具一起运行。",
1156
1141
  "alert_forwarder_enable": "启用共存模式",
@@ -1693,11 +1678,6 @@
1693
1678
  "hook_installed_restart": "フックをインストールしました。Claude Code を一度再起動してください。",
1694
1679
  "hook_install_failed": "フックのインストールに失敗しました",
1695
1680
  "hook_install_failed_default": "setup_hook.setup() が失敗を返しました",
1696
- "repair_dialog_title": "ステータスライン設定の競合",
1697
- "repair_dialog_message": "別のツールが Claude Code のステータスラインを使用しています。\n共存モードに切り替えますか?usage app と他のツールを同時に動かせます。",
1698
- "repair_dialog_repair": "今すぐ修復",
1699
- "repair_dialog_skip": "あとで",
1700
- "repair_dialog_never": "今後表示しない",
1701
1681
  "alert_forwarder_title": "共存モードを有効にしますか?",
1702
1682
  "alert_forwarder_body": "他の Claude Code ステータスラインツールを検出しました。共存モードでは、usage はフォワーダー経由で既存のツールと一緒に動作します。",
1703
1683
  "alert_forwarder_enable": "共存モードを有効化",
@@ -2240,11 +2220,6 @@
2240
2220
  "hook_installed_restart": "훅 설치가 완료되었습니다. Claude Code를 한 번 다시 시작하세요.",
2241
2221
  "hook_install_failed": "훅 설치에 실패했습니다",
2242
2222
  "hook_install_failed_default": "setup_hook.setup()가 실패를 반환했습니다",
2243
- "repair_dialog_title": "상태 표시줄 설정 충돌",
2244
- "repair_dialog_message": "다른 도구가 Claude Code 상태 표시줄을 사용 중입니다.\n공존 모드로 전환할까요? usage app과 다른 도구를 함께 실행할 수 있습니다.",
2245
- "repair_dialog_repair": "지금 복구",
2246
- "repair_dialog_skip": "나중에",
2247
- "repair_dialog_never": "다시 묻지 않기",
2248
2223
  "alert_forwarder_title": "공존 모드를 활성화할까요?",
2249
2224
  "alert_forwarder_body": "다른 Claude Code 상태 표시줄 도구를 감지했습니다. 공존 모드에서는 usage가 포워더를 통해 기존 도구와 함께 실행됩니다.",
2250
2225
  "alert_forwarder_enable": "공존 모드 활성화",
@@ -9,8 +9,8 @@ import shutil
9
9
  import sys
10
10
  from pathlib import Path
11
11
 
12
- from i18n import t as _t
13
12
  from installer import setup_hook
13
+ from usage_common.i18n import t as _t
14
14
  from usage_common.usage_lang import detect_lang
15
15
 
16
16
  INSTALL_DIR = Path.home() / ".usage" / "claude-pane" / "usage-dash"
@@ -62,7 +62,7 @@ def _status_argv() -> list[str]:
62
62
  f"import sys;sys.path[:0]=[{resources!r}+'/lib/python{major}{minor}.zip',"
63
63
  f"{resources!r}+'/lib/python{major}.{minor}',"
64
64
  f"{resources!r}+'/lib/python{major}.{minor}/lib-dynload',{resources!r}];"
65
- "import usage_cli;sys.argv=['usage','status','--json'];usage_cli.main()"
65
+ "from usage_app import cli;sys.argv=['usage','status','--json'];cli.main()"
66
66
  )
67
67
  return [
68
68
  "/usr/bin/env",
@@ -72,16 +72,17 @@ def _status_argv() -> list[str]:
72
72
  "-c",
73
73
  bootstrap,
74
74
  ]
75
+ root = str(Path(__file__).resolve().parent.parent)
75
76
  return [
76
77
  sys.executable,
77
- str(Path(__file__).resolve().parent.parent / "usage_cli.py"),
78
- "status",
79
- "--json",
78
+ "-c",
79
+ f"import sys;sys.path.insert(0,{root!r});from usage_app import cli;"
80
+ "sys.argv=['usage','status','--json'];cli.main()",
80
81
  ]
81
82
 
82
83
 
83
84
  def _sidecar_text(mod: str = "usage-dash") -> str:
84
- from i18n import I18N_PATH
85
+ from usage_common.i18n import I18N_PATH
85
86
 
86
87
  bundle = json.loads(I18N_PATH.read_text(encoding="utf-8"))
87
88
  english = bundle["en"]
@@ -20,7 +20,6 @@ from datetime import UTC, datetime
20
20
  from pathlib import Path
21
21
  from typing import Any
22
22
 
23
- from i18n import t as _t
24
23
  from installer import setup_hook
25
24
  from installer.setup_hook import (
26
25
  BACKUP_KEY,
@@ -50,8 +49,9 @@ from installer.setup_hook import (
50
49
  update_hook,
51
50
  )
52
51
  from loaders.codex_paths import codex_home
52
+ from usage_common.i18n import t as _t
53
53
  from usage_common.usage_lang import detect_lang
54
- from usage_statusline import _exclusive_lock
54
+ from usage_hooks.usage_statusline import _exclusive_lock
55
55
 
56
56
  CODEX_CONFIG = setup_hook.CODEX_CONFIG
57
57
 
@@ -94,7 +94,7 @@ _TERSE_REMINDER_MARKER = "usage-terse-reminder"
94
94
  _TERSE_REMINDER_MARKERS = (_TERSE_REMINDER_MARKER, "usage_terse_reminder")
95
95
  # Independent, opt-in Claude Code UserPromptSubmit hook.
96
96
  QUOTA_AWARE_HOOK_TARGET = Path(os.path.expanduser("~/.claude/usage-quota-aware.py"))
97
- QUOTA_AWARE_HOOK_VERSION = "1.0"
97
+ QUOTA_AWARE_HOOK_VERSION = "1.1"
98
98
  QUOTA_AWARE_MATCHER = ""
99
99
  _QUOTA_AWARE_MARKER = "usage-quota-aware"
100
100
  _QUOTA_AWARE_MARKERS = (_QUOTA_AWARE_MARKER, "usage_quota_aware")
@@ -205,9 +205,9 @@ def _migrate_bundled_python_commands_if_needed(
205
205
 
206
206
 
207
207
  def _resolve_resume_source() -> Path:
208
- # installer/ is one level below the repo root, where the hook scripts remain.
208
+ # installer/ is one level below the repo root; hook sources live in usage_hooks/.
209
209
  paths = [
210
- Path(__file__).resolve().parent.parent / "usage_session_resume.py",
210
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_session_resume.py",
211
211
  Path(sys.executable).resolve().parent.parent / "Resources" / "usage_session_resume.py",
212
212
  ]
213
213
  for path in paths:
@@ -219,7 +219,7 @@ def _resolve_resume_source() -> Path:
219
219
 
220
220
  def _resolve_terse_source() -> Path:
221
221
  paths = [
222
- Path(__file__).resolve().parent.parent / "usage_terse_mode.py",
222
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_terse_mode.py",
223
223
  Path(sys.executable).resolve().parent.parent / "Resources" / "usage_terse_mode.py",
224
224
  ]
225
225
  for path in paths:
@@ -231,7 +231,7 @@ def _resolve_terse_source() -> Path:
231
231
 
232
232
  def _resolve_terse_reminder_source() -> Path:
233
233
  paths = [
234
- Path(__file__).resolve().parent.parent / "usage_terse_reminder.py",
234
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_terse_reminder.py",
235
235
  (Path(sys.executable).resolve().parent.parent / "Resources" / "usage_terse_reminder.py"),
236
236
  ]
237
237
  for path in paths:
@@ -286,7 +286,7 @@ def _copy_terse_reminder_script() -> None:
286
286
  def _write_resume_sidecar() -> None:
287
287
  """Mirror i18n.json's rw_prompt/rw_none into a sidecar the stdlib hook can read,
288
288
  so the injected wording stays single-sourced and the hook needs no app imports."""
289
- from i18n import I18N_PATH
289
+ from usage_common.i18n import I18N_PATH
290
290
 
291
291
  try:
292
292
  bundle = json.loads(I18N_PATH.read_text(encoding="utf-8"))
@@ -350,7 +350,7 @@ def _write_resume_sidecar() -> None:
350
350
 
351
351
 
352
352
  def _write_terse_sidecar() -> None:
353
- from i18n import I18N_PATH
353
+ from usage_common.i18n import I18N_PATH
354
354
 
355
355
  try:
356
356
  bundle = json.loads(I18N_PATH.read_text(encoding="utf-8"))
@@ -1275,7 +1275,7 @@ def self_heal() -> None:
1275
1275
 
1276
1276
  def _resolve_quota_aware_source() -> Path:
1277
1277
  paths = [
1278
- Path(__file__).resolve().parent.parent / "usage_quota_aware.py",
1278
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_quota_aware.py",
1279
1279
  Path(sys.executable).resolve().parent.parent / "Resources" / "usage_quota_aware.py",
1280
1280
  ]
1281
1281
  for path in paths:
@@ -8,7 +8,7 @@
8
8
 
9
9
  Claude Code calls the command configured in ~/.claude/settings.json statusLine
10
10
  and sends session JSON on stdin whenever it refreshes the status line. The
11
- installer copies usage_statusline.py to ~/.claude/usage-statusline.py and points
11
+ installer copies usage_hooks/usage_statusline.py to ~/.claude/usage-statusline.py and points
12
12
  statusLine at it, so the main app can read a local status file.
13
13
 
14
14
  The previous statusLine is backed up under settings["usage"]["previousStatusLine"]
@@ -34,9 +34,9 @@ from datetime import UTC, datetime
34
34
  from pathlib import Path
35
35
  from typing import Any, cast
36
36
 
37
- from i18n import t as _t
38
37
  from loaders.claude_paths import claude_home
39
38
  from loaders.codex_paths import codex_home
39
+ from usage_common.i18n import t as _t
40
40
  from usage_common.subprocess_utils import hidden_console_kwargs
41
41
 
42
42
  HOOK_TARGET = Path(os.path.expanduser("~/.claude/usage-statusline.py"))
@@ -118,9 +118,9 @@ def configure_windows_utf8_output() -> None:
118
118
 
119
119
 
120
120
  def _resolve_hook_source() -> Path:
121
- # installer/ is one level below the repo root, where the hook scripts remain.
121
+ # installer/ is one level below the repo root; hook sources live in usage_hooks/.
122
122
  paths = [
123
- Path(__file__).resolve().parent.parent / "usage_statusline.py",
123
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_statusline.py",
124
124
  Path(sys.executable).resolve().parent.parent / "Resources" / "usage_statusline.py",
125
125
  ]
126
126
  for path in paths:
@@ -132,7 +132,7 @@ def _resolve_hook_source() -> Path:
132
132
 
133
133
  def _resolve_forwarder_source() -> Path:
134
134
  paths = [
135
- Path(__file__).resolve().parent.parent / "usage_statusline_forwarder.py",
135
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_statusline_forwarder.py",
136
136
  (
137
137
  Path(sys.executable).resolve().parent.parent
138
138
  / "Resources"
@@ -148,7 +148,7 @@ def _resolve_forwarder_source() -> Path:
148
148
 
149
149
  def _resolve_agy_hook_source() -> Path | None:
150
150
  paths = [
151
- Path(__file__).resolve().parent.parent / "usage_statusline_agy.py",
151
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_statusline_agy.py",
152
152
  Path(sys.executable).resolve().parent.parent / "Resources" / "usage_statusline_agy.py",
153
153
  ]
154
154
  return next((path for path in paths if path.exists()), None)
@@ -166,7 +166,7 @@ def _agy_hook_script_is_stale() -> bool:
166
166
 
167
167
  def _resolve_grok_hook_source() -> Path | None:
168
168
  paths = [
169
- Path(__file__).resolve().parent.parent / "usage_statusline_grok.py",
169
+ Path(__file__).resolve().parent.parent / "usage_hooks" / "usage_statusline_grok.py",
170
170
  Path(sys.executable).resolve().parent.parent / "Resources" / "usage_statusline_grok.py",
171
171
  ]
172
172
  return next((path for path in paths if path.exists()), None)
@@ -1080,10 +1080,6 @@ def _ensure_table_line(content: str, name: str, line_regex: re.Pattern[str], lin
1080
1080
  return content[:start] + f"\n{line}" + content[start:]
1081
1081
 
1082
1082
 
1083
- def _find_tui_table(content: str) -> re.Match[str] | None:
1084
- return _find_table(content, "tui")
1085
-
1086
-
1087
1083
  def _insert_tui_status_line(content: str, replacement: str) -> str:
1088
1084
  return _insert_table_line(content, "tui", replacement)
1089
1085
 
@@ -1277,7 +1273,7 @@ def is_codex_setup() -> bool:
1277
1273
 
1278
1274
 
1279
1275
  def _install_forwarder(settings: dict[str, Any]) -> None:
1280
- """Copy usage_statusline_forwarder.py to ~/.claude/ and update settings.json."""
1276
+ """Copy usage_hooks/usage_statusline_forwarder.py to ~/.claude/ and update settings.json."""
1281
1277
  _copy_hook_script()
1282
1278
  _copy_forwarder_script()
1283
1279
  _backup_existing_statusline(settings)
@@ -28,7 +28,7 @@ from loaders.disk_cache_lifecycle import (
28
28
  from loaders.disk_cache_lifecycle import (
29
29
  flush_caches_on_terminate as _flush_caches_on_terminate,
30
30
  )
31
- from project_resolver import resolve_project_name
31
+ from usage_common.project_resolver import resolve_project_name
32
32
 
33
33
  logger = logging.getLogger(__name__)
34
34
 
@@ -18,10 +18,10 @@ from enum import StrEnum
18
18
  from pathlib import Path
19
19
  from typing import Any
20
20
 
21
- from i18n import _t
22
21
  from installer.setup_hook import current_hook_state
23
22
  from loaders import claude_desktop
24
23
  from loaders.claude_paths import claude_config_dirs, claude_json_path
24
+ from usage_common.i18n import _t
25
25
  from usage_common.usage_lang import detect_lang
26
26
 
27
27
  logger = logging.getLogger(__name__)
@@ -61,7 +61,7 @@ from loaders.disk_cache_lifecycle import (
61
61
  )
62
62
  from loaders.history_loader import UsageEntry
63
63
  from loaders.jsonl_limits import read_bounded_jsonl_line
64
- from project_resolver import resolve_project_name
64
+ from usage_common.project_resolver import resolve_project_name
65
65
  from usage_common.time_utils import parse_optional_iso8601_utc
66
66
 
67
67
  logger = logging.getLogger(__name__)
@@ -26,7 +26,7 @@ from urllib.parse import unquote_to_bytes
26
26
 
27
27
  from loaders.history_loader import UsageEntry
28
28
  from loaders.jsonl_limits import read_bounded_jsonl_line
29
- from project_resolver import resolve_project_name
29
+ from usage_common.project_resolver import resolve_project_name
30
30
  from usage_common.time_utils import parse_optional_iso8601_utc
31
31
 
32
32
  logger = logging.getLogger(__name__)
@@ -30,7 +30,7 @@ from loaders.disk_cache_lifecycle import (
30
30
  )
31
31
  from loaders.history_disk_cache import _shard_index, flush_caches, seed_caches
32
32
  from loaders.jsonl_limits import read_bounded_jsonl_line
33
- from project_resolver import project_from_encoded_path, resolve_project_name
33
+ from usage_common.project_resolver import project_from_encoded_path, resolve_project_name
34
34
  from usage_common.time_utils import parse_optional_iso8601_utc
35
35
 
36
36
  logger = logging.getLogger(__name__)
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
  from typing import Any
14
14
 
15
15
  from loaders.history_loader import UsageEntry
16
- from project_resolver import resolve_project_name
16
+ from usage_common.project_resolver import resolve_project_name
17
17
 
18
18
  logger = logging.getLogger(__name__)
19
19
  MUSE_SESSIONS_DIR = Path(os.path.expanduser("~/.local/share/muse/sessions"))