Clawmeter browser extension
Reads Claude reset grants from claude.ai and API credits from the Claude Console with your browser session and sends them to Clawmeter on this computer, once a minute.
claude.ai answers 403 to requests from the extension's background worker, so background.js runs the claude.ai read inside each open claude.ai tab, in an isolated script world, and falls back to the worker when no tab answers. Console reads run in each open Console tab and always once in the worker, which has the browser's main session, so a signed-out container tab cannot hide a signed-in main session. Each cached Console organization records when another session, such as a container signed in to another account, last listed it. An organization only the main session holds is dropped as soon as the main session answers without it. One another session listed in the past week is kept, because that session's tab may just be closed, and while any such organization is cached the extension does not tell Clawmeter that the Console is signed out. A tab that lists the same organizations as the main session counts as the main session. The popup says when a tab did not answer, since accounts signed in only there are missing from that reading. Its warnings carry the action that clears them. The toolbar icon turns grey while the Clawmeter app can't be reached, and shows an orange "!" only after Clawmeter has refused this browser's readings in three checks in a row. A check that sends Clawmeter nothing keeps the icon and badge the last one set, since it learned nothing about the app. A closed claude.ai tab or a sign-out is shown in the popup only: reset grants change rarely, and the tray shows how old each reading is. A reply that carries Clawmeter-Reading: ignored means Clawmeter does not track that account. Tabs in different browser containers can hold different accounts' sessions, so every tab is read; ordinary tabs share one session, and an organization seen in one tab is not read again.
resets.js reads reset grants and posts them to /v1/resets. It also reads each organization's plan link state from claude.ai at most once an hour, and sends the next monthly API credit date when the plan is linked to a Console organization.
console.js reads prepaid API credits and posts them to /v1/api-credits.
popup.html shows the latest check: whether Clawmeter received it, what each source returned, and links to the pages that fix a problem. background.js keeps that check in session storage, so names never reach the disk.
- The receiver is
internal/claudeweb/extension.go. It admits only the extension IDs in ExtensionOrigins; the manifest key fixes the unpacked ID.
- Every OS user's browser reaches the same loopback port, so the receiver pairs with one extension folder. Clawmeter writes a token to
pairing.json in the folder it installs and keeps it across reinstalls (internal/browserext); the extension sends it as Clawmeter-Token, and the receiver checks it against the same file (internal/claudeweb/pairing.go). A wrong token gets 401, which the extension shows as another user's Clawmeter. A reading with no token is accepted until the first paired one arrives, so a browser still running an older copy keeps working. A copy loaded from this source tree has no pairing.json; once Clawmeter is paired, copy that file in from the installed folder.
Run the tests with node --test extension/*.test.js. go test ./internal/claudeweb also runs both readers in Node and posts their output to the Go receiver.
make extension-zip builds the Chrome Web Store upload; see docs/chrome-web-store.md.