usage-cli 0.31.6__tar.gz → 0.32.1__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.
- {usage_cli-0.31.6 → usage_cli-0.32.1}/PKG-INFO +32 -3
- {usage_cli-0.31.6 → usage_cli-0.32.1}/README.md +31 -2
- {usage_cli-0.31.6 → usage_cli-0.32.1}/i18n.json +275 -5
- usage_cli-0.32.1/installer/claude_pane.py +203 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/main.py +5 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/actions.py +48 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/app.py +6 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/menu.py +12 -1
- usage_cli-0.32.1/menubar/new_badge.py +97 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/update.py +5 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/pyproject.toml +1 -1
- {usage_cli-0.31.6 → usage_cli-0.32.1}/setup_app.py +1 -0
- usage_cli-0.32.1/tests/test_claude_pane.py +416 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_main.py +13 -0
- usage_cli-0.32.1/tests/test_new_badge.py +137 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_cli.py +108 -1
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_wintray.py +88 -1
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.egg-info/PKG-INFO +32 -3
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.egg-info/SOURCES.txt +4 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.py +65 -4
- {usage_cli-0.31.6 → usage_cli-0.32.1}/wintray/app.py +61 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/wintray/menu.py +2 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/LICENSE +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/agy.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/claude.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/codex.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/grok.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/muse.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/rate_limits.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/registry.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/adapters/types.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/aggregator.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/blocks.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/diagnoser.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/dispatch_ledger.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/insights.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/persona_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/reporter.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/subscription.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/analyzer/usage_snapshot.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/doctor.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/fsevents_watch.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/i18n.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/installer/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/installer/login_item.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/installer/session_hooks.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/installer/setup_hook.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/installer/statusline_settings.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/agy_disk_cache.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/agy_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/agy_quota_probe.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/cache_quarantine.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/claude_paths.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/codex_disk_cache.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/codex_events.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/codex_fork_replay.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/codex_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/codex_paths.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/disk_cache_common.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/disk_cache_lifecycle.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/grok_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/grok_quota_probe.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/history_disk_cache.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/history_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/jsonl_limits.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/jsonl_utils.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/loaders/muse_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/agy.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/chrome.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/grok.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/notify.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/popover.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/prefs.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/refresh.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/state.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/menubar/title.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/base.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/dynamic_height.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/panel_scale.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/panel_window.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/panel_window_state.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/payload.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/web_panel.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/panels/window_drag.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/prefs.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/pricing.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/project_resolver.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/quota/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/quota/agy_window_keeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/quota/burn_rate.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/quota/codex_window_keeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/quota/usage_rate.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/quota/window_keeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/service_status.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/setup.cfg +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_adapters_claude.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_adapters_codex.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_adapters_rate_limits.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_aggregator.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_agy_adapter.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_agy_disk_cache.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_agy_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_agy_quota_probe.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_agy_window_keeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_analyzer_blocks.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_analyzer_pipeline.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_burn_rate.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_cache_quarantine.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_claude_paths.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_codex_consistency.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_codex_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_codex_window_keeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_diagnoser.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_disk_cache_shards.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_dispatch_ledger.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_doctor.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_dynamic_height.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_fsevents_watch.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_grok_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_grok_quota_probe.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_history_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_hook_scripts_are_standalone.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_html_report_snapshot.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_i18n_format_fallback.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_i18n_key_parity.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_i18n_packaged_path.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_insights.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_jsonl_utils.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_login_item.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_menubar.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_menubar_agy.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_menubar_grok.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_menubar_notify.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_menubar_prefs.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_menubar_state.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_muse_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_packaged_resources.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_packaging.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_panel_footer_layout.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_panel_scale.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_panel_window_state.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_panels.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_panels_lazy_import.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_persona_loader.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_pricing.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_project_resolver.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_report_daily_chart.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_report_filter_js.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_reporter_build_data.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_service_status.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_session_resume.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_setup_app.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_setup_hook.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_setup_hook_coexistence.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_setup_hook_resume.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_setup_hook_terse.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_subprocess_utils.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_subscription.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_time_utils.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_tui.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_tui_sprite.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_ui_tables.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_update_checker.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_update_gate.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_update_release_notes.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_client.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_diagnosis_snapshot.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_dir_sweeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_lang.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_logging.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_notifications.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_rate.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_snapshot.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_snapshot_replay.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_statusline.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_statusline_agy.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_statusline_forwarder.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_statusline_grok.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_terse_mode.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_usage_terse_reminder.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_web_panel_payload.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_wheel_packaging.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_win_login_item.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_window_keeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tests/test_windows_manifest.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tui/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tui/app.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/tui/sprite.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/html_report.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/report_charts.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/report_daily_chart.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/report_filter.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/report_ledger.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/report_scripts.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/report_styles.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/ui/tables.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/updates/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/updates/checker.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/updates/gate.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/updates/release_notes.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.egg-info/dependency_links.txt +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.egg-info/entry_points.txt +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.egg-info/requires.txt +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_cli.egg-info/top_level.txt +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_client.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_common/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_common/subprocess_utils.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_common/time_utils.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_common/usage_dir_sweeper.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_common/usage_lang.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_common/usage_logging.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_diagnosis_snapshot.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_notifications.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_session_resume.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_statusline.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_statusline_agy.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_statusline_forwarder.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_statusline_grok.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_terse_mode.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/usage_terse_reminder.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/wintray/__init__.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/wintray/login_item.py +0 -0
- {usage_cli-0.31.6 → usage_cli-0.32.1}/wintray/watch.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: usage-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.32.1
|
|
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
|
|
@@ -57,7 +57,7 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
|
|
|
57
57
|
|
|
58
58
|
**Not on macOS?** `uvx usage-cli` runs the terminal interface anywhere, Linux included — no install, no menu bar.
|
|
59
59
|
|
|
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)
|
|
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) · [Claude Code Side Pane](#claude-code-side-pane) · [Windows](#windows-support) · [Themes](#theme-gallery) · [Troubleshooting](#troubleshooting) · [Comparison](#comparison) · [Not a Fit?](#when-usage-isnt-the-right-fit) · [Development](#development)
|
|
61
61
|
|
|
62
62
|
## What You Get
|
|
63
63
|
|
|
@@ -76,8 +76,9 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
|
|
|
76
76
|
|
|
77
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.
|
|
78
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.
|
|
79
|
+
- **Claude Code side pane (macOS and Windows):** Quotas, conversations, and background jobs inside Claude Code. [See the side pane](#claude-code-side-pane).
|
|
79
80
|
- **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
|
|
81
|
+
- **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).
|
|
81
82
|
- **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.
|
|
82
83
|
|
|
83
84
|
### Stay Current
|
|
@@ -146,6 +147,34 @@ Once set up, the bottom of the Claude Code window will show a status line like t
|
|
|
146
147
|
<img src="docs/statusline.en.gif" alt="Claude Code statusLine display (English)" width="900">
|
|
147
148
|
</p>
|
|
148
149
|
|
|
150
|
+
## Claude Code Side Pane
|
|
151
|
+
|
|
152
|
+
See your quota, other conversations, and background jobs without leaving Claude Code. Available on macOS and Windows.
|
|
153
|
+
|
|
154
|
+
<p align="center"><img src="docs/side-pane.png" alt="Claude Code side pane showing quotas, conversations, and background jobs" width="637"></p>
|
|
155
|
+
|
|
156
|
+
**What you’ll see**
|
|
157
|
+
|
|
158
|
+
- **Quotas:** Your 5-hour and weekly limits.
|
|
159
|
+
- **Claude conversations:** Conversations waiting for your permission or MCP input are marked in yellow.
|
|
160
|
+
- **Background jobs:** Includes subagents started by Claude with the Agent tool and their status.
|
|
161
|
+
|
|
162
|
+
**How to enable**
|
|
163
|
+
|
|
164
|
+
1. In the usage menu bar menu (macOS) or the system-tray panel menu (Windows), check **Claude Code side pane**.
|
|
165
|
+
2. Open a new conversation or run `/reload-plugins`.
|
|
166
|
+
3. At terminal widths ≥144 columns, the pane opens on the right automatically. In narrower terminals, enter `/usage-dash`.
|
|
167
|
+
|
|
168
|
+
<details>
|
|
169
|
+
<summary>Compatibility and updates</summary>
|
|
170
|
+
|
|
171
|
+
- Requires a recent Claude Code with mod support; tested with 2.1.289.
|
|
172
|
+
- The pane docks on the right only in Claude Code's fullscreen layout; otherwise it appears above the prompt. On Windows, enabling the pane turns the fullscreen layout on as well, and turning the pane off switches it back.
|
|
173
|
+
- The built-in macOS Terminal supports only 256 colors and may show a gray background. Select an ANSI dark theme in `/config`.
|
|
174
|
+
- When the usage app starts, it automatically updates an enabled pane to the bundled version.
|
|
175
|
+
|
|
176
|
+
</details>
|
|
177
|
+
|
|
149
178
|
## Windows Support
|
|
150
179
|
|
|
151
180
|
Windows has the full core experience: the system-tray UI, Claude Code status-line hook, and Codex history parsing all work natively. Download `usage-windows.zip` from the [latest GitHub Release](https://github.com/aqua5230/usage/releases/latest), unzip it, then run `usage.exe`—no installer is needed. If SmartScreen shows **Windows protected your PC** on first launch, click **More info** → **Run anyway**. The tray UI requires Microsoft Edge WebView2 Runtime, which is normally included with Windows 10 and 11.
|
|
@@ -37,7 +37,7 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
|
|
|
37
37
|
|
|
38
38
|
**Not on macOS?** `uvx usage-cli` runs the terminal interface anywhere, Linux included — no install, no menu bar.
|
|
39
39
|
|
|
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)
|
|
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) · [Claude Code Side Pane](#claude-code-side-pane) · [Windows](#windows-support) · [Themes](#theme-gallery) · [Troubleshooting](#troubleshooting) · [Comparison](#comparison) · [Not a Fit?](#when-usage-isnt-the-right-fit) · [Development](#development)
|
|
41
41
|
|
|
42
42
|
## What You Get
|
|
43
43
|
|
|
@@ -56,8 +56,9 @@ It lands in your Applications folder automatically. Open it once; if macOS 15 or
|
|
|
56
56
|
|
|
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
|
+
- **Claude Code side pane (macOS and Windows):** Quotas, conversations, and background jobs inside Claude Code. [See the side pane](#claude-code-side-pane).
|
|
59
60
|
- **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
|
|
61
|
+
- **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).
|
|
61
62
|
- **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.
|
|
62
63
|
|
|
63
64
|
### Stay Current
|
|
@@ -126,6 +127,34 @@ Once set up, the bottom of the Claude Code window will show a status line like t
|
|
|
126
127
|
<img src="docs/statusline.en.gif" alt="Claude Code statusLine display (English)" width="900">
|
|
127
128
|
</p>
|
|
128
129
|
|
|
130
|
+
## Claude Code Side Pane
|
|
131
|
+
|
|
132
|
+
See your quota, other conversations, and background jobs without leaving Claude Code. Available on macOS and Windows.
|
|
133
|
+
|
|
134
|
+
<p align="center"><img src="docs/side-pane.png" alt="Claude Code side pane showing quotas, conversations, and background jobs" width="637"></p>
|
|
135
|
+
|
|
136
|
+
**What you’ll see**
|
|
137
|
+
|
|
138
|
+
- **Quotas:** Your 5-hour and weekly limits.
|
|
139
|
+
- **Claude conversations:** Conversations waiting for your permission or MCP input are marked in yellow.
|
|
140
|
+
- **Background jobs:** Includes subagents started by Claude with the Agent tool and their status.
|
|
141
|
+
|
|
142
|
+
**How to enable**
|
|
143
|
+
|
|
144
|
+
1. In the usage menu bar menu (macOS) or the system-tray panel menu (Windows), check **Claude Code side pane**.
|
|
145
|
+
2. Open a new conversation or run `/reload-plugins`.
|
|
146
|
+
3. At terminal widths ≥144 columns, the pane opens on the right automatically. In narrower terminals, enter `/usage-dash`.
|
|
147
|
+
|
|
148
|
+
<details>
|
|
149
|
+
<summary>Compatibility and updates</summary>
|
|
150
|
+
|
|
151
|
+
- Requires a recent Claude Code with mod support; tested with 2.1.289.
|
|
152
|
+
- The pane docks on the right only in Claude Code's fullscreen layout; otherwise it appears above the prompt. On Windows, enabling the pane turns the fullscreen layout on as well, and turning the pane off switches it back.
|
|
153
|
+
- The built-in macOS Terminal supports only 256 colors and may show a gray background. Select an ANSI dark theme in `/config`.
|
|
154
|
+
- When the usage app starts, it automatically updates an enabled pane to the bundled version.
|
|
155
|
+
|
|
156
|
+
</details>
|
|
157
|
+
|
|
129
158
|
## Windows Support
|
|
130
159
|
|
|
131
160
|
Windows has the full core experience: the system-tray UI, Claude Code status-line hook, and Codex history parsing all work natively. Download `usage-windows.zip` from the [latest GitHub Release](https://github.com/aqua5230/usage/releases/latest), unzip it, then run `usage.exe`—no installer is needed. If SmartScreen shows **Windows protected your PC** on first launch, click **More info** → **Run anyway**. The tray UI requires Microsoft Edge WebView2 Runtime, which is normally included with Windows 10 and 11.
|
|
@@ -425,7 +425,61 @@
|
|
|
425
425
|
"setup_hook_deleted": "✓ 已刪除 hook:{path}",
|
|
426
426
|
"setup_status_file_deleted": "✓ 已刪除狀態檔:{path}",
|
|
427
427
|
"wintray_unavailable": "Windows 系統匣介面尚未安裝,改用終端機 TUI。",
|
|
428
|
-
"wintray_already_running": "usage 已在執行中;請點系統匣的 usage 圖示開啟面板。"
|
|
428
|
+
"wintray_already_running": "usage 已在執行中;請點系統匣的 usage 圖示開啟面板。",
|
|
429
|
+
"claude_pane_quota": "額度",
|
|
430
|
+
"claude_pane_five_hour": "5小時",
|
|
431
|
+
"claude_pane_week": "週",
|
|
432
|
+
"claude_pane_period": "期間",
|
|
433
|
+
"claude_pane_sessions": "Claude 對話",
|
|
434
|
+
"claude_pane_busy": "忙",
|
|
435
|
+
"claude_pane_waiting": "等你",
|
|
436
|
+
"claude_pane_agent_running": "執行中",
|
|
437
|
+
"claude_pane_agent_idle": "閒置",
|
|
438
|
+
"claude_pane_agent_pending": "待執行",
|
|
439
|
+
"claude_pane_busy_count": "{count} 忙 / {total}",
|
|
440
|
+
"claude_pane_idle": "閒置 {ago}",
|
|
441
|
+
"claude_pane_runs": "背景工作",
|
|
442
|
+
"claude_pane_none": "(沒有)",
|
|
443
|
+
"claude_pane_untitled": "(無標題)",
|
|
444
|
+
"claude_pane_no_project": "(無專案)",
|
|
445
|
+
"claude_pane_here": "(這裡)",
|
|
446
|
+
"claude_pane_more": "還有 {count} 個",
|
|
447
|
+
"claude_pane_less": "收回",
|
|
448
|
+
"claude_pane_terminal": "終端",
|
|
449
|
+
"claude_pane_desktop": "桌面",
|
|
450
|
+
"claude_pane_minutes": "{count}分",
|
|
451
|
+
"claude_pane_hours": "{count}時",
|
|
452
|
+
"claude_pane_days": "{count}天",
|
|
453
|
+
"claude_pane_seconds": "{count}秒",
|
|
454
|
+
"claude_pane_minutes_ago": "{count}分前",
|
|
455
|
+
"claude_pane_seconds_ago": "{count}秒前",
|
|
456
|
+
"claude_pane_just_now": "剛剛",
|
|
457
|
+
"claude_pane_failed": "失敗",
|
|
458
|
+
"claude_pane_completed": "完成",
|
|
459
|
+
"claude_pane_completed_ago": "{ago}{status}",
|
|
460
|
+
"claude_pane_quota_invalid": "額度 JSON 缺少 agents",
|
|
461
|
+
"claude_pane_exit_code": "結束碼 {code}",
|
|
462
|
+
"claude_pane_quota_error": "額度讀取失敗:{error}",
|
|
463
|
+
"claude_pane_session_error": "對話讀取失敗:{error}",
|
|
464
|
+
"claude_pane_home_missing": "HOME 未設定",
|
|
465
|
+
"claude_pane_description": "開啟額度、Claude 對話與背景工作面板",
|
|
466
|
+
"claude_pane_title": "使用狀態",
|
|
467
|
+
"claude_pane_opened": "已開啟使用狀態面板。",
|
|
468
|
+
"claude_pane_compact_summary": "對話 {busy} 忙 / {total} · 背景工作 ",
|
|
469
|
+
"claude_pane_sidecar_error": "面板設定讀取失敗:{error}",
|
|
470
|
+
"menu_badge_new": "新",
|
|
471
|
+
"claude_pane_menu": "Claude Code 側邊面板",
|
|
472
|
+
"claude_pane_tooltip": "在 Claude Code 顯示額度、對話與背景工作",
|
|
473
|
+
"claude_pane_enabled_msg": "已開啟側邊面板。開新的 Claude Code 對話(或在對話裡打 /reload-plugins)後生效;終端機寬度不夠時打 /usage-dash 叫出面板。",
|
|
474
|
+
"claude_pane_fullscreen_enabled_note": "已一併開啟 Claude Code 的全螢幕介面,讓面板顯示在右側。取消勾選側邊面板時會改回。",
|
|
475
|
+
"claude_pane_disabled_msg": "已移除 Claude Code 側邊面板。",
|
|
476
|
+
"claude_pane_action_failed": "Claude Code 側邊面板切換失敗。",
|
|
477
|
+
"claude_pane_source_missing": "找不到面板原始碼。已檢查:{tried}",
|
|
478
|
+
"claude_pane_invalid_env": "Claude 設定的 env 必須是物件,CLAUDE_CODE_PLUGIN_DIRS 必須是字串。",
|
|
479
|
+
"claude_pane_invalid_sidecar": "usage-pane.json 格式錯誤",
|
|
480
|
+
"claude_pane_elapsed": "{minutes}分{seconds}秒",
|
|
481
|
+
"claude_pane_remaining": "剩",
|
|
482
|
+
"claude_pane_hours_ago": "{count}時前"
|
|
429
483
|
},
|
|
430
484
|
"en": {
|
|
431
485
|
"panel_default_name": "Default",
|
|
@@ -853,7 +907,61 @@
|
|
|
853
907
|
"setup_hook_deleted": "✓ Deleted hook: {path}",
|
|
854
908
|
"setup_status_file_deleted": "✓ Deleted status file: {path}",
|
|
855
909
|
"wintray_unavailable": "The Windows tray interface is not installed; falling back to the terminal TUI.",
|
|
856
|
-
"wintray_already_running": "usage is already running; click the usage tray icon to open the panel."
|
|
910
|
+
"wintray_already_running": "usage is already running; click the usage tray icon to open the panel.",
|
|
911
|
+
"claude_pane_quota": "Quota",
|
|
912
|
+
"claude_pane_five_hour": "5h",
|
|
913
|
+
"claude_pane_week": "Week",
|
|
914
|
+
"claude_pane_period": "Period",
|
|
915
|
+
"claude_pane_sessions": "Claude sessions",
|
|
916
|
+
"claude_pane_busy": "Busy",
|
|
917
|
+
"claude_pane_waiting": "waiting for you",
|
|
918
|
+
"claude_pane_agent_running": "running",
|
|
919
|
+
"claude_pane_agent_idle": "idle",
|
|
920
|
+
"claude_pane_agent_pending": "pending",
|
|
921
|
+
"claude_pane_busy_count": "{count} busy / {total}",
|
|
922
|
+
"claude_pane_idle": "Idle {ago}",
|
|
923
|
+
"claude_pane_runs": "Background jobs",
|
|
924
|
+
"claude_pane_none": "(none)",
|
|
925
|
+
"claude_pane_untitled": "(untitled)",
|
|
926
|
+
"claude_pane_no_project": "(no project)",
|
|
927
|
+
"claude_pane_here": "(here)",
|
|
928
|
+
"claude_pane_more": "{count} more",
|
|
929
|
+
"claude_pane_less": "Show less",
|
|
930
|
+
"claude_pane_terminal": "Terminal",
|
|
931
|
+
"claude_pane_desktop": "Desktop",
|
|
932
|
+
"claude_pane_minutes": "{count}m",
|
|
933
|
+
"claude_pane_hours": "{count}h",
|
|
934
|
+
"claude_pane_days": "{count}d",
|
|
935
|
+
"claude_pane_seconds": "{count}s",
|
|
936
|
+
"claude_pane_minutes_ago": "{count}m ago",
|
|
937
|
+
"claude_pane_seconds_ago": "{count}s ago",
|
|
938
|
+
"claude_pane_just_now": "just now",
|
|
939
|
+
"claude_pane_failed": "failed",
|
|
940
|
+
"claude_pane_completed": "completed",
|
|
941
|
+
"claude_pane_completed_ago": "{ago} · {status}",
|
|
942
|
+
"claude_pane_quota_invalid": "Quota JSON has no agents",
|
|
943
|
+
"claude_pane_exit_code": "exit code {code}",
|
|
944
|
+
"claude_pane_quota_error": "Cannot read quota: {error}",
|
|
945
|
+
"claude_pane_session_error": "Cannot read sessions: {error}",
|
|
946
|
+
"claude_pane_home_missing": "HOME is not set",
|
|
947
|
+
"claude_pane_description": "Open the quota, Claude sessions and background jobs pane",
|
|
948
|
+
"claude_pane_title": "Usage",
|
|
949
|
+
"claude_pane_opened": "Usage pane opened.",
|
|
950
|
+
"claude_pane_compact_summary": "Sessions {busy} busy / {total} · Background jobs ",
|
|
951
|
+
"claude_pane_sidecar_error": "Cannot read pane settings: {error}",
|
|
952
|
+
"menu_badge_new": "New",
|
|
953
|
+
"claude_pane_menu": "Claude Code side pane",
|
|
954
|
+
"claude_pane_tooltip": "Show quotas, Claude sessions and background jobs in Claude Code",
|
|
955
|
+
"claude_pane_enabled_msg": "Pane enabled. Open a new Claude Code conversation (or run /reload-plugins in a conversation). If the terminal is too narrow, run /usage-dash to open the pane.",
|
|
956
|
+
"claude_pane_fullscreen_enabled_note": "Claude Code's fullscreen layout is now on so the pane can sit on the right. Turning the side pane off switches it back.",
|
|
957
|
+
"claude_pane_disabled_msg": "Claude Code side pane removed.",
|
|
958
|
+
"claude_pane_action_failed": "Could not change the Claude Code side pane.",
|
|
959
|
+
"claude_pane_source_missing": "Pane source not found. Tried: {tried}",
|
|
960
|
+
"claude_pane_invalid_env": "Claude settings env must be an object and CLAUDE_CODE_PLUGIN_DIRS must be a string.",
|
|
961
|
+
"claude_pane_invalid_sidecar": "Invalid usage-pane.json",
|
|
962
|
+
"claude_pane_elapsed": "{minutes}m{seconds}s",
|
|
963
|
+
"claude_pane_remaining": "left",
|
|
964
|
+
"claude_pane_hours_ago": "{count}h ago"
|
|
857
965
|
},
|
|
858
966
|
"zh-CN": {
|
|
859
967
|
"panel_default_name": "默认",
|
|
@@ -1281,7 +1389,61 @@
|
|
|
1281
1389
|
"setup_hook_deleted": "✓ 已删除 hook:{path}",
|
|
1282
1390
|
"setup_status_file_deleted": "✓ 已删除状态文件:{path}",
|
|
1283
1391
|
"wintray_unavailable": "Windows 系统托盘界面尚未安装,改用终端 TUI。",
|
|
1284
|
-
"wintray_already_running": "usage 已在运行;请点击系统托盘的 usage 图标打开面板。"
|
|
1392
|
+
"wintray_already_running": "usage 已在运行;请点击系统托盘的 usage 图标打开面板。",
|
|
1393
|
+
"claude_pane_quota": "额度",
|
|
1394
|
+
"claude_pane_five_hour": "5小时",
|
|
1395
|
+
"claude_pane_week": "周",
|
|
1396
|
+
"claude_pane_period": "期间",
|
|
1397
|
+
"claude_pane_sessions": "Claude 对话",
|
|
1398
|
+
"claude_pane_busy": "忙",
|
|
1399
|
+
"claude_pane_waiting": "等你",
|
|
1400
|
+
"claude_pane_agent_running": "运行中",
|
|
1401
|
+
"claude_pane_agent_idle": "空闲",
|
|
1402
|
+
"claude_pane_agent_pending": "待运行",
|
|
1403
|
+
"claude_pane_busy_count": "{count} 忙 / {total}",
|
|
1404
|
+
"claude_pane_idle": "闲置 {ago}",
|
|
1405
|
+
"claude_pane_runs": "后台任务",
|
|
1406
|
+
"claude_pane_none": "(没有)",
|
|
1407
|
+
"claude_pane_untitled": "(无标题)",
|
|
1408
|
+
"claude_pane_no_project": "(无项目)",
|
|
1409
|
+
"claude_pane_here": "(这里)",
|
|
1410
|
+
"claude_pane_more": "还有 {count} 个",
|
|
1411
|
+
"claude_pane_less": "收起",
|
|
1412
|
+
"claude_pane_terminal": "终端",
|
|
1413
|
+
"claude_pane_desktop": "桌面",
|
|
1414
|
+
"claude_pane_minutes": "{count}分",
|
|
1415
|
+
"claude_pane_hours": "{count}时",
|
|
1416
|
+
"claude_pane_days": "{count}天",
|
|
1417
|
+
"claude_pane_seconds": "{count}秒",
|
|
1418
|
+
"claude_pane_minutes_ago": "{count}分前",
|
|
1419
|
+
"claude_pane_seconds_ago": "{count}秒前",
|
|
1420
|
+
"claude_pane_just_now": "刚刚",
|
|
1421
|
+
"claude_pane_failed": "失败",
|
|
1422
|
+
"claude_pane_completed": "完成",
|
|
1423
|
+
"claude_pane_completed_ago": "{ago}{status}",
|
|
1424
|
+
"claude_pane_quota_invalid": "额度 JSON 缺少 agents",
|
|
1425
|
+
"claude_pane_exit_code": "退出码 {code}",
|
|
1426
|
+
"claude_pane_quota_error": "额度读取失败:{error}",
|
|
1427
|
+
"claude_pane_session_error": "对话读取失败:{error}",
|
|
1428
|
+
"claude_pane_home_missing": "HOME 未设置",
|
|
1429
|
+
"claude_pane_description": "打开额度、Claude 对话与后台任务面板",
|
|
1430
|
+
"claude_pane_title": "使用状态",
|
|
1431
|
+
"claude_pane_opened": "已打开使用状态面板。",
|
|
1432
|
+
"claude_pane_compact_summary": "对话 {busy} 忙 / {total} · 后台任务 ",
|
|
1433
|
+
"claude_pane_sidecar_error": "面板设置读取失败:{error}",
|
|
1434
|
+
"menu_badge_new": "新",
|
|
1435
|
+
"claude_pane_menu": "Claude Code 侧边面板",
|
|
1436
|
+
"claude_pane_tooltip": "在 Claude Code 显示额度、对话与后台任务",
|
|
1437
|
+
"claude_pane_enabled_msg": "已开启侧边面板。打开新的 Claude Code 对话(或在对话里输入 /reload-plugins)后生效;终端宽度不够时输入 /usage-dash 打开面板。",
|
|
1438
|
+
"claude_pane_fullscreen_enabled_note": "已一并开启 Claude Code 的全屏界面,让面板显示在右侧。取消勾选侧边面板时会改回。",
|
|
1439
|
+
"claude_pane_disabled_msg": "已移除 Claude Code 侧边面板。",
|
|
1440
|
+
"claude_pane_action_failed": "Claude Code 侧边面板切换失败。",
|
|
1441
|
+
"claude_pane_source_missing": "找不到面板源代码。已检查:{tried}",
|
|
1442
|
+
"claude_pane_invalid_env": "Claude 设置的 env 必须是对象,CLAUDE_CODE_PLUGIN_DIRS 必须是字符串。",
|
|
1443
|
+
"claude_pane_invalid_sidecar": "usage-pane.json 格式错误",
|
|
1444
|
+
"claude_pane_elapsed": "{minutes}分{seconds}秒",
|
|
1445
|
+
"claude_pane_remaining": "剩",
|
|
1446
|
+
"claude_pane_hours_ago": "{count}时前"
|
|
1285
1447
|
},
|
|
1286
1448
|
"ja": {
|
|
1287
1449
|
"panel_default_name": "デフォルト",
|
|
@@ -1709,7 +1871,61 @@
|
|
|
1709
1871
|
"setup_hook_deleted": "✓ hook を削除しました: {path}",
|
|
1710
1872
|
"setup_status_file_deleted": "✓ 状態ファイルを削除しました: {path}",
|
|
1711
1873
|
"wintray_unavailable": "Windows のシステムトレイ画面は未インストールです。ターミナル TUI に切り替えます。",
|
|
1712
|
-
"wintray_already_running": "usage は既に実行中です。トレイの usage アイコンをクリックしてパネルを開いてください。"
|
|
1874
|
+
"wintray_already_running": "usage は既に実行中です。トレイの usage アイコンをクリックしてパネルを開いてください。",
|
|
1875
|
+
"claude_pane_quota": "使用量",
|
|
1876
|
+
"claude_pane_five_hour": "5時間",
|
|
1877
|
+
"claude_pane_week": "週",
|
|
1878
|
+
"claude_pane_period": "期間",
|
|
1879
|
+
"claude_pane_sessions": "Claude セッション",
|
|
1880
|
+
"claude_pane_busy": "実行中",
|
|
1881
|
+
"claude_pane_waiting": "入力待ち",
|
|
1882
|
+
"claude_pane_agent_running": "実行中",
|
|
1883
|
+
"claude_pane_agent_idle": "待機中",
|
|
1884
|
+
"claude_pane_agent_pending": "実行待ち",
|
|
1885
|
+
"claude_pane_busy_count": "{count} 実行中 / {total}",
|
|
1886
|
+
"claude_pane_idle": "待機 {ago}",
|
|
1887
|
+
"claude_pane_runs": "バックグラウンド作業",
|
|
1888
|
+
"claude_pane_none": "(なし)",
|
|
1889
|
+
"claude_pane_untitled": "(無題)",
|
|
1890
|
+
"claude_pane_no_project": "(プロジェクトなし)",
|
|
1891
|
+
"claude_pane_here": "(ここ)",
|
|
1892
|
+
"claude_pane_more": "あと {count} 件",
|
|
1893
|
+
"claude_pane_less": "折りたたむ",
|
|
1894
|
+
"claude_pane_terminal": "ターミナル",
|
|
1895
|
+
"claude_pane_desktop": "デスクトップ",
|
|
1896
|
+
"claude_pane_minutes": "{count}分",
|
|
1897
|
+
"claude_pane_hours": "{count}時間",
|
|
1898
|
+
"claude_pane_days": "{count}日",
|
|
1899
|
+
"claude_pane_seconds": "{count}秒",
|
|
1900
|
+
"claude_pane_minutes_ago": "{count}分前",
|
|
1901
|
+
"claude_pane_seconds_ago": "{count}秒前",
|
|
1902
|
+
"claude_pane_just_now": "たった今",
|
|
1903
|
+
"claude_pane_failed": "失敗",
|
|
1904
|
+
"claude_pane_completed": "完了",
|
|
1905
|
+
"claude_pane_completed_ago": "{ago} · {status}",
|
|
1906
|
+
"claude_pane_quota_invalid": "使用量 JSON に agents がありません",
|
|
1907
|
+
"claude_pane_exit_code": "終了コード {code}",
|
|
1908
|
+
"claude_pane_quota_error": "使用量を読み込めません: {error}",
|
|
1909
|
+
"claude_pane_session_error": "セッションを読み込めません: {error}",
|
|
1910
|
+
"claude_pane_home_missing": "HOME が設定されていません",
|
|
1911
|
+
"claude_pane_description": "使用量、Claude セッション、バックグラウンド作業のパネルを開く",
|
|
1912
|
+
"claude_pane_title": "使用状況",
|
|
1913
|
+
"claude_pane_opened": "使用状況パネルを開きました。",
|
|
1914
|
+
"claude_pane_compact_summary": "セッション {busy} 実行中 / {total} · バックグラウンド作業 ",
|
|
1915
|
+
"claude_pane_sidecar_error": "パネル設定を読み込めません: {error}",
|
|
1916
|
+
"menu_badge_new": "新規",
|
|
1917
|
+
"claude_pane_menu": "Claude Code サイドパネル",
|
|
1918
|
+
"claude_pane_tooltip": "Claude Code に使用量、セッション、バックグラウンド作業を表示",
|
|
1919
|
+
"claude_pane_enabled_msg": "サイドパネルを有効にしました。新しい Claude Code セッションを開くか、会話で /reload-plugins を実行してください。ターミナルの幅が足りない場合は /usage-dash で開けます。",
|
|
1920
|
+
"claude_pane_fullscreen_enabled_note": "Claude Code のフルスクリーンレイアウトを有効にし、パネルを右側に表示できるようにしました。サイドパネルをオフにすると元に戻ります。",
|
|
1921
|
+
"claude_pane_disabled_msg": "Claude Code サイドパネルを削除しました。",
|
|
1922
|
+
"claude_pane_action_failed": "Claude Code サイドパネルを切り替えられませんでした。",
|
|
1923
|
+
"claude_pane_source_missing": "パネルのソースがありません。確認先: {tried}",
|
|
1924
|
+
"claude_pane_invalid_env": "Claude 設定の env はオブジェクト、CLAUDE_CODE_PLUGIN_DIRS は文字列が必要です。",
|
|
1925
|
+
"claude_pane_invalid_sidecar": "usage-pane.json の形式が不正です",
|
|
1926
|
+
"claude_pane_elapsed": "{minutes}分{seconds}秒",
|
|
1927
|
+
"claude_pane_remaining": "残り",
|
|
1928
|
+
"claude_pane_hours_ago": "{count}時間前"
|
|
1713
1929
|
},
|
|
1714
1930
|
"ko": {
|
|
1715
1931
|
"panel_default_name": "기본",
|
|
@@ -2137,6 +2353,60 @@
|
|
|
2137
2353
|
"setup_hook_deleted": "✓ hook 삭제됨: {path}",
|
|
2138
2354
|
"setup_status_file_deleted": "✓ 상태 파일 삭제됨: {path}",
|
|
2139
2355
|
"wintray_unavailable": "Windows 시스템 트레이 화면이 설치되지 않아 터미널 TUI로 전환합니다.",
|
|
2140
|
-
"wintray_already_running": "usage가 이미 실행 중입니다. 트레이의 usage 아이콘을 클릭해 패널을 여세요."
|
|
2356
|
+
"wintray_already_running": "usage가 이미 실행 중입니다. 트레이의 usage 아이콘을 클릭해 패널을 여세요.",
|
|
2357
|
+
"claude_pane_quota": "사용량",
|
|
2358
|
+
"claude_pane_five_hour": "5시간",
|
|
2359
|
+
"claude_pane_week": "주간",
|
|
2360
|
+
"claude_pane_period": "기간",
|
|
2361
|
+
"claude_pane_sessions": "Claude 대화",
|
|
2362
|
+
"claude_pane_busy": "작업 중",
|
|
2363
|
+
"claude_pane_waiting": "입력 대기",
|
|
2364
|
+
"claude_pane_agent_running": "실행 중",
|
|
2365
|
+
"claude_pane_agent_idle": "유휴",
|
|
2366
|
+
"claude_pane_agent_pending": "실행 대기",
|
|
2367
|
+
"claude_pane_busy_count": "{count} 작업 중 / {total}",
|
|
2368
|
+
"claude_pane_idle": "대기 {ago}",
|
|
2369
|
+
"claude_pane_runs": "백그라운드 작업",
|
|
2370
|
+
"claude_pane_none": "(없음)",
|
|
2371
|
+
"claude_pane_untitled": "(제목 없음)",
|
|
2372
|
+
"claude_pane_no_project": "(프로젝트 없음)",
|
|
2373
|
+
"claude_pane_here": "(여기)",
|
|
2374
|
+
"claude_pane_more": "{count}개 더",
|
|
2375
|
+
"claude_pane_less": "접기",
|
|
2376
|
+
"claude_pane_terminal": "터미널",
|
|
2377
|
+
"claude_pane_desktop": "데스크톱",
|
|
2378
|
+
"claude_pane_minutes": "{count}분",
|
|
2379
|
+
"claude_pane_hours": "{count}시간",
|
|
2380
|
+
"claude_pane_days": "{count}일",
|
|
2381
|
+
"claude_pane_seconds": "{count}초",
|
|
2382
|
+
"claude_pane_minutes_ago": "{count}분 전",
|
|
2383
|
+
"claude_pane_seconds_ago": "{count}초 전",
|
|
2384
|
+
"claude_pane_just_now": "방금",
|
|
2385
|
+
"claude_pane_failed": "실패",
|
|
2386
|
+
"claude_pane_completed": "완료",
|
|
2387
|
+
"claude_pane_completed_ago": "{ago} · {status}",
|
|
2388
|
+
"claude_pane_quota_invalid": "사용량 JSON에 agents가 없습니다",
|
|
2389
|
+
"claude_pane_exit_code": "종료 코드 {code}",
|
|
2390
|
+
"claude_pane_quota_error": "사용량을 읽을 수 없습니다: {error}",
|
|
2391
|
+
"claude_pane_session_error": "대화를 읽을 수 없습니다: {error}",
|
|
2392
|
+
"claude_pane_home_missing": "HOME이 설정되지 않았습니다",
|
|
2393
|
+
"claude_pane_description": "사용량, Claude 대화 및 백그라운드 작업 패널 열기",
|
|
2394
|
+
"claude_pane_title": "사용 현황",
|
|
2395
|
+
"claude_pane_opened": "사용 현황 패널을 열었습니다.",
|
|
2396
|
+
"claude_pane_compact_summary": "대화 {busy} 작업 중 / {total} · 백그라운드 작업 ",
|
|
2397
|
+
"claude_pane_sidecar_error": "패널 설정을 읽을 수 없습니다: {error}",
|
|
2398
|
+
"menu_badge_new": "신규",
|
|
2399
|
+
"claude_pane_menu": "Claude Code 사이드 패널",
|
|
2400
|
+
"claude_pane_tooltip": "Claude Code에 사용량, 대화 및 백그라운드 작업 표시",
|
|
2401
|
+
"claude_pane_enabled_msg": "사이드 패널을 켰습니다. 새 Claude Code 대화를 열거나 대화에서 /reload-plugins를 실행하세요. 터미널이 좁으면 /usage-dash로 패널을 여세요.",
|
|
2402
|
+
"claude_pane_fullscreen_enabled_note": "Claude Code의 전체 화면 레이아웃도 켜서 패널이 오른쪽에 표시됩니다. 사이드 패널을 끄면 원래대로 돌아갑니다.",
|
|
2403
|
+
"claude_pane_disabled_msg": "Claude Code 사이드 패널을 제거했습니다.",
|
|
2404
|
+
"claude_pane_action_failed": "Claude Code 사이드 패널을 전환하지 못했습니다.",
|
|
2405
|
+
"claude_pane_source_missing": "패널 소스를 찾을 수 없습니다. 확인한 경로: {tried}",
|
|
2406
|
+
"claude_pane_invalid_env": "Claude 설정의 env는 객체, CLAUDE_CODE_PLUGIN_DIRS는 문자열이어야 합니다.",
|
|
2407
|
+
"claude_pane_invalid_sidecar": "usage-pane.json 형식이 잘못되었습니다",
|
|
2408
|
+
"claude_pane_elapsed": "{minutes}분{seconds}초",
|
|
2409
|
+
"claude_pane_remaining": "남음",
|
|
2410
|
+
"claude_pane_hours_ago": "{count}시간 전"
|
|
2141
2411
|
}
|
|
2142
2412
|
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""Install the opt-in Claude Code pane without changing other plugins."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import filecmp
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from i18n import t as _t
|
|
13
|
+
from installer import setup_hook
|
|
14
|
+
from usage_common.usage_lang import detect_lang
|
|
15
|
+
|
|
16
|
+
INSTALL_DIR = Path.home() / ".usage" / "claude-pane" / "usage-dash"
|
|
17
|
+
PLUGIN_DIRS_KEY = "CLAUDE_CODE_PLUGIN_DIRS"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _same_path(left: str, right: str) -> bool:
|
|
21
|
+
return os.path.normpath(os.path.expanduser(left)) == os.path.normpath(os.path.expanduser(right))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _add_path(value: str, path: str) -> str:
|
|
25
|
+
parts = value.split(os.pathsep) if value else []
|
|
26
|
+
if not any(part and _same_path(part, path) for part in parts):
|
|
27
|
+
parts.append(path)
|
|
28
|
+
return os.pathsep.join(parts)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _remove_path(value: str, path: str) -> str:
|
|
32
|
+
parts = [part for part in value.split(os.pathsep) if not (part and _same_path(part, path))]
|
|
33
|
+
return os.pathsep.join(parts) if any(parts) else ""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _resolve_source() -> Path:
|
|
37
|
+
paths = [
|
|
38
|
+
Path(__file__).resolve().parent.parent / "claude_pane" / "usage-dash",
|
|
39
|
+
Path(sys.executable).resolve().parent.parent / "Resources" / "claude_pane" / "usage-dash",
|
|
40
|
+
]
|
|
41
|
+
for path in paths:
|
|
42
|
+
if path.is_dir():
|
|
43
|
+
return path
|
|
44
|
+
raise SystemExit(_t("claude_pane_source_missing", tried=", ".join(map(str, paths))))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _status_argv() -> list[str]:
|
|
48
|
+
if getattr(sys, "frozen", False) and sys.platform == "win32":
|
|
49
|
+
return [sys.executable, "status", "--json"]
|
|
50
|
+
if getattr(sys, "frozen", False):
|
|
51
|
+
resources = str(Path(sys.executable).resolve().parent.parent / "Resources")
|
|
52
|
+
major, minor = sys.version_info[:2]
|
|
53
|
+
bootstrap = (
|
|
54
|
+
f"import sys;sys.path[:0]=[{resources!r}+'/lib/python{major}{minor}.zip',"
|
|
55
|
+
f"{resources!r}+'/lib/python{major}.{minor}',"
|
|
56
|
+
f"{resources!r}+'/lib/python{major}.{minor}/lib-dynload',{resources!r}];"
|
|
57
|
+
"import usage_cli;sys.argv=['usage','status','--json'];usage_cli.main()"
|
|
58
|
+
)
|
|
59
|
+
return [
|
|
60
|
+
"/usr/bin/env",
|
|
61
|
+
f"PYTHONHOME={resources}",
|
|
62
|
+
f"RESOURCEPATH={resources}",
|
|
63
|
+
sys.executable,
|
|
64
|
+
"-c",
|
|
65
|
+
bootstrap,
|
|
66
|
+
]
|
|
67
|
+
return [
|
|
68
|
+
sys.executable,
|
|
69
|
+
str(Path(__file__).resolve().parent.parent / "usage_cli.py"),
|
|
70
|
+
"status",
|
|
71
|
+
"--json",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _sidecar_text() -> str:
|
|
76
|
+
from i18n import I18N_PATH
|
|
77
|
+
|
|
78
|
+
bundle = json.loads(I18N_PATH.read_text(encoding="utf-8"))
|
|
79
|
+
english = bundle["en"]
|
|
80
|
+
table = bundle.get(detect_lang(), english)
|
|
81
|
+
strings = {
|
|
82
|
+
key: table.get(key) or value
|
|
83
|
+
for key, value in english.items()
|
|
84
|
+
if key.startswith("claude_pane_")
|
|
85
|
+
}
|
|
86
|
+
return (
|
|
87
|
+
json.dumps(
|
|
88
|
+
{"strings": strings, "status_argv": _status_argv()}, ensure_ascii=False, indent=2
|
|
89
|
+
)
|
|
90
|
+
+ "\n"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _write_sidecar() -> None:
|
|
95
|
+
setup_hook._atomic_write_text(INSTALL_DIR / "usage-pane.json", _sidecar_text())
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _copy_pane() -> None:
|
|
99
|
+
source = _resolve_source()
|
|
100
|
+
if INSTALL_DIR.exists():
|
|
101
|
+
shutil.rmtree(INSTALL_DIR)
|
|
102
|
+
shutil.copytree(source, INSTALL_DIR, ignore=shutil.ignore_patterns("*.test.ts"))
|
|
103
|
+
_write_sidecar()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _installed_is_current() -> bool:
|
|
107
|
+
source = _resolve_source()
|
|
108
|
+
shipped = {
|
|
109
|
+
path.relative_to(source)
|
|
110
|
+
for path in source.rglob("*")
|
|
111
|
+
if path.is_file() and not path.name.endswith(".test.ts")
|
|
112
|
+
}
|
|
113
|
+
# Claude Code writes its own type stubs under .claude-plugin/types; they are not ours.
|
|
114
|
+
generated = Path(".claude-plugin", "types")
|
|
115
|
+
installed = {
|
|
116
|
+
path.relative_to(INSTALL_DIR)
|
|
117
|
+
for path in INSTALL_DIR.rglob("*")
|
|
118
|
+
if path.is_file() and generated not in path.relative_to(INSTALL_DIR).parents
|
|
119
|
+
} - {Path("usage-pane.json")}
|
|
120
|
+
if shipped != installed:
|
|
121
|
+
return False
|
|
122
|
+
if not all(filecmp.cmp(source / path, INSTALL_DIR / path, shallow=False) for path in shipped):
|
|
123
|
+
return False
|
|
124
|
+
try:
|
|
125
|
+
return (INSTALL_DIR / "usage-pane.json").read_text(encoding="utf-8") == _sidecar_text()
|
|
126
|
+
except OSError:
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _env(settings: dict[str, object]) -> dict[str, str]:
|
|
131
|
+
env = settings.get("env", {})
|
|
132
|
+
if not isinstance(env, dict) or not isinstance(env.get(PLUGIN_DIRS_KEY, ""), str):
|
|
133
|
+
raise SystemExit(_t("claude_pane_invalid_env"))
|
|
134
|
+
return env
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def enable_claude_pane() -> int:
|
|
138
|
+
_copy_pane()
|
|
139
|
+
settings = setup_hook._load_settings()
|
|
140
|
+
env = _env(settings)
|
|
141
|
+
env[PLUGIN_DIRS_KEY] = _add_path(env.get(PLUGIN_DIRS_KEY, ""), str(INSTALL_DIR.absolute()))
|
|
142
|
+
settings["env"] = env
|
|
143
|
+
setup_hook._save_settings(settings)
|
|
144
|
+
return 0
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def is_fullscreen_layout() -> bool:
|
|
148
|
+
return setup_hook._load_settings().get("tui") == "fullscreen"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def enable_fullscreen_layout() -> None:
|
|
152
|
+
settings = setup_hook._load_settings()
|
|
153
|
+
settings["tui"] = "fullscreen"
|
|
154
|
+
usage = settings.get("usage")
|
|
155
|
+
if not isinstance(usage, dict):
|
|
156
|
+
usage = {}
|
|
157
|
+
settings["usage"] = usage
|
|
158
|
+
usage["claudePaneSetFullscreen"] = True
|
|
159
|
+
setup_hook._save_settings(settings)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def disable_claude_pane() -> int:
|
|
163
|
+
settings = setup_hook._load_settings()
|
|
164
|
+
env = _env(settings)
|
|
165
|
+
changed = False
|
|
166
|
+
if PLUGIN_DIRS_KEY in env:
|
|
167
|
+
value = _remove_path(env[PLUGIN_DIRS_KEY], str(INSTALL_DIR.absolute()))
|
|
168
|
+
if value:
|
|
169
|
+
env[PLUGIN_DIRS_KEY] = value
|
|
170
|
+
else:
|
|
171
|
+
env.pop(PLUGIN_DIRS_KEY)
|
|
172
|
+
if not env:
|
|
173
|
+
settings.pop("env", None)
|
|
174
|
+
changed = True
|
|
175
|
+
usage = settings.get("usage")
|
|
176
|
+
if isinstance(usage, dict) and usage.get("claudePaneSetFullscreen") is True:
|
|
177
|
+
if settings.get("tui") == "fullscreen":
|
|
178
|
+
settings.pop("tui")
|
|
179
|
+
usage.pop("claudePaneSetFullscreen")
|
|
180
|
+
if not usage:
|
|
181
|
+
settings.pop("usage")
|
|
182
|
+
changed = True
|
|
183
|
+
if changed:
|
|
184
|
+
setup_hook._save_settings(settings)
|
|
185
|
+
if INSTALL_DIR.exists():
|
|
186
|
+
shutil.rmtree(INSTALL_DIR)
|
|
187
|
+
return 0
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def is_claude_pane_enabled() -> bool:
|
|
191
|
+
try:
|
|
192
|
+
value = _env(setup_hook._load_settings()).get(PLUGIN_DIRS_KEY, "")
|
|
193
|
+
except SystemExit:
|
|
194
|
+
return False
|
|
195
|
+
return INSTALL_DIR.is_dir() and any(
|
|
196
|
+
part and _same_path(part, str(INSTALL_DIR.absolute())) for part in value.split(os.pathsep)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def refresh_claude_pane() -> None:
|
|
201
|
+
"""Re-copy an enabled pane whose files differ from this build's, e.g. after an app upgrade."""
|
|
202
|
+
if is_claude_pane_enabled() and not _installed_is_current():
|
|
203
|
+
_copy_pane()
|
|
@@ -314,6 +314,11 @@ async def run_tui(mock: bool, interval: int, force_group: int | None = None) ->
|
|
|
314
314
|
|
|
315
315
|
|
|
316
316
|
def main() -> None:
|
|
317
|
+
if sys.argv[1:2] == ["status"]:
|
|
318
|
+
import usage_cli
|
|
319
|
+
|
|
320
|
+
usage_cli.main()
|
|
321
|
+
return
|
|
317
322
|
_setup_logging()
|
|
318
323
|
args = parse_args()
|
|
319
324
|
if args.doctor:
|