Installation

July 24, 2026 · View on GitHub

Distribution channels

cctally ships through three channels. They land identical functionality; pick the one that matches your environment.

Every release ships to an opt-in beta channel first and is promoted to stable once it proves out (Homebrew tracks stable only). To follow the newest builds as they land, opt in with cctally config set update.channel beta, and flip back with cctally config set update.channel stable. See Beta channel for the full behavior.

Homebrew tap

brew install omrikais/cctally/cctally

The formula installs python@3.13 if it's not already present and pins cctally's shebang to that keg, so the tool keeps working even if your system Python changes. Symlinks cctally and the user-facing wrappers (cctally-tui, cctally-dashboard, cctally-forecast, …) into /opt/homebrew/bin/ (Apple Silicon) or /usr/local/bin/ (Intel/Linuxbrew).

After brew install, run cctally setup once to register Claude Code hooks and bootstrap the local SQLite cache.

npm

npm install -g cctally

The package bundles bin/cctally (the Python script) and the dashboard static assets. The cctally command on PATH is a ~30-line Node shim that resolves python3 and execs the bundled script. Windows is not supported — use WSL or a native Linux/macOS environment.

If you have a custom Python install, set CCTALLY_PYTHON:

export CCTALLY_PYTHON=/opt/homebrew/bin/python3.13

The Node shim needs a python3 on your PATH. If cctally setup reports python3 not found, install Python (brew install python on macOS) and re-run, or point CCTALLY_PYTHON at your interpreter.

From source

git clone https://github.com/omrikais/cctally
cd cctally
./bin/cctally setup

Useful when you want to run unreleased commits or iterate on contributions. setup symlinks bin/cctally* into ~/.local/bin/.

Migrating from the status-line snippet

If you already wired cctally record-usage into ~/.claude/statusline-command.sh, you don't have to do anything; it keeps working. To switch to the new hook-based path, run cctally setup. The legacy snippet will be detected and you'll be told it's safe to remove (we don't touch your file).

Migrating from an earlier install pattern

If you previously wired cctally into Claude Code via hand-installed scripts under ~/.claude/hooks/ (e.g. record-usage-stop.py, usage-poller-{start,stop}.py, usage-poller.py), cctally setup will detect them and offer to migrate: unwire the matching settings.json entries, move the files to a timestamped backup directory under ~/.claude/, and best-effort stop any active background daemon. See Migrating from a prior install pattern for the details and the new --migrate-legacy-hooks / --no-migrate-legacy-hooks flags.

Requirements

  • Python 3.11+ (stdlib only, no pip install needed).
  • macOS or Linux. Tested primarily on macOS (zsh).
  • Claude Code installed and run at least once (~/.claude/ must exist).

Install

git clone https://github.com/omrikais/cctally
cd cctally
./bin/cctally setup

cctally setup will:

  • Symlink the user-facing binaries into ~/.local/bin/
  • Add three hook entries (PostToolBatch, Stop, SubagentStop) to ~/.claude/settings.json (additive: it never modifies your existing entries)
  • Bootstrap the local SQLite cache and (if you've authenticated with Claude) fetch the first usage snapshot

If ~/.local/bin isn't on your PATH yet, setup will print the line to add to your shell rc.

Using cctally before (or without) setup

You don't have to run cctally setup to get value from cctally. The reporting commands read your ~/.claude session logs (and the local cache) directly, so they work immediately after an npm/npx or source install:

npx cctally daily          # cost-by-day, no setup required
npx cctally dashboard      # live web dashboard
npx cctally tui            # terminal dashboard

(After a global npm install — or a source checkout whose bin/ is on your PATH — drop the npx and just run cctally daily.)

What setup adds is auto-recording: the live status-line quota percentage and the three hooks that keep data flowing as you work, plus the first-run cache bootstrap. Run it once you want continuous tracking rather than on-demand reports. On a large session history that first-run cache sync now streams live progress to the terminal, so a multi-second cold sync no longer looks hung.

Verify

cctally setup --status
cctally daily
cctally dashboard

Uninstall

cctally setup --uninstall            # remove hooks + symlinks; keep history
cctally setup --uninstall --purge    # also wipe ~/.local/share/cctally/

Optional: opt-in status-line integration (no OAuth API calls)

If you'd rather have your existing status line feed cctally directly (and avoid the OAuth API roundtrips that the hook path makes once per ~30s), see docs/commands/record-usage.md. The two paths are not mutually exclusive; both go through the same record-usage funnel and dedupe correctly.