Skip to content
This repository was archived by the owner on Jun 14, 2026. It is now read-only.

Commit dfa5ef2

Browse files
abhi-singhsCopilot
andcommitted
Release 0.2.2 — run hooks only under Copilot CLI
Gate every hook in hooks.json on $COPILOT_PLUGIN_ROOT so the token meter fires only under Copilot CLI. When the variable is unset (VS Code's Copilot chat agent or any other non-CLI host), the hook command exits 0 immediately without invoking Node. Removes the previous fallback chain ($CLAUDE_PLUGIN_ROOT, $PLUGIN_ROOT, hardcoded direct-install path) that caused the hook to run under non-CLI hosts and the earlier MODULE_NOT_FOUND crash. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent f1d5bfa commit dfa5ef2

3 files changed

Lines changed: 13 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.2.2] - 2026-06-05
11+
1012
### Fixed
11-
- **Hook no longer crashes with `MODULE_NOT_FOUND` when invoked from VS Code (or any host that runs hooks with cwd ≠ plugin dir).** `hooks.json` used to invoke `node ./bin/token-meter.js`, which only resolved correctly because Copilot CLI sets cwd to the plugin directory. VS Code's Copilot chat agent runs the hook with cwd = workspace folder, so Node looked for `./bin/token-meter.js` under the user's project and failed with `Error: Cannot find module '/path/to/workspace/bin/token-meter.js'`. The hook command now resolves an absolute script path from `$COPILOT_PLUGIN_ROOT` (exported by Copilot CLI 1.0.56+) — falling back to `$CLAUDE_PLUGIN_ROOT`, `$PLUGIN_ROOT`, and finally the standard direct-install path `~/.copilot/installed-plugins/_direct/abhi-singhs--copilot-token-meter`. The bash and PowerShell forms also guard with a `[ -f "$S" ]` / `Test-Path` check and silently `exit 0` when the script can't be located, so a misplaced install never blocks the agent. `hooks.log` now also records the resolved `root=` so install issues are easy to diagnose.
13+
- **Hooks now only run under Copilot CLI and never fire under other hosts (e.g. VS Code's Copilot chat agent or any non-CLI host).** Each hook in `hooks.json` now gates on `$COPILOT_PLUGIN_ROOT` (the Copilot-CLI-specific variable, exported by Copilot CLI 1.0.56+): if it is unset, the hook command immediately `exit 0`s without invoking Node. The script path is resolved directly from `$COPILOT_PLUGIN_ROOT/bin/token-meter.js` — the previous fallback chain (`$CLAUDE_PLUGIN_ROOT`, `$PLUGIN_ROOT`, and the hardcoded direct-install path) has been removed, since those caused the hook to run under hosts other than Copilot CLI. This also resolves the earlier `MODULE_NOT_FOUND` crash seen in VS Code, where hooks ran with cwd = workspace folder and Node couldn't locate `./bin/token-meter.js`. The bash and PowerShell forms still guard with a `[ -f "$S" ]` / `Test-Path` check so a misplaced install never blocks the agent.
1214

1315
## [0.2.1] - 2026-05-22
1416

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,9 @@ Pricing/context-window data is read lazily and cached for the lifetime of each h
260260

261261
Check `~/.copilot/state/token-meter/errors.log`. The hook script is wrapped so any error is logged there and the process exits 0 — a hook failure never blocks Copilot CLI. If you see repeated errors, please file an issue with the relevant log excerpt and your Copilot CLI version.
262262

263-
### `Cannot find module '.../bin/token-meter.js'` in VS Code
263+
### Hooks running (or erroring) under VS Code or another non-CLI host
264264

265-
Older versions of `hooks.json` invoked `node ./bin/token-meter.js`, which only worked because Copilot CLI sets the hook's working directory to the plugin folder. VS Code's Copilot chat agent uses the open workspace as the working directory instead, so the relative path resolves under your project (e.g. `~/Documents/my-project/bin/token-meter.js`) and Node throws `MODULE_NOT_FOUND`. `hooks.json` in 0.2.2+ resolves the script via `$COPILOT_PLUGIN_ROOT` (exported by Copilot CLI 1.0.56+, with fallbacks to `$CLAUDE_PLUGIN_ROOT`, `$PLUGIN_ROOT`, and the standard direct-install path). If you're on the older command, `copilot plugin update copilot-token-meter` (or re-install) picks up the new `hooks.json`.
265+
The hooks are meant for Copilot CLI only. As of 0.2.2, every hook in `hooks.json` gates on `$COPILOT_PLUGIN_ROOT` (set by Copilot CLI 1.0.56+) and immediately exits without doing anything when that variable is unset — so the meter never fires under VS Code's Copilot chat agent or any other host. This also fixes the older `MODULE_NOT_FOUND` crash, where a non-CLI host ran the hook with cwd = workspace folder and Node couldn't resolve `./bin/token-meter.js`. If you're on an older `hooks.json`, run `copilot plugin update copilot-token-meter` (or re-install) to pick up the new gating.
266266

267267
### `copilot-tokens` colours are mangled in tmux / less / scripts
268268

hooks.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44
"sessionStart": [
55
{
66
"type": "command",
7-
"bash": "S=\"${COPILOT_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-$HOME/.copilot/installed-plugins/_direct/abhi-singhs--copilot-token-meter}}}/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=sessionStart; exit 0",
8-
"powershell": "$r = if ($env:COPILOT_PLUGIN_ROOT) { $env:COPILOT_PLUGIN_ROOT } elseif ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } elseif ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { \"$env:USERPROFILE\\.copilot\\installed-plugins\\_direct\\abhi-singhs--copilot-token-meter\" }; $s = Join-Path $r 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=sessionStart }",
7+
"bash": "[ -n \"$COPILOT_PLUGIN_ROOT\" ] || exit 0; S=\"$COPILOT_PLUGIN_ROOT/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=sessionStart; exit 0",
8+
"powershell": "if (-not $env:COPILOT_PLUGIN_ROOT) { exit 0 }; $s = Join-Path $env:COPILOT_PLUGIN_ROOT 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=sessionStart }",
99
"timeoutSec": 10
1010
}
1111
],
1212
"postToolUse": [
1313
{
1414
"type": "command",
15-
"bash": "S=\"${COPILOT_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-$HOME/.copilot/installed-plugins/_direct/abhi-singhs--copilot-token-meter}}}/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=postToolUse; exit 0",
16-
"powershell": "$r = if ($env:COPILOT_PLUGIN_ROOT) { $env:COPILOT_PLUGIN_ROOT } elseif ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } elseif ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { \"$env:USERPROFILE\\.copilot\\installed-plugins\\_direct\\abhi-singhs--copilot-token-meter\" }; $s = Join-Path $r 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=postToolUse }",
15+
"bash": "[ -n \"$COPILOT_PLUGIN_ROOT\" ] || exit 0; S=\"$COPILOT_PLUGIN_ROOT/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=postToolUse; exit 0",
16+
"powershell": "if (-not $env:COPILOT_PLUGIN_ROOT) { exit 0 }; $s = Join-Path $env:COPILOT_PLUGIN_ROOT 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=postToolUse }",
1717
"timeoutSec": 10
1818
}
1919
],
2020
"userPromptSubmitted": [
2121
{
2222
"type": "command",
23-
"bash": "S=\"${COPILOT_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-$HOME/.copilot/installed-plugins/_direct/abhi-singhs--copilot-token-meter}}}/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=userPromptSubmitted; exit 0",
24-
"powershell": "$r = if ($env:COPILOT_PLUGIN_ROOT) { $env:COPILOT_PLUGIN_ROOT } elseif ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } elseif ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { \"$env:USERPROFILE\\.copilot\\installed-plugins\\_direct\\abhi-singhs--copilot-token-meter\" }; $s = Join-Path $r 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=userPromptSubmitted }",
23+
"bash": "[ -n \"$COPILOT_PLUGIN_ROOT\" ] || exit 0; S=\"$COPILOT_PLUGIN_ROOT/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=userPromptSubmitted; exit 0",
24+
"powershell": "if (-not $env:COPILOT_PLUGIN_ROOT) { exit 0 }; $s = Join-Path $env:COPILOT_PLUGIN_ROOT 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=userPromptSubmitted }",
2525
"timeoutSec": 10
2626
}
2727
],
2828
"agentStop": [
2929
{
3030
"type": "command",
31-
"bash": "S=\"${COPILOT_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-$HOME/.copilot/installed-plugins/_direct/abhi-singhs--copilot-token-meter}}}/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=agentStop; exit 0",
32-
"powershell": "$r = if ($env:COPILOT_PLUGIN_ROOT) { $env:COPILOT_PLUGIN_ROOT } elseif ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } elseif ($env:PLUGIN_ROOT) { $env:PLUGIN_ROOT } else { \"$env:USERPROFILE\\.copilot\\installed-plugins\\_direct\\abhi-singhs--copilot-token-meter\" }; $s = Join-Path $r 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=agentStop }",
31+
"bash": "[ -n \"$COPILOT_PLUGIN_ROOT\" ] || exit 0; S=\"$COPILOT_PLUGIN_ROOT/bin/token-meter.js\"; [ -f \"$S\" ] && exec node \"$S\" --hook=agentStop; exit 0",
32+
"powershell": "if (-not $env:COPILOT_PLUGIN_ROOT) { exit 0 }; $s = Join-Path $env:COPILOT_PLUGIN_ROOT 'bin\\token-meter.js'; if (Test-Path $s) { node $s --hook=agentStop }",
3333
"timeoutSec": 10
3434
}
3535
]

0 commit comments

Comments
 (0)