claudectl 0.15.5

TUI for monitoring and managing Claude Code CLI agents
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# claudectl

**Mission control for Claude Code.**

Monitor multiple Claude Code sessions in one terminal dashboard. Catch blocked agents, control token burn, approve actions, and orchestrate work across tmux, iTerm2, Ghostty, Warp, and more.

[![CI](https://github.com/mercurialsolo/claudectl/actions/workflows/ci.yml/badge.svg)](https://github.com/mercurialsolo/claudectl/actions/workflows/ci.yml)
[![Crates.io](https://img.shields.io/crates/v/claudectl)](https://crates.io/crates/claudectl)
[![Homebrew](https://img.shields.io/badge/homebrew-mercurialsolo%2Ftap-orange)](https://github.com/mercurialsolo/homebrew-tap)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey)]()

<sub>~1 MB binary. Sub-50ms startup. Zero config required.</sub>

[![claudectl demo](https://asciinema.org/a/bovJrUq2vEmC08NU.svg)](https://asciinema.org/a/bovJrUq2vEmC08NU)

## Install

```bash
brew install mercurialsolo/tap/claudectl     # Homebrew (macOS)
cargo install claudectl                       # Cargo (any platform)
```

<details>
<summary>Other methods</summary>

**Quick install (macOS / Linux)**

```bash
curl -fsSL https://raw.githubusercontent.com/mercurialsolo/claudectl/main/install.sh | sh
```

**Nix**

```bash
nix run github:mercurialsolo/claudectl
```

**From source**

```bash
git clone https://github.com/mercurialsolo/claudectl.git
cd claudectl && cargo install --path .
```

</details>

## Quickstart

```bash
# Make sure you have at least one Claude Code session running, then:
claudectl
```

That's it. claudectl auto-discovers all running Claude Code sessions and shows a live dashboard. No configuration needed.

From the dashboard you can:
- Press `y` to approve a blocked permission prompt
- Press `i` to type input to a session
- Press `Tab` to jump to a session's terminal tab
- Press `d` to kill a runaway session
- Press `?` for all keybindings

## Why This Exists

Claude Code is excellent at execution. It is not built to supervise many concurrent sessions.

When you run 3, 5, or 8 sessions across terminals, real problems appear:

- **Which session is blocked?** One is waiting for approval and you don't know which tab.
- **Which session is burning money?** You can't see token spend without switching to each one.
- **Which session needs input?** A permission prompt has been sitting for 10 minutes.
- **Which session is stalled?** It looks busy but CPU is zero.

claudectl is the operator layer that answers these questions from one pane.

## Claude Code vs claudectl

| Capability | Claude Code alone | With claudectl |
|-----------|:-:|:-:|
| Run a single session | Yes | Yes |
| See status of all sessions at once | No | **Yes** |
| Know which session is blocked | Tab-hunt | **At a glance** |
| Track cost per session | Manually | **Live $/hr burn rate** |
| Enforce spend budgets | No | **Auto-kill at limit** |
| Approve prompts without switching | No | **Press `y`** |
| Get notified on stalls/blocks | No | **Desktop + webhook** |
| Orchestrate multi-session workflows | No | **Dependency-ordered tasks** |
| Record session highlight reels | No | **Press `R`** |

## Core Workflows

### Supervise multiple sessions

Launch `claudectl` and see every running session: status, cost, burn rate, CPU, context window usage, token counts, and activity sparkline — all updating live.

```bash
claudectl                   # Interactive TUI dashboard
claudectl --watch           # Stream status changes (no TUI)
claudectl --list            # Print session table and exit
claudectl --json            # Machine-readable output for scripting
```

### Control spend

Set per-session budgets. Get warned at 80%. Optionally auto-kill at 100%.

```bash
claudectl --budget 5 --kill-on-budget
```

Weekly and daily cost aggregation shows in the title bar. Use `--history` and `--stats` to review past spend:

```bash
claudectl --history --since 24h
claudectl --stats --since 7d
```

### Catch blockers instantly

Sessions needing approval show as **Needs Input** in magenta. Desktop notifications and webhooks alert you even when claudectl isn't focused:

```bash
claudectl --notify
claudectl --webhook https://hooks.slack.com/... --webhook-on NeedsInput,Finished
```

### Orchestrate multi-session work

Run coordinated tasks with dependency ordering:

```json
{
  "tasks": [
    {
      "name": "Add auth middleware",
      "cwd": "./backend",
      "prompt": "Add JWT auth middleware to all API routes"
    },
    {
      "name": "Update tests",
      "cwd": "./backend",
      "prompt": "Update API tests for the new auth middleware",
      "depends_on": ["Add auth middleware"]
    },
    {
      "name": "Update docs",
      "cwd": "./docs",
      "prompt": "Document the new auth flow"
    }
  ]
}
```

```bash
claudectl --run tasks.json --parallel
```

### Record and share

**Highlight reels** — Press `R` on any session to record a supercut: file edits, bash commands, errors, and successes. Idle time and noise are stripped. Output is a shareable GIF.

**Dashboard recording** — Capture the full TUI:

```bash
claudectl --record session.gif      # Direct GIF (requires agg)
claudectl --record session.cast     # Raw asciicast v2
```

**Demo mode** — Deterministic fake sessions for screenshots and content:

```bash
claudectl --demo                    # Animated TUI with 8 fake sessions
claudectl --demo --record demo.gif  # One-command GIF for your README
```

## Features

### Dashboard
- Live table: PID, project, status, context %, cost, $/hr burn rate, elapsed, CPU%, memory, tokens, sparkline
- Detail panel (`Enter`) with full session metadata
- Grouped view (`g`) by project with aggregate stats
- Sort by status, context, cost, burn rate, or elapsed (`s`)
- Conflict detection when 2+ sessions share the same git worktree (`!!`)
- Permission wait time — shows how long sessions have been waiting, longest first

### Status Detection

Multi-signal inference from CPU usage, JSONL events, and timestamps:

| Status | Color | Meaning |
|--------|-------|---------|
| **Needs Input** | Magenta | Waiting for user to approve/confirm a tool use |
| **Processing** | Green | Actively generating or executing tools |
| **Waiting** | Yellow | Done responding, waiting for user's next prompt |
| **Unknown** | Blue | Session is alive, but transcript telemetry is missing or unsupported |
| **Idle** | Gray | No recent activity (>10 min since last message) |
| **Finished** | Red | Process exited |

### Cost Tracking & Budgets
- Per-session USD estimates (Opus, Sonnet, Haiku model pricing)
- Live $/hr burn rate
- Per-session budget alerts at 80%, auto-kill at 100%
- Daily/weekly aggregate cost tracking
- Session history with cost analytics

### Interactive Controls

| Key | Action |
|-----|--------|
| `j`/`k` or `Up`/`Down` | Navigate sessions |
| `Tab` | Switch to session's terminal tab |
| `Enter` | Toggle detail panel |
| `y` | Approve (send Enter to NeedsInput session) |
| `i` | Input mode (type text to session) |
| `d`/`x` | Kill session (double-tap to confirm) |
| `a` | Toggle auto-approve (double-tap to confirm) |
| `n` | Launch new Claude session (`tmux`, Kitty, WezTerm) |
| `g` | Toggle grouped view by project |
| `s` | Cycle sort column |
| `c` | Send /compact to session (when idle) |
| `R` | Record session highlight reel (toggle) |
| `r` | Force refresh |
| `?` | Toggle help overlay |
| `q`/`Esc` | Quit |

### Terminal Support

| Terminal | Tab Switch | Approve/Input | Method |
|----------|-----------|---------------|--------|
| **Ghostty** | Background | Background | Native AppleScript API |
| **Kitty** | Background | Background | `kitty @` remote control |
| **tmux** | Background | Background | `tmux send-keys` |
| **WezTerm** | Background | - | CLI JSON API |
| **Warp** | Focus switch | Focus switch | Command Palette + System Events |
| **iTerm2** | Focus switch | Focus switch | AppleScript + System Events |
| **Terminal.app** | Focus switch | Focus switch | AppleScript + System Events |

**Notes:** Ghostty has the best support — no config needed. Kitty requires `allow_remote_control yes` in config. Warp requires Accessibility permission. tmux is auto-detected.

### Themes
- Dark, light, and monochrome (`--theme`)
- Respects `NO_COLOR` environment variable

## Event Hooks

Run shell commands automatically when session events occur. Add to your config file:

```toml
# ~/.config/claudectl/config.toml

[hooks.on_needs_input]
run = "say 'Claude needs your attention'"

[hooks.on_finished]
run = "terminal-notifier -title 'claudectl' -message '{project} finished (${cost})'"

[hooks.on_budget_warning]
run = "curl -X POST $SLACK_WEBHOOK -d '{\"text\": \"{project} hit 80% budget (${cost})\"}'"

[hooks.on_status_change]
run = "echo '[{project}] {old_status} -> {new_status}' >> ~/claude-activity.log"
```

### Events

| Event | Trigger |
|-------|---------|
| `on_session_start` | New session discovered |
| `on_status_change` | Any status transition |
| `on_needs_input` | Session needs user approval/input |
| `on_finished` | Session process exited |
| `on_budget_warning` | Session hit 80% of budget |
| `on_budget_exceeded` | Session hit 100% of budget |
| `on_idle` | Session went idle (>10 min) |
| `on_context_high` | Context window usage crossed threshold (default 75%) |
| `on_conflict_detected` | 2+ sessions share the same working directory |

### Template Variables

`{pid}`, `{project}`, `{status}`, `{cost}`, `{model}`, `{cwd}`, `{tokens_in}`, `{tokens_out}`, `{elapsed}`, `{session_id}`, `{old_status}`, `{new_status}`, `{context_pct}`

Use `claudectl --hooks` to verify your configured hooks.

### Verified Hooks

We maintain a curated set of verified hooks at [mercurialsolo/claudectl-hooks](https://github.com/mercurialsolo/claudectl-hooks). Submitted hooks are reviewed for security, reliability, and usefulness before being added.

To submit a hook, [open an issue](https://github.com/mercurialsolo/claudectl-hooks/issues) with the config snippet, what it solves, and any dependencies.

## Configuration

claudectl loads settings from `~/.config/claudectl/config.toml` (global) and `.claudectl.toml` (per-project). CLI flags override both.

```toml
[defaults]
interval = 1000
notify = true
grouped = true
sort = "cost"
budget = 5.00
kill_on_budget = false

[webhook]
url = "https://hooks.slack.com/..."
events = ["NeedsInput", "Finished"]

[context]
warn_threshold = 75

[models."gpt-4o"]
input_per_m = 1.25
output_per_m = 5.0
cache_read_per_m = 0.15
cache_write_per_m = 0.9
context_max = 128000
```

Show resolved config: `claudectl --config`

## Maintenance

```bash
claudectl --clean --older-than 7d --dry-run   # Preview cleanup
claudectl --clean --finished                    # Remove finished session data
```

## How It Works

claudectl reads Claude Code's local data — no API keys, no network access, no modifications to Claude Code:

- **`~/.claude/sessions/*.json`** — session metadata (PID, session ID, working directory, start time)
- **`~/.claude/projects/{slug}/*.jsonl`** — conversation logs with token usage and events
- **`ps`** — CPU%, memory, TTY for each process
- **`/tmp/claude-{uid}/{slug}/{sessionId}/tasks/`** — subagent task files

Status inference combines multiple signals: `waiting_for_task` events, CPU usage thresholds, `stop_reason` fields, and message recency.

## Troubleshooting

**No sessions found**
- Ensure Claude Code is running (`claude` in another terminal)
- Check that `~/.claude/sessions/` contains `.json` files
- Run `claudectl --log /tmp/claudectl.log` and check the log

**Tab switching doesn't work**
- Ghostty: should work out of the box
- Kitty: add `allow_remote_control yes` to `~/.config/kitty/kitty.conf`
- Warp: grant Accessibility permission in System Settings > Privacy & Security
- tmux: must be running inside a tmux session

**Cost shows $0.00**
- claudectl reads token usage from JSONL logs. If the session just started, wait for the first response to complete
- Check that `~/.claude/projects/` contains `.jsonl` files

**High CPU usage from claudectl itself**
- Increase the poll interval: `claudectl --interval 3000` (default is 1000ms)

For other issues, run with `--log` and [open an issue](https://github.com/mercurialsolo/claudectl/issues/new) with the log attached.

## FAQ

**Does claudectl modify Claude Code or its files?**
No. It is read-only. The only writes are to its own history file and log file.

**Does it need an API key?**
No. It reads local files on disk. No network access required (unless you configure webhooks).

**Does it work with Claude Code in VS Code / JetBrains?**
It monitors any Claude Code process, regardless of how it was launched. Terminal-specific features (tab switching, input) require a supported terminal.

**Can I use it with a single session?**
Yes, but the value increases with concurrency. If you run one session, you already know where it is.

**What about Windows?**
Not yet. macOS and Linux only. WSL support is planned.

## Security

claudectl runs entirely locally. It reads Claude Code's session files from disk and process data from `ps`. It does not:
- Send data to any server (unless you configure webhooks)
- Modify Claude Code's files or behavior
- Require API keys or authentication
- Run with elevated privileges

Webhook payloads contain session metadata (project name, cost, status). Review your webhook URL and event filters before enabling.

## Contributing

Contributions are welcome.

### Setup

```bash
git clone https://github.com/mercurialsolo/claudectl.git
cd claudectl
cargo build
cargo test --all-targets
```

### Before submitting

```bash
cargo test --all-targets
cargo clippy --all-targets -- -D warnings
cargo fmt --all -- --check
```

### Guidelines

- **No new dependencies** without strong justification — the project stays lightweight
- **Test behavior, not implementation** — focus on what the code does
- **Match existing patterns** — look at similar code before writing new code
- **Keep commits atomic** — one logical change per commit

Not all contributions are code. Hooks, docs, config presets, terminal compatibility fixes, and packaging help are all valuable.

### Architecture

| Module | Purpose |
|--------|---------|
| `session.rs` | Session data structures and formatting |
| `discovery.rs` | Session file scanning and JSONL path resolution |
| `monitor.rs` | JSONL parsing, token counting, status inference |
| `process.rs` | Process introspection via `ps` |
| `app.rs` | Core app state, refresh loop, event handling |
| `config.rs` | TOML config file loading and layering |
| `theme.rs` | Color palette and theme modes |
| `history.rs` | Session history persistence and analytics |
| `orchestrator.rs` | Multi-session task runner |
| `hooks.rs` | Event hooks system and execution |
| `logger.rs` | Diagnostic file logging |
| `demo.rs` | Deterministic fake sessions for demo mode |
| `recorder.rs` | Asciicast recording with tee writer |
| `session_recorder.rs` | Per-session highlight reel generator |
| `terminals/` | Terminal-specific switching and input injection |
| `ui/` | TUI rendering (table, detail, help, status bar) |

## Community

Questions, ideas, or workflows to share? [Start a Discussion](https://github.com/mercurialsolo/claudectl/discussions).

Found a bug? [Open an issue](https://github.com/mercurialsolo/claudectl/issues/new) with `claudectl --version`, your terminal (`echo $TERM_PROGRAM`), and steps to reproduce.

## License

MIT