Linux Tutorials

Install Starship Prompt for Bash, Zsh and Fish on Linux

Starship gives bash, zsh and fish the same prompt from one binary and one TOML file. It shows the user, the host when you are on SSH, the directory, the git branch and how long the last command took, and on our test box no module needed more than 2 ms to render. You configure it once in starship.toml instead of maintaining three dialects of PS1.

Original content from computingforgeeks.com - post 27034

This guide installs the Starship prompt with the official script, because the distro packages are behind or missing. It then enables the prompt in each shell, puts a Nerd Font where it actually matters and tunes the config with presets, and it covers the installer’s sudo error, two config errors and a clean removal. Every command below was run on Debian 13 with Starship 1.27.0 in October 2026.

Pick an install method

Use the official install script on Debian, Ubuntu, Fedora and Rocky Linux, and the distro package only on Arch. We checked the package each distro ships in October 2026, and only Arch carries the current release. Debian and Ubuntu still ship the 1.22 line, which is five minor releases behind, and Fedora and Rocky Linux (even with EPEL) do not package Starship at all.

DistributionPackage commandWhat it gave us
Arch Linuxpacman -S starship1.27.0 from extra, current
Debian 13apt install starship1.22.1-5
Ubuntu 26.04apt install starship1.22.1-9ubuntu1
Fedora 43dnf install starshipNo match for argument: starship
Rocky Linux 10 + EPELdnf install starshipUnable to find a match: starship

The Debian and Ubuntu packages work, so they are fine if you only want a prompt and never read the docs. The trouble starts when you copy an option or preset from the current documentation into the older build. Starship warns about a key it does not know (Unknown key in the prompt output) and loads the rest, so the prompt works but your new setting does nothing. Check what your own distro offers before you decide:

apt-cache policy starship | sed -n 1,3p

On Debian 13 the candidate is the 1.22 build, while GitHub was already on the 1.27 line when we ran this:

starship:
  Installed: (none)
  Candidate: 1.22.1-5

On Arch, the package in extra tracks upstream closely, so install it with pacman and skip the script entirely. CachyOS builds on the Arch repositories, so the same command should work there too, though we only ran it in an Arch Linux container, not on CachyOS itself. If you’ve just set up that distro, our list of things to do after installing CachyOS covers the rest of the shell setup.

sudo pacman -S starship

Termux on Android and Homebrew on macOS have their own packages, listed as pkg install starship and brew install starship in the Starship installation guide. We did not test either platform. The init lines and starship.toml settings below are the same everywhere, though, so the rest of this guide still applies once the binary is installed.

Error: “No match for argument: starship” on Fedora

Fedora 43’s repositories do not carry Starship, so dnf stops before it resolves anything. Refreshing mirrors changes nothing, and --skip-unavailable only turns the failure into an install of nothing:

Failed to resolve the transaction:
No match for argument: starship
You can try to add to command line:
  --skip-unavailable to skip unavailable packages

Rocky Linux 10 fails the same way with EPEL enabled, ending in Error: Unable to find a match: starship, because EPEL has no Starship package either. Fedora users will find a community COPR repository for Starship, but this guide sticks to the official script rather than a third-party repo, and we did not test the COPR. On both distros, go straight to the install script in the next section, which works across distributions because it installs a static musl build.

Install Starship with the official script

The script detects your architecture, downloads the static musl build of the latest release from GitHub, and drops a single binary into /usr/local/bin. Download it to a file first instead of piping curl into sh, so you can read it and see its options:

curl -sS https://starship.rs/install.sh -o /tmp/starship-install.sh
sh /tmp/starship-install.sh --help

The help lists the flags you’ll actually use. Only -y matters for a normal install, while -b is the way out when you have no root on the box:

  • -y or -f: skip the confirmation prompt
  • -b, --bin-dir: install somewhere other than /usr/local/bin
  • -p, --platform: override the detected unknown-linux-musl
  • -a, --arch: override the detected CPU architecture
  • -V, --verbose: show what the installer is doing
  • -v, --version: install a specific release, such as v1.2.3
  • -B, --base-url: download releases from a mirror

