Summary
On Windows, the code the bundle labels src/services/tags.ts queries git with
execSync(<string command>) and does not pass windowsHide: true. Node runs a
string command through cmd.exe on Windows, and windowsHide defaults to
false, so that child is created with a console window. Everything this plugin
runs inside the OpenCode service process, and on this machine console processes
spawned from that process demonstrably do get visible windows (see Actual
Behavior). The resulting window takes foreground focus, which breaks IME
composition while a session is in use.
Environment
- opencode version: v2.0.21 (latest)
- OS: Windows 11 25H2, build 26200.8655 (win32 x64). Note: the version API still
reports 10.0.26200 because Windows 11 kept the 10.0 major/minor; build >= 22000
is what identifies Windows 11.
- Terminal: OpenCode desktop app (Electron)
- Shell: C:\WINDOWS\system32\cmd.exe
- Install/channel: release (latest)
- Active plugins: opencode-supermemory 2.0.15, superpowers (git)
Reproduction
- Run OpenCode v2 on Windows with this plugin enabled, inside a git repository.
- Send a message and let the agent take a turn.
- Console windows appear repeatedly, observed at roughly one per second, titled
C:\WINDOWS\system32\cmd.exe.
Expected Behavior
The plugin's internal git queries for tags/context should never create a
visible window.
Actual Behavior
With a 60 ms process/window watcher running during an active session, over a
133 second span (19:15:11 - 19:17:24):
162 x cmd
161 x conhost
145 x git
10 x node
That is roughly one cmd.exe + conhost.exe pair per second, frequently with
git children. In total 105 new visible ConsoleWindowClass windows were
recorded in that 133 s span — about one every 1.3 seconds. Newly created
visible windows in the same capture (window class ConsoleWindowClass):
19:16:56.644 | class=ConsoleWindowClass title='C:\WINDOWS\system32\cmd.exe'
19:16:57.140 | class=ConsoleWindowClass title='C:\WINDOWS\system32\cmd.exe'
19:16:57.687 | class=ConsoleWindowClass title='C:\WINDOWS\system32\cmd.exe'
19:16:59.181 | class=ConsoleWindowClass title='C:\WINDOWS\system32\cmd.exe'
19:17:00.288 | class=ConsoleWindowClass title='C:\WINDOWS\system32\cmd.exe'
19:17:01.743 | class=ConsoleWindowClass title='C:\WINDOWS\system32\cmd.exe'
and one titled after a git binary:
19:15:46.517 | class=ConsoleWindowClass title='C:\Program Files\Git\cmd\git.exe'
That last line is the important one for this report: it shows that a console
process spawned from the OpenCode service process on this machine is created
with a visible window — which is exactly the mechanism described above.
Capture method: WMI Win32_ProcessStartTrace could not be subscribed on this
machine (Call cancelled), so this is polling based and processes shorter than
the 60 ms interval may be undercounted.
Impact: with a Chinese IME (Google Pinyin) the repeated focus stealing makes the
candidate window flicker and typing produce nothing.
Caveat on attribution, stated plainly: in the same capture, OpenCode's own MCP
server startup also spawns cmd.exe /d /s /c "npx ...", and those children
include node.exe and git-remote-https.exe. The MCP servers were disabled at
the same time as this patch was applied, so this capture cannot establish how
much of the observed flashing came from the plugin specifically. The missing
windowsHide is nonetheless a defect on its own: on Windows it creates a
console window whenever this code runs in a process without a console.
Additional Context
The offending calls (dist/v2/index.js). stdio does not suppress a console
window on Windows — windowsHide: true is what does:
const gitCommonDir = execSync("git rev-parse --git-common-dir", {
cwd: directory,
encoding: "utf-8",
stdio: ["pipe", "pipe", "pipe"]
}).trim();
dist/v2/index.js contains six such call sites (git rev-parse --git-common-dir, git rev-parse --show-toplevel x3, git config user.email,
git remote get-url origin). The same execSync(...) + options pattern also
appears in dist/cli.js, dist/index.js and dist/server.js.
The CLI already passes the option, which suggests an oversight rather than
intent:
execFile(command, args, { windowsHide: true }, (error) => { ... });
Two smaller observations:
getGitRoot() is not memoized (repoInfoCache only covers
getGitRepoInfo()), so it shells out to git on every call.
execSync with a string command also routes through cmd.exe, adding a
process layer that execFileSync("git", [...]) would avoid.
Suggested fix: pass windowsHide: true in those options objects (and/or switch
to execFileSync with an argv array).
Workaround applied locally: windowsHide: true added to all six call sites in
dist/v2/index.js. After that change, a 20 second watch during a turn showed a
single cmd.exe, not visible.
Summary
On Windows, the code the bundle labels
src/services/tags.tsqueries git withexecSync(<string command>)and does not passwindowsHide: true. Node runs astring command through
cmd.exeon Windows, andwindowsHidedefaults tofalse, so that child is created with a console window. Everything this pluginruns inside the OpenCode service process, and on this machine console processes
spawned from that process demonstrably do get visible windows (see Actual
Behavior). The resulting window takes foreground focus, which breaks IME
composition while a session is in use.
Environment
reports
10.0.26200because Windows 11 kept the 10.0 major/minor; build >= 22000is what identifies Windows 11.
Reproduction
C:\WINDOWS\system32\cmd.exe.Expected Behavior
The plugin's internal
gitqueries for tags/context should never create avisible window.
Actual Behavior
With a 60 ms process/window watcher running during an active session, over a
133 second span (19:15:11 - 19:17:24):
That is roughly one
cmd.exe+conhost.exepair per second, frequently withgitchildren. In total 105 new visibleConsoleWindowClasswindows wererecorded in that 133 s span — about one every 1.3 seconds. Newly created
visible windows in the same capture (window class
ConsoleWindowClass):and one titled after a git binary:
That last line is the important one for this report: it shows that a console
process spawned from the OpenCode service process on this machine is created
with a visible window — which is exactly the mechanism described above.
Capture method: WMI
Win32_ProcessStartTracecould not be subscribed on thismachine (
Call cancelled), so this is polling based and processes shorter thanthe 60 ms interval may be undercounted.
Impact: with a Chinese IME (Google Pinyin) the repeated focus stealing makes the
candidate window flicker and typing produce nothing.
Caveat on attribution, stated plainly: in the same capture, OpenCode's own MCP
server startup also spawns
cmd.exe /d /s /c "npx ...", and those childreninclude
node.exeandgit-remote-https.exe. The MCP servers were disabled atthe same time as this patch was applied, so this capture cannot establish how
much of the observed flashing came from the plugin specifically. The missing
windowsHideis nonetheless a defect on its own: on Windows it creates aconsole window whenever this code runs in a process without a console.
Additional Context
The offending calls (
dist/v2/index.js).stdiodoes not suppress a consolewindow on Windows —
windowsHide: trueis what does:dist/v2/index.jscontains six such call sites (git rev-parse --git-common-dir,git rev-parse --show-toplevelx3,git config user.email,git remote get-url origin). The sameexecSync(...)+ options pattern alsoappears in
dist/cli.js,dist/index.jsanddist/server.js.The CLI already passes the option, which suggests an oversight rather than
intent:
Two smaller observations:
getGitRoot()is not memoized (repoInfoCacheonly coversgetGitRepoInfo()), so it shells out togiton every call.execSyncwith a string command also routes throughcmd.exe, adding aprocess layer that
execFileSync("git", [...])would avoid.Suggested fix: pass
windowsHide: truein those options objects (and/or switchto
execFileSyncwith an argv array).Workaround applied locally:
windowsHide: trueadded to all six call sites indist/v2/index.js. After that change, a 20 second watch during a turn showed asingle
cmd.exe, not visible.