- pxpipe는 Claude Code 요청의 큰 컨텍스트를 로컬 프록시에서 PNG 이미지로 바꿔 입력 토큰을 줄이며, Fable 현재 정가 기준 엔드투엔드 청구액을 약 59~70% 낮춘다고 밝힘
- 핵심 원리는 이미지 토큰 비용이 안에 들어간 텍스트 양이 아니라 픽셀 크기로 정해지는 점이며, 코드·JSON·도구 출력 같은 밀집 텍스트는 실제 Claude Code 트래픽에서 이미지 토큰당 약 3.1자, 텍스트 토큰당 약 1자를 담음
- 압축 대상은 큰 tool_result, 오래된 접힌 히스토리, 정적 시스템 프롬프트와 도구 문서이며, 최근 턴·사용자 메시지·모델 출력·희소한 prose·허용 목록 밖 모델은 텍스트 그대로 통과함
- 손실이 있는 방식이라 정확한 12자 hex 문자열 회상은 Fable 5에서 13/15, Opus에서 0/15였고, 누락은 오류가 아니라 그럴듯한 오답으로 나타날 수 있어 ID·해시·시크릿 같은 바이트 정확 값은 텍스트로 유지해야 함
- 기본 대상 모델은 claude-fable-5,gpt-5.6이며 Opus 4.7/4.8과 GPT 5.5는 이미지 컨텍스트 판독 성능 저하 때문에 옵트인으로만 사용하고, 실제 적용 여부와 절감량은 ~/.pxpipe/events.jsonl에서 요청별로 확인 가능함
pxpipe가 줄이려는 비용
- pxpipe는 Claude Code의 입력 토큰을 줄이기 위해 큰 컨텍스트를 이미지로 렌더링하는 로컬 프록시임
- 대상은 시스템 프롬프트, 도구 문서, 과거 히스토리, 큰 도구 출력처럼 요청 본문에서 부피가 큰 입력 블록임
- 모델 출력은 압축하지 않고, 응답 스트리밍은 정상적으로 동작함
- 이미지의 토큰 비용은 이미지 안의 글자 수가 아니라 픽셀 크기에 따라 정해짐
- 실제 Claude Code 트래픽에서 밀집 콘텐츠는 이미지 토큰당 약 3.1자를 담음
- 텍스트 토큰은 약 1자 수준으로 측정됨
- 예시 렌더는 약 48k자의 시스템 프롬프트와 도구 문서를 1573×1248 이미지 한 장에 담았고, 텍스트로는 약 25k 토큰, 이미지로는 약 2.7k 이미지 토큰이 필요함
실행과 대시보드
npx pxpipe-proxy # proxy on 127.0.0.1:47821
ANTHROPIC_BASE_URL=
http://127.0.0.1:47821 claude # point Claude Code at it
- 프록시는 127.0.0.1:47821에서 실행됨
- 대시보드는 http://127.0.0.1:47821/에서 제공됨
- 저장된 토큰 수
- 텍스트→이미지 변환의 좌우 비교
- 킬 스위치
- 실시간 모델 칩
- 최근 턴은 텍스트로 유지되고, 시스템 프롬프트·도구 문서·오래된 대량 히스토리는 이미지화됨
데모에서 보인 결과
- Fable 5는 기본값이며 README에서는 100/100 판독 모델로 제시됨
- 39개의 이미지화된 filler 파일에서 정확한 토큰 카운트를 10/10 맞춤
- grep 결과와 줄 단위로 일치함
- 다단계 ledger 산술을 맞춤
- 세션 비용은 pxpipe 사용 시 $6.06, 일반 텍스트는 $42.21로 제시됨
- pxpipe 쪽은 요청된 한 줄 출력 형식을 맞추기 위해 한 번의 nudging이 필요했음
- Opus 4.8은 기본 비활성화 상태임
- 텍스트 needle은 양쪽 모두에서 읽힘
- 이미지화된 phrase-count는 Opus에서 읽히지 않았고, pxpipe는 숫자를 지어내지 않고 실패를 드러냄
- 이 오독률 때문에 Opus는 옵트인 대상임
정확도와 손실성
- pxpipe는 손실 압축 방식임
- 밀집 이미지 콘텐츠에서 정확한 12자 hex 문자열 회상 결과는 모델별로 크게 갈림
- Fable 5: 13/15
- Opus: 0/15
- 누락은 오류로 나타나는 것이 아니라 조용한 confabulation으로 나타날 수 있음
- ID, 해시, 시크릿 같은 바이트 단위 정확성이 필요한 값은 텍스트로 유지해야 함
- 전용 verbatim-risk guard는 아직 내장되어 있지 않음
- 비허용 목록 모델을 쓰는 subagent는 텍스트로 통과시킬 수 있음
- CLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4-6
- agent frontmatter의 model: sonnet
벤치마크와 측정값
- 새 랜덤 숫자 문제 기반 벤치마크에서 모델이 암기했을 가능성이 낮은 문제를 사용함
테스트
N
텍스트
pxpipe 이미지
토큰
| novel arithmetic, claude-fable-5 |
100 |
100% |
100% |
−38% |
| novel arithmetic, claude-opus-4-8 |
100 |
100% |
93% |
−38% |
| gist recall A/B, Fable 5 |
98/arm |
98/98 |
98/98 |
- |
| state tracking, Fable 5 |
18/arm |
18/18 |
18/18 |
- |
| never-stated facts confabulation, Fable 5 |
16/arm |
0/16 |
0/16 |
- |
| verbatim 12-char hex recall, dense render, Opus |
15 |
15/15 |
0/15 |
- |
| verbatim 12-char hex recall, dense render, Fable 5 |
15 |
- |
13/15 |
- |
- SWE-bench Lite 파일럿은 양쪽 모두 10/10이며 요청 크기는 −65%였음
- SWE-bench Pro는 ON 14/19, OFF 15/19이며 요청 크기는 −60%였음
- 판정은 18/19에서 일치함
- 한 건의 split은 복제 실행에서 3/3으로 다시 해결됨
- README는 이를 압축 문제가 아니라 실행 간 변동으로 취급함
- 표본 수가 작다는 caveat가 붙음
- GSM8K는 이미지화 상태에서 96%였지만 학습 데이터에 포함되어 있을 수 있어, README는 novel-number 평가를 앞세움
동작 방식
tool_result string ──► wrap at 1928px-wide columns ──► pack ~92,000 chars/page ──► PNG[]
- 프록시는 /v1/messages를 가로채고, 적합한 대량 입력을 image block으로 다시 씀
- 변환된 블록은 캐시 친화적으로 다시 삽입되며, 정적 prefix가 보존되어 prompt caching이 계속 동작함
- 1928×1928 이미지는 약 4,761 vision token을 쓰고 약 92,000자를 담음
- 텍스트가 이기려면 약 19자/token을 넘어야 하는데, Claude Code 트래픽은 N=391 기준 약 1.91로 측정됨
- 요청별 추정기가 이미지화 여부를 결정하며, 희소한 prose는 텍스트로 유지됨
- 이벤트는 ~/.pxpipe/events.jsonl에 기록됨
무엇을 압축하고 무엇을 그대로 두는가
- 압축 대상은 세 가지 입력 블록이며, 모두 수익성 게이트 뒤에 있음
- 약 6k자 이상의 토큰 밀집 tool_result 본문
- live tail 뒤쪽의 오래된 접힌 히스토리
- 정적 시스템 프롬프트와 도구 문서 slab
- 그대로 통과하는 항목도 명시되어 있음
- 사용자 메시지
- 최근 턴
- 모델 출력
- 희소한 prose
- 너무 작아서 이득이 없는 블록
- 허용 목록 밖 모델
- 기본 범위는 Fable 5와 GPT 5.6임
- Opus 4.8과 GPT 5.5는 이미지 콘텐츠 판독 성능이 나빠 대시보드나 PXPIPE_MODELS로 명시적으로 켜야 함
- PXPIPE_MODELS=off는 이미지화를 비활성화함
- GPT 경로에서는 도구 정의가 native JSON으로 유지되고 Anthropic cache_control 마커를 쓰지 않음
비용 계산 방식
- 헤드라인 절감률은 입력 슬라이스만이 아니라 전체 청구액 기준임
- 13,709개 요청 스냅샷에서 $100이 약 $41로 줄어 59% 절감으로 계산됨
- 이후 8,904개 압축 요청 trace에서는 약 70% 로 측정됨
- 압축된 요청만 따로 보면 72~74% 수준이지만, README는 이를 헤드라인으로 쓰지 않음
- 각 /v1/messages POST마다 원본 비압축 본문에 대해 무료 count_tokens counterfactual을 병렬 실행함
- 실제 청구 사용량은 Anthropic 응답의 usage block에서 읽음
- 원본과 실제 사용량은 같은 ~/.pxpipe/events.jsonl 행에 기록되어 turn-count나 run-to-run confound를 피함
- 달러 변환은 Fable 5 정가 비율을 사용함
- input ×1.0
- cache write ×1.25
- cache read ×0.1
- output ×5
- 캐시 가격은 양쪽에 동일하게 적용되어 캐시 할인은 절감으로 중복 계산되지 않음
라이브러리 사용
import { renderTextToPngs, transformAnthropicMessages } from "pxpipe";
const imgs = await renderTextToPngs(toolResultText); // RenderedImage[]
const { body, applied, info } = await transformAnthropicMessages({
body: requestBytes,
model: "claude-fable-5",
});
- 프록시 없이 라이브러리로도 사용할 수 있음
- options.keepSharp(block)은 특정 블록을 텍스트로 고정함
- options.emitRecoverable은 이미지화된 블록의 원본을 반환함
- 런타임은 Pure JS이며 Node와 edge/Workers를 지원함
- @napi-rs/canvas는 빌드 타임에만 사용됨
- 전체 API는 src/core/index.ts에 있음
실제 실패와 한계
- 몇 주간의 일상 사용 중 한 번, 이미지화된 채팅 히스토리에서 사람 이름을 회상하다가 확신 있게 틀린 사례가 있었음
- 코딩 세션은 편집 전 파일을 다시 읽기 때문에 이 실패 모드를 견딜 수 있지만, 순수 채팅 회상에는 같은 검증이 없음
- legibility audit에서는 렌더 페이지에서의 정확 문자열 회상을 측정함
- 밀집 identifier의 blind read는 최대 63%였음
- 모든 miss는 glyph-confusability matrix로 예측됐음
- API resample cap에 맞춰 page geometry를 제한하는 완화책이 적용됨
- SHA와 숫자 같은 정확 identifier는 텍스트로 함께 실음
- 제한 사항도 명시되어 있음
- 이미지 기반 verbatim recall은 신뢰하기 어려움
- 큰 요청은 전송 전 PNG 인코딩 지연이 추가됨
- ASCII/Latin-1은 잘 테스트됨
- CJK는 동작하지만 보수적으로 처리됨
개발과 로드맵
pnpm install && pnpm test
pnpm run build # regenerates dist/
- 개발 명령은 설치·테스트와 빌드로 구성됨
- 라이선스는 MIT임
- 로드맵은 가설로만 제시되며, 숫자와 표본 수가 붙지 않으면 claim으로 취급하지 않음
- 더 선명한 glyph rendering
- 이미지화된 bulk가 같은 1M window에서 유효 컨텍스트를 약 2배 늘릴 수 있는지
- 더 작은 active context가 긴 작업 정확도를 높이는지