01 Overview
Cache Clock is an extension for GitHub Copilot CLI and VS Code's Copilot chat, modelled on cache-tax for Claude Code. Copilot bills tokens in AI credits, and on Claude and newer GPT models a cache write costs far more than a cache read. Step away longer than the cache lives and your next message, even "give me a recap", rewrites the whole conversation at the write price. Cache Clock shows that clock and that price, and asks before a costly cold send goes out.
Download the MP4 ↓ (17 s, silent). Made with make-motion from this spec.
Companion pages go deeper: the visual explainer walks through the clock, the guard and the report step by step; the diagrams map the architecture, every install case, every prompt, the clock and heads-up, report and VS Code.
02 Problem & why it's needed
Prompt caches expire silently. Through Copilot, a Claude Sonnet 5.5 cache lives 5 minutes and a write costs 25× a read; GPT-6 Luna lives 30 minutes at 12.5×. Copilot shows neither the clock nor the price, so a coffee break turns the next "carry on" into a full rewrite of the context at the write price.
/cache-clock min lowers the bar. Above it, Cache Clock warns before expiry, prices the cold send and asks before sending; not sending costs 0 AI credits.03 Install
One line, once per machine. No clone and no Node needed: the extension runs inside Copilot's own runtime.
Install
curl -fsSL https://raw.githubusercontent.com/abhijitbansal/claude-skills/main/tools/cache-clock/install.sh | shDownloads a copy into ~/.copilot/extensions/cache-clock. A failed download leaves nothing behind. COPILOT_HOME moves ~/.copilot.
Copilot CLI
Start a new copilot session. Copilot asks once whether the extension may "register hooks": allow it (option 2 remembers it for that repo). Then:
/cache-clock helpVS Code Copilot chat
VS Code loads the extension from the project, not from ~/.copilot/extensions. From each repo you use it in, install a copy into .github/extensions/cache-clock (commit it to share it, or add it to .git/info/exclude to keep it local):
curl -fsSL https://raw.githubusercontent.com/abhijitbansal/claude-skills/main/tools/cache-clock/install.sh | sh -s -- --projectThen add this to your VS Code settings.json, run "Developer: Reload Window", start a new chat and type /cache-clock in full (VS Code does not list it in the / menu).
"chat.canvases.enabled": trueFrom a clone, or to remove
sh claude-skills/tools/cache-clock/install.shsh claude-skills/tools/cache-clock/install.sh --uninstallFrom a clone the installer links the extension, so a git pull updates it; --copy copies instead; --project [DIR] copies into DIR's git root, and --uninstall --project removes that copy. It replaces only its own install (one with cache-clock's own files) or a dangling link, and refuses any other folder.
/experimental on, reload Copilot CLI, and accept the permission prompts when it asks./experimental on04 Usability guide
One slash command. Settings live in ~/.copilot/cache-clock/config.json and apply to every session.
A costly cold send: the question
When the cache has expired and the rewrite costs at least the threshold more than a warm send, Cache Clock asks in the chat before anything goes out: Send anyway or Don't send. Don't send stops it before any model call, so it costs 0 AI credits; dismissing the question or leaving it for 5 minutes does the same. It asks once per cold cache; after that, sends go through with a price note. Checked live on 12 October 2026 in Copilot CLI and VS Code.
Where it cannot ask: refuse once
In copilot -p, which has no question UI, the send is refused once with the price, and sending it again pays. A real capture, taken with /cache-clock min 0.01:
/cache-clock — the card
The last model used, its cache state and time left, the context size, what the next send costs warm and cold, and the session's tally. A real card from a resumed session:
/cache-clock help
How it works, what a cold send triggers, every command, the report and the VS Code setup, in the chat.
/cache-clock help/cache-clock guard refuse | warn | off
refuse (default) asks before a costly cold send, or refuses it once where it cannot ask. warn sends it and prints the price. off disables the guard; the heads-up keeps its own switch.
/cache-clock guard warn/cache-clock guard refuse/cache-clock min <usd>
Guard only cold sends whose extra cost is at least this many dollars (default $0.10).
/cache-clock min 0.25/cache-clock headsup <min> | off
One ephemeral line before expiry, when the cold send's extra cost is at least the threshold. The lead is the smaller of this setting and a fifth of the TTL, so a 5-minute Claude cache warns 1 minute ahead.
/cache-clock headsup 5/cache-clock headsup off05 How it works under the hood
The clock
Every main-agent model call emits assistant.usage with cacheReadTokens, cacheWriteTokens, cacheExpiresAt, cacheTtlSeconds and prices in nano-AIU per batch of tokens. Cache Clock keeps the last call per model. Nothing is guessed: the TTL, the expiry and the prices all come from Copilot. Sub-agent and background calls are ignored.
The guard
onUserPromptSubmitted checks the last model's clock. If the cache has expired and rewriting it would cost at least the threshold more than reading it, the hook asks with session.ui.select and waits for the answer. To stop the send it calls session.abort() without awaiting it (awaiting inside the hook deadlocks). The cold episode is remembered per session in ~/.copilot/cache-clock/refused.json for a week, even across processes.
What is never guarded
Slash commands and ! shell escapes. A message queued while a turn is running only gets the note, because stopping it then would cancel the running turn. The first send after a compaction, since the context was rewritten anyway.
Resume
assistant.usage is not replayed on copilot --resume, and getEvents() omits usage records, so the extension seeds the clock from the session's own ~/.copilot/session-state/<id>/events.jsonl.
Architecture
Seven small modules: wiring attaches to the session, clock keeps per-model state, guard decides, usage normalises events and prices, format writes every message, config stores settings and refusals, history feeds the report. Open the architecture diagram →
06 VS Code
Measured on 11–12 October 2026 with VS Code's Copilot agent host (bundled runtime 1.0.92-4.unstable).
"chat.canvases.enabled": true (experimental)..github/extensions/cache-clock, not the ~/.copilot/extensions install. Use install.sh --project in each repo, and rerun it to update the copy./cache-clock works typed in full; VS Code's / menu does not list it.session.usage_checkpoint totals, so the report counts them as totals. VS Code's Cache Explorer (Agent Debug Logs) shows per-turn hit rates.07 What Copilot reported, measured
Measured on Copilot CLI 1.0.95, 11 October 2026. Each boundary result is a single run.
cacheExpiresAt: read 0, wrote 44,388. The reported expiry held to the second.auto, Sonnet's write was $2.25/M (list $2.50), auto's 10% off. 1 AI credit = $0.01.08 Report: what cold sends already cost you
The extension only sees sessions it was loaded in. The report reads every session Copilot has persisted, CLI and VS Code alike, and sends nothing anywhere. It ships with every install and needs Node 18+.
node ~/.copilot/extensions/cache-clock/report.mjsnode ~/.copilot/extensions/cache-clock/report.mjs --since 7dnode ~/.copilot/extensions/cache-clock/report.mjs --json"Extra paid" is what each cold call cost above a warm read of the same tokens. "Prefix breaks" are cold calls inside the reported TTL: something changed the prompt prefix, or the provider served it cold early.
09 Limits
No keep-warm yet
cache-tax pings to hold the cache during a break. An extension can only ping with session.send, which adds a user and an assistant turn to your conversation each time. Run the report first: whether pings pay off depends on your own tax.
Auto routes per prompt
With auto, the next prompt may go to a different model than the last. The guard prices the last model used.
The estimate is approximate
It is the last call's input plus its answer. The real resend adds your new message and anything Copilot attaches (44.4k actual vs 37.2k estimated in the capture above).
Early eviction is invisible to the guard
It trusts Copilot's cacheExpiresAt. When a provider serves a cache cold sooner (Luna at 29 of 30 minutes, once), the send is billed cold and the guard stays quiet; the report counts it as a prefix break.
VS Code relies on an experimental setting
chat.canvases.enabled may be renamed or removed in a later VS Code release.
-p mode
The guard refuses once in copilot -p, but slash commands there go to the model as text, so /cache-clock needs the interactive CLI.
10 What's inside
Copilot extension
help, guard, min and headsup subcommands--since, --dir, --jsonwiring, clock, guard, usage, format, config, historyInstall and tests
--copy or --uninstall. Replaces only its own install or a dangling link.Explore the other plugins
Second Wind
Run Claude overnight; auto-resume after 5-hour limit resets
prompt-craft
Sharpen rough prompts into specs, suggest follow-up commands
ios-dev
Build iOS apps, screenshot remotely, release to App Store
core-workflow
Opinionated dev workflow: commit + share + team up
linear-pm
Linear issues → code, branches, PRs — autonomous end-to-end
portable-artifacts
Dashboards and animated explainers from a prompt — offline, any agent
Session mods
test-board and session-compass: test results and session status above the prompt