Skip to content

Permanent Claude 0/0 fix: Firefox cookies + honest fallback + /health#33

Merged
BlockedPath merged 1 commit into
mainfrom
fix/claude-permanent-firefox
May 22, 2026
Merged

Permanent Claude 0/0 fix: Firefox cookies + honest fallback + /health#33
BlockedPath merged 1 commit into
mainfrom
fix/claude-permanent-firefox

Conversation

@BlockedPath

Copy link
Copy Markdown
Owner

Why

Three rounds of "0/0 on the iPhone" all traced to the same architecture:
the AppleScript-Chrome scrape was a single point of failure (Chrome can
silently disable "Allow JavaScript from Apple Events" on update), and
when it broke the daemon fell through to a token-count fallback that
reported 0% any time you exceeded the hardcoded 200k/1M budget. The user
couldn't tell "daemon down" from "limit hit."

This PR is the permanent fix.

What changed

  • New scripts/claude-plan-usage-firefox.py — reads sessionKey from
    Firefox's unencrypted cookies.sqlite and calls
    https://claude.ai/api/organizations/{org}/usage directly. No
    AppleScript, no DOM scrape; immune to page-layout changes and the
    Chrome preference. Writes a health side-file so /health can surface
    the last scrape outcome. Setup is one-time: ./scripts/claude-plan-usage-firefox.py login.
  • LaunchAgent + install.sh switched to the Firefox script as primary.
    The Chrome AppleScript script stays for manual fallback only.
  • Honest fallback in the daemon — when every fresh source fails, return
    the last cached claude-plan-usage.json percentages with ok=False
    and status "stale Nh" instead of the misleading token-budget 0/0.
    The token-count path is no longer reachable for the Claude provider.
  • /health endpoint exposes per-source freshness, last scrape result,
    and the snapshot the daemon is currently serving.
  • CLAUDE.md is the new project runbook: documents every failure
    mode I've debugged in this thread (Firefox session expired, daemon
    running stale code after pull, LaunchAgent dead, claude.ai page change,
    Chrome preference disabled, mDNS name collision) with the exact
    /health signature and the commands to fix each.

Verified live

$ curl -s http://localhost:9596/usage
{"s":63,"sr":66,"w":73,"wr":476,"st":"5h 37% used · 7d 27% used","ok":true,...}

$ curl -s http://localhost:9596/health | jq .sources.plan_usage
{ "path": ".../claude-plan-usage.json", "exists": true, "age_seconds": 8, "fresh": true }

Test plan

  • ruff check daemon/ scripts/ clean
  • pytest -q (11 passed)
  • Restart claude daemon → /usage serves real percentages from Firefox-cookie scrape
  • /health reports sources.plan_usage.fresh: true and current snapshot ok: true
  • iOS app shows non-zero values after next 30 s poll
  • After Firefox session expires, daemon serves last-known with ok: false and status: "stale Xh" instead of 0/0

🤖 Generated with Claude Code

The recurring 0/0 came from a chain of single points of failure: the
AppleScript-Chrome scrape depended on Chrome's "Allow JavaScript from
Apple Events" preference (which Chrome can silently disable on
update), and when the scrape inevitably broke the daemon dropped to a
token-count fallback that reported 0% any time the user exceeded the
hardcoded 200k/1M budget. The user couldn't tell daemon-down from
limit-hit.

This commit removes both failure modes:

- New scripts/claude-plan-usage-firefox.py reads sessionKey from
  Firefox's unencrypted cookies.sqlite and calls claude.ai/api/.../usage
  directly. No AppleScript, no DOM scrape, immune to page-layout
  changes and the Chrome preference. Writes a health side-file so /health
  can surface the last scrape outcome.

- install.sh and the running LaunchAgent now point at the Firefox script
  as primary. The old Chrome AppleScript script stays in the repo as a
  manual fallback.

- Daemon's Claude fallback is now honest: when every fresh source fails,
  it returns the last cached plan-usage percentages with ok=False and
  status "stale Nh" instead of the misleading token-budget 0/0. The
  token-count path is no longer reachable for the Claude provider.

- New /health endpoint exposes per-source freshness, last scrape
  result, and the snapshot the daemon is currently serving — one
  curl tells you what's wrong.

- CLAUDE.md is the new project memory / runbook: documents every
  failure mode we've already debugged with the exact /health output and
  commands to fix each.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@BlockedPath
BlockedPath merged commit 1887a36 into main May 22, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant