Copilot Guard
track copilot. warn before wall. keep using brain.

Status bar shows Copilot: 142 / 1900. Turns yellow, orange, red as you approach your company cap.
Warns you before GitHub does. No network interception, no private APIs, no root CAs.
Get your count · Commands · Settings · Skills · Limitations · Development
What it does
| Feature |
Detail |
| Status bar |
$(copilot) Copilot: 142 / 1900 (estimated) — colored by state, click for dashboard |
| Limit engine |
Green → Yellow → Orange → Red, driven by two configurable thresholds |
| Notifications |
VS Code toast at each state transition — dismissable, opt-out in settings |
| Soft gate |
Best-effort warning when you hit Red on a keybinding-triggered send. A deterrent, not a block |
| Skills |
Reusable instruction presets written as real .github/copilot-instructions.md and *.instructions.md files |
| Sync |
Pull official usage totals from GitHub's billing API — personal accounts only, see below |
Every displayed number carries a confidence tag: exact, synced, or estimated. Never shown as official when it isn't.
Getting your count
VS Code exposes no API that lets a third-party extension read what the native Copilot Chat panel sends or receives. These are the real options, from most to least accurate:
Option 1 — GitHub PAT sync (most accurate, delayed 24 h)
Works only if Copilot is billed to your personal GitHub account (Copilot Individual / legacy setup). If your company pays for your Business seat, skip to Option 2 — the API will return empty data.
Create the token:
- Go to github.com/settings/tokens → Generate new token (classic)
- Tick
manage_billing:copilot scope (under Billing)
- Copy the token — you won't see it again
Connect it:
Cmd+Shift+P → Copilot Guard: Sync Usage from GitHub
- Paste the token when prompted (stored in VS Code's encrypted secret storage, never in settings files)
- Run the same command any time to refresh — data lags up to ~24 h since GitHub aggregates daily
If you're on a Business/org-managed seat the sync will show a warning: "Personal billing data unavailable — this seat is managed by an org or enterprise." That's correct behavior, not a bug. Your only option then is to ask your org admin for usage data, or use Option 2.
┌─────────────────────────────────────────────────┐
│ accuracy ████████████████████████ exact │
│ freshness ████░░░░░░░░░░░░░░░░░░░░ ~24 h │
│ setup ███░░░░░░░░░░░░░░░░░░░░░ PAT req │
│ seat types personal accounts only │
└─────────────────────────────────────────────────┘
Option 2 — Keybinding shadow (semi-automatic, zero ongoing effort)
Bind the copilotGuard.gated.chatSubmit command to your Copilot Chat send key. Every submit fires it first — Copilot Guard logs +1 (with model multiplier if you set a default model), then passes through.
Set it up:
Cmd+Shift+P → Preferences: Open Keyboard Shortcuts
- Search
Copilot Guard: Gated Chat Submit
- Bind it to
Enter with when: inChatInput (or whatever key you use to send)
Not bound by default — binding the wrong key silently breaks your Copilot Chat send, so this is deliberate opt-in.
┌─────────────────────────────────────────────────┐
│ accuracy ████████████░░░░░░░░░░░░ ±1/turn │
│ freshness ████████████████████████ live │
│ setup ████░░░░░░░░░░░░░░░░░░░░ keybind │
│ seat types all │
└─────────────────────────────────────────────────┘
Counts sends, not responses. No token data. GPT-4.5 and Claude Opus turns count the same as GPT-4o unless you manually set a default model in settings.
Option 3 — Manual log (always works)
Cmd+Shift+P → Copilot Guard: Log Copilot Request
Prompts for a model name (optional). Applies the correct multiplier from the published GitHub pricing table — Claude Opus 10×, GPT-4.5 50×, everything else 1×. Status bar updates immediately.
Bind it to a key for speed:
{ "key": "ctrl+alt+l", "command": "copilotGuard.logRequest" }
┌─────────────────────────────────────────────────┐
│ accuracy ████████████░░░░░░░░░░░░ weighted │
│ freshness ████████████████████████ live │
│ setup ██░░░░░░░░░░░░░░░░░░░░░░ none │
│ seat types all │
└─────────────────────────────────────────────────┘
Nothing else works — why
| What you might expect |
Why it doesn't exist |
| Intercept native Copilot Chat turns |
VS Code fires no event another extension can listen to |
| Read the Copilot status bar number |
No inter-extension API; the value is internal to github.copilot |
| Count tokens per response |
vscode.lm.countTokens() only works on messages you construct yourself |
| Org/Business seat REST API |
Requires org owner or billing_manager — not available to a regular seat holder |
| Network interception |
Requires root CA install + MITM proxy; outside extension scope |
Full research in docs/feasibility.md and docs/quota-read-research.md.
Commands
| Command |
What it does |
Copilot Guard: Log Copilot Request |
Manually record a request — asks for model (optional), applies multiplier |
Copilot Guard: Sync Usage from GitHub |
Pull official usage totals via GitHub billing API (personal accounts, PAT required) |
Copilot Guard: Gated Chat Submit |
Bind to your send key — logs +1 and passes through |
Copilot Guard: Reset Usage Counter |
Clear all recorded usage events |
Copilot Guard: Apply Skill |
Quick-pick a preset and write it to the correct instructions file |
Copilot Guard: Open Settings |
Jump to copilotGuard.* settings |
AI Workspace: Quick Switch |
Cmd+Alt+A — switch active skill/profile |
Settings
| Setting |
Default |
What it does |
copilotGuard.maxCredits |
1900 |
Monthly cap — Red state fires at or above this value |
copilotGuard.warningAt |
[1800, 1850] |
Ascending list of thresholds; each entry adds a warning band and notification |
copilotGuard.enableBlocking |
true |
Show modal warning at Red on gated sends |
copilotGuard.showStatusBar |
true |
Show/hide the status bar item |
copilotGuard.notifications |
true |
Toast notifications on state transitions |
copilotGuard.skills.enabled |
true |
Enable the Skills system |
copilotGuard.skills.defaultSkill |
"" |
Auto-apply this skill on activation |
Skills
Skills are reusable Copilot instruction presets. Applying one writes a real
.github/copilot-instructions.md or *.instructions.md file — no hooks, no private APIs,
just files Copilot Chat natively reads.
Built-in presets: Backend Review, Security Audit, Refactoring, Bug Hunter, Performance, Code Explainer, Documentation Writer, and more. See resources/skills/builtin/.
Cmd+Shift+P → Copilot Guard: Apply Skill → pick from the list.
Limitations
- Cannot count native Copilot Chat turns automatically — no VS Code API exposes them to third-party extensions. Use Option 1, 2, or 3 above.
- Cannot force-block Copilot — the gate is a warning/deterrent. VS Code has no API to cancel another extension's command.
- GitHub sync is personal-account-only — Business/org seats get no data from the personal billing endpoint.
- Model multipliers drift —
estimator.ts has the table; update it when GitHub changes pricing.
Development
npm install
npm run watch # esbuild watch
npm run lint
npm run test:unit # plain Node, no extension host needed
npm run test:integration # @vscode/test-electron, needs a display
F5 in VS Code → Extension Development Host.
Testing the warning bands
Set a low cap in your settings.json so you can hit every band by logging a handful of requests:
"copilotGuard.maxCredits": 10,
"copilotGuard.warningAt": [2, 4, 6, 8]
Then run Copilot Guard: Log Copilot Request repeatedly and watch the status bar step through:
| Count |
State |
Color |
| 0–1 |
green |
— |
| 2–3 |
w1 |
electric blue #00b4ff |
| 4–5 |
w2 |
teal #00d4aa |
| 6–7 |
w3 |
gold #ffd700 |
| 8–9 |
w4 |
orange #ff9500 |
| 10+ |
red |
error background |
A VS Code notification fires at each band crossing. Restore your real values when done:
"copilotGuard.maxCredits": 1900,
"copilotGuard.warningAt": [1500, 1700, 1800, 1850]
ROADMAP.md · TODO.md · docs/feasibility.md · docs/quota-read-research.md
MIT — free like untracked tokens on an open plain.