The last two sit further down the same help output, past where our capture stopped, and we did not run them. Pinning with -v is the one to reach for when every machine in a fleet should draw the same prompt.

Run it under sudo for a system-wide install. That is the method we’d pick on any machine where you have sudo, because the binary lands on every user’s PATH and a later run of the same command upgrades it in place. The installer’s help says as much: if Starship is already installed, it is updated to the latest version.

sudo sh /tmp/starship-install.sh -y

Check which binary your shell finds and the build it reports. If you tried the user install below first, delete that copy, because Debian’s default ~/.profile puts ~/.local/bin ahead of /usr/local/bin and the stale binary would win.

command -v starship
starship --version

A healthy install prints /usr/local/bin/starship and the release details. The binary is about 12.6 MB and has no runtime dependencies:

/usr/local/bin/starship
starship 1.27.0
branch:main
commit_hash:f8e4e21
build_time:2026-10-17 09:20:07 +00:00
build_env:rustc 1.99.1 (58cf8f9c3 2026-10-13),

No sudo on the box? Install into your home directory instead. Create ~/.local/bin first, because the installer won’t, and make sure it’s on your PATH (Debian and Ubuntu’s default ~/.profile adds it at login once the directory exists):

mkdir -p ~/.local/bin
sh /tmp/starship-install.sh -y -b ~/.local/bin

That run needed no root at all, and ~/.local/bin/starship --version reported the same build. The trade is that only your account gets the prompt, and you upgrade each copy yourself, so it suits shared servers where you can’t touch /usr/local.

Error: “x Superuser not granted, aborting installation”

Running the script as a normal user without -b can fail even when your account has passwordless sudo. Our test user had a josphat ALL=(ALL) NOPASSWD:ALL rule and sudo -n true succeeded, yet the installer still stopped here, as the top half of this capture shows:

Starship install script failing without sudo, then installing Starship to /usr/local/bin under sudo on Debian 13

The installer escalates with sudo -v, which validates your credentials rather than running a command. For -v, sudo’s verifypw setting defaults to all, which means every sudoers entry that matches you must be NOPASSWD. Debian’s stock %sudo ALL=(ALL:ALL) ALL line also matched our user (it is in the sudo group) and has no NOPASSWD, so sudo -n -v answered “a password is required”. At an interactive terminal sudo would simply ask for the password, so this only bites in scripts, Ansible tasks and CI jobs, or on accounts with no usable password. You can see both rules that match you:

sudo -l 2>&1 | sed -n "/may run/,\$p"

Our test user had one rule from the group and one of its own, and only the second is passwordless:

User josphat may run the following commands on deb01:
    (ALL : ALL) ALL
    (ALL) NOPASSWD: ALL

The simplest fix is to run the whole script under sudo, as in the bottom half of the capture, or to pass -b ~/.local/bin so it never needs root. If an automation job has to run the installer as the user, tell sudo that one NOPASSWD entry is enough for -v. Write a drop-in with verifypw=any for that account and check its syntax before relying on it, because a broken sudoers file can lock you out of sudo:

printf "Defaults:$USER verifypw=any\n" | sudo tee /etc/sudoers.d/99-verifypw >/dev/null
sudo chmod 440 /etc/sudoers.d/99-verifypw
sudo visudo -cf /etc/sudoers.d/99-verifypw
sudo -n -v; echo "sudo -n -v rc=$?"

A good result is parsed OK from visudo and a zero return code from sudo -n -v. With that file in place, the installer completed as the normal user on our VM:

/etc/sudoers.d/99-verifypw: parsed OK
sudo -n -v rc=0

We removed the drop-in afterwards with sudo rm -f /etc/sudoers.d/99-verifypw, and sudo -n -v went back to returning 1. Keep the file only if you need it, since it relaxes credential checks for that account.

Enable Starship in bash, zsh and fish

