Starship: A Cross-Shell Prompt

I've had an interest in prompts since I started using Linux in 1995 or 1996. So much so that I wrote the Bash Prompt HOWTO - sure, it's incredibly old, but it's also still pretty accurate. More recently, I've done a lot of work on creating a modular way of creating Bash prompts ... which is still just on my own machines as it's not ready for public consumption. The interesting thing about the latter project is that many have tried it before me, and all have failed. For some reason the one I remember most is Bashish: not a bad project, but not super easy to use, didn't really catch on, and hasn't been updated since 2006. All of which makes me suspect my project will never go public ...

I spend a huge amount of my life at a shell prompt - and that shell has been Bash since I started using Linux. I've tried others, but the only one that's come close to replacing it is ZSH. Since I was always at the prompt, the prompt seemed like an obvious place to display information, as compactly as possible. I found that the information I wanted/needed was always just a little different from what others wanted - sometimes it was as small a thing as formatting, with my preference for date display being "2020-08-02" and time display "1705" (24 hour clock). Learning how to customize the Bash prompt to look the way I wanted was the obvious path.

Is Starship going to be different than all these previous failed projects? Right out of the gate, yes: it's Rust-based (most prompt projects are shell-specific), and thus cross-shell, and also cross-platform (not a problem for a shell-specific prompt if the shell itself runs on alternative platforms, but fairly cool given this is a compiled language).

Starship is available for (at least) Bash, Fish, ZSH, and Powershell. It's easily installable on (at least) Fedora (dnf install starship) and Mac (brew install starship). Check their main page for other shells and platforms.

One thing you'll need, the only significant dependency the package installation probably won't take care of, is a Programmer's Font (that's my guide to the subject ... theirs may be more useful in this context).

To test it in Bash, just run eval "$(starship init bash)" - results aren't guaranteed though. In my case, this fails if I'm using a complex prompt because the environment variable $PROMPT_COMMAND and Starship don't play well together, so I had to run PROMPT_COMMAND="" before starting Starship. To permanently set up Starship, just add the eval line to your ~/.bashrc file. See their documentation (which is quite good) for more details.

Customisation

The first thing I saws on a Mac was that the default Starship setup wanted to tell me what version of Node I had installed. For work reasons, I need Node installed - I use it once every six months and I don't program in it: I DON'T CARE what version it is. But whenever I changed into a git repository, Starship dropped the Node information and replaced it with the git repo status. Had it not been showing me the Node version, it might well have shown Ruby, or Python, or ... it does this for many languages. I also discovered that their idea of a default value of when to tell you about battery status was when it dropped below 10% ... I've changed that default to 90% because the reality on a couple of my older laptops is that 90% means I have only about 30 minutes of power left. That's machine-specific and clearly a personal thing, but it shows a couple points: I don't like Starship's defaults, and - more importantly - it's easy to customise. Which means that it's easy for you to display the version of the programming language that matters to you.

# ~/.config/starship.toml
# Configuration details: https://starship.rs/config/#prompt

# Don't print a new line at the start of the prompt
add_newline = false

# Possible options for what to display in the prompt:
#prompt_order = [ "username", "hostname", "kubernetes", "directory", "git_branch", "git_commit", "git_state", "git_status", "hg_branch", "docker_context", "package", "dotnet", "elixir", "elm", "erlang", "golang", "java", "julia", "nim", "nodejs", "ocaml", "php", "purescript", "python", "ruby", "rust", "terraform", "zig", "nix_shell", "conda", "memory_usage", "aws", "env_var", "crystal", "cmd_duration", "custom", "line_break", "jobs", "battery", "time", "character", ]

prompt_order = [ "directory", "git_branch", "git_state", "git_status", "cmd_duration", "line_break", "battery", "character" ]

[character]
# this is the last character you see before the stuff you type
symbol = "❯"
error_symbol = "✗"
use_symbol_for_status = true

# Disable the package module, hiding it from the prompt completely
[package]
disabled = true

[battery]
full_symbol = "Ω"
charging_symbol = "^"
discharging_symbol = "v"

# no idea why this is in double square brackets, but that's the example
# and it works.
[[battery.display]]
threshold = 90
style = "bold yellow"

[git_status]
# Overriding a lot of these as some of the specialty symbols that work
# on Mac don't work on Linux.
conflicted = "⊥"
ahead = "^"
behind = "v"
diverged = "Δ"
untracked = "+"
stashed = "S"
modified = "±"
staged.value = "++"
staged.style = "green"
staged_count.enabled = true
staged_count.style = "green"
renamed = "r"
deleted = "-"

[directory]
truncation_length=2
truncate_to_repo=false

Since I've only started using Starship in the last couple weeks, this is likely to change considerably over time. But it's already proven a good start for me. I'm also not sure I'll permanently change from my own Bash prompts to Starship, but it's interesting and good and may work well for others.

I'm particularly a fan of cmd_duration which shows the time the previous command took (if it exceeded a minimum time, which defaults to two seconds but can be changed).