You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
currently, node's cli interface is pretty simple and lean,
it mainly accepts flags that start with two dashes, or sometimes a single dash for some aliases.
additionally, many flags depend on each other or imply using another flag.
now that more and more flags are added to node, (and each new flag is heavily considered before adding to avoid options bloat), I propose we support a more complex cli interface with sub-commands.
this issue has come up before when adding node --run, and to avoid blocking that - the discussion was postponed, so I went ahead and opened this issue.
If I recall, the main concern was node run or node test is a breaking change since it today runs node run.js or node test.js accordingly - that can be addressed with releasing this gradually as semver-major with a deprecation warning for a few versions prior to the actual change
some groups/clusters of commands that might fit using sub commands:
node --run
node --watch, --watch-path
node --test
node --build-snapshot
What is the feature you are proposing to solve the problem?
I've voiced concerns about this various times in the past, perhaps most recently in this comment. Don't get me wrong, subcommands are great, and if we were to redesign Node.js from scratch we likely should use them. However, ...
I have reason to believe that a significant number of users rely on the fact that node test runs either test.js or test/index.js, and the same is likely true for node run. So while semver-major releases technically allow us to break things, I think this would cause significant breakage. There's probably many semi-maintained npm modules that use node test (or variations thereof) as their npm test script.
More generally, accepting either a positional argument or a subcommand in the same location is an anti-pattern in my mind. We unfortunately already have node inspect, so Node.js is already following something that I'd consider an anti-pattern, but that shouldn't be a loophole for us to further commit to that anti-pattern.
The only semi-reasonable way I see is to fully deprecate node xyz, where xyz would usually cause the execution of whatever xyz resolves to. Of course, this would be a huge breaking change and would likely take years, but anything less than this will introduce more and more inconsistencies, and each new subcommand would cause new breakage and deprecation cycles.
The only semi-reasonable way I see is to fully deprecate node xyz, where xyz would usually cause the execution of whatever xyz resolves to. Of course, this would be a huge breaking change and would likely take years, but anything less than this will introduce more and more inconsistencies, and each new subcommand would cause new breakage and deprecation cycles.
We can doc-only deprecate the current behavior right now, and releasing that would take days to weeks. But actually moving node xyz to end-of-life seems like a huge breaking change to me. (Then again, some project members are more open to rapidly breaking things than myself, so maybe it would just take two semver-majors or so.)
We could take some pragmatic, not very elegant steps to avoid reaching end-of-life status, e.g., by still allowing node xyz whenever xyz looks like a path (e.g., contains a file extension or a directory separator). But in any case, we'll break the very basics of how people run JavaScript files with Node.js.
For files with the same name as commands, the project could adopt what many CLIs do, which is if a value is within quotes, don't treat as a CLI flag (IE "--hello" is a file, while --hello is a CLI argument)
I'm not aware of anything else that does this, but IMO this would be terribly confusing to users -- in many cases the quotes would be processed by the shell and wouldn't be seen by the program being run (i.e. node).
I'm +1 on making this breaking change. I think the UX for cli flags are really bad that even I have some trouble understanding if feature X is working with feature Y.
Reacted by Chemi Atlow, Vas Sudanagunta, Jacob Smith and Pietro Marchini
There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the
never-staleIssues and PRs exempt from automated stale handling.
label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.
There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the
never-staleIssues and PRs exempt from automated stale handling.
label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.
Another option, that is backward compatible, is for node test to work as it does today IFF test resolves to a script, and otherwise to invoke the test subcommand.
If you think of the test subcommand as the built-in default resolution for node test, user overridable by the presence of a script named test in the cwd, there is both rhyme and reason to this behavior.
Why bother? Because the current node CLI is unwieldy and will only get worse. For example see discussions under #51384 and nodejs/test-runner#13.
Activity
tniessen commentedon Jun 17, 2024
I've voiced concerns about this various times in the past, perhaps most recently in this comment. Don't get me wrong, subcommands are great, and if we were to redesign Node.js from scratch we likely should use them. However, ...
I have reason to believe that a significant number of users rely on the fact that
node testruns eithertest.jsortest/index.js, and the same is likely true fornode run. So while semver-major releases technically allow us to break things, I think this would cause significant breakage. There's probably many semi-maintained npm modules that usenode test(or variations thereof) as their npmtestscript.More generally, accepting either a positional argument or a subcommand in the same location is an anti-pattern in my mind. We unfortunately already have
node inspect, so Node.js is already following something that I'd consider an anti-pattern, but that shouldn't be a loophole for us to further commit to that anti-pattern.The only semi-reasonable way I see is to fully deprecate
node xyz, wherexyzwould usually cause the execution of whateverxyzresolves to. Of course, this would be a huge breaking change and would likely take years, but anything less than this will introduce more and more inconsistencies, and each new subcommand would cause new breakage and deprecation cycles.MoLow commentedon Jun 17, 2024
why would that take years?
tniessen commentedon Jun 17, 2024
We can doc-only deprecate the current behavior right now, and releasing that would take days to weeks. But actually moving
node xyzto end-of-life seems like a huge breaking change to me. (Then again, some project members are more open to rapidly breaking things than myself, so maybe it would just take two semver-majors or so.)We could take some pragmatic, not very elegant steps to avoid reaching end-of-life status, e.g., by still allowing
node xyzwheneverxyzlooks like a path (e.g., contains a file extension or a directory separator). But in any case, we'll break the very basics of how people run JavaScript files with Node.js.richardlau commentedon Jun 17, 2024
I think, for example, that preventing
node xyzfrom runningxyzwould stop Node.js shell scripts (i.e. those that begin#!/usr/bin/env node ...) from working.
avivkeller commentedon Jun 17, 2024
richardlau commentedon Jun 17, 2024
I'm not aware of anything else that does this, but IMO this would be terribly confusing to users -- in many cases the quotes would be processed by the shell and wouldn't be seen by the program being run (i.e.
node).avivkeller commentedon Jun 17, 2024
MoLow commentedon Jun 17, 2024
why would adding subcommands break hashbang? I am not following
richardlau commentedon Jun 17, 2024
Because if you have a file called
xyzthat begins:#!/usr/bin/env node ...that has execute permissions and you run it, e.g.
it will end up running the equivalent of
anonrig commentedon Jun 18, 2024
I'm +1 on making this breaking change. I think the UX for cli flags are really bad that even I have some trouble understanding if feature X is working with feature Y.
github-actions commentedon Dec 16, 2024
There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-staleIssues and PRs exempt from automated stale handling.
label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.
github-actions commentedon Jun 15, 2025
There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the never-staleIssues and PRs exempt from automated stale handling.
label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment.
For more information on how the project manages feature requests, please consult the feature request management document.
vassudanagunta commentedon Mar 5, 2026
While I think I'm ok with the breaking change wrt to
node xyz, an alternative to consider is having separate commands:vassudanagunta commentedon Mar 5, 2026
If
node testinvoked thetestsubcommand, then one could usenode -- testto force "test" to be treated as an argument.vassudanagunta commentedon Mar 6, 2026
Another option, that is backward compatible, is for
node testto work as it does today IFFtestresolves to a script, and otherwise to invoke the test subcommand.If you think of the test subcommand as the built-in default resolution for
node test, user overridable by the presence of a script namedtestin the cwd, there is both rhyme and reason to this behavior.Why bother? Because the current node CLI is unwieldy and will only get worse. For example see discussions under #51384 and nodejs/test-runner#13.