Starship does nothing until your shell runs its init code, which you add as the last line of each shell’s startup file. Put it at the end because anything that sets the prompt later in the file (a framework, a theme, a leftover PS1) will override Starship. Add only the lines for the shells you use, and run each echo once: it appends again every time, so a second run leaves a duplicate init line. Check with grep -c starship ~/.bashrc if you are not sure.

For bash, append the init line to ~/.bashrc:

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

Bash does not show the change in PS1, because Starship builds the prompt from a hook that runs before each prompt is drawn. So printing PS1 proves nothing, and the useful check is whether the hook function exists in an interactive shell:

bash -ic "type starship_precmd >/dev/null && echo starship-hooked; echo PS1=\$PS1" 2>&1 | tail -2

Seeing starship-hooked means it’s wired in. The PS1 line still shows Debian’s default string, and that’s expected, because the hook swaps it at draw time:

starship-hooked
PS1=${debian_chroot:+($debian_chroot)}\u@\h:\w\$

For zsh, the line goes at the end of ~/.zshrc. If you run Oh My Zsh, keep the Starship line below the line that loads it, for the reason above; the Zsh and Oh My Zsh setup shows how that file is laid out.

echo 'eval "$(starship init zsh)"' >> ~/.zshrc

Zsh exposes the result directly in $PROMPT, which makes it the easiest of the three to verify. If the output still shows your old theme, something later in ~/.zshrc set the prompt again, so move the Starship line below it:

zsh -ic "echo PROMPT=\$PROMPT" 2>&1 | tail -1

The prompt is now a call to the Starship binary with the terminal width, keymap, exit status and command duration passed in. Zsh runs that call every time it draws a prompt, so any slowness you notice later comes from the modules, which you can measure with starship timings further down:

PROMPT=$(/usr/local/bin/starship prompt --terminal-width="$COLUMNS" --keymap="${KEYMAP:-}" --status="${STARSHIP_CMD_STATUS:-}" --pipestatus="${STARSHIP_PIPE_STATUS[*]:-}" --cmd-duration="${STARSHIP_DURATION:-}" --jobs="$STARSHIP_JOBS_COUNT")

Starship only draws the prompt, so it pairs well with plugins that change how you type. Command autosuggestions in zsh run alongside it without any changes to either config.

For fish, the syntax differs. Older guides, including the first version of this one, used eval (starship init fish); the current form pipes into source. The config directory may not exist on a fresh account, so create it first:

mkdir -p ~/.config/fish
echo "starship init fish | source" >> ~/.config/fish/config.fish

Fish draws its prompt from a function called fish_prompt, and the init line replaces that function with one Starship generates. So the check is to print the top of the function in an interactive fish:

fish -ic "functions -q fish_prompt; and functions fish_prompt | head -4"

The function now comes from a temporary file Starship sourced, not from fish’s default prompt, and it already handles the vi and helix key bindings:

# Defined in /tmp/.psub.kGWxIhpb88 @ line 13
function fish_prompt
    switch "$fish_key_bindings"
        case fish_hybrid_key_bindings fish_vi_key_bindings fish_helix_key_bindings

The fish package from the Debian 13 repository worked with no extra steps. If fish is new to you, our guide to installing and configuring the fish shell covers making it your login shell. Open a new terminal (or exec the shell) to see the prompt in each one.

Install a Nerd Font on the desktop

The default prompt uses icons that most terminal fonts don’t have. You can see them in the raw output Starship renders for a command that took 2.5 seconds, with the colour codes stripped:

starship prompt --status 0 --cmd-duration 2500

Over SSH, the hostname appears with a globe symbol, and the input marker is the ❯ character on its own line:

josphat in 🌐 deb01 in /tmp took 2s
❯ 

The ❯ and the globe usually render with ordinary fonts, since one is a standard Unicode arrow and the other an emoji. The branch icon the git module adds inside a repository and the language icons are Nerd Font glyphs. Those show as empty boxes until a Nerd Font is installed and enabled in your terminal, which is what the Starship docs ask for. The font must be installed on the machine that runs your terminal emulator, which is your laptop or desktop, not the server you SSH into. Starship sends characters, and the terminal on your side decides how they look. That’s also why the old Powerline font packages aren’t the answer: Starship’s git and language icons come from the Nerd Fonts set.

