Skip to content

Instantly share code, notes, and snippets.

@cicorias
Forked from burkeholland/INSTALL.md
Created July 20, 2026 19:48
Show Gist options
  • Select an option

  • Save cicorias/4c77bd1886de6d9c5bb35c0679e2716c to your computer and use it in GitHub Desktop.

Select an option

Save cicorias/4c77bd1886de6d9c5bb35c0679e2716c to your computer and use it in GitHub Desktop.
Cache Break Notifier plugin for GitHub Copilot CLI
import { joinSession } from "@github/copilot-sdk/extension";
const DROP_TOKENS = 4096; // the only tunable: how big a cache-read drop is worth a warning
/** @type {Map<string, number>} last turn-entry cacheRead per model */
const perModel = new Map();
// Only the FIRST eligible main-agent call of each turn is evaluated.
let acceptingTurnEntry = false;
const session = await joinSession({});
await session.log("cache-drop-notifier active", { ephemeral: true });
session.on("assistant.turn_start", () => {
acceptingTurnEntry = true;
});
session.on("assistant.turn_end", () => {
acceptingTurnEntry = false;
});
session.on("assistant.usage", (event) => {
const d = event.data ?? {};
// Main context only: skip separate-context calls entirely (don't consume the slot).
const initiator = d.initiator;
const isMain =
initiator !== "sub-agent" &&
initiator !== "mcp-sampling" &&
d.parentToolCallId == null;
if (!acceptingTurnEntry || !isMain) return;
// This is the turn-entry sample — consume the slot even if the metrics are unusable,
// so a later continuation call can't masquerade as the entry.
acceptingTurnEntry = false;
// Unknown != zero: a missing counter means "no data," so we skip this turn's line.
// Only cacheReadTokens matters now (inputTokens is no longer part of detection), so a
// missing inputTokens must not be allowed to suppress a real drop.
const cached = d.cacheReadTokens;
if (!Number.isFinite(cached) || cached < 0) return;
const model = d.model ?? "unknown";
const prev = perModel.get(model);
// A "drop" (not a "miss"): reused tokens fell by a large absolute amount versus the last
// turn on this model. An intentional context shrink looks identical in the counts.
const isDrop = prev !== undefined && prev - cached >= DROP_TOKENS;
if (isDrop) {
session.log(
`Cache break detected on ${model}.`,
{ level: "warning" }
).catch(() => {});
} else if (cached === 0) {
session.log(
`No cache tokens reused on ${model}.`,
{ level: "warning" }
).catch(() => {});
}
// Always update — this is why a drop is reported once and the baseline self-heals.
perModel.set(model, cached);
});

Install Cache Break Notifier

Install this plugin directly from its GitHub Gist:

copilot plugin install https://gist.github.com/burkeholland/647ad0e579c06a43346ce6a373261eba.git

Start Copilot CLI to load the plugin:

copilot

No npm install is required. Copilot CLI supplies @github/copilot-sdk to the bundled extension automatically.

Install from inside Copilot CLI

Run:

/plugin install https://gist.github.com/burkeholland/647ad0e579c06a43346ce6a373261eba.git

Then start a new session:

/clear
{
"name": "cache-break-notifier",
"description": "Warns when Copilot CLI cache reuse drops significantly.",
"version": "1.0.1",
"extensions": "."
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment