Large Language Models

Recording Chat Transcripts

Published 2025-12-13. Last modified 2025-12-14.
Time to read: 1 minutes.

This page is part of the llm collection.

Command-line interface (CLI) chat clients like ollama, ChatGPT, and Mini-Agent are very useful, but most of them suffer from a few serious problems:

  1. They do not provide a way to save a transcript of the entire session.
  2. The scrollback buffer is limited in size. For a chat client, that means you can only see the last few screens of dialog before it is lost forever.
  3. Transcripts cannot be searched or summarized.

This article discusses the record Bash script that provides a universal solution to that problem.

The record Script

record
#!/bin/bash

# Mike Slinn mslinn@mslinn.com

# Default values:
CHAT_COMMAND="mini-agent" # Put your favorite chat command here
# CHAT_COMMAND="ollama run qwen3:4b" # Example of running a ollama model
OUTFILE_BASE="chat"
STRIP_ANSI=false

check_pyte_installed() {
    python3 -c "import pyte" 2>/dev/null
    return $?
}

usage() {
    local pyte_note=""
    if ! check_pyte_installed; then
        pyte_note="    Note: Requires pyte (install with: pip3 install pyte)"
    fi

    echo "
Usage: $(basename $0) [-a] [-o BASENAME] [-c COMMAND] [COMMAND_ARGS...]

Output defaults to a noisy timestamped .log file, viewable with less.

Options:
  -a  Record with ttyrec for playback with ttyplay
      (saves a .ttyrec file type instead of .log file type)
  -c  Specify the command to run the chat client (default: ${CHAT_COMMAND})
  -o  Specify the base name for the log file (default: ${OUTFILE_BASE})

Examples:
  $(basename $0)
      Runs the default client with the default output file base name

  $(basename $0) -c mini-agent -o inspect
      Run mini-agent and save to a log file with 'inspect' in the name

  $(basename $0) -c 'ollama run qwen3:4b' -o prototyping
      Run ollama model and save to a log file with 'prototyping' in the name

  $(basename $0) -a -c claude -o claude_session
      Run claude and save as ttyrec for interactive playback

Viewing recordings:
  Timed playback (.ttyrec files only):
    ttyplay 2025-12-12_20-06-39_chat.ttyrec

    ttyplay controls: 0=pause, 1-9=set speed, +=faster, -=slower
                      Note: No rewind support, includes all redraws

  Clean text view (.ttyrec or .log files):
    record_clean 2025-12-12_20-06-39_chat.ttyrec | less
    record_clean 2025-12-12_20-06-39_chat.log | less

    Removes redraws and produces readable text for browsing with less/vim
${pyte_note}
"
  exit 1
}

while getopts ":ao:c:h" opt; do
  case $opt in
    a)
      STRIP_ANSI=true
      ;;
    c)
      CHAT_COMMAND="$OPTARG"
      ;;
    o)
      OUTFILE_BASE="$OPTARG"
      ;;
    *)
      usage
      ;;
  esac
done
shift $((OPTIND-1))

if [ -z "$CHAT_COMMAND" ]; then
  echo "Error: You must specify a chat client command using -c."
  usage
fi

# Check if ttyrec is installed when -a option is used
if [ "$STRIP_ANSI" = true ]; then
  if ! command -v ttyrec &> /dev/null; then
    echo "Error: ttyrec is not installed."
    echo ""
    echo "To install ttyrec (includes ttyplay for playback):"
    echo "  Ubuntu/Debian: sudo apt-get install ttyrec"
    echo "  Fedora/RHEL:   sudo dnf install ttyrec"
    echo "  macOS:         brew install ttyrec"
    echo ""
    exit 1
  fi
fi

# Set file extension based on recording method
if [ "$STRIP_ANSI" = true ]; then
  LOG_FILE="$(date +\%Y-\%m-\%d_\%H-\%M-\%S)_${OUTFILE_BASE}.ttyrec"
else
  LOG_FILE="$(date +\%Y-\%m-\%d_\%H-\%M-\%S)_${OUTFILE_BASE}.log"
fi

if [ "$CHAT_COMMAND" != mini-agent ]; then
  echo "Press Ctrl+D to end the chat and stop recording."
fi

