bash
command line
terminal
troubleshooting
prompt update

Why doesn't my bash prompt update?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Your bash prompt -- the text that appears before every command you type -- is controlled by environment variables like PS1. When it stops updating (for example, no longer showing the current directory or git branch), it usually means the shell is not re-evaluating the prompt string between commands. This article explains the most common causes and how to fix each one.

How the Bash Prompt Works

Bash evaluates the PS1 variable each time it is about to display a new prompt. If PS1 contains special escape sequences (like \w for the working directory or \u for the username), bash expands them on every prompt render. Here is a typical prompt definition:

bash
PS1='\u@\h:\w\$ '
# Produces: alice@laptop:/home/alice$

The key detail is that bash only expands the built-in escape sequences (\u, \h, \w, etc.) by default. If you want to run a command every time the prompt renders, you need to use PROMPT_COMMAND or embed a command substitution correctly.

Cause 1: Using Double Quotes Instead of Single Quotes

This is by far the most common mistake. When you define PS1 with double quotes, the shell evaluates command substitutions immediately -- at definition time -- rather than at display time.

bash
1# WRONG: evaluated once when defined
2PS1="$(whoami)@$(hostname):\w\$ "
3# The username and hostname are baked in as static text
4
5# CORRECT: single quotes defer evaluation to display time
6PS1='$(whoami)@$(hostname):\w\$ '

With single quotes, the $(...) expressions are stored literally in PS1 and evaluated fresh every time bash renders the prompt. With double quotes, they are expanded once and never change.

For this deferred evaluation to work, you also need the promptvars shell option enabled (it is on by default):

bash
shopt -s promptvars

Cause 2: Overridden by Another Config File

Bash sources multiple configuration files in a specific order, and a later file can overwrite your customized PS1. The loading order for a login shell is:

  1. /etc/profile
  2. ~/.bash_profile (or ~/.bash_login or ~/.profile)
  3. ~/.bashrc (if sourced by ~/.bash_profile)

For a non-login interactive shell (like opening a new terminal tab), only ~/.bashrc is sourced. Common issues include:

bash
1# In ~/.bashrc, your custom PS1:
2PS1='[\u@\h \W]\$ '
3
4# But later in the same file, a tool like conda adds:
5# (base) is prepended to PS1 by conda's init script

Check the bottom of your ~/.bashrc for tools that modify PS1. Run echo "$PS1" in your terminal to see the current value and compare it against what you set in your config.

Cause 3: PROMPT_COMMAND Resets PS1

The PROMPT_COMMAND variable holds a command (or function) that bash runs before displaying each prompt. Some frameworks and tools set PROMPT_COMMAND to a function that rebuilds PS1 from scratch, overriding your changes.

bash
1# A tool might set this:
2PROMPT_COMMAND='__my_tool_ps1'
3
4# The function __my_tool_ps1 reconstructs PS1 every time,
5# ignoring whatever you set manually.

To diagnose this, inspect the current value:

bash
echo "$PROMPT_COMMAND"
declare -f __my_tool_ps1   # if it's a function, print its source

If a tool is overriding your prompt through PROMPT_COMMAND, you have two options: modify the tool's prompt function, or set your own PROMPT_COMMAND after the tool's initialization.

Cause 4: Running in a Non-Interactive or Non-Bash Shell

If your prompt never updates at all, verify that you are actually running bash and that the shell is interactive:

bash
1echo $0          # should show "bash" or "-bash"
2echo $SHELL      # your default shell
3echo $BASH_VERSION
4[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"

If $0 shows sh, zsh, or dash, you are not in bash and PS1 escape sequences like \w will not work. On macOS, the default shell is zsh since Catalina, so ~/.bashrc changes have no effect unless you explicitly run bash.

Cause 5: Subshell or Script Context

If you set PS1 inside a script, the change only affects that script's subshell and vanishes when the script exits. To make changes persist, source the file instead of executing it:

bash
1# This does NOT affect your current shell:
2bash my_prompt_setup.sh
3
4# This DOES affect your current shell:
5source my_prompt_setup.sh
6# or equivalently:
7. my_prompt_setup.sh

Dynamic Prompts with PROMPT_COMMAND

For prompts that show dynamic information (like the current git branch), use PROMPT_COMMAND to rebuild PS1 before each prompt display:

bash
1update_prompt() {
2    local branch
3    branch=$(git branch --show-current 2>/dev/null)
4    if [ -n "$branch" ]; then
5        PS1="\u@\h [\w] ($branch)\$ "
6    else
7        PS1="\u@\h [\w]\$ "
8    fi
9}
10PROMPT_COMMAND=update_prompt

Common Pitfalls

  • Double-quoting PS1 with command substitutions: The commands run once at assignment time and the prompt becomes static. Always use single quotes when PS1 contains $(...).
  • Editing the wrong config file: On macOS (zsh default) or systems using ~/.profile, changes to ~/.bashrc may never be loaded. Verify which file your shell actually sources.
  • Forgetting to source after editing: Changes to ~/.bashrc do not take effect in already-open terminals until you run source ~/.bashrc or open a new terminal.
  • PROMPT_COMMAND conflicts: Tools like conda, virtualenv, and starship set their own PROMPT_COMMAND. If you override it, you may break their integration. Append to it instead: PROMPT_COMMAND="my_func;$PROMPT_COMMAND".
  • Disabling promptvars: If shopt -u promptvars has been set (rarely done intentionally), bash stops expanding PS1 variables and command substitutions entirely.

Summary

  • Always define PS1 with single quotes so command substitutions are evaluated at display time, not definition time.
  • Check ~/.bashrc, ~/.bash_profile, and PROMPT_COMMAND for tools that silently override your prompt.
  • Verify you are running an interactive bash shell and not zsh, dash, or a non-interactive session.
  • Use source (not execution) to apply prompt changes from a script to your current shell.
  • Use PROMPT_COMMAND for dynamic prompt elements like git branches or virtual environment names.

Course illustration
Course illustration

All Rights Reserved.