iTerm Panel Debugging
November 15, 2025 · View on GitHub
Why scripted terminals matter
Testing the pi-tui panel inside this repo requires a real terminal (iTerm, tmux, etc.). The panel won't launch in the sandbox shell (pnpm exec tsx src/cli.ts panel exits immediately because stdio isn’t a TTY). Always exercise keyboard/mouse input via an external terminal. We use mcporter plus the iterm-mcp server to drive iTerm programmatically.
Launching the panel through mcporter
cd ~/Projects/mcporter
# Start the panel inside iTerm’s active tab
./runner pnpm run mcporter call \
'iterm.write_to_terminal(command: "cd ~/Projects/poltergeist && pnpm exec tsx src/cli.ts panel")'
# Read the terminal buffer to confirm it’s running
./runner pnpm run mcporter call 'iterm.read_terminal_output(linesOfOutput: 40)'
Sending keys (quit, refresh, etc.)
# Quit via “q”
./runner pnpm run mcporter call 'iterm.write_to_terminal(command: "q")'
# Trigger a refresh
./runner pnpm run mcporter call 'iterm.write_to_terminal(command: "r")'
# Inspect the buffer after key presses
./runner pnpm run mcporter call 'iterm.read_terminal_output(linesOfOutput: 20)'
Note:
iterm.write_to_terminalexecutes shell commands (it effectively typesq⏎). Raw-mode apps won’t see those as keystrokes—they just echo in the shell. To send actual keys (without Enter), use tmuxsend-keys, iTerm hotkey windows, or extenditerm-mcpwith a dedicatedsend_keystool.
Set POLTERGEIST_INPUT_DEBUG=1 to log raw input bytes while diagnosing keyboard issues:
./runner pnpm run mcporter call \
'iterm.write_to_terminal(command: "cd ~/Projects/poltergeist && POLTERGEIST_INPUT_DEBUG=1 pnpm exec tsx src/cli.ts panel")'
When the terminal gets stuck
- Kill iTerm2 and reopen it if the panel stops responding. Quick options:
osascript -e 'tell application "iTerm2" to quit'killall iTerm2
- Relaunch mcporter commands afterwards to reattach the panel session.
Key takeaways
- You cannot reproduce the panel’s keyboard/mouse behavior inside the repo’s non-interactive shell—use iTerm (or another real terminal) driven via mcporter.
- mcporter’s
iterm.*tools (write_to_terminal,read_terminal_output,send_control_character) provide a reproducible way to script iTerm for CI/debugging.
Input Debugging
- Export
POLTERGEIST_INPUT_DEBUG=1before launching the panel to capture raw input bytes.POLTERGEIST_INPUT_DEBUG=1 pnpm exec tsx src/cli.ts panel # or via mcporter/iterm-mcp ./runner pnpm run mcporter call 'iterm.write_to_terminal(command: "cd ~/Projects/poltergeist && POLTERGEIST_INPUT_DEBUG=1 pnpm exec tsx src/cli.ts panel")' - Raw input events are appended to
/tmp/poltergeist-panel-input.logas hex + decoded text:tail -n20 /tmp/poltergeist-panel-input.log # [PanelInputDebug] 2025-11-15T14:31:42.123Z bytes=71 text="q" - Use this log to map iTerm/tmux escape sequences; bind them explicitly if needed.
- If the log stops updating while iTerm shows the panel, the MCP bridge may be hung—kill/restart iTerm and relaunch via mcporter.
- A scripted flow that reliably works today:
-
./runner pnpm run mcporter call \ 'iterm.send_keys(text: "cd ~/Projects/poltergeist && ./scripts/run-panel-once.sh\r")'-
./runner pnpm run mcporter call 'iterm.send_keys(text: "q")'
-
-
-
tail -n20 /tmp/panel.logconfirms you saw[panel] starting/closed, andtail -n20 /tmp/poltergeist-panel-input.logshowsbytes=71+exit via q. If the log doesn’t update, the keystroke never reached the panel—relaunch iTerm and retry.