Posted on
Artificial Intelligence

Advanced Prompt Patterns

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Advanced Prompt Patterns for Bash: Turn Your Terminal Into a Heads-Up Display

If your terminal is your daily cockpit, your prompt is the instrument panel. A great prompt surfaces the right information at the right time—without noise—so you move faster, make fewer mistakes, and stay in flow. The problem? Most default Bash prompts are either cluttered or barren, and “cool prompt” one-liners from the internet often break on different distros or terminals.

This article lays out practical, advanced prompt patterns you can copy into your ~/.bashrc. You’ll get a responsive, informative, two-line prompt with context-aware indicators (user/host, directory, Python venv), Git status, exit codes, and command durations—without needing a giant framework. We’ll also show how to install and optionally switch to Starship if you prefer a managed solution.

Why this matters

  • Reduces errors: Clear root/SSH indicators help prevent accidental operations on the wrong machine.

  • Saves time: Git and venv hints keep you oriented; durations reveal slow commands right when you need to know.

  • Stays portable: Pure-Bash approach works across common Linux distributions with minimum external dependencies.

  • Extensible: Each “pattern” is a self-contained building block you can reuse or disable.

Prerequisites (optional but recommended)

  • Git (for Git-aware prompt)

  • bash-completion (nice to have; does not affect prompt but improves shell UX)

Install on your distro:

  • apt (Debian/Ubuntu):

    sudo apt update
    sudo apt install -y git bash-completion
    
  • dnf (Fedora/RHEL/CentOS Stream):

    sudo dnf install -y git bash-completion
    
  • zypper (openSUSE/SLE):

    sudo zypper install -y git bash-completion
    

Note: The Git package often includes a “git-prompt” helper script we’ll try to source automatically.


Core: Advanced Prompt Patterns (drop-in script)

Copy the following into the end of your ~/.bashrc, then run: source ~/.bashrc

# === Advanced Prompt Patterns for Bash ===

# 1) Colors (non-printing wrappers to keep readline cursor in sync)
RED='\[\e[31m\]'; GREEN='\[\e[32m\]'; YELLOW='\[\e[33m\]'; BLUE='\[\e[34m\]'
MAGENTA='\[\e[35m\]'; CYAN='\[\e[36m\]'; BOLD='\[\e[1m\]'; RESET='\[\e[0m\]'

# 2) Optional: Git prompt helpers (source distro script if present; provides __git_ps1)
for cand in \
  /usr/share/git-core/contrib/completion/git-prompt.sh \
  /usr/share/git/completion/git-prompt.sh \
  /usr/lib/git-core/git-sh-prompt \
; do
  [ -f "$cand" ] && . "$cand" && break
done

# Fallback if __git_ps1 is unavailable (tiny, fast-enough)
__git_ps1_fallback() {
  command -v git >/dev/null 2>&1 || return
  local b
  b="$(git symbolic-ref --quiet --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)" || return
  local marks=""
  git diff --no-ext-diff --quiet --ignore-submodules -- 2>/dev/null || marks="*"
  git diff --no-ext-diff --cached --quiet --ignore-submodules -- 2>/dev/null || marks="${marks}+"
  printf '%s%s' "$b" "$marks"
}

# 3) Timing and status + prompt builder
PROMPT_DIRTRIM=3  # keep last 3 path components in \w

__prompt_update() {
  local exit=$?
  # Timing
  local end=${EPOCHREALTIME:-$(date +%s.%N)}
  local start=${LAST_CMD_START:-$end}
  local dur
  dur=$(awk -v s="$start" -v e="$end" 'BEGIN{d=e-s; if (d>=1) printf "%.2fs", d; else if (d>=0.001) printf "%.0fms", d*1000; else printf "%dus", d*1000000}')
  # Show status if non-zero
  local status=""
  if (( exit != 0 )); then
    status="${RED}✗ ${exit}${RESET} "
  fi
  # Show duration if >= 100ms
  local timebit=""
  awk -v s="$start" -v e="$end" 'BEGIN{d=e-s; if (d>=0.1) exit 0; else exit 1}'
  if (( $? == 0 )); then
    timebit="${YELLOW}${dur}${RESET} "
  fi

  # User/host colors and symbol
  local usercolor hostcolor sym
  if (( EUID == 0 )); then usercolor="${RED}${BOLD}"; sym='#'; else usercolor="${GREEN}${BOLD}"; sym='$'; fi
  if [[ -n "$SSH_CONNECTION" || -n "$SSH_TTY" || -n "$SSH_CLIENT" ]]; then hostcolor="${MAGENTA}"; else hostcolor="${BLUE}"; fi

  # Python venv indicator
  local venv=""
  if [[ -n "$VIRTUAL_ENV" ]]; then
    venv=" ${YELLOW}($(basename "$VIRTUAL_ENV"))${RESET}"
  fi

  # Git piece (branch + marks)
  local gitpiece=""
  if type __git_ps1 >/dev/null 2>&1; then
    gitpiece="$(__git_ps1 '%s')"
  else
    gitpiece="$(__git_ps1_fallback 2>/dev/null)"
  fi
  if [[ -n "$gitpiece" ]]; then
    gitpiece=" ${MAGENTA}[${gitpiece}]${RESET}"
  fi

  # Two-line prompt:
  # line 1: status/time
  # line 2: user@host path [git] (venv)
  # line 3: $ or #
  PS1="${status}${timebit}\n${usercolor}\u${RESET}@${hostcolor}\h${RESET} ${CYAN}\w${RESET}${gitpiece}${venv}\n${sym} "
}
# Capture start time before each command
trap 'LAST_CMD_START=${EPOCHREALTIME:-$(date +%s.%N)}' DEBUG
PROMPT_COMMAND='__prompt_update'

