Metadata-Version: 2.4
Name: headroom-ai
Version: 0.43.1
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: tiktoken>=0.5.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: litellm>=1.96.2,<2.0
Requires-Dist: click>=8.3.3
Requires-Dist: rich>=13.0.0
Requires-Dist: opentelemetry-api>=1.45.1
Requires-Dist: ast-grep-cli>=0.30.0,!=0.44.1
Requires-Dist: pyyaml>=6.0
Requires-Dist: tomlkit>=0.15.2,<1.0
Requires-Dist: truststore>=0.10.0
Requires-Dist: hf-xet>=1.6.0 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'
Requires-Dist: filelock>=4.2.1
Requires-Dist: agno>=1.0.0 ; extra == 'agno'
Requires-Dist: headroom-ai[proxy,code,ml,memory,relevance,image,reports,otel,evals,voice,html,mcp,spreadsheet] ; extra == 'all'
Requires-Dist: any-llm-sdk>=1.0.0 ; python_full_version >= '3.11' and extra == 'anyllm'
Requires-Dist: autogen-agentchat>=0.7 ; extra == 'autogen'
Requires-Dist: boto3>=1.41.0 ; extra == 'bedrock'
Requires-Dist: botocore[crt]>=1.41.0 ; extra == 'bedrock'
Requires-Dist: tree-sitter-language-pack>=0.10.0,<1.0 ; extra == 'code'
Requires-Dist: tree-sitter>=0.25.2,<0.27 ; extra == 'code'
Requires-Dist: pytest>=7.0.0 ; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0 ; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0 ; extra == 'dev'
Requires-Dist: ruff==0.17.3 ; extra == 'dev'
Requires-Dist: mypy>=1.0.0 ; extra == 'dev'
Requires-Dist: pre-commit>=3.0.0 ; extra == 'dev'
Requires-Dist: openai>=1.0.0 ; extra == 'dev'
Requires-Dist: anthropic>=0.18.0 ; extra == 'dev'
Requires-Dist: litellm>=1.96.2,<2.0 ; extra == 'dev'
Requires-Dist: fastapi>=0.100.0 ; extra == 'dev'
Requires-Dist: uvicorn>=0.23.0,<1.0 ; extra == 'dev'
Requires-Dist: httpx[http2,socks]>=0.24.0 ; extra == 'dev'
Requires-Dist: websockets>=13.0 ; extra == 'dev'
Requires-Dist: opentelemetry-sdk>=1.24.0 ; extra == 'dev'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.24.0 ; extra == 'dev'
Requires-Dist: ollama>=0.4.0 ; extra == 'dev'
Requires-Dist: langchain-ollama>=0.2.0 ; extra == 'dev'
Requires-Dist: hnswlib>=0.8.0 ; extra == 'dev'
Requires-Dist: sqlite-vec>=0.1.6 ; extra == 'dev'
Requires-Dist: sentence-transformers>=2.2.0,<7.0 ; extra == 'dev'
Requires-Dist: numpy>=1.24.0 ; extra == 'dev'
Requires-Dist: openpyxl>=3.1.0 ; extra == 'dev'
Requires-Dist: fakeredis[lua]>=2.20.0 ; extra == 'dev'
Requires-Dist: xlrd>=2.0.1 ; extra == 'dev'
Requires-Dist: xlwt>=1.3.0 ; extra == 'dev'
Requires-Dist: cryptography>=50.0.0 ; extra == 'dev'
Requires-Dist: respx>=0.20.0 ; extra == 'dev'
Requires-Dist: datasets>=5.0.1 ; extra == 'evals'
Requires-Dist: sentence-transformers>=2.2.0,<7.0 ; (platform_machine != 'x86_64' and extra == 'evals') or (sys_platform != 'darwin' and extra == 'evals')
Requires-Dist: numpy>=1.24.0 ; extra == 'evals'
Requires-Dist: scikit-learn>=1.3.0 ; extra == 'evals'
Requires-Dist: anthropic>=0.18.0 ; extra == 'evals'
Requires-Dist: openai>=1.0.0 ; extra == 'evals'
Requires-Dist: trafilatura>=1.6.0 ; extra == 'html'
Requires-Dist: pillow>=12.3.0 ; extra == 'image'
Requires-Dist: sentencepiece>=0.1.99 ; extra == 'image'
Requires-Dist: rapidocr-onnxruntime>=1.4.0,<2 ; python_full_version < '3.13' and extra == 'image'
Requires-Dist: rapidocr>=3.0,<4 ; (python_full_version == '3.13.*' and extra == 'image') or (python_full_version >= '3.14' and platform_machine != 'x86_64' and extra == 'image') or (python_full_version >= '3.14' and sys_platform != 'darwin' and extra == 'image')
Requires-Dist: onnxruntime>=1.7,<2 ; (python_full_version == '3.13.*' and extra == 'image') or (python_full_version >= '3.14' and platform_machine != 'x86_64' and extra == 'image') or (python_full_version >= '3.14' and sys_platform != 'darwin' and extra == 'image')
Requires-Dist: langchain-core>=1.3.3,<4.0 ; extra == 'langchain'
Requires-Dist: langchain-openai>=1.1.14,<2.0 ; extra == 'langchain'
Requires-Dist: langchain-core>=1.3.3,<4.0 ; extra == 'langgraph'
Requires-Dist: langchain-openai>=1.1.14,<2.0 ; extra == 'langgraph'
Requires-Dist: langgraph>=1.2.14,<2.0 ; extra == 'langgraph'
Requires-Dist: headroom-ai[proxy,code,relevance,reports,otel,html,mcp,spreadsheet] ; extra == 'lean'
Requires-Dist: mcp>=2.2.0,<3.0.0 ; extra == 'mcp'
Requires-Dist: httpx>=0.24.0 ; extra == 'mcp'
Requires-Dist: starlette>=0.27.0 ; extra == 'mcp'
Requires-Dist: uvicorn>=0.23.0,<1.0 ; extra == 'mcp'
Requires-Dist: sqlite-vec>=0.1.6 ; extra == 'memory'
Requires-Dist: sentence-transformers>=2.2.0,<7.0 ; (platform_machine != 'x86_64' and extra == 'memory') or (sys_platform != 'darwin' and extra == 'memory')
Requires-Dist: mem0ai>=2.0.18,<3.0 ; extra == 'memory-stack'
Requires-Dist: qdrant-client>=1.9.0,<2.0 ; extra == 'memory-stack'
Requires-Dist: neo4j>=5.20.0,<7.0 ; extra == 'memory-stack'
Requires-Dist: torch>=2.12.1 ; (platform_machine != 'x86_64' and extra == 'ml') or (sys_platform != 'darwin' and extra == 'ml')
Requires-Dist: transformers>=5.5.0,<6.0 ; extra == 'ml'
Requires-Dist: huggingface-hub>=1.5.0,<3.0 ; extra == 'ml'
Requires-Dist: opentelemetry-sdk>=1.24.0 ; extra == 'otel'
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.24.0 ; extra == 'otel'
Requires-Dist: fastapi>=0.100.0 ; extra == 'proxy'
Requires-Dist: uvicorn>=0.23.0,<1.0 ; extra == 'proxy'
Requires-Dist: orjson>=3.9.14 ; platform_python_implementation != 'PyPy' and extra == 'proxy'
Requires-Dist: httpx[http2]>=0.24.0 ; extra == 'proxy'
Requires-Dist: openai>=2.14.0 ; extra == 'proxy'
Requires-Dist: mcp>=2.2.0,<3.0.0 ; extra == 'proxy'
Requires-Dist: magika>=0.6.0 ; (python_full_version < '3.14' and extra == 'proxy') or (platform_machine != 'x86_64' and extra == 'proxy') or (sys_platform != 'darwin' and extra == 'proxy')
Requires-Dist: zstandard>=0.20.0 ; extra == 'proxy'
Requires-Dist: websockets>=13.0 ; extra == 'proxy'
Requires-Dist: python-socks[asyncio]>=2.7.1 ; extra == 'proxy'
Requires-Dist: onnxruntime>=1.24.0 ; (python_full_version >= '3.11' and platform_machine != 'x86_64' and extra == 'proxy') or (python_full_version >= '3.11' and sys_platform != 'darwin' and extra == 'proxy')
Requires-Dist: onnxruntime>=1.16.0,<1.24.0 ; (python_full_version < '3.11' and extra == 'proxy') or (python_full_version < '3.14' and platform_machine == 'x86_64' and sys_platform == 'darwin' and extra == 'proxy')
Requires-Dist: transformers>=5.5.0,<6.0 ; extra == 'proxy'
Requires-Dist: watchdog>=4.0.0 ; (python_full_version < '3.14' and extra == 'proxy') or (sys_platform != 'darwin' and extra == 'proxy')
Requires-Dist: sqlite-vec>=0.1.6 ; extra == 'proxy'
Requires-Dist: headroom-ai[proxy] ; extra == 'proxy-prod'
Requires-Dist: gunicorn>=21.0.0 ; sys_platform != 'win32' and extra == 'proxy-prod'
Requires-Dist: torch>=2.12.1 ; sys_platform == 'darwin' and extra == 'pytorch-mps'
Requires-Dist: sentence-transformers>=2.2.0 ; sys_platform == 'darwin' and extra == 'pytorch-mps'
Requires-Dist: redis>=5.0.0 ; extra == 'redis'
Requires-Dist: fastembed>=0.6.0 ; (python_full_version < '3.14' and extra == 'relevance') or (platform_machine != 'x86_64' and extra == 'relevance') or (sys_platform != 'darwin' and extra == 'relevance')
Requires-Dist: numpy>=1.24.0 ; extra == 'relevance'
Requires-Dist: jinja2>=3.0.0 ; extra == 'reports'
Requires-Dist: headroom-ai[lean] ; extra == 'sandbox'
Requires-Dist: openpyxl>=3.1.0 ; extra == 'spreadsheet'
Requires-Dist: xlrd>=2.0.1 ; extra == 'spreadsheet'
Requires-Dist: strands-agents>=0.1.0 ; extra == 'strands'
Requires-Dist: hnswlib>=0.8.0 ; extra == 'vector'
Requires-Dist: onnxruntime>=1.24.0 ; (python_full_version >= '3.11' and platform_machine != 'x86_64' and extra == 'voice') or (python_full_version >= '3.11' and sys_platform != 'darwin' and extra == 'voice')
Requires-Dist: onnxruntime>=1.16.0,<1.24.0 ; (python_full_version < '3.11' and extra == 'voice') or (python_full_version < '3.14' and platform_machine == 'x86_64' and sys_platform == 'darwin' and extra == 'voice')
Requires-Dist: transformers>=5.5.0,<6.0 ; extra == 'voice'
Requires-Dist: torch>=2.12.1 ; (platform_machine != 'x86_64' and extra == 'voice') or (sys_platform != 'darwin' and extra == 'voice')
Requires-Dist: headroom-ai[voice] ; extra == 'voice-train'
Requires-Dist: datasets>=5.0.1 ; extra == 'voice-train'
Requires-Dist: accelerate>=0.20.0 ; extra == 'voice-train'
Provides-Extra: agno
Provides-Extra: all
Provides-Extra: anyllm
Provides-Extra: autogen
Provides-Extra: bedrock
Provides-Extra: code
Provides-Extra: dev
Provides-Extra: evals
Provides-Extra: html
Provides-Extra: image
Provides-Extra: langchain
Provides-Extra: langgraph
Provides-Extra: lean
Provides-Extra: mcp
Provides-Extra: memory
Provides-Extra: memory-stack
Provides-Extra: ml
Provides-Extra: otel
Provides-Extra: proxy
Provides-Extra: proxy-prod
Provides-Extra: pytorch-mps
Provides-Extra: redis
Provides-Extra: relevance
Provides-Extra: reports
Provides-Extra: sandbox
Provides-Extra: spreadsheet
Provides-Extra: strands
Provides-Extra: vector
Provides-Extra: voice
Provides-Extra: voice-train
License-File: LICENSE
License-File: NOTICE
Summary: Compress tool outputs, logs, JSON and chat history before each LLM call. Fewer input tokens, same answers; in-process, no API key. Library, proxy and MCP server.
Keywords: llm,openai,anthropic,claude,gpt,gemini,token-cost,reduce-tokens,input-tokens,context-window,token-budget,tool-output,tool-results,chat-history,trim-messages,context-compression,prompt-compression,context-engineering,agents,coding-agents,mcp,proxy,fastapi,langchain,litellm
Author: Headroom Contributors
Maintainer: Headroom Contributors
License-Expression: Apache-2.0
Requires-Python: >=3.11
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: AI / LLM Index, https://docs.headroomlabs.ai/llms.txt
Project-URL: Changelog, https://github.com/headroomlabs-ai/headroom/blob/main/CHANGELOG.md
Project-URL: Documentation, https://docs.headroomlabs.ai/docs
Project-URL: Homepage, https://docs.headroomlabs.ai
Project-URL: Issues, https://github.com/headroomlabs-ai/headroom/issues
Project-URL: Repository, https://github.com/headroomlabs-ai/headroom

