1. Why Spend Time on Your Prompt?
| Reason | What you get |
|---|---|
| Instant context | See current directory, git branch, status, python/ruby/node env, kubernetes context, time, exit code, etc. |
| Reduced cognitive load | No need to run pwd, git status, conda env list manually. |
| Speed | A good prompt is rendered in < 5 ms, even on large repos. |
| Aesthetic joy | Nerd‑font icons + colors make the terminal a pleasant place to work. |
| Consistency | Same look across all your machines (desktop, laptop, WSL, remote SSH). |
2. Prerequisites – What You Need on Ubuntu
| Item | Minimum version | Install command |
|---|---|---|
| Ubuntu | 20.04 LTS (or newer) | — |
| Bash | 5.x (comes default) | — |
| Git | 2.30+ | sudo apt install git |
| curl / wget | any | sudo apt install curl wget |
| A Nerd Font | any patched font | see section 3 |
| Starship | latest release (v1.x) | see section 4 |
Optional: bat, fd, ripgrep |
– | sudo apt install bat fd-find ripgrep |
Optional: zsh or fish |
– | Not required, but useful for cross‑shell config. |
NOTE: This guide assumes a pure Bash environment (no Oh‑My‑Bash, no PS1 hacks). If you already use a Bash framework, you can still follow the steps – just make sure to comment out the old PS1 assignments.
3. Step‑by‑Step: Install a Nerd Font
Nerd Fonts are patched fonts that embed thousands of icons (Font Awesome, Octicons, Powerline, etc.) used by Starship.
3.1 Choose a Font
| Font | Why you might like it | Recommended size |
|---|---|---|
| FiraCode Nerd Font | Monospaced, ligatures, great for code | 11‑13 pt |
| Hack Nerd Font | Classic coding font, high readability | 11‑12 pt |
| JetBrainsMono Nerd Font | Modern, tall glyphs, nice for UI | 12‑13 pt |
| CaskaydiaCove Nerd Font (formerly Cascadia Code) | Windows‑like, great for Powerline | 12‑13 pt |
3.2 Download & Install
You can install via the fonts-noto-color-emoji package or manually.
Method A – Using apt (Ubuntu 22.04+)
# Install the pre‑packaged Nerd Font from the Ubuntu repo (limited selection)
sudo apt update
sudo apt install fonts-firacode
# For the Nerd‑patched version:
sudo apt install fonts-firacode-nerd
The repo version may be outdated. For the latest glyph set, use Method B.
Method B – Manual download (recommended)
# Choose a version, e.g., JetBrainsMono
FONT_NAME="JetBrainsMono"
VERSION="2.304" # check https://github.com/ryanoasis/nerd-fonts/releases for latest
mkdir -p ~/.local/share/fonts/nerd-fonts
cd ~/.local/share/fonts/nerd-fonts
wget "https://github.com/ryanoasis/nerd-fonts/releases/download/v${VERSION}/${FONT_NAME}.zip"
unzip "${FONT_NAME}.zip"
rm "${FONT_NAME}.zip"
# Update the font cache
fc-cache -fv
3.3 Set the Font in Your Terminal Emulator
| Terminal | How to set the font |
|---|---|
| GNOME Terminal | Preferences → Profile → Text → Custom Font → select JetBrainsMono Nerd Font (or whichever you installed). |
| Tilix | Right‑click → Preferences → Profiles → Text → Font. |
| Alacritty | Edit ~/.config/alacritty/alacritty.yml: font: family: "JetBrainsMono Nerd Font" |
| Kitty | font_family JetBrainsMono Nerd Font in ~/.config/kitty/kitty.conf. |
| WezTerm | font = wezterm.font("JetBrainsMono Nerd Font") in ~/.wezterm.lua. |
Tip: Enable “Allow bold text” and “Use built‑in rendering for Powerline symbols” if your emulator offers those options.
4. Step‑by‑STEP: Install & Configure Starship
4.1 What is Starship?
Starship is a cross‑shell, minimal, fast prompt written in Rust. It reads a single starship.toml file and prints a line of ANSI‑colored text that Bash (or any shell) can use as PS1.
4.2 Install the Binary
# Using the official script (recommended)
curl -fsSL https://starship.rs/install.sh | bash
# Or via Cargo (if you already have Rust)
cargo install starship
# Verify
starship --version
The installer puts the binary at ~/.cargo/bin/starship. Add it to your PATH if it isn’t already:
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
4.3 Verify Execution
starship prompt
# Should output a short colored line (the prompt itself)
If you see command not found, double‑check the PATH entry and re‑source.
5. Integrating Starship with Bash
Open (or create) ~/.bashrc and add the following near the end before any custom PS1:
# -------------------------------------------------
# Starship Prompt – Begin
# -------------------------------------------------
# Load the Starship binary and initialise the prompt.
# The eval command is required because Starship prints a
# string that contains escape sequences.
if command -v starship > /dev/null; then
# Optional: make Starship load faster by disabling certain modules here
# export STARSHIP_CONFIG="$HOME/.config/starship.toml"
eval "$(starship init bash)"
fi
# -------------------------------------------------
# Starship Prompt – End
# -------------------------------------------------
5.1 Reload
source ~/.bashrc
You should now see a very minimal prompt (just a line of a symbol). The rest of this manual will teach you how to make it useful and beautiful.
6. Deep‑Dive: The starship.toml Configuration File
Starship reads its configuration from $XDG_CONFIG_HOME/starship.toml (by default ~/.config/starship.toml). This file is fully TOML‑syntax and controls every module that appears in the prompt.
6.1 File Skeleton
# ~/.config/starship.toml
# -------------------------------------------------
# Global Settings
# -------------------------------------------------
[character] # The prompt "character"
success_symbol = "[❯](bold green)" # When the last command succeeded
error_symbol = "[❯](bold red)" # When the last command failed
vicmd_symbol = "[❮](bold bright-black)" # When in vi insert mode (if using vi mode)
[cmd_duration] # Show how long the previous command ran
min_time = 2_000 # Show only if >2s (milliseconds)
[hostname] # Optional: show hostname on remote connections
ssh_only = true
format = "[$ssh_symbol]($style) [$hostname]($style) "
# -------------------------------------------------
# Git Section
# -------------------------------------------------
[git_branch]
symbol = "🌿 " # Nerd Font branch icon
format = "[$symbol$branch]($style) "
[git_state]
rebase = "REBASING"
merge = "MERGING"
format = "[$state]($style) "
[git_status]
# Shows staged, unstaged, untracked, conflicted, etc.
format = "[$all_status]($style) "
conflicted = "⚔️"
ahead = "⇡${count}"
behind = "⇣${count}"
staged = "✚${count}"
unstaged = "✚${count}"
untracked = "…"
# -------------------------------------------------
# Language Runtimes
# -------------------------------------------------
[python]
symbol = "🐍 "
style = "bright-yellow"
format = "[$symbol($virtualenv)]($style) "
[nodejs]
symbol = "⚡ "
format = "[$symbol$v]($style) "
[golang]
symbol = "🐹 "
format = "[$symbol($version )]($style) "
# -------------------------------------------------
# Miscellaneous
# -------------------------------------------------
[time]
disabled = false
format = "[$time]($style) "
time_format = "%R" # 24‑hour HH:MM
[status]
disabled = false
format = "[$symbol $status]($style) "
[custom.k8s]
command = "kubectl config current-context 2>/dev/null || echo ''"
when = "kubectl config current-context 2>/dev/null"
symbol = "⎈ "
style = "cyan"
format = "[$symbol($output)]($style) "
# -------------------------------------------------
# Palette – define colors once and reuse
# -------------------------------------------------
[palettes]
# Define a palette to avoid duplication
my_palette = {
primary = "bright-blue",
secondary = "bright-black",
success = "green",
error = "red",
warning = "yellow"
}
Tip: Use the starship explain command to get a JSON view of each module's default values.6.2 Common Global Settings
| Setting | Description | Example |
|---|---|---|
add_newline |
Add an empty line before the prompt (makes it easier to read). | add_newline |
scan_timeout |
How long (ms) Starship will wait for scanning the filesystem (git status, etc.). | scan_timeout |
command_timeout |
Global timeout for custom module commands. | command_timeout |
format |
Full prompt layout – you can reorder modules or hide them completely. | format |
right_format |
Modules that appear on the right side (requires a terminal that supports right‑aligned prompts). | right_format |
6.3 Understanding format Syntax
${module}– a placeholder for a module defined elsewhere ([git_branch],[nodejs], etc.).- Literal text may be placed directly:
"on "or" 🔧 ". - Colors can be added inline with
($style)or via a named palette:($my_palette.success).
Example – a compact dev‑focused layout:
format = """
[┌](bold bright-black)$username$hostname $directory
[│](bold bright-black)$git_branch$git_status$python$nodejs$golang$kubernetes
[└](bold bright-black)$character
"""
The three‑line layout mimics Powerline but uses pure Unicode characters (╭─, │, ╰─) – you can replace them with Nerd‑Font glyphs (\ue0b0, \ue0b2, etc.) for a sleek look.
7. Common Modules & How to Tweak Them
Below is a module‑by‑module cheat sheet for developers. Each block shows the default values, typical customizations, and why you might want to change them.
| Module | What it Shows | Default Symbol | Typical Customization | Example |
|---|---|---|---|---|
character |
The prompt symbol (❯). |
❯ (green on success) |
Use Powerline arrow, show vi‑mode symbol. | success_symbol = "[➜](bold green)" |
username |
Current user name. | (if show_user enabled) |
Hide on local machine; show only on SSH. | show_always = false |
hostname |
Hostname (useful for remote sessions). | |
Show only on SSH, shorten with ssh_only = true. |
ssh_only = true |
directory |
Current working directory. | |
Truncate deep paths, show git repo root. | truncation_length = 3 |
git_branch |
Active git branch. | |
Show detached HEAD with special style. |
symbol = " " |
git_status |
Staged/unstaged changes, ahead/behind. | Various icons. | Hide untracked files to reduce noise. | untracked = "" |
git_state |
Rebase/merge/etc. | REBASING etc. |
Use emojis for states. | rebase = "🔄 " |
cmd_duration |
How long last command took. | took X secs |
Show only when > 1 s. | min_time = 1000 |
status |
Exit code of previous command. | ✖ (red) |
Show numeric code, or hide on success. | symbol = "⚠️" |
python |
Active virtualenv + version. | |
Show only when inside venv. | format = "[$symbol($virtualenv)]($style) " |
nodejs |
Node version (node -v). |
|
Show only when package.json exists. |
detect_files = ["package.json"] |
golang |
Go version (go version). |
|
Show go.mod detection. | detect_files = ["go.mod"] |
rust |
Rust version (rustc --version). |
|
Detect Cargo.toml. |
detect_files = ["Cargo.toml"] |
java |
JDK version. | ☕ |
Detect pom.xml or build.gradle. |
detect_files = ["pom.xml","build.gradle"] |
kubernetes (custom) |
Current kubectl context. |
⎈ |
Show only when kubectl config exists. |
see custom module below |
time |
Current time. | None | 24‑hour format, optional seconds. | time_format = "%R:%S" |
custom.* |
Anything you can script. | ❓ |
Perfect for Docker, Terraform, etc. | see section 8 |
7.1 Example: A “Powerline‑Style” format
format = """
[╭─](bold $palette.primary)$username$hostname $directory
[│](bold $palette.primary)$git_branch$git_status$python$nodejs$golang$kubernetes
[╰─](bold $palette.primary)$character
"""
How it works
- The first line shows user/host and directory, prefixed by a Unicode “╭─”.
- The second line prints git information and language runtimes.
- The third line is the final prompt character.
Result (colors omitted for brevity):
╭─john@work ~/projects/starship-demo
│ main ⇡2 ⇣1 (venv) 1.22.5 ⎈ dev-cluster
╰─❯
8. Adding Your Own Custom Modules
Starship’s [custom.<name>] section lets you run any command and display its output, with conditions for when it should appear.
8.1 Anatomy of a Custom Module
| Field | Meaning | Example |
|---|---|---|
command |
Shell command to run. Must output a single line (no newlines). | command = "git rev-parse --abbrev-ref HEAD" |
when |
Optional test that decides if the module is rendered. | when = "test -f Cargo.toml" |
format |
How to render the output, with $output. |
format = "[$symbol($output)]($style) " |
symbol |
Optional leading icon. | symbol = "🚀 " |
style |
Color/style. | style = "bright-magenta" |
shell |
Override default shell (bash). Useful for complex pipelines. |
shell = ["zsh", "-c"] |
description |
Human‑readable description (used by starship explain). |
description = "Current Docker context" |
command_timeout |
Override global timeout (ms). | command_timeout = 2000 |
environment |
Set environment variables for the command. | environment = [{ name = "DOCKER_HOST", value = "unix:///var/run/docker.sock" }] |
8.2 Real‑World Examples
8.2.1 Docker Context
[custom.docker]
command = "docker context show 2>/dev/null || echo ''"
when = "docker context show 2>/dev/null"
symbol = "🐳 "
style = "cyan"
format = "[$symbol($output)]($style) "
8.2.2 Terraform Workspace
[custom.terraform]
command = "terraform workspace show 2>/dev/null"
when = "test -d .terraform"
symbol = "🛠️ "
style = "bright-yellow"
format = "[$symbol($output)]($style) "
8.2.3 AWS Profile
[custom.aws]
command = "aws configure get profile"
when = "aws configure get profile"
symbol = "☁️ "
style = "bright-blue"
format = "[$symbol($output)]($style) "
8.2.4 Battery Status (Linux)
[custom.battery]
command = "cat /sys/class/power_supply/BAT0/capacity"
when = "test -d /sys/class/power_supply/BAT0"
symbol = "🔋"
style = "green"
format = "[$symbol $output%]($style) "
Tip: Keep custom commands fast. Prefer reading a file (e.g., /proc/...) over spawning heavy CLI tools.8.3 Debugging
# Use Starship's built‑in debug mode
starship explain
Here's a breakdown of your prompt:
"❯ " (<1ms) - A character (usually an arrow) beside where the text is entered in your terminal
" " (<1ms) - The current working directory
"@192.168.1.14 " (<1ms) - The currently assigned ipv4 address
" " (11ms) - The current operating system
" 21:08 " (<1ms) - The current local time
" pavel " (<1ms) - The active user's username
This prints a JSON object showing why the module was rendered or why it was skipped (missing file, timeout, etc.).
9. Color Schemes, Transparency & True‑Color
9.1 256‑Color vs True‑Color
- 256‑color works everywhere (including older
xterm). Use codes likebright-red,247,#ff5f00. - True‑color (24‑bit) offers unlimited palette (
#ff00ff). Most modern terminals (GNOME Terminal, Alacritty, Kitty, iTerm2) support it.
Starship automatically detects true‑color. You can force a mode:
[palette]
# Force 256‑color mode (useful for remote SSH to an old box)
# use_256_colors = true
9.2 Sample Palettes
| Palette Name | Primary | Secondary | Accent | Error | Warning | Success |
|---|---|---|---|---|---|---|
| Dracula | #ff79c6 |
#6272a4 |
#bd93f9 |
#ff5555 |
#f1fa8c |
#50fa7b |
| Solarized Dark | #268bd2 |
#586e75 |
#b58900 |
#dc322f |
#cb4b16 |
#859900 |
| Monokai Pro | #ff6188 |
#2c2c2c |
#c5c8c6 |
#ff6188 |
#ffb86c |
#a9dc76 |
Define a palette in starship.toml:
[palettes.dracula]
primary = "#ff79c6"
secondary = "#6272a4"
accent = "#bd93f9"
error = "#ff5555"
warning = "#f1fa8c"
success = "#50fa7b"
Then reference it:
[character]
success_symbol = "[❯]($dracula.success bold)"
error_symbol = "[❯]($dracula.error bold)"
9.3 Transparent Background
Most terminals respect the background of the terminal window. If you use a transparent terminal, Starship’s colors will blend nicely. Just ensure you don’t set a background color in any module:
[character]
background = "none"
If a module accidentally sets a background, you can override globally:
[custom]
background = "none"
10. Performance Optimizations
| Problem | Fix |
|---|---|
| Prompt lags > 100 ms | 1. Increase scan_timeout (default 30 ms).2. Disable modules you don’t need ( [git_status] disabled = true).3. Use command_timeout for heavy custom modules. |
| Git status slow in huge repos | Set git_status = { disabled = true } and enable git_status = . |
| Network-dependent modules (e.g., AWS profile) | Add when = "test -f ~/.aws/config"to avoid hitting the network each prompt. |
| Repeated file reads | Cache results via shell functions or small scripts saved under ~/.cache/starship. Example: a custom module that reads ~/.nvmrc only once per directory change. |
| Too many custom modules | Group related logic into a single script that outputs multiple symbols, reducing the number of subprocesses. |
Example: Global Fast‑Prompt Settings
# ~/.config/starship.toml
scan_timeout = 10
command_timeout = 500
add_newline = false
[git_status]
disabled = false
ignore_submodules = true
ignore_stash = true
11. Fallback & Compatibility
11.1 When Starship Can’t Load (e.g., Remote Minimal Box)
- Graceful degradation – Create a minimal
starship.tomlin~/.config/starship.tomlthat only enablescharacteranddirectory.
Detect missing binary – In ~/.bashrc:
if ! command -v starship &>/dev/null; then
export PS1='\u@\h:\w\$ '
else
eval "$(starship init bash)"
fi
11.2 Using Starship with Other Shells
- Zsh:
eval "$(starship init zsh)"in~/.zshrc. - Fish:
starship init fish | source.
All modules share the same config file, so you get a consistent look across shells.
11.3 Mixing with Oh‑My‑Bash / Bash‑It
If you already use a framework that sets PS1, you can either:
- Disable the framework’s prompt (
export OMB_PROMPT=offfor Oh‑My‑Bash) and let Starship own the prompt. - Or wrap Starship inside the framework by calling
starship promptinside a custom segment.
12. Troubleshooting FAQ
| Symptom | Likely Cause | Fix |
|---|---|---|
Prompt shows raw escape sequences (\e[0m) |
Terminal doesn’t understand ANSI; $TERM mis‑set. |
Ensure export TERM=xterm-256color (or alacritty, xterm-truecolor). |
| Icons appear as boxes | Nerd Font not selected in terminal. | Re‑select the Nerd Font in terminal preferences, clear the font cache (fc-cache -fv). |
| Git status never appears | git not installed or repo is huge. |
Install git. If repo is massive, set git_status = { disabled = true } or increase scan_timeout. |
Prompt freezes for 5 s after cd into a directory with many files. |
Starship scanning for .git or custom module reading many files. |
Increase scan_timeout, or add when = "test -d .git" to git modules. |
custom module always empty |
Command writes to stderr, or when condition fails. |
Append 2>/dev/null to command or remove the when. Use starship explain to see debug output. |
| Colors are wrong (e.g., bright yellow looks orange) | Terminal color theme overrides. | Use true‑color hex values (#ffdd00) for exact colors. |
| Prompt disappears after SSH | Remote machine doesn’t have Starship installed. | Install Starship on remote host, or configure starship init bash to fall back to a simple PS1. |
starship command not found after source ~/.bashrc |
~/.cargo/bin not in $PATH. |
Add export PATH="$HOME/.cargo/bin:$PATH" to ~/.bashrc before the Starship init block. |
[character] shows a red ❯ even after successful command |
status module is still printing an error symbol. |
Ensure status module isn’t overriding character. Set disabled = true for [status] if you don’t want it. |
13. Advanced Topics
13.1 Git Hooks to Speed Up Prompt
You can configure Git to cache status in a hidden file, reducing Starship’s scanning cost:
git config --global status.showUntrackedFiles no # hide untracked files
git config --global core.preloadIndex true # preload the index
git config --global gc.auto 0 # disable auto‑gc in hot repos
13.2 Using Starship in CI (e.g., GitHub Actions)
When you run tests that log the prompt (rare), you might want a non‑interactive prompt:
steps:
- name: Install Starship
run: |
curl -fsSL https://starship.rs/install.sh | bash
echo 'eval "$(starship init bash)"' >> $HOME/.bashrc
- name: Run script
run: |
source $HOME/.bashrc
starship prompt # prints the prompt string
Set add_newline = false for compact CI logs.
13.3 Multi‑Line Right‑Aligned Prompt
Starship can output a right‑aligned segment if your terminal supports it (\e[?7l / \e[?7h tricks).
right_format = "$time"
To make the right side appear on the same line (like Powerline), ensure your terminal supports the OSC 133 escape sequences (most modern terminals do). No extra config needed.
14. Resources, Cheat‑Sheets & Community
| Resource | Description |
|---|---|
| Official Docs | https://starship.rs – complete module list, config reference, FAQ. |
| Nerd Fonts | https://www.nerdfonts.com – download page, cheat‑sheet of icons. |
| Starship GitHub | https://github.com/starship/starship – issue tracker, contribution guide. |
| Awesome Bash Prompt | https://github.com/awesome-cli/awesome-cli#bash-prompt – curated list of prompt projects. |
| Color Palettes | https://github.com/mbadolato/iTerm2-Color-Schemes – importable .itermcolors for many terminals. |
| Starship Discord | #support channel – quick help from community members. |
| Bash Prompt Cheat‑Sheet | https://github.com/awesome-cli/awesome-cli/blob/master/README.md#bash-prompt – quick reference for $PS1 syntax. |
| Vim/Neovim Integration | set statusline=%{system('starship prompt')} – use Starship as a statusline in Vim. |
Congratulations!
You now have a fully‑featured, fast, beautiful, and cross‑shell prompt powered by Starship and Nerd Fonts. Feel free to tweak the modules, symbols, and colors until the prompt feels like an extension of your workflow.
Happy hacking! 🚀