Metadata-Version: 2.4
Name: tce-monitor
Version: 0.4.0
Summary: Terminus Cancrorum Est — monitor Claude Code processes, token usage, and costs
Project-URL: Homepage, https://github.com/tmancino/Terminus-Cancrorum-Est
Project-URL: Repository, https://github.com/tmancino/Terminus-Cancrorum-Est
Project-URL: Issues, https://github.com/tmancino/Terminus-Cancrorum-Est/issues
Author-email: Tommy Mancino <tom.mancino@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: claude,claude-code,monitor,process-monitor,token-usage
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Environment :: MacOS X
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: fastapi>=0.115.0
Requires-Dist: jinja2>=3.1.0
Requires-Dist: psutil>=5.9.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pywebview>=5.0; sys_platform == 'darwin'
Requires-Dist: rumps>=0.4.0; sys_platform == 'darwin'
Requires-Dist: uvicorn>=0.30.0
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# TCE -  Terminus Cancrorum Est

<p align="center">
  <strong><em>"The End of the Crab"</em></strong>
</p>

<p align="center">
  A macOS menu bar app + web dashboard + CLI for monitoring Claude Code processes, token usage, and costs.
</p>

<p align="center">
  <a href="https://pypi.org/project/tce-monitor/"><img src="https://img.shields.io/pypi/v/tce-monitor?color=c4a7e7&style=flat-square" alt="PyPI"></a>
  <a href="https://pypi.org/project/tce-monitor/"><img src="https://img.shields.io/pypi/pyversions/tce-monitor?color=89b4fa&style=flat-square" alt="Python"></a>
  <a href="LICENSE"><img src="https://img.shields.io/github/license/tmancino/Terminus-Cancrorum-Est?color=a6e3a1&style=flat-square" alt="License"></a>
</p>

---

## The Problem

Running multiple concurrent Claude Code sessions across many projects leaves you blind:

- **No process visibility** — How many Claude sessions are running? Which are stuck?
- **Zombie and stale processes** — Forgotten sessions silently consume hundreds of MBs
- **Resource hogs** — Claude processes can spike to 75%+ of your system's CPU or memory
- **Token cost blindness** — Opus 4.5 costs $90/M output tokens. Costs compound invisibly across sessions.
- **No session history** — Which projects burned the most tokens today?

`tce` gives you real-time visibility into all of this from a single command, a menu bar icon, or a web dashboard.

## Install

```bash
pipx install tce-monitor
```

That's it. On macOS, this automatically includes the menu bar and native webview. On Linux, you get the CLI and web dashboard. Requires Python 3.11+.

To auto-start at login (macOS):

```bash
tce install
```

> **Don't have pipx?** Install it with `brew install pipx && pipx ensurepath` (macOS) or `pip3 install --user pipx` (any platform).

## Quick Start

```bash
# See all your Claude processes with CPU/memory usage
tce status

# Check how much you've spent on tokens
tce usage

# Kill all idle processes
tce kill-stale

# Kill a specific resource-heavy process
tce kill 12345

# Launch the web dashboard
tce dashboard

# Run menu bar app with live monitoring
tce run
```

---

## CLI Reference

| Command | Description |
|---------|-------------|
| `tce status` | Process health overview — PIDs, projects, memory, CPU, uptime, health status |
| `tce usage` | Token usage and costs — per-model breakdown with input, output, cache tokens |
| `tce sessions` | Recent session history — project, duration, tokens, lines changed, summary |
| `tce kill <PID>` | Kill a Claude process (SIGTERM). Add `--force` for SIGKILL |
| `tce kill-stale` | Find and kill all stale processes at once |
| `tce pin <PID>` | Pin a process — exempts it from stale detection |
| `tce unpin <PID>` | Remove pin from a process |
| `tce dashboard` | Start the web dashboard on `localhost:5111` and open in browser |
| `tce dashboard-stop` | Stop the running dashboard server |
| `tce run` | Full app — menu bar + dashboard (macOS) or dashboard-only (other platforms) |
| `tce install` | Install as macOS login service (auto-start at login via launchd) |
| `tce uninstall` | Remove macOS login service |

### Example Output

```
============================================================
 TERMINUS CANCRORUM EST — Process Status
============================================================
 Total: 7  |  Healthy: 4  |  Stale: 3  |  Zombie: 0  |  Pinned: 0
 Resource Alerts: 1  |  Total Memory: 3449 MB
============================================================
 [+] PID  17742  rpgmaster                      6 MB    0.0%     6.9h  healthy
 [!] PID  31230  crab-trap                    392 MB    0.0%     6.8h  stale
              terminal: /dev/ttys002
 [+] PID  41126  openclaw                     219 MB   82.5%     1.4h  healthy
              ⚠️  RESOURCE ALERT: CPU 82.5% of system
 [+] PID  59593  adventure-graph              953 MB    0.0%     2.3h  healthy
              terminal: /dev/ttys003
 [!] PID  85244  tweek-public                1167 MB    0.0%     6.1h  stale
              terminal: /dev/ttys007

 WARNING: 3 stale process(es) detected. Use 'tce kill-stale' to clean up.
 WARNING: 1 process(es) consuming excessive resources (>75% CPU or memory).
```

