Starship
Starship is a fast, cross-shell prompt with over 55,000 GitHub stars. It ships with built-in modules for git, kubernetes, cloud providers, language environments, and more — but every one of those modules runs a fresh process on each prompt render. In a typical developer environment with git status, kubectl context, AWS profile, and a language version check all enabled, you are spawning five or more subprocesses before your prompt appears.
Beachcomber eliminates that overhead. Its comb g command reads from an in-memory cache maintained by a background daemon. The first call populates the cache; every subsequent call returns in microseconds. Starship's [custom.*] module system is a perfect fit: point the command and when fields at comb g, disable the conflicting built-in module, and your prompt becomes a cache read.
Prerequisites
- Beachcomber is installed. Verify the daemon is reachable with:
comb g load.one
If this prints a number, the daemon is up. The daemon is socket-activated — it starts on the first comb call and shuts down after an idle period. You do not need to launch it manually. If the command errors, confirm comb --version works and see the Debugging page.
- Starship is installed and active in your shell. Verify with:
starship --version
- The
combbinary is on yourPATHso starship can invoke it from a non-interactive shell context. Verify with:
which comb
How custom modules work
Starship's [custom.NAME] blocks define a module that runs an arbitrary shell command. Two fields matter here:
command— the shell command whose stdout becomes the module's displayed text.when— a shell command that must exit 0 and produce non-empty output for the module to appear. If thewhencommand returns empty output, starship hides the module entirely.
For beachcomber, both fields can use the same comb g invocation. When the daemon has no data for a key (daemon not running, provider not applicable to the current directory), comb g returns empty output. That naturally satisfies the when contract — if there is no data, the module disappears cleanly.
Where to put the config
Starship reads from ~/.config/starship.toml. Open that file and add the custom module blocks shown in the sections below. If the file does not exist yet, create it.
To disable a built-in starship module that conflicts with your custom one, add the corresponding section with disabled = true. For example, to replace the built-in git branch display:
[git_branch]
disabled = true
Testing that it works
After editing ~/.config/starship.toml, test any module directly from the terminal before opening a new shell:
comb g git.branch . # g = get, text is the default format
Expected output: the current branch name, e.g. main.
Then check that starship renders the module:
starship module custom.git_branch
If the module is configured correctly and comb g returns data, this prints the formatted module output. If it prints nothing, the when condition evaluated to empty — see the Troubleshooting section.
Git modules
Disable the built-in git modules and replace them with cache-backed equivalents:
[git_branch]
disabled = true
[git_status]
disabled = true
[custom.git_branch]
command = "comb g git.branch ."
when = "comb g git.branch ."
format = "[$output]($style) "
style = "bold blue"
description = "Git branch via beachcomber"
[custom.git_dirty]
command = 'test "$(comb g git.dirty .)" = "true" && echo "*"'
when = "comb g git.branch ."
format = "[$output]($style)"
style = "bold red"
description = "Git dirty indicator via beachcomber"
[custom.git_stash]
command = "comb g git.stash_count ."
when = "comb g git.stash_count ."
format = '[stash:$output]($style) '
style = "yellow"
description = "Git stash count via beachcomber"
The git_dirty module uses a small shell expression because the raw value is true or false — the test converts it to a displayable * character or suppresses output entirely.
Path-scoped providers (git, terraform, conda, mise, asdf) require the current directory to be passed as the second argument. The . shown above tells starship to pass $PWD at render time. Omitting it causes beachcomber to look up data with no path context, which returns empty for path-scoped providers.
System modules
These providers are global — no path argument is needed.
[custom.battery]
command = "comb g battery.percent"
when = "comb g battery.percent"
format = "[BAT $output%]($style) "
style = "bold yellow"
description = "Battery percentage via beachcomber"
[custom.load]
command = "comb g load.one"
when = "comb g load.one"
format = "[load $output]($style) "
style = "dimmed white"
description = "1-minute load average via beachcomber"
[custom.network]
command = "comb g network.ssid"
when = "comb g network.ssid"
format = "[$output]($style) "
style = "dimmed cyan"
description = "Wi-Fi SSID via beachcomber"
Kubernetes module
Replace starship's built-in kubernetes module, which calls kubectl on every prompt:
[kubernetes]
disabled = true
[custom.kube]
command = "comb g kubecontext.context"
when = "comb g kubecontext.context"
format = "[$output]($style) "
style = "bold cyan"
description = "Kubernetes context via beachcomber"
[custom.kube_namespace]
command = "comb g kubecontext.namespace"
when = "comb g kubecontext.namespace"
format = "[$output]($style) "
style = "cyan"
description = "Kubernetes namespace via beachcomber"
Cloud provider modules
[aws]
disabled = true
[custom.aws]
command = "comb g aws.profile"
when = "comb g aws.profile"
format = "[aws:$output]($style) "
style = "bold orange"
description = "AWS profile via beachcomber"
[gcloud]
disabled = true
[custom.gcloud]
command = "comb g gcloud.project"
when = "comb g gcloud.project"
format = "[gcp:$output]($style) "
style = "bold blue"
description = "GCloud project via beachcomber"
Environment and toolchain modules
These providers are path-scoped — pass . so beachcomber receives the current directory.
[conda]
disabled = true
[custom.conda]
command = "comb g conda.env ."
when = "comb g conda.env ."
format = "[conda:$output]($style) "
style = "bold green"
description = "Conda environment via beachcomber"
[terraform]
disabled = true
[custom.terraform]
command = "comb g terraform.workspace ."
when = "comb g terraform.workspace ."
format = "[tf:$output]($style) "
style = "bold purple"
description = "Terraform workspace via beachcomber"
Complete example
A realistic config combining several modules. Paste this into ~/.config/starship.toml and adjust styles to taste:
# Disable built-in modules replaced by beachcomber
[git_branch]
disabled = true
[git_status]
disabled = true
[kubernetes]
disabled = true
[aws]
disabled = true
[gcloud]
disabled = true
[conda]
disabled = true
[terraform]
disabled = true
# Beachcomber-backed modules
[custom.git_branch]
command = "comb g git.branch ."
when = "comb g git.branch ."
format = "on [$output]($style) "
style = "bold blue"
description = "Git branch via beachcomber"
[custom.git_dirty]
command = 'test "$(comb g git.dirty .)" = "true" && echo "*"'
when = "comb g git.branch ."
format = "[$output]($style)"
style = "bold red"
description = "Git dirty indicator via beachcomber"
[custom.kube]
command = "comb g kubecontext.context"
when = "comb g kubecontext.context"
format = "[kube:$output]($style) "
style = "bold cyan"
description = "Kubernetes context via beachcomber"
[custom.aws]
command = "comb g aws.profile"
when = "comb g aws.profile"
format = "[aws:$output]($style) "
style = "bold yellow"
description = "AWS profile via beachcomber"
[custom.gcloud]
command = "comb g gcloud.project"
when = "comb g gcloud.project"
format = "[gcp:$output]($style) "
style = "bold blue"
description = "GCloud project via beachcomber"
[custom.terraform]
command = "comb g terraform.workspace ."
when = "comb g terraform.workspace ."
format = "[tf:$output]($style) "
style = "bold purple"
description = "Terraform workspace via beachcomber"
[custom.conda]
command = "comb g conda.env ."
when = "comb g conda.env ."
format = "[conda:$output]($style) "
style = "bold green"
description = "Conda environment via beachcomber"
[custom.load]
command = "comb g load.one"
when = "comb g load.one"
format = "[load:$output]($style) "
style = "dimmed white"
description = "System load via beachcomber"
[custom.battery]
command = "comb g battery.percent"
when = "comb g battery.percent"
format = "[bat:$output%]($style) "
style = "bold yellow"
description = "Battery via beachcomber"
Expected output
With the complete config active, a prompt in a git repository checked out to a feature branch, connected to an AWS account, with a kubernetes context selected, looks something like:
~/projects/myapp on main * kube:prod-us-east-1 aws:engineering load:1.42
>
Modules that have no data for the current context are suppressed automatically. In a directory with no git repository, custom.git_branch and custom.git_dirty do not appear. On a machine with no kubeconfig, custom.kube is hidden. No configuration changes are needed — the when field handles it.
Troubleshooting
- Modules hidden when they should show: starship runs
commandandwhenin a non-interactive shell. Ifcombis only on your interactive shell's PATH, starship will not find it. See comb not found in non-interactive shells. - Module shows empty outside a repo: this is correct. Path-scoped providers return empty when the directory is not a relevant context. The
whenfield hides the module automatically. - Testing a module in isolation:
starship module custom.git_branchrenders just that module using your current config and directory.
See the Troubleshooting guide for general diagnostics.