session.rpc.extensions.list() always returns empty array when called from extension hooks
- Dominant language
- Shell
- Stars
- 11.2k
- Forks
- 1.9k
- Avg merge
- 14h 16m
- Merged PRs (30d)
- 6
Description
### Summary
When an extension calls `session.rpc.extensions.list()` from inside an `onSessionStart` or `onPreToolUse` hook, the returned `extensions` array is always empty, even when extensions are loaded (including the calling extension itself).
The same RPC works correctly when invoked from the foreground CLI (e.g. via `/extensions` or the `extensions_manage` tool), so the data is clearly available to the host — just not to extensions through this API.
### Environment
- Copilot CLI version: 1.0.44-0
- OS: Windows 11
- SDK: `@github/copilot-sdk/extension`
### Repro
Minimal extension at `.github/extensions/repro/extension.mjs`:
```js
import { joinSession } from "@github/copilot-sdk/extension";
const session = await joinSession({
hooks: {
onSessionStart: async () => {
const { extensions } = await session.rpc.extensions.list();
await session.log(`onSessionStart: ${extensions.length} extension(s)`);
},
onPreToolUse: async () => {
const { extensions } = await session.rpc.extensions.list();
await session.log(`onPreToolUse: ${extensions.length} extension(s)`);
return { permissionDecision: "allow" };
},
},
tools: [],
});
```
Start a Copilot CLI session in the repo and trigger any tool call.
### Expected
The logged count is ≥ 1 (at least the calling extension itself, plus any user-source extensions installed in `~/.copilot/extensions/`).
### Actual
The logged count is always `0`, in both `onSessionStart` and `onPreToolUse`. No error is thrown; the call resolves successfully with an empty list.
### Impact
This API is the only documented way for an extension to discover its peers. Any extension that needs to coordinate with another extension is broken — for example, a project-level guard extension that should refuse to operate unless a specific user-level companion extension (e.g. an auth/policy plugin) is also installed and running cannot make that determination.
### Notes
- The sibling RPCs `extensions.enable` / `extensions.disable` / `extensions.reload` throw `"Extensions not available"` in failure modes. `extensions.list` returning a successful-looking empty array instead of erroring made this much harder to diagnose — at minimum, the failure mode should be consistent (a thrown error rather than a misleading empty result) so callers can tell "no peers" apart from "I can't see them".
Contributor guide
Assessment
This issue has not been assessed yet.