Skip to main content

Push alerts when your Claude Code subscription usage crosses a limit.

Project description

ccwatch

ccwatch — watches your Claude Code usage for you. Pacing and checkpoint alerts pushed to Telegram, Discord, and Slack on your phone.

ccwatch keeps an eye on your Claude Code usage so you don't have to.

Mid-session you start wondering how much of your weekly limit you've burned, and the only way to know is to stop and check /usage (or through the claude app / website in settings, manually). ccwatch watches it for you and pings your phone (or desktop, or a channel) as you cross each mark (10%, 25%, 50%, 75%, 90%, 100%), so you always have a feel for what's left, plus a heads-up like "at this pace you'll hit your weekly limit around 4pm" before you actually do.

  • No Python dependencies. Pure standard library, so pipx install ccwatch pulls nothing else (it does need two system tools at runtime: tmux and the claude CLI).
  • Many channels. Telegram, Discord, Slack, ntfy, generic webhook, desktop notifications. Enable any combination.
  • Pacing. Linear burn-rate projection: know before you run out.
  • Usage history. Every reading is timestamped and logged to a local SQLite database — a record of your Claude Code usage over time, with optional daily/weekly summaries and sparklines.

ccusage vs ccwatch. ccusage reads token cost from your local logs. ccwatch watches your actual subscription limit % (the session/weekly windows shown in /usage, which aren't in the logs) and pushes you alerts. They're complementary.


How it works

Claude Code doesn't expose usage over an API, but it renders it in the /usage TUI panel. ccwatch runs a dedicated, throwaway Claude Code session in a tmux pane, sends it /usage on a schedule, and scrapes the rendered percentages. /usage only displays your usage rather than prompting the model, so the probe's token footprint is negligibleAnthropic notes commands like /usage make only tiny background status checks.

ccwatch ──tmux send-keys "/usage"──▶ [dedicated claude session]
        ◀──tmux capture-pane──────── (rendered /usage panel)
        ──parse %──▶ checkpoints / pacing / history ──▶ Telegram / Discord / …

Because the session and weekly limits are account-global, reading them from one probe gives your true usage, so there's no need to watch your real working sessions. See docs/how-it-works.md for the parser, tuning, and the design trade-offs.

Install

pipx install ccwatch        # or: pip install ccwatch

Requirements: Python 3.11+, the claude CLI on your PATH (logged in), and tmux (ccwatch drives Claude Code through a tmux session). tmux is a one-line install:

brew install tmux            # macOS
sudo apt install tmux        # Debian / Ubuntu
sudo dnf install tmux        # Fedora
sudo pacman -S tmux          # Arch
# Windows: run ccwatch under WSL, then sudo apt install tmux

(ccwatch doctor checks for tmux and prints the right command for your system if it's missing.)

From source:

git clone https://github.com/richykim7/ccwatch && cd ccwatch
pip install -e .

Quick start

ccwatch setup     # interactive: pick channels, link them, send a live test, write config
ccwatch start     # starts watching in the background (offered at the end of setup too)

ccwatch start keeps watching after you close the terminal; ccwatch stop ends it. That's the whole flow on a laptop — no systemd, no extra setup.

ccwatch setup walks you through each notifier (creating a Telegram bot, pasting a Discord/Slack webhook, choosing an ntfy topic…), sends a test message so you know it works, and writes ~/.ccwatch/config.toml for you.

Prefer to wire it up by hand? See docs/notifiers.md for step-by-step instructions per channel. The smallest setup is just two env vars: ccwatch runs with only TG_BOT_TOKEN + TG_CHAT_ID set, no config file needed.

Keeping it running

ccwatch start is all most people need: it watches in the background — a detached tmux session — so you can close the terminal or disconnect SSH and it keeps going. You never have to reattach (attaching only views the logs), and there's only ever one session: a singleton guard makes a repeat ccwatch start a no-op, and if it exits the session cleans itself up, so you won't pile up empty sessions. Stop it with ccwatch stop, and tmux attach -t ccwatch to watch live. It survives terminal close and SSH drops, but not a reboot (tmux sessions live in memory).

For more than that — restart-on-crash, survive reboots, run headless — pick one:

Start it automatically

  • macOS: the launchd agent (com.ccwatch.plist) starts ccwatch at login via RunAtLoad.
  • Linux: install the systemd user service (ccwatch.service) and run loginctl enable-linger, so it starts at boot and keeps running after you log out.
  • With Claude Code (one command): run ccwatch hook install. It adds a SessionStart hook to ~/.claude/settings.json so ccwatch auto-starts whenever you open Claude Code (idempotent; it no-ops if already running). It's silent so it won't clutter your Claude session, and ccwatch hook uninstall removes it cleanly.

Running it 24/7

A laptop only watches while it's awake; closing the lid suspends everything, tmux included. That's usually fine, since you only spend Claude usage while you're working (i.e. while the machine is awake). For true around-the-clock monitoring, run ccwatch on an always-on machine: a server, VPS, Raspberry Pi, or a cloud VM. On an always-on VM, ccwatch start is ideal: it keeps running after you disconnect SSH and watches continuously for as long as the VM is up. (Add the systemd unit too if you want it to survive VM reboots.)

Commands

  • ccwatch setup: interactive wizard to link & test notifiers and write the config.
  • ccwatch start: start watching in the background (survives closing the terminal).
  • ccwatch stop: stop the background watcher.
  • ccwatch settings [get KEY | set KEY VALUE]: list, read, or change config values (e.g. ccwatch settings set poll.interval 900).
  • ccwatch hook install|uninstall|status: auto-start ccwatch when you open Claude Code.
  • ccwatch once: one poll → notify cycle and exit (for cron / systemd timers).
  • ccwatch peek: dump the raw /usage pane and parsed readings (use this to tune the parser).
  • ccwatch selftest [--notifier X]: send a test message through your notifiers.
  • ccwatch get-chat-id: list Telegram chat ids that have messaged your bot.
  • ccwatch status [--live]: current usage as colored bars + pacing, at a glance.
  • ccwatch history [--days N]: recent readings as sparklines.
  • ccwatch digest [--daily|--weekly] [--send]: compose a summary now.
  • ccwatch doctor: check tmux / claude / config / notifiers.

Global: --config PATH, --dry-run (route every notification to the log instead of sending, great for trying it out).

Configuration

Settings live in ~/.ccwatch/config.toml (or any path you pass with --config PATH). Change values with ccwatch settings set KEY VALUE or by editing the file directly (comments are preserved either way), then restart the daemon for it to take effect (ccwatch stop && ccwatch start, or restart your service). Config is read once at startup, not live.

Everything is optional and has a default; config.example.toml is the full annotated reference. A minimal config is just one notifier:

[[notifiers]]
type = "telegram"
token = "123456:ABC..."        # your bot token (this file is local, chmod 600)
chats = ["987654321"]          # your chat id

# add as many as you like:
# [[notifiers]]
# type = "discord"
# webhook = "https://discord.com/api/webhooks/..."

Any value can also be written as "env:NAME" to read it from an environment variable instead, which is useful only if you keep your config inside a repo (see Caveats).

Per-section checkpoint thresholds and message wording are configurable; pacing, quiet hours, history, digests, and presentation ([display]) each have their own [section] in the file. [display] controls the message tone (style = "terse" or "cheery" for upbeat, motivational messages), whether to add a usage bar to alert bodies (bars), channel-native severity, and terminal color.

For how to obtain each channel's token/webhook/topic, see docs/notifiers.md, or just run ccwatch setup.

Caveats

  • The /usage panel is scraped, so the parser is layout-dependent. If a Claude Code update changes the panel, run ccwatch peek and adjust the regexes in parse.py. The percentage is approximate (rounded); the reset time is scraped from the same panel.
  • The probe runs with --dangerously-skip-permissions (yolo) so it can boot unattended. It only ever receives /usage, but understand what that flag means before enabling it; set yolo = false to require manual trust.
  • Don't commit secrets to git. ccwatch setup keeps your token in ~/.ccwatch/config.toml (outside any repo, chmod 600), so by default there's nothing to do. Only if you keep your config inside a repo (e.g. dotfiles) should you switch to env: indirection, so the committed file holds a pointer rather than the secret itself.

Development & testing

PYTHONPATH=src python3 -m unittest discover -s tests

The suite has no third-party Python dependencies and makes no external network calls: notifier payloads are verified both against a fake transport and with real urllib sends to a localhost server, a fake claude script exercises the full tmux probe path (send-keyscapture-pane → parse), and the setup wizard's config output is round-tripped back through the loader. See docs/testing.md for how to verify live delivery to each real channel.

Acknowledgements

ccwatch shells out to tmux (ISC license) and the Claude Code CLI. Neither is bundled or modified; ccwatch just invokes the copies you install. Thanks to both projects.

License

MIT. See LICENSE.


ccwatch is an independent project and is not affiliated with, endorsed by, or sponsored by Anthropic. "Claude" and "Claude Code" are trademarks of Anthropic, PBC; they are used here only to describe what ccwatch works with.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ccwatch-1.0.0.tar.gz (57.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ccwatch-1.0.0-py3-none-any.whl (48.2 kB view details)

Uploaded Python 3

File details

Details for the file ccwatch-1.0.0.tar.gz.

File metadata

  • Download URL: ccwatch-1.0.0.tar.gz
  • Upload date:
  • Size: 57.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ccwatch-1.0.0.tar.gz
Algorithm Hash digest
SHA256 6133e52335ef7ae3a90037822425986b54d255178c6fe2ca8f81cdab3a3476c6
MD5 78d202cd278ef9e56ded0476605a53d7
BLAKE2b-256 2728b36dc4b3e95cc98bab14ef8436411d00a09dff0b4a90661674166a96a309

See more details on using hashes here.

Provenance

The following attestation bundles were made for ccwatch-1.0.0.tar.gz:

Publisher: release.yml on richykim7/ccwatch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ccwatch-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: ccwatch-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 48.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ccwatch-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3810ec2b182ca51e566f30005ec8f5a4454c8daff57be488900a515b3f6f4018
MD5 e1593d890c903e8186d62213c72211df
BLAKE2b-256 06a85559bedcd89ac7f84a1e6210a2e7ae68e716c68b4faf69bafb5b6ebbc3d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for ccwatch-1.0.0-py3-none-any.whl:

Publisher: release.yml on richykim7/ccwatch

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page