Skip to content

Instantly share code, notes, and snippets.

@hereisderek
Last active September 21, 2026 06:37
Show Gist options
  • Select an option

  • Save hereisderek/8f41efc72e5b2f60b1089041bb1fc388 to your computer and use it in GitHub Desktop.

Select an option

Save hereisderek/8f41efc72e5b2f60b1089041bb1fc388 to your computer and use it in GitHub Desktop.
asciinema auto record shell
# Define the alias for ALL shells so you can use it inside the recording
alias term-record="~/.config/asciinema/auto_asciinema.sh"
# Optional: Ensure it's executable (only needs to be run once, but fine to leave here)
chmod +x ~/.config/asciinema/auto_asciinema.sh
# Start Asciinema Auto-Record wrapper ONLY if attached to a real TTY (-t 0)
if [[ $- == *i* && -z "$ASCIINEMA_REC" && -t 0 ]]; then
~/.config/asciinema/auto_asciinema.sh auto
# Close the outer shell window cleanly when the inner recording shell exits
[ $? -eq 0 ] && exit
fi
# alias term-record="~/.config/asciinema/auto_asciinema.sh"; chmod +x ~/.config/asciinema/auto_asciinema.sh; [[ $- == *i* && -z "$ASCIINEMA_REC" && -t 0 ]] && ~/.config/asciinema/auto_asciinema.sh auto && exit
#!/usr/bin/env bash
# ==========================================
# Configuration (Easily Modifiable Constants)
# ==========================================
RECORD_DIR="${HOME}/.config/asciinema/records"
PENDING_DIR="${HOME}/.config/asciinema/pending_upload"
AUTO_SAVE_DIR="${HOME}/.config/asciinema/auto_save"
DEFAULT_FILENAME="$(hostname)_$(date +%Y%m%d_%H%M%S).cast"
# ==========================================
# Help Menu
# ==========================================
show_help() {
cat << 'EOF'
Usage: term-record [command] [options]
Commands:
auto Start auto-recording (use in your shell profile)
save [name] [local|upload] Stop recording, save the cast, and KEEP the terminal open
-h, --help Show this help message
Examples:
term-record save # Saves current session with default name and stops recording
term-record save my_script # Saves as my_script.cast locally and stops recording
term-record save my_script upload # Uploads session to asciinema.org and stops recording
EOF
}
# ==========================================
# Script Logic
# ==========================================
# Show help if requested or if no arguments are provided
if [ -z "$1" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
show_help
exit 0
fi
# The interactive command to save/upload the session
if [ "$1" = "save" ]; then
if [ -z "$ASCIINEMA_REC" ] || [ -z "$ASCIINEMA_OUTER_PID" ]; then
echo "Error: Not currently in an auto-recorded asciinema session."
exit 1
fi
INTENT_NAME="${2:-$DEFAULT_FILENAME}"
INTENT_DEST="${3:-local}"
# Save intent for the wrapper, adding a KEEP_OPEN flag
echo "${INTENT_NAME}|${INTENT_DEST}|KEEP_OPEN" > "/tmp/asciinema_intent_$ASCIINEMA_OUTER_PID"
echo "Stopping recording..."
echo "File will be processed as '${INTENT_NAME}' for '${INTENT_DEST}'."
# Kill the parent process (the inner shell) to seamlessly end the asciinema recording
kill -HUP $PPID
exit 0
fi
# The automated wrapper logic
if [ "$1" = "auto" ]; then
# 1. Install check
if ! command -v asciinema >/dev/null 2>&1; then
echo "asciinema is not installed, but auto-recording is enabled."
printf "Would you like to install it now? (y/n): "
read -r REPLY < /dev/tty
if [[ $REPLY =~ ^[Yy]$ ]]; then
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update && sudo apt-get install -y asciinema
elif command -v brew >/dev/null 2>&1; then
brew install asciinema
elif command -v pacman >/dev/null 2>&1; then
sudo pacman -S --noconfirm asciinema
elif command -v dnf >/dev/null 2>&1; then
sudo dnf install -y asciinema
else
echo "Could not detect package manager. Please install asciinema manually."
fi
fi
if ! command -v asciinema >/dev/null 2>&1; then
echo "Skipping auto-record for this session (asciinema not installed)."
exit 2
fi
fi
# 2. Setup directories
mkdir -p "$RECORD_DIR" "$PENDING_DIR" "$AUTO_SAVE_DIR"
# 3. Process pending uploads from previous network drops
for pending in "$PENDING_DIR"/*.cast; do
[ -e "$pending" ] || continue
echo "Uploading pending session: $(basename "$pending")..."
if asciinema upload "$pending" >/dev/null 2>&1; then
echo "Upload successful."
rm -f "$pending"
else
echo "Upload still failing, will retry next time."
fi
done
# 4. Setup current session
export ASCIINEMA_OUTER_PID=$$
TEMP_CAST="/tmp/asciinema_auto_$ASCIINEMA_OUTER_PID.cast"
INTENT_FILE="/tmp/asciinema_intent_$ASCIINEMA_OUTER_PID"
rm -f "$INTENT_FILE"
# 5. Start recording (This blocks until the inner shell is closed)
asciinema rec -q "$TEMP_CAST"
# 6. Post-recording wrap-up
KEEP_OPEN=0
if [ -f "$TEMP_CAST" ]; then
FINAL_NAME="$DEFAULT_FILENAME"
FINAL_DEST="auto" # Default if no explicit save command is issued
if [ -f "$INTENT_FILE" ]; then
IFS='|' read -r FINAL_NAME FINAL_DEST FLAG < "$INTENT_FILE"
rm -f "$INTENT_FILE"
[ "$FLAG" = "KEEP_OPEN" ] && KEEP_OPEN=1
fi
# Ensure the filename ends in .cast
[[ "$FINAL_NAME" != *.cast ]] && FINAL_NAME="${FINAL_NAME}.cast"
if [ "$FINAL_DEST" = "upload" ]; then
echo "Uploading session $FINAL_NAME..."
if asciinema upload "$TEMP_CAST"; then
rm -f "$TEMP_CAST"
else
echo "Upload failed (network issue?). Moving to pending queue."
mv "$TEMP_CAST" "$PENDING_DIR/$FINAL_NAME"
fi
elif [ "$FINAL_DEST" = "local" ]; then
mv "$TEMP_CAST" "$RECORD_DIR/$FINAL_NAME"
echo "Session saved locally to $RECORD_DIR/$FINAL_NAME"
else
# Handles "auto" fallback when terminal is closed normally
mv "$TEMP_CAST" "$AUTO_SAVE_DIR/$FINAL_NAME"
echo "Session auto-saved to $AUTO_SAVE_DIR/$FINAL_NAME"
fi
fi
# 7. Smart Exit Logic
if [ "$KEEP_OPEN" -eq 1 ]; then
echo -e "\n\033[1;33m[!] Recording stopped. You are now in a standard, unrecorded session.\033[0m"
exit 3
else
exit 0
fi
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment