Interactive TUI for viewing tmux session logs. Designed to work for both humans and AIs.
# Interactive TUI (for humans)
bun scripts/tmux/tmux-viewer/index.tsx <session-name>
# Start in replay mode (auto-plays through captures like a video)
bun scripts/tmux/tmux-viewer/index.tsx <session-name> --replay
# JSON output (for AIs)
bun scripts/tmux/tmux-viewer/index.tsx <session-name> --json
# Export as animated GIF
bun scripts/tmux/tmux-viewer/index.tsx <session-name> --export-gif output.gif
# Export with custom frame delay (default: 1500ms)
bun scripts/tmux/tmux-viewer/index.tsx <session-name> --export-gif output.gif --frame-delay 2000
# Export with custom font size (default: 14px)
bun scripts/tmux/tmux-viewer/index.tsx <session-name> --export-gif output.gif --font-size 16
# List available sessions
bun scripts/tmux/tmux-viewer/index.tsx --list
# View most recent session (if no session specified)
bun scripts/tmux/tmux-viewer/index.tsxOr using the npm script:
cd scripts/tmux && bun run view-session <session-name>The TUI uses a vertical layout designed for clarity:
┌─────────────────────────────────────────────────────────────────┐
│ Session: my-session 120x30 5 cmds 10 captures │ ← Header
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ │
│ │ [terminal output │ │ ← Capture
│ │ centered in │ │ View
│ │ muted border] │ │
│ └──────────────────┘ │
│ │
├─ ⏸ Paused ──────────────────────────────────────────────────────┤
│ ┌─○ [1] 12:00:00─┐ ┌─▶ [2] 12:00:05─┐ ┌─○ [3] 12:00:10─┐ │ ← Timeline
│ │ initial-state │ │ after-command │ │ final-state │ │ Cards
│ │ $ codebuff... │ │ $ /help │ │ $ /quit │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ ▶ 2/10 @1.5s space: play/pause +/-: speed ←→: navigate │ ← Footer
└─────────────────────────────────────────────────────────────────┘
- Header: Session name, dimensions, command/capture counts
- Capture View: Terminal output centered with a muted border showing exact capture dimensions
- Timeline: Horizontal card-style navigation at the bottom, selected card stays centered
- Footer: Playback status, position, speed, and keyboard shortcuts
- Capture view: Terminal output centered with visible boundary
- Timeline panel: Card-style navigation at the bottom with label and triggering command
- Auto-centering: Selected timeline card stays centered in view
- Metadata display: Session info, dimensions, command count
- Replay mode: Auto-play through captures like a video player
- Keyboard shortcuts:
←/→orh/l: Navigate between capturesSpace: Play/pause replay+/-: Adjust playback speed (faster/slower)r: Restart from beginningqor Ctrl+C: Quit- Use the
--jsonflag on the CLI entrypoint for JSON output
Replay mode auto-advances through captures chronologically, like a video player:
# Start replay immediately
bun scripts/tmux/tmux-viewer/index.tsx my-session --replay
# Or press Space in the TUI to start/stop replayPlayback controls:
Space- Toggle play/pause+or=- Speed up (shorter interval between captures)-or_- Slow down (longer interval between captures)r- Restart from the first capture←/→- Navigate captures (automatically pauses replay)
Available speeds: 0.5s, 1.0s, 1.5s (default), 2.0s, 3.0s, 5.0s per capture
The timeline panel title shows ▶ Playing or ⏸ Paused, and the footer shows current position (e.g., 2/10), playback speed (e.g., @1.5s), and controls.
Use the --json flag to get structured output:
{
"session": {
"session": "cli-test-1234567890",
"started": "2025-01-01T12:00:00Z",
"dimensions": { "width": 120, "height": 30 },
"status": "active"
},
"commands": [
{ "timestamp": "...", "type": "text", "input": "/help", "auto_enter": true }
],
"captures": [
{
"sequence": 1,
"label": "initial-state",
"timestamp": "...",
"after_command": null,
"dimensions": { "width": 120, "height": 30 },
"path": "debug/tmux-sessions/.../capture-001-initial-state.txt",
"content": "[terminal output]"
}
],
"timeline": [
{ "timestamp": "...", "type": "command", "data": {...} },
{ "timestamp": "...", "type": "capture", "data": {...} }
]
}The viewer reads YAML-formatted session data from debug/tmux-sessions/{session}/:
session-info.yaml- Session metadatacommands.yaml- Array of commands sentcapture-*.txt- Capture files with YAML front-matter
session: cli-test-1234567890
started: 2025-01-01T12:00:00Z
started_local: Wed Jan 1 12:00:00 PST 2025
dimensions:
width: 120
height: 30
status: active- timestamp: 2025-01-01T12:00:05Z
type: text
input: "/help"
auto_enter: true---
sequence: 1
label: initial-state
timestamp: 2025-01-01T12:00:30Z
after_command: null
dimensions:
width: 120
height: 30
---
[terminal content here]The @cli-tester agent can use this viewer to inspect session data:
// In cli-tester output
{
captures: [
{ path: "debug/tmux-sessions/cli-test-123/capture-001-initial.txt", label: "initial" }
]
}
// Parent agent can view the session
// bun scripts/tmux/tmux-viewer/index.tsx cli-test-123 --jsonThe --export-gif flag renders the session replay as an animated GIF, perfect for:
- Sharing CLI demonstrations
- Embedding in documentation
- Bug reports and issue tracking
- Creating tutorials
| Option | Description | Default |
|---|---|---|
--export-gif [path] |
Output file path | <session>-<timestamp>.gif |
--frame-delay <ms> |
Delay between frames in milliseconds | 1500 |
--font-size <px> |
Font size for terminal text | 14 |
# Basic export (auto-names the file)
bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif
# Specify output path
bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif demo.gif
# Fast playback (500ms per frame)
bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif fast.gif --frame-delay 500
# Larger text for readability
bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif large.gif --font-size 18The exported GIF includes:
- Terminal content rendered as monospace text
- Frame labels showing capture sequence number and label
- Timestamps for each frame
- Dark terminal-style background
- Automatic sizing based on terminal dimensions
# Typecheck
cd scripts/tmux/tmux-viewer && bun x tsc --noEmit
# Run directly
bun scripts/tmux/tmux-viewer/index.tsx --list