Skip to content
Shell & TerminalHow-To Published Updated 5 min readViews unavailable

How to Configure a Custom Prompt With Starship

Installing Starship, a fast, shell-agnostic prompt that works identically across Bash, Zsh, and fish, and configuring which information it shows.

Starship is a prompt tool that works identically across Bash, Zsh, and fish, handling the genuinely fiddly work of fast, correct prompt rendering — git status, language version detection, command timing — so you don’t have to hand-write it yourself.

Step 1: install Starship

curl -sS https://starship.rs/install.sh | sh

Package manager installs are also available (brew install starship on macOS, for instance) if you’d prefer not to run the install script directly.

Step 2: add Starship’s initialization to your shell’s config

# Bash: in ~/.bashrc
eval "$(starship init bash)"

# Zsh: in ~/.zshrc
eval "$(starship init zsh)"

This single line is what actually activates Starship as your prompt — without it, Starship is installed but not yet in use.

Step 3: reload your shell to see the default prompt

exec $SHELL

Starship’s default configuration already shows useful context — current directory, git branch and status, and language-specific version indicators when relevant (a Python virtual environment, a Node.js project) — with zero further configuration required.

Step 4: generate a starting configuration file

mkdir -p ~/.config
starship preset nerd-font-symbols -o ~/.config/starship.toml

Starship ships several built-in presets — this example uses one assuming a Nerd Font is installed for icon glyphs; check starship preset --list for alternatives if you’re not using a patched font.

Step 5: customize which modules appear

# ~/.config/starship.toml
[git_status]
disabled = false

[package]
disabled = true

Starship’s configuration is organized into modules — one per piece of information it can show — each independently enableable, disableable, and stylable.

Step 6: customize the format and ordering of prompt segments

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

The format string controls exactly which modules appear and in what order — a genuinely direct way to build precisely the prompt layout you want, rather than working around a theme’s fixed layout.

Step 7: adjust performance-sensitive modules if startup feels slow

[git_status]
disabled = false

[cmd_duration]
min_time = 500

If prompt display feels slow in specific large repositories, checking module-specific settings like git_status’s scan behavior (or disabling it project-by-project via .starship_disabled files, per Starship’s own documentation) addresses the specific cause rather than disabling Starship’s git integration entirely.

Step 8: verify the configuration file is valid

starship config

This opens the configuration file in your default editor and validates it, useful for catching a TOML syntax error before it causes confusing prompt behavior.

Why a shell-agnostic prompt tool is genuinely useful, not just convenient

Since Starship works identically regardless of which shell you’re actually running, switching between Bash, Zsh, or fish across different machines or contexts doesn’t mean maintaining separate prompt configurations for each — one starship.toml file produces the same prompt everywhere Starship is initialized, which is a meaningfully different guarantee than shell-specific PS1 string configuration provides.

Where Starship itself came from

Starship was created by Matan Kushner, who founded the project in 2019 and wrote it in Rust — a deliberate choice favoring fast, native execution over the interpreted-language overhead a prompt evaluated on literally every single new command line is especially sensitive to. That shell-agnostic, single-binary design is precisely what let it become a genuine alternative to framework-specific prompt theming (an Oh My Zsh theme, for instance, only ever works inside Zsh) — the same starship.toml and the same compiled binary produce an identical prompt regardless of which shell happens to be initializing it.

Step 9: add a custom module for information Starship doesn’t track natively

[custom.k8s_context]
command = "kubectl config current-context 2>/dev/null"
when = "command -v kubectl >/dev/null"
format = "on [☸ $output](bold blue) "

A custom module runs an arbitrary shell command and renders its output as part of the prompt, gated by a when guard command that decides whether the module shows at all — here, only when kubectl is actually installed. This is how Starship covers information it has no dedicated built-in module for at all: any value a shell command can print (a Kubernetes context, a feature-flag state, a deploy target) becomes a prompt segment the same way git status or language versions do, styled and positioned through the same format mechanism as every built-in module.

Step 10: diagnose a slow prompt with Starship’s own profiler

starship timings

If the prompt feels sluggish, starship timings prints exactly how long each module took to render on the last prompt draw, sorted slowest first — turning a vague “the prompt feels slow” into a specific module to disable or investigate, rather than guessing. Custom modules count against command_timeout (500ms by default) the same as any other module; a custom command that occasionally runs longer than that gets silently killed mid-render and the segment simply disappears from that prompt draw, which is worth knowing before spending time debugging a custom module that “randomly” fails to appear — it’s very often just running too slowly, not actually erroring.

Step 11: fall back gracefully when Starship or a Nerd Font isn’t available

Not every machine you work on will have Starship installed, and not every terminal you connect from will have a Nerd Font configured — a quick SSH session onto an unfamiliar server is a common case of both. Keeping each shell’s own minimal native prompt configuration intact as a fallback, rather than assuming starship init always succeeds, means an unconfigured environment degrades to something plain and readable instead of an error or a prompt full of broken glyph boxes. Since the eval "$(starship init ...)" line only takes effect when the starship binary is actually found on PATH, wrapping it in an existence check (command -v starship >/dev/null && eval "$(starship init bash)") keeps the same dotfile portable across machines that do and don’t have it installed, without needing a separate configuration file for each case.

Related:

Sources:

Comments