headforward documentation

headforward shrinks the tool output a coding agent reads (test runs, build logs, git output, JSON, file reads) before it reaches the model, so every turn costs fewer input tokens. It runs as a Claude Code hook, a local proxy, or both. Error lines are always kept, anything shortened can be read back, and your own messages are never changed.

Install

Requires Python 3.9 or newer on macOS, Linux or Windows. There are no other dependencies.

pip install headforward

Optional, for exact token counts instead of estimates:

pip install "headforward[exact]"

No pip? headforward is one file. Save headforward.py and run python3 headforward.py wherever these docs say headforward.

Quick start

  1. Turn on the hook for every Claude Code session, desktop app included:
    headforward hooks install global
  2. Check your setup. It prints the fix for anything wrong:
    headforward doctor
  3. Start a new Claude Code session and work as usual. When a noisy command is shortened, its output ends with a line like [40 passing test lines omitted; full output: headforward show ID].
  4. See running totals any time:
    headforward stats

Hooks (desktop app too)

A Claude Code PreToolUse hook pipes noisy commands through the filter. It runs inside every session, including Claude Code in the desktop app, which proxies can't reach.

headforward hooks install global          # or one project: headforward hooks install ~/code/my-app
headforward hooks uninstall global
CommandsWhat happens
Tests: pytest, npm test, go test, cargo test and similarPassing-test lines collapse to a count. Failures, tracebacks and the summary are kept.
Installs and builds: pip install, npm install, make, cargo build, docker buildDownload, progress and build-step lines collapse to a count.
git logHashes shortened, a single author stated once, stat bar graphs dropped.
ls -lLink counts dropped, a single owner stated once.
grep, rgMatches grouped under their file.
log show and timestamped logsNear-identical lines counted on the first one.

Every other command is left alone. Error-like lines are always kept, the command's exit code is preserved, and the full output is saved: headforward show ID prints it, and --lines A-B prints part of it.

Always-on proxy (macOS)

Runs the proxy at login and points Claude Code's settings at it, so every terminal session is compressed without typing wrap.

headforward desktop on global      # or one project: headforward desktop on ~/code/my-app
headforward desktop status         # running? which settings use it? where does it forward?
headforward desktop off            # stop it and undo every settings change

Settings change only after the proxy is confirmed running, and a backup is kept. If your settings already point ANTHROPIC_BASE_URL at another gateway (a router, cost tracker or company proxy), headforward goes in front of it: Claude Code → headforward → your gateway → Anthropic. desktop off puts your URL back.

Claude Code in the desktop app ignores ANTHROPIC_BASE_URL but honors HTTPS_PROXY. Add --https and headforward serves it as its HTTPS proxy:

headforward desktop on global --https

It makes a local certificate authority in ~/.headforward/ca that can only vouch for api.anthropic.com, and adds HTTPS_PROXY, NODE_EXTRA_CA_CERTS and NO_PROXY to the settings file. Only api.anthropic.com is decrypted; every other host gets a plain tunnel. There is no fallback: if the proxy is down, desktop sessions can't connect until it's back or you run desktop off.

An ANTHROPIC_BASE_URL exported in your shell overrides Claude Code settings and skips the proxy; headforward doctor warns about it.

Coding agents

wrap starts a private proxy on a random local port, launches the agent pointed at it, and shuts the proxy down when the agent exits.

AgentCommandNotes
Claude Codeheadforward wrap claudeSign in to Claude Code once with /login, or set ANTHROPIC_API_KEY.
OpenAI Codex CLIheadforward wrap codexUse an API key login. A ChatGPT-account login talks to ChatGPT's servers and bypasses the proxy.
Aiderheadforward wrap aiderWorks with OpenAI and Anthropic models.

Anything after the agent name is passed to the agent, for example headforward wrap claude --continue.

Proxy for your own app

Run the proxy, then point your SDK at it with its base URL setting.

headforward proxy --port 8787

# in your app's environment
export ANTHROPIC_BASE_URL=http://127.0.0.1:8787
export OPENAI_BASE_URL=http://127.0.0.1:8787/v1

Supported request formats: Anthropic Messages, OpenAI Chat Completions and OpenAI Responses. Streaming responses pass through as they arrive.

If ANTHROPIC_BASE_URL or OPENAI_BASE_URL is already set when the proxy starts, it forwards there instead of the public API, so company gateways keep working. To force a destination, use --upstream URL.

Prompt compression

For text you paste into a chat app. It removes filler, greetings, sign-offs, wordy phrases and repeated sentences. Code is never rewritten.

# macOS: compress your clipboard and put it back
pbpaste | headforward - -l high | pbcopy

# a file
headforward prompt.txt -l high
LevelWhat it removes
lightExtra spaces and blank lines.
mediumPlus filler words, wordy phrases, greetings, sign-offs and repeated sentences. The default.
highPlus articles, hedges such as "I think", bold markers; JSON code blocks are minified.
maxPlus comment-only lines and blank lines inside code blocks.

To apply the tool-output rules to a file instead, use --tool: headforward api.json --tool.

Savings and billing

The proxy reads the usage numbers the provider returns with every response: input tokens, cache reads and output tokens. headforward stats shows those billed totals for the last 24 hours and all time, plus tokens saved. Savings are converted from characters removed at the token rate you were actually billed for those requests.

$ headforward stats
Last 24 hours     212 requests  1,830,114 input tokens billed, ~402,770 saved (18% less input), cache hits 91%, 48,210 output

The numbers above are an illustration of the format, not a measurement.

Stats are stored locally in ~/.headforward/stats.jsonl.

Check answers don't change

Record real requests while you work, then replay each one to the model with and without compression and compare what comes back.

headforward wrap --record ~/lt-rec claude   # work as usual
headforward eval ~/lt-rec --tokens-only     # exact token savings only
headforward eval ~/lt-rec                   # also compare the model's answers

How compression works

headforward only rewrites tool results. System prompts and your messages reach the model unchanged.

InputWhat happensLossless?
JSON lists of same-shaped objectsKeys are written once and values as rows. A column with one value in every row is stated once.Yes. The original can be rebuilt exactly.
A tool result identical to an earlier oneReplaced by [Same output as tool call X above.]Yes. The earlier copy is still in context.
Logs and command outputRepeated lines collapse to one line with a count. Terminal color codes and trailing spaces are removed.Yes, apart from color codes.
File readsLine-number padding is trimmed.Yes.
Routine command output (hooks, --smart)Runs of 3+ installs, progress bars, passing tests or build steps collapse to a count.Recoverable with headforward show ID.
Git log, ls -l, grep, timestamped logs (hooks, --lossy)Repeated and derivable parts removed; every distinct line kept.Recoverable with headforward show ID.
Runs of near-identical log lines (--lossy only)First and last lines kept, the middle replaced by a count.No.

Here is a JSON result before and after:

[{"id": 1, "status": "shipped", "total": 19.99},
 {"id": 2, "status": "shipped", "total": 24.50},
 {"id": 3, "status": "shipped", "total": 8.00}]

{"_cols":["id","total"],"_rows":[[1,19.99],[2,24.5],[3,8.0]],"_same":{"status":"shipped"}}

Prompt caching

Anthropic and OpenAI bill repeated prompt prefixes at a fraction of the normal rate. headforward is deterministic and never rewrites earlier turns, so each request still starts with exactly the bytes of the previous one and cache hits keep landing.

CLI reference

CommandOptions
headforward wrap AGENT [args]--lossy, --record FOLDER
headforward proxy--port N (default 8787), --upstream URL, --lossy, --record FOLDER
headforward hooks install|uninstall [PROJECT|global]none
headforward desktop on|off|status [PROJECT|global]--smart
headforward doctornone
headforward show ID--lines A-B
headforward statsnone
headforward eval FOLDER--tokens-only, --limit N (default 50), --lossy, --max-tokens N
headforward FILE (or - for stdin)-l, --level light | medium | high | max; -t, --tool; --lossy; -s, --stats; -q, --quiet; --model NAME
OptionMeaning
--lossyAlso shorten runs of near-identical log lines.
--record FOLDERSave each original request, without API keys, for eval.
--upstream URLSend all traffic to this base URL instead of the provider's API.
-s, --statsPrint only the savings line.
-q, --quietDon't print the savings line to stderr.
--model NAMEWhich tiktoken encoding to count with (default gpt-4o).

Environment variables: HEADFORWARD_LOSSY=1 turns on lossy mode for wrap; HEADFORWARD_UPSTREAM sets the upstream for wrap.

Privacy and safety

Limits

Troubleshooting

Claude Code says "Not logged in"

The terminal version of Claude Code has its own sign-in, separate from the desktop app. Type /login inside Claude Code once. headforward passes your sign-in through unchanged.

headforward: command not found

The folder pip installs scripts into isn't on your PATH. Run python3 -m pip show -f headforward to find it, or run the single file with python3 headforward.py.

No savings were recorded

Hooks and settings apply to new sessions only, so start a new Claude Code session. Then run something noisy, like your tests, and look for a headforward show ID line in the output. For the proxy, run headforward doctor: a shell ANTHROPIC_BASE_URL overrides Claude Code settings and skips it. Codex with a ChatGPT login and browser apps never reach the proxy.

A command with ! hangs at dquote>

In zsh, ! inside double quotes is history expansion. Press Ctrl-C, then use single quotes: echo 'Hello!' | headforward -.