Search code examples
javascriptnode.jsnpmnpx

How to make npx run the js cli script in windows?


The Problem - My npx scaffolding script works fine on linux but doesn't work on windows. However I see a lot packages which runs fine on windows but I couldn't find out what they are doing differently. I asked AI tools (Chatgpt/Gemini) they couldn't provide a solution.

What happens on linux? - Script is normally executed by node and works fine.
What happens on windows? - It just opens a new command prompt window doing nothing.

  • I created a npm package @reuk/start for scaffolding my commonly used project templates.
  • I intented to use it as npx script. similar to npx create-vite.
  • For this i created a script and added that to the bin field in my package.json -> "bin": "./bin/cli.js". and published the package.
  • Running the script normally like node ./bin/cli.js works perfectly fine. the only problem is when doing npx @reuk/start it is not invoking the script using node.
  • My cli.js has a shebang #!/usr/bin/env node to tell the interpreter to run it using node. I know shebang only works in unix systems and windows doesn't support it, but how does create-vite work on windows, and why doesn't mine work despite having the similar code?

What am I doing wrong here? And more importantly how do I make it work cross platform seamlessly?

For reference here is the code - @reuk/start | create-vite


Solution

  • It seems that the name of your bin script clashes with a cmd start command.

    The fix could be choosing a more specific name for the command under which you want your script to be available. This name should also be a valid filename to avoid any further issues.

    In package.json:

    "bin": {
      "rvg": "bin/cli.js"
    }
    

    Here is a simplified and technically imprecise explanation of what is going on when you run npx @reuk/start:

    1. npx tries to resolve the package using the usual node.js package resolution mechanism
    2. if nothing is found it installs the package globally
    3. npm sees the bin section in package.json and creates platform-specific wrappers under node_modules/.bin folder. In your case, it adds files named start because another command - @reuk/start is not a valid file name.
    4. npx tries to run start but it resolves to cmd command and not your script.

    To be honest, the last point seems to be a bug, and there are pretty many open bugs related to scoped packages in general, but I have not find any explaining this particular case.