Ramblings of an aging IT geek
← Ramblings of an aging IT geek
tooling

a prompt that earns its keep

How I pared my shell prompt down to the few signals I actually read before running a command.

A mechanical keyboard lit beside a terminal

For years my prompt was a vanity project. Two lines, a clock, a battery glyph, the phase of the moon. It looked lovely in a screenshot and told me almost nothing I needed in the half second before I hit return. The day I deleted most of it was the day it started being useful.

The rule I settled on is simple: a prompt should only show things that change my next keystroke. Everything else is decoration, and decoration costs render time and eye time. So I sat down and asked what I actually read before running a command, and the honest answer was short.

Where am I. Which git branch, and is it dirty. Whether the last command failed. Whether I'm somewhere I should be careful, which for me means a production context or a root shell. That's it. The hostname matters when I'm SSH'd somewhere, and not at all when I'm on my own laptop, so it only appears when it's not localhost.

A terminal showing a colour-coded prompt

I run starship now, mostly because it's fast and the config is one readable TOML file rather than a tangle of shell escapes I'd have to relearn every time I touched it. The whole thing is about thirty lines.

format = """
$directory$git_branch$git_status$kubernetes
$character"""

[directory]
truncation_length = 3
truncate_to_repo = true

[git_status]
conflicted = "="
ahead = "⇡${count}"
behind = "⇣${count}"
modified = "!${count}"
untracked = "?${count}"

[kubernetes]
disabled = false
format = '[$context](dimmed red) '

That kubernetes block is the one that's saved me from myself. It only shows when there's a kube context active, and it renders the context name in a dim red. It is deliberately ugly. When I see red in my prompt I slow down, because red means the next kubectl delete might land somewhere that pages people. A prompt that's pretty all the time can't warn you. A prompt that's plain most of the time and loud occasionally can.

The git status counts earn their place too. I don't want a vague "dirty" marker, I want !3 ?1: three modified, one untracked. That's enough to know whether I've left something uncommitted before I switch branches, without running git status first. Small thing, but I do it forty times a day.

The exit-code signal is the other keeper. My prompt character goes red when the previous command exited non-zero. Not a number, not a stack trace, just a colour change on the thing I'm about to type next to. It catches the silent failures, the pipe that returned 1 while everything looked fine, the script that exited early without a word.

What I cut was the timestamp, the username on my own box, the language version badges, and the little icons that told me which OS I was on as if I might forget. None of it changed what I typed next. If I want the time I have a clock, and the language version is a question I ask with --version on the rare occasion it matters.

The wider point isn't really about prompts. It's that ambient information has a cost even when it's free to display, because your eyes still have to skip over it to find the one thing that matters. A prompt that shows everything is a prompt that shows nothing. Strip it back to the signals that change a decision, make the dangerous ones loud, and let the quiet ones stay quiet. Mine's boring now, and I've never run fewer destructive commands by accident.