On a Linux desktop, a user-level font install needs fontconfig and unzip. Most desktop installs already have both, but minimal ones and servers often lack unzip.

sudo apt install fontconfig unzip

Download FiraCode into /tmp from the Nerd Fonts releases, unpack it into your font directory, rebuild the font cache and delete the zip. The releases/latest/download URL always resolves to the newest release, and the FiraCode zip was 28 MB when we ran it:

mkdir -p ~/.local/share/fonts
cd /tmp
curl -fsSLO https://github.com/ryanoasis/nerd-fonts/releases/latest/download/FiraCode.zip
unzip -oq FiraCode.zip -d ~/.local/share/fonts/FiraCode
fc-cache -f
rm -f /tmp/FiraCode.zip

If fc-cache ran without errors, fontconfig should now list the new families. Check before you open the terminal settings, because a font that isn’t in this list won’t show up in the font picker either:

fc-list : family | grep -m2 "FiraCode Nerd Font"

The zip installed 18 faces. You want the Mono family for a terminal, because its icons are forced to a single cell width and won’t push the prompt out of alignment:

FiraCode Nerd Font,FiraCode Nerd Font Ret
FiraCode Nerd Font Mono,FiraCode Nerd Font Mono SemBd

Select “FiraCode Nerd Font Mono” in your terminal’s font settings. We ran these commands on the Debian VM to confirm them, not on a desktop with a GUI terminal, so we didn’t capture the rendered icons. The Nerd Fonts install guide covers macOS and other font families, and Alacritty users set the font in its config file as shown in the Alacritty setup. If you can’t change the font (a locked-down jump host, a web console), use the plain-text-symbols or no-nerd-font preset from the next section instead.

Configure starship.toml

Starship runs on built-in defaults until you create ~/.config/starship.toml, and no such file exists after install. To see what the defaults are, dump the effective config:

starship print-config 2>/dev/null | head -12

Three top-level keys matter most. format = "$all" turns on every module that has something to show, command_timeout is how long Starship waits for an external command in milliseconds, and add_newline prints a blank line before each prompt. The first comment line expands $all into the full module list, which runs to well over a hundred names, so it’s trimmed here:

"$schema" = "https://starship.rs/config-schema.json"
format = "$all"
right_format = ""
continuation_prompt = "[βˆ™](bright-black) "
scan_timeout = 30
command_timeout = 500
add_newline = true
follow_symlinks = true

A preset is the quickest way to a different look, because it writes a complete starship.toml for you. List the presets your build ships with starship preset --list (the full list is in the reference card at the end), then write one to your config file. This one swaps every icon for plain text, so it works with any font:

starship preset plain-text-symbols -o ~/.config/starship.toml

The prompt changes on the next draw with no shell restart, because Starship reads the config each time it renders. The globe became the word ssh and the arrow became >:

josphat in ssh deb01 in /tmp
> 

Note that -o overwrites the file without asking, so copy your own config somewhere first if you already have one. For changes of your own, edit the file directly:

vim ~/.config/starship.toml

The config we tested is deliberately small. It drops the blank line and gives slow commands a full second. The marker is a plain > that turns into a red x when the last command failed, only the last two directory levels show, and the hostname appears even outside SSH:

add_newline = false
command_timeout = 1000

[character]
success_symbol = "[>](bold green)"
error_symbol = "[x](bold red)"

[directory]
truncation_length = 2

[hostname]
ssh_only = false
format = "[$hostname](bold blue) "

To check a config without opening new shells, render the prompt directly. The --status flag fakes the exit code of the previous command, so you can see both states:

mkdir -p /tmp/a/b/c/d; cd /tmp/a/b/c/d
starship prompt --status 0 | sed "s/\x1b\[[0-9;]*m//g"; starship prompt --status 1 | sed "s/\x1b\[[0-9;]*m//g"

