Describe the bug
Calling extensions_reload or extensions_manage tools in a session where a project-level extension (using joinSession() from @github/copilot-sdk/extension) is active results in a permanent hang that requires the user to manually cancel the tool call. The CLI never recovers from the hang — the tool call must be interrupted every time.
Root cause analysis
The deadlock is caused by a circular IPC dependency during the reload sequence:
extensions_reload is invoked → the CLI main process blocks synchronously, waiting for the reload to complete.
- The existing extension subprocess is terminated.
- A new
extension_bootstrap.mjs subprocess is spawned and loads the extension module.
- The extension module calls
await joinSession() at the top level — this sends a handshake message back to the CLI main process to register tools and establish the session.
- The CLI main process cannot respond to the handshake because it is blocked in step 1.
- → Permanent deadlock: parent waits for child, child waits for parent.
The same deadlock occurs with extensions_manage because it goes through the same extension management subsystem.
Affected version
GitHub Copilot CLI 1.0.12
Steps to reproduce
- Create a project-level extension in
.github/extensions/my-ext/extension.mjs with a top-level await joinSession(...) call (standard SDK pattern from the documentation).
- Start a Copilot CLI session in that project directory. The extension loads successfully.
- In the session, call the
extensions_reload tool (or extensions_manage with operation list/inspect).
- Observe: the tool call never returns. The CLI is permanently unresponsive until the tool call is manually cancelled.
- Repeat step 3 after cancelling — same result every time.
Expected behavior
extensions_reload should complete successfully and the extension should be re-registered.
- If the reload mechanism requires a subprocess handshake, the main process should handle IPC messages asynchronously (non-blocking) during the reload wait, so the new extension subprocess can complete its
joinSession() registration.
Additional context
Environment:
- OS: Linux (Ubuntu)
- Copilot CLI version:
1.0.12
- Extension type: project-level (
.github/extensions/), JS/ESM, using @github/copilot-sdk/extension
Workaround:
- Skills and agent
.md files are effective immediately on save (no reload needed).
- For changes to
extension.mjs JS code: close the terminal and re-open a new session.
Process evidence (at time of hang):
# Two extension_bootstrap.mjs subprocesses observed — both blocked
PID 230448 EXTENSION_PATH=.github/extensions/my-ext/extension.mjs COPILOT_LOADER_PID=230374
PID 245405 EXTENSION_PATH=.github/extensions/my-ext/extension.mjs COPILOT_LOADER_PID=210913
# stdin/stdout of each subprocess are sockets (IPC channels), confirming the
# joinSession() handshake is attempted but the parent is not reading from them.
fd 0 -> socket:[...]
fd 1 -> socket:[...]
Describe the bug
Calling
extensions_reloadorextensions_managetools in a session where a project-level extension (usingjoinSession()from@github/copilot-sdk/extension) is active results in a permanent hang that requires the user to manually cancel the tool call. The CLI never recovers from the hang — the tool call must be interrupted every time.Root cause analysis
The deadlock is caused by a circular IPC dependency during the reload sequence:
extensions_reloadis invoked → the CLI main process blocks synchronously, waiting for the reload to complete.extension_bootstrap.mjssubprocess is spawned and loads the extension module.await joinSession()at the top level — this sends a handshake message back to the CLI main process to register tools and establish the session.The same deadlock occurs with
extensions_managebecause it goes through the same extension management subsystem.Affected version
GitHub Copilot CLI
1.0.12Steps to reproduce
.github/extensions/my-ext/extension.mjswith a top-levelawait joinSession(...)call (standard SDK pattern from the documentation).extensions_reloadtool (orextensions_managewith operationlist/inspect).Expected behavior
extensions_reloadshould complete successfully and the extension should be re-registered.joinSession()registration.Additional context
Environment:
1.0.12.github/extensions/), JS/ESM, using@github/copilot-sdk/extensionWorkaround:
.mdfiles are effective immediately on save (no reload needed).extension.mjsJS code: close the terminal and re-open a new session.Process evidence (at time of hang):