____ _____ _______ ____ _ ___ _ _ _____ ____ ____
| _ \ / _ \ \ / / ____| _ \| | |_ _| \ | | ____| _ \/ ___|
| |_) | | | \ \ /\ / /| _| | |_) | | | || \| | _| | |_) \___ \
| __/| |_| |\ V V / | |___| _ <| |___ | || |\ | |___| _ < ___) |
|_| \___/ \_/\_/ |_____|_| \_\_____|___|_| \_|_____|_| \_\____/
[SIGNAL // POWERLINE WITHOUT THE PYTHON IMPORT COST]
// jacking your prompt off the python interpreter — same segments, same theme grammar, native exec speed //
> SYSTEM OVERVIEW
powerliners is a Rust port of powerline-status — the canonical Python-driven statusline/prompt renderer used in tmux, zsh, bash, vim, ipython, and shell continuation lines. The Python implementation pays a ~50–150 ms interpreter-startup tax on every render (every prompt redraw, every tmux refresh). powerliners is a single static binary: zero-import, zero-GC, sub-millisecond render.
Drop-in compatible with the existing powerline/config JSON theme + segment files so users can keep their themes unchanged.
> WHY A PORT?
[x] python startup is the killer — ~100 ms per render on the default tmux+powerline setup
[x] tmux refreshes the statusline every interval, and per-window — startup cost compounds
[x] zsh's prompt redraws after every keystroke when `precmd` hooks fire
[x] a 100 ms latency tax on every keystroke-induced redraw turns interactive shells into slideshows
[x] rust gives us: a static binary, microsecond startup, zero runtime deps, cross-arch builds
[x] preserve the exact powerline theme grammar — users keep their .json themes verbatim
> TARGETS
[x] tmux statusline / continuation lines
[x] zsh prompt (PS1 / RPROMPT)
[x] bash prompt (PS1 / PROMPT_COMMAND)
[x] vim statusline
[x] ipython / python REPL prompt (via shell hook, not embedded)
> STATUS
[port progress] 134 / 137 upstream .py files at DONE tier (97.8%)
[remaining] 3 NEAR — class-only Python sources at classifier ceiling
[partial/sparse] 0 / 0 — no degraded files
[lib tests] 2097 passing, 0 failing, 0 ignored
[parity tests] 397 against live upstream Python — every assertion runs the
Python interpreter on the vendored powerline and compares
byte/value identical with the Rust port
[port bugs fixed] 11 surfaced by the parity harness and corrected in the
Rust port (see git log for the full list)
[drift gate] green — every ported fn name matches docs/powerline_py_functions.txt
[citation rule] every Rust body line annotated // py:NNN against the upstream source line
The port is structurally complete at the function level. Citation-density
tier classifier (scripts/gen_port_checklist.py) requires // py:NNN
citation density >= 0.5 plus a /// Port of <py_fn>() doccomment per
Python function for DONE classification. All upstream Python files with
function bodies are at DONE.
The 3 remaining NEAR files (renderers/shell/readline.py,
renderers/shell/zsh.py, bindings/i3/powerline-i3.py) are class-only
Python sources with py_methods == 0 — the classifier routes class-only
files through a NEAR-or-STUB-HEAVY branch (NEAR when
rs_port_doccomments >= py_classes), bypassing the citation-density check.
These files' Rust ports are complete and the classifier acknowledges them
as NEAR; promoting them to DONE would require a classifier amendment.
What's wired end-to-end
| Binary | Mirrors | What it does |
|---|---|---|
powerline |
vendor/powerline/client/powerline.c |
Native Rust client — forwards argv + cwd + env to the daemon over a Unix socket via the upstream wire format, falls back to powerline-render exec if the daemon is unreachable |
powerline-config |
scripts/powerline-config |
tmux / shell known-function dispatch |
powerline-lint |
scripts/powerline-lint |
argparse + full check pipeline (markedjson loader + Spec checks + orchestrator integration) |
powerline-render |
scripts/powerline-render |
argparse + ext lookup + full direct-render path through the Powerline orchestrator (used as daemon-less fallback) |
powerline-daemon |
scripts/powerline-daemon |
UNIX-socket bind + daemonize + pidfile lock + accept loop + EOF shutdown + end-to-end statusline rendering against a real ~/.config/powerline/themes/... JSON tree |
End-to-end render
powerline-daemon produces real #[fg=…,bg=…]… tmux markup from a
user's powerline config root via the wire format compatible with the
upstream Python powerline C client. The render path covers:
- Config cascade load (
_find_config_files+load_json_config+mergedicts) - Colorscheme alias chasing + cterm color resolution (
Colorscheme::get_highlighting) - Segment preparation via
gen_segment_getterreturning aTheme.segmentstable - Segment dispatch through
process_segment/process_segment_lister - Renderer loop (
do_render/_render_segments/_render_length) with hard/soft divider insertion and per-side outer padding - TmuxRenderer
#[…]markup emission withterm_truecolorcterm path
30 segment adapters wired in src/bin/shared/render_runtime.rs (shared
between powerline-daemon and powerline-render): battery, branch,
clementine, cmus, cpu_load_percent, cwd, date, dbus_player,
email_imap_alert, environment, external_ip, fuzzy_time,
hostname, internal_ip, itunes, jobnum, last_pipe_status,
last_status, mem_usage, mocp, mpd, network_load, rhythmbox,
spotify, stash, system_load, uptime, user, virtualenv,
weather.
Point it at a config root via POWERLINE_CONFIG_PATHS:
POWERLINE_CONFIG_PATHS=/.config/powerline
The Python powerline C client already installed via pip talks to it
unchanged — same argc\0arg\0arg\0cwd\0KEY=VAL\0...\0\0 wire format
and same EOF\0\0 shutdown sentinel.
Regenerate the per-file tier table from the live source via:
Regenerate the function-coverage report via:
> MIGRATION TUTORIAL
Drop-in replacement for the Python powerline-daemon. The C client
shipped with powerline-status (installed via pip install powerline-status) talks to our daemon unchanged — same wire format,
same EOF\0\0 shutdown, same socket path (/tmp/powerline-ipc-$UID
on macOS / BSD, abstract \0powerline-ipc-$UID on Linux).
Step 1: Install or build
Fastest path — Homebrew tap (auto-bumped by each release):
# installs powerline, powerline-daemon, powerline-config, powerline-render, powerline-lint
Or build from source (entire 5-binary suite):
Release binaries land at target/release/{powerline,powerline-daemon,powerline-config,powerline-render,powerline-lint}.
Step 2: Verify parity against your config
Before swapping anything, run the daemon against a copy of your real config root and confirm the rendered tmux markup matches what you currently see:
# Spawn our daemon on a throwaway socket
POWERLINE_CONFIG_PATHS=/.config/powerline \
&
# Render the right side via the wire protocol
# Compare against the Python upstream (powerline-status must be installed)
If the two outputs match byte-for-byte for your common segments,
proceed. If they don't, file an issue with the divergence — the
daemon_parity suite covers 45 byte-for-byte scenarios but real
configs hit combinations we haven't asserted on.
Step 3: Stop the Python daemon
Step 4: Replace the binary in $PATH
The simplest approach is symlinking the Rust binary into a directory
that comes before powerline-status's ~/.local/bin (or wherever
pip put it) in your $PATH:
# verify the new resolution
The Python C client at ~/.local/bin/powerline (or powerline-render
as fallback) does NOT need to be replaced — it speaks the same wire
protocol to whichever daemon is bound to the socket.
Step 5: Restart tmux
Your existing ~/.tmux.conf invocations work unchanged. The
canonical line:
run-shell -b "powerline-daemon -q &>/dev/null || exit 0"
now spawns the Rust binary. Kill and reattach tmux to confirm:
The status bar should look identical. The powerline-daemon process
in ps aux should now be a target/release/powerline-daemon invocation
rather than the Python shebang.
Step 6: Confirm
# expected: /usr/local/bin/powerline-daemon -q
# expected: lrwxr-xr-x ... -> .../target/release/powerline-daemon
Rollback
Re-resolve powerline-daemon to the Python script:
Everything is byte-compatible — no config edits, no .tmux.conf edits,
no shell-rc edits.
Known divergences from Python upstream
These are the only areas where output may differ. Each is documented under the test suite's "inherent divergence" notes:
- Live-data segments (
cpu_load_percent,network_load, ...) are sampled per-render via subprocess probes in our daemon; the Python upstream usespsutilwith a different sampling cadence. Numeric values may differ by a sampling-window's worth of data; the markup framing is identical. - Threaded segment caching: Python's
ThreadedSegmentpolls in a background thread and renders the last-known value; our daemon samples on-demand. Latency profile differs (we may block briefly when network/disk segments hit); output content matches. - psutil-only features: Python upstream errors loudly when
psutilis missing and skips affected segments. Our daemon resolves the same data via OS subprocess probes (top,vm_stat,netstat,pmset,uptime) and renders successfully. -m modepropagation: The Rust client argv parser doesn't yet route-m insertthrough to the renderer's mode parameter; without an explicit mode,mode_translationscolorscheme groups are inert (matching Python's behavior with no mode).
For everything else — markup, escaping (# → ##[], control chars
via translate_np), dividers (hard/soft/multi-char/empty/single-char),
colorscheme resolution (alias chains, fallback groups, gradients,
cterm/truecolor encoding with falsy-hex fallback), attrs (bold +
italics + underline bit-packed), outer_padding, spaces, left/right
side handling, empty sides, before/after wrapping, Unicode contents
— the byte stream is identical.
> LICENSE
MIT. Theme JSON files in powerline/config/themes/ remain under their upstream licenses.