@jmcombs/pi-headroom
v1.0.1
Published
Pi extension that compresses the whole conversation each LLM call via the local Headroom proxy, with graceful passthrough when it is unreachable.
Maintainers
Readme
@jmcombs/pi-headroom
Context-compression for the Pi coding agent. It compresses the whole conversation before each LLM call through a local Headroom proxy, lets the model recover any detail that lossy compression elided, and degrades to pure passthrough whenever the proxy is unreachable.
Long agent sessions accumulate bulky tool output — file dumps, logs, search
results — that stays in context turn after turn and quietly inflates token cost.
Headroom crushes the stale parts of the conversation while protecting the
recent turns, so the model keeps the context it is actively using and sheds the
weight it is not. Every elision is reversible: the model can call
headroom_retrieve to pull back the full original on demand.
Requirement: the Headroom Python proxy
The npm headroom-ai package is a thin HTTP client; the compression engine is a
local Python proxy that you run and manage yourself. This extension never
starts, stops, or installs it — it only health-checks it and reports its state.
Install the proxy once into a virtualenv:
python3 -m venv ~/.headroom-venv
~/.headroom-venv/bin/pip install "headroom-ai[proxy]"The
[proxy]extra pulls inonnxruntime+magika(no PyTorch).
Then run the proxy (default endpoint http://127.0.0.1:8787):
~/.headroom-venv/bin/headroom proxy --port 8787Confirm it is healthy:
curl -s http://127.0.0.1:8787/health # → {"status":"healthy","version":"0.27.0",...}If the proxy is not running, the extension stays fully usable: it emits a single non-fatal notice at session start and runs in passthrough mode (no compression, no added latency). See Graceful degradation.
Install
# Globally (recommended)
pi install npm:@jmcombs/pi-headroom
# For a single session, without installing
pi -e ./packages/headroomSee the Pi packages documentation for git, local path, project-scoped install, and filtering options.
What it adds
Commands
/headroom-status— a one-line snapshot: whether compression is enabled, whether the proxy is reachable (+ version), its mode and key tuning, and the session + lifetime tokens saved./headroom-authenticate— securely store a proxy API key (the input is captured by the TUI and never enters the LLM's context). Only needed if you front the proxy with authentication./headroom-stats— the detailed view: session savings, the proxy's lifetime tokens saved and compression percentage, request counts, the proxy's effective tuning, and a per-strategy breakdown (e.g. how much each ofsmartCrusher,search,kompresssaved). Read-only./headroom-simulate <text>— a dry-run projection. Paste a blob after the command and Headroom reports the projected token savings and the transforms that would fire — without any LLM call. The blob is evaluated as a stale tool result (the position compression actually targets), so the numbers reflect what compression would really do to that content.
Tool
headroom_retrieve— the model's safety net. Compression is lossy on the surface: a crushed tool result carries an inline marker… Retrieve more: hash=<hash>. The model callsheadroom_retrievewith that hash to recover the full original text (optionally filtered by aquery). This tool is always enabled — even when compression is turned off — so no elided detail is ever truly lost.
Flag
--headroom-no-compress— disable compression for the session. Retrieve stays enabled; only the compression pass is turned off.
Status display
When running in the TUI, a persistent above-editor widget shows Headroom's state at a glance and refreshes as the session progresses — so whether compression is enabled, whether the proxy is reachable, its mode, and session savings are "just known" without running a command. The display is read-only: it never changes any proxy setting.
- Active — compression is on and the proxy is reachable. The blocks are the
proxy version, its optimization mode (
tokenorcache, see Proxy settings), and the 💾 tokens saved this session. - Compression off — the session was started with
--headroom-no-compress. The proxy may still be up (green), butmode: off(red) means nothing is being compressed; the savings figure is dropped because there is nothing to measure. - Proxy offline — the proxy is unreachable, so the extension is in pure
passthrough. Only the red
proxy offlineblock is shown — with the proxy down there is no mode or savings to report.
Nerd Font required. The widget uses Powerline separators and a Nerd Font brand glyph. Your terminal must be using a Nerd Font (e.g. MesloLGS NF, FiraCode NF, JetBrainsMono NF) or the separators and icon will render as missing-glyph boxes. This affects display only — compression, retrieve, and all commands work regardless of the font.
How it works
On each LLM call, the extension's context hook converts Pi's message array to a
Headroom-recognized format, compresses the stale portion of the conversation
through the proxy, and swaps the compressed text back onto the original messages
in place — preserving every field and tool-call linkage. Recent turns are
protected, so the model never loses the context it is actively reasoning over.
Graceful degradation
The extension is built to never throw into the agent loop and never block it:
- A short-TTL cached health probe gates every compression pass. When the proxy is
down, the
contexthandler is a pure passthrough — no network call, no added latency — and the conversation is returned untouched. - Every compression call uses the SDK's
fallback: trueand is additionally wrapped in defensivetry/catch; any error returns the original conversation unchanged. - A single non-fatal warning at session start tells you the proxy is unreachable
so you know you are in passthrough mode. The check retries briefly (up to 3
attempts, 500 ms apart) to absorb the startup race where the proxy binds just
after Pi loads extensions; only if all attempts fail is the notice shown. Set
HEADROOM_DEBUG=1to log the underlying probe error to Pi's debug log.
Savings model
- Session savings are the in-memory total of tokens removed by this
extension's compression passes during the current session — free and realtime,
surfaced in the status display and
/headroom-stats. - Lifetime savings come from the proxy's own
proxyStats()(tokens saved, compression percentage, per-strategy breakdown) and reflect all traffic the proxy has compressed, not just this session.
Configuration
The base URL and optional API key are resolved independently.
Base URL (first match wins):
- An explicit argument passed to the client (used internally).
- The
HEADROOM_BASE_URLenvironment variable. - Default
http://127.0.0.1:8787.
API key (first match wins):
- An explicit argument passed to the client (used internally).
AuthStorage.getApiKey("headroom")(~/.pi/agent/auth.json).- The
HEADROOM_API_KEYenvironment variable. - Otherwise unset.
The key is read through the portable getApiKey() accessor (rather than a stored
credential object) so resolution works across Pi SDK variants, including oh-my-pi.
The base URL is not read from auth.json — set it via HEADROOM_BASE_URL or
rely on the default.
A local proxy typically needs no API key. Configure one only if you front the proxy with authentication.
Environment variables
export HEADROOM_BASE_URL="http://127.0.0.1:8787"
export HEADROOM_API_KEY="…" # only if your proxy requires it
export HEADROOM_DEBUG=1 # optional: log health-probe errors to Pi's debug logHEADROOM_DEBUG (any non-empty value) surfaces the underlying error whenever a
health probe fails — written to Pi's debug log, not the TUI. Leave it unset for
normal use: a down proxy is an expected, non-fatal state, so the extension stays
quiet apart from the single passthrough notice.
~/.pi/agent/auth.json
Used for the API key only (via getApiKey("headroom")); the base URL is not
read from here.
{
"headroom": {
"type": "api_key",
"key": "HEADROOM_API_KEY"
}
}Proxy settings are read-only
The proxy's optimization mode (token / cache) and tuning (target ratio,
recency protection, …) are server-launch settings — they are chosen when you
start the proxy, e.g.:
~/.headroom-venv/bin/headroom proxy --port 8787 --mode cacheThis extension only ever reads and reports those settings (via
/headroom-status and /headroom-stats); it never changes them, because that
would mean relaunching the proxy, which it does not manage. To change a setting,
restart the proxy yourself with the desired flags.
Requirements
- Pi
>= 0.1.0 - Node
>= 22.0.0 - A running Headroom Python proxy (see above).
- A Nerd Font in your terminal, for the status widget's Powerline separators and brand glyph (display only — see Status display).
Development
This package lives in the pi-extensions monorepo.
See CONTRIBUTING.md at the repo root for project conventions.
# From the repo root
npm ci
npm run check # full quality gate
npm run test -- packages/headroom # this package's smoke + unit testsTo try local changes against a real Pi session (start the proxy first):
pi -e ./packages/headroomThe committed test suite asserts registration shape and exercises the pure
formatting/conversion logic with no network. Real end-to-end behavior is
exercised against a running proxy via pi -e and the headless RPC driver in
docs/headroom/.
License
MIT © Jeremy Combs
