DEV Community

Barada Sahu
Barada Sahu

Posted on

No more switching tabs - manage multiple Claude Code sessions from a single terminal

I run a lot of Claude Code sessions at the same time. Backend refactor in one terminal, tests in another, docs in a third, frontend in a fourth. It works great until it doesn't.

The problems show up fast:

  • One session is blocked waiting for permission approval. I don't know which tab.
  • One's burning through tokens at $4/hr. I can't see that without switching to it.
  • One's idle for 15 minutes
  • I'm tab-hunting instead of coding.

Claude Code is great at execution. It's not built to manage all these parallel coding sessions. Built the missing layer

claudectl

A terminal dashboard that monitors every running Claude Code session from one pane.


It auto-discovers all running sessions and shows live status, cost, burn rate, CPU usage, context window percentage, and token counts. No config needed. Just run claudectl.

The problems it solves

Which session is blocked?
Sessions needing approval show as "Needs Input" in magenta. Press y to approve without switching terminals.

Which session is burning money?
Every session shows a live $/hr burn rate. Set a budget with --budget 5 --kill-on-budget and it auto-kills sessions that exceed it.

Which session is stalled?
Status detection uses multiple signals — CPU usage, JSONL conversation events, and message timestamps — not just one indicator. If CPU is zero but the last event says "processing," claudectl knows something is wrong.

How do I intervene without tab-hunting?
Press Tab to jump to any session's terminal. Press i to type input. Press d to kill. All from the dashboard.

How it works under the hood

claudectl is read-only. It never modifies Claude Code's files or behavior. It reads:

  • ~/.claude/sessions/*.json for session metadata
  • ~/.claude/projects/{slug}/*.jsonl for conversation logs and token usage
  • ps output for CPU and memory per process

Status inference combines multiple signals rather than relying on any single one:

waiting_for_task event → Needs Input
CPU > 5% → Processing (overrides everything)
stop_reason: end_turn → Waiting
Last message > 10 min ago → Idle
Process exited → Finished

JSONL parsing is incremental — it tracks file offsets so it never rereads the full log. The binary is ~1MB with sub-50ms startup because it uses native ps instead of heavier system info crates.

Beyond monitoring

A few features that turned out to be more useful than I expected:

Event hooks — Run shell commands on session events. I use this to get Slack alerts when a session needs input:


toml
  [hooks.on_needs_input]
  run = "curl -X POST $SLACK_WEBHOOK -d '{\"text\": \"{project} needs approval\"}'"

  [hooks.on_budget_warning]
  run = "say '{project} hit 80% budget'"

  Task orchestration — Define multi-session workflows with dependencies:

  {
    "tasks": [
      { "name": "Add auth", "cwd": "./backend", "prompt": "Add JWT middleware" },
      { "name": "Update tests", "cwd": "./backend", "prompt": "Update API tests",   "depends_on": ["Add auth"] }
    ]
  }

 Highlight reels — Press R on any session to record a supercut of what it did: file   edits, commands run, errors hit. Idle time and noise are stripped. Output is a   shareable GIF.

  Install

  brew install mercurialsolo/tap/claudectl
  # or
  cargo install claudectl

  Works on macOS and Linux. Supports Ghostty, Kitty, tmux, WezTerm, Warp, iTerm2, and   Terminal.app.

What's next

The tool is at v0.9.1 now. The immediate roadmap is Windows/WSL support and expanding   the hooks ecosystem. Longer term, I'm thinking about multi-agent monitoring beyond   just Claude Code.

If you run multiple Claude Code sessions, give it a try. If you have ideas or run into issues, the repo is open:

GitHub: https://github.com/mercurialsolo/claudectl

---
_Built in Rust with ratatui. MIT licensed. The entire project was built with Claude Code._
Enter fullscreen mode Exit fullscreen mode

Top comments (0)