Im my project i am trying to use dotenv-cli with pnpm. I am using PowerShell 7.2.1 on windows. I have monorepo with package api
with script dev
in package.json
.
First what I tried was:
dotenv -e .\.env -- pnpm dev --filter api
And it did not work:
ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL not found: dev
But when I tried:
dotenv -e .\.env -- pnpm -- dev --filter api
It worked well.
As I had read --
signifies the end of command options, after which only positional arguments are accepted. So why do I need to use it twice for my command to work? Why is it working like that?
The problem is that when you call from PowerShell (unlike from cmd.exe
), the command name dotenv
resolves to a PowerShell script, namely dotenv.ps1
, as you report.
When PowerShell calls a PowerShell-native command - including .ps1
files - its own parameter binder interprets the (first) --
argument and removes it; that is, the target command never sees it.
(The semantics of --
is analogous to that of Unix utilities: --
tells the parameter binder to treat subsequent arguments as positional ones, even if they look like parameter (option) names, such as -foo
.)
Thus, unfortunately, you need to specify --
twice in order to pass a single --
instance through to the .ps1
script itself:
# The first '--' is removed by PowerShell's parameter binder.
# The second one is then received as an actual, positional argument by
# dotenv.ps1
dotenv -e .\.env -- -- pnpm dev --filter api
Alternatively, assuming that dotenv.cmd
, i.e. a batch file version of the CLI exists too (and is also in a directory listed in $env:PATH
), you can bypass this problem by calling it explicitly, instead of the .ps1
; when calling external programs (including scripts interpreted by other shells / scripting engines, such as cmd.exe
), PowerShell does not remove --
:
# Calling the batch-file form of the command doesn't require
# passing '--' twice.
dotenv.cmd -e .\.env -- pnpm dev --filter api
Caveat: While it will typically not matter, the way a batch file parses its arguments differs from how PowerShell does it for its native commands.