claudectl 0.15.1

TUI for monitoring and managing Claude Code CLI agents
Documentation

claudectl

A fast, lightweight TUI for monitoring and managing multiple Claude Code CLI sessions running across terminals.

Built in Rust. ~1MB binary. Sub-50ms startup.

claudectl demo

Features

  • Live dashboard — PID, project, status, context window %, cost, $/hr burn rate, elapsed time, CPU%, memory, token counts, activity sparkline
  • Smart status detection — Processing / Needs Input / Waiting / Idle / Finished, inferred from JSONL events, CPU usage, and message timestamps
  • Cost tracking — Per-session and total USD estimates based on model pricing (Opus, Sonnet, Haiku) with burn rate
  • Budget enforcement — Per-session budget alerts at 80%, optional auto-kill at 100%
  • Approve/input — Press y to approve permission prompts, i to type input to sessions
  • Auto-approve — Press a twice to enable auto-approve for trusted sessions
  • Tab switching — Press Tab to jump to a session's terminal tab (7 terminals supported)
  • Session launcher — Press n to start a new Claude Code session from within claudectl
  • Grouped view — Press g to group sessions by project with aggregate stats
  • Detail panel — Press Enter to expand session details (tokens, cost, model, paths)
  • Notifications — Desktop notifications when sessions need input (--notify)
  • Webhooks — POST JSON to Slack/Discord/URL on status changes (--webhook)
  • Watch mode — Stream status changes without TUI (--watch)
  • Session history — Persist completed sessions and view cost analytics (--history, --stats)
  • Configuration file — Persistent settings via ~/.config/claudectl/config.toml
  • Theme system — Dark, light, and monochrome themes (--theme, NO_COLOR support)
  • Task orchestration — Run multiple Claude sessions with dependency ordering (--run)
  • Session highlight reels — Press R to record a supercut of any session as a shareable GIF
  • Remote compaction — Press c to send /compact to an idle session
  • Conflict detection — Warns when 2+ sessions share the same git worktree (!! indicator)
  • Context alertson_context_high hook when context window crosses threshold
  • Permission wait time — Shows how long sessions have been waiting, sorted by longest first
  • Session cleanupclaudectl --clean to remove old session data and free disk space
  • Demo mode--demo for deterministic fake sessions (screenshots, content creation)
  • Diagnostic logging — Structured debug output for troubleshooting (--log)

Install

Homebrew (macOS)

brew tap mercurialsolo/tap
brew install claudectl

Quick install (macOS / Linux)

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

From source

cargo install --path .

Nix

nix run github:mercurialsolo/claudectl

Usage

# Launch the TUI dashboard
claudectl

# Print session list and exit
claudectl --list

# Export JSON for scripting
claudectl --json

# Stream status changes (no TUI)
claudectl --watch
claudectl --watch --json

# Session history and cost analytics
claudectl --history --since 24h
claudectl --stats --since 7d

# Launch a new Claude session
claudectl --new --cwd ~/projects/my-app --prompt "Fix the auth bug"

# Budget enforcement
claudectl --budget 5 --kill-on-budget

# Notifications and webhooks
claudectl --notify
claudectl --webhook https://hooks.slack.com/... --webhook-on NeedsInput,Finished

# Theme and diagnostics
claudectl --theme light
claudectl --log /tmp/claudectl.log

# Run multiple tasks from a file
claudectl --run tasks.json --parallel

# Clean up old session data
claudectl --clean --older-than 7d --dry-run
claudectl --clean --finished

# Show resolved configuration
claudectl --config

Configuration

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

[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  # Fire on_context_high when context window exceeds this %

Event Hooks

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

# ~/.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_session_start]
run = "echo '{pid},{project},{model}' >> ~/claude-sessions.csv"

[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 officially verified hooks at mercurialsolo/claudectl-hooks. Only verified hooks are endorsed for production use.

To submit a hook for verification, open an issue on the claudectl-hooks repository with:

  • Hook name and description
  • The [hooks.*] config snippet
  • What problem it solves
  • Any dependencies (e.g., terminal-notifier, jq)

Submitted hooks are reviewed for security, reliability, and usefulness before being added to the verified collection.

Task Orchestration

Run multiple Claude sessions with dependency ordering:

{
  "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"
    }
  ]
}
claudectl --run tasks.json --parallel

