powerline-go: A Compiled Prompt Renderer for Bash, Zsh and Fish
A beautiful and useful low-latency prompt for your shell, written in go
At a glance
- What is it?
- powerline-go is a Go binary that prints a Powerline-style prompt string from shell state passed in as flags. It suits users who want git status, virtualenv and job count in the prompt without running a Python interpreter on every command, and it costs you a shell hook plus a patched font.
- Who is it for?
- Adopt powerline-go if you already run Go 1.15 or newer, want the prompt rendered by a single binary rather than a Python process, and are willing to install a Powerline font for the default patched mode. Skip it if you need a right-side prompt in Bash, since the README states right prompt support is not available there, or if you cannot accept a GPL-3.0 dependency in a distributed product.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 35 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: prompt state that costs a process per keystroke
A shell prompt looks static but is rebuilt constantly. Every command you run ends with the shell re-evaluating PS1, and if that evaluation shells out to a scripting runtime, you pay interpreter startup on each cycle. powerline-go takes the opposite route: it is a compiled Go program that reads its inputs from command-line flags and writes a finished prompt string to stdout. The README describes it as a Powerline-like prompt for Bash, ZSH and Fish, ported to Go from banga's Powerline-Shell. The port is the point. The original is a Python script, and this version replaces that with a binary you install once. The audience is developers who spend the day in a repository and want branch state, dirty markers, virtualenv name and pending push or pull count visible without typing git status. The README also notes the prompt changes color when the last command exited with a failure code, which is the kind of signal that only works if it is free to render.
What the prompt actually renders, and where the data comes from
The binary does not inspect your shell. Your shell inspects itself and hands the results over as flags. In the Bash snippet the README gives, the hook calls powerline-go with -error $? and -jobs $(jobs -p | wc -l). The Zsh version passes -error $? and -jobs ${${(%):%j}:-0}. The Fish version passes -error $status and -jobs (count (jobs -p)). So the exit code and the background job count are captured by the shell and forwarded. Everything else, the current directory, the git or hg branch, the virtualenv, the rbenv or rvm Ruby version, the nix shell indicator, is discovered by the binary itself when it runs. The git segment is the most detailed part of the README: the branch name is shown and its background color changes when the branch is dirty; divergence from the remote is shown as a commit count next to an upward or downward arrow indicating whether a push or pull is pending. Git additionally gets single-character markers: a pencil for a modified but unstaged file, a check for a staged file, a sparkle for conflicts, a plus for untracked files, and a flag for a stash. Each marker carries a number when more than one file matches. The path is truncated with an ellipsis when you go deep, controlled by -cwd-max-depth, which defaults to 5.
Installing the binary and wiring the hook
The README states Go 1.15 or newer is required, and that precompiled binaries for x64 Linux and macOS are published in the releases tab. On other platforms the documented command is go install github.com/justjanne/powerline-go@latest, which places the binary in $GOPATH/bin unless you change $GOPATH or $GOBIN. The README warns that if you do change those, you must also change the path in the shell scripts. For Bash you define an _update_ps1 function that sets PS1 to the output of $GOPATH/bin/powerline-go -error $? -jobs $(jobs -p | wc -l), then append it to PROMPT_COMMAND, guarded by a check that $TERM is not linux and that the binary exists. For Zsh the equivalent is a powerline_precmd function plus an install_powerline_precmd helper that appends it to precmd_functions only if it is not already there. Fish redefines fish_prompt in ~/.config/fish/config.fish and evaluates the binary with -error $status -jobs (count (jobs -p)). PowerShell takes a different route: the README's profile snippet builds a System.Diagnostics.ProcessStartInfo, sets TERM to xterm-256color, forces UTF-8 stdout encoding, and runs the binary with -shell bare. The README explains that ProcessStartInfo is used because the environment variables powerline-go needs must be filled in explicitly. Colors are ANSI codes, and the README says you may need to set $TERM to xterm-256color. The default patched mode needs a Powerline font; compatible and flat modes avoid that requirement.
The font and terminal assumptions are not optional
The default rendering mode is patched, and the README is explicit that this requires a powerline font, either installed as a fallback or by patching the font your terminal uses. If you skip that step you get the prompt, but the separator glyphs will not render as intended. The README offers compatible and flat modes as alternatives, which is the honest way to handle it, but it means the first decision a new user makes is not about git markers, it is about typography. The TERM variable is the second assumption. The README says ANSI color codes should work everywhere nowadays but that you may need xterm-256color. The Bash and Zsh snippets both skip installation entirely when $TERM is linux, so on a bare Linux console the prompt silently does not appear. That is a deliberate guard, not a bug, but it is a guard that will confuse anyone who wonders why their .bashrc change had no effect.
Where powerline-go is the wrong choice
Bash users lose right prompt support. The README states this plainly: right prompt support is not available when using bash. If your workflow depends on a right-aligned segment, this project cannot give it to you in Bash, and no configuration flag changes that. The second constraint is nix. Under nix-shell --pure the README says powerline-go will not be accessible and your prompt will disappear. The documented workaround is a .bashrc snippet that checks $IN_NIX_SHELL for the value pure and aliases powerline-go to $HOME/.nix-profile/bin/powerline-go or /run/current-system/sw/bin/powerline-go, whichever is executable. The README hedges that this should re-enable the prompt in most cases, which is a fair description of a workaround rather than a fix. The third constraint is the error-clearing option. Both the Bash and Zsh snippets include a commented-out set "?" line, and the README warns it clears the error not only for powerline-go but for everything else you run in that shell. That is a real side effect on shell state, and the README tells you not to enable it unless you are sure.
The Python original and what the Go port changes
The README names the lineage directly: this is based on Powerline-Shell by @banga, ported to golang by @justjanne. The two projects render the same kind of prompt, git branch with dirty state, path truncation, virtualenv, Ruby version. The difference is the runtime. Powerline-Shell is a Python script, so the prompt depends on a Python interpreter being present and starting fast enough that you do not notice it between commands. powerline-go is a single compiled binary with no interpreter in the loop, which is the reason to prefer it on a machine where you care about prompt latency. The trade-off is distribution. A Python script can be dropped into a dotfiles repository and run anywhere Python exists; a Go binary has to be built per platform or downloaded from the releases tab, which the README only provides for x64 Linux and macOS. If your environment is a mix of architectures, go install is the documented fallback and it requires a Go toolchain on each machine.
Licence, maintenance and the cost of staying current
powerline-go is GPL-3.0. For a personal shell prompt that is unremarkable. If you embed the binary in a product you distribute, the licence terms apply to that distribution, and this is a question for your own legal review rather than something to settle from a README. On maintenance, the release history shows v1.24 in May 2023, v1.25 in November 2024, and v1.26 in January 2026, with the repository last pushed in August 2026. That is a slow cadence, roughly one release a year, which fits a tool whose job is to print a string. Upgrades are low-risk in the sense that the interface is a set of command-line flags; the README's own usage block lists them, including -cwd-mode with valid choices fancy, semifancy, plain and dironly, -cwd-max-dir-size, -condensed, -colorize-hostname, -alternate-ssh-icon and -duration. Changing any of those means editing the command in your shell init file, not migrating data. The cost is that there is no config file to version separately, so your prompt configuration lives inside .bashrc or .zshrc alongside everything else, and a flag rename in a future release would surface as a broken prompt rather than an error message.
Editorial conclusion
Adopt powerline-go if you already run Go 1.15 or newer, want the prompt rendered by a single binary rather than a Python process, and are willing to install a Powerline font for the default patched mode. Skip it if you need a right-side prompt in Bash, since the README states right prompt support is not available there, or if you cannot accept a GPL-3.0 dependency in a distributed product. Before committing, verify three things on your own machine: that your terminal reports xterm-256color, that $GOPATH/bin/powerline-go is on the path your shell hook references, and that the -error and -jobs flags you pass actually reflect the values your shell exposes.
Community notes