Skip to content

Terminal Mastery

You have Claude Code running in one terminal tab, your dev server in another, test output in a third, and git log in a fourth. You are constantly switching tabs, losing track of which one has the output you need. Then Claude finishes a task and you miss the notification because you were reading logs in a different tab.

Power users solve this with terminal multiplexers. One screen, multiple panes, Claude Code always visible.

  • A tmux configuration optimized for Claude Code workflows
  • Multi-pane layouts for development, debugging, and review
  • Shell integration patterns that pipe data into Claude Code
  • Notification strategies so you never miss when Claude finishes

The ideal layout has three or four panes:

+----------------------------+------------------+
| | |
| Claude Code | Dev Server |
| (main pane) | (top-right) |
| | |
+----------------------------+------------------+
| | |
| Editor / Files | Test Output |
| (bottom-left) | (bottom-right) |
| | |
+----------------------------+------------------+

Add to ~/.tmux.conf for fast pane switching:

# Use Alt+arrow to switch panes without prefix
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# Increase history for scrollback
set -g history-limit 50000

The real power of CLI-first development is piping. Every shell command’s output can become Claude Code input:

Terminal window
# Analyze test failures
npm run test 2>&1 | claude -p "What are the root causes of these test failures? Group by category."
# Explain complex git history
git log --oneline --graph --since="1 week ago" | claude -p "Summarize the development activity this week."
# Debug build errors
npm run build 2>&1 | claude -p "Fix these TypeScript build errors. Show me the exact changes needed."
# Analyze dependency vulnerabilities
npm audit --json | claude -p "Which of these vulnerabilities are critical and what are the upgrade paths?"

Build multi-step pipelines that use Claude Code as a processing step:

Terminal window
# Generate a changelog from commits
git log --oneline v1.2.0..HEAD | \
claude -p "Generate a user-facing changelog from these commits. Group by: Features, Bug Fixes, Performance." \
--output-format text > CHANGELOG-draft.md
# Create a PR description from the diff
git diff main...HEAD | \
claude -p "Write a PR description for these changes. Include: Summary, Changes Made, Testing Notes." \
--output-format text

Run multiple Claude Code instances for different concerns. The first run in each pane starts a fresh session; -r/--resume then resumes it by name on later runs (resume does not create a session — pointing it at a name that does not exist drops you into the interactive picker):

Terminal window
# Terminal 1: Main development -- start fresh, resume by name later
claude # later: claude -r "feature-work"
# Terminal 2: Background code review (separate tmux pane)
claude --model sonnet # later: claude -r "review-session" --model sonnet
# Terminal 3: Test debugging (another pane) -- pin the ID up front to resume deterministically
claude --session-id "550e8400-e29b-41d4-a716-446655440000"

Each session maintains its own context. The feature work session knows about your architecture decisions. The review session focuses on code quality. The test session tracks test patterns and failures. Use --session-id <uuid> when you want a known handle to resume later; otherwise let the session be created on first run and resume it by name.

Monitor a process and feed its output to Claude Code when something goes wrong:

Terminal window
# Watch test output and analyze the FIRST failure of each run automatically.
# A naive version fires `claude -p` on every line matching FAIL -- on a noisy
# suite that is dozens of API calls per save (cost and rate-limit blow-up).
# The `triggered` guard limits it to one analysis per run; the test runner
# clearing the screen resets it for the next run.
triggered=0
npm run test:watch 2>&1 | while IFS= read -r line; do
echo "$line"
case "$line" in
*"Watching for file changes"*|*"Ran all test suites"*) triggered=0 ;;
*FAIL*)
if [ "$triggered" -eq 0 ]; then
triggered=1
echo "$line" | claude -p "This test just failed. What is the likely cause based on the error message?"
fi
;;
esac
done

Configure Claude Code to play a sound when it finishes:

{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "afplay /System/Library/Sounds/Glass.aiff"
}
]
}
]
}
}

Most terminal emulators can flash or bounce in the dock when a bell character is received:

{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "printf '\\a'"
}
]
}
]
}
}

tmux scrollback does not capture Claude Code output: Increase your history limit with set -g history-limit 50000 in ~/.tmux.conf. Claude Code sessions can produce thousands of lines.

Piped output is too large for Claude Code: When piping large outputs, use head or tail to limit the input. Claude Code works best with focused context, not 10,000 lines of logs.

Multiple Claude Code instances hit rate limits: Each instance consumes tokens independently. If you are running three parallel sessions, your token usage triples. Watch your /cost across all sessions.

Notification sounds play during meetings: Gate the sound on volume. Avoid output muted of (get volume settings) — on many macOS setups it returns missing value rather than true/false, so the guard reads as not-muted and the sound plays anyway. Check the level instead: [[ "$(osascript -e 'output volume of (get volume settings)')" -gt 0 ]] && afplay /System/Library/Sounds/Glass.aiff.