|
| 1 | +# tmux-viewer |
| 2 | + |
| 3 | +Interactive TUI for viewing tmux session logs. Designed to work for **both humans and AIs**. |
| 4 | + |
| 5 | +## Usage |
| 6 | + |
| 7 | +```bash |
| 8 | +# Interactive TUI (for humans) |
| 9 | +bun scripts/tmux/tmux-viewer/index.tsx <session-name> |
| 10 | + |
| 11 | +# Start in replay mode (auto-plays through captures like a video) |
| 12 | +bun scripts/tmux/tmux-viewer/index.tsx <session-name> --replay |
| 13 | + |
| 14 | +# JSON output (for AIs) |
| 15 | +bun scripts/tmux/tmux-viewer/index.tsx <session-name> --json |
| 16 | + |
| 17 | +# Export as animated GIF |
| 18 | +bun scripts/tmux/tmux-viewer/index.tsx <session-name> --export-gif output.gif |
| 19 | + |
| 20 | +# Export with custom frame delay (default: 1500ms) |
| 21 | +bun scripts/tmux/tmux-viewer/index.tsx <session-name> --export-gif output.gif --frame-delay 2000 |
| 22 | + |
| 23 | +# Export with custom font size (default: 14px) |
| 24 | +bun scripts/tmux/tmux-viewer/index.tsx <session-name> --export-gif output.gif --font-size 16 |
| 25 | + |
| 26 | +# List available sessions |
| 27 | +bun scripts/tmux/tmux-viewer/index.tsx --list |
| 28 | + |
| 29 | +# View most recent session (if no session specified) |
| 30 | +bun scripts/tmux/tmux-viewer/index.tsx |
| 31 | +``` |
| 32 | + |
| 33 | +Or using the npm script: |
| 34 | + |
| 35 | +```bash |
| 36 | +cd scripts/tmux && bun run view-session <session-name> |
| 37 | +``` |
| 38 | + |
| 39 | +## Layout |
| 40 | + |
| 41 | +The TUI uses a vertical layout designed for clarity: |
| 42 | + |
| 43 | +``` |
| 44 | +┌─────────────────────────────────────────────────────────────────┐ |
| 45 | +│ Session: my-session 120x30 5 cmds 10 captures │ ← Header |
| 46 | +├─────────────────────────────────────────────────────────────────┤ |
| 47 | +│ │ |
| 48 | +│ ┌──────────────────┐ │ |
| 49 | +│ │ [terminal output │ │ ← Capture |
| 50 | +│ │ centered in │ │ View |
| 51 | +│ │ muted border] │ │ |
| 52 | +│ └──────────────────┘ │ |
| 53 | +│ │ |
| 54 | +├─ ⏸ Paused ──────────────────────────────────────────────────────┤ |
| 55 | +│ ┌─○ [1] 12:00:00─┐ ┌─▶ [2] 12:00:05─┐ ┌─○ [3] 12:00:10─┐ │ ← Timeline |
| 56 | +│ │ initial-state │ │ after-command │ │ final-state │ │ Cards |
| 57 | +│ │ $ codebuff... │ │ $ /help │ │ $ /quit │ │ |
| 58 | +│ └────────────────┘ └────────────────┘ └────────────────┘ │ |
| 59 | +├─────────────────────────────────────────────────────────────────┤ |
| 60 | +│ ▶ 2/10 @1.5s space: play/pause +/-: speed ←→: navigate │ ← Footer |
| 61 | +└─────────────────────────────────────────────────────────────────┘ |
| 62 | +``` |
| 63 | + |
| 64 | +- **Header**: Session name, dimensions, command/capture counts |
| 65 | +- **Capture View**: Terminal output centered with a muted border showing exact capture dimensions |
| 66 | +- **Timeline**: Horizontal card-style navigation at the bottom, selected card stays centered |
| 67 | +- **Footer**: Playback status, position, speed, and keyboard shortcuts |
| 68 | + |
| 69 | +## Features |
| 70 | + |
| 71 | +### For Humans (Interactive TUI) |
| 72 | +- **Capture view**: Terminal output centered with visible boundary |
| 73 | +- **Timeline panel**: Card-style navigation at the bottom with label and triggering command |
| 74 | +- **Auto-centering**: Selected timeline card stays centered in view |
| 75 | +- **Metadata display**: Session info, dimensions, command count |
| 76 | +- **Replay mode**: Auto-play through captures like a video player |
| 77 | +- **Keyboard shortcuts**: |
| 78 | + - `←` / `→` or `h` / `l`: Navigate between captures |
| 79 | + - `Space`: Play/pause replay |
| 80 | + - `+` / `-`: Adjust playback speed (faster/slower) |
| 81 | + - `r`: Restart from beginning |
| 82 | + - `q` or Ctrl+C: Quit |
| 83 | + - Use the `--json` flag on the CLI entrypoint for JSON output |
| 84 | + |
| 85 | +### Replay Mode |
| 86 | + |
| 87 | +Replay mode auto-advances through captures chronologically, like a video player: |
| 88 | + |
| 89 | +```bash |
| 90 | +# Start replay immediately |
| 91 | +bun scripts/tmux/tmux-viewer/index.tsx my-session --replay |
| 92 | + |
| 93 | +# Or press Space in the TUI to start/stop replay |
| 94 | +``` |
| 95 | + |
| 96 | +**Playback controls:** |
| 97 | +- `Space` - Toggle play/pause |
| 98 | +- `+` or `=` - Speed up (shorter interval between captures) |
| 99 | +- `-` or `_` - Slow down (longer interval between captures) |
| 100 | +- `r` - Restart from the first capture |
| 101 | +- `←` / `→` - Navigate captures (automatically pauses replay) |
| 102 | + |
| 103 | +**Available speeds:** 0.5s, 1.0s, 1.5s (default), 2.0s, 3.0s, 5.0s per capture |
| 104 | + |
| 105 | +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. |
| 106 | + |
| 107 | +### For AIs (JSON Output) |
| 108 | +Use the `--json` flag to get structured output: |
| 109 | + |
| 110 | +```json |
| 111 | +{ |
| 112 | + "session": { |
| 113 | + "session": "cli-test-1234567890", |
| 114 | + "started": "2025-01-01T12:00:00Z", |
| 115 | + "dimensions": { "width": 120, "height": 30 }, |
| 116 | + "status": "active" |
| 117 | + }, |
| 118 | + "commands": [ |
| 119 | + { "timestamp": "...", "type": "text", "input": "/help", "auto_enter": true } |
| 120 | + ], |
| 121 | + "captures": [ |
| 122 | + { |
| 123 | + "sequence": 1, |
| 124 | + "label": "initial-state", |
| 125 | + "timestamp": "...", |
| 126 | + "after_command": null, |
| 127 | + "dimensions": { "width": 120, "height": 30 }, |
| 128 | + "path": "debug/tmux-sessions/.../capture-001-initial-state.txt", |
| 129 | + "content": "[terminal output]" |
| 130 | + } |
| 131 | + ], |
| 132 | + "timeline": [ |
| 133 | + { "timestamp": "...", "type": "command", "data": {...} }, |
| 134 | + { "timestamp": "...", "type": "capture", "data": {...} } |
| 135 | + ] |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +## Data Format |
| 140 | + |
| 141 | +The viewer reads YAML-formatted session data from `debug/tmux-sessions/{session}/`: |
| 142 | + |
| 143 | +- `session-info.yaml` - Session metadata |
| 144 | +- `commands.yaml` - Array of commands sent |
| 145 | +- `capture-*.txt` - Capture files with YAML front-matter |
| 146 | + |
| 147 | +### Session Info (session-info.yaml) |
| 148 | +```yaml |
| 149 | +session: cli-test-1234567890 |
| 150 | +started: 2025-01-01T12:00:00Z |
| 151 | +started_local: Wed Jan 1 12:00:00 PST 2025 |
| 152 | +dimensions: |
| 153 | + width: 120 |
| 154 | + height: 30 |
| 155 | +status: active |
| 156 | +``` |
| 157 | +
|
| 158 | +### Commands (commands.yaml) |
| 159 | +```yaml |
| 160 | +- timestamp: 2025-01-01T12:00:05Z |
| 161 | + type: text |
| 162 | + input: "/help" |
| 163 | + auto_enter: true |
| 164 | +``` |
| 165 | +
|
| 166 | +### Capture Files (capture-001-label.txt) |
| 167 | +```yaml |
| 168 | +--- |
| 169 | +sequence: 1 |
| 170 | +label: initial-state |
| 171 | +timestamp: 2025-01-01T12:00:30Z |
| 172 | +after_command: null |
| 173 | +dimensions: |
| 174 | + width: 120 |
| 175 | + height: 30 |
| 176 | +--- |
| 177 | +[terminal content here] |
| 178 | +``` |
| 179 | + |
| 180 | +## Integration with cli-ui-tester |
| 181 | + |
| 182 | +The `@cli-ui-tester` agent can use this viewer to inspect session data: |
| 183 | + |
| 184 | +```typescript |
| 185 | +// In cli-ui-tester output |
| 186 | +{ |
| 187 | + captures: [ |
| 188 | + { path: "debug/tmux-sessions/cli-test-123/capture-001-initial.txt", label: "initial" } |
| 189 | + ] |
| 190 | +} |
| 191 | + |
| 192 | +// Parent agent can view the session |
| 193 | +// bun scripts/tmux/tmux-viewer/index.tsx cli-test-123 --json |
| 194 | +``` |
| 195 | + |
| 196 | +## GIF Export |
| 197 | + |
| 198 | +The `--export-gif` flag renders the session replay as an animated GIF, perfect for: |
| 199 | +- Sharing CLI demonstrations |
| 200 | +- Embedding in documentation |
| 201 | +- Bug reports and issue tracking |
| 202 | +- Creating tutorials |
| 203 | + |
| 204 | +### GIF Export Options |
| 205 | + |
| 206 | +| Option | Description | Default | |
| 207 | +|--------|-------------|--------| |
| 208 | +| `--export-gif [path]` | Output file path | `<session>-<timestamp>.gif` | |
| 209 | +| `--frame-delay <ms>` | Delay between frames in milliseconds | `1500` | |
| 210 | +| `--font-size <px>` | Font size for terminal text | `14` | |
| 211 | + |
| 212 | +### Examples |
| 213 | + |
| 214 | +```bash |
| 215 | +# Basic export (auto-names the file) |
| 216 | +bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif |
| 217 | + |
| 218 | +# Specify output path |
| 219 | +bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif demo.gif |
| 220 | + |
| 221 | +# Fast playback (500ms per frame) |
| 222 | +bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif fast.gif --frame-delay 500 |
| 223 | + |
| 224 | +# Larger text for readability |
| 225 | +bun scripts/tmux/tmux-viewer/index.tsx my-session --export-gif large.gif --font-size 18 |
| 226 | +``` |
| 227 | + |
| 228 | +### GIF Output |
| 229 | + |
| 230 | +The exported GIF includes: |
| 231 | +- Terminal content rendered as monospace text |
| 232 | +- Frame labels showing capture sequence number and label |
| 233 | +- Timestamps for each frame |
| 234 | +- Dark terminal-style background |
| 235 | +- Automatic sizing based on terminal dimensions |
| 236 | + |
| 237 | +## Development |
| 238 | + |
| 239 | +```bash |
| 240 | +# Typecheck |
| 241 | +cd scripts/tmux/tmux-viewer && bun x tsc --noEmit |
| 242 | + |
| 243 | +# Run directly |
| 244 | +bun scripts/tmux/tmux-viewer/index.tsx --list |
| 245 | +``` |
0 commit comments