headroom Documentation

Compress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy headroom on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name headroom -p 8787:8787 --restart always qdrant/qdrant:v1.17.1
Configured Services & Ports
โš™๏ธ headroom-proxy
image: build locally
๐Ÿ”Œ Ports: 127.0.0.1:8787:8787
โš™๏ธ qdrant
image: qdrant/qdrant:v1.17.1
๐Ÿ”Œ Ports: 127.0.0.1:6333:6333, 127.0.0.1:6334:6334
โš™๏ธ neo4j
image: neo4j:5.26
๐Ÿ”Œ Ports: 127.0.0.1:7474:7474, 127.0.0.1:7687:7687
docker-compose.yml
yaml (docker-compose.yml)
# =============================================================================
# Headroom โ€” full "memory stack" compose
# =============================================================================
# Brings up the Headroom proxy together with the two datastores it needs for
# semantic memory: Qdrant (vector search) and Neo4j (relationship graph).
#
# Quick start:
#   1. cp .env.example .env   # then set a real NEO4J_AUTH before any non-local use
#   2. docker compose up -d
#   3. point your LLM client at http://localhost:8787  (proxy)
#
# Just want the proxy without the memory features? You can run the proxy image
# on its own (`docker run --rm -p 127.0.0.1:8787:8787 -e HEADROOM_ALLOW_UNAUTHENTICATED_BIND=1
# ghcr.io/headroomlabs-ai/headroom --host 0.0.0.0 --port 8787`; the env var acknowledges that the
# 127.0.0.1 publication, not a token, is what keeps the port private); the two
# database services below are only required for the memory/relevance features.
#
# Ports published on the host โ€” all bound to 127.0.0.1 (this machine only):
#   8787  proxy (OpenAI-compatible endpoint)
#   6333  Qdrant REST   6334  Qdrant gRPC
#   7474  Neo4j Browser 7687  Neo4j Bolt
#
# None of these three services authenticates inbound callers by default: the
# proxy's /v1/* data plane is open unless HEADROOM_PROXY_TOKEN is set, Qdrant
# has no API key, and Neo4j falls back to a published dev password. Publishing
# them on 0.0.0.0 therefore hands any peer on your network a relay through the
# proxy plus direct read/write on the embeddings and graph derived from your
# prompts. They are bound to loopback so that `docker compose up -d` is safe on
# a shared or untrusted network.
#
# To reach the proxy from another machine, publish it deliberately AND require
# a token โ€” never one without the other:
#   HEADROOM_PROXY_TOKEN=$(openssl rand -hex 32)   # put this in .env
#   ports: ["8787:8787"]                           # override in a compose override file
# =============================================================================

