Repository navigation
Windows: detected launchers (venv, mvnw, gradlew, bin/rails) do not run in cmd.exe #8
Description
Found by reading the code while reviewing #5. Not yet reproduced on a Windows machine.
Problem
When commands.runner is unset, frameworks.mjs picks a launcher for the project. Three of the choices do not run on Windows, where the record command goes through cmd.exe (runShell in manage.mjs uses shell: true, which is %ComSpec%).
| Framework | Launcher chosen today | Why it fails on Windows |
|---|---|---|
| pytest, unittest | .venv/bin/appmap-python .venv/bin/pytest |
venvBin looks for .venv/Scripts/appmap-python, but the file is appmap-python.exe, so the venv is never found and the plain appmap-python pytest runs instead. If it were found, cmd.exe would still refuse .venv/Scripts/appmap-python (see the ./ note below). |
| maven | ./mvnw test |
cmd.exe reads ./mvnw as the command . with a switch /mvnw: '.' is not recognized as an internal or external command. |
| gradle | ./gradlew appmap test |
Same. |
| rails-test | bin/rails test |
bin/rails has no extension, so PATHEXT does not help, and the slash breaks the lookup the same way. It needs ruby bin/rails test. |
Note on the wrappers: cmd.exe does add the PATHEXT suffixes when it looks up a command, and searches the current directory first. So mvnw test alone finds mvnw.cmd, and gradlew appmap test finds gradlew.bat. The ./ prefix is the only problem. (This works in PowerShell and Git Bash, but the engine runs cmd.exe.)
Suggested fix
Give resolveRunner and the detectRunner functions a platform parameter (default process.platform), the way detectMaxCommandLength already takes one.
On win32:
venvBinalso checks forappmap-python.exe, andpythonLauncherreturns.venv\Scripts\appmap-python .venv\Scripts\pytest.- maven returns
mvnw testwhenmvnw.cmdexists (no./). - gradle returns
gradlew appmap testwhengradlew.batexists (no./). - rails-test defaults to
ruby bin/rails test.
Also update the runner: example in appmap-gold-traces/SKILL.md (it shows .venv/bin/appmap-python pytest) to mention the Windows form.
Test cases needed
Unit tests in frameworks.test.mjs, next to the existing detect: tests, passing platform: 'win32' so they run on any machine. Each one builds a temp directory with the marker files:
- A dir holding
.venv/Scripts/appmap-python.exegives.venv\Scripts\appmap-python .venv\Scripts\pytest. - The same for
venv/and for unittest (... python -m unittest). - A dir holding both
mvnwandmvnw.cmdgivesmvnw testonwin32and./mvnw testelsewhere. - The same for
gradlewandgradlew.bat. - A dir holding only
mvnw(no.cmd) falls back tomvn testonwin32. - rails-test gives
ruby bin/rails testonwin32andbin/rails testelsewhere. - An explicit
commands.runneris still never overridden onwin32. - uv, Poetry and Pipenv detection is unchanged on
win32.
One test that runs on the real shell, to settle the cmd.exe behaviour with evidence (CI runs the tests on Windows now, #11): make a temp dir with a mvnw.cmd that exits 0, run mvnw test and ./mvnw test through spawnSync(command, { shell: true }), and assert that the first starts and the second does not. On macOS and Linux the same test can use a mvnw script and assert that ./mvnw test starts.
Activity
dividedmind commentedon Sep 22, 2026
FWIW as far as I know ./mvnw and ./gradlew should automatically route to bat/cmd files due to how cmd.exe looks up commands – it looks for executable files by adding suffixes and plain mvnw/gradlew don't have an executable suffix; it does need double-checking on Windows to confirm. venv/ruby issues are probably legit.
kgilpin commentedon Sep 22, 2026
Agreed on the suffix lookup:
mvnw testalone findsmvnw.cmd, so the fix does not need to name the.cmd/.batfile. The problem is the./prefix:cmd.exereads./mvnwas the command.with a switch/mvnw('.' is not recognized as an internal or external command). PowerShell and Git Bash accept it, but the engine runs the record command withshell: true, which is%ComSpec%=cmd.exe. So on Windows the launcher should bemvnw testandgradlew appmap testwith no./.I've updated the issue with that, and added a test that runs
mvnw testand./mvnw testthrough the real shell on the Windows CI runner, so this is checked with evidence rather than memory.