The importance of a lean PROMPT

Jun 15, 2026 5 min

I recently updated my dotfiles with a fundamental change in how I display git-related information in my shell’s prompt.

In particular, my PROMPT environment variable contained a call to:

function parse_git_branch() {
  git branch 2> /dev/null | sed -n -e 's/^\* \(.*\)/[\1]/p'
}

and now, for git repositories, it does:

if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
    local ref
    ref=$(git branch --show-current 2>/dev/null)
    if [[ -n "$ref" ]]; then
        echo "git [$ref]"
    else
        echo "git [$(git rev-parse --short HEAD 2>/dev/null)]"
    fi
    return
fi

echo "[no_vcs]"

Commonalities

What both commands have in common is error redirect, or:

2>file

where file in this case is /dev/null, which simply discards the data it receives.

Previous prompt

My previous prompt was naively doing:

  • list all git branches (git branch, equivalent to git branch --list)
  • never print errors
  • pipe git branches into sed (s/pattern/replacement/flags)
    • -n: do [n]ot print input
    • -e: use a sed [e]xpression
    • match regex pattern /^\* \(.*\)/ (asterisk followed by a space and something else, like * main, and capture group after space and asterisk)
    • replace match with capture group 1 in square brackets ([\1])
    • /p flag means “print if successful”

So, it would list all branches, and then find the current one (if any, marked with an asterisk by git), and wrap it in square brackets.

Current prompt

The current prompt makes use of rev-parse and branch --show-current instead of branch (--list).

Despite its cryptic man page, git’s rev-parse is a simple query command to get information about the repository (branches, hashes, root, etc.). From it, we leverage:

  • --is-inside-work-tree: returns true if CWD is inside the git repository that git attempts to find when launching the CLI (typically, a .git/ dir in CWD or parent directories)

and from git branch:

  • git branch --show-current: returns the current branch, or empty string if none. Should take O(1) instead of O(#branches).

Speed improvement

The performance in my prompt was of 5x, measured with GNU/BSD time (/usr/bin/time) and iterating 100 times as a rough estimate:

$ /usr/bin/time -p zsh -c '
for i in {1..100}; do
    <command>
done
'

making it from total time elapsed of 4.38s to 0.87s, in a repo with a badly managed history:

  • 1.4GB of .git/ directory, and
  • 254 tracked branches

effectively, managing the repo usable in my current shell (zsh).

JJ Prompt

JJ (jujutsu), a version control system I found out thanks to the great Steve Klabnik (steveklabnik.com), is my go-to CLI to manage history of software projects. It has git compatibility, so I can use it with current projects hosted in git-compatible servers (Github, Gitlab, Bitbucket, etc.).

I have started adding some jj information to my prompt, with:

if [[ -d .jj ]]; then
    local jj_id
    jj_id=$(jj log -r @ --no-graph --ignore-working-copy --template 'change_id.short()' 2>/dev/null) || jj_id="err"
    echo "jj [$jj_id]"
    return
fi

Which looks for a .jj/ directory and, if present, gets the current short id of the current (@) commit.

With time, I might add some more information. However, I will only if I see that the commands needed are lightweight, as this experiment has proven to me that having a lean PROMPT is essential to have a usable shell.

~mpsanchis