services:
  # Headroom proxy โ€” the OpenAI-compatible endpoint your client talks to.
  # Built from the repo Dockerfile so it tracks your local checkout.
  headroom-proxy:
    build:
      context: .
      args:
        HEADROOM_BUILD_VERSION: ${HEADROOM_BUILD_VERSION:-source-build}
    # Bind to all interfaces inside the container so the published port is reachable.
    command: ["--host", "0.0.0.0"]
    environment:
      - HEADROOM_HOST=0.0.0.0
      # The proxy binds 0.0.0.0 *inside* the container (required for Docker port
      # forwarding); it is confined to host loopback by the published port below.
      # A proxy token is required so the data plane is never open if you widen the
      # bind. Generate one with: openssl rand -hex 32
      - HEADROOM_PROXY_TOKEN=${HEADROOM_PROXY_TOKEN:?set HEADROOM_PROXY_TOKEN (see .env.example; e.g. openssl rand -hex 32)}
      - HOME=/home/nonroot
      # Keep all Headroom read/write state on the named volume below.
      - HEADROOM_WORKSPACE_DIR=/home/nonroot/.headroom
      - HEADROOM_CONFIG_DIR=/home/nonroot/.headroom/config
      # if you want to use a custom OpenAI-compatible API endpoint,
      # uncomment and set the following line with the desired URL
      # - OPENAI_TARGET_API_URL=https://api.x.ai
      # Required before publishing this port beyond loopback: without it the
      # /v1/* data plane accepts unauthenticated callers.
      # - HEADROOM_PROXY_TOKEN=${HEADROOM_PROXY_TOKEN}
    ports:
      # Loopback-only. The container still listens on 0.0.0.0 (above) so the
      # other compose services can reach it by name; this line controls only
      # which host interfaces the port is published on.
      - "127.0.0.1:8787:8787"
    volumes:
      - headroom_workspace:/home/nonroot/.headroom
    # Readiness probe: the orchestrator polls /readyz so dependents and
    # `docker compose up --wait` only see the proxy as healthy once it's serving.
    healthcheck:
      test: ["CMD", "curl", "--fail", "--silent", "http://127.0.0.1:8787/readyz"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
    # Start the datastores first. Note: this waits for the containers to start,
    # not for them to be fully ready โ€” the proxy retries its connections, so a
    # brief "database not ready yet" window on first boot is expected.
    depends_on:
      - qdrant
      - neo4j

  # Vector database for semantic search.
  # Stores embeddings so the proxy can retrieve semantically similar context.
  qdrant:
    image: qdrant/qdrant:v1.17.1
    ports:
      # Loopback-only: Qdrant runs unauthenticated here and holds embeddings
      # derived from your prompts.
      - "127.0.0.1:6333:6333"  # REST API
      - "127.0.0.1:6334:6334"  # gRPC
    # Named volume keeps the vector index across container restarts/recreates.
    volumes:
      - qdrant_data:/qdrant/storage
    environment:
      - QDRANT__SERVICE__GRPC_PORT=6334

  # Graph database for relationships and multi-hop reasoning.
  # Backs the memory features that traverse links between stored items.
  neo4j:
    image: neo4j:5.26
    ports:
      # Loopback-only to keep the graph store off the network.
      - "127.0.0.1:7474:7474"  # HTTP (Browser)
      - "127.0.0.1:7687:7687"  # Bolt
    # Named volume persists the graph data across container restarts/recreates.
    volumes:
      - neo4j_data:/data
    environment:
      # No default credential โ€” must be supplied (see .env.example).
      - NEO4J_AUTH=${NEO4J_AUTH:?set NEO4J_AUTH, e.g. neo4j/}
      # APOC: Neo4j's standard procedure library, needed by Headroom's queries.
      - NEO4J_PLUGINS=["apoc"]
      # APOC file import/export stays disabled (its Neo4j default) โ€” it grants
      # filesystem read/write via stored procedures. Do not enable unless required.

# Named volumes โ€” managed by Docker, survive `docker compose down` (use
# `docker compose down -v` to delete the stored data as well).
volumes:
  headroom_workspace:    # persists dashboard savings/history, logs, config, memory state, session stats, and TOIN
  qdrant_data:
  neo4j_data:

Headroom

Context optimization layer for LLM applications. Compress tool outputs, logs, files, and RAG chunks before they reach the model. Same answers, 60โ€“95% fewer tokens. Library, proxy, and MCP server. Apache 2.0, local-first.

Headroom is shipped as a Python package (headroom-ai), a TypeScript package (headroom-ai), an OpenAI + Anthropic-compatible HTTP proxy (headroom proxy), and an MCP server (headroom_compress, headroom_retrieve, headroom_stats tools). All four modes use the same compression pipeline: per-content-type compressors (JSON, code, logs, diffs, text) feed into a Compress-Cache-Retrieve (CCR) store so compression stays reversible โ€” the LLM can ask for the original whenever it wants.

The canonical, always-current documentation index lives at the docs site below. If you can fetch one URL, fetch that one; the entries here are a hand-curated subset.

Canonical docs (start here)

Install (copy-paste-runnable)

  • Python: pip install headroom-ai (add [all] for every optional extra)
  • TypeScript / Node: npm install headroom-ai (or pnpm add headroom-ai, bun add headroom-ai)
  • Docker: docker run -p 8787:8787 ghcr.io/headroomlabs-ai/headroom:latest
  • Run the proxy: headroom proxy --port 8787 then point any client at http://127.0.0.1:8787
  • Wrap an agent in one command: headroom wrap claude (also: codex, copilot, cursor, aider, opencode, cline, continue, goose, openhands, openclaw, vibe, omp)

Entry points

  • Quickstart: 5-minute end-to-end (install โ†’ compress โ†’ call the model).
  • Installation: All install paths, extras, Docker tags, env vars.
  • Proxy server: Run as a local HTTP proxy in front of OpenAI / Anthropic / Gemini.
  • MCP server: headroom_compress, headroom_retrieve, headroom_stats for Claude Code / Cursor / any MCP host.
  • API reference: Python + TypeScript compress() API.

How it works

SDK / framework integrations

  • Anthropic SDK: withHeadroom(anthropic) wrapper.
  • OpenAI SDK: withHeadroom(openai) wrapper.
  • Vercel AI SDK: Middleware + withHeadroom().
  • LangChain: Chat models, memory, retrievers, agents.
  • Agno: Model wrapping + observability hooks.
  • Strands: Model wrapping + hook-based tool output compression.
  • LiteLLM: Single callback; works with all 100+ LiteLLM providers.

Memory & cross-agent state

  • Persistent memory: Per-project SQLite + HNSW vector store. No cross-project bleed (GH #462).
  • SharedContext: Compressed inter-agent context handoffs.
  • Failure learning: Offline analysis writes corrections to CLAUDE.local.md (default, gitignored) or CLAUDE.md (shared) / AGENTS.md / GEMINI.md.

Operations

Licensing

Apache 2.0. Use commercially, modify, redistribute. Data stays on the user's machine when running the library, proxy, or MCP server locally. Anonymous telemetry is off by default (opt-in); enable with HEADROOM_TELEMETRY=on or headroom proxy --telemetry.