---
sidebar_position: 4
---
# Powerlevel10k
## Introduction
powerlevel10k (p10k) is one of the fastest zsh themes. It uses gitstatus — a purpose-built C++ daemon — for git information, tightly integrated into its async rendering pipeline. beachcomber can replace gitstatus as the git data source, consolidating all shell state queries into a single daemon instead of running two.
beachcomber also provides cached data for things p10k does not cover natively, such as mise project tool versions.
There are two levels of integration:
- **Complementary segments** — add beachcomber-backed segments alongside p10k's built-in ones
- **Full git replacement** — replace gitstatus entirely with a beachcomber-backed segment
## Prerequisites
- beachcomber installed and the daemon running (`comb s` should succeed)
- powerlevel10k installed and configured (`p10k configure` has been run at least once)
- `~/.p10k.zsh` exists (generated by the configuration wizard)
## The durability problem
`~/.p10k.zsh` is regenerated when you run `p10k configure`. Any edits to that file will be overwritten. beachcomber integration must survive regeneration.
The solution is an **overlay file** — a separate zsh script sourced immediately after `~/.p10k.zsh`. It patches the prompt element arrays and defines custom segment functions. When `p10k configure` regenerates `~/.p10k.zsh`, the overlay re-applies its changes on next shell startup. The generated file is never modified.
### Setting up the overlay
Create `~/.config/zsh/beachcomber-p10k.zsh` (or any path you prefer) and source it in your `.zshrc` immediately after the p10k config:
```zsh
# .zshrc
source ~/.p10k.zsh
source ~/.config/zsh/beachcomber-p10k.zsh
```
All beachcomber segment definitions and array patches go in the overlay file. The rest of this guide shows what to put in it.
## Complementary segments
These segments add data that p10k does not provide natively. They work alongside p10k's built-in segments without replacing anything.
### Kubernetes context
```zsh
# comb g returns plain text by default. g = get, no suffix needed.
function prompt_bc_kube() {
local ctx=$(comb g kubecontext.context 2>/dev/null)
[[ -n "$ctx" ]] || return
p10k segment -f cyan -i '☸' -t "$ctx"
}
```
### AWS profile
```zsh
function prompt_bc_aws() {
local profile=$(comb g aws.profile 2>/dev/null)
[[ -n "$profile" ]] || return
p10k segment -f yellow -t "$profile"
}
```
The beachcomber AWS provider detects profiles from both `$AWS_PROFILE` (native CLI, granted) and `$AWS_VAULT` (aws-vault), with session expiration tracking via `$AWS_CREDENTIAL_EXPIRATION`.
### GCloud project
```zsh
function prompt_bc_gcloud() {
local project=$(comb g gcloud.project 2>/dev/null)
[[ -n "$project" ]] || return
p10k segment -f blue -t "$project"
}
```
### mise project tools
Shows tool versions that are overridden at the project level (from a local `mise.toml`), distinguishing them from the global baseline. Only appears in directories with a project-level mise config.
```zsh
typeset -g POWERLEVEL9K_COMB_MISE_FOREGROUND=147
typeset -g POWERLEVEL9K_COMB_MISE_VISUAL_IDENTIFIER_EXPANSION=$'\uF07C' # folder-open icon
function prompt_comb_mise() {
local cwd=${(%):-%/}
local project
local display=()
local entry tool ver
for entry in "${(@s:,:)project}"; do
[[ -z "$entry" ]] && continue
tool=${entry%%=*}
ver=${entry#*=}
display+=("${tool} ${ver}")
done
p10k segment -f 147 -i $'\uF07C' -t "${(j: | :)display}"
}
```
The beachcomber mise provider exposes three fields:
- `mise.project` — only tools sourced from a local `mise.toml` (project-scoped overrides)
- `mise.global` — only tools sourced from `~/.config/mise/` (the global baseline)
- `mise.tools` — all tools combined with `P:` and `G:` prefixes
### Adding complementary segments to the prompt
After defining the functions, patch the elements array in the overlay. This example inserts `comb_mise` before the `time` segment:
```zsh
typeset -ga _comb_rpe=()
for _comb_e in "${POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS[@]}"; do
[[ "$_comb_e" == "time" ]] && _comb_rpe+=(comb_mise)
_comb_rpe+=("$_comb_e")
done
POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=("${_comb_rpe[@]}")
unset _comb_rpe _comb_e
```
For simpler cases, append to the end:
```zsh
POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS+=(bc_kube bc_aws bc_gcloud)
```
## Full git replacement
This replaces p10k's gitstatus-backed `vcs` segment with a custom `comb_git` segment that reads all git state from beachcomber. When `vcs` is removed from the elements array, p10k does not start the gitstatus daemon — eliminating one long-running process from your system.
### Why replace gitstatus?
gitstatus is already fast. The motivation is architectural, not performance:
- **One daemon instead of two.** gitstatus runs one C++ daemon per shell session. beachcomber runs one daemon shared across all shells, tmux panes, and other consumers. Fewer processes, less memory, shared cache.
- **Consistent data.** The same git state that feeds your prompt also feeds your tmux status bar, neovim statusline, and any other beachcomber consumer. No divergence between tools.
- **Broader coverage.** beachcomber's git provider includes fields that gitstatus does not expose, such as line-level diff stats (`lines_added`, `lines_removed`), stash counts, and the current tag.
### Current limitations
beachcomber's git provider now exposes `commit_summary` (the first line of the HEAD commit message) and `push_ahead`/`push_behind` (commits ahead of or behind the push remote). The `comb_git` segment above can be extended to use these fields. WIP detection and push indicator rendering require wiring them into the segment function — see the field table in [Built-in Providers](../reference/built-in-providers.md) for the field names.
### The comb_git segment
Add this to your overlay file:
```zsh
# Swap vcs for comb_git in the left prompt elements.
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(${POWERLEVEL9K_LEFT_PROMPT_ELEMENTS[@]/vcs/comb_git})
# Colours matching the default vcs segment config
typeset -g POWERLEVEL9K_COMB_GIT_CLEAN_FOREGROUND=76
typeset -g POWERLEVEL9K_COMB_GIT_MODIFIED_FOREGROUND=178
typeset -g POWERLEVEL9K_COMB_GIT_UNTRACKED_FOREGROUND=76
typeset -g POWERLEVEL9K_COMB_GIT_VISUAL_IDENTIFIER_EXPANSION=
typeset -g POWERLEVEL9K_COMB_GIT_LOADING_VISUAL_IDENTIFIER_COLOR=244
function prompt_comb_git() {
local cwd=${(%):-%/}
local output
# Parse key=value lines into an associative array
local -A g
local line
for line in ${(f)output}; do
local key=${line%%=*}
local val=${line#*=}
g[$key]=$val
done
[[ -z ${g[branch]} ]] && [[ -z ${g[commit]} ]] && return
# Determine state for foreground colour
local state=CLEAN
elif (( ${g[untracked]:-0} )); then
state=UNTRACKED
fi
# Build display string matching p10k's default git formatting
local meta='%f'
local clean='%76F'
local modified='%178F'
local untracked='%39F'
local conflicted='%196F'
local res
# Branch name (truncate if > 32 chars)
if [[ -n ${g[branch]} ]]; then
local branch=${g[branch]}
(( $#branch > 32 )) && branch="${branch[1,12]}…${branch[-12,-1]}"
res+="${clean}${branch//\%/%%}"
elif [[ -n ${g[tag]} && ${g[tag]} != "null" ]]; then
local tag=${g[tag]}
(( $#tag > 32 )) && tag="${tag[1,12]}…${tag[-12,-1]}"
res+="${meta}#${clean}${tag//\%/%%}"
elif [[ -n ${g[commit]} ]]; then
res+="${meta}@${clean}${g[commit][1,8]}"
fi
# Upstream tracking branch (only if different from local)
if [[ -n ${g[upstream]} && ${g[upstream]} != "null" ]]; then
local remote_branch=${g[upstream]#*/}
if [[ -n ${remote_branch} && ${remote_branch} != ${g[branch]} ]]; then
res+="${meta}:${clean}${remote_branch//\%/%%}"
fi
fi
# Ahead/behind
(( ${g[ahead]:-0} && !${g[behind]:-0} )) && res+=" "
(( ${g[ahead]:-0} )) && res+="${clean}⇡${g[ahead]}"
fi
# Stashes
(( ${g[stash]:-0} )) && res+=" ${clean}*${g[stash]}"
# Merge/rebase state
[[ ${g[state]} != "clean" && -n ${g[state]} ]] && res+=" ${conflicted}${g[state]}"
# Conflicted
(( ${g[conflicted]:-0} )) && res+=" ${conflicted}~${g[conflicted]}"
# Staged
(( ${g[staged]:-0} )) && res+=" ${modified}+${g[staged]}"
# Unstaged
(( ${g[unstaged]:-0} )) && res+=" ${modified}!${g[unstaged]}"
# Untracked
(( ${g[untracked]:-0} )) && res+=" ${untracked}?${g[untracked]}"
p10k segment -s $state -t "$res"
}
```
The element substitution `${POWERLEVEL9K_LEFT_PROMPT_ELEMENTS[@]/vcs/comb_git}` replaces `vcs` with `comb_git` in whatever array `~/.p10k.zsh` defined. If `p10k configure` regenerates the file with `vcs` back in the array, the overlay swaps it out again on next shell startup.
### Verifying gitstatus is not running
After opening a new shell with the overlay active, confirm gitstatus is stopped:
```sh
pgrep -P $$ gitstatusd
```
This should return nothing. If it returns a PID, the `vcs` segment is still in the elements array — check that the overlay is being sourced after `~/.p10k.zsh`.
### First-prompt cache miss
On the very first prompt after the daemon starts (or after switching to a new directory that has not been queried before), the git provider executes inline. The `comb g` call blocks briefly while the provider runs and returns the result directly — the segment will have data on that first prompt, with a short delay while git runs. Subsequent prompts return the cached value with no delay.
Once the provider has run for a given directory, the cache is kept warm by ongoing demand from prompt queries.
## Customizing colours
All beachcomber segments follow p10k's standard colour configuration. For a segment named `comb_git`, set:
```zsh
typeset -g POWERLEVEL9K_COMB_GIT_FOREGROUND=76
typeset -g POWERLEVEL9K_COMB_GIT_CLEAN_FOREGROUND=76
typeset -g POWERLEVEL9K_COMB_GIT_MODIFIED_FOREGROUND=178
```
The `-s $state` argument in `p10k segment` selects which colour variant to use. States map to the `_CLEAN_`, `_MODIFIED_`, and `_UNTRACKED_` colour keys.
## Reverting
To revert all beachcomber integration:
1. Comment out or delete the `source` line for the overlay in `.zshrc`
2. Restart zsh
The `~/.p10k.zsh` file was never modified. The `vcs` segment will reappear and gitstatus will start again automatically.
To revert just the git replacement while keeping other segments, remove the `POWERLEVEL9K_LEFT_PROMPT_ELEMENTS` substitution line from the overlay. The `vcs` segment from `~/.p10k.zsh` will take effect again.
## Troubleshooting
- **Segment not showing:** verify the function name exactly matches `prompt_<segment_name>` and the segment name is in the `PROMPT_ELEMENTS` array. Run `echo $POWERLEVEL9K_LEFT_PROMPT_ELEMENTS` to check. A typo in either causes p10k to silently skip it.
- **Git segment slow on first prompt:** on a cold cache the provider executes inline, which takes as long as a normal `git` invocation (typically a few milliseconds). This is a one-time cost per directory.
- **Overlay not taking effect:** ensure the `source` line comes after the `~/.p10k.zsh` source in `.zshrc`. The overlay must run second to patch the arrays.
- **gitstatus still running:** check `pgrep -P $$ gitstatusd`. If it returns a PID, `vcs` is still in the elements array. The overlay may not be loaded — check `type prompt_comb_git` to see if the function exists.
- **Icons not rendering:** the Nerd Font glyphs require a patched font. p10k's recommended fonts include all required glyphs. Replace icons with text labels if your font lacks them.
- **Changes lost after `p10k configure`:** this is expected — `p10k configure` regenerates `~/.p10k.zsh`. The overlay re-applies changes on next shell startup. Just open a new shell.
See the [Troubleshooting](./troubleshooting.md) guide for general diagnostics.