fix(bin): rewrite launcher as cross-platform Node.js script (fixes Windows global install)#577
Open
fix(bin): rewrite launcher as cross-platform Node.js script (fixes Windows global install)#577
Conversation
The previous launcher was a POSIX shell script with `#!/bin/sh`. When `npm install -g @tobilu/qmd` runs on Windows, npm reads that shebang and generates cmd/ps1/sh shims that try to route through `/bin/sh` — which doesn't exist on Windows, so `qmd` fails immediately after a successful install from every shell (cmd, PowerShell, Git Bash). Rewrite the launcher in Node.js with a `#!/usr/bin/env node` shebang so npm generates native shims that invoke `node` directly on every platform. The runtime detection logic is preserved verbatim: - package-lock.json present → node (npm install) - bun.lock or bun.lockb present → bun - no lockfile → node Node is launched via `process.execPath` (guaranteed to exist, no PATH lookup). Bun is launched by name; on Windows this needs `shell: true` so PATHEXT resolves `bun.exe`/`bun.cmd`. The shell-based test at `test/launcher-detection.test.sh` continues to document the intended detection behavior; its `detect_runtime` helper mirrors the JS implementation. A platform-agnostic vitest version can follow in a separate PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
npm install -g @tobilu/qmdon Windows installs successfully but produces aqmdcommand that fails in every shell (cmd, PowerShell, Git Bash).Root cause:
bin/qmdhas a#!/bin/shshebang. When npm generates its cmd/ps1/sh shims on Windows, it reads that shebang and routes them through/bin/sh— a path that doesn't exist on Windows:So the shim dies before any qmd code runs.
Fix
Rewrite
bin/qmdas a Node.js script with a#!/usr/bin/env nodeshebang. npm then generates native shims that invokenodedirectly on every platform. The runtime-detection logic is preserved verbatim:package-lock.jsonpresent →node(npm install)bun.lock/bun.lockbpresent →bunnodeImplementation notes:
process.execPath(guaranteed to exist, skips PATH resolution, avoids thechild_processshell: truedeprecation warning).shell: truesoPATHEXTresolvesbun.exe/bun.cmd.fs.realpathSync, matching the old shellreadlinkloop, sonpm linkkeeps working.Testing
qmd --helpworks from cmd, PowerShell, and Git Bash afternpm install -g.test/launcher-detection.test.shstill documents the intended detection behavior; itsdetect_runtimehelper mirrors the JS implementation. A platform-agnostic vitest version can follow in a separate PR (would also let Windows CI catch regressions — currently CI only runs Linux + macOS).Alternative considered
Pointing
bin.qmdinpackage.jsondirectly atdist/cli/qmd.js(which already has a Node shebang). That's simpler but drops the bun-vs-node lockfile detection, so I kept the launcher.