AI

ลองใช้ Headroom บีบ context ก่อนส่งเข้า Claude Code

รีวิว Headroom ตัวบีบ context ก่อนส่งถึง LLM ตั้งแต่วิธีติดตั้ง ตัวเลขจริงที่วัดได้จากเครื่องตัวเอง ไปจนถึงข้อดีข้อเสียและเรื่องที่ควรรู้ก่อนเอาไปใช้จริง

Introduction

ใครใช้ Claude Code หรือ Codex เป็นหลักน่าจะเคยรู้สึกเหมือนกันครับ ว่า token มันไหลเร็วกว่าที่คิดเยอะ Agent อ่านไฟล์ที ยิง grep ที ดึง log ที ของพวกนี้เข้าไปกองอยู่ใน context แล้วรอบถัดไปก็ส่งไปใหม่อีก

ช่วงนี้ผมเลยลอง Headroom ดู มันเป็น proxy ที่คั่นอยู่ระหว่าง agent กับ provider แล้วพยายามบีบ context พวกนี้ให้เล็กลงก่อนส่งออก ตอนที่เขียนอยู่นี่ repo มีดาวเจ็ดหมื่นกว่า ทั้งที่เพิ่งสร้างเมื่อมกราคมปีนี้เอง

บทความนี้ไม่ได้เอา benchmark ใน README มาเล่าต่อนะครับ ผมรันมันจริงบนเครื่องตัวเองหนึ่งวัน ตัวเลขกับ output ที่แปะไว้ก๊อปมาจาก terminal ตรง ๆ มีตัดบางบรรทัดที่ไม่เกี่ยวออกเพื่อให้อ่านง่าย แต่ไม่ได้แก้ตัวเลข เวอร์ชันที่ใช้คือ v0.37.0 ต่อกับ Claude Code

แล้วผลที่ได้ก็ไม่ค่อยเหมือนที่ผมคิดไว้ตอนแรกเท่าไหร่

Headroom คืออะไร

ถ้าอธิบายแบบไม่ลงรายละเอียดเยอะ Headroom ก็คือชั้นบีบ context ที่รันอยู่ในเครื่องเราเอง ของที่ไหลผ่านมันมีทั้ง tool output, log, ไฟล์, RAG chunk แล้วก็ประวัติแชท

