>_EXECUTIVE SUMMARY
powerliners is a structurally complete (134/137 upstream py files at DONE tier; the 3 holdouts are Python lipstick — zero-fn class shells whose constants the Rust port already carries) Rust port of Python's powerline-status. The target is a single static binary that drops into the same hook points (tmux statusline, zsh PS1, vim statusline, ipython prompt) with sub-millisecond render — replacing the ~100 ms python-interpreter startup tax that compounds across every render in interactive shells.
~ SCALE & POSITION
| Metric | Value | Notes |
|---|---|---|
| Rust LOC (src/ported) | ~66,043 | 137-file 1:1 mirror of upstream powerline/ |
| Upstream py fn allowlist | 624 | docs/powerline_py_functions.txt (regen via scripts/regen_py_functions.sh) |
| Audit tests | 2 | allowlist_files_are_well_formed + every_ported_fn_name_exists_in_python_allowlist |
| Lib tests | 2,473 | port body + parity assertions across the ported surface; src/extensions/ covers cache-size segments, vcs, thermal, gpu, k8s, github_ci, aws/gcp context, etc. |
| Parity tests | 462 | byte/value identical between Rust port and live upstream Python interpreter |
| Port bugs fixed | 11 | surfaced by the parity harness — see git log for the full list |
| Tier progress | 134 / 137 DONE | 3 holdouts are Python lipstick (readline.py / zsh.py = zero-fn class shells with escape-marker constants; powerline-i3.py = 100% ported, classifier just can't promote 0/0 → DONE) |
| Target render budget | < 1 ms | vs ~100 ms upstream py-startup |
| Runtime deps | 0 | single static binary; no python, no glibc-only features |
| Current tag | v0.2.18 | function-level port complete; orchestrator wired through render_runtime::render_once in both powerline-render and powerline-daemon; byte-identical with upstream Python across 45 daemon-parity + 462 unit-parity fixtures |
# SUBSYSTEM BREAKDOWN
| Subsystem | Module | Role |
|---|---|---|
| Path utilities | src/ported/lib/path.rs | cross-platform os.path equivalents |
| Bindings — ipython | src/ported/bindings/ipython/ | 4 version flavours: pre_0_11, post_0_11, since_5, since_7 |
| Bindings — config | src/ported/bindings/config.rs | shared config loader |
| Daemon lifecycle | src/ported/scripts/powerline_daemon.rs + src/bin/powerline-daemon.rs | UNIX socket bind + daemonize + pidfile lock + accept loop |
| Parity harness | tests/parity_against_upstream.rs | 462 tests piping the same input through upstream Python and Rust |
| Audit harness | tests/ported_fn_names_match_py.rs | enforces fn name parity with upstream py |
| Allowlist | docs/powerline_py_functions.txt | 624 upstream py fns (regenerable) |
| Exemptions | tests/data/fake_fn_allowlist.txt | maintainer-approved Rust-only fns |
$ BINARIES & CLI SURFACE
Five binaries ship from this crate — one hot-path client, four management / fallback tools. Each is a 1:1 port of an upstream scripts/ or client/ entry point.
| Binary | Mirrors | Role |
|---|---|---|
powerline | client/powerline.c | Wire client — packs argv + cwd + env, sends over the per-UID Unix socket, copies the reply to stdout; execvps powerline-render on connect-fail. |
powerline-daemon | scripts/powerline-daemon | Socket bind + daemonize + pidfile lock + accept loop + EOF\0\0 shutdown + render via render_runtime::render_once. |
powerline-render | scripts/powerline-render | One-shot direct render through the same orchestrator path (daemon-less fallback). |
powerline-config | scripts/powerline-config | tmux / shell known-function dispatch + vim source-path plugin extraction. |
powerline-lint | scripts/powerline-lint | argparse + markedjson loader + Spec checks pipeline. |
Render-request flags parsed by parse_client_argv: -w/--width, -r/--renderer-module, -c/--config-override, -t/--theme-override, -R/--renderer-arg, -p/--config-path, -m/--mode, --last-exit-code, --last-pipe-status, --jobnum, --socket. Daemon process flags (parse_daemon_argv): -q/--quiet, -f/--foreground, -s/--socket, -k/--kill, -r/--replace. Full per-flag reference + integration snippets live in the docs page.
= WIRE PROTOCOL
The client / daemon split is byte-compatible with upstream's client/powerline.c, so a Python-installed powerline binary talks to this daemon unchanged and vice-versa.
- Request frame.
hex(argc)\0 arg\0 arg\0 … cwd\0 KEY=VAL\0 …\0\0— argument count, NUL-separated argv, the current working directory, then the inherited environment, terminated by a double-NUL. - Shutdown sentinel.
EOF\0\0(const EOF: &[u8] = b"EOF\0\0",src/ported/scripts/powerline_daemon.rs) — on receipt the daemon exits 0. - Socket path.
/tmp/powerline-ipc-$UID(macOS / BSD filesystem socket) or abstract\0powerline-ipc-$UID(Linux). Pidfile lock at/tmp/powerline-ipc-$UID.pid. - Fallback. On connect-fail the client
execvpspowerline-renderwith the same argv — never a hard error if the daemon is down.
% ENVIRONMENT
| Variable | Effect |
|---|---|
POWERLINE_COMMAND | Command shell integrations invoke to render (set to powerline). |
POWERLINE_CONFIG_PATHS | Colon-separated config-root search list; mirrors upstream order. |
POWERLINE_CONFIG_OVERRIDES | Theme-override key=value pairs per extension. |
POWERLINERS_ICONS | Icon tier: default Nerd Font / =unicode / =ascii (read once per process). |
$XDG_CACHE_HOME | Extracted tmux conf + vim plugin root (powerliners/{tmux,vim}/). |
$FUSEVM_JIT_CACHE · ${NAME}_RKYV_CACHE/_HOME · $XDG_DATA_HOME | Cache-size segment override roots. |
+ ARCHITECTURE
End-to-end data flow from a shell / editor / multiplexer hook down to the rendered statusline bytes. Every layer below is wired and exercised by the lib + parity test suites; the only run-time variability is which segment modules a given theme.json references.
┌───────────────────────────────────────────────────────────────────┐
│ HOOK SURFACE │
│ tmux statusline │ zsh PROMPT │ bash PS1 │ vim &statusline │
│ ipython prompt │ i3bar │ wm / awesome │ shell continuation │
└─────────────────────────────────┬─────────────────────────────────┘
│ exec `powerline <ext> <side> -r k=v…`
▼
┌───────────────────────────────────────────────────────────────────┐
│ WIRE LAYER ─ src/bin/powerline.rs (thin C-style client) │
│ │
│ pack argv + cwd + env → `hex(argc)\0 a\0 b\0 … cwd\0 …\0\0` │
│ │
│ ├─ connect /tmp/powerline-ipc-$UID (macOS / BSD) │
│ ├─ connect \0powerline-ipc-$UID (Linux abstract) │
│ └─ on connect-fail → execvp("powerline-render", argv) │
└─────────────────────────────────┬─────────────────────────────────┘
│ unix socket request
▼
┌───────────────────────────────────────────────────────────────────┐
│ DAEMON main_loop ─ src/bin/powerline-daemon.rs │
│ │
│ accept() → parse_client_argv → Args { ext, side, … } │
│ │
│ Configs cache (keyed by ext: tmux / vim / shell / ipython) │
│ ├─ Theme tree + Colorscheme cascade │
│ ├─ Renderer state (TmuxRenderer | VimRenderer | …) │
│ └─ ADAPTERS dispatch table (built-in segments) │
│ │
│ render_runtime::render_once(args, environ, cwd, configs, R) │
└─────────────────────────────────┬─────────────────────────────────┘
│ segment fn calls
▼
┌───────────────────────────────────────────────────────────────────┐
│ SEGMENT LAYER │
│ │
│ src/extensions/ ─ net-new live-data segments │
│ ├─ gpu / thermal / disk / mem / proc / docker / k8s │
│ ├─ github_ci / aws_ctx / gcp_ctx / git_status │
│ └─ cache-size: fusevm_jit / {zshrs,stryke,awkrs}_rkyv │
│ │
│ src/ported/segments/ ─ 1:1 mirror of upstream │
│ ├─ common / shell / tmux / vim / i3 / ipython │
│ └─ plugins: nerdtree / syntastic / ale / coc / tagbar / … │
│ │
│ each returns Vec<{contents, highlight_groups, divider_*}> │
└─────────────────────────────────┬─────────────────────────────────┘
│ segment chunks
▼
┌───────────────────────────────────────────────────────────────────┐
│ RENDERER ─ src/ported/renderers/ │
│ │
│ TmuxRenderer → #[fg=#RRGGBB,bg=…] markup + hard/soft │
│ dividers, empty-side handling │
│ VimRenderer → :hi Pl_<cf>_<gf>_<cb>_<gb>_<a> … │
│ + %#Pl_…# inline references │
│ ShellRenderer → zsh / bash ANSI escape sequences │
│ IpyRenderer → IPython prompt markup │
└─────────────────────────────────┬─────────────────────────────────┘
│ bytes
▼
┌────────────────────────────────┐
│ stdout / socket reply │
│ (statusline / prompt body) │
└────────────────────────────────┘
Configs persist for the lifetime of the daemon process — bound at first request for a given ext, reused on every subsequent render. Theme + colorscheme JSON parses once; VimRenderer's (fg, bg, attrs) → hl_group cache compounds across renders so repeated :hi GroupName … declarations are emitted only on first encounter (subsequent vim renders ship just %#GroupName# references). The C-client / daemon split + execvp fallback are byte-compatible with upstream's client/powerline.c, so an existing Python-installed powerline binary talks to this daemon unchanged.
@ EXECUTION PIPELINE (target)
argv ───► CLI parse ───► segment renderer ───► encoded statusline
│ │ │
▼ ▼ ▼
config.json per-segment fn tmux/zsh/vim escape sequences
(powerline- (host context, time, (truecolor + box-drawing chars)
compatible) git, kube, …) on stdout
Render path is allocation-light: segments stream into a fixed-capacity output buffer, no intermediate Vec<Segment> when the configuration is static. Hot path uses zero-copy slicing over the config JSON arena.
! PORT DISCIPLINE
The two audit tests are load-bearing: removing or weakening them is treated as audit-tool tampering per the project's global rules (see tests/ported_fn_names_match_py.rs).
- Naming. Every
fndefined undersrc/ported/must have a name that exists indocs/powerline_py_functions.txt, intests/data/fake_fn_allowlist.txt, or in the small trait-impl exemption set (new,fmt,clone, …). - Layout. Directory structure mirrors upstream —
powerline/lib/path.py→src/ported/lib/path.rs,powerline/bindings/ipython/since_7.py→src/ported/bindings/ipython/since_7.rs. - Citation. Each ported fn carries a
// py:LINE-LINEcomment pointing back to the original Python source range, so reviewers can verify line-by-line.
* TESTS & PARITY
$ cargo test --locked --no-fail-fast test result: ok. 2436 passed; 0 failed # lib::tests test result: ok. 2 passed; 0 failed # tests/ported_fn_names_match_py.rs (drift gate) test result: ok. 462 passed; 0 failed # tests/parity_against_upstream.rs
The parity harness invokes the upstream Python interpreter (via the vendored powerline-status at vendor/powerline/) and compares its return values against the Rust port for the same inputs. 11 real port bugs were surfaced this way and fixed: ThreadedSegment.daemon class-attr override, Spec.did_type gating logic, encoding-locale env-var lookup, _clear_special_values use-after-free (BTreeMap rebalance invalidated saved raw pointers), Spec.ident regex (rejected colon-form identifiers like solarized:term), Spec.context_message child-recursion, Spec.tuple length bounds (lower bound silently dropped), Spec.unknown_msg arg-drop, Spec.unknown_spec dispatch-tuple loss, NON_PRINTABLE_RE regex-class inversion, and Spec.printable/unsigned chained constraints.
Beyond the port body, src/extensions/ ships net-new segments with dedicated module-local coverage. The cache-size family (fusevm_jit, zshrs_rkyv, stryke_rkyv, awkrs_rkyv) and the git_status / thermal segments extract pure-functional seams (default_path_with(get_env, path_exists), default_root_with(get_env), parse_porcelain_v2, render_git_chunk, format_thermal, thermal_gradient, parse_ioreg_centi_celsius) so the env-precedence chains, porcelain-v2 line semantics, p10k counter ordering, RPM-tail collapse, gradient clamps, and ioreg centi-°C parsing can be pinned by deterministic unit tests with no env-var mutation and no thread-safety hazard.
~ CRANELIFT JIT (future)
Out of scope for the initial port. powerline-status is render-bound, not compute-bound — Cranelift gives no win until segment computation surface includes user-extensible scripting. Re-evaluate after the static segment pipeline ships and benchmark numbers show where the actual hot loop is.
. NEXT MILESTONES
- Benchmark harness. Stand up
benches/with a Criterion target that renders the user's daily-driver tmux config 10,000× and reports wall-clock vs upstreampowerline-status, end-to-end through the daemon socket. Target: <1 ms per render (vs ~100 ms python-interpreter startup tax). Publish results todocs/bench.htmlon each release tag. - Parity-fixture expansion. Grow
tests/parity_against_upstream.rspast the current 462 tests toward one fixture per upstream Python source file with function bodies — backfill the segments and renderer-internals files that don't yet have dedicated byte-identical assertions. The 11 port bugs surfaced so far suggest the asymptote isn't reached.
(The earlier "orchestrator integration" / "default.json byte-identical comparison" milestones shipped in 0.2.x — powerline-render and powerline-daemon both run the full orchestrator chain via render_runtime::render_once, and tests/daemon_parity.rs already asserts byte-identical output between the Rust daemon and upstream python3 vendor/powerline/scripts/powerline-render across 45 fixtures.)