claudectl
Mission control for Claude Code.
Run 3, 5, or 8 Claude Code sessions without tab hunting. claudectl shows which agent is blocked, burning budget, waiting for approval, or stalled, and lets you intervene from one terminal dashboard across GNOME Terminal, tmux, iTerm2, Ghostty, Warp, and more.
~1 MB binary. Sub-50ms startup. Zero config required.
README is the quick technical entry point. Use the landing page for the full overview, screenshots, and shareable launch surface.
Install
Quick install (macOS / Linux)
|
Nix
From source
&&
Quickstart
Use --demo if you want to evaluate the UI or record assets without any live Claude Code sessions. Use plain claudectl when you already have at least one Claude Code session running. No configuration needed.
From the dashboard you can:
- Press
yto approve a blocked permission prompt - Press
ito type input to a session - Press
Tabto jump to a session's terminal tab - Press
dto kill a runaway session - Press
?for all keybindings
See CHANGELOG.md for release history and the landing page for the higher-level product overview.
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.
Control spend
Set per-session budgets. Get warned at 80%. Optionally auto-kill at 100%.
Weekly and daily cost aggregation shows in the title bar. Use --history and --stats to review past spend:
Unknown models are marked as fallback estimates until you override pricing and context in config.
Catch blockers instantly
Sessions needing approval show as Needs Input in magenta. Desktop notifications and webhooks alert you even when claudectl isn't focused:
Orchestrate multi-session work
Run coordinated tasks with dependency ordering, retries, and resumable sessions:
Each run writes live progress to .claudectl-runs/.../status.json, final results to .claudectl-runs/.../summary.json, and per-attempt stdout/stderr logs for every task. Press Ctrl-C to abort a run cleanly.
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:
Demo mode — Deterministic fake sessions for screenshots and content:
Features
Dashboard
- Live table: PID, project, status, context %, cost, $/hr burn rate, elapsed, CPU%, memory, tokens, sparkline
- Parent sessions expand into subagent rows so you can see completed-subagent totals and currently active subagents separately
- 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) - Live triage filters: status cycle (
f), focus cycle (v), text search (/), clear (z) - 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 wizard for cwd, prompt, and resume (GNOME Terminal, tmux, Kitty, WezTerm, Windows Terminal on WSL) |
g |
Toggle grouped view by project |
s |
Cycle sort column |
f |
Cycle status filter |
v |
Cycle focus filter (attention, budget, context, telemetry, conflicts) |
/ |
Search project/model/session text |
z |
Clear all active filters |
c |
Send /compact to session (when idle) |
R |
Record session highlight reel (toggle) |
r |
Force refresh |
? |
Toggle help overlay |
q/Esc |
Quit |
Use claudectl --doctor to check the current terminal's launch/switch/input support, CLI dependencies, and setup requirements.
Terminal Support
| Terminal | Launch (--new / n) |
Switch | Input | Approve | Notes |
|---|---|---|---|---|---|
| GNOME Terminal | Yes | - | - | - | Visible launch via gnome-terminal --window on Linux |
| Ghostty | - | Yes | Yes | Yes | Native AppleScript API, no Kitty-style remote control setup |
| Kitty | Yes | Yes | Yes | Yes | kitty @ remote control |
| tmux | Yes | Yes | Yes | Yes | tmux pane/window control |
| WezTerm | Yes | Yes | - | - | wezterm cli launch + pane activation |
| Windows Terminal (WSL) | Yes | - | - | - | Visible launch via cmd.exe /c wt.exe into a new WSL tab |
| Warp | - | Yes | Yes | Yes | Command Palette + System Events |
| iTerm2 | - | Yes | Yes | Yes | AppleScript + System Events |
| Terminal.app | - | Yes | Yes | Yes | AppleScript + System Events |
Notes: Run claudectl --doctor from the same terminal family you use for Claude. It reports the supported launch/switch/input/approve actions plus any missing prerequisites. GNOME Terminal launch is verified on Linux under Docker/X11, but remote switch/input/approve automation is intentionally unsupported there. Windows Terminal support is WSL-only and currently covers visible launch, not remote tab control. Kitty requires allow_remote_control yes in config. Warp, iTerm2, and Terminal.app require macOS Automation/Accessibility permission. tmux support assumes claudectl can reach the same tmux server as the Claude panes.
Themes
- Dark, light, and none (
--theme) - Respects
NO_COLORenvironment variable
Event Hooks
Run shell commands automatically when session events occur. Add to your config file:
# ~/.config/claudectl/config.toml
[]
= "say 'Claude needs your attention'"
[]
= "terminal-notifier -title 'claudectl' -message '{project} finished (${cost})'"
[]
= "curl -X POST $SLACK_WEBHOOK -d '{\"text\": \"{project} hit 80% budget (${cost})\"}'"
[]
= "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. Submitted hooks are reviewed for security, reliability, and usefulness before being added.
To submit a hook, open an issue 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.
[]
= 2000
= true
= true
= "cost"
= 5.00
= false
[]
= 25.00
= 100.00
[]
= "https://hooks.slack.com/..."
= ["NeedsInput", "Finished"]
[]
= 75
[]
= 1.25
= 5.0
= 0.15
= 0.9
= 128000
Show resolved config: claudectl --config
Maintenance
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 eventsps— 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 (
claudein another terminal) - Check that
~/.claude/sessions/contains.jsonfiles - Run
claudectl --log /tmp/claudectl.logand check the log
Tab switching doesn't work
- Run
claudectl --doctorfirst to see the detected terminal, missing prerequisites, and supported actions - GNOME Terminal: launch support is available; use tmux or Kitty if you need remote switching or input automation
- Windows Terminal on WSL: launch support is available when
cmd.exe /c wt.exeworks; use tmux or Kitty inside WSL for switching and input automation - Ghostty: should work out of the box
- Kitty: add
allow_remote_control yesto~/.config/kitty/kitty.conf - Warp/iTerm2/Terminal.app: grant Automation/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.jsonlfiles
High CPU usage from claudectl itself
- Increase the poll interval:
claudectl --interval 3000(default is 2000ms)
For other issues, run with --log and open an issue 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?
Native Windows is not supported yet. WSL plus Windows Terminal can now launch new Claude tabs through claudectl --new or n, and WSL plus tmux remains the recommended setup when you also want switch/input/approve automation.
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
Before submitting
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.
Found a bug? Open an issue with claudectl --version, your terminal (echo $TERM_PROGRAM), and steps to reproduce.
License
MIT