Package Exports
- agent-cache-optimizer
- agent-cache-optimizer/core
- agent-cache-optimizer/heuristics
- agent-cache-optimizer/splitting
Readme
π§ agent-cache-optimizer
Content-agnostic KV cache optimizer for LLM CLI agents
Boost prompt cache hit rates by 40β88%.
Zero config. Zero content knowledge. Works with any agent framework.
π― The Problem
LLM providers (DeepSeek, Anthropic, OpenAI, Google) use prefix-match KV caching: if your prompt starts with the same bytes as a previous request, the computed key-value states are reused β cache hits cost near-zero tokens.
But every CLI agent puts dynamic content at the FRONT of the system prompt:
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β β‘ HANDOFF block (changes every session) β β Cache BUSTED
β β‘ REMEMBER / MEMORY (changes throughout day) β β Cache BUSTED
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
CLAUDE.md (changes weekly) β β Never reached
β β
Agent definitions (static) β β Never reached
β β
MCP / Skills / Tools (static) β β Never reached
β β‘ currentDate (changes daily) β
β β‘ Memory injection (changes per query) β
βββββββββββββββββββββββββββββββββββββββββββββββββββResult: 0% cache reuse across sessions. Every session recomputes the entire system prompt from scratch, even though 70-90% of it hasn't changed.
π‘ The Fix
agent-cache-optimizer reorders the system prompt at runtime:
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
CLAUDE.md (stable) β Cached β
β β
Agent definitions (stable) β Cached β
β β
MCP / Skills / Tools β Cached β
β β
Tool definitions β Cached β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β‘ currentDate β
β β‘ HANDOFF / REMEMBER / MEMORY β
β β‘ Memory injection β
βββββββββββββββββββββββββββββββββββββββββββββββββββStable blocks first β prefix survives session changes β 40-88% cache reuse.
π Install
{
"plugin": ["agent-cache-optimizer"]
}Add to ~/.config/opencode/opencode.json. OpenCode auto-installs from npm on next startup.
# Or via CLI
opencode plugin agent-cache-optimizer --globalRestart OpenCode β done. Zero config. Works immediately for DeepSeek, Anthropic, OpenAI, and any provider with prefix-match KV caching.
Verify
# Check plugin is loaded
opencode debug config | grep agent-cache-optimizer
# Watch reorder activity in real time
tail -f ~/.cache/opencode/agent-cache-optimizer/diag.logStatus dashboard
agent-cache-optimizer status # text dashboard
agent-cache-optimizer status --json # JSON for scriptsOutput
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β KV Cache Optimizer Status β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β Status: ACTIVE β
β Mode: orchestrator=WARM oracle=COLD β
β Uptime: 2026-06-24T15:30 β 2026-06-24T16:45 β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β Agent Obs Positions Stable β
β orchestrator 12 11 8/11 β
β oracle 3 5 3/5 β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β Estimated cache reuse: ~73% of system prompt β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββπ How It Works
1. Observe (content-agnostic)
The plugin never reads the content of your prompts. It only hashes each system block and tracks which hashes stay the same vs change across calls.
Session 1: [H1, CLAUDE-A, AGENT-X, TOOLS-V1, DATE-1, MEM-1]
Session 2: [H2, CLAUDE-A, AGENT-X, TOOLS-V1, DATE-2, MEM-2]
Session 3: [H3, CLAUDE-A, AGENT-X, TOOLS-V1, DATE-2, MEM-3]
After 3 observations:
H1/H2/H3 at position 0 change every time β score 0.0 (dynamic)
CLAUDE-A at position 1 never changes β score 1.0 (stable)
AGENT-X at position 2 never changes β score 1.0 (stable)
...2. Classify & Reorder
ββββββββββββ
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β STABLE β
β HANDOFF β β CLAUDE β β TOOLS β β MEMORY β βββΆ β CLAUDE β
β (dynamic)β β (stable) β β (stable) β β (dynamic)β β TOOLS β
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ
β‘ β
β
β‘ β DYNAMIC β
β HANDOFF β
β MEMORY β
ββββββββββββ3. Two-phase decision
| Phase | Trigger | Method |
|---|---|---|
| Cold start | First 2 calls per agent | Universal position/size/structure heuristics |
| Warm | 3+ calls | Hash-based stability scores |
The cold-start heuristics use only structural signals (position, size, delimiters, line density) β no keyword matching, no config awareness. This means the plugin works immediately with any agent setup.
π Benchmarks
Tested on a realistic OpenCode orchestrator prompt (~25KB system prompt):
| Scenario | Cacheable prefix | Improvement |
|---|---|---|
| Original (no reorder) | 0 KB (0%) | β |
| Cold start (heuristics) | 21.8 KB (88%) | +88% |
| Warm (hash-based, 3+ sessions) | 21.8 KB (88%) | +88% |
Per-agent results (3 different agent configurations):
| Agent | Blocks | Stable | Dynamic | Cacheable |
|---|---|---|---|---|
| orchestrator | 11 | 8 | 3 | 88% |
| oracle | 6 | 3 | 3 | 88% |
| fixer | 6 | 3 | 3 | 90% |
π Supported Platforms
| Platform | Status | Adapter |
|---|---|---|
| OpenCode | β Plugin | src/index.ts (native) |
| Claude Code | π Guidelines | adapters/claude-code.md |
| Codex | π Planned | Adapt OpenCode plugin |
| Gemini CLI | π Planned | Google context caching |
π§© API (standalone usage)
The core engine is CLI-agnostic. Use it in any project:
import { emptyDB, updateDB, classify } from "agent-cache-optimizer"
// Track stability
let db = emptyDB()
const blocks = ["HANDOFF...", "CLAUDE.md...", "AGENT...", "MEMORY..."]
// Classify and reorder
const classified = classify(blocks, db)
const optimized = [...classified.stable, ...classified.unknown, ...classified.dynamic]
// Update for next call
db = updateDB(db, optimized)π Project Structure
agent-cache-optimizer/
βββ src/
β βββ index.ts # OpenCode plugin entry point
β βββ core.ts # Hash-tracking engine (CLI-agnostic)
β βββ heuristics.ts # Cold-start position/size classifiers
β βββ splitting.ts # Large block splitter (>4KB)
β βββ types.ts # TypeScript types
βββ adapters/
β βββ claude-code.md # Claude Code optimization guide
βββ bin/
β βββ aco # CLI: agent-cache-optimizer status
βββ scripts/
β βββ cache-status.sh # Status dashboard (legacy)
β βββ check-cache-friendly.sh # Config audit tool
βββ docs/
β βββ cross-cli.md # Cross-CLI architecture
β βββ upstream.md # Upstream fix recommendations
βββ README.md
βββ README.zh-CN.md # δΈζζζ‘£
βββ LICENSE # MIT
βββ CHANGELOG.mdπ Cache-Friendliness Audit
Check any config file for patterns that bust the KV cache:
bash scripts/check-cache-friendly.sh CLAUDE.md
bash scripts/check-cache-friendly.sh --opencode
bash scripts/check-cache-friendly.sh --allπ FAQ
Q: Does this change my prompts? A: Only the ORDER of system blocks. Content is never modified.
Q: Will it break my agent? A: No. The LLM sees the same blocks, just in a different order. System prompts are position-independent by design.
Q: Does it work with non-OpenCode agents? A: The core engine is CLI-agnostic. Adapters exist for OpenCode (plugin) and Claude Code (guidelines). Codex and Gemini CLI adapters are planned.
Q: What if my prompts change? A: The hash-based tracking adapts automatically. If a previously-stable block starts changing, its score drops and it moves to dynamic. If a new stable block is added, it converges to stable after a few observations.
Q: Does this work with Anthropic's prompt caching?
A: Yes β the chat.headers hook adds the prompt-caching-2024-07-31 beta
header automatically for Anthropic providers.
π License
MIT β use it, fork it, ship it, star it β
Built with β€οΈ for the LLM CLI ecosystem. If this saved you tokens,
drop a β on GitHub β it helps more people find it.