```
============================================================
 TERMINUS CANCRORUM EST — Token Usage & Costs
============================================================
 Total Cost: $22,248.66
 Total Sessions: 183
============================================================
 Model                     Input     Output   Cache Rd   Cache Cr         Cost
 -------------------- ---------- ---------- ---------- ---------- ------------
 Opus 4.5                   2.9M       8.0M       7.4B     460.4M $ 20,318.33
 Opus 4.6                 392.0K     365.9K     734.6M      41.2M $  1,906.99
 Sonnet 4.5                 4.4K        655      23.6M       2.7M $     17.26
 Haiku 4.5                  5.7K       6.5K      31.4M       3.5M $      6.07
 -------------------- ---------- ---------- ---------- ---------- ------------
 TOTAL                      3.3M       8.3M       8.2B            $ 22,248.66
```

---

## Web Dashboard

Start with `tce dashboard` and open `http://localhost:5111`.

### Features

**Processes Tab**
- Live process table with color-coded health dots (green/yellow/red/blue)
- PID, project name, memory, CPU%, uptime, child process count, terminal
- Resource usage: CPU and memory as % of total system (with alert indicators)
- One-click Kill, Force Kill, and Pin/Unpin buttons
- Status badge: "ALL HEALTHY", "STALE DETECTED", "ZOMBIE DETECTED", or "RESOURCE ALERTS"
- Auto-refreshes every 10 seconds

**Token Usage Tab**
- Cost breakdown by model with color-coded bars
- Stacked bar chart of daily token consumption (last 30 days) via Chart.js
- Detailed token table: input, output, cache read, cache creation per model
- Total cost prominently displayed

**Sessions Tab**
- Recent sessions sorted by start time
- Project name, start time, duration, input/output tokens
- Lines added/removed (green/red)
- Session summary text

### Design
- Dark theme with monospace typography
- Tailwind CSS + Chart.js
- Sticky header with live status badge
- Responsive layout (2-6 column stat cards)

### API Endpoints