Inside /tmp/a/b/c/d the directory shows as c/d, the host appears without the globe, and the marker is > after a success and x after a failure. The word “in” that used to follow the hostname has gone too, because the stock hostname format adds it and the custom format doesn’t:

josphat in deb01 c/d
> josphat in deb01 c/d
x 

Inside a git repository the git modules show up on their own. In a fresh repo with one untracked file, the prompt read josphat in deb01 repo on master [?], where the blank before master is the Nerd Font branch icon and [?] means untracked files. Every key for every module is in the Starship configuration reference.

Starship can tell you where a segment comes from and what it costs. starship explain names the module behind each part of the prompt, and starship timings shows how long each one took. Here both ran with the custom config above active:

starship explain and starship timings output showing each Starship prompt module and its render time

The netns module was the slowest at 2 ms, and everything else came in under 1 ms, so the whole prompt drew in a few milliseconds. On a busy machine the numbers to watch are the git and language modules inside large repositories, because those are the ones that read the disk or call external tools.

Fix config errors and slow modules

Starship never stops drawing a prompt because of a bad config. It prints the problem to the terminal and carries on with defaults, so a typo looks like “my settings were ignored” rather than a crash. Read the message before you start changing settings, because it names the file position or the module at fault. Both errors below were reproduced on purpose on the Debian 13 VM.

Error: “Unable to parse the config file: TOML parse error”

