Repository navigation
Description
Description
On Windows, the background service (opencode serve --service) shells out to opencode service status roughly twice a second. The service is started detached, so it owns no console; every one of those cmd.exe children is therefore given a brand-new console window. A newly created console is allowed to take the foreground, so the window steals keyboard focus about every two seconds and interrupts typing in any other application.
A process-start trace shows the exact chain:
cmd.exe /d /s /c "opencode service status"
parent: opencode.exe serve --service
parent: opencode.exe (TUI)
parent: opencode.exe (launcher)
Cadence and cost, measured over 45 seconds: 24 cmd.exe starts (one every ~1.9 s). Each start was followed by conhost.exe, OpenConsole.exe and two further opencode.exe processes, so roughly five process creations per probe, ~160 per minute.
Notes that narrowed it down:
- It is not a failure loop.
opencode service statusreturns a healthy URL while this is happening; it is a heartbeat. - It is not a plugin. The process that runs the command is the core daemon,
opencode serve --service. Third-party TUI plugins were loaded during the capture, but the parent chain is the core service, not a plugin process. - It is not the TUI. Killing the TUI does not stop it, and
opencode service stopis undone within seconds because the TUI starts a replacement daemon immediately.
Impact: on Windows this makes OpenCode actively hostile to use alongside any other application, because it takes focus from whatever the user is typing into.
Plugins
[email protected], [email protected] (TUI-only). The polling process is the core service, not either plugin.
OpenCode version
opencode v2.2.6, Windows build, bun global install (@opencode/cli).
Steps to reproduce
- Use Windows 11 and install opencode 2.2.6 (bun global install; also seen from a scoop-installed copy).
- Launch the TUI without
--standalone, so it uses the background service, from any launcher that does not give the service an inherited console. - Focus another application with a text field and type continuously.
- Every ~2 seconds a console window appears and focus is taken away from the text field.
- Observe the process tree for a few seconds and confirm the spawn:
- child:
cmd.exe /d /s /c "opencode service status" - parent:
opencode.exe serve --service
- child:
- Optional: count the spawns. A WMI
Win32_ProcessStartTracesubscription for 45 seconds gives ~24cmd.exestarts, each followed by a newconhost.exe.
Expected
No console window ever appears. Either:
- the service checks its own status in-process instead of shelling out to the CLI, or
- the spawn passes
windowsHide: true(i.e.CREATE_NO_WINDOW), or avoids the shell entirely by invoking the CLI with arguments rather than a command string.
Screenshot
No screenshot needed: the process-start trace above is the evidence. Terminal flashes are visible, but the parent chain is decisive.
Operating System
Windows 11 Pro, version 10.0.26300, build 26300 (x64).
Terminal
Windows Terminal (default terminal application); the spawned consoles are hosted by OpenConsole.exe from Windows Terminal 1.25.2733.0.
Workaround
Launching with opencode --standalone (private server, no background service) avoids it, at the cost of the background service itself.
Activity
opencodejr commentedon Nov 10, 2026
Thanks for the very detailed trace!
I think this is a duplicate of #52266. That issue tracks the same root cause: the background service (
opencode serve --service) runs without a console on Windows, so any console child it starts withoutCREATE_NO_WINDOWgets its own visible window, which takes focus. The open PR #60471 addresses this by giving the service a windowless console, so unhidden children like yourcmd.exestay hidden.One thing worth knowing: I couldn't find any code in OpenCode 2.2.6 (or on
dev) that runsopencode service statusas a heartbeat. Core doesn't shell out to the CLI for its own status. The server entry points ofoc-flight-deckandoc-plugin-vieware empty stubs, so they aren't the source either. Thecmd /d /s /c "opencode service status"command string most likely comes from something else loaded into the service: another server plugin, a local MCP server, a hook, or a project.opencodeconfig. Look through your global and projectopencode.json(c)and plugin directories for it; that would also stop the ~160 process starts per minute. If you find the source, please add it to #52266.Possible duplicates and related issues, ordered from most to least likely:
tasklist.exe) that steals focusThe bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
nathwn12 commentedon Nov 10, 2026
Same root cause as #52266, and I accept the duplicate: the detached service has no console, so a console child it starts gets a new visible window, and that window takes the foreground. #60471's windowless-console change would fix the symptom no matter which code issues the spawn.
One correction on attribution, because it changes where to look. In my trace the parent of the
cmd.exeis the service itself, for every one of 24 starts in 45 seconds:It is a heartbeat, not a retry:
opencode service statusreturns a healthy URL while it runs.If grep for the literal phrase finds nothing in core, the command is probably assembled from an argv pair, for example
["service", "status"]joined into a shell command line, which a search for the joined string would miss. Searching the service entry point forservicenearstatuswould settle it faster than searching for the phrase.Plugins active during the capture:
oc-plugin-view,oc-flight-deck,oc-stacked. oc-stacked registers no timers; its tools only run when called, and it produced no spawns in the trace. I could not find the phrase in any installed plugin source either.I am happy to re-run the WMI process-start trace against a build containing #60471 and report whether the windows stop; that would also confirm the fix independently of the attribution question.
opencodejr commentedon Nov 10, 2026
Thanks for confirming, and for the careful follow-up on the attribution.
I did search for
"service"as a separate argument in the 2.2.6 source too, not only the full phrase. Apart from the CLI's own command definitions, the only code that builds aservice …command is the desktop app's remote-access pairing (packages/gui-plugins/src/pairing/main.ts). It callsexecFile(cli, [..., "service", ...args], { windowsHide: true })with no shell, and only when pairing settings are read or changed. It can't produce acmd.exe /d /s /c "opencode service status"child, and I found no shell-based spawn in core that runs this on a timer. So I still think the command string comes from something loaded into the service, not from core itself. As you say, though, #60471 fixes the visible window regardless.Your offer to re-run the WMI trace against a build with #60471 would be really useful. Please post the results on #60471 (or #52266) so they're in front of the people working on the fix. If the trace shows which module issues the spawn (for example, the service's loaded plugins and MCP servers at that moment), adding that there would settle the attribution question too.
This issue will still be closed as a duplicate of #52266 as planned. Please follow that issue for updates.
nathwn12 commentedon Nov 10, 2026
Correction to my last note, which I have deleted: strike the speculative part. What stands is measured:
24 starts in 45 seconds (about one every 1.9 s), and the status call returns a healthy URL while it runs, so it is a heartbeat.
I accept the duplicate of #52266. Same root cause, and #60471 fixes the symptom regardless of which code issues the spawn.
opencodejr commentedon Nov 10, 2026
Thanks for the extra searching and for confirming. The measured part (a
cmd.exe /d /s /c "opencode service status"child ofserve --serviceabout every 1.9 s, returning a healthy URL) is clear, and the root cause of the visible window is the one #52266 tracks.If you want to keep tracing the source: plugins can also load from the global
~/.config/opencode/plugins/directory or from a project.opencode/directory, not only from thepluginsarray inopencode.jsonc. Either could explain a plugin appearing that your config doesn't declare.This will be closed as a duplicate of #52266 as planned. Your WMI trace against a build with #60471, posted on that PR, would be a valuable check of the fix.
neriousy commentedon Nov 10, 2026
Thanks for the report. This is the same issue as #52266, so we're tracking it there. Closing as a duplicate. Please add any extra details on #52266.
opencodejr commentedon Nov 11, 2026
Closing this as a duplicate of #52266, as discussed. Thanks for agreeing to it, and for the detailed process trace. The visible, focus-stealing console comes from the same root cause: the background service runs without a console, so its unhidden console children get their own window. The open PR #60471 addresses this whatever process issues the spawn.
Please follow #52266 for updates. Your WMI trace against a build that includes #60471, posted on that PR, would be very welcome. If the windows keep appearing with that change in place, please say so there.