Session Recording & Highlight Reels

Per-Session Highlight Reel (press R)

Select any running session and press R to start recording a supercut:

  • What's captured: file edits (path + diff size), bash commands (+ output), errors (red ✗), successes (green ✓)
  • What's skipped: file reads, grep/glob searches, verbose explanations, idle time
  • Output: title card → paced events → final summary with edit/command/error tally
  • Multiple recordings: press R on different sessions to record them all simultaneously
  • Passive: records in background while you keep using claudectl
  • Works in split terminals: reads JSONL on disk, not terminal output

Table shows REC prefix on recorded sessions. Status bar shows REC 2 sessions: a, b (R to stop).

TUI Recording (--record)

Record the full claudectl dashboard as a shareable GIF:

claudectl --record session.gif           # Direct GIF (requires agg: cargo install agg)
claudectl --record session.cast          # Raw asciicast v2

Demo Mode

No sessions running? Use --demo for deterministic fake sessions:

claudectl --demo                         # Animated TUI with 8 fake sessions
claudectl --demo --record demo.gif       # One-command GIF for your README
claudectl --demo --list                  # Print as table
claudectl --demo --json                  # Export as JSON

Keybindings

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
g Toggle grouped view by project
s Cycle sort column (Status, Context, Cost, $/hr, Elapsed)
c Send /compact to session (when idle)
R Record session highlight reel (toggle)
r Force refresh
? Toggle help overlay
q/Esc Quit

Status Colors

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
Idle Gray No recent activity (>10 min since last message)
Finished Red Process exited

How It Works

claudectl reads Claude Code's local data:

  • ~/.claude/sessions/*.json — One file per running Claude process with PID, session ID, working directory, and start time
  • ~/.claude/projects/{slug}/*.jsonl — Conversation logs with token usage, model info, stop_reason, and waiting_for_task events
  • ps — CPU%, memory, TTY, and command args for each process
  • /tmp/claude-{uid}/{slug}/{sessionId}/tasks/ — Subagent task files

Status is inferred from multiple signals:

  • waiting_for_task progress event → Needs Input (needs user confirmation)
  • CPU > 5% → Processing (overrides all other signals)
  • stop_reason: tool_use + low CPU + age >5s → Needs Input (permission prompt)
  • stop_reason: end_turn + recent activity → Waiting
  • Last message > 10 minutes ago → Idle

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

Terminal-specific notes

  • Ghostty: Best support. Native AppleScript with working directory and TTY matching. No extra config needed.
  • Kitty: Requires allow_remote_control yes (or socket-only) in ~/.config/kitty/kitty.conf.
  • Warp: Requires Accessibility permission (System Settings > Privacy & Security > Accessibility). Approve/input briefly switches focus to the Claude tab, sends the keystroke, then you can switch back.
  • tmux: Auto-detected when running inside tmux. Works alongside the outer terminal's support.

Requirements

  • macOS or Linux
  • Claude Code CLI installed and running
  • Rust 2024 edition (to build from source)

Issues & Feature Requests

Found a bug or have an idea? Open an issue.

Bug reports — please include:

  • claudectl --version output
  • Your terminal (echo $TERM_PROGRAM) and OS
  • Steps to reproduce
  • If possible, attach a log file: claudectl --log /tmp/claudectl-debug.log and reproduce the issue

Feature requests — describe the use case, not just the solution. What are you trying to accomplish? Knowing the "why" helps us find the best approach.

Contributing

Contributions are welcome! Here's how to get started:

Setup

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

Development workflow

  1. Check existing issues — look for good first issue or comment on something you'd like to work on
  2. Fork and branch — create a feature branch from main
  3. Write tests — new functionality should include tests in tests/integration_tests.rs or as module-level #[cfg(test)] tests
  4. Pass all checks before submitting:
    cargo test --all-targets
    cargo clippy --all-targets -- -D warnings
    cargo fmt --all -- --check
    
  5. Open a PR — describe what changed and why. Link to any related issues.

Architecture

The codebase is organized into focused modules:

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)

Guidelines

  • No new dependencies without strong justification — the project stays lightweight
  • Test behavior, not implementation — focus on what the code does, not how
  • Match existing patterns — look at similar code in the repo before writing new code
  • Keep commits atomic — one logical change per commit with a clear message

License

MIT