
Shell Prompt
- 103 installs
- 6 repo stars
- Updated July 22, 2026
- julianobarbosa/claude-code-skills
Modern shell prompt configuration with Powerlevel10k and Zsh Vi Mode. Use when configuring prompts, setting up vi keybindings, customizing cursor styles, optimizing performance.
About
Modern shell prompt configuration with Powerlevel10k and Zsh Vi Mode.. Use for prompt config, vi keybindings, cursor styles, mode indicators, performance optimization.
- beginner skill
- core: cli & terminal
Shell Prompt by the numbers
- 103 all-time installs (skills.sh)
- +2 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #246 of 550 CLI & Terminal skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/julianobarbosa/claude-code-skills --skill shell-promptAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 103 |
|---|---|
| repo stars | ★ 6 |
| Last updated | July 22, 2026 |
| Repository | julianobarbosa/claude-code-skills ↗ |
What it does
Modern shell prompt configuration with Powerlevel10k and Zsh Vi Mode. Use when configuring prompts, setting up vi keybindings, customizing cursor styles, optimizing performance.
Files
Shell Prompt Skill
Configure high-performance shell prompts with Powerlevel10k and Zsh Vi Mode.
Overview
Modern shell prompts provide:
- Git status with branch, dirty state, and remote tracking
- Environment indicators (Python venv, Node version, K8s context)
- Execution time for long-running commands
- Exit code visualization
- Async updates for responsive experience
- Vi mode indicators and cursor changes
Zsh Vi Mode
Zsh supports vi-style line editing with visual feedback through cursor changes and mode indicators.
Quick Setup (Built-in)
# ~/.zshrc
bindkey -v # Enable vi mode
# Reduce key timeout for faster mode switching (default 400ms)
export KEYTIMEOUT=10 # 100ms - don't go below 10Cursor Style by Mode
Change cursor shape based on current mode:
# Add to ~/.zshrc
cursor_mode() {
# Beam cursor for insert mode
cursor_beam='\e[6 q'
# Block cursor for normal mode
cursor_block='\e[2 q'
function zle-keymap-select {
if [[ ${KEYMAP} == vicmd ]] ||
[[ $1 = 'block' ]]; then
echo -ne $cursor_block
elif [[ ${KEYMAP} == main ]] ||
[[ ${KEYMAP} == viins ]] ||
[[ ${KEYMAP} = '' ]] ||
[[ $1 = 'beam' ]]; then
echo -ne $cursor_beam
fi
}
zle-line-init() {
echo -ne $cursor_beam
}
zle -N zle-keymap-select
zle -N zle-line-init
}
cursor_modeCursor Escape Codes
| Code | Style |
|---|---|
\e[1 q | Blinking block |
\e[2 q | Steady block |
\e[3 q | Blinking underline |
\e[4 q | Steady underline |
\e[5 q | Blinking bar/beam |
\e[6 q | Steady bar/beam |
Vi Mode Plugins
Oh My Zsh vi-mode Plugin
# ~/.zshrc
plugins=(... vi-mode)
# Configuration (before sourcing oh-my-zsh.sh)
VI_MODE_SET_CURSOR=true
VI_MODE_RESET_PROMPT_ON_MODE_CHANGE=true
# Cursor styles (0-6)
VI_MODE_CURSOR_NORMAL=2 # Solid block
VI_MODE_CURSOR_INSERT=6 # Solid beam
VI_MODE_CURSOR_VISUAL=6 # Solid beam
VI_MODE_CURSOR_OPPEND=0 # Blinking block
# Mode indicators
MODE_INDICATOR="%F{red}<<<NORMAL%f"
INSERT_MODE_INDICATOR="%F{green}<<<INSERT%f"softmoth/zsh-vim-mode
Full-featured vi mode with text objects and surround bindings.
Installation:
# Clone
git clone https://github.com/softmoth/zsh-vim-mode.git ~/.zsh/zsh-vim-mode
# Source in .zshrc (after other plugins)
source ~/.zsh/zsh-vim-mode/zsh-vim-mode.plugin.zshLoad order matters: zsh-autosuggestions -> zsh-syntax-highlighting -> zsh-vim-mode
Configuration:
# Cursor styles (supports colors!)
MODE_CURSOR_VIINS="#00ff00 blinking bar"
MODE_CURSOR_VICMD="green block"
MODE_CURSOR_REPLACE="red block"
MODE_CURSOR_SEARCH="#ff00ff steady underline"
MODE_CURSOR_VISUAL="$MODE_CURSOR_VICMD steady bar"
MODE_CURSOR_VLINE="$MODE_CURSOR_VISUAL #00ffff"
# Mode indicators (auto-added to RPS1 if unset)
MODE_INDICATOR_VIINS='%F{15}<%F{8}INSERT>%f'
MODE_INDICATOR_VICMD='%F{10}<%F{2}NORMAL>%f'
MODE_INDICATOR_REPLACE='%F{9}<%F{1}REPLACE>%f'
MODE_INDICATOR_SEARCH='%F{13}<%F{5}SEARCH>%f'
MODE_INDICATOR_VISUAL='%F{12}<%F{4}VISUAL>%f'
MODE_INDICATOR_VLINE='%F{12}<%F{4}V-LINE>%f'
# Other options
VIM_MODE_VICMD_KEY='^[' # Default escape key
VIM_MODE_TRACK_KEYMAP=true # Enable mode tracking
VIM_MODE_INITIAL_KEYMAP=viins # Start in insert modeFeatures:
- Text objects:
ci",da(,vi[ - Surround:
cs"'(change surrounding " to ') - Visual mode selection
- Emacs bindings in insert mode (Ctrl-A, Ctrl-E)
jeffreytse/zsh-vi-mode
Modern vi mode with operator-pending mode support.
Installation:
# With zinit
zinit ice depth=1
zinit light jeffreytse/zsh-vi-mode
# Manual
git clone https://github.com/jeffreytse/zsh-vi-mode.git ~/.zsh/zsh-vi-mode
source ~/.zsh/zsh-vi-mode/zsh-vi-mode.plugin.zshConfiguration:
# Cursor styles
ZVM_NORMAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK
ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BEAM
ZVM_VISUAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK
ZVM_VISUAL_LINE_MODE_CURSOR=$ZVM_CURSOR_BLOCK
ZVM_OPPEND_MODE_CURSOR=$ZVM_CURSOR_UNDERLINE
# Mode indicator in prompt
function zvm_after_select_vi_mode() {
case $ZVM_MODE in
$ZVM_MODE_NORMAL)
# Update prompt for normal mode
;;
$ZVM_MODE_INSERT)
# Update prompt for insert mode
;;
$ZVM_MODE_VISUAL)
# Update prompt for visual mode
;;
esac
}
# Disable cursor style changes (if using another method)
ZVM_CURSOR_STYLE_ENABLED=falseKey Bindings Reference
Mode Switching
| Key | Action |
|---|---|
ESC or Ctrl-[ | Enter Normal mode |
i | Insert before cursor |
a | Append after cursor |
I | Insert at line start |
A | Append at line end |
v | Enter Visual mode |
V | Enter Visual Line mode |
Navigation (Normal Mode)
| Key | Action |
|---|---|
h/l | Left/right |
j/k | Down/up in history |
w/W | Forward word |
b/B | Backward word |
e/E | End of word |
0 | Start of line |
^ | First non-blank |
$ | End of line |
f{char} | Find char forward |
F{char} | Find char backward |
t{char} | Till char forward |
T{char} | Till char backward |
Editing (Normal Mode)
| Key | Action |
|---|---|
x | Delete char |
dd | Delete line |
D | Delete to end |
cc | Change line |
C | Change to end |
yy | Yank line |
p/P | Paste after/before |
u | Undo |
Ctrl-r | Redo |
Text Objects
| Key | Action |
|---|---|
ciw | Change inner word |
daw | Delete a word (with space) |
ci" | Change inside quotes |
da( | Delete around parens |
vi[ | Select inside brackets |
KEYTIMEOUT Considerations
The KEYTIMEOUT variable affects multi-key sequences:
# Default is 40 (400ms)
export KEYTIMEOUT=10 # 100ms - good balance
# Too low (<10) breaks multi-key bindings
# Too high (>40) feels sluggish on ESCWorkarounds for escape delay:
# Option 1: Use Ctrl-[ instead of Escape
# (Ctrl-[ sends ESC immediately)
# Option 2: Bind jk or jj to escape
bindkey -M viins 'jk' vi-cmd-mode
bindkey -M viins 'jj' vi-cmd-modePowerlevel10k
Installation
# With Oh My Zsh
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
# Set in .zshrc
ZSH_THEME="powerlevel10k/powerlevel10k"
# Run configuration wizard
p10k configureInstant Prompt Setup
Add at the very top of ~/.zshrc (before anything else):
# Enable Powerlevel10k instant prompt
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fiAdd at the end of ~/.zshrc:
# Source Powerlevel10k config
[[ -f ~/.p10k.zsh ]] && source ~/.p10k.zshConfiguration Options
Key settings in ~/.p10k.zsh:
# Left prompt segments
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
os_icon
dir
vcs
newline
prompt_char
)
# Right prompt segments
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
status
command_execution_time
background_jobs
virtualenv
kubecontext
azure
aws
vi_mode # Show vi mode indicator!
context
time
)
# Transient prompt (clean up previous prompts)
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
# Directory truncation
typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=3
# Vi mode indicator styling
typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING=''
typeset -g POWERLEVEL9K_VI_COMMAND_MODE_STRING='NORMAL'
typeset -g POWERLEVEL9K_VI_MODE_NORMAL_FOREGROUND=0
typeset -g POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=2Performance Tuning
# Disable slow segments
typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=false # Keep enabled!
# Large repo optimization
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=1000
# Async git status (default, don't change)
typeset -g POWERLEVEL9K_VCS_BACKENDS=(git)
# Reduce segment count for speed
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time vi_mode)Performance Summary
Benchmark Results (zsh-bench)
| Metric | Target | Powerlevel10k |
|---|---|---|
| First prompt lag | <50ms | 24ms |
| Command lag | <10ms | 15ms |
| Git status (small) | <30ms | <10ms |
| Git status (large) | <100ms | Async/instant |
Architecture
Powerlevel10k (gitstatus daemon):
┌─────────────┐ pipes ┌─────────────┐
│ Zsh │ <============> │ gitstatusd │
│ (prompt) │ │ (C++ daemon)
└─────────────┘ └─────────────┘
│ │
│ async │ keeps state
│ never blocks │ in memory
▼ ▼
Instant prompt Fast git queriesBenchmarking Your Setup
Using zsh-bench
# Install
git clone https://github.com/romkatv/zsh-bench ~/zsh-bench
# Run benchmark
~/zsh-bench/zsh-bench
# Key metrics to watch:
# - first_prompt_lag_ms: <50ms ideal
# - command_lag_ms: <10ms idealManual Timing
# Zsh startup time
time zsh -i -c exit
# Per-command timing
TIMEFMT='%*E seconds'
time (for i in {1..10}; do zsh -i -c 'print -P "$PROMPT"' >/dev/null; done)Troubleshooting
Slow Prompt
# Check segment timing
zsh -xv # Verbose trace
# Common culprits:
# - git_status in large repos
# - python/node version detection
# - cloud context (aws/azure/gcloud)P10k: gitstatus Failed
# Reinstall gitstatusd
rm -rf ~/.cache/gitstatus
# Restart zsh
exec zshVi Mode Not Working
# Verify vi mode is enabled
bindkey -l | grep vi
# Check current keymap
echo $KEYMAP
# Reset bindings
bindkey -vCursor Not Changing
1. Verify terminal supports cursor escape codes 2. Check zle-keymap-select is defined: whence -f zle-keymap-select 3. Some terminals (like Apple Terminal) have limited cursor support 4. Try iTerm2 or Alacritty for full support
References
- references/powerlevel10k-config.md - Complete P10k configuration
- references/zsh-vim-mode.md - softmoth/zsh-vim-mode details
- references/performance-tuning.md - Advanced optimization
- references/troubleshooting.md - Common issues and fixes
External Links
- Powerlevel10k: https://github.com/romkatv/powerlevel10k
- softmoth/zsh-vim-mode: https://github.com/softmoth/zsh-vim-mode
- jeffreytse/zsh-vi-mode: https://github.com/jeffreytse/zsh-vi-mode
- Oh My Zsh vi-mode: https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/vi-mode
- zsh-bench: https://github.com/romkatv/zsh-bench
- gitstatus: https://github.com/romkatv/gitstatus
---
Gotchas
- P10k instant prompt MUST be at the very top of `.zshrc`, before any output: Even an
echoor unguardedcommand -vproduces a warning and disables instant prompt. Move all stdout-producing code below the instant prompt block or wrap with&>/dev/null. - `KEYTIMEOUT=1` breaks multi-key bindings like `jk` to escape: Below 10 (100ms), zsh can't distinguish
jthenkfrom a multi-byte ESC sequence. Symptom: prompt acceptsjandkas literal characters in normal mode. - `bindkey -v` resets ALL previous bindings: Custom bindings made before
bindkey -vare silently wiped. Place vi mode setup first, then all custombindkeycalls. - Cursor escape codes (`\e[6 q`) don't work in tmux without passthrough: tmux strips DECSCUSR by default — add
set -ga terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[ q'to.tmux.confor cursor stays as block. - gitstatusd caches per-repo: a `git reset --hard` from outside zsh shows stale prompt: P10k's daemon hasn't seen the change. Wait ~2s, run
git statusmanually, orp10k reloadto force refresh. - Plugin load order: zsh-vim-mode AFTER autosuggestions and syntax-highlighting: Reversed order causes vim-mode to overwrite zle widgets — symptoms range from broken cursor changes to nonfunctional ESC. Verify with
zle -lL | grep widget-name.
Shell Prompt Performance Tuning
Advanced guide for optimizing shell prompt performance.
Understanding Prompt Latency
Key Metrics
| Metric | Acceptable | Good | Excellent |
|---|---|---|---|
| First prompt lag | <200ms | <50ms | <20ms |
| Command lag | <50ms | <20ms | <10ms |
| Git status | <200ms | <50ms | <20ms |
Perception Thresholds
- <10ms: Imperceptible, feels instant
- 10-50ms: Barely noticeable
- 50-100ms: Noticeable but acceptable
- 100-200ms: Slow, annoying
- >200ms: Very slow, interrupts flow
Benchmarking Tools
zsh-bench (Comprehensive)
# Install
git clone https://github.com/romkatv/zsh-bench ~/zsh-bench
# Run benchmark
~/zsh-bench/zsh-bench
# Output metrics:
# - creates_tty: whether test runs in TTY
# - has_compsys: completion system loaded
# - has_syntax_highlighting: syntax highlighting enabled
# - has_autosuggestions: autosuggestions enabled
# - has_git_prompt: git info in prompt
# - first_prompt_lag_ms: time to first prompt
# - first_command_lag_ms: time for first command
# - command_lag_ms: subsequent command latency
# - input_lag_ms: input responsiveness
# - exit_time_ms: shell exit timeManual Timing
# Zsh startup time (10 iterations)
for i in {1..10}; do
time zsh -i -c exit
done
# Average startup time
repeat 10 { time zsh -i -c exit } 2>&1 | grep real | awk '{sum+=$2} END {print sum/10}'
# Profile with zprof
# Add to top of .zshrc:
zmodload zsh/zprof
# Add to bottom of .zshrc:
zprof
# Then start new shell to see profileStarship Timing
# Per-module timing
starship timings
# Sample output:
# aws - <1ms - ~
# directory - 4ms - ~/project
# git_branch - 2ms - main
# git_status - 185ms - [!+] <- SLOW!
# character - <1ms - >Common Performance Bottlenecks
1. Git Status in Large Repos
Symptoms: Prompt freezes when entering repo directory
Causes:
- Many untracked files
- Large index
- Slow disk I/O
- Remote git operations
Solutions:
# Powerlevel10k: Limit dirty check
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=100
# Powerlevel10k: Disable git entirely
typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true# Starship: Disable git_status
[git_status]
disabled = true
# Or increase timeout
command_timeout = 20002. Language Version Detection
Symptoms: Slow prompt in project directories
Causes:
- Python/Node/Ruby version managers
- Multiple detect_files checks
- Traversing up directory tree
Solutions:
# Starship: Disable language modules
[python]
disabled = true
[nodejs]
disabled = true
[ruby]
disabled = true
[package]
disabled = true3. Cloud Context Lookups
Symptoms: Slow prompt with AWS/Azure/GCP modules
Causes:
- Reading config files
- API calls for credentials
- Token refresh
Solutions:
# Powerlevel10k: Show only on relevant commands
typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|terraform'
typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm'# Starship: Disable cloud modules
[aws]
disabled = true
[gcloud]
disabled = true
[azure]
disabled = true
[kubernetes]
disabled = true4. Slow Shell Startup
Symptoms: Long delay opening new terminal
Causes:
- Heavy plugin loading
- Compinit regeneration
- Slow .zshrc execution
Solutions:
# Lazy load completions (only regenerate daily)
autoload -Uz compinit
if [[ -n ~/.zcompdump(#qN.mh+24) ]]; then
compinit
else
compinit -C
fi
# Use instant prompt (P10k)
# Add at top of .zshrc - see P10k docs
# Defer slow plugins
zsh-defer source heavy-plugin.zshPowerlevel10k Optimization
Fastest P10k Config
# ~/.p10k.zsh
# Minimal segments
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir vcs newline prompt_char)
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time)
# Lean style (no separators)
typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR=''
typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR=''
typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR=' '
typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR=' '
# Transient prompt
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
# Git optimization
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=100
typeset -g POWERLEVEL9K_VCS_BACKENDS=(git)
# Directory optimization
typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=2
# Disable wizard
typeset -g POWERLEVEL9K_DISABLE_CONFIGURATION_WIZARD=trueInstant Prompt Best Practices
# At VERY TOP of .zshrc (before anything else)
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# Everything that needs console input ABOVE this block
# Everything else BELOW
# Suppress warnings if needed
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quietgitstatus Tuning
# Reduce index scan threshold
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=100
# Disable for huge repos (>10k files)
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1
# Only show branch, not status
typeset -g POWERLEVEL9K_VCS_GIT_HOOKS=(git-remotebranch)Starship Optimization
Fastest Starship Config
# ~/.config/starship.toml
# Minimal format
format = "$directory$git_branch$character"
add_newline = false
command_timeout = 500
[directory]
truncation_length = 2
truncate_to_repo = true
style = "cyan"
[git_branch]
format = "[$branch]($style) "
style = "purple"
truncation_length = 15
# DISABLE git_status (biggest impact)
[git_status]
disabled = true
[character]
success_symbol = "[>](green)"
error_symbol = "[>](red)"
# Disable ALL language detectors
[python]
disabled = true
[nodejs]
disabled = true
[rust]
disabled = true
[golang]
disabled = true
[java]
disabled = true
[ruby]
disabled = true
[php]
disabled = true
[package]
disabled = true
# Disable cloud contexts
[aws]
disabled = true
[gcloud]
disabled = true
[azure]
disabled = true
[kubernetes]
disabled = trueTimeout Configuration
# Global timeout (default 500ms)
command_timeout = 1000
# For specific modules that need more time
# (Individual modules don't have timeout settings,
# but you can increase global timeout)Shell Configuration Optimization
Lazy Loading
# Lazy load nvm (slow by default)
lazy_load_nvm() {
unset -f nvm node npm npx
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
}
nvm() { lazy_load_nvm && nvm "$@" }
node() { lazy_load_nvm && node "$@" }
npm() { lazy_load_nvm && npm "$@" }
npx() { lazy_load_nvm && npx "$@" }
# Lazy load pyenv
lazy_load_pyenv() {
unset -f pyenv python python3 pip pip3
export PYENV_ROOT="$HOME/.pyenv"
eval "$(pyenv init -)"
}
pyenv() { lazy_load_pyenv && pyenv "$@" }
python() { lazy_load_pyenv && python "$@" }
python3() { lazy_load_pyenv && python3 "$@" }Completion Caching
# Only regenerate completions once per day
autoload -Uz compinit
if [[ -n ${ZDOTDIR:-$HOME}/.zcompdump(#qN.mh+24) ]]; then
compinit
else
compinit -C # Skip security check
fiPlugin Manager Optimization
# Zinit turbo mode (deferred loading)
zinit ice wait lucid
zinit light zsh-users/zsh-autosuggestions
zinit ice wait lucid atload'_zsh_autosuggest_start'
zinit light zsh-users/zsh-syntax-highlighting
# Compile plugins
zinit ice compile'*.zsh'
zinit light some/pluginMeasuring Improvements
Before/After Comparison
# Create baseline
~/zsh-bench/zsh-bench > ~/prompt-baseline.txt
# Make changes to config
# ...
# Compare
~/zsh-bench/zsh-bench > ~/prompt-optimized.txt
diff ~/prompt-baseline.txt ~/prompt-optimized.txtContinuous Monitoring
# Add to .zshrc for timing info
REPORTTIME=1 # Report commands taking >1 second
# Prompt render time in RPROMPT
RPROMPT='%F{8}${PROMPT_RENDER_TIME}ms%f'Platform-Specific Tips
macOS
# Use fast git from Homebrew
brew install git
# Ensure using Homebrew git, not Xcode
which git # Should be /opt/homebrew/bin/gitLinux
# Increase inotify watches for large repos
echo 'fs.inotify.max_user_watches=524288' | sudo tee -a /etc/sysctl.conf
sudo sysctl -pWSL
# Starship: Avoid Windows paths
[directory]
truncation_length = 3
# Don't traverse Windows filesystem# P10k: Avoid Windows git
export GIT_OPTIONAL_LOCKS=0Summary: Optimization Checklist
1. [ ] Benchmark current state with zsh-bench 2. [ ] Enable instant prompt (P10k only) 3. [ ] Disable git_status in large repos 4. [ ] Remove unused language modules 5. [ ] Disable cloud context modules or limit to relevant commands 6. [ ] Lazy load version managers (nvm, pyenv, rbenv) 7. [ ] Cache completions (compinit -C) 8. [ ] Use lean/minimal prompt style 9. [ ] Reduce segment count to essentials 10. [ ] Benchmark again and compare
Powerlevel10k Configuration Reference
Complete guide to configuring Powerlevel10k for maximum performance and customization.
File Structure
~/.zshrc # Main config, loads P10k
~/.p10k.zsh # P10k configuration (generated by wizard)
~/.cache/p10k-instant-prompt-*.zsh # Instant prompt cache
~/.cache/gitstatus/ # gitstatusd binary cacheInstallation Methods
Oh My Zsh
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
# In .zshrc
ZSH_THEME="powerlevel10k/powerlevel10k"Zinit
zinit ice depth=1
zinit light romkatv/powerlevel10kAntigen
antigen theme romkatv/powerlevel10kManual
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >> ~/.zshrcInstant Prompt
Setup (Required for Best Performance)
Add at the very beginning of ~/.zshrc:
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
# Initialization code that may require console input (password prompts, [y/n]
# confirmations, etc.) must go above this block; everything else may go below.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fiHow It Works
1. P10k saves prompt state to cache file 2. On shell start, cache is loaded instantly (~10ms) 3. Real prompt calculated in background 4. Seamless transition when ready
Verbosity Levels
# In ~/.p10k.zsh
typeset -g POWERLEVEL9K_INSTANT_PROMPT=verbose # Show warnings
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet # Suppress warnings
typeset -g POWERLEVEL9K_INSTANT_PROMPT=off # Disable featurePrompt Segments
Left Prompt Elements
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
# Line 1
os_icon # OS identifier
dir # Current directory
vcs # Git status
# Line 2
newline # Line break
prompt_char # Prompt symbol (changes on error)
)Right Prompt Elements
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
# Line 1
status # Exit code of last command
command_execution_time # Duration of last command
background_jobs # Background job indicator
direnv # direnv status
virtualenv # Python venv
pyenv # Python version
nodenv # Node.js version
nvm # NVM version
kubecontext # Kubernetes context
terraform # Terraform workspace
aws # AWS profile
azure # Azure account
gcloud # GCP project
context # user@hostname
time # Current time
# Line 2
newline
)Available Segments
| Segment | Description |
|---|---|
os_icon | Operating system icon |
dir | Current directory |
vcs | Version control (git) |
prompt_char | ❯ or ❮ based on exit code |
status | Exit code if non-zero |
command_execution_time | Command duration |
background_jobs | Background job count |
virtualenv | Python virtual environment |
anaconda | Conda environment |
pyenv | pyenv Python version |
nodenv | nodenv Node version |
nvm | nvm Node version |
rbenv | rbenv Ruby version |
kubecontext | Kubernetes context |
terraform | Terraform workspace |
aws | AWS profile |
azure | Azure subscription |
gcloud | GCP project |
docker_context | Docker context |
context | user@hostname |
time | Current time |
battery | Battery status |
wifi | WiFi signal |
vpn_ip | VPN indicator |
Directory Configuration
# Truncation strategy
typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
# Options: truncate_to_unique, truncate_from_right, truncate_to_last,
# truncate_absolute, truncate_with_folder_marker
# Directory length
typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=3
# Anchor folders (always show full name)
typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER='(.git|.svn|.terraform)'
# Show full path in repos
typeset -g POWERLEVEL9K_DIR_TRUNCATE_BEFORE_MARKER=true
# Home directory symbol
typeset -g POWERLEVEL9K_HOME_ICON='~'
# Directory colors
typeset -g POWERLEVEL9K_DIR_FOREGROUND=31
typeset -g POWERLEVEL9K_DIR_BACKGROUND=noneGit (VCS) Configuration
# Enable git status
typeset -g POWERLEVEL9K_VCS_BACKENDS=(git)
# Icons
typeset -g POWERLEVEL9K_VCS_BRANCH_ICON='\uF126 ' #
typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?'
typeset -g POWERLEVEL9K_VCS_UNSTAGED_ICON='!'
typeset -g POWERLEVEL9K_VCS_STAGED_ICON='+'
# Show remote tracking
typeset -g POWERLEVEL9K_VCS_GIT_HOOKS=(vcs-detect-changes git-untracked git-aheadbehind git-stash git-remotebranch)
# Performance: disable for large repos
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=1000
# Disable git status completely (fastest)
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
# Colors for states
typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=76
typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=178
typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=178Command Execution Time
# Minimum duration to show (seconds)
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_THRESHOLD=3
# Precision (decimal places)
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_PRECISION=2
# Format
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FORMAT='d h m s'
# Colors
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_FOREGROUND=yellow
typeset -g POWERLEVEL9K_COMMAND_EXECUTION_TIME_BACKGROUND=noneTransient Prompt
Cleans up previous prompts for cleaner scrollback:
# Enable transient prompt
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=always
# Options: off, always, same-dir
# What to show in transient prompt
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT_ELEMENTS=(prompt_char)Kubernetes Context
# Show kubecontext
typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc|istioctl|kogito|k9s|helmfile|flux|fluxctl|stern'
# Hide default context
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTEXT_PATTERN='default'
# Shorten context names
typeset -g POWERLEVEL9K_KUBECONTEXT_SHORTEN=(
'gke_*_*_*' 'gke-$4'
'arn:aws:eks:*:*:cluster/*' 'eks-$4'
)
# Colors per context pattern
typeset -g POWERLEVEL9K_KUBECONTEXT_PROD_FOREGROUND=red
typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=(
'*prod*' PROD
'*staging*' STAGING
'*' DEFAULT
)AWS Profile
# Show AWS profile
typeset -g POWERLEVEL9K_AWS_SHOW_ON_COMMAND='aws|awless|terraform|pulumi|terragrunt'
# Colors per profile
typeset -g POWERLEVEL9K_AWS_CLASSES=(
'*prod*' PROD
'*dev*' DEV
'*' DEFAULT
)
typeset -g POWERLEVEL9K_AWS_PROD_FOREGROUND=red
typeset -g POWERLEVEL9K_AWS_DEV_FOREGROUND=greenPrompt Styles
Rainbow (Colorful Background)
typeset -g POWERLEVEL9K_MODE=nerdfont-complete
typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR='\uE0B0'
typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR='\uE0B2'Lean (No Background)
typeset -g POWERLEVEL9K_MODE=nerdfont-complete
typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR=''
typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR=''
typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR=' '
typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR=' 'Pure Style (Minimal)
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir vcs newline prompt_char)
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=()
typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=green
typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=redPerformance Optimization
Fastest Configuration
# Minimal segments
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(dir vcs newline prompt_char)
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status command_execution_time)
# Disable slow features
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=100
typeset -g POWERLEVEL9K_DISABLE_CONFIGURATION_WIZARD=true
# Use lean style (no separators to render)
typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR=''
typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR=''Disable Specific Segments
# Disable via content
typeset -g POWERLEVEL9K_TIME_CONTENT_EXPANSION=''
# Or remove from elements array entirelyReconfiguration
# Run wizard again
p10k configure
# Reload config without restart
source ~/.p10k.zsh
# Reset everything
rm ~/.p10k.zsh
exec zshCommon Issues
Fonts Not Displaying
# Install Nerd Font
brew tap homebrew/cask-fonts
brew install --cask font-meslo-lg-nerd-font
# Set in terminal emulator preferencesInstant Prompt Errors
# Add before instant prompt block
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quietSlow in Large Repos
# Reduce dirty check threshold
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=100
# Or disable dirty check entirely
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1Starship Configuration Reference
Complete guide to configuring Starship prompt with TOML.
File Location
~/.config/starship.toml # Main config file
$STARSHIP_CONFIG # Override via environment variableInstallation
Package Managers
# macOS
brew install starship
# Arch Linux
pacman -S starship
# Windows (scoop)
scoop install starship
# Windows (winget)
winget install starshipBinary Install
# Linux/macOS
curl -sS https://starship.rs/install.sh | sh
# With specific directory
curl -sS https://starship.rs/install.sh | sh -s -- --bin-dir ~/.local/binCargo
cargo install starship --lockedShell Integration
Zsh
# ~/.zshrc
eval "$(starship init zsh)"Bash
# ~/.bashrc
eval "$(starship init bash)"Fish
# ~/.config/fish/config.fish
starship init fish | sourcePowerShell
# Microsoft.PowerShell_profile.ps1
Invoke-Expression (&starship init powershell)Nushell
# config.nu
use ~/.cache/starship/init.nuBasic Configuration
Minimal Fast Config
# ~/.config/starship.toml
# Prompt format
format = """
$directory\
$git_branch\
$git_status\
$character"""
# Disable newline at start
add_newline = false
# Character
[character]
success_symbol = "[>](bold green)"
error_symbol = "[>](bold red)"Full-Featured Config
# ~/.config/starship.toml
format = """
[┌─](bold blue)$os$username$hostname$directory$git_branch$git_status$git_state
[└─](bold blue)$character"""
add_newline = false
command_timeout = 1000
[os]
disabled = false
style = "bold white"
[username]
show_always = false
style_user = "bold yellow"
format = "[$user]($style)@"
[hostname]
ssh_only = true
format = "[$hostname]($style):"
style = "bold green"
[directory]
truncation_length = 3
truncate_to_repo = true
style = "bold cyan"
format = "[$path]($style)[$read_only]($read_only_style) "
[git_branch]
format = "[$symbol$branch(:$remote_branch)]($style) "
symbol = " "
style = "bold purple"
[git_status]
format = '([$all_status$ahead_behind]($style))'
style = "bold red"
conflicted = "="
ahead = "⇡${count}"
behind = "⇣${count}"
diverged = "⇕⇡${ahead_count}⇣${behind_count}"
untracked = "?${count}"
stashed = "*${count}"
modified = "!${count}"
staged = "+${count}"
renamed = "»${count}"
deleted = "✘${count}"
[character]
success_symbol = "[❯](bold green)"
error_symbol = "[❯](bold red)"
vimcmd_symbol = "[❮](bold green)"Module Configuration
Directory
[directory]
truncation_length = 3
truncate_to_repo = true
truncation_symbol = "…/"
home_symbol = "~"
read_only = " "
read_only_style = "bold red"
style = "bold cyan"
format = "[$path]($style)[$read_only]($read_only_style) "
# Substitutions
[directory.substitutions]
"Documents" = " "
"Downloads" = " "
"Music" = " "
"Pictures" = " "
"~/projects" = " "Git Branch
[git_branch]
format = "[$symbol$branch(:$remote_branch)]($style) "
symbol = " "
style = "bold purple"
truncation_length = 20
truncation_symbol = "…"
only_attached = false
always_show_remote = falseGit Status
[git_status]
format = '([\[$all_status$ahead_behind\]]($style) )'
style = "bold red"
conflicted = "="
ahead = "⇡${count}"
behind = "⇣${count}"
diverged = "⇕⇡${ahead_count}⇣${behind_count}"
untracked = "?${count}"
stashed = "$${count}"
modified = "!${count}"
staged = "+${count}"
renamed = "»${count}"
deleted = "✘${count}"
# Performance: disable if slow
disabled = falseGit State
[git_state]
format = '\([$state( $progress_current/$progress_total)]($style)\) '
rebase = "REBASING"
merge = "MERGING"
revert = "REVERTING"
cherry_pick = "CHERRY-PICKING"
bisect = "BISECTING"
am = "AM"
am_or_rebase = "AM/REBASE"
style = "bold yellow"Command Duration
[cmd_duration]
min_time = 2000 # milliseconds
format = "took [$duration]($style) "
style = "bold yellow"
show_milliseconds = false
show_notifications = false # Desktop notifications
min_time_to_notify = 45000Status (Exit Code)
[status]
format = '[$symbol$status]($style) '
symbol = "✖ "
success_symbol = ""
not_executable_symbol = "🚫"
not_found_symbol = "🔍"
sigint_symbol = "🧱"
signal_symbol = "⚡"
style = "bold red"
map_symbol = true
disabled = falsePython
[python]
format = '[${symbol}${pyenv_prefix}(${version})(\($virtualenv\))]($style) '
symbol = " "
style = "bold yellow"
pyenv_version_name = false
pyenv_prefix = "pyenv "
python_binary = ["python", "python3", "python2"]
detect_extensions = ["py"]
detect_files = [".python-version", "Pipfile", "pyproject.toml", "requirements.txt", "setup.py", "tox.ini"]
detect_folders = []
# Disable if causing slowness
disabled = falseNode.js
[nodejs]
format = "[$symbol($version)]($style) "
symbol = " "
style = "bold green"
detect_extensions = ["js", "mjs", "cjs", "ts", "mts", "cts"]
detect_files = ["package.json", ".node-version", ".nvmrc"]
detect_folders = ["node_modules"]
not_capable_style = "bold red"
disabled = falseKubernetes
[kubernetes]
format = '[$symbol$context( \($namespace\))]($style) '
symbol = "☸ "
style = "bold blue"
disabled = false
# Only show on specific commands
detect_files = []
detect_folders = []
detect_extensions = []
detect_env_vars = ["KUBECONFIG"]
# Context aliases
[kubernetes.context_aliases]
"gke_.*_(?P<cluster>[\\w-]+)" = "gke-$cluster"
"arn:aws:eks:.*:.*:cluster/(?P<cluster>[\\w-]+)" = "eks-$cluster"AWS
[aws]
format = '[$symbol($profile)(\($region\))(\[$duration\])]($style) '
symbol = " "
style = "bold yellow"
disabled = false
expiration_symbol = "X"
force_display = false
[aws.region_aliases]
us-east-1 = "ue1"
us-west-2 = "uw2"
eu-west-1 = "ew1"
[aws.profile_aliases]
CompanyAccount-production = "prod"
CompanyAccount-development = "dev"Azure
[azure]
format = "[$symbol($subscription)]($style) "
symbol = " "
style = "bold blue"
disabled = falseDocker
[docker_context]
format = "[$symbol$context]($style) "
symbol = " "
style = "bold blue"
only_with_files = true
detect_files = ["docker-compose.yml", "docker-compose.yaml", "Dockerfile"]
detect_folders = []
disabled = falseTerraform
[terraform]
format = "[$symbol$workspace]($style) "
symbol = "💠 "
style = "bold 105"
detect_files = [".terraform", "*.tf", "*.hcl"]
detect_folders = [".terraform"]
disabled = falseTime
[time]
format = "[$time]($style) "
style = "bold white"
use_12hr = false
time_format = "%H:%M"
utc_time_offset = "local"
disabled = true # Disabled by default
time_range = "-" # Always show, or use "09:00:00-17:00:00"Performance Optimization
Minimal Config for Speed
# Fastest possible Starship config
format = "$directory$git_branch$character"
add_newline = false
command_timeout = 500
[directory]
truncation_length = 2
truncate_to_repo = true
[git_branch]
format = "[$branch]($style) "
style = "purple"
# Disable git_status (biggest performance hit)
[git_status]
disabled = true
[character]
success_symbol = "[>](green)"
error_symbol = "[>](red)"
# Disable all language detectors
[python]
disabled = true
[nodejs]
disabled = true
[rust]
disabled = true
[golang]
disabled = true
[java]
disabled = true
[package]
disabled = trueIncrease Timeouts
# For large repos
command_timeout = 2000 # 2 seconds (default 500ms)
[git_status]
disabled = false # Keep enabled but with longer timeoutDisable Specific Modules
# Modules that can be slow
[python]
disabled = true
[nodejs]
disabled = true
[package]
disabled = true
[git_status]
disabled = true # Biggest impact on large reposDebugging
Show Timing Per Module
starship timingsOutput:
aws - <1ms - ~
character - <1ms - >
cmd_duration - <1ms -
directory - 4ms - ~/projects/app
git_branch - 2ms - main
git_status - 185ms - [!+]Explain Current Prompt
starship explainCheck Configuration
starship configPrint Prompt
starship promptCustom Modules
Basic Custom Command
[custom.giturl]
command = "git remote get-url origin | sed 's/.*github.com[:\\/]//' | sed 's/.git$//'"
when = "git rev-parse --git-dir 2>/dev/null"
format = "[$output]($style) "
style = "bold cyan"Environment Variable
[env_var.KUBECONFIG]
format = "[$env_value]($style) "
style = "bold yellow"
disabled = falseCustom with Shell
[custom.docker_host]
command = "echo $DOCKER_HOST | sed 's|tcp://||'"
when = '[ -n "$DOCKER_HOST" ]'
shell = ["bash", "--noprofile", "--norc"]
format = "[🐋 $output]($style) "
style = "bold blue"Presets
Apply a Preset
# List available presets
starship preset --list
# Apply preset
starship preset nerd-font-symbols -o ~/.config/starship.toml
starship preset plain-text-symbols -o ~/.config/starship.toml
starship preset pure-preset -o ~/.config/starship.toml
starship preset tokyo-night -o ~/.config/starship.tomlPopular Presets
nerd-font-symbols- Uses Nerd Font iconsplain-text-symbols- ASCII only, no special fontspure-preset- Minimal like Pure prompttokyo-night- Dark theme inspired by Tokyo Nightgruvbox-rainbow- Gruvbox color schemepastel-powerline- Soft colors with powerline
Common Issues
Git Status Slow
# Option 1: Disable
[git_status]
disabled = true
# Option 2: Increase timeout
command_timeout = 2000Module Not Showing
# Check if module is detecting correctly
cd /path/to/project
starship explain
# Force module to show
[python]
detect_files = []
detect_folders = []
detect_extensions = []
python_binary = ["python3"]Wrong Version Detected
# Specify binary path
[python]
python_binary = ["/usr/local/bin/python3", "python3", "python"]Prompt Too Slow
# Identify slow modules
starship timings
# Disable culprits
[git_status]
disabled = true
[python]
disabled = trueShell Prompt Troubleshooting
Common issues and solutions for Powerlevel10k and Starship.
Quick Diagnostics
Check Current Setup
# What shell?
echo $SHELL
echo $ZSH_VERSION
# What prompt?
echo $ZSH_THEME # P10k via OMZ
which starship # Starship installed?
# P10k status
[[ -f ~/.p10k.zsh ]] && echo "P10k config exists"
# Starship status
[[ -f ~/.config/starship.toml ]] && echo "Starship config exists"Timing Analysis
# Shell startup time
time zsh -i -c exit
# Starship module timing
starship timings
# P10k profiling (add to .zshrc)
zmodload zsh/zprof
# Then at end:
zprofPowerlevel10k Issues
Icons/Glyphs Not Displaying
Symptom: Boxes, question marks, or missing icons
Solution 1: Install Nerd Font
# macOS
brew tap homebrew/cask-fonts
brew install --cask font-meslo-lg-nerd-font
# Or download manually from
# https://github.com/ryanoasis/nerd-fonts/releasesSolution 2: Configure Terminal
1. Open terminal preferences 2. Set font to "MesloLGS NF" or installed Nerd Font 3. Restart terminal
Solution 3: Use ASCII-only mode
# Re-run wizard with "no" to font questions
p10k configureInstant Prompt Errors
Symptom: Warnings about console output during instant prompt
Solution 1: Move output above instant prompt block
# This BEFORE instant prompt:
echo "Welcome!"
# Instant prompt block
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# Everything else AFTERSolution 2: Suppress warnings
# In ~/.p10k.zsh
typeset -g POWERLEVEL9K_INSTANT_PROMPT=quietSolution 3: Disable instant prompt
# In ~/.p10k.zsh
typeset -g POWERLEVEL9K_INSTANT_PROMPT=offgitstatus Failed to Initialize
Symptom: [ERROR]: gitstatus failed to initialize
Solution 1: Clear cache
rm -rf ~/.cache/gitstatus
exec zshSolution 2: Manual binary install
# Check architecture
uname -m
# Download appropriate binary from
# https://github.com/romkatv/gitstatus/releases
# Place in ~/.cache/gitstatus/Solution 3: Build from source
git clone --depth=1 https://github.com/romkatv/gitstatus.git
cd gitstatus
./build -wSlow in Git Repositories
Symptom: Prompt freezes when entering repo
Solution 1: Reduce dirty check threshold
# ~/.p10k.zsh
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=100Solution 2: Disable dirty check
typeset -g POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY=-1Solution 3: Disable git entirely
typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=trueTheme Not Loading
Symptom: Default zsh prompt instead of P10k
Check 1: Theme path
ls ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10kCheck 2: .zshrc setting
grep ZSH_THEME ~/.zshrc
# Should be: ZSH_THEME="powerlevel10k/powerlevel10k"Check 3: Oh My Zsh loading
grep "source.*oh-my-zsh.sh" ~/.zshrcSolution: Reinstall
rm -rf ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
exec zshConfiguration Wizard Issues
Symptom: p10k configure doesn't work
Solution 1: Source manually
source ~/.oh-my-zsh/custom/themes/powerlevel10k/powerlevel10k.zsh-theme
p10k configureSolution 2: Reset config
rm ~/.p10k.zsh
exec zsh
# Wizard should start automaticallyStarship Issues
Prompt Not Showing
Symptom: Default shell prompt instead of Starship
Check 1: Installation
which starship
starship --versionCheck 2: Shell integration
# Zsh
grep starship ~/.zshrc
# Should have: eval "$(starship init zsh)"
# Bash
grep starship ~/.bashrcSolution: Add integration
# ~/.zshrc
eval "$(starship init zsh)"Git Status Timeout
Symptom: [WARN] - Executing command "/usr/bin/git" timed out
Solution 1: Increase timeout
# ~/.config/starship.toml
command_timeout = 2000 # 2 secondsSolution 2: Disable git_status
[git_status]
disabled = trueSolution 3: Optimize git
# For very large repos
git config core.untrackedCache true
git config core.fsmonitor trueModule Not Appearing
Symptom: Expected module missing from prompt
Check 1: Detection files
# Show what Starship detects
starship explainCheck 2: Module disabled
# Check if disabled in config
[python]
disabled = false # Make sure this isn't trueSolution: Force detection
[python]
detect_files = []
detect_folders = []
detect_extensions = []
python_binary = ["python3", "python"]
disabled = falseSlow Prompt
Symptom: Noticeable delay after each command
Step 1: Identify slow module
starship timingsStep 2: Disable culprit
# If git_status is slow
[git_status]
disabled = true
# If python detection is slow
[python]
disabled = trueConfig Not Loading
Symptom: Changes to starship.toml have no effect
Check 1: Config location
echo $STARSHIP_CONFIG
ls ~/.config/starship.tomlCheck 2: TOML syntax
# Validate TOML
starship config # Will error on invalid syntaxSolution: Specify config path
export STARSHIP_CONFIG=~/.config/starship.tomlWrong Version Detected
Symptom: Shows wrong Python/Node/etc. version
Solution 1: Specify binary path
[python]
python_binary = ["/usr/local/bin/python3", "python3"]Solution 2: Check PATH order
which python
which -a python # All in PATHGeneral Issues
Prompt Appears Twice
Symptom: Duplicate prompts displayed
Cause: Multiple prompt initializations
Solution: Check for duplicate init calls
grep -E "(p10k|starship)" ~/.zshrc
# Remove duplicatesColors Wrong
Symptom: Incorrect or missing colors
Check 1: Terminal color support
echo $TERM
# Should be xterm-256color or similarCheck 2: COLORTERM
echo $COLORTERM
# Should be truecolor for full supportSolution: Set terminal type
# ~/.zshrc
export TERM=xterm-256color
export COLORTERM=truecolorSSH Breaks Prompt
Symptom: Prompt works locally but not over SSH
Check 1: TERM forwarding
ssh -t user@host 'echo $TERM'Solution 1: Set TERM on remote
# Remote ~/.zshrc
export TERM=xterm-256colorSolution 2: Configure SSH
# ~/.ssh/config
Host *
SetEnv TERM=xterm-256colortmux/screen Issues
Symptom: Prompt breaks in tmux
Solution 1: tmux term setting
# ~/.tmux.conf
set -g default-terminal "screen-256color"
set -ga terminal-overrides ",xterm-256color:Tc"Solution 2: Force shell
# ~/.tmux.conf
set -g default-shell /bin/zshRecovery Procedures
Reset to Default Prompt
Zsh without frameworks:
# Minimal .zshrc
PROMPT='%n@%m:%~%# 'With Oh My Zsh:
# In .zshrc
ZSH_THEME="robbyrussell"Complete P10k Reset
# Remove all P10k files
rm -rf ~/.p10k.zsh
rm -rf ~/.cache/p10k-*
rm -rf ~/.cache/gitstatus
# Reinstall
rm -rf ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/themes/powerlevel10k
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/themes/powerlevel10k
exec zshComplete Starship Reset
# Remove config
rm ~/.config/starship.toml
# Remove from shell
# Edit ~/.zshrc and remove: eval "$(starship init zsh)"
# Uninstall
brew uninstall starship
# or
rm $(which starship)
exec zshGetting Help
Powerlevel10k
- GitHub Issues: https://github.com/romkatv/powerlevel10k/issues
- Note: Maintainer no longer responding (project on life support)
- Search existing issues for solutions
Starship
- GitHub Discussions: https://github.com/starship/starship/discussions
- GitHub Issues: https://github.com/starship/starship/issues
- Discord: https://discord.gg/starship
Debug Information to Collect
# System info
uname -a
echo $SHELL
echo $ZSH_VERSION
echo $TERM
# P10k
cat ~/.p10k.zsh | head -50
ls -la ~/.cache/gitstatus/
# Starship
starship --version
cat ~/.config/starship.toml
starship timings
starship explainsoftmoth/zsh-vim-mode Reference
Comprehensive guide for the zsh-vim-mode plugin by softmoth.
Repository: https://github.com/softmoth/zsh-vim-mode
Requirements
- ZSH 5.3+ (full features)
- ZSH 5.0.8+ (text object support)
Installation
Manual
git clone https://github.com/softmoth/zsh-vim-mode.git ~/.zsh/zsh-vim-modeAdd to ~/.zshrc:
source ~/.zsh/zsh-vim-mode/zsh-vim-mode.plugin.zshWith Plugin Manager
Zinit:
zinit light softmoth/zsh-vim-modeAntigen:
antigen bundle softmoth/zsh-vim-modeZplug:
zplug "softmoth/zsh-vim-mode"Plugin Load Order
Critical: Load zsh-vim-mode LAST to avoid keybinding conflicts:
# Correct order
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source ~/.zsh/zsh-vim-mode/zsh-vim-mode.plugin.zsh # LASTConfiguration Variables
Core Settings
| Variable | Description | Default |
|---|---|---|
VIM_MODE_VICMD_KEY | Key to enter NORMAL mode | ^[ (Escape) |
VIM_MODE_NO_DEFAULT_BINDINGS | Disable built-in keybindings | unset |
VIM_MODE_TRACK_KEYMAP | Toggle mode-sensitive feedback | true |
VIM_MODE_INITIAL_KEYMAP | Starting mode | viins |
Initial keymap options:
viins- Start in INSERT mode (default)vicmd- Start in NORMAL modelast- Remember last mode across prompts
Cursor Styling
Define cursor appearance per mode:
# Format: "color style"
# Colors: named (green, red) or hex (#RRGGBB)
# Styles: steady, blinking, block, underline, bar
MODE_CURSOR_VIINS="#00ff00 blinking bar"
MODE_CURSOR_VICMD="green block"
MODE_CURSOR_REPLACE="red block"
MODE_CURSOR_SEARCH="#ff00ff steady underline"
MODE_CURSOR_VISUAL="$MODE_CURSOR_VICMD steady bar"
MODE_CURSOR_VLINE="$MODE_CURSOR_VISUAL #00ffff"Style values:
| Style | Description |
|---|---|
block | Full cursor block |
underline | Underscore cursor |
bar | Vertical line cursor |
steady | No blinking |
blinking | Blinking cursor |
Mode Indicators
Customize prompt indicators per mode:
# Uses zsh prompt expansion
MODE_INDICATOR_VIINS='%F{15}<%F{8}INSERT>%f'
MODE_INDICATOR_VICMD='%F{10}<%F{2}NORMAL>%f'
MODE_INDICATOR_REPLACE='%F{9}<%F{1}REPLACE>%f'
MODE_INDICATOR_SEARCH='%F{13}<%F{5}SEARCH>%f'
MODE_INDICATOR_VISUAL='%F{12}<%F{4}VISUAL>%f'
MODE_INDICATOR_VLINE='%F{12}<%F{4}V-LINE>%f'Auto-display: If RPS1/RPROMPT is unset, indicators display automatically.
Manual placement: Use ${MODE_INDICATOR_PROMPT} in your prompt when prompt_subst is enabled:
setopt prompt_subst
RPROMPT='${MODE_INDICATOR_PROMPT}'Key Features
Text Objects
Standard vim text objects work with operators (d, c, y, v):
| Text Object | Selects |
|---|---|
iw / aw | Inner/a word |
iW / aW | Inner/a WORD |
i" / a" | Inside/around double quotes |
i' / a' | Inside/around single quotes |
` i ` / a `` | Inside/around backticks |
i( / a( | Inside/around parentheses |
i[ / a[ | Inside/around brackets |
i{ / a{ | Inside/around braces |
i< / a< | Inside/around angle brackets |
Examples:
ci"- Change text inside double quotesda(- Delete text including parenthesesvi[- Visual select inside brackets
Surround Operations
Change, delete, or add surrounding characters:
| Command | Action |
|---|---|
cs"' | Change surrounding " to ' |
cs"( | Change " to ( |
ds( | Delete surrounding parentheses |
ysaw" | Surround a word with " |
Visual Mode
| Key | Action |
|---|---|
v | Character-wise visual |
V | Line-wise visual |
a" | Select around quotes |
i( | Select inside parens |
INSERT Mode Emacs Bindings
Emacs shortcuts available in INSERT mode:
| Key | Action |
|---|---|
Ctrl-A | Beginning of line |
Ctrl-E | End of line |
Ctrl-B | Back one character |
Ctrl-F | Forward one character |
Ctrl-K | Kill to end of line |
Ctrl-U | Kill to beginning of line |
Ctrl-W | Kill word backward |
Ctrl-R | Incremental history search |
KEYTIMEOUT Configuration
The KEYTIMEOUT affects escape key behavior:
# Default is 40 (400ms)
# Lower = faster mode switch, but may break multi-key sequences
export KEYTIMEOUT=20 # 200ms - reasonable compromiseIssues with low KEYTIMEOUT:
- Multi-key sequences (like
cs"') may not work - Arrow keys might not function in some terminals
Alternatives to reduce ESC delay:
1. Use Ctrl-[ instead of Escape (sends ESC immediately)
2. Remove double-ESC binding:
# In .zshrc before sourcing plugin
bindkey -M vicmd '\e' undefined-key3. Reassign NORMAL mode key:
VIM_MODE_VICMD_KEY='^X' # Use Ctrl-X instead4. Bind jk/jj to escape:
bindkey -M viins 'jk' vi-cmd-modeIntegration with Powerlevel10k
P10k has built-in vi mode support:
# In ~/.p10k.zsh
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(... vi_mode ...)
# Customize vi mode segment
typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING=''
typeset -g POWERLEVEL9K_VI_COMMAND_MODE_STRING='NORMAL'
typeset -g POWERLEVEL9K_VI_MODE_NORMAL_FOREGROUND=0
typeset -g POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=2When using P10k's vi_mode segment, you may want to disable zsh-vim-mode's indicator:
MODE_INDICATOR_VIINS=''
MODE_INDICATOR_VICMD=''
# ... etcTroubleshooting
Cursor Not Changing
1. Check terminal support: Not all terminals support cursor escape codes
- Works: iTerm2, Alacritty, Kitty, GNOME Terminal
- Limited: Apple Terminal, some SSH sessions
2. Verify variable is set:
echo $MODE_CURSOR_VICMD3. Test manually:
echo -ne '\e[2 q' # Should show block cursor
echo -ne '\e[6 q' # Should show beam cursorBindings Not Working
1. Check load order: Ensure zsh-vim-mode loads LAST
2. Verify plugin loaded:
which -a zle-keymap-select3. Check for conflicts:
bindkey -M vicmd | grep -E "cs|ds|ys"Mode Indicator Not Showing
1. Check RPROMPT:
echo $RPROMPT2. Force indicator:
setopt prompt_subst
RPROMPT='${MODE_INDICATOR_PROMPT}'Slow Mode Switching
1. Reduce KEYTIMEOUT:
export KEYTIMEOUT=102. Use Ctrl-[ instead of Escape
Complete Configuration Example
# ~/.zshrc
# Load plugin (after other plugins)
source ~/.zsh/zsh-vim-mode/zsh-vim-mode.plugin.zsh
# Key timeout
export KEYTIMEOUT=20
# Cursor styles
MODE_CURSOR_VIINS="green blinking bar"
MODE_CURSOR_VICMD="green block"
MODE_CURSOR_REPLACE="red blinking block"
MODE_CURSOR_SEARCH="yellow underline"
MODE_CURSOR_VISUAL="cyan block"
MODE_CURSOR_VLINE="magenta block"
# Mode indicators
MODE_INDICATOR_VIINS='%F{green}-- INSERT --%f'
MODE_INDICATOR_VICMD='%F{blue}-- NORMAL --%f'
MODE_INDICATOR_REPLACE='%F{red}-- REPLACE --%f'
MODE_INDICATOR_SEARCH='%F{yellow}-- SEARCH --%f'
MODE_INDICATOR_VISUAL='%F{cyan}-- VISUAL --%f'
MODE_INDICATOR_VLINE='%F{magenta}-- V-LINE --%f'
# Start in insert mode
VIM_MODE_INITIAL_KEYMAP=viins
# Alternative escape (optional)
bindkey -M viins 'jk' vi-cmd-modeExternal Resources
- GitHub: https://github.com/softmoth/zsh-vim-mode
- Oh My Zsh vi-mode: https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/vi-mode
- jeffreytse/zsh-vi-mode: https://github.com/jeffreytse/zsh-vi-mode
#!/usr/bin/env zsh
# benchmark-prompt.zsh - Shell prompt performance benchmark
# Usage: ./benchmark-prompt.zsh [iterations]
set -e
ITERATIONS=${1:-10}
BOLD='\033[1m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
NC='\033[0m'
echo "${BOLD}Shell Prompt Performance Benchmark${NC}"
echo "===================================="
echo ""
# Detect current prompt
detect_prompt() {
if [[ -n "$POWERLEVEL9K_MODE" ]] || [[ -f ~/.p10k.zsh ]]; then
echo "powerlevel10k"
elif command -v starship &>/dev/null && grep -q "starship" ~/.zshrc 2>/dev/null; then
echo "starship"
elif [[ -n "$ZSH_THEME" ]]; then
echo "omz:$ZSH_THEME"
else
echo "default"
fi
}
PROMPT_TYPE=$(detect_prompt)
echo "Detected prompt: ${BOLD}${PROMPT_TYPE}${NC}"
echo "Iterations: ${ITERATIONS}"
echo ""
# Shell startup time
echo "${BOLD}1. Shell Startup Time${NC}"
echo "---------------------"
startup_times=()
for i in $(seq 1 $ITERATIONS); do
start=$(date +%s%N)
zsh -i -c exit 2>/dev/null
end=$(date +%s%N)
duration=$(( (end - start) / 1000000 ))
startup_times+=($duration)
printf " Run %2d: %d ms\n" $i $duration
done
# Calculate average
total=0
for t in "${startup_times[@]}"; do
total=$((total + t))
done
avg=$((total / ITERATIONS))
if [[ $avg -lt 100 ]]; then
color=$GREEN
elif [[ $avg -lt 300 ]]; then
color=$YELLOW
else
color=$RED
fi
echo ""
echo " ${BOLD}Average: ${color}${avg} ms${NC}"
echo ""
# Per-command latency (if zsh-bench available)
if [[ -x ~/zsh-bench/zsh-bench ]]; then
echo "${BOLD}2. zsh-bench Results${NC}"
echo "--------------------"
~/zsh-bench/zsh-bench 2>/dev/null | grep -E "(first_prompt|command_lag|input_lag)"
echo ""
fi
# Starship-specific timing
if [[ "$PROMPT_TYPE" == "starship" ]] && command -v starship &>/dev/null; then
echo "${BOLD}2. Starship Module Timing${NC}"
echo "-------------------------"
starship timings 2>/dev/null | head -20
echo ""
fi
# Git performance (if in a repo)
if git rev-parse --git-dir &>/dev/null; then
echo "${BOLD}3. Git Status Performance${NC}"
echo "-------------------------"
# Native git status
start=$(date +%s%N)
git status --porcelain &>/dev/null
end=$(date +%s%N)
git_time=$(( (end - start) / 1000000 ))
echo " Native git status: ${git_time} ms"
# File count
file_count=$(git ls-files | wc -l | tr -d ' ')
echo " Tracked files: ${file_count}"
# Untracked count
untracked=$(git status --porcelain 2>/dev/null | grep '^??' | wc -l | tr -d ' ')
echo " Untracked files: ${untracked}"
if [[ $git_time -gt 100 ]]; then
echo ""
echo " ${YELLOW}Warning: Git operations are slow in this repo.${NC}"
echo " Consider disabling git_status in prompt config."
fi
echo ""
fi
# Recommendations
echo "${BOLD}4. Recommendations${NC}"
echo "------------------"
if [[ $avg -gt 300 ]]; then
echo " ${RED}! Startup is slow (>300ms)${NC}"
echo " - Enable instant prompt (P10k)"
echo " - Lazy load plugins"
echo " - Cache completions"
fi
if [[ "$PROMPT_TYPE" == "starship" ]]; then
echo " - Run 'starship timings' to identify slow modules"
echo " - Consider disabling git_status for large repos"
fi
if [[ "$PROMPT_TYPE" == "powerlevel10k" ]]; then
echo " - Verify instant prompt is enabled"
echo " - Check POWERLEVEL9K_VCS_MAX_INDEX_SIZE_DIRTY setting"
fi
echo ""
echo "${BOLD}Benchmark complete.${NC}"