Starship Prompt in Claude Code's Status Line
27 Feb 2026Claude Code has a status line at the bottom of the terminal that shows you the current model and context usage. It’s useful, but it doesn’t show you where you are in the filesystem or what git branch you’re on. I already have Starship configured with all that information for my shell prompt, so I figured: why not reuse it?
Claude Code lets you set a custom status line command in
~/.claude/settings.json. The command receives a JSON blob on stdin with
the model name, working directory, and context window usage, and whatever
you print to stdout becomes the status line.
The trick is getting starship to output something Claude Code can actually
render. Starship detects which shell it’s running in and wraps ANSI color
codes with shell-specific escape sequences - %{...%} for zsh, \[...\]
for bash. Claude Code isn’t a shell, so those sequences show up as
literal garbage:
[Opus 4.6] | ctx:18% | %{%}~/p/dot-files%{%} on %{%} %{%}main%{%} %{%}❯%{%}
The fix: set STARSHIP_SHELL=plain. There’s no actual “plain” shell type
in starship’s code (I checked - it has bash, fish, zsh, etc.), but
unrecognized values fall through to an “unknown” handler that outputs raw
ANSI codes without any shell wrapping.
I also didn’t want the ❯ prompt character in a status line, so I point
starship at a separate config that disables the character and
line_break modules:
# claude-starship.toml
[character]
disabled = true
[line_break]
disabled = true
Here’s the script:
#!/bin/bash
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
if [ "$1" = "install" ]; then
SETTINGS="$HOME/.claude/settings.json"
COMMAND="$SCRIPT_DIR/claude-statusline.sh"
mkdir -p "$HOME/.claude"
if [ -f "$SETTINGS" ]; then
jq --arg cmd "$COMMAND" \
'.statusLine = {"type": "command", "command": $cmd}' \
"$SETTINGS" > "$SETTINGS.tmp" \
&& mv "$SETTINGS.tmp" "$SETTINGS"
else
jq -n --arg cmd "$COMMAND" \
'{"statusLine": {"type": "command", "command": $cmd}}' \
> "$SETTINGS"
fi
echo "Installed. Restart Claude Code to apply."
exit 0
fi
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
CURRENT_DIR=$(echo "$input" | jq -r '.workspace.current_dir')
CONTEXT_PERCENT=$(echo "$input" | jq -r \
'.context_window.used_percentage // 0' | cut -d. -f1)
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
STARSHIP_PROMPT=""
if command -v starship &>/dev/null; then
STARSHIP_PROMPT=$(cd "$CURRENT_DIR" 2>/dev/null \
&& STARSHIP_SHELL=plain \
STARSHIP_CONFIG="$SCRIPT_DIR/claude-starship.toml" \
starship prompt --terminal-width=80 2>/dev/null \
| tr -d '\n')
fi
printf "${BLUE}[%s]${NC} | ${YELLOW}ctx:%s%%${NC} | %s\n" \
"$MODEL" "$CONTEXT_PERCENT" "$STARSHIP_PROMPT"
Drop the script and claude-starship.toml in your dotfiles, then run
claude-statusline.sh install. It uses jq to merge the statusLine
config into your existing ~/.claude/settings.json without clobbering
anything else.
Now my status line shows the model, context usage, current directory, and
git branch - all rendered by my existing starship config. And because
it’s in my private dotfiles repo, install works on any machine.