One missing bracket in a table header is enough. With STARSHIP_CONFIG pointing at a file whose first line reads [character, every prompt prints this before falling back to the defaults:

[ERROR] - (starship::config): Unable to parse the config file: TOML parse error at line 1, column 11
  |
1 | [character
  |           ^
unclosed table, expected `]`

The line and column point straight at the fault, so fix that spot and the next prompt picks up your settings. The STARSHIP_CONFIG variable is also the safe way to try a config before you swap it in, because a broken test file never touches ~/.config/starship.toml.

Warning: “Executing custom command … timed out”

Any module that runs an external command is cut off after command_timeout, which defaults to 500 ms. A custom module running sleep 2; echo slow produced two warnings and no output from that module:

[WARN] - (starship::modules::custom): Executing custom command "sleep 2; echo slow" timed out.
[WARN] - (starship::modules::custom): You can set command_timeout in your config to a higher value or set ignore_timeout to true for this module to allow longer-running commands to keep executing.

The same class of warning shows up in very large git repositories and on slow network filesystems. Raising command_timeout to 1000, as in the config above, quiets it, but every prompt then waits up to a second. We’d rather fix or drop the slow module, and only set ignore_timeout = true on a custom module whose output you genuinely need on every prompt.

Remove Starship cleanly

Starship leaves very little behind, but the order matters. Take the init lines out of your shell startup files before you delete the binary, because a startup file that still calls Starship prints an error in every new shell once the binary is gone. These are the places it touches:

  • the init line in ~/.bashrc, ~/.zshrc and ~/.config/fish/config.fish
  • the binary in /usr/local/bin/starship (or ~/.local/bin/starship)
  • your config in ~/.config/starship.toml
  • logs and session files in ~/.cache/starship

The sed commands delete only the lines that call starship init, so the rest of each file stays as it was. Skip any line for a shell you never set up, since sed fails on a missing file:

sed -i "/starship init bash/d" ~/.bashrc
sed -i "/starship init zsh/d" ~/.zshrc
sed -i "/starship init fish/d" ~/.config/fish/config.fish
sudo rm -f /usr/local/bin/starship
rm -f ~/.config/starship.toml
rm -rf ~/.cache/starship

Then confirm that the binary is gone and that no startup file still mentions it. The || prints a marker instead of nothing when the binary is missing, which is the result you want here:

command -v starship || echo starship-removed; grep -c starship ~/.bashrc ~/.zshrc ~/.config/fish/config.fish

The marker line and a zero count for every file mean the removal is complete:

starship-removed
/home/josphat/.bashrc:0
/home/josphat/.zshrc:0
/home/josphat/.config/fish/config.fish:0

A new interactive bash started afterwards without any Starship error, so nothing is left calling the binary. If you skipped the sed step, you get the error below instead.

Error: “bash: starship: command not found” in every new shell

Each new bash prints bash: starship: command not found when the binary is gone but the init line stayed in ~/.bashrc, and then drops back to the default prompt. It is harmless but noisy, and it also happens on a machine where you’ve copied your dotfiles but haven’t installed Starship yet. Delete the line as shown above, or, if you share one ~/.bashrc across machines, guard the init so it only runs where the binary exists:

if command -v starship >/dev/null 2>&1; then
    eval "$(starship init bash)"
fi

With that block in place and Starship absent, bash started cleanly with no error. That’s the version we’d keep in shared dotfiles.

Starship preset and module reference card

These are the presets starship preset --list printed for the build we tested. We applied plain-text-symbols on the test VM; the descriptions of the others come from the Starship presets page:

PresetWhat it changesNeeds a Nerd Font
nerd-font-symbolsNerd Font icons for every moduleYes
no-nerd-fontLimits symbols to the emoji and powerline setsNo
plain-text-symbolsPlain text instead of every icon (tested)No
bracketed-segmentsWraps each segment in brackets instead of “via” and “on”No
no-runtime-versionsHides language and runtime version numbersNo
no-empty-iconsHides a toolset icon when its version can’t be foundNo
pure-presetMimics the Pure zsh promptNo
jetpackMinimal prompt inspired by geometry and spaceship, using the terminal’s own colours; needs a shell with right-prompt support (bash needs ble.sh)Not listed
pastel-powerline, tokyo-night, gruvbox-rainbow, catppuccin-powerlineFull colour themes with powerline-style segmentsYes

Pick plain-text-symbols for servers and web consoles where you cannot control the font, and keep the colour themes for your own desktop. A preset is only a starting file, so apply one and then edit it like any other config. Back up your own starship.toml first, because -o replaces it.

These are the commands and settings you’ll reach for most after install. Every command in the table was run on the Debian 13 VM for this guide, and the keys are the ones the custom config above uses:

Command or keyWhat it does
starship init bash|zsh|fishPrints the init code your startup file evaluates
starship preset <name> -o ~/.config/starship.tomlWrites a preset to your config, overwriting it
starship print-configDumps the effective config, defaults included
starship explainNames the module behind each prompt segment
starship timingsShows render time per module
STARSHIP_CONFIG=/path/file.tomlUses another config file, for testing
add_newlineBlank line before each prompt (default true)
command_timeoutMilliseconds to wait for external commands (default 500)
[character]Success and error symbols at the input position
[directory] truncation_lengthHow many path levels to show
[hostname] ssh_onlyShow the host only over SSH (default true)

Re-run sudo sh /tmp/starship-install.sh -y with a freshly downloaded script whenever you want the latest release, because the installer upgrades an existing binary in place. If you also want the current Kubernetes context in your prompt without Starship’s kubernetes module, kube-ps1 is the lighter alternative for bash and zsh.

Keep reading

Fix β€œapt-key is deprecated. Manage keyring files in trusted.gpg.d instead” Debian Fix β€œapt-key is deprecated. Manage keyring files in trusted.gpg.d instead” Best Terminal Shell Prompts for Zsh, Bash and Fish Featured Best Terminal Shell Prompts for Zsh, Bash and Fish Linux Terminal Shortcuts Cheat Sheet (Bash and zsh) Cheat Sheets Linux Terminal Shortcuts Cheat Sheet (Bash and zsh) Install lazygit on Linux: Ubuntu, Debian, Fedora and Arch Git Install lazygit on Linux: Ubuntu, Debian, Fedora and Arch Linux Commands Cheat Sheet for Ubuntu and Rocky Linux (PDF) Cheat Sheets Linux Commands Cheat Sheet for Ubuntu and Rocky Linux (PDF) How To Truncate or Empty Log Files in Linux Terminal How To Truncate or Empty Log Files in Linux

Leave a Comment

Press ESC to close