All data is available programmatically:

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/` | Dashboard HTML |
| `GET` | `/api/processes` | Process list (JSON) |
| `GET` | `/api/usage` | Token usage + costs (JSON) |
| `GET` | `/api/sessions?limit=20` | Recent sessions (JSON) |
| `POST` | `/api/kill/{pid}?force=false` | Kill a process |
| `POST` | `/api/pin/{pid}` | Pin a process |
| `POST` | `/api/unpin/{pid}` | Unpin a process |

---

## macOS Menu Bar

With `pip install 'tce-monitor[macos]'`, run `tce run` to get a persistent menu bar icon:

- **Menu bar icon**: Crab emoji with status badges
  - 🦀 💀2 — 2 zombie processes (highest priority)
  - 🦀 ⚠️1 — 1 resource alert
  - 🦀 🟡3 — 3 stale processes
  - 🦀 — all healthy

- **Dropdown menu**: All processes with detailed metrics
  - Health icons (✅ healthy, 🟡 stale, 💀 zombie, 📌 pinned)
  - CPU usage with 🔴 red circle when >75% of system
  - Memory usage with 🔴 red circle when >75% of system
  - Uptime in hours
  - Example: `⚠️ ✅ 12345 — my-project (🔴 CPU: 85.0%, Mem: 1024MB, 1.2h)`

- **Per-process actions**: Kill, Force Kill, Pin/Unpin

- **Resource alert details**: Expand processes with ⚠️ to see system-wide percentages
  - Example: `System Usage: 🔴 CPU 82.5%, Memory 6.2%`

- **Open Dashboard**: Launch the web dashboard in a native webview window

- **macOS notifications**: Alerts when processes go stale, become zombies, or consume excessive resources (with 30-minute cooldown per alert type)

- **Summary line**: Process count, total memory, and resource alert count
  - Example: `5 processes | 5877 MB total | ⚠️ 2 resource alerts`

The menu bar runs on the main thread (required by PyObjC) with the web dashboard on a daemon thread.

### Enabling Notifications

Desktop notifications require `terminal-notifier` (installed automatically by `tce install`, or manually with `brew install terminal-notifier`).

After the first notification fires, macOS will silently suppress future alerts unless you allow them:

1. Open **System Settings > Notifications > terminal-notifier**
2. Toggle **Allow Notifications** to ON
3. Set alert style to **Banners** or **Alerts**

> **Important:** If you use **Focus / Do Not Disturb**, notifications will be blocked while it's active. Add `terminal-notifier` to your Focus mode's allowed apps, or notifications will only appear when Focus is off.

---

## Process Detection

Claude Code doesn't appear as `claude` in `ps aux`. Detection uses two strategies:

| Strategy | How |
|----------|-----|
| **Primary** | Executable path contains `.local/share/claude/versions/` |
| **Fallback** | `cmdline[0] == 'claude'` |

Both are checked per-process via `psutil`, with graceful handling of `AccessDenied` and `NoSuchProcess`.

## Health Classification

| Status | Icon | Criteria |
|--------|------|----------|
| **Healthy** | `+` / green | Running or sleeping, under all thresholds |
| **Stale** | `!` / yellow | Sleeping with <1% CPU for >4h (interactive) or >8h (background) |
| **Zombie** | `X` / red | Process in stopped (`T`) or zombie (`Z`) state |
| **Pinned** | `*` / blue | User-exempted from stale detection via `tce pin` |

Interactive vs. background is determined by whether the process has an attached terminal (`/dev/ttys*`).

## Resource Alerts

TCE monitors CPU and memory consumption per process as a percentage of total system resources:

| Metric | Threshold (Default) | Alert Trigger |
|--------|---------------------|---------------|
| **CPU** | 75% of system | Process using ≥75% of total CPU cores |
| **Memory** | 75% of system | Process using ≥75% of total RAM |

**Alert Types:**
- `HIGH_CPU` — Process exceeds CPU threshold
- `HIGH_MEMORY` — Process exceeds memory threshold
- `BOTH` — Process exceeds both thresholds

**Example:** On an 8-core system with 16GB RAM:
- A process using 6+ cores (≥600% in `ps` terms) triggers `HIGH_CPU`
- A process using 12+ GB triggers `HIGH_MEMORY`

**Visual Indicators:**
- CLI: ⚠️ with exact percentages (`⚠️ RESOURCE ALERT: CPU 82.5% of system`)
- Menu bar: 🔴 red circles next to exceeding values (`🔴 CPU: 85.0%`)
- Notifications: macOS alerts with actionable kill suggestions

**Independent from health status:** A process can be `healthy` (active) but still trigger resource alerts.

## Data Sources

| Source | Path | What It Provides |
|--------|------|------------------|
| **Live processes** | `psutil` | PID, executable, cmdline, cwd, terminal, CPU%, RSS, children |
| **Stats cache** | `~/.claude/stats-cache.json` | Token counts per model, daily activity, session totals |
| **Session meta** | `~/.claude/usage-data/session-meta/*.json` | Per-session: project, duration, tokens, tools used, lines changed, summary |

Token data uses mtime-based caching — files are only re-read when modified.

## Model Pricing

Costs are computed from Anthropic's published pricing (per million tokens):

| Model | Input | Output | Cache Read | Cache Creation |
|-------|-------|--------|------------|----------------|
| Opus 4.5 | $15.00 | $75.00 | $1.50 | $18.75 |
| Opus 4.6 | $15.00 | $75.00 | $1.50 | $18.75 |
| Sonnet 4.5 | $3.00 | $15.00 | $0.30 | $3.75 |
| Haiku 4.5 | $0.80 | $4.00 | $0.08 | $1.00 |

---

## Configuration

Settings are loaded from environment variables (with `CLAUDE_MONITOR_` prefix) and `.env` files:

| Variable | Default | Description |
|----------|---------|-------------|
| `CLAUDE_MONITOR_PORT` | `5111` | Dashboard server port |
| `CLAUDE_MONITOR_HOST` | `127.0.0.1` | Dashboard bind address |
| `CLAUDE_MONITOR_PROCESS_POLL_INTERVAL` | `10` | Seconds between process scans |
| `CLAUDE_MONITOR_STALE_INTERACTIVE_HOURS` | `4.0` | Hours before interactive process is stale |
| `CLAUDE_MONITOR_STALE_BACKGROUND_HOURS` | `8.0` | Hours before background process is stale |
| `CLAUDE_MONITOR_STALE_CPU_THRESHOLD` | `1.0` | CPU% below which a process is considered idle |
| `CLAUDE_MONITOR_RESOURCE_CPU_PERCENT_THRESHOLD` | `75.0` | CPU% of system before resource alert |
| `CLAUDE_MONITOR_RESOURCE_MEMORY_PERCENT_THRESHOLD` | `75.0` | Memory% of system before resource alert |
| `CLAUDE_MONITOR_ALERT_COOLDOWN` | `1800` | Seconds between macOS alerts for same PID |
| `CLAUDE_MONITOR_RESOURCE_ALERT_COOLDOWN` | `1800` | Seconds between resource alerts for same PID |

## Auto-Start at Login (macOS)

The easiest way to have TCE start automatically when you log in:

```bash
tce install
```

This creates a macOS launchd service that:
- Starts `tce run` (menu bar + dashboard) at every login
- Keeps the process alive (auto-restarts if it crashes)
- Logs to `~/.terminus-cancrorum-est/logs/`

To remove:
```bash
tce uninstall
```

### Manual launchd Setup

If you prefer to manage the plist yourself:

```bash
cp scripts/com.terminus-cancrorum-est.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.terminus-cancrorum-est.plist
```

To stop:
```bash
launchctl unload ~/Library/LaunchAgents/com.terminus-cancrorum-est.plist
```

---

## Claude Code Skill Integration

TCE includes a Claude Code skill so any Claude session can query your processes. Drop this project in your workspace and Claude will automatically use it:

```
You: "Check my Claude processes"
Claude: [runs tce status] → reports 7 processes, 3 stale

You: "How much have I spent on Claude?"
Claude: [runs tce usage] → $22,248.66 total, Opus 4.5 dominant

You: "Kill stale processes"
Claude: [runs tce kill-stale] → killed 3 processes
```

The skill is defined in `.claude/skills/terminus-cancrorum-est/SKILL.md`.

---

## Development

```bash
git clone https://github.com/tmancino/Terminus-Cancrorum-Est.git
cd Terminus-Cancrorum-Est
pip install -e ".[macos,dev]"

# Run tests
pytest tests/ -v --cov=tce

# Lint
ruff check tce/ tests/

# Type check
mypy tce/
```

### Project Structure

```
Terminus-Cancrorum-Est/
├── tce/                          # Installable Python package
│   ├── cli.py                    # CLI entry point (tce command)
│   ├── app.py                    # Full app: menu bar + dashboard
│   ├── menubar.py                # rumps macOS menu bar
│   ├── dashboard.py              # FastAPI web dashboard
│   ├── webview_window.py         # Native webview (macOS, optional)
│   ├── process_scanner.py        # psutil process detection + health
│   ├── token_tracker.py          # Stats cache + session meta parsing
│   ├── cost_calculator.py        # Token → USD pricing
│   ├── alert_service.py          # macOS notification alerts
│   ├── models.py                 # Pydantic models
│   ├── config.py                 # pydantic-settings configuration
│   ├── templates/
│   │   └── dashboard.html        # Tailwind + Chart.js dashboard
│   └── static/
│       └── logo.jpg
├── tests/                        # 50 tests (pytest)
│   ├── test_process_scanner.py   # Detection, health, pinning, scan, kill
│   ├── test_token_tracker.py     # Dashboard assembly, sessions, caching
│   ├── test_cost_calculator.py   # Pricing accuracy per model
│   └── test_models.py            # Pydantic serialization
├── scripts/
│   └── com.terminus-cancrorum-est.plist   # launchd auto-start
├── pyproject.toml                # Package metadata + tool config
├── LICENSE                       # MIT
└── README.md
```

### Architecture

```
tce run
├── Main thread: rumps menu bar [macOS only, requires pip install tce-monitor[macos]]
│   ├── Crab icon with zombie/stale badge
│   ├── Process dropdown with Kill/Pin actions
│   ├── "Open Dashboard" → native webview subprocess
│   └── macOS notification alerts (stale/zombie)
│
└── Daemon thread: FastAPI + uvicorn on :5111
    ├── GET /                  → Tailwind dashboard (Jinja2 template)
    ├── GET /api/processes     → ProcessScanner.scan()
    ├── GET /api/usage         → TokenTracker.get_dashboard()
    ├── GET /api/sessions      → TokenTracker.get_recent_sessions()
    ├── POST /api/kill/{pid}   → ProcessScanner.kill_process()
    └── POST /api/pin/{pid}    → ProcessScanner.pin()
```

On non-macOS platforms (or without the `[macos]` extra), `tce run` launches the dashboard on the main thread instead.

---

## Platform Support

| Platform | `tce` CLI | Web Dashboard | Menu Bar | Native Webview | Notifications |
|----------|-----------|---------------|----------|----------------|---------------|
| macOS | Yes | Yes | Yes (with `[macos]`) | Yes (with `[macos]`) | Yes |
| Linux | Yes | Yes | No | No | No |
| Windows | Untested | Probably | No | No | No |

---

## License

[MIT](LICENSE) — Tommy Mancino, 2026
