headroom/wiki/quickstart.md
Tejas Chopra bd76235f5c
fix(cli): harden all CLI surfaces + fix docs accuracy (#1491)
## Summary

Full CLI audit + documentation accuracy pass. All 5 commits on this
branch:

### CLI Hardening (4 commits)
- **Clean errors instead of tracebacks**: corrupt manifests, missing
Docker, malformed JSONL, bad `--profile`, invalid env-var values all now
raise `click.ClickException` with helpful messages
- **Range validation**: ~25 numeric flags across 10 files now use
`click.IntRange`/`FloatRange` — `--port 0`, `--hours -1`, `--limit 0`
etc. produce clean usage errors instead of silent wrong behavior
- **Flag combination warnings**: conflicting combos (`--no-rate-limit` +
`--rpm`, `--no-optimize` + `--target-ratio`, `--telemetry` +
`--no-telemetry`) emit yellow warnings on stderr
- **`memory --db-path` default fixed**: was resolving to
`headroom_memory.db` (wrong bare file); now uses project store
`./.headroom/memory.db` if present, else `~/.headroom/memory.db`
- **`memory list --search` + filters**: `--scope`/`--session`/`--since`
were silently ignored when `--search` was also set; now filters are
applied to search results
- **`learn --verbosity --apply` now works**: the output shaper is off by
default (`HEADROOM_OUTPUT_SHAPER`); `--apply` now hot-enables it via
`POST /admin/runtime-env` on a running proxy, or prints explicit `export
HEADROOM_OUTPUT_SHAPER=1` instructions when no proxy is running
- **`perf --hours` overflow**: `1e9` hours no longer raises
`OverflowError`; treated as "all data"
- **`evals memory --categories` invalid input**: `abc,1,2` now raises
`BadParameter` instead of a raw `ValueError` traceback

### Documentation (1 commit, 20 files)

Corrected factual errors found by 3 parallel audit agents across root
docs, wiki, and the published Fumadocs site:

**Critical (caused runtime errors or wrong behavior if followed):**
- `simulation.mdx`: `plan.transforms_applied` -> `plan.transforms`;
`plan.savings_percent` -> computed from available fields (both raised
`AttributeError`)
- `shared-context.mdx`: `import { SharedContext } from "headroom"` ->
`"headroom-ai"` (5x `ImportError`)
- `claude-code-azure-foundry.mdx`: `pip install headroom` -> `pip
install headroom-ai`
- `api-reference.mdx` + `configuration.mdx`: `from headroom import
GoogleProvider` -> `from headroom.providers import GoogleProvider`
- `ccr.mdx`: CCR TTL default 300s -> 1800s (30 min)

**Fabricated flags removed:**
- `wiki/proxy.md` + `wiki/cli.md`: `--no-intelligent-context`,
`--no-intelligent-scoring`, `--no-compress-first` (none exist); replaced
with real CCR flags
- `wiki/configuration.md`: `--no-ccr-responses`, `--no-ccr-expansion`
(none exist); replaced with real flags
- `wiki/troubleshooting.md`, `wiki/metrics.md`,
`docs/troubleshooting.mdx`: `headroom proxy --log-level debug` (flag
doesn't exist)

**Stale content corrected:**
- `llms.txt`: telemetry stated as enabled-by-default (it's opt-in); wrap
list had 5 tools (now 11)
- `README.md`: compatibility matrix added 5 missing `wrap` targets;
`unwrap`, `doctor`, `init`/`install`, savings-analytics now mentioned
- `SECURITY.md`: supported version table showed 0.2.x (current: 0.27.x)
- `wiki/learn.md`: 5 missing flags added; verbosity shaper-off behavior
documented
- `wiki/quickstart.md`: "Configuration Reference" linked to `api.md`
(wrong) -> `configuration.md`
- `CacheAlignerConfig.enabled` default corrected: `True` -> `False`
- `opencode.mdx`: `--port` default wrong ("random") -> 8787; `openai`
backend removed
- `CONTRIBUTING.md`: broken Markdown table cell fixed
- `docs/meta.json`: `claude-code-azure-foundry` added to nav (was
unreachable orphan page)
- `configuration.mdx`: SDK modes vs proxy `--mode` now clearly
distinguished

## Test plan

- [x] `python -m pytest tests/ -x -q` — 857 passed, 0 failures
- [x] 41-combination CLI smoke test (all flag combos across 8 commands)
— 0 tracebacks
- [x] `ruff check` on all modified Python files — clean
- [x] Docs changes are removals/corrections of fabricated or stale
content; no new claims introduced
2026-06-27 14:48:43 -07:00

8 KiB

Quickstart Guide

Get Headroom running in 5 minutes with these copy-paste examples.


Installation

Python:

# Core only (minimal dependencies)
pip install headroom-ai

# With proxy server
pip install "headroom-ai[proxy]"

# Everything
pip install "headroom-ai[all]"

TypeScript / Node.js:

npm install headroom-ai

Docker-native:

curl -fsSL https://raw.githubusercontent.com/chopratejas/headroom/main/scripts/install.sh | bash

See Docker-native install if you want Docker to provide the Headroom runtime while your agent CLIs stay on the host.

Persistent background runtime:

headroom install apply --preset persistent-service --providers auto

See Persistent Installs if you want Headroom to stay up in the background and be reused by wrap.


Option 1: Proxy Server (Zero Code Changes)

The fastest way to start saving tokens. Works with any OpenAI-compatible client.

Step 1: Start the Proxy

headroom proxy --port 8787

Step 2: Verify It's Running

curl http://localhost:8787/health
# Expected: {"status":"healthy","ready":true,"config":{"backend":"anthropic",...},...}

Step 3: Point Your Client

# Claude Code
ANTHROPIC_BASE_URL=http://localhost:8787 claude

# GitHub Copilot CLI (default Anthropic-style proxy route)
headroom wrap copilot -- --model claude-sonnet-4-20250514

# Cursor / Continue / any OpenAI client
OPENAI_BASE_URL=http://localhost:8787/v1 your-app

# Python
export OPENAI_BASE_URL=http://localhost:8787/v1
python your_script.py

Step 4: Check Savings

curl http://localhost:8787/stats
# {"requests_total": 42, "tokens_saved_total": 125000, ...}

Option 2: Python SDK

Wrap your existing client for fine-grained control.

Basic Example

from headroom import HeadroomClient, OpenAIProvider
from openai import OpenAI

# Create wrapped client
client = HeadroomClient(
    original_client=OpenAI(),
    provider=OpenAIProvider(),
    default_mode="optimize",
)

# Use exactly like OpenAI client
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello!"},
    ],
)

print(response.choices[0].message.content)

# Check what happened
stats = client.get_stats()
print(f"Tokens saved: {stats['session']['tokens_saved_total']}")

With Tool Outputs (Where Savings Happen)

from headroom import HeadroomClient, OpenAIProvider
from openai import OpenAI
import json

client = HeadroomClient(
    original_client=OpenAI(),
    provider=OpenAIProvider(),
    default_mode="optimize",
)

# Simulate a conversation with large tool outputs
messages = [
    {"role": "system", "content": "You analyze search results."},
    {"role": "user", "content": "Search for Python tutorials."},
    {
        "role": "assistant",
        "content": None,
        "tool_calls": [{
            "id": "call_1",
            "type": "function",
            "function": {"name": "search", "arguments": '{"q": "python"}'},
        }],
    },
    {
        "role": "tool",
        "tool_call_id": "call_1",
        # This is where Headroom shines - compressing large outputs
        "content": json.dumps({
            "results": [{"title": f"Result {i}", "score": 100-i} for i in range(500)]
        }),
    },
    {"role": "user", "content": "What are the top 3 results?"},
]

# Headroom compresses the 500 results to ~20, keeping the most relevant
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
)

