원클릭으로
cline-fix-volatile-msg
Stop Cline from burning a cache breakpoint on the volatile current user message every turn.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Stop Cline from burning a cache breakpoint on the volatile current user message every turn.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | cline-fix-volatile-msg |
| description | Stop Cline from burning a cache breakpoint on the volatile current user message every turn. |
| target_harness | Cline |
| target_repo | cline/cline |
| target_files | ["src/core/api/transform/anthropic-format.ts"] |
| target_commit | 65e9727c (verify current at apply time) |
| estimated_savings | ~30% wasted cache write premium eliminated per turn |
src/core/api/transform/anthropic-format.ts in cline/cline.
Permalink: https://github.com/cline/cline/blob/65e9727c/src/core/api/transform/anthropic-format.ts
Cline marks the LAST TWO USER MESSAGES with cache_control: ephemeral.
The last user message is the CURRENT user turn — it's different on
every request by definition. Caching content that changes every
request pays the 1.25x write premium on those tokens every turn for
zero cache reads. Net result: one of Cline's 3 breakpoints is burned
producing nothing.
You can confirm on the wire: in two consecutive identical-prompt
turns, the response usage.cache_creation_input_tokens stays > 0 on
turn 2 instead of dropping to ~0.
Replace the "last 2 user messages" logic with "last STABLE message" (typically the previous assistant turn or tool_result):
--- a/src/core/api/transform/anthropic-format.ts
+++ b/src/core/api/transform/anthropic-format.ts
@@
- const userMsgIndices = clineMessages.reduce((acc, msg, index) => {
- if (msg.role === "user") acc.push(index)
- return acc
- }, [] as number[])
- const lastUserMsgIndex = userMsgIndices.at(-1)
- const secondLastMsgUserIndex = userMsgIndices.at(-2)
+ // Cache the LAST STABLE message — the message BEFORE the current
+ // user turn. The current user turn changes every request and would
+ // pay the 1.25x cache-write premium for zero subsequent reads.
+ // The previous turn (assistant message or tool_result) is stable
+ // across the request → response cycle.
+ const lastStableIdx = clineMessages.length >= 2
+ ? clineMessages.length - 2
+ : -1
@@
- if (supportCache && (index === lastUserMsgIndex || index === secondLastMsgUserIndex)) {
+ if (supportCache && index === lastStableIdx) {
return addCacheControl(anthropicMsg)
}
This frees one breakpoint. Optionally use that freed breakpoint to
cache the tools array independently — see audits/cline.md for the
extended pattern.
mitmdump -p 8090 -w /tmp/cline.flowhttp://127.0.0.1:8090)usage:
cache_creation_input_tokens > 0 every turn (bug)cache_creation_input_tokens ≈ 0, cache_read_input_tokens covers system + tools + previous turnHit rate (turn 2): should be ≥80% of input tokens.
See docs/gotchas.md #1 ("Putting cache_control
on volatile content"). Anthropic caches the entire prefix up to and
including the marked block; marking a block that mutates per request
means the cache is invalidated every request.
Full audit: audits/cline.md.
Aider uses 5min TTL by default and works around long pauses with keepalive pings. Wire up the 1h TTL beta instead.
Aider's --cache-prompts is off by default. Flip it on for supported models.
Cline OpenAI native provider sends no prompt_cache_key. Add a stable per-task key so cached_tokens stops being zero.
Cline's system prompt includes a timestamp that may be recomputed per request, invalidating the system-prompt cache.
Continue's prompt caching is opt-in via config and off by default. Flip the default to systemAndTools.
Continue inherits the Cline-family volatile-message cache bug. Same fix shape.