# Headroom (`headroom-ai`)

Compress tool outputs, logs, JSON and chat history before each LLM call, so the
model sees fewer input tokens and the same facts. Runs in-process, in Python,
with no API key and no model download. Originals are cached locally and
retrievable.

Measured: 21–57% fewer input tokens on four agent scenarios, 90%+ on repeated
JSON arrays and log lines, little on prose. Numbers and how to reproduce them:
https://docs.headroomlabs.ai/docs/benchmarks and the "Proof" section of
https://github.com/headroomlabs-ai/headroom

## Use it from a Python app that calls an LLM

```bash
pip install headroom-ai
```

```python
from headroom import compress

result = compress(messages, model="gpt-4o")  # OpenAI or Anthropic message dicts
result.messages  # same shape as the input, fewer tokens
result.tokens_before, result.tokens_after, result.tokens_saved
```

Pass `result.messages` to your existing client call instead of `messages`.
Nothing else changes. Error lines, stack traces, first and last items and
statistical outliers are kept; repeated and low-information items are dropped.

Zero-network check, no provider key needed:

```bash
HEADROOM_OFFLINE=1 python -c "from headroom import compress; log='\n'.join(f'INFO step {i} ok' for i in range(3000))+'\nFATAL disk full'; r=compress([{'role':'user','content':'What failed?'},{'role':'assistant','content':None,'tool_calls':[{'id':'c1','type':'function','function':{'name':'logs','arguments':'{}'}}]},{'role':'tool','tool_call_id':'c1','content':log}], model='gpt-4o'); print(r.tokens_before, '->', r.tokens_after, 'FATAL kept:', 'FATAL' in str(r.messages))"
```

