claude-reset
v1.3.0
Published
Background monitor for Claude Code usage limits with desktop or Slack notifications
Maintainers
Readme
claude-reset
A background monitor that watches your Claude Code usage limits and notifies you — on your desktop, or in Slack — the moment your session resets, so you don't have to keep refreshing the settings page.
Run multiple Claude accounts? claude-reset watches all of them at once and tags every notification with the account name — so it doesn't matter how you switch your active session (cswap, manual re-login, etc.); the monitor tracks each account independently.
How it works
Claude enforces two rolling usage caps shared across the CLI and web UI:
- 5-hour window — short-term rate limit
- 7-day window — weekly cap
claude-reset polls a private Anthropic endpoint every few minutes. It detects a reset when the
resets_at timestamp jumps forward well past the poll interval (at least an hour, and more on
a long interval) — the unambiguous signal that Anthropic issued a fresh window. (Minor
timestamp jitter and occasional epoch/1970 glitches from the API are filtered out so they
can't trigger a false alarm.)
When a reset is detected it notifies you exactly once — on your desktop, in Slack, or both, depending on your config. A Slack notification reaches your phone like any other message, with no need to keep Slack web open.
What you see in the terminal while it runs:
[2026-05-21T10:00:00Z] claude-reset started — polling every 5 min — watching 2 account(s): work, personal
[2026-05-21T10:00:00Z] [work] 5h: 72% (resets 5/21/26, 4:45 PM) | 7d: 31% (resets 5/28/26, 2:05 PM)
[2026-05-21T10:00:00Z] [personal] 5h: 12% (resets 5/21/26, 1:10 PM) | 7d: 8% (resets 5/27/26, 9:00 AM)
[2026-05-21T16:46:00Z] [work] RESET DETECTED — 5-hour window. Sending notification.Prerequisites
- Node.js ≥ 18 — download here
- A Claude Pro/Max account with an active browser session
- (optional) A Slack Incoming Webhook URL — create one here (free, 2 min). Without it, notifications go to your desktop (native OS notification) instead.
Installation
The fastest way — install globally so the claude-reset command works from anywhere:
npm install -g claude-reset
# or straight from GitHub:
npm install -g github:nazarli-shabnam/claude-resetOr work from a clone:
git clone https://github.com/nazarli-shabnam/claude-reset.git
cd claude-reset
npm install # runs the build automatically (via the `prepare` script)
npm install -g . # optional: expose the global `claude-reset` commandUsing Bun instead?
bun installworks the same way — it also runs thepreparebuild. Then usebun run start/bun run devin place of thenpmequivalents.
Because the prepare script builds dist/ on install, the global claude-reset
command works immediately — no separate build step needed.
Signing in
The tool authenticates as your browser does — with the sessionKey cookie from a logged-in
claude.ai session. There are two ways to hand it over.
Browser login (recommended) — claude-reset init, add-account, and login can open a
browser window for you:
claude-reset login # opens claude.ai, waits for you to sign in, captures the key
claude-reset login --account workSign in normally (password or Google/SSO). Once you're in, the window closes and the key is
saved. The login is remembered in a dedicated browser profile beside your config, so a later
login (e.g. after the key expires) is usually one click. Needs Chrome or Edge installed; set
CHROME_PATH if it's somewhere unusual.
Manual paste — pick this at the wizard's first prompt if you'd rather not use the browser helper:
- Open claude.ai → F12 → Application tab → Cookies →
https://claude.ai - Copy the value of the
sessionKeycookie
The session key is equivalent to your password. Never share it or commit it to git.
Either way, the organization UUID is auto-detected from the key — you don't need to find it.
Why not "Sign in with Anthropic"? Anthropic's OAuth is locked to Claude Code and claude.ai — there's no third-party client registration and no device-code grant, and reusing Claude Code's own token from another tool is against their credential-use policy (and actively blocked). Driving a real browser login is the sanctioned path, so that's what this does.
Setup
Run the interactive wizard once:
claude-reset init
# or without global install:
node dist/index.js initYour config is saved to ~/.config/claude-reset/config.json (Windows: %USERPROFILE%\.config\claude-reset\config.json) with owner-only read permissions. Setup only runs once — future starts read the file silently. If your session key expires (you'll see a 401/403 in the logs) run claude-reset login to refresh it; re-run init only to change other settings.
Watching more than one account
init configures your first account. Add others with add-account:
claude-reset add-account # asks to log in via browser, or paste a key; org_id is auto-detected
claude-reset accounts # list configured accounts
claude-reset remove-account workEach account needs its own claude.ai session — add-account and
claude-reset login --account <name> sign you in to it (see Signing in above); the org UUID
is detected automatically. Account-switchers like
cswap rotate Claude Code's OAuth tokens, which are
a different credential from the sessionKey cookie this tool uses, so they can't be reused
here. Notification settings and the check interval are shared across all accounts.
Verify it works:
claude-reset status Claude usage snapshot
work
5-hour: 72% → resets 5/21/26, 4:45 PM
7-day: 31% → resets 5/28/26, 2:05 PM
personal
5-hour: 12% → resets 5/21/26, 1:10 PM
7-day: 8% → resets 5/27/26, 9:00 AMRunning the monitor
| Command | What it does |
|---|---|
| claude-reset start | Start in background — silent, writes to log file |
| claude-reset start --logs | Start in terminal with live log output |
| claude-reset stop | Stop the background process |
| claude-reset logs | Tail the log file live (Ctrl+C to exit) |
| claude-reset status | One-shot usage snapshot for every account — current utilization and reset times |
| claude-reset pulse | Is the account being used right now? Plus 5h/7d utilization and the Opus/Sonnet split. Add --json for scripting |
| claude-reset dashboard | Every account in one view — utilization, reset times, model split, live-activity dot, and the full limits[] breakdown the settings page collapses. --json for the raw payload |
| claude-reset timeline | In-use / idle intervals and window resets, reconstructed from the activity log. --account <name>, --days N (default 7), --json |
| claude-reset test-notify | Send a test message through every configured channel (desktop and/or Slack) |
| claude-reset add-account | Add another Claude account to monitor |
| claude-reset remove-account <name> | Remove an account by name |
| claude-reset accounts | List configured accounts |
| claude-reset login [--account <name>] | Sign in via a browser window; captures the session key for you |
| claude-reset init | Re-run setup to update credentials or settings |
Auto-start on login (Windows)
Startup folder (simplest):
- Press Win + R → type
shell:startup→ Enter - Right-click → New → Shortcut
- Location:
node C:\Users\YourName\projects\claude-reset\dist\index.js start
Task Scheduler (more reliable, survives crashes):
$action = New-ScheduledTaskAction -Execute "node" -Argument "C:\Users\$env:USERNAME\projects\claude-reset\dist\index.js start"
$trigger = New-ScheduledTaskTrigger -AtLogOn
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 0
Register-ScheduledTask -TaskName "claude-reset" -Action $action -Trigger $trigger -Settings $settingsmacOS (runs in background, auto-restarts):
# Create ~/Library/LaunchAgents/com.claude-reset.plist
# See full plist template in the wiki
launchctl load ~/Library/LaunchAgents/com.claude-reset.plistLinux (systemd):
# Create ~/.config/systemd/user/claude-reset.service
# ExecStart=/usr/local/bin/node /path/to/dist/index.js start
systemctl --user enable --now claude-resetStopping the monitor
# If started with --logs (terminal)
Ctrl + C
# If running in background
claude-reset stop
# Remove Task Scheduler auto-start entry permanently
Unregister-ScheduledTask -TaskName "claude-reset" -Confirm:$falseActivity pulse
claude-reset pulse shows whether the account is in active use at this moment, alongside its
5-hour / 7-day utilization and the per-model split:
default — ● active now
5-hour: 38% 7-day: 13%
models: Opus — Sonnet 1%The running monitor also notifies you once each time the account flips from idle to active
— useful on a shared account to know when someone has started working — and records every
idle↔active flip and reset to an activity log you can read back with claude-reset timeline.
Hard limitation — read this. Because everyone signs into a single shared account, Anthropic exposes no per-person data.
pulsetells you that the account is being used and how much aggregate capacity is consumed — it cannot tell you who is using it, how many people are on it, or whether it's Claude Code (CLI) vs the web app. That data is simply not in the API for a shared account (the private endpoints that would list active sessions/devices don't exist or aren't readable). For true per-member visibility you need separate Team/Enterprise seats.
Configuration
~/.config/claude-reset/config.json
{
"accounts": [
{ "name": "work", "session_key": "sk-ant-sid01-...", "org_id": "..." },
{ "name": "personal", "session_key": "sk-ant-sid01-...", "org_id": "..." }
],
"slack_webhook_url": "https://hooks.slack.com/services/...",
"check_interval_minutes": 15,
"notifications": { "desktop": true, "slack": true, "digest": "off" }
}| Field | Description | Default |
|---|---|---|
| accounts[].name | Label shown in logs and notifications | required |
| accounts[].session_key | sk-ant-sid01-... cookie value for that account | required |
| accounts[].org_id | Claude organization UUID for that account | auto-detected during setup |
| slack_webhook_url | Slack Incoming Webhook URL (shared by all accounts) | optional |
| check_interval_minutes | How often to poll | 15 |
| notifications.desktop | Send a native OS desktop notification | true |
| notifications.slack | Post to Slack (needs slack_webhook_url) | true when a webhook is set |
| notifications.digest | "daily" sends a once-a-day dashboard rollup through the configured channels | "off" |
At least one channel must be enabled. Desktop notifications use the OS's built-in
mechanism — Windows toast, macOS Notification Center, or notify-send on Linux — with
no extra dependency; a missing Linux notify-send is logged as a warning, not fatal.
Upgrading from a single-account version? Old configs with top-level
session_keyandorg_idare migrated automatically into a single account nameddefault— no action needed.
Adding notification channels
Every notifier implements one interface from src/types.ts:
export interface Notifier {
notify(message: string, context?: NotificationContext): Promise<void>;
}SlackNotifier and DesktopNotifier in src/notifier.ts are worked reference
implementations. A WhatsApp stub is also there. To activate it: uncomment WhatsAppNotifier, fill in the Twilio/Meta Cloud API call, add credentials to the config, and push it into the notifiers array in src/index.ts. The BroadcastNotifier fans out to all channels simultaneously.
Troubleshooting
| Error | Fix |
|---|---|
| Auth rejected (HTTP 401) | Session key expired — run claude-reset login (or login --account <name>) to refresh it |
| Config not found | Run claude-reset init first |
| Notifications never fire | Run claude-reset test-notify to check every configured channel. If that works but resets still don't notify, run claude-reset logs to confirm the monitor is running and polling. |
| node: command not found | Node.js isn't installed or not on PATH — download here |
Testing
The test suite runs on Bun (the tests import Bun's built-in runner):
bun test
# or: npm test — this first checks that Bun is installed and prints an
# install hint if it isn't, then delegates to `bun test`.It covers the reset-detection state machine, config load/save (including malformed and
BOM-prefixed files, migration, org_id backfill), the notifier fan-out (Slack, desktop,
broadcast), the browser-capture helpers, the activity-timeline logic, the dashboard formatter,
and the usage-API client's error handling — all without network access. Tests use the
CLAUDE_RESET_CONFIG_DIR environment variable to point file I/O at a temp directory, so they
never touch your real ~/.config/claude-reset.
Project structure
src/
types.ts Shared interfaces — UsageResponse, Account, WatcherConfig, Notifier
auth/
browserCapture.ts Drive Chrome/Edge to the claude.ai login page, capture the sessionKey
config.ts Config file read/write, org_id backfill, account management, wizards
claudeClient.ts HTTP fetch to the private Anthropic usage endpoint
pulse.ts Pure helpers — summarize usage into an activity pulse, detect idle→active
history.ts Activity timeline — append/read JSONL, pair active↔idle into intervals
dashboard.ts Pure formatter — every account + raw limits[] in one text block
notifier.ts SlackNotifier, DesktopNotifier, BroadcastNotifier, WhatsApp stub
monitor.ts Per-account polling loop + reset-detection state machine + daily digest
index.ts CLI entry point — init / login / start / status / pulse / dashboard / timeline / …License
MIT