What you get:

  • Context Capsule: user@host is color-coded (green for normal user, red for root; magenta host if SSH).

  • Smart Path: directory trimmed to last 3 components (set PROMPT_DIRTRIM to taste).

  • Git-aware Signals: shows branch; “+” if staged changes; “*” if unstaged changes.

  • Execution Feedback: red ✗ and exit code on failures; duration for commands taking ≥100ms.

  • Minimal Cognitive Load: optional bits appear only when relevant (git present, venv active, non-zero exit).

Tip: If your prompt alignment looks off, you likely missed the [ ] wrappers around color codes. Non-printing characters must be wrapped so readline can count characters correctly.


3–5 Actionable Patterns You Can Reuse

1) Context Capsule Pattern

  • Problem: Mistakes on the wrong server or as root are costly.

  • Solution: Color-code user/host and show SSH explicitly (already in the script).

  • Tweak: Change host color logic to highlight certain hostnames:

    if [[ "$HOSTNAME" =~ prod ]]; then hostcolor="${RED}${BOLD}"; fi
    

2) Git-aware Signals Pattern

  • Problem: “Am I on the right branch? Did I stage that file?”

  • Solution: Use __git_ps1 if available; fallback is included. You’ll see:

    • [main] on main, clean
    • [feature+] staged changes
    • [bugfix*] unstaged changes
    • [a1b2c3] detached HEAD at short SHA

3) Execution Feedback Pattern

  • Problem: Slow or failing commands go unnoticed in a busy shell.

  • Solution: Show elapsed time for slow commands and the exit code on failure, right before the next prompt, so you notice immediately.

4) Conditional Info Bits Pattern

  • Problem: Cluttered prompts are distracting.

  • Solution: Only show info when it matters (e.g., venv only when active, git only in repos, timing only if slow, status only if non-zero). This reduces noise and preserves attention.

5) Multi-line Prompt Pattern

  • Problem: One-line prompts pack too much into one row and wrap awkwardly.

  • Solution: Use a two-line (or three-line) layout so “context” is on its own line and the input area stays clean. Already implemented above.


Real-world examples where this shines

  • SSH into production: Prompt turns magenta for host and red if root—instant “danger mode” feedback.

  • Deep repos: Git branch in brackets keeps you oriented when juggling multiple features.

  • Data science venvs: The (env-name) bubble avoids installing to the wrong interpreter.

  • Long-running commands: See 3.42s right in the prompt, so you can decide whether to optimize or background similar tasks next time.


Optional: A Managed Prompt with Starship

Prefer a fast, prebuilt, cross-shell prompt with batteries included? Starship is excellent and works great in Bash.

Install on your distro:

  • apt (Debian/Ubuntu):

    sudo apt update
    sudo apt install -y starship
    
  • dnf (Fedora/RHEL/CentOS Stream):

    sudo dnf install -y starship
    
  • zypper (openSUSE/SLE):

    sudo zypper install -y starship
    

Enable for Bash:

echo 'eval "$(starship init bash)"' >> ~/.bashrc
source ~/.bashrc

You can then customize ~/.config/starship.toml to define modules (git, time, battery, etc.) and behavior similar to the patterns above.


Conclusion and Next Steps

A great Bash prompt is not about eye-candy; it’s about shaping attention and reducing friction. The patterns here—Context Capsule, Git-aware Signals, Execution Feedback, Conditional Bits, and Multi-line Layout—give you a performant, portable, and low-noise prompt you can extend over time.

Your next steps:

  • Paste the script into ~/.bashrc and reload with source ~/.bashrc.

  • Tailor colors, PROMPT_DIRTRIM, or the SSH/root rules to match your environment.

  • Optionally try Starship if you want a managed solution with lots of modules out of the box.

If you found this useful, share your favorite prompt tweaks or questions. What else do you want your terminal’s HUD to show?