Summary
On Windows, connecting OpenCode / Claude Code / Codex in the desktop app fails even when the CLIs work fine in a terminal.
OpenCode error shown in UI:
No models configured in OpenCode. Run "opencode" to set up
(Claude/Codex fail for the same root cause when installed via npm.)
Root cause
resolve_cli in crates/op-host-services/src/model_discovery.rs tries Windows extensions in this order:
[", ".exe", ".cmd", ".bat"]
npm global installs put an extensionless Unix shell script (#!/bin/sh) next to the real Windows entry:
| Path |
What it is |
%APPDATA%\npm\opencode |
Unix shim — not a valid Win32 PE |
%APPDATA%\npm\opencode.cmd |
Real Windows launcher |
...\node_modules\opencode-ai\bin\opencode.exe |
Real binary |
Because candidate.is_file() is true for the extensionless shim, resolve_cli returns that path first. Command::new(exe).arg("models").output() then fails (invalid application for this OS), discover_opencode() gets an empty list, and connect_opencode() reports “No models configured…”.
Terminal works because PowerShell/CMD prefer .ps1 / .cmd, not the bare shim.
Same pattern for claude and codex under %APPDATA%\npm\.
Repro
- Windows 10/11
- Install CLIs via npm, e.g.
npm i -g opencode-ai (and/or Claude Code / Codex)
- Confirm terminal works:
opencode models lists provider/model lines
- Launch OpenPencil desktop (Start Menu / shortcut is enough)
- Settings → connect OpenCode
Expected: models listed, connect succeeds
Actual: No models configured in OpenCode. Run "opencode" to set up
Local proof (CreateProcess-style)
# Fails — bare npm shim is a shell script
Start-Process -FilePath "$env:APPDATA\npm\opencode" -ArgumentList models -NoNewWindow -Wait
# → not a valid application for this OS platform
# Works
& "$env:APPDATA\npm\opencode.cmd" models
& "$env:APPDATA\npm\node_modules\opencode-ai\bin\opencode.exe" models
Workaround
Rename/remove the extensionless shims so resolution falls through to .cmd:
cd $env:APPDATA\npm
Rename-Item opencode opencode.sh.bak -ErrorAction SilentlyContinue
Rename-Item claude claude.sh.bak -ErrorAction SilentlyContinue
Rename-Item codex codex.sh.bak -ErrorAction SilentlyContinue
Then fully quit and restart OpenPencil.
Suggested fix
On Windows, do not treat extensionless files as executables in resolve_cli (or try .exe / .cmd / .bat before ""`).
Minimal change sketch:
// windows: prefer real PE / cmd shims over npm's extensionless #!/bin/sh
let exts: &[&str] = if cfg!(windows) {
&[".exe", ".cmd", ".bat", "] // or drop " entirely on Windows
} else {
&["]
};
Optionally also prefer resolving through to the real .exe under node_modules\...\bin\ when the hit is an npm shim.
Environment (reporter)
- OpenPencil desktop (latest pre-release, e.g. v0.8.2)
- Windows (
win32)
opencode 1.18.7 via npm (%APPDATA%\npm)
opencode models works in PowerShell and lists many models
- Config present at
%USERPROFILE%\.config\opencode\opencode.json (not the old ~\.opencode\config.json path the UI hint mentions)
Related code
crates/op-host-services/src/model_discovery.rs — resolve_cli, discover_opencode
crates/op-host-services/src/provider_probe.rs — connect_opencode empty-models message
crates/op-host-services/src/cli_resolver_windows.rs — GUI PATH fallbacks (includes %APPDATA%\npm, which is correct; the bug is extension order)
Thanks!
Summary
On Windows, connecting OpenCode / Claude Code / Codex in the desktop app fails even when the CLIs work fine in a terminal.
OpenCode error shown in UI:
(Claude/Codex fail for the same root cause when installed via npm.)
Root cause
resolve_cliincrates/op-host-services/src/model_discovery.rstries Windows extensions in this order:npm global installs put an extensionless Unix shell script (
#!/bin/sh) next to the real Windows entry:%APPDATA%\npm\opencode%APPDATA%\npm\opencode.cmd...\node_modules\opencode-ai\bin\opencode.exeBecause
candidate.is_file()is true for the extensionless shim,resolve_clireturns that path first.Command::new(exe).arg("models").output()then fails (invalid application for this OS),discover_opencode()gets an empty list, andconnect_opencode()reports “No models configured…”.Terminal works because PowerShell/CMD prefer
.ps1/.cmd, not the bare shim.Same pattern for
claudeandcodexunder%APPDATA%\npm\.Repro
npm i -g opencode-ai(and/or Claude Code / Codex)opencode modelslistsprovider/modellinesExpected: models listed, connect succeeds
Actual:
No models configured in OpenCode. Run "opencode" to set upLocal proof (CreateProcess-style)
Workaround
Rename/remove the extensionless shims so resolution falls through to
.cmd:Then fully quit and restart OpenPencil.
Suggested fix
On Windows, do not treat extensionless files as executables in
resolve_cli(or try.exe/.cmd/.batbefore ""`).Minimal change sketch:
Optionally also prefer resolving through to the real
.exeundernode_modules\...\bin\when the hit is an npm shim.Environment (reporter)
win32)opencode1.18.7 via npm (%APPDATA%\npm)opencode modelsworks in PowerShell and lists many models%USERPROFILE%\.config\opencode\opencode.json(not the old~\.opencode\config.jsonpath the UI hint mentions)Related code
crates/op-host-services/src/model_discovery.rs—resolve_cli,discover_opencodecrates/op-host-services/src/provider_probe.rs—connect_opencodeempty-models messagecrates/op-host-services/src/cli_resolver_windows.rs— GUI PATH fallbacks (includes%APPDATA%\npm, which is correct; the bug is extension order)Thanks!