Prints on the order of `20000 -> 95 FATAL kept: True`. `HEADROOM_OFFLINE=1`
blocks every connection Headroom would make on its own: the update check, model
and pricing-table downloads, and the anonymous usage beacon the proxy and MCP
server send by default (`HEADROOM_BEACON=off` turns off only the beacon).

FastAPI example with a `POST /chat` endpoint:
https://docs.headroomlabs.ai/docs/fastapi

## Use it around a coding agent (no code changes)

```bash
uv tool install --python 3.13 "headroom-ai[all]"   # CLI in its own env; pip install "headroom-ai[proxy]" also works
headroom wrap claude        # also: codex, grok, copilot, cursor, aider, opencode, cline, continue, goose, openhands, openclaw, vibe, omp, zcode
headroom proxy --port 8787  # or run the proxy and point any client at it
```

## Other entry points

- OpenAI, Anthropic, LiteLLM, LangChain, Agno, Strands, CrewAI, AutoGen adapters:
  https://docs.headroomlabs.ai/docs (Integrations)
- MCP server (`headroom_compress`, `headroom_retrieve`, `headroom_stats`):
  https://docs.headroomlabs.ai/docs/mcp
- TypeScript SDK (`npm install headroom-ai`, needs the proxy running):
  https://www.npmjs.com/package/headroom-ai
- Full docs index for agents: https://docs.headroomlabs.ai/llms.txt
- Source and issues: https://github.com/headroomlabs-ai/headroom

Extras: `[proxy]` adds the HTTP proxy and `headroom wrap`, `[mcp]` the MCP
server, `[ml]` the Kompress text model (torch), `[all]` everything. The base
install is enough for `compress()`. Requires Python 3.11+.

Apache 2.0. The import and CLI name is `headroom`; the PyPI distribution named
`headroom` is a different project.

