Skip to main content

Auto-popup terminals waiting for user input — like a poker MTT client for your terminal

Project description

MTT (Multi-Terminal Taker)

Tests

Auto-popup terminals waiting for your input — like a poker MTT client, but for your terminal.

Running 5 Claude Code sessions at once? MTT watches all of them and automatically brings each terminal to the front the moment it needs your input. When you respond, the next waiting terminal pops up. Zero dependencies. Pure Python.

The Problem

You have multiple terminals open — builds, tests, AI agents, servers. Most run on their own, but occasionally one needs your input. You waste time hunting through windows to find which one.

The Solution

MTT monitors all your terminal windows. When one starts waiting for input, it pops up automatically. You deal with it, and the next one pops up — like a poker multi-table tournament client that shows you whichever table needs your action.

How It Works

Terminal.app / iTerm2           MTT
┌──────────────┐
│ Tab 1: build │ ──running──┐
│ Tab 2: test  │ ──running──┤
│ Tab 3: claude│ ──idle────┐│   ┌─────────┐   ┌────────┐
│ Tab 4: claude│ ──busy────┤├──▶│  Queue   │──▶│ Pop up │
│ Tab 5: zsh   │ ──idle────┘│   │ (FIFO)  │   │ window │
│ Tab 6: server│ ──running──┘   └─────────┘   └────────┘
└──────────────┘
  1. Scan — AppleScript reads all terminal windows/tabs every second
  2. Detect — Checks if each terminal is waiting for input (3 methods)
  3. Queue — Waiting terminals enter a FIFO queue
  4. Pop up — The next terminal gets its window raised; when you respond, the next one pops up

Detection Methods

Method Trigger Speed
Hook marker Claude Code idle/busy hooks create/remove marker files Instant
Shell prompt Foreground process is zsh/bash/fish Instant
Content stasis Interactive app (claude, node) + content unchanged for 8s + no new child processes 8s delay

Content stasis catches mid-turn waiting states like Claude Code's AskUserQuestion prompts, where the Stop hook hasn't fired yet. The busy marker prevents false positives during API calls (no child processes to detect), and child process tracking prevents false positives during long tool calls.

Supported Terminals

  • Terminal.app — Full support
  • iTerm2 — Full support
  • Auto-detects which apps are running; works with both simultaneously

Claude Code Integration

MTT integrates with Claude Code hooks for instant idle/busy detection:

Add to ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/mtt/scripts/hook-idle.sh"
          }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/mtt/scripts/hook-busy.sh"
          }
        ]
      }
    ]
  }
}

Without hooks, MTT still works via shell prompt detection and content stasis — hooks just make it faster.

Requirements

  • macOS (uses AppleScript)
  • Python 3.12+
  • Accessibility permission (System Settings → Privacy & Security → Accessibility)

Install

pip install multi-terminal-taker

Or from source:

git clone https://github.com/wkdgks150/multi-terminal-taker.git
cd multi-terminal-taker
pip install -e .

Zero external dependencies — Python standard library only.

Usage

mtt start    # Start daemon (foreground)
mtt status   # Check if running
mtt stop     # Stop daemon

Output while running:

[12:34:56] IDLE
[12:34:57] QUEUE: 2 | SERVING: /dev/ttys003
[12:34:58] QUEUE: 1 | SERVING: /dev/ttys007
[12:34:59] IDLE

Project Structure

src/mtt/
├── cli.py                # CLI (start/stop/status)
├── daemon.py             # Main polling loop (1s interval)
├── monitor.py            # Terminal scanner (Terminal.app + iTerm2)
├── detector.py           # Idle detection (hooks + shell + content stasis)
├── queue.py              # FIFO popup queue
└── window_controller.py  # Window popup (Terminal.app + iTerm2)
scripts/
├── hook-idle.sh          # Claude Code Stop hook
└── hook-busy.sh          # Claude Code UserPromptSubmit hook

Tests

pip install pytest
pytest

Roadmap

  • Terminal scan + auto-popup + FIFO queue
  • Claude Code hook integration
  • Content stasis detection (AskUserQuestion, etc.)
  • iTerm2 support
  • Menu bar status indicator
  • Priority rules (pin important terminals)
  • Configurable polling interval and stasis threshold

License

MIT


한국어

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

multi_terminal_taker-0.1.0.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

multi_terminal_taker-0.1.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file multi_terminal_taker-0.1.0.tar.gz.

File metadata

  • Download URL: multi_terminal_taker-0.1.0.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for multi_terminal_taker-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0513786600f5997df90365635ba99b161db74a646f9366965e0968033474cd46
MD5 e0521907372082bbb419fbba06ce2505
BLAKE2b-256 7ba4f3b1aea66a0f9bb69af72002e547ce24ac8986c075c292ba4eedfc34d0a4

See more details on using hashes here.

File details

Details for the file multi_terminal_taker-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: multi_terminal_taker-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for multi_terminal_taker-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc4dd8d347505c3ac4e8c28837356d5d0e6ae898ac91448885ef51276451ea38
MD5 cc12f29d94f7442f77c9d82bfeb55f34
BLAKE2b-256 de70351ad776597ff245bb16d4e069a31db1ab701007200d2f7577196a00c7fd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page