2026-05-28
Every few years some kid rediscovers terminal recording and writes a tool named after a Greek letter. Meanwhile, script(1) has been quietly recording sessions since 3BSD shipped it in 1979, and its sibling scriptreplay(1) plays them back with the original keystroke timing intact. Both ship in util-linux on every Linux box you'll ever touch. No daemon. No JSON. No tarball of someone's JavaScript player. Just two binaries and a plain text log.
The basic loop:
$ script --timing=demo.tim demo.log
Script started, output file is demo.log
$ uname -a
$ ps aux | head -5
$ exit
Script done.
$ scriptreplay --timing=demo.tim demo.log
That second command isn't printing the file — it's re-playing the entire session at the original speed, including the pauses while you thought about what to type. Speed it up with --maxdelay 0.5 to cap dead air, or --divisor 4 for a 4x replay. The log itself is just raw bytes (escape codes and all), so cat demo.log shows the final state and grep works against it.
Why it beats the alternatives. asciinema is fine, but it requires an interpreter to play back, ships a custom JSON format, and tempts you to upload sessions to a third party. script outputs plain bytes and a timing file that's literally delay bytecount\n lines. You can hand-edit it. You can tail -f the log while the session runs. You can pipe it through ansifilter for a clean transcript. Try that with a JSON blob.
The flags nobody reads. Modern script (util-linux 2.32+) has grown teeth:
--log-io combined.log — record stdin and stdout interleaved. Audit logging gold.-E never — disable the ^[ escape prefix so embedded editors don't get confused.-c "command" — record a single non-interactive command. Perfect for cron-driven captures.-a — append to existing logs across sessions.--command with -q — silent recording for unattended jobs.The trick that earns its keep. Use it as a bug-report machine. Ask the user to run:
$ script -t 2>repro.tim repro.log -c "./our-broken-tool --verbose"
They mail you two files. You run scriptreplay and watch the exact failure unfold at real speed — every misread prompt, every twenty-second pause where they panicked, every typo they backspaced through. No more "works on my machine" because you're literally watching their machine.
Another use. Recording long-running deploys to an append log:
$ script -af -t 2>>/var/log/deploy.tim /var/log/deploy.log
Six months later when someone asks "what exactly did we type on the night of the outage," you have it byte-for-byte, with timing. auditd tells you which syscalls fired. script tells you what the human actually saw on the glass.
Gotcha. script allocates a PTY, so anything checking isatty(0) will behave as if a human is present. Usually what you want. Occasionally not — pipe-aware tools may emit color codes and progress bars that pollute the log. Use TERM=dumb inside the recorded shell to tame them.
script -t and scriptreplay have been waiting in /usr/bin the entire time, producing plain-text logs you can grep, edit, and replay without anyone's runtime.
