Skip to content

Resolve npm .cmd-shim backends on Windows - #2

Merged
rodion-m merged 4 commits into
CodeAlive-AI:mainfrom
av-frox:fix/windows-cmd-shim-binary-resolution
Oct 5, 2026
Merged

rodion-m merged 4 commits into
CodeAlive-AI:mainfrom
av-frox:fix/windows-cmd-shim-binary-resolution

Conversation

@av-frox

@av-frox av-frox commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Fixes #1.

What was wrong

resolve_binary() uses shutil.which. Under native Windows Python that walks PATHEXT and returns the .CMD sibling with backslashes:

>>> shutil.which("codex")
'C:\\Users\\<user>\\.npm-global\\codex.CMD'

$ which codex
/c/Users/<user>/.npm-global/codex

The resolved value is consumed by bash in backend_run.sh, and neither half of the existing check can accept it: command -v does not resolve an absolute backslash path, and [[ -x ]] is false because npm writes the .cmd shim without the executable bit.

$ ls -la ~/.npm-global/ | grep codex
-rwxr-xr-x  421  codex        <- the launcher bash can use
-rw-r--r--  341  codex.cmd    <- what shutil.which returns
-rwxr-xr-x  869  codex.ps1

Result: every npm-installed backend (codex, opencode, gemini) is rejected with a false backend CLI not found, and the real backend error stays hidden behind it.

The change

This is option B from the issue — the fallback lives in the shell layer that actually consumes the value, so resolve_binary and its Python-side callers keep their current contract. Happy to move it into resolve_binary instead if you prefer option A; the test does not care which layer fixes it.

When $BIN is unusable and looks like a resolved path, retry with the extensionless basename. A bare name that resolves to nothing fails exactly where it did before, so a genuine misconfiguration is still reported.

Test

New section in scripts/tests/run.sh, built on the existing fakes: a shimcodex + non-executable shimcodex.cmd pair, with PORCH_BIN_CODEX pointing at the backslash-spelled .CMD path.

The condition is reproducible on any platform — on Linux that path is simply an unresolvable filename — so the regression is covered by the existing ubuntu-latest / macos-latest job that runs run.sh, without needing the Windows job to install a backend CLI.

Verified in a Linux environment:

run result
baseline (main) 957 passed, 0 failed
with this PR 960 passed, 0 failed
test kept, fix reverted windows .cmd path falls back to extensionless launcher and windows .cmd path is not reported missing both FAIL with the reported error; missing bare binary still fails still passes

scripts/tests/platform_test.py also passes (20 tests, 4 skipped).

Note on the Windows CI gap

porch-smoke.yml does cover windows-latest, but no backend CLI is installed there, so a .cmd shim is never resolved and this class of bug is invisible to the matrix. The test added here closes that without changing the workflow. If you would rather also exercise it natively on Windows, that would need a shim fixture plus a Windows-enabled slice of run.sh — happy to do that in a follow-up if it is useful.

🤖 Generated with Claude Code

av-frox and others added 4 commits September 22, 2026 12:46
The backend contract resolves CLI paths with Python's shutil.which. Under
native Windows Python that walks PATHEXT and returns the `foo.CMD` sibling
spelled with backslashes. The value is then consumed by bash, which can
neither `command -v` that path nor exec-test it: npm writes the .cmd shim
without the executable bit, and the launcher bash can use is the
extensionless name on its own PATH.

Every npm-installed backend was therefore rejected with a false
"backend CLI not found", which also masked the real backend error.

Fall back to the extensionless basename when the resolved value looks like
a path and is unusable. A bare name that resolves to nothing still fails
where it did before.

Fixes CodeAlive-AI#1

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Resolve version conflicts in .claude-plugin/*.json by taking upstream
2.0.0-beta.1; the 1.3.5 bump from this branch is superseded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Re-run smoke tests after a flaky ubuntu failure caused by interleaved
writes to the fake backend argv log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rodion-m
rodion-m merged commit 181189b into CodeAlive-AI:main Oct 5, 2026
0 of 8 checks passed
@rodion-m

rodion-m commented Oct 5, 2026

Copy link
Copy Markdown
Member

merged. thanks for contribution!

@av-frox
av-frox deleted the fix/windows-cmd-shim-binary-resolution branch October 10, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows/Git Bash: npm .cmd-shim backends fail with false "backend CLI not found"

2 participants