print(response.choices[0].message.content)

Simulate Before Sending

Preview optimizations without making an API call:

# See what would happen without calling the API
plan = client.chat.completions.simulate(
    model="gpt-4o",
    messages=messages,
)

print(f"Tokens before: {plan.tokens_before}")
print(f"Tokens after: {plan.tokens_after}")
print(f"Would save: {plan.tokens_saved} tokens ({plan.tokens_saved/plan.tokens_before*100:.0f}%)")
print(f"Transforms: {plan.transforms}")
print(f"Estimated savings: {plan.estimated_savings}")

Option 3: Anthropic SDK

from headroom import HeadroomClient, AnthropicProvider
from anthropic import Anthropic

client = HeadroomClient(
    original_client=Anthropic(),
    provider=AnthropicProvider(),
    default_mode="optimize",
)

# Use Anthropic-style API
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Hello, Claude!"},
    ],
)

print(response.content[0].text)

Verify It's Working

Method 1: Enable Logging

import logging
logging.basicConfig(level=logging.INFO)

# Now you'll see:
# INFO:headroom.transforms.pipeline:Pipeline complete: 45000 -> 4500 tokens (saved 40500, 90.0% reduction)
# INFO:headroom.transforms.smart_crusher:SmartCrusher: keeping 15 of 500 items

