fix: Windows Claude quota via ~/.claude.json fallback, ASCII hook paths#78
Conversation
- usage_client: read cachedUsageUtilization from ~/.claude.json as a claude-json fallback source when no usage-status.json exists (Windows statusLine never fires due to a Claude Code regression) - session_hooks: normalize resume/terse/reminder hook commands to the canonical ~/.claude targets so settings never point into the project or bundle path (non-ASCII paths broke hook execution on Windows) - tests: align test_setup_hook.py with the normalize-to-target behavior Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Lines 937 to 940 in 2db61e1
When session resume is enabled with the new target-path command, this condition matches on every self_heal() invocation and rewrites the same value unconditionally. That causes a settings-file write and an additional migrate_resume_command self-heal log entry on every app startup, quickly crowding out useful repair history. Compare command with new_command before setting changed, as the other migration loops do.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| scan = menubar_state.history_source_scan() | ||
| if menubar_state.history_cache_needs_reload( | ||
| self._history_fingerprint, | ||
| scan.fingerprint, | ||
| has_cached_result=( | ||
| self._cached_history is not None and self._cached_projects is not None | ||
| ), | ||
| ): | ||
| self._cached_history = self._load_entries(scan) | ||
| self._cached_projects = ( | ||
| _mock_projects() | ||
| if self.mock | ||
| else menubar_state.project_rows_for_windows(self._cached_history.entries) | ||
| ) |
There was a problem hiding this comment.
Recompute time-window project rows without file changes
The cache only rebuilds project_rows_for_windows when the history-source fingerprint changes, but that function computes today/7-day/30-day membership from the current time (menubar_state.py:243-269). If the tray stays running across midnight or an entry ages out of a rolling window while no transcript file is modified, the cached projects, projects_7d, and projects_30d remain stale until unrelated history activity or a restart.
Useful? React with 👍 / 👎.
…tion _migrate_resume_command_if_needed() flagged already-migrated commands as needing migration again (old_target now equals new_command's own target), writing a duplicate selfHealLog entry on every self_heal() run. Add the missing command == new_command guard and broaden the match to _RESUME_MARKERS so legacy source-path commands are still caught. Also fix the log detail direction, which described migrating away from the canonical target instead of toward it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Summary
usage_client.pynow readscachedUsageUtilizationfrom~/.claude.jsonas aclaude-jsonfallback source when nousage-status.jsonexists. On Windows the statusLine hook never fires due to a Claude Code regression, so this is the only way to surface Claude quota there.session_hooks.pyself-heal now normalizes the resume / terse / terse-reminder hook commands to their canonical~/.claude/targets instead of pointing into the project or app-bundle source path. Non-ASCII (CJK) project paths broke hook execution on Windows.test_setup_hook.pyaligned with the normalize-to-target behavior.Test plan
ruff checkcleanmypy .clean_read_claude_json_snapshot()on a real Windows~/.claude.json(weekly 99% surfaced,data_source="claude-json")🤖 Generated with Claude Code