Claude Code từ zero đến thành thạo · Phần 3 — Context window và prompt caching
Ràng buộc lớn nhất của mọi phiên dài: cái gì nạp vào context và lúc nào, cái gì sống sót qua compaction, khi nào dùng /compact hay /clear — và vì sao đổi model giữa chừng khiến lượt sau chậm hẳn.
Phần 2 nói agent loop chạy thế nào. Phần này nói về cái hộp mà loop chạy bên trong: context window.
Đây là ràng buộc chi phối mọi phiên làm việc dài. Hiểu nó, bạn sẽ biết vì sao Claude “quên” chỉ dẫn bạn đưa từ đầu phiên, vì sao có lượt trả lời chậm hẳn không rõ lý do, và vì sao lời khuyên “cứ chat tiếp trong một phiên cho tiện” là lời khuyên tệ.
Context window chứa gì
Context window giữ mọi thứ Claude biết về phiên hiện tại: chỉ dẫn của bạn, file nó đọc, phản hồi của chính nó, và cả nội dung không bao giờ hiện trong terminal của bạn.
Trước khi bạn gõ chữ nào, những thứ này đã nạp sẵn:
| Thành phần | Ghi chú |
|---|---|
| System prompt | Chỉ dẫn cốt lõi về hành vi, cách dùng tool, cách định dạng phản hồi. Luôn nạp đầu tiên. Bạn không bao giờ thấy nó |
Auto memory (MEMORY.md) | Ghi chú Claude tự viết cho mình từ các phiên trước: lệnh build đã học, pattern đã nhận ra, lỗi cần tránh. Chỉ 200 dòng hoặc 25KB đầu được nạp |
CLAUDE.md và rule không gắn path | Chỉ dẫn bạn viết cho project |
| Environment info | Thư mục làm việc, platform, shell, OS version, có phải git repo không. Branch, status và commit gần đây nạp thành một khối riêng ở cuối system prompt |
| Tên tool MCP | Mặc định schema đầy đủ được hoãn lại, chỉ tên tool tốn context. Claude nạp schema cụ thể khi cần qua tool search |
| Mô tả skill | Chỉ phần mô tả. Nội dung skill chỉ nạp khi skill được dùng |
Ngoài ra, thiết lập riêng của bạn có thể thêm nữa — ví dụ một output style hoặc chuỗi truyền qua --append-system-prompt, cả hai đều đi vào system prompt theo cùng một đường.
Khi Claude làm việc, mỗi lần đọc file lại cộng thêm vào context. Path-scoped rule tự nạp kèm khi file khớp được đọc, và PostToolUse hook chạy sau mỗi lần sửa.
Ngược lại, subagent xử lý việc trong context window riêng của nó — các lượt đọc file lớn nằm ở đó, không nằm ở chỗ bạn. Chỉ bản tóm tắt và một phần metadata nhỏ quay về.
Cái gì sống sót qua compaction
Khi phiên dài, Claude Code tóm tắt lịch sử hội thoại cho vừa context window. Số phận của các chỉ dẫn phụ thuộc cách chúng được nạp:
| Cơ chế | Sau compaction |
|---|---|
| System prompt và output style | Không đổi; chúng không thuộc lịch sử tin nhắn |
CLAUDE.md ở gốc project và rule không gắn path | Được nạp lại từ đĩa |
| Auto memory | Được nạp lại từ đĩa |
Rule có frontmatter paths: | Mất, tới khi một file khớp được đọc lại |
CLAUDE.md lồng trong thư mục con | Mất, tới khi một file trong thư mục đó được đọc lại |
| Nội dung skill đã gọi | Nạp lại, giới hạn 5.000 token mỗi skill và 25.000 token tổng; cũ nhất bị bỏ trước |
| Hook | Không áp dụng; hook chạy như code, không phải context |
Hai hệ quả thực dụng rút ra từ bảng này:
Nếu một rule bắt buộc phải sống qua compaction, bỏ frontmatter paths: của nó đi, hoặc chuyển nội dung lên CLAUDE.md ở gốc project.
Nội dung skill bị cắt cụt để vừa hạn mức, và phần được giữ là phần đầu file — nên hãy đặt chỉ dẫn quan trọng nhất lên đầu SKILL.md.
Một chi tiết nữa: request tóm tắt kế thừa cấu hình extended thinking của phiên bạn, nên nó suy luận có thinking khi phiên bạn bật thinking. Điều đó chỉ ảnh hưởng cách bản tóm tắt được tạo ra; thiết lập phiên của bạn không đổi sau đó.
Khi context đầy
Claude Code tự compact khi bạn tiến gần giới hạn, nên context đầy không kết thúc phiên của bạn. Nó dọn output của tool cũ trước, rồi mới tóm tắt hội thoại nếu cần. Yêu cầu của bạn và các đoạn code quan trọng được giữ; chỉ dẫn chi tiết từ đầu hội thoại có thể mất.
Đây là lý do lời khuyên “đặt luật lâu dài vào
CLAUDE.md” không phải sở thích cá nhân mà là hệ quả kỹ thuật: chỉ dẫn nói trong chat sẽ bay mất, chỉ dẫn trongCLAUDE.mdđược nạp lại từ đĩa.
Bốn cách chủ động, làm trước khi vòng tự động chạy:
- Compact có trọng tâm — chạy
/compactkèm chỉ dẫn, ví dụ/compact focus on the auth bug fix, trước khi bắt đầu task dài mới. Bản tóm tắt giữ thứ bạn chọn thay vì thứ vòng tự động đoán là quan trọng. - Compact sớm hơn — chạy
/autocompactkèm số token, ví dụ/autocompact 500k, để đặt mức đầy trước khi vòng tự động chạy. - Xoá giữa các task — chạy
/clearkhi chuyển sang việc không liên quan. Hội thoại cũ chèn chỗ của file bạn cần tiếp theo và tốn token ở mọi tin nhắn sau đó. - Đẩy phần đọc lớn cho subagent — gửi việc nghiên cứu cho subagent để nội dung file nằm trong context của nó, không phải của bạn.
Bạn cũng điều khiển được thứ được giữ lại khi compact bằng cách thêm mục “Compact Instructions” vào CLAUDE.md.
Trường hợp hỏng: nếu một file hoặc output tool lớn tới mức context đầy lại ngay sau mỗi lần tóm tắt, Claude Code dừng auto-compact sau vài lần thử và báo lỗi thay vì lặp vô hạn.
Cần cửa sổ lớn hơn thay vì hội thoại ngắn hơn? Fable 5, Sonnet 5, Opus 4.6 trở lên và Sonnet 4.6 hỗ trợ context window 1 triệu token. Sonnet 5 chạy ở mức 1M mà không cần chọn biến thể [1m]. Compaction vẫn hoạt động y hệt ở giới hạn lớn hơn.
Kiểm tra phiên của chính bạn: chạy /context để xem phân rã theo nhóm kèm gợi ý tối ưu, gồm cả danh sách file CLAUDE.md và auto memory nào đã nạp. Chạy /memory để mở và sửa chúng. Chạy /mcp để xem chi phí context theo từng MCP server.
Prompt caching: vì sao có lượt chậm bất thường
Phần trên nói về dung lượng. Phần này nói về tốc độ và chi phí — và cả hai đến từ cùng một cơ chế.
Mỗi lần bạn gửi một tin nhắn, Claude Code tạo một API request mới. Model không nhớ gì giữa các request, nên Claude Code gửi lại toàn bộ context: system prompt, ngữ cảnh project, mọi tin nhắn và kết quả tool trước đó, cộng tin nhắn mới của bạn. Nội dung mới được nối vào cuối, nghĩa là phần lớn mỗi request giống hệt request trước.
Prompt caching là cách API tránh xử lý lại phần không đổi. API so khớp phần đầu của mỗi request — gọi là prefix — với nội dung nó vừa xử lý gần đây.
Điểm mấu chốt: so khớp là chính xác tuyệt đối. Một thay đổi ở bất kỳ đâu trong prefix sẽ làm mọi thứ phía sau nó phải tính lại. Không có cache theo từng file hay từng đoạn.
Để tận dụng prefix matching, Claude Code sắp xếp request theo thứ tự ít-đổi-trước:
| Tầng | Nội dung | Đổi khi |
|---|---|---|
| System prompt | Chỉ dẫn cốt lõi, định nghĩa tool, output style | Tập tool định nghĩa đổi, hoặc Claude Code được nâng cấp |
| Project context | CLAUDE.md, auto memory, rule không gắn path | Phiên bắt đầu, hoặc sau /clear và /compact |
| Conversation | Tin nhắn của bạn, phản hồi của Claude, kết quả tool | Mỗi lượt |
Thay đổi ở tầng conversation vẫn giữ nguyên cache của system prompt và project context. Thay đổi ở system prompt thì huỷ toàn bộ, vì mọi nội dung phía sau giờ nằm sau một prefix khác.
Hai thiết lập không nằm trong văn bản prompt nhưng vẫn thuộc cache key:
- Model — mỗi model có cache riêng. Đổi model tính lại toàn bộ request dù nội dung y hệt.
- Effort level — mỗi mức effort có cache riêng cho cùng một model. Đổi giữa phiên tính lại toàn bộ, và Claude Code hỏi xác nhận trước khi áp dụng.
Tám hành động huỷ cache
Mỗi hành động dưới đây gây ra một lượt chậm và tốn hơn, sau đó prefix mới được cache lại:
- Đổi model (
/model). Thiết lậpopusplangiải về Opus trong plan mode và Sonnet khi thực thi — nên mỗi lần bật/tắt plan mode là một lần đổi model. - Đổi effort level (
/effort). - Bật fast mode — thêm một request header thuộc cache key. Chi phí chỉ phát sinh một lần mỗi hội thoại; tắt rồi bật lại sau đó vẫn giữ cache. Bật đầu phiên rẻ hơn bật giữa một phiên dài.
- Nối hoặc ngắt MCP server — chỉ khi tool của nó nạp thẳng vào prefix. Mặc định tool được hoãn qua tool search, khi đó server nối/ngắt chỉ nối thêm nội dung mới và không đụng phần đã cache.
- Bật hoặc tắt plugin — chỉ khi plugin cung cấp MCP server. Skill, command, agent, hook, LSP server, monitor và theme không bao giờ huỷ cache.
- Deny nguyên một tool — thêm tên tool trần như
BashhayWebFetchvào deny rule sẽ gỡ hẳn tool đó khỏi context. Deny có phạm vi nhưBash(rm *), và mọi allow/ask rule, không đụng cache. - Compact hội thoại — theo thiết kế, vì lịch sử mới ngắn hơn và không chung prefix với cái cũ.
- Nâng cấp Claude Code — bản mới thường đổi system prompt hoặc định nghĩa tool.
Cẩn thận với trường hợp cuối: resume một phiên sau khi nâng cấp sẽ xử lý lại toàn bộ lịch sử không cache. Chi phí tỉ lệ với độ dài hội thoại, nên lượt đầu quay lại một phiên dài có thể là request đắt nhất bạn từng gửi.
Tám hành động giữ được cache
Nhóm này hoặc chỉ nối vào cuối hội thoại, hoặc không đụng request:
- Sửa file trong repo — nội dung file chỉ vào context khi Claude đọc. Sửa file Claude đã đọc không sửa ngược lượt đọc cũ trong lịch sử; Claude Code chỉ nối thêm một
<system-reminder>báo file đã đổi. - Sửa
CLAUDE.mdgiữa phiên — không huỷ cache, nhưng cũng không có hiệu lực. Claude tiếp tục dùng bản đã nạp lúc bắt đầu phiên. Nội dung mới nạp ở lần/clear,/compacthoặc khởi động lại kế tiếp. - Đổi output style — y hệt: không huỷ cache, cũng không áp dụng cho tới
/clearhoặc restart. - Đổi permission mode — an toàn với cache. Ngoại lệ là plan mode với thiết lập
opusplan, vì nó kéo theo đổi model. - Gọi skill và command — chúng chèn chỉ dẫn dưới dạng tin nhắn user tại điểm gọi. Không có gì trước đó thay đổi.
- Chạy
/recap— nối bản tóm tắt như output lệnh, không thay lịch sử tin nhắn. - Rewind hội thoại (
/rewind) — cắt lịch sử về lượt trước đó. Phần còn lại đúng bằng nội dung cache đã dựng ở thời điểm ấy, nên request kế tiếp trúng cache cũ. - Sinh subagent — subagent có prompt và tool riêng nên không đọc cache của cha, nhưng cache của cha cũng không bị đụng.
Đây là mẹo đáng nhớ nhất: nếu bạn đã đi sai đường và muốn bỏ hẳn hướng đó,
/rewindtốt hơn/compact. Rewind cắt về một prefix đã được cache sẵn; compact dựng một prefix hoàn toàn mới.
Cache sống được bao lâu
Prefix đã cache hết hạn sau một khoảng không hoạt động. Mỗi request trúng cache đặt lại đồng hồ, nên cache còn ấm chừng nào bạn còn làm việc. Sau một quãng nghỉ đủ dài, request kế tiếp tính lại toàn bộ — đó là lý do lượt đầu sau khi rời bàn đi cà phê thấy chậm rõ.
API có hai mức TTL: 5 phút và 1 giờ. Claude Code chọn giúp bạn theo cách bạn xác thực:
- Trên Claude subscription — tự động yêu cầu TTL 1 giờ. Nếu bạn đã vượt hạn mức và đang dùng usage credit, Claude Code tự hạ về 5 phút vì cache write ở mức 1 giờ đắt hơn; muốn giữ 1 giờ thì set
ENABLE_PROMPT_CACHING_1H=1. - Trên API key hoặc third-party provider — mặc định 5 phút vì bạn trả theo token. Bật 1 giờ bằng cùng biến trên.
- Ép về 5 phút trong mọi trường hợp:
FORCE_PROMPT_CACHING_5M=1.
Cache có phạm vi tới đâu
Trong Claude Code, cache thực tế gắn với một máy và một thư mục. System prompt nhúng thư mục làm việc, platform, shell, OS version và đường dẫn auto memory — nên hai phiên ở hai thư mục khác nhau dựng prefix khác nhau và không dùng chung cache. Điều đó bao gồm cả các worktree của cùng một repo.
Các phiên chạy song song trong cùng một thư mục thì dựng prefix khớp nhau và đọc cache của nhau. Phiên chạy nối tiếp chỉ chung prefix khi ảnh chụp git status lúc khởi động khớp, vì system prompt cũng nắm branch và commit gần đây.
Kiểm tra hiệu quả cache
API báo hai con số token trong mọi response:
| Trường | Ý nghĩa |
|---|---|
cache_creation_input_tokens | Token được ghi vào cache ở lượt này, tính theo giá cache write |
cache_read_input_tokens | Token đọc từ cache ở lượt này, tính khoảng 10% giá input tiêu chuẩn |
Tỉ lệ read trên creation cao nghĩa là cache đang chạy tốt. Nếu creation cứ cao lượt này qua lượt khác, có thứ gì đó trong prefix của bạn đang thay đổi — tra lại danh sách tám hành động huỷ cache ở trên. Cách theo dõi trực tiếp nhất là một script statusline đọc object current_usage.
Ba quy tắc rút gọn
Nếu bạn chỉ nhớ được ba điều từ bài này:
- Chọn model và effort ở đầu phiên, rồi đừng đổi giữa task. Để dành
/compactcho quãng nghỉ tự nhiên giữa các task. - Luật lâu dài viết vào
CLAUDE.md, đừng nói trong chat — chat sẽ bị compaction tóm tắt mất,CLAUDE.mdđược nạp lại từ đĩa. /clearkhi đổi việc,/rewindkhi đi sai đường,/compactkhi cần giữ mạch nhưng hết chỗ. Ba lệnh, ba tình huống khác nhau.
Nguồn
Docs gốc cập nhật thường xuyên; khi có mâu thuẫn, tin bản tiếng Anh.