// POWERLINERS — ENGINEERING REPORT

>_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

MetricValueNotes
Rust LOC (src/ported)~66,043137-file 1:1 mirror of upstream powerline/
Upstream py fn allowlist624docs/powerline_py_functions.txt (regen via scripts/regen_py_functions.sh)
Audit tests2allowlist_files_are_well_formed + every_ported_fn_name_exists_in_python_allowlist
Lib tests2,473port body + parity assertions across the ported surface; src/extensions/ covers cache-size segments, vcs, thermal, gpu, k8s, github_ci, aws/gcp context, etc.
Parity tests462byte/value identical between Rust port and live upstream Python interpreter
Port bugs fixed11surfaced by the parity harness — see git log for the full list
Tier progress134 / 137 DONE3 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 msvs ~100 ms upstream py-startup
Runtime deps0single static binary; no python, no glibc-only features
Current tagv0.2.18function-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

SubsystemModuleRole
Path utilitiessrc/ported/lib/path.rscross-platform os.path equivalents
Bindings — ipythonsrc/ported/bindings/ipython/4 version flavours: pre_0_11, post_0_11, since_5, since_7
Bindings — configsrc/ported/bindings/config.rsshared config loader
Daemon lifecyclesrc/ported/scripts/powerline_daemon.rs + src/bin/powerline-daemon.rsUNIX socket bind + daemonize + pidfile lock + accept loop
Parity harnesstests/parity_against_upstream.rs462 tests piping the same input through upstream Python and Rust
Audit harnesstests/ported_fn_names_match_py.rsenforces fn name parity with upstream py
Allowlistdocs/powerline_py_functions.txt624 upstream py fns (regenerable)
Exemptionstests/data/fake_fn_allowlist.txtmaintainer-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.

BinaryMirrorsRole
powerlineclient/powerline.cWire client — packs argv + cwd + env, sends over the per-UID Unix socket, copies the reply to stdout; execvps powerline-render on connect-fail.
powerline-daemonscripts/powerline-daemonSocket bind + daemonize + pidfile lock + accept loop + EOF\0\0 shutdown + render via render_runtime::render_once.
powerline-renderscripts/powerline-renderOne-shot direct render through the same orchestrator path (daemon-less fallback).
powerline-configscripts/powerline-configtmux / shell known-function dispatch + vim source-path plugin extraction.
powerline-lintscripts/powerline-lintargparse + 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.

% ENVIRONMENT

VariableEffect
POWERLINE_COMMANDCommand shell integrations invoke to render (set to powerline).
POWERLINE_CONFIG_PATHSColon-separated config-root search list; mirrors upstream order.
POWERLINE_CONFIG_OVERRIDESTheme-override key=value pairs per extension.
POWERLINERS_ICONSIcon tier: default Nerd Font / =unicode / =ascii (read once per process).
$XDG_CACHE_HOMEExtracted tmux conf + vim plugin root (powerliners/{tmux,vim}/).
$FUSEVM_JIT_CACHE · ${NAME}_RKYV_CACHE/_HOME · $XDG_DATA_HOMECache-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).

* 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

  1. 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 upstream powerline-status, end-to-end through the daemon socket. Target: <1 ms per render (vs ~100 ms python-interpreter startup tax). Publish results to docs/bench.html on each release tag.
  2. Parity-fixture expansion. Grow tests/parity_against_upstream.rs past 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.)