ข้างในไม่ได้มีตัวบีบตัวเดียว แต่แบ่งงานกันตามชนิดของข้อมูล มี SmartCrusher ไว้จัดการ JSON ก้อนใหญ่ ๆ มี CodeCompressor ที่อ่าน AST ของภาษาได้ 11 ภาษา (Python, JS/TS, Go, Rust, Java, C/C++, C#, PHP, Perl) แล้วก็มีโมเดลชื่อ kompress-v2-base ไว้บีบข้อความธรรมดา ตัวที่คอยดูว่าจะส่งงานให้ใครเรียกว่า ContentRouter

เรื่อง CodeCompressor มีอะไรให้พูดนิดนึงครับ เอกสารเขาเขียนไว้เองตรง ๆ ว่ามัน gate ไว้แน่นจน "แทบไม่ทำงานในสถานการณ์จริง" แล้วก็บอกด้วยว่าตั้งใจให้เป็นแบบนั้น มันจะเก็บโค้ดที่เพิ่งคุยกันกับโค้ดที่กำลังวิเคราะห์อยู่ไว้ครบ ไม่ไปแตะ ซึ่งก็เข้าใจได้ว่ากลัวทำของที่เรากำลังแก้อยู่เพี้ยน แต่ผลคือทั้งวันของผมมันยิงไปแค่ 3 ครั้งเอง

อย่างหนึ่งที่ผมชอบคือมัน ย้อนกลับได้ ของเดิมถูก cache ไว้ในเครื่อง แล้วโมเดลเรียก headroom_retrieve ขอตัวเต็มคืนได้ ไม่ใช่บีบแล้วหายไปเลย ตรงนี้เดี๋ยวจะกลับมาพูดอีกที เพราะพอใช้จริงแล้วมันสำคัญกว่าที่คิด

ใช้ได้ 4 แบบครับ เรียกเป็น library ในโค้ด, รันเป็น proxy, สั่ง wrap agent ให้เลย หรือเสียบเป็น MCP server ผมเลือกแบบ wrap เพราะง่ายสุด

วิธีการติดตั้ง

ตัว CLI มีเฉพาะใน PyPI นะครับ ส่วน headroom-ai บน npm เป็น TypeScript SDK อย่างเดียว ไม่มีคำสั่ง headroom ให้ใช้ ต้องมี Python 3.10 ขึ้นไป

uv tool install --python 3.13 "headroom-ai[all]"

ผมแนะนำให้ล็อก Python เป็น 3.13 ไปเลยครับ เพราะตัวคิดเงินของมันพึ่ง LiteLLM ซึ่งลงบน Python 3.14 ไม่ได้ ถ้าใช้ 3.14 ตัวเลข token ยังนับปกติ แต่ช่องเงินใน dashboard จะค้างอยู่ที่ $0.00

เช็คเวอร์ชันก่อน

headroom --version
headroom, version 0.37.0

จากนั้นสั่ง wrap ได้เลย คำสั่งเดียวจบ

headroom wrap claude

มันจะยก proxy ขึ้นที่ port 8787 แล้วเปิด Claude Code ให้โดยตั้ง ANTHROPIC_BASE_URL ชี้มาที่ proxy ให้เสร็จสรรพ (แถมตั้ง ENABLE_TOOL_SEARCH ให้ด้วย เดี๋ยวจะได้เห็นว่าตัวนี้แหละที่ประหยัดได้เยอะสุด) อยากเลิกใช้เมื่อไหร่ก็ headroom unwrap claude คืนค่าเดิมให้

มีคำสั่ง doctor ไว้ตรวจว่าต่อติดจริงไหมด้วย อันนี้ควรรันสักรอบครับ

headroom doctor
Headroom Doctor v0.37.0 · port 8787

┃ check       ┃ status ┃ summary                                     ┃
│ proxy       │ ✓ pass │ running at http://127.0.0.1:8787 (up 3m)    │
│ version     │ ✓ pass │ proxy matches installed v0.37.0             │
│ claude      │ ✓ pass │ routed via ...                              │
│ wrap_marker │ ✓ pass │ live wrap session (pid 84723)               │
│ shell env   │ ✓ pass │ routed via ANTHROPIC_BASE_URL               │
│ budget      │ ⚠ warn │ no budget configured — spend is unlimited   │

ตรง budget ที่ขึ้นเตือนมา ตั้งเพดานรายวันได้ครับ ถ้าใช้ท่า wrap แบบนี้ให้ส่งผ่าน env ไป

HEADROOM_BUDGET=10 headroom wrap claude

ส่วน flag --budget เป็นของคำสั่ง headroom proxy คนละตัวกัน ถ้ายก proxy เองอยู่แล้วค่อยใช้อันนั้น (แล้วอย่าไปยกซ้อน port 8787 ที่ wrap จองไว้นะ มันชนกัน)

ตัวเลขจริงหลังใช้ไปหนึ่งวัน

ตรงนี้แหละที่ผมว่าน่าสนใจที่สุด เพราะผลที่ได้ไม่ตรงกับที่คิดไว้ตอนแรกเลย

ดูแบบเร็ว ๆ ได้จากคำสั่ง headroom dashboard มันจะเปิดหน้าเว็บที่ 127.0.0.1:8787/dashboard ให้

ภาพนี้ผมถ่ายทีหลังนะครับ ตัวเลขเลยเดินไปจากที่จะยกมาข้างล่างอยู่บ้าง แต่รูปร่างของมันเหมือนเดิม สังเกตช่อง SAVINGS · TOOL SEARCH ที่แยกออกมาอยู่ต่างหากจาก TOKENS SAVED ไว้ก่อน เดี๋ยวจะได้เห็นว่าทำไมถึงต้องสนใจตรงนั้น

ส่วนถ้าอยากได้ตัวเลขดิบ ดึงจาก /stats ตรง ๆ ได้แบบนี้

curl -s 127.0.0.1:8787/stats | jq .summary.compression
{
  "requests_compressed": 129,
  "avg_compression_pct": 1.7,
  "best_compression_pct": 11.8,
  "best_detail": "15,316 → 13,505 tokens",
  "total_tokens_removed": 130497,
  "total_tokens_before": 10992312,
  "tool_schema_tokens_saved": 484226,
  "total_tokens_saved_all_layers": 614723
}

ตอนเห็นครั้งแรกผมก็งงนิดนึง เพราะตัว compression ที่ควรจะเป็นพระเอกของโปรเจกต์นี้ลดไป 130,497 token แต่ tool_schema_tokens_saved กลับลดไปถึง 484,226 token

สองอย่างนี้คนละเรื่องกันครับ ตัวหลังคือการไม่ส่ง schema ของ tool ทั้งกองไปหาโมเดลทุกรอบ แล้วค่อยโหลดเฉพาะตัวที่จะใช้แทน

พูดง่าย ๆ คือเกือบ 80% ของ token ที่ประหยัดได้ในงานผม ไม่ได้มาจาก compression เลย

ตลกดีตรงที่ /stats ของมันเองกลับไม่ตีราคาส่วนนี้เป็นเงินให้เลย

curl -s 127.0.0.1:8787/stats | jq -c '.savings.by_source'
[{ "source": "tool_search", "realized": true, "events": 79, "tokens": 484226, "usd": 0.0 }]

สี่แสนแปดหมื่น token แต่ช่อง usd ยังเป็น 0.0

เพราะงั้นถ้าดูแค่ตัวเลขเงินบน dashboard จะเข้าใจว่าประหยัดได้น้อยกว่าความเป็นจริง เพราะมันนับเงินจากฝั่ง compression แต่ไม่ได้รวม token ที่หายไปจาก tool schema

แล้วทำไม compression ของผมถึงได้น้อยขนาดนี้?

จริง ๆ README บอกไว้ค่อนข้างตรงอยู่แล้วว่า ถ้า input เป็นข้อความล้วนหรือข้อมูลที่แน่นอยู่แล้ว มันจะบีบได้ไม่เยอะ ส่วน benchmark 21-57% ที่เขาโชว์จะเป็น output ของ tool พวก code search, ไล่ incident, สำรวจ codebase หรือ triage issue ซึ่งมีของก้อนใหญ่ ๆ ให้บีบ

แต่วันที่ผมทดสอบ ผมนั่งเขียน markdown ภาษาไทยเป็นหลัก ก็เลยไม่มีอะไรให้มันบีบเท่าไหร่ครับ

อีกเรื่องที่ควรรู้คือเลข avg_compression_pct 1.7 เป็นค่าเฉลี่ยราย request ถ้าเอา token ที่ลดได้ทั้งหมดหารด้วยของที่ส่งไปทั้งหมด (130,497 จาก 10,992,312) จะเหลือราว 1.2% ครับ

ส่วนช่อง cache_savings_usd มันขึ้นตัวเลขใหญ่มาก (ของผมสะสมทั้งวันรวมทุกโปรเจกต์ไปร้อยกว่าเหรียญ) แต่อันนี้ ไม่ใช่ของที่ Headroom ประหยัดให้ นะครับ ไม่ต้องเชื่อผมก็ได้ ไปอ่านคำอธิบายที่มันเขียนไว้เองใน /stats เลย

Cost discount from provider prefix caching. Headroom's CacheAligner improves
hit rates; baseline caching is provider-native.

baseline caching is provider-native คือ prompt cache เป็นของฝั่ง Anthropic API ที่ Claude Code เรียกใช้อยู่แล้วตั้งแต่แรก หน้าที่ของ Headroom คือบีบเฉพาะส่วนที่เพิ่งเข้ามาใหม่ ไม่ไปแตะก้อนเดิม cache มันเลยยังใช้ได้อยู่ พูดให้ถูกคือ "ไม่ไปทำ cache พัง" มากกว่า "ประหยัดค่า cache ให้"

หลังใช้จริงแล้วชอบอะไรบ้าง

ติดตั้งแล้วจบ ไม่ต้องไปนั่งแก้โค้ดหรือแก้ config ของ agent เอง สั่ง headroom wrap claude ทีเดียวแล้วใช้ต่อได้เลย ถอนก็คำสั่งเดียว

ลด tool schema ได้จริงและเยอะ อันนี้เห็นผลชัดสุดในงานผม สี่แสนกว่า token ในวันเดียว และอย่างที่บอกไปว่ามันไม่ยอมคิดเป็นเงินให้ด้วย เลยเป็นกำไรที่ไม่โผล่ในรายงาน

ของเดิมย้อนกลับได้ ไม่ได้บีบทิ้งอย่างเดียว มี headroom_retrieve ให้ขอตัวเต็มคืน

ช้าลงบ้างแต่ไม่ถึงกับรู้สึก อันนี้ผมวัดเองจาก /stats ได้ค่า overhead เฉลี่ยราว ๆ 100 ms ต่อ request เทียบกับเวลารอโมเดลตอบจริงที่หลักสิบวินาที ก็ถือว่าไม่ได้เป็นภาระอะไร (README เคลมไว้ที่ 0.21 ms แต่นั่นคือ path ของ JSON ส่วนงานเขียนข้อความมันวิ่งเข้าตัวบีบที่เป็น ML ซึ่งช้ากว่ากันเยอะ ของผมหนักสุดที่เจอคือ 4 วินาที)

มีเครื่องมือให้ดูตัวเลข ทั้ง doctor, dashboard, กับ /stats ไม่ต้องเดาว่ามันทำงานอยู่หรือเปล่า

จุดที่ผมติดจริง ๆ ตอนใช้งาน

ข้อแรกนี่สำคัญสุด: มันบีบ tool output จนอ่านได้ไม่ครบ

อันนี้เจอตอนเขียนบทความนี้เองเลยครับ ผมให้ agent ไป grep หาคำในไฟล์ README ตัวผมที่นั่งดูอยู่หน้า terminal เห็น output ครบทุกบรรทัดปกติดี แต่ของที่ส่งไปถึงตัวโมเดลจริง ๆ หน้าตาเป็นแบบนี้

328:you
330:preserved. vscode-claude`

มันเกือบสรุปว่าไม่เจออะไรแล้ว พอสั่งให้เรียก headroom_retrieve ขอตัวเต็มคืนมาดู ของจริงคือแบบนี้

328:you use the Claude Code panel; the dashboard or proxy log printed at startup
330:preserved. `Ctrl+C` stops the proxy; `headroom unwrap vscode-claude` restores the

คือตัดกลางประโยคไปเลย

ที่ผมว่าน่ากลัวคือคนนั่งหน้าจอไม่มีทางรู้ เพราะเราเห็นของครบ ตัวที่อ่านไม่ครบคือโมเดล สัญญาณเดียวที่พอสังเกตได้คือบรรทัดเล็ก ๆ ที่มันแปะไว้ท้าย output

[276 words compressed to 174 (from 6 source lines). Retrieve more: hash=24aa7b12]

ย้ำว่าของเดิมยังอยู่ ขอคืนได้ครับ แต่ปัญหาคือ ต้องรู้ตัวก่อนว่าต้องขอคืน ถ้า agent ไม่ทันสังเกตว่า output ขาดไป ก็ตัดสินใจจากของที่ไม่ครบไปแล้ว งานไหนที่ต้องอ่านทุกบรรทัดจริง ๆ เช่นไล่ log หาสาเหตุ หรือ audit ของที่เกี่ยวกับความปลอดภัย ผมว่าต้องระวังตรงนี้มาก ๆ

มันแถม Serena มาให้ด้วย

ตาม README บอกไว้ว่าพอสั่ง wrap มันจะลง Serena (ตัวช่วย navigate โค้ดแบบเข้าใจ symbol) ให้เลย แล้วลงทะเบียนไว้ที่ user scope คือใน ~/.claude.json ไม่ได้อยู่แค่โปรเจกต์ที่เรา wrap เท่ากับเปิดโปรเจกต์อื่นก็จะเจอมันติดไปด้วย จนกว่าจะสั่ง unwrap

ส่วนใครที่มี Serena ของตัวเองอยู่ก่อนแล้วไม่ต้องกังวลครับ ผมไปเปิด ~/.claude.json ดู config เดิมของผมยังอยู่ครบ ไม่โดนทับ (ของผม pin เวอร์ชันไว้เองผ่าน uvx มันก็ยังเป็นอันเดิมเป๊ะ) ถ้าไม่อยากได้เลยก็ใส่ --code-memory none ตอน wrap ได้ครับ

แต่มันแอบแก้ของให้เราหลายอย่างกว่าที่คิด

ต่อจากข้อบน ผมบอกไปตอนข้อดีว่า "ไม่ต้องแก้ config เอง" ซึ่งก็จริงในแง่ที่เราไม่ต้องลงมือเอง แต่ไม่ได้แปลว่าไม่มีอะไรถูกแก้นะครับ ของผมมันเพิ่ม MCP server ชื่อ headroom เข้าไปใน ~/.claude.json ที่ user scope แล้วก็โปรยไฟล์ไว้ในโปรเจกต์อีกชุด ทั้ง .claude/.headroom_wrap_marker.json, .headroom_wrap_owners.json กับโฟลเดอร์ .headroom/ ที่มี database อยู่ 3 ไฟล์

ของพวกนี้โผล่ใน git status เป็น untracked หมด ใครจะใช้ก็แนะนำให้ใส่ .gitignore ไว้ก่อนเลยครับ ไม่งั้นเผลอ commit ติดไปแน่นอน

.headroom/
.claude/.headroom_wrap_*

ส่ง telemetry ออกไปตั้งแต่แรก ค่า default คือเปิด เขาบอกว่าส่งแค่อัตราการบีบ, ชื่อ provider/model, OS, สถาปัตยกรรม ไม่ส่ง prompt ไม่ส่งโค้ด ไม่ส่ง path ถ้าไม่อยากให้ส่งก็ปิดได้ด้วย HEADROOM_BEACON=off, DO_NOT_TRACK=1 หรือ --offline (ของผมปิดอยู่แล้วเพราะตั้ง DO_NOT_TRACK ไว้ตั้งแต่แรก)

ฟีเจอร์บางอย่างของ Claude Code จะใช้ไม่ได้ เพราะพอ ANTHROPIC_BASE_URL ชี้ไปที่ proxy ตัว Claude Code จะปิด /remote-control ให้เอง แล้ว context 1M token ก็ไม่ได้มาให้อัตโนมัติ ต้องสั่ง headroom wrap claude --1m เอง ส่วน Claude Desktop ยังไม่รองรับ มันเขียนทับ base URL ทิ้ง

ออกเวอร์ชันถี่มาก 198 เวอร์ชันบน PyPI ในเวลา 7 เดือนครึ่ง เฉลี่ยเกือบวันละตัว ข้อดีคือแก้บั๊กไว แต่ก็แปลว่าของมันขยับเร็ว ใครไม่ชอบไล่ตามอาจจะเหนื่อย

สรุป

ก่อนลอง ผมคิดว่าเหตุผลหลักที่จะใช้ Headroom คือเอามาบีบ context ให้เล็กลง

พอลองจริงหนึ่งวัน กลายเป็นว่าส่วน compression ลด token ในงานผมได้ไม่เยอะเลย ของที่ช่วยหนักกว่าดันเป็น tool search ซึ่งลดไปสี่แสนกว่า token โดยที่ dashboard ยังไม่ได้คิดออกมาเป็นเงินให้ด้วยซ้ำ

แต่สิ่งที่ทำให้ผมลังเลกลับไม่ใช่เรื่องว่ามันประหยัดได้กี่เปอร์เซ็นต์ เป็นเรื่อง output แหว่งมากกว่า

ของเดิมไม่ได้หายนะครับ เรียกคืนได้ แต่เราต้องรู้ก่อนว่ามีอะไรหายถึงจะเรียกคืน และตรงนี้แหละที่ผมว่าน่าคิด เพราะคนที่นั่งหน้า terminal เห็น output ครบ คนที่เห็นของไม่ครบคือโมเดล

ถ้างานเป็นพวก API response ใหญ่ ๆ, JSON, code search หรือ log ยาว ๆ Headroom น่าจะได้ทำงานที่มันถนัดกว่าวันที่ผมทดสอบเยอะ ส่วนงานเขียนหรือแก้ไฟล์ทีละไฟล์แบบที่ผมทำวันนั้น compression แทบไม่ได้ช่วยอะไร

ตอนนี้ผมยังเปิดใช้อยู่ครับ อย่างน้อยก็อยากเก็บตัวเลขต่ออีกหน่อย แต่กับงานที่ข้อมูลทุกบรรทัดสำคัญ ผมคงไม่ปล่อยให้มันบีบแล้วเชื่อ output ที่ได้ทันที

ใครอยากลองก็ลองได้ครับ ติดตั้งง่าย ถอนง่าย แค่แนะนำให้รู้ก่อนว่า wrap ทำอะไรกับเครื่องเราบ้าง แล้วก็อย่าลืม .gitignore ไฟล์ที่มันสร้างไว้ด้วย

References

Related Articles

N8N วิธีการ Setup | Part 1
AI

N8N วิธีการ Setup | Part 1

วิธี self-hosted N8N ด้วย docker compose อย่างง่าย พร้อมต่อ PGVector ไว้ใช้กับงาน LLM ในภายหลัง
N8N วิธีการการใช้งานเบื้องต้น | Part 2
AI

N8N วิธีการการใช้งานเบื้องต้น | Part 2

พาสร้าง workflow แรกใน N8N ด้วยโจทย์ดึง URLs ของ domain ที่ต้องการจาก Wayback Machine
Ollama มี UI ให้ใช้แล้ว
AI

Ollama มี UI ให้ใช้แล้ว

Ollama ออก Desktop Application พร้อม Chat UI มาให้ใช้แล้ว ไม่ต้องรัน model ผ่าน cli อีกต่อไป

Copyright © 2026