Method 2: Check Session Stats

stats = client.get_stats()
print(stats)
# {
#   "session": {"requests_total": 10, "tokens_saved_total": 5000, ...},
#   "config": {"mode": "optimize", "provider": "openai", ...},
#   "transforms": {"smart_crusher_enabled": True, ...}
# }

Method 3: Validate Setup

result = client.validate_setup()
if not result["valid"]:
    print("Setup issues:", result)
else:
    print("Setup OK!")
    print(f"Provider: {result['provider']['name']}")
    print(f"Storage: {result['storage']['url']}")

Common Configuration

Adjust Compression

from headroom import HeadroomClient, OpenAIProvider, HeadroomConfig

config = HeadroomConfig()

# Keep more items after compression (default: 15)
config.smart_crusher.max_items_after_crush = 30

# Only compress if tool output has > 500 tokens (default: 200)
config.smart_crusher.min_tokens_to_crush = 500

client = HeadroomClient(
    original_client=OpenAI(),
    provider=OpenAIProvider(),
    config=config,  # Pass custom config
    default_mode="optimize",
)

Skip Compression for Specific Tools

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    headroom_tool_profiles={
        "database_query": {"skip_compression": True},  # Never compress
        "search": {"max_items": 50},  # Keep more items
    },
)

Audit Mode (Observe Only)

# Start in audit mode - see what WOULD be optimized
client = HeadroomClient(
    original_client=OpenAI(),
    provider=OpenAIProvider(),
    default_mode="audit",  # No modifications, just logging
)

# Override per-request
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    headroom_mode="optimize",  # Enable for this request only
)

What Gets Optimized?

Content Type What Headroom Does Typical Savings
Tool outputs with lists Keeps errors, anomalies, high-score items 70-90%
Repeated search results Deduplicates and samples 60-80%
Long conversations Drops old turns, keeps recent 40-60%
System prompts with dates Stabilizes for cache hits Cache savings

Next Steps


Quick Troubleshooting

"No token savings"

# 1. Check mode
stats = client.get_stats()
print(stats["config"]["mode"])  # Should be "optimize"

# 2. Enable logging to see what's happening
import logging
logging.basicConfig(level=logging.DEBUG)

"High latency"

# Use BM25 instead of embeddings for faster relevance scoring
config.smart_crusher.relevance.tier = "bm25"

"Compression too aggressive"

# Keep more items
config.smart_crusher.max_items_after_crush = 50

See Troubleshooting Guide for more solutions.