# Execute the recording command
if [ "$STRIP_ANSI" = true ]; then
  # Use ttyrec for recording
  ttyrec -e "$CHAT_COMMAND" "$LOG_FILE"
  echo "Recording finished. Playback with: ttyplay $PWD/$LOG_FILE"
else
  # Use script for plain log recording
  script -a "$LOG_FILE" -c "$CHAT_COMMAND"
  echo "Recording finished. Log saved to $PWD/$LOG_FILE"
fi

# Remind user about pyte if not installed
if ! check_pyte_installed; then
  echo ""
  echo "Tip: For clean text view (removes redraws), install pyte:"
  echo "  pip3 install pyte"
  echo "  record_clean $PWD/$LOG_FILE | less"
fi

Help Message

This is the record help message:

Shell
$ record -h
Usage: record [-a] [-o BASENAME] [-c COMMAND] [COMMAND_ARGS...] Output defaults to a noisy timestamped .log file, viewable with less. Options: -a Record with ttyrec for playback with ttyplay (saves a .ttyrec file type instead of .log file type) -c Specify the command to run the chat client (default: mini-agent) -o Specify the base name for the log file (default: chat) Examples: record Runs the default client with the default output file base name record -c mini-agent -o inspect Run mini-agent and save to a log file with 'inspect' in the name record -c 'ollama run qwen3:4b' -o prototyping Run ollama model and save to a log file with 'prototyping' in the name record -a -c claude -o claude_session Run claude and save as ttyrec for interactive playback Viewing recordings: Timed playback (.ttyrec files only): ttyplay 2025-12-12_20-06-39_chat.ttyrec ttyplay controls: 0=pause, 1-9=set speed, +=faster, -=slower Note: No rewind support, includes all redraws Clean text view (.ttyrec or .log files): record_clean 2025-12-12_20-06-39_chat.ttyrec | less record_clean 2025-12-12_20-06-39_chat.log | less Removes redraws and produces readable text for browsing with less/vim

Using the -a option causes the replay to be saved as a file with a .ttyrec extension.

Usage Examples

Examples of usage are provided in:

Log Playback

If you did not use the -a option, you could review the session later by typing:

Shell
$ less 2025-12-12_20-06-39_chat.log

The session log will probably have ANSI escape characters in it. You can use the ansi2txt command to remove them.

Shell
$ ansi2txt < 2025-12-14_12-16-20_chat.log > 2025-12-14_12-16-20_clean_chat.log

You could also view the log of the live session delayed by a few seconds by using tail -F:

Shell
$ tail -F 2025-12-12_20-06-39_chat.log

This is an easy way to share a chat with an audience. Everyone in the audience would use SSH to connect to the machine running the chat, then they would all use the above tail -F command.

TTYPlay

This is the man page for ttyplay:

man ttyplay
TTYPLAY(1) General Commands Manual TTYPLAY(1)

NAME
ttyplay - player of the tty session recorded by ttyrec

SYNOPSIS
ttyplay [-s SPEED] [-n] [-p] file

DESCRIPTION
Ttyplay plays the tty session in file, which was recorded previΓÇÉ
ously by ttyrec(1).

When -p option is given, ttyplay output the file as it grows.
It means that you can see the "live" shell session running by
another user.

If you hit any key during playback, it will go right to the next
character typed. This is handy when examining sessions where a
user spends a lot of time at a prompt.

Additionally, there are some special keys defined:

+ or f
double the speed of playback.

- or s
halve the speed of playback.

0 set playback speed to 0, pausing playback.

1 set playback to speed 1.0 again.

q quit.

OPTIONS
-s SPEED
multiply the playing speed by SPEED (default is 1).

-n no wait mode. Ignore the timing information in file.

-p peek another person's tty session.

SEE ALSO
script(1), ttyrec(1), ttytime(1)

TTYPLAY(1)

Interact with a keystroke-by-keystroke replay with:

Shell
$ ttyplay 2025-12-12_20-06-39_test_plan.ttyrec
* indicates a required field.

Please select the following to receive Mike Slinn’s newsletter:

You can unsubscribe at any time by clicking the link in the footer of emails.

Mike Slinn uses Mailchimp as his marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp’s privacy practices.