pxpipe

Claude Code の肥大化した入力コンテキスト(システムプロンプト・ツールドキュメント・古い履歴)を高密度 PNG に変換し、ビジョン経路で読ませることで入力トークンを削減するローカルプロキシ。teamchong/pxpipe(npm: pxpipe-proxy)の技術概要。

1 — 概要

画像トークンはピクセル寸法で固定され、中身の文字量には依存しない。コード・JSON・ツール出力など密度の高いコンテキストは、テキストトークンより画像トークンあたり約 3.1 文字を載せられる。pxpipe は /v1/messages を傍受し、対象ブロックを 1928px 幅の列に折り返して PNG ページにレンダリングし、リクエストだけを圧縮して Anthropic / OpenAI へ転送する。応答ストリームはそのまま。

~59–70%エンドツーエンド請求削減(Fable 5 想定)
~92kchars / 1928×1928 ページ
47821デフォルト待受ポート
Node + Workersランタイム

削減率はワークロード依存。リクエストごとに無料の count_tokens カウンターファクチュアルと実請求を並列計測し、~/.pxpipe/events.jsonl に記録する。ダッシュボード(http://127.0.0.1:47821/)で節約量・変換前後の比較・モデル切替・キルスイッチを確認できる。

2 — 起動手順
npx pxpipe-proxy                                  # 127.0.0.1:47821 で待受
ANTHROPIC_BASE_URL=http://127.0.0.1:47821 claude  # Claude Code をプロキシ経由に

直近ターンはテキストのまま。システムプロンプト・ツールドキュメント・古い履歴の塊だけが画像化される。デフォルトで有効なモデルは claude-fable-5 と gpt-5.6。PXPIPE_MODELS=off で画像化を無効化できる。

開発ビルド

pnpm install && pnpm test
pnpm run build   # dist/ を再生成
3 — 処理の流れ
flowchart TD
  CC["Claude Code / クライアント"] --> PX["pxpipe proxy\n127.0.0.1:47821"]
  PX --> GATE{"適用判定\nモデル・収益性ゲート"}
  GATE -->|"対象ブロックあり"| RENDER["折り返し → PNG ページ生成\n~92k chars / page"]
  GATE -->|"非対象"| PASS["バイト同一で転送"]
  RENDER --> SPLICE["image block へ差し替え\ncache-friendly に再構成"]
  SPLICE --> API["Anthropic / OpenAI API"]
  PASS --> API
  API --> RESP["応答ストリーム(非圧縮)"]
  RESP --> CC
  PX -.-> LOG["events.jsonl\nカウンターファクチュアル計測"]

レンダリングの要点は README の一行式どおり:

tool_result 文字列 → 1928px 幅で折り返し → ~92,000 chars / page に詰める → PNG[]

1928×1928 画像は約 4,761 ビジョントークンで、テキストが ~19 chars/token を超える場合のみ画像化が有利。Claude Code 実トラフィックは ~1.91 chars/token(N=391)なので、リクエスト単位の推定器がスパースな散文はテキストのまま残す。静的プレフィックス(システム+ツール定義)はキャッシュ整合を保ったまま差し替える。

4 — 圧縮対象と制約
種類条件備考
大きな tool_resultトークン密度の高い本文が ~6k chars 超ファイル読取・コマンド出力・ログ
折りたたまれた古い履歴ライブテールより手前のターン直近ターンは常にテキスト
システムプロンプト + ツールドキュメント静的スラブキャッシュプレフィックスとして保持

それ以外(ユーザーメッセージ、直近ターン、スパース散文、小さすぎるブロック、許可リスト外モデル)はバイト同一で通過。GPT 経路ではツール定義はネイティブ JSON のまま、Anthropic の cache_control マーカーは使わない。

モデルビジョンは OCR ではない。 パッチ埋め込み経由で「読む」ため、12 文字の hex などバイト完全一致が必要な値は画像から信頼できない。密なレンダー上の verbatim 12-char hex は Fable 5 で 13/15、Opus 4.8 で 0/15。ミスはエラーではなく、もっともらしい誤答として表面化する。
  • ID・ハッシュ・シークレットはテキストのまま残す。専用の verbatim ガードは未実装。
  • 非許可モデルのサブエージェントはテキスト通過 — バイト厳密な作業は CLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4-6 等へ逃がす。
  • Opus 4.7/4.8 は ~7% のレンダー誤読、GPT 5.5 は画像化コンテキストで劣化 — いずれも PXPIPE_MODELS で opt-in。
  • PNG エンコードは大きなリクエストに送信前レイテンシを追加する。

詳細: docs/NOT-OCR.md、LEGIBILITY-AUDIT-2026-07-01.md、FINDINGS.md。

5 — ベンチマーク
テストNtextpxpipeトークン
novel arithmetic, claude-fable-5100100%100%−38%
novel arithmetic, claude-opus-4-8100100%93%−38%
gist recall A/B, Fable 598/arm98/9898/98—
state tracking, Fable 518/arm18/1818/18—
confabulation(未提示事実)16/arm0/160/16—
verbatim 12-char hex, Opus1515/150/15—
verbatim 12-char hex, Fable 515—13/15—

実作業ベンチ

  • SWE-bench Lite pilot: 10/10 both arms、リクエストサイズ −65%
  • SWE-bench Pro: 14/19 ON vs 15/19 OFF、−60%、判定一致 18/19(差分 1 件は run-to-run 分散)
  • デモ動画: Fable 5 で 39 ファイルの imaged filler を 10/10 でカウント、セッション終了時 $6.06 vs $42.21(plain 比)

受領データ・ログ: eval/swe-bench、eval/swe-bench-pro、eval/gist-recall。

6 — API と参照
import { renderTextToImages, transformAnthropicMessages } from "pxpipe-proxy";

const { pages } = await renderTextToImages(toolResultText);
const { body, applied, info } = await transformAnthropicMessages({
  body: requestBytes,
  model: "claude-fable-5",
});

options.keepSharp(block) でブロックをテキスト固定、options.emitRecoverable で画像化した元ブロックを返却。公開 API の正は src/core/index.ts。

主要エクスポート(パッケージ)

サブパス用途
pxpipe-proxyrenderTextToImages、transformAnthropicMessages
pxpipe-proxy/transformtransformRequest、低レベル変換
pxpipe-proxy/proxycreateProxy — HTTP プロキシ本体
pxpipe-proxy/node / ./workerNode / Cloudflare Workers エントリ
pxpipe-proxy/measurementcount_tokens カウンターファクチュアル
pxpipe-proxy/applicabilityモデル許可リスト・適用判定