Metadata-Version: 2.4
Name: ccwatch
Version: 1.0.0
Summary: Push alerts when your Claude Code subscription usage crosses a limit.
Author: ccwatch contributors
License: MIT
Project-URL: Homepage, https://github.com/richykim7/ccwatch
Project-URL: Issues, https://github.com/richykim7/ccwatch/issues
Keywords: claude,claude-code,anthropic,usage,rate-limit,notifications,telegram
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# ccwatch

<p align="center">
  <img src="docs/media/hero.png" alt="ccwatch — watches your Claude Code usage for you. Pacing and checkpoint alerts pushed to Telegram, Discord, and Slack on your phone." width="100%">
</p>

**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](https://ntfy.sh), 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`](https://github.com/ryoppippi/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 negligible** — [Anthropic notes commands like `/usage`
make only tiny background status checks](https://code.claude.com/docs/en/costs#background-token-usage).

```
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`](docs/how-it-works.md) for the parser, tuning, and the
design trade-offs.

## Install

```bash
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:

```bash
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:

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

## Quick start

```bash
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](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:
- **systemd** (Linux): [`packaging/systemd/ccwatch.service`](packaging/systemd/ccwatch.service). Survives reboot and restarts on crash.
- **launchd** (macOS): [`packaging/launchd/com.ccwatch.plist`](packaging/launchd/com.ccwatch.plist). Same, plus it starts at login.
- **cron / timer:** schedule `ccwatch once` instead of a long-running daemon.
- **Docker:** [`packaging/docker/Dockerfile`](packaging/docker/Dockerfile) (note the auth caveats inside).

### Start it automatically

- **macOS:** the launchd agent ([`com.ccwatch.plist`](packaging/launchd/com.ccwatch.plist)) starts ccwatch at login via `RunAtLoad`.
- **Linux:** install the systemd user service ([`ccwatch.service`](packaging/systemd/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](https://code.claude.com/docs/en/hooks-guide) 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`](config.example.toml)
is the full annotated reference. A minimal config is just one notifier:

```toml
[[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](#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](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

```bash
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-keys` → `capture-pane` → parse), and the setup wizard's
config output is round-tripped back through the loader. See
[`docs/testing.md`](docs/testing.md) for how to verify live delivery to each real
channel.

## Acknowledgements

ccwatch shells out to **[tmux](https://github.com/tmux/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](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.

