Prerequisites
Bug Description
codemie update and codemie list can hang indefinitely — not for a few seconds, but forever, with no timeout, no error, and no visible indication of what they're waiting on. The only way to recover is to open another terminal, find the hidden child process manually, and kill it.
This happens whenever CodeMie tries to detect the installed version of GitHub Copilot CLI, on any machine that has the VS Code "GitHub Copilot Chat" extension installed but does not have the separate, standalone GitHub Copilot CLI (npm package @github/copilot) installed. That is a very common combination — most developers use Copilot only inside the VS Code chat panel and have never run npm i -g @github/copilot — so this is not an edge case, it will affect a large fraction of your users.
How we tracked it down (so you don't have to re-derive it):
- We ran
codemie update --verbose and watched it get all the way through checking Claude's version (Checking version compatibility { agent: 'claude', ... } in the debug log), then just stop producing any output. No error, no next step, nothing — it looked like it had silently died or was stuck on network I/O.
- We used
ps aux while it was stuck and found it had spawned two extra child processes that never show up in any CodeMie log line:
/bin/sh "…/Code/User/globalStorage/github.copilot-chat/copilotCli/copilot" --version
└── "Code Helper (Plugin).app" "…/copilotCli/copilotCLIShim.js" --version
That copilot file is not a CodeMie artifact — it's a small shim script that VS Code's GitHub Copilot Chat extension drops into its globalStorage folder. We confirmed this by inspecting its contents directly (#!/bin/sh … ELECTRON_RUN_AS_NODE=1 "Code Helper (Plugin)" copilotCLIShim.js "$@"), and the shim's own footer comment says DO NOT modify, this file was COPIED from 'microsoft/vscode'.
- We used
lsof -p <pid> on the hung process and found zero network sockets open. So this is not a slow registry/API call, not a DNS issue, not rate limiting — it's a purely local deadlock.
- We used
sample <pid> (macOS's built-in stack sampler) on the hung process. Its main thread was idle inside uv_run → uv__io_poll → kevent — i.e., genuinely blocked waiting for an I/O event, not spinning or crashed.
- We then decompiled/read the shim's bundled source (
copilotCLIShim.js) to find out what event it could possibly be waiting for. Its logic (paraphrasing the minified function names for clarity) is:
Ye() runs spawnSync("copilot --version", { shell: true, env: <PATH with the shim's own directory stripped out> }), specifically to avoid finding itself. On a machine without the real CLI installed, this returns nothing.
Ce() (the "ensure Copilot CLI" function) then does: if Ye() found nothing, print Cannot find GitHub Copilot CLI (…install docs URL…), then call a helper (me()) that does readline.createInterface({input: process.stdin, output: process.stdout}).question("Install GitHub Copilot CLI? ['y/N'] ", callback).
- That
readline.question() call is a blocking, interactive prompt with no timeout. Whatever process CodeMie used to launch this shim, its stdin is still attached to CodeMie's own controlling terminal (we confirmed this too — lsof showed the child's stdin/stdout as /dev/ttys00x, the real TTY, not /dev/null or a pipe CodeMie was driving).
- Since CodeMie's own version-check flow never expects or answers this nested "Install GitHub Copilot CLI? [y/N]" prompt, and nothing else is watching that terminal for it, the prompt just sits there forever.
codemie update is left synchronously waiting on this child process to exit, so CodeMie itself hangs, even though the actual bug (an interactive prompt with no timeout) lives in the VS Code-shipped shim, not in CodeMie's own code.
In short: CodeMie shells out to a third-party interactive script to check a version number, doesn't give it a timeout, doesn't suppress its ability to prompt, and has no fallback if that third-party script decides to ask a question instead of just returning an error.
A secondary issue we noticed while investigating: GitHub Copilot isn't even listed as a managed agent by codemie list (that command only shows CodeMie Code, Claude Code, Claude Code ACP, Gemini CLI, OpenCode CLI, OpenAI Codex CLI, Pi, Kimi Code, Kimi Code ACP, and OpenWiki). So this integration is invisible to the user — there's no entry to codemie uninstall, no flag to skip it, and no documentation mentioning that codemie update/codemie list reach out to VS Code's Copilot Chat extension data at all. A user hitting this hang has essentially no way to discover, from CodeMie's own UI, what's actually blocking them — you have to do exactly the OS-level forensics described above.
Steps to Reproduce
- Install VS Code with the "GitHub Copilot Chat" extension enabled and used at least once (so
~/Library/Application Support/Code/User/globalStorage/github.copilot-chat/copilotCli/ exists — on Linux/Windows this would be the equivalent VS Code user-data path).
- Do not install the standalone GitHub Copilot CLI (verify with
npm ls -g @github/copilot → empty, and command -v copilot → resolves only to the VS Code extension's bundled shim path, not a real binary elsewhere on PATH).
- Run
codemie update (with or without piping stdin, e.g. printf '\n' | codemie update), or simply codemie list.
- Watch it print
- Checking for updates... (for update) or start printing the agent list (for list), then stop advancing entirely. No error, no timeout, no further output — CPU usage on the CodeMie process itself drops to ~0% because it's just waiting on wait()/similar for its child.
- In a second terminal, run
codemie update --verbose instead to see it clearly stop right after logging Claude's version-compatibility check, confirming the Copilot probe is the very next step and where it dies.
- Confirm the hang:
ps aux | grep copilotCLIShim will show a live Code Helper (Plugin) process running copilotCLIShim.js --version, parented by a /bin/sh …/copilotCli/copilot --version, parented by the codemie Node process. lsof -p <that pid> shows no sockets and stdin/stdout on the real tty. It will sit there indefinitely — we let it run for several minutes with no change.
Expected Behavior
codemie update / codemie list should complete (or at least fail with a clear error) within a bounded, short time regardless of what any external tool it probes decides to do. Concretely, we'd suggest:
- Add a timeout to every external subprocess spawned purely for version detection (Copilot's is the one we found, but the same class of bug could exist for any other agent probe that shells out to a third-party binary). A few seconds is plenty — if a
--version call hasn't returned by then, treat that agent as "unknown/not installed" and move on, rather than blocking the whole command.
- Never let a version-probe subprocess inherit CodeMie's real stdin/tty. Spawn it with stdin redirected to
/dev/null (or an already-closed pipe). That alone would fix this specific case: the VS Code shim's readline.question() would hit EOF immediately and get an empty answer instead of blocking forever, letting Ce()/Ye() return promptly.
- Since GitHub Copilot isn't part of CodeMie's own managed-agent registry (it doesn't appear in
codemie list), consider whether probing it during update/list is even in scope — if it's meant to be a "detect what else is installed on this machine" convenience feature, it should be clearly optional (a config flag, or at minimum documented), not a silent, unbounded dependency of the core update/list flow.
Actual Behavior
codemie update and codemie list hang forever — we let one run for several minutes with no output change and 0% CPU before manually diagnosing and killing the hidden child process tree ourselves. There is no timeout, no error message, and nothing in CodeMie's own output (even with --verbose) that indicates it's waiting on GitHub Copilot CLI detection specifically, let alone that the underlying cause is a third-party interactive prompt it can never answer. A typical user would have no way to know this is even happening — they'd just conclude "codemie is broken" or "my network is slow" and either give up or file a much less specific bug report than this one.
As a stop-gap on our end (documented here so it's clear this is a workaround, not a fix we think is sufficient), we wrapped our own call to codemie update in a shell function with a hard ~20 second kill-timeout, and treat a timeout from it as non-fatal (log a warning, continue with the rest of our update script). We picked 20s empirically: the rest of CodeMie's own version-check work (Claude, etc.) reliably finishes in well under that before the Copilot probe is reached and hangs. We'd very much rather not need this workaround at all.
CodeMie CLI Version
0.15.0
Which agent are you using?
Not applicable / General CLI
Which provider are you using?
AI/Run SSO
Model
claude-sonnet-5
Node.js Version
v26.8.1
Operating System
macOS
Configuration (Redacted)
{
"version": 2,
"activeProfile": "default",
"profiles": {
"default": {
"provider": "ai-run-sso",
"apiKey": "<REDACTED>",
"baseUrl": "https://codemie.lab.epam.com/code-assistant-api",
"model": "claude-sonnet-5",
"haikuModel": "claude-haiku-4-5-20251001",
"sonnetModel": "claude-sonnet-5",
"opusModel": "claude-opus-5",
"name": "default"
},
"airun-assistant-vscode": {
"name": "airun-assistant-vscode",
"provider": "ai-run-sso",
"baseUrl": "https://codemie.lab.epam.com/code-assistant-api",
"authMethod": "sso",
"model": "claude-4-5-sonnet",
"timeout": 60000,
"debug": true
}
},
"codemieSkills": [],
"codemieAssistants": [],
"workspace": {
"codeMieUrl": "https://codemie.lab.epam.com",
"codeMieProject": "<REDACTED>"
}
}
Error Logs
$ printf '\n' | codemie update --verbose
[DEBUG] [system] [] Verbose mode enabled
🔍 Verbose mode enabled - showing detailed logs
- Checking for updates...
[DEBUG] [system] [] [opencode-adapter] Registered processor: opencode-metrics (priority: 1)
[DEBUG] [system] [] [opencode-adapter] Registered processor: opencode-conversations (priority: 2)
[DEBUG] [system] [] [opencode-adapter] Initialized 2 processors
[DEBUG] [system] [] [claude-adapter] Registered processor: metrics (priority: 1)
[DEBUG] [system] [] [claude-adapter] Registered processor: conversations (priority: 2)
[DEBUG] [system] [] [claude-adapter] Initialized 2 processors
[DEBUG] [system] [] [gemini-adapter] Registered processor: gemini-metrics (priority: 1)
[DEBUG] [system] [] [gemini-adapter] Registered processor: gemini-conversations (priority: 2)
[DEBUG] [system] [] [gemini-adapter] Initialized 2 processors
[DEBUG] [system] [] [codex-adapter] Registered processor: codex-metrics (priority: 1)
[DEBUG] [system] [] [codex-adapter] Registered processor: codex-conversations (priority: 2)
[DEBUG] [system] [] [codex-adapter] Initialized 2 processors
[DEBUG] [system] [] [pi-adapter] Registered processor: pi-metrics (priority: 1)
[DEBUG] [system] [] [pi-adapter] Registered processor: pi-conversations (priority: 2)
[DEBUG] [system] [] [pi-adapter] Initialized 2 processors
[DEBUG] [system] [] [codemie-code] Resolved platform binary: .../codemie-opencode-darwin-arm64/bin/codemie
[DEBUG] [system] [] [codex-plugin] Codex not installed. Install with:
[DEBUG] [system] [] [codex-plugin] codemie install codex
[DEBUG] [system] [] [kimi-plugin] Kimi not installed. Install with:
[DEBUG] [system] [] [kimi-plugin] codemie install kimi
[DEBUG] [system] [] Checking version compatibility {
agent: 'claude',
installedVersion: '2.1.263',
supportedVersion: '2.1.218',
minimumSupportedVersion: '2.1.208'
}
[DEBUG] [system] [] Version comparison result {
agent: 'claude',
comparison: 1,
installedVersion: '2.1.263',
supportedVersion: '2.1.218',
minimumSupportedVersion: '2.1.208',
compatible: false,
isNewer: true,
hasUpdate: false,
isBelowMinimum: false
}
# <hangs here forever. Confirmed via `ps aux` that CodeMie has, at this exact
# point, spawned:
# /bin/sh ".../Code/User/globalStorage/github.copilot-chat/copilotCli/copilot" --version
# └─ "Code Helper (Plugin).app/.../Code Helper (Plugin)"
# ".../copilotCli/copilotCLIShim.js" --version
# which is blocked forever inside that shim's own
# readline.question("Install GitHub Copilot CLI? ['y/N'] ") prompt, because
# the real `@github/copilot` CLI isn't installed on this machine and nothing
# is answering that prompt.>
Additional Context
- This is fully reproducible, not flaky. We hit it on three separate runs (
codemie update, codemie update --verbose, and codemie list), always at the same point, always with the same hung copilotCLIShim.js child.
- It's not a network problem.
lsof -p <pid> on the hung process shows zero open sockets. Anyone else hitting "codemie update hangs" who assumes it's their network/VPN/proxy will waste time chasing the wrong cause — this is a purely local subprocess/stdin issue.
- It's not a "wait longer" problem either. We let it run for several minutes with no CPU activity and no state change;
sample <pid> shows the main thread parked in kevent the entire time, i.e., truly blocked, not making slow progress.
- The exact file involved is not shipped by CodeMie — it lives at
~/Library/Application Support/Code/User/globalStorage/github.copilot-chat/copilotCli/copilot (macOS path; the Windows/Linux equivalents would be under VS Code's respective globalStorage locations) and its JS payload (copilotCLIShim.js) carries a comment stating it was copied from microsoft/vscode. We're flagging this so your team doesn't spend time looking for this bug inside your own version-check code for the wrong agent — the trigger is CodeMie's call into this file, not anything wrong with Claude/Gemini/OpenCode/etc. detection.
- Workaround applied locally, purely on our side, while waiting for a real fix: a shell wrapper around
codemie update with a hard 20-second kill-timeout that treats a timeout as non-fatal and lets the rest of our update script continue. Happy to share the exact wrapper if useful, but it's really just a spawn + sleep timer + SIGTERM pattern — nothing CodeMie-specific.
- Happy to provide anything else needed to help fix this — PIDs/stack samples were gathered fresh on macOS 26.6.2 (ARM64) with Node v26.8.1 and can be reproduced again if you want us to run something specific.
Prerequisites
Bug Description
codemie updateandcodemie listcan hang indefinitely — not for a few seconds, but forever, with no timeout, no error, and no visible indication of what they're waiting on. The only way to recover is to open another terminal, find the hidden child process manually, and kill it.This happens whenever CodeMie tries to detect the installed version of GitHub Copilot CLI, on any machine that has the VS Code "GitHub Copilot Chat" extension installed but does not have the separate, standalone GitHub Copilot CLI (npm package
@github/copilot) installed. That is a very common combination — most developers use Copilot only inside the VS Code chat panel and have never runnpm i -g @github/copilot— so this is not an edge case, it will affect a large fraction of your users.How we tracked it down (so you don't have to re-derive it):
codemie update --verboseand watched it get all the way through checking Claude's version (Checking version compatibility { agent: 'claude', ... }in the debug log), then just stop producing any output. No error, no next step, nothing — it looked like it had silently died or was stuck on network I/O.ps auxwhile it was stuck and found it had spawned two extra child processes that never show up in any CodeMie log line:copilotfile is not a CodeMie artifact — it's a small shim script that VS Code's GitHub Copilot Chat extension drops into itsglobalStoragefolder. We confirmed this by inspecting its contents directly (#!/bin/sh … ELECTRON_RUN_AS_NODE=1 "Code Helper (Plugin)" copilotCLIShim.js "$@"), and the shim's own footer comment saysDO NOT modify, this file was COPIED from 'microsoft/vscode'.lsof -p <pid>on the hung process and found zero network sockets open. So this is not a slow registry/API call, not a DNS issue, not rate limiting — it's a purely local deadlock.sample <pid>(macOS's built-in stack sampler) on the hung process. Its main thread was idle insideuv_run → uv__io_poll → kevent— i.e., genuinely blocked waiting for an I/O event, not spinning or crashed.copilotCLIShim.js) to find out what event it could possibly be waiting for. Its logic (paraphrasing the minified function names for clarity) is:Ye()runsspawnSync("copilot --version", { shell: true, env: <PATH with the shim's own directory stripped out> }), specifically to avoid finding itself. On a machine without the real CLI installed, this returns nothing.Ce()(the "ensure Copilot CLI" function) then does: ifYe()found nothing, printCannot find GitHub Copilot CLI (…install docs URL…), then call a helper (me()) that doesreadline.createInterface({input: process.stdin, output: process.stdout}).question("Install GitHub Copilot CLI? ['y/N'] ", callback).readline.question()call is a blocking, interactive prompt with no timeout. Whatever process CodeMie used to launch this shim, its stdin is still attached to CodeMie's own controlling terminal (we confirmed this too —lsofshowed the child's stdin/stdout as/dev/ttys00x, the real TTY, not/dev/nullor a pipe CodeMie was driving).codemie updateis left synchronously waiting on this child process to exit, so CodeMie itself hangs, even though the actual bug (an interactive prompt with no timeout) lives in the VS Code-shipped shim, not in CodeMie's own code.In short: CodeMie shells out to a third-party interactive script to check a version number, doesn't give it a timeout, doesn't suppress its ability to prompt, and has no fallback if that third-party script decides to ask a question instead of just returning an error.
A secondary issue we noticed while investigating: GitHub Copilot isn't even listed as a managed agent by
codemie list(that command only shows CodeMie Code, Claude Code, Claude Code ACP, Gemini CLI, OpenCode CLI, OpenAI Codex CLI, Pi, Kimi Code, Kimi Code ACP, and OpenWiki). So this integration is invisible to the user — there's no entry tocodemie uninstall, no flag to skip it, and no documentation mentioning thatcodemie update/codemie listreach out to VS Code's Copilot Chat extension data at all. A user hitting this hang has essentially no way to discover, from CodeMie's own UI, what's actually blocking them — you have to do exactly the OS-level forensics described above.Steps to Reproduce
~/Library/Application Support/Code/User/globalStorage/github.copilot-chat/copilotCli/exists — on Linux/Windows this would be the equivalent VS Code user-data path).npm ls -g @github/copilot→ empty, andcommand -v copilot→ resolves only to the VS Code extension's bundled shim path, not a real binary elsewhere onPATH).codemie update(with or without piping stdin, e.g.printf '\n' | codemie update), or simplycodemie list.- Checking for updates...(forupdate) or start printing the agent list (forlist), then stop advancing entirely. No error, no timeout, no further output — CPU usage on the CodeMie process itself drops to ~0% because it's just waiting onwait()/similar for its child.codemie update --verboseinstead to see it clearly stop right after logging Claude's version-compatibility check, confirming the Copilot probe is the very next step and where it dies.ps aux | grep copilotCLIShimwill show a liveCode Helper (Plugin)process runningcopilotCLIShim.js --version, parented by a/bin/sh …/copilotCli/copilot --version, parented by thecodemieNode process.lsof -p <that pid>shows no sockets and stdin/stdout on the real tty. It will sit there indefinitely — we let it run for several minutes with no change.Expected Behavior
codemie update/codemie listshould complete (or at least fail with a clear error) within a bounded, short time regardless of what any external tool it probes decides to do. Concretely, we'd suggest:--versioncall hasn't returned by then, treat that agent as "unknown/not installed" and move on, rather than blocking the whole command./dev/null(or an already-closed pipe). That alone would fix this specific case: the VS Code shim'sreadline.question()would hit EOF immediately and get an empty answer instead of blocking forever, lettingCe()/Ye()return promptly.codemie list), consider whether probing it duringupdate/listis even in scope — if it's meant to be a "detect what else is installed on this machine" convenience feature, it should be clearly optional (a config flag, or at minimum documented), not a silent, unbounded dependency of the core update/list flow.Actual Behavior
codemie updateandcodemie listhang forever — we let one run for several minutes with no output change and 0% CPU before manually diagnosing and killing the hidden child process tree ourselves. There is no timeout, no error message, and nothing in CodeMie's own output (even with--verbose) that indicates it's waiting on GitHub Copilot CLI detection specifically, let alone that the underlying cause is a third-party interactive prompt it can never answer. A typical user would have no way to know this is even happening — they'd just conclude "codemie is broken" or "my network is slow" and either give up or file a much less specific bug report than this one.As a stop-gap on our end (documented here so it's clear this is a workaround, not a fix we think is sufficient), we wrapped our own call to
codemie updatein a shell function with a hard ~20 second kill-timeout, and treat a timeout from it as non-fatal (log a warning, continue with the rest of our update script). We picked 20s empirically: the rest of CodeMie's own version-check work (Claude, etc.) reliably finishes in well under that before the Copilot probe is reached and hangs. We'd very much rather not need this workaround at all.CodeMie CLI Version
0.15.0
Which agent are you using?
Not applicable / General CLI
Which provider are you using?
AI/Run SSO
Model
claude-sonnet-5
Node.js Version
v26.8.1
Operating System
macOS
Configuration (Redacted)
{ "version": 2, "activeProfile": "default", "profiles": { "default": { "provider": "ai-run-sso", "apiKey": "<REDACTED>", "baseUrl": "https://codemie.lab.epam.com/code-assistant-api", "model": "claude-sonnet-5", "haikuModel": "claude-haiku-4-5-20251001", "sonnetModel": "claude-sonnet-5", "opusModel": "claude-opus-5", "name": "default" }, "airun-assistant-vscode": { "name": "airun-assistant-vscode", "provider": "ai-run-sso", "baseUrl": "https://codemie.lab.epam.com/code-assistant-api", "authMethod": "sso", "model": "claude-4-5-sonnet", "timeout": 60000, "debug": true } }, "codemieSkills": [], "codemieAssistants": [], "workspace": { "codeMieUrl": "https://codemie.lab.epam.com", "codeMieProject": "<REDACTED>" } }Error Logs
Additional Context
codemie update,codemie update --verbose, andcodemie list), always at the same point, always with the same hungcopilotCLIShim.jschild.lsof -p <pid>on the hung process shows zero open sockets. Anyone else hitting "codemie update hangs" who assumes it's their network/VPN/proxy will waste time chasing the wrong cause — this is a purely local subprocess/stdin issue.sample <pid>shows the main thread parked inkeventthe entire time, i.e., truly blocked, not making slow progress.~/Library/Application Support/Code/User/globalStorage/github.copilot-chat/copilotCli/copilot(macOS path; the Windows/Linux equivalents would be under VS Code's respectiveglobalStoragelocations) and its JS payload (copilotCLIShim.js) carries a comment stating it was copied frommicrosoft/vscode. We're flagging this so your team doesn't spend time looking for this bug inside your own version-check code for the wrong agent — the trigger is CodeMie's call into this file, not anything wrong with Claude/Gemini/OpenCode/etc. detection.codemie updatewith a hard 20-second kill-timeout that treats a timeout as non-fatal and lets the rest of our update script continue. Happy to share the exact wrapper if useful, but it's really just aspawn + sleep timer + SIGTERMpattern — nothing CodeMie-specific.