Bash shell: Interactive Menu to Insert any String from the Tmux Scrollback Buffer Into the Shell Prompt

Imagine you’re working in a tmux session, navigating logs, editing config files, or running commands, and you suddenly need to reuse a path, variable name, or keyword that appeared earlier on the tmux scrollback buffer. Instead of scrolling back or retyping it manually, you press Ctrl-n, type a few fuzzy letters, press enter, and the desired string from the tmux scrollback is instantly inserted at your cursor.

The tmux scrollback buffer is the internal history of terminal output that tmux maintains for each pane. It consists of the lines that have scrolled off the visible screen but are still accessible for review or processing.

This article presents a Bash function that scans the tmux scrollback buffer, lets you interactively select strings using fzf, and inserts the chosen string directly into the command line prompt. It offers a fast, context-aware mechanism for inline string insertion, allowing you to work efficiently without breaking your flow.

Requirements

Implementation using Bash functions and readline

Add the following code snippet to your ~/.bashrc to bind Ctrl-n for selecting strings from the tmux scrollback buffer using fzf, and inserting the selected string directly into the shell prompt:

#!/usr/bin/env bash
# Author: James Cherti
# License: MIT
# URL: https://www.jamescherti.com/tmux-autocomplete-fzf-fuzzy-insertion-scrollback/

__tmux_fzf_autocomplete__() {
  # Capture the last 100,000 lines from the tmux scrollback buffer, reverse
  # order, and extract strings
  tmux capture-pane -pS -100000 \
    |
    # Split input on spaces and newlines, remove duplicates while preserving
    # order, and keep only strings longer than 4 characters
    awk 'BEGIN { RS = "[ \t\n]" } length($0) > 4 && !seen[$0]++' \
    |
    # Invoke fzf for case-insensitive exact fuzzy matching, with results shown
    # in reverse order
    fzf --no-sort --exact +i --tac
}

__tmux_fzf_autocomplete_inline__() {
  local selected
  selected="$(__tmux_fzf_autocomplete__)"

  local before
  before="${READLINE_LINE:0:$READLINE_POINT}"

  local after
  after="${READLINE_LINE:$READLINE_POINT}"
  
  READLINE_LINE="${before}${selected}${after}"
  READLINE_POINT=$((READLINE_POINT + ${#selected}))
}

# Pressing Ctrl-n autocompletes from the Tmux scrollback buffer
bind -x '"\C-n": "__tmux_fzf_autocomplete_inline__"'Code language: Bash (bash)

Key components:

  • tmux capture-pane: Retrieves the scrollback content from the active tmux pane.
  • awk: Processes tokens, removes duplicates, and filters out strings shorter than 5 characters to produce a concise list.
  • fzf: Offers an interactive fuzzy interface for filtering and selecting the desired token. The --tac flag reverses the line order, prioritizing the most recent content.
  • bind: Inserts the selected token inline at the Bash prompt using a readline binding, activated by Ctrl-n. This binding does not interfere with typical command-line editing, preserves the existing prompt content, and updates the cursor position correctly.

Conclusion

The code snippet in this article enhances the Bash shell by turning the tmux scrollback buffer into a live source of contextual string insertion. Within tmux workflows, it removes the need to scroll through output, improving both speed and accuracy during command-line tasks.

Related Links

  • This function is included in the author’s .bashrc, which is available in the jc-dotfiles repository.

A tool to Execute a Command in a new Tmux Window

The Python script tmux-run.py allows executing a command in a new tmux window. A tmux window is similar to a tab in other software.

If the script is executed from within a tmux session, it creates a tmux window in the same tmux session. However, if the script is executed from outside of a tmux session, it creates a new tmux window in the first available tmux session.

(Requirement: libtmux)

The Python script: tmux-run.py

#!/usr/bin/env python
# License: MIT
# Author: James Cherti
# URL: https://www.jamescherti.com/python-script-run-command-new-tmux-window/
"""Execute a command in a new tmux window.

This script allows executing a command in a new tmux window (a tmux window is
similar to a tab in other software).

- If it is executed from within a tmux session, it creates a tmux window
in the same tmux session.
- However, if the script is executed from outside of a tmux
session, it creates a new tmux window in the first available tmux session.

"""

import os
import shlex
import shutil
import sys

import libtmux


SCRIPT_NAME = os.path.basename(sys.argv[0])


def parse_args():
    if len(sys.argv) < 2:
        print(f"Usage: {SCRIPT_NAME} <command> [args...]",
              file=sys.stderr)
        sys.exit(1)

    args = sys.argv[1:]
    args[0] = shutil.which(args[0])
    if args[0] is None:
        print(f"{SCRIPT_NAME}: no {args[0]} in "
              f"({os.environ.get('PATH', '')})", file=sys.stderr)
        sys.exit(1)

    return args


def get_tmux_session():
    tmux_server = libtmux.Server()
    if not tmux_server.sessions:
        print(f"{SCRIPT_NAME}: the tmux session was not found",
              file=sys.stderr)
        sys.exit(1)

    tmux_session_id = os.environ["TMUX"].split(",")[-1]
    if tmux_session_id:
        try:
            return tmux_server.sessions.get(id=f"${tmux_session_id}")
        except Exception:  # pylint: disable=broad-except
            pass

    return tmux_server.sessions[0]


def run_in_tmux_window():
    try:
        command_args = parse_args()
        tmux_session = get_tmux_session()
        command_str = shlex.join(command_args)
        tmux_session.new_window(attach=True, window_shell=command_str)
    except libtmux.exc.LibTmuxException as err:
        print(f"Error: {err}.", file=sys.stderr)
        sys.exit(1)


if __name__ == '__main__':
    run_in_tmux_window()


Code language: Python (python)