Skip to the content.

Headroom Proxy — Installation & Systemd Setup

Install the Headroom context-optimization proxy and run it as a systemd user-scope service, chained to a local LiteLLM proxy for upstream LLM access.

Traffic Chain

Any OpenAI-compatible client → Headroom Proxy (:8787) → LiteLLM (:4000) → Vertex AI (Claude)
                                 ↑ context compression        ↑ model routing

Headroom exposes OpenAI-compatible endpoints (/v1/chat/completions) and Anthropic-compatible endpoints (/v1/messages), so any client that speaks either protocol can use it.

Prerequisites


Workflow

Step 1 — Install Headroom

Install Headroom using uv:

uv tool install 'headroom-ai[proxy]'

Verify:

headroom --version
headroom proxy --help

If uv is not installed:

curl -LsSf https://astral.sh/uv/install.sh | sh

Step 2 — Create the Headroom Systemd Service

File: ~/.config/systemd/user/headroom-proxy.service

[Unit]
Description=Headroom Proxy - Context optimization layer for LLM traffic
After=litellm-proxy.service
Wants=litellm-proxy.service

[Service]
Type=simple
ExecStart=/home/<USER>/.local/bin/headroom proxy \
  --host 127.0.0.1 \
  --port 8787 \
  --openai-api-url http://localhost:4000 \
  --no-ccr-inject-tool \
  --no-ccr-marker \
  --no-telemetry \
  --no-rate-limit \
  --request-timeout-seconds 600 \
  --mode token \
  --target-ratio 0.5 \
  --intercept-tool-results
Restart=on-failure
RestartSec=5
Environment=OPENAI_TARGET_API_URL=http://localhost:4000
Environment=HEADROOM_TELEMETRY=off

[Install]
WantedBy=default.target

Replace <USER> with your username.

Key Service Flags Explained

Flag Purpose
--openai-api-url http://localhost:4000 Route upstream traffic to LiteLLM
--no-ccr-inject-tool Don’t inject CCR retrieve tool (downstream clients can’t resolve it)
--no-ccr-marker Don’t add CCR markers to compressed content
--no-telemetry Disable anonymous telemetry
--no-rate-limit Disable rate limiting (local use)
--mode token Prioritize token compression savings
--target-ratio 0.5 Kompress compression target — keep ~50% of tokens in compressed turns (lower = more aggressive)
--intercept-tool-results Compress stale tool result blocks (file reads, shell output, etc.)
--request-timeout-seconds 600 10-minute timeout for long-running requests

Compression Tuning

The --target-ratio controls how aggressively Kompress ML compresses older conversation turns:

Value Behavior Risk
0.3 Aggressive — keep ~30%, remove ~70% Model may miss details from older turns
0.5 Balanced — keep ~50%, remove ~50% Good default for most workloads
0.7 Conservative — keep ~70%, remove ~30% Minimal information loss, modest savings
unset Kompress decides autonomously Very conservative, often skips compression

Only older conversation turns are compressed — the most recent messages always retain full fidelity.

Flags NOT to Use

Flag Why to avoid
--lossless Restricts to format-native lossless compaction only — blocks Kompress ML compression, resulting in near-zero savings through OpenAI-compatible endpoints
--memory Injects memory_save/memory_search tools that downstream clients (e.g., Goose) don’t understand; duplicates agent-side memory systems
--learn Writes MEMORY.md/AGENTS.md to CWD which conflicts with agent-managed files; headroom learn CLI only supports Claude Code/Codex/Gemini, not Goose

Step 3 — Enable and Start the Service

systemctl --user daemon-reload
systemctl --user enable headroom-proxy
systemctl --user start headroom-proxy

Step 4 — Verify the Service

systemctl --user status headroom-proxy

Confirm it shows active (running).

Step 5 — Verify Health Endpoint

curl -s http://127.0.0.1:8787/health | python3 -m json.tool

Confirm status is healthy and ready is true. Check that:

Step 6 — Test the Full Chain

Test end-to-end through Headroom → LiteLLM → Vertex AI:

curl -s -X POST http://localhost:8787/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer sk-EXAMPLE-not-real' \
  -d '{
    "model": "claude-sonnet-4-6",
    "messages": [{"role": "user", "content": "Say hello in one word."}],
    "max_tokens": 50
  }'

You should get a valid chat completion response with a choices array.

Step 7 — Check Compression Stats

curl -s http://127.0.0.1:8787/stats | python3 -m json.tool

Key fields to verify:

Compression kicks in on longer conversations once older turns exceed the min_tokens_to_crush threshold (default 500 tokens). Short conversations will show zero compression — this is expected.


Headroom API Endpoints

The Headroom proxy exposes these endpoints:

Endpoint Method Description
/v1/chat/completions POST OpenAI-compatible chat completions
/v1/messages POST Anthropic-compatible messages
/v1/compress POST Compression-only (no LLM call)
/health GET Service health and configuration
/stats GET Compression statistics
/stats-history GET Durable compression history
/metrics GET Prometheus-format metrics
/livez GET Process liveness
/readyz GET Traffic readiness

Using Headroom with Any Client

Point any OpenAI-compatible or Anthropic-compatible client at the proxy:

# OpenAI-compatible clients
OPENAI_BASE_URL=http://localhost:8787/v1 your-app

# Anthropic-compatible clients (e.g. Claude Code)
ANTHROPIC_BASE_URL=http://localhost:8787 claude

For Goose specifically, see the goose-headroom-provider skill.


Service Management

# Status
systemctl --user status headroom-proxy

# Start / Stop / Restart
systemctl --user start headroom-proxy
systemctl --user stop headroom-proxy
systemctl --user restart headroom-proxy

# Live logs
journalctl --user -u headroom-proxy -f

# Disable auto-start
systemctl --user disable headroom-proxy

Verification Checklist

Troubleshooting

Symptom Cause Fix
headroom: command not found Not installed uv tool install 'headroom-ai[proxy]'
Service fails to start Wrong ExecStart path Verify which headroom and update service file
“Connection refused” on :8787 Service not running systemctl --user start headroom-proxy
Health shows unhealthy upstream LiteLLM not running systemctl --user start litellm-proxy
--openai-api-url not taking effect Also set via env var Check OPENAI_TARGET_API_URL in service file
High memory usage Expected (~300–750 MB) Normal for Headroom with Kompress compression models loaded
CCR tool errors from downstream clients CCR injection enabled Add --no-ccr-inject-tool --no-ccr-marker flags
Timeout on long requests Default timeout too short Increase --request-timeout-seconds
0% compression after many requests --lossless flag set Remove --lossless; ensure --target-ratio is set (e.g. 0.5)
0% compression on short conversations Normal — too few old turns Compression triggers once older turns exceed min_tokens_to_crush (500)
All requests show no_compressible_content Content is protected user messages Remove --lossless; add --target-ratio to enable ML compression

Changelog

See CHANGELOG.md for version history.