Why Vercel CLI adds itself to package.json during global version upgrades

I have vercel installed as a global npm package.

Whenever I invoke a vc command in a repo and Vercel detects an upgrade is available, it alerts me and prompts to upgrade, which of course makes sense.

What I’m confused and frequently frustrated by, is that the upgrade then insists on adding vercel as a dependency to the local package.json I happen to be working in, whether or not it is currently there, as well as correspondingly modifying package-lock.json.

Is this by design? If so, why?

My understanding is that Vercel is intended to installed globally, and adding it as a local dependency just adds a bunch of installation complexity, and would require npx anyway. Even if you wanted to, I don’t understand it’s the default behavior.

If relevant, my npm (and node) are installed and managed by Homebrew.

How are you upgrading it? Are you letting the CLI do it itself? There was one other report in the past few days of vercel adding itself to the package.json but that was upon starting a dev server which shouldn’t be related

Homebrew is a possible culprit, if npm checks its global package directory for vercel and doesn’t find it, it might assume it’s a local package that needs to be installed. If you’re using a built in upgrade feature, can you try installing via npm i -g vercel instead and see if you get the same behavior?

It is installed globally via npm i -g vercel.

And yes, the upgrade process I’m using is its self-updater, by accepting y when vercel detects an upgrade available, when I invoke just about any vc command while within a project.

So even though my vercel is installed globally with NPM, it keeps adding itself locally within its own upgrade process.

I actually have an old PR which I think will address this, though I had it marked as draft until just now due to an (unrelated?) test failure. Trying again: [cli] Provide correct upgrade command for Homebrew-managed npm by unitof · Pull Request #14487 · vercel/vercel · GitHub

Noting that this is still happening. I just ran vc ls in a local NextJS repo, and after the output vc prompted for an upgrade. I accepted, but vercel added itself to package.json and package-lock.json:

wv-redirector ▶ vc ls
vc ls
Vercel CLI 54.18.2 (Node.js 20.17.0)
> Deployments for nocomment/wv-redirector [209ms]

[list of deployments removed]

> To display the next page, run `vercel ls --next 1726067481034`

Update available for Vercel CLI (v54.18.2 → v54.20.0)
Changelog: https://github.com/vercel/vercel/releases/tag/vercel%4054.20.0
? Would you like to upgrade now? yes
> Success! Vercel CLI has been upgraded to v54.20.0 successfully!
? Enable automatic CLI updates for future releases? yes
wv-redirector ▶ git st
On branch main
Your branch is up to date with 'github/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   lib/redirects.ts
	modified:   package-lock.json
	modified:   package.json

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.tool-versions
	lib/redirect-matcher.ts

no changes added to commit (use "git add" and/or "git commit -a")
wv-redirector ▶ git diff package.json
diff --git i/package.json w/package.json
index f19cd3a..ae9dabc 100644
--- i/package.json
+++ w/package.json
@@ -1,10 +1,12 @@
 {
   "dependencies": {
-    "next": "^12.1.6"
+    "next": "^12.1.6",
+    "vercel": "^54.20.0"
   },
   "devDependencies": {
     "@types/node": "^17.0.33",
     "@types/react": "^18.0.9",
+    "tsx": "^4.23.0",
     "typescript": "^4.6.4"
   }
 }
wv-redirector ▶ 

My vc bin is insalled via npm i -g vercel. npm is installed via Homebrew (along with node), and in this repo npm is handled by a mise shim to match my node version to Vercel’s:

wv-redirector ▶ where vc
/opt/homebrew/bin/vc
wv-redirector ▶ where vercel
/opt/homebrew/bin/vercel
wv-redirector ▶ npm ls vc
wv-redirector@ /Users/jacob/repos/nc/wv-redirector
└── (empty)

wv-redirector ▶ npm ls vercel
wv-redirector@ /Users/jacob/repos/nc/wv-redirector
└── vercel@54.20.0

wv-redirector ▶ npm ls vercel -g
/Users/jacob/.local/share/mise/installs/node/20.17.0/lib
└── (empty)

wv-redirector ▶ npm ls vc -g
/Users/jacob/.local/share/mise/installs/node/20.17.0/lib
└── (empty)

wv-redirector ▶ cd
~ ▶ where vercel
/opt/homebrew/bin/vercel
~ ▶ npm ls -g vercel
/opt/homebrew/lib
└── vercel@54.18.2

~ ▶ 

I’m going to revisit [cli] Provide correct upgrade command for Homebrew-managed npm by unitof · Pull Request #14487 · vercel/vercel · GitHub and attempt to get it merge-ready. I think Vercel should detect when it is globally installed via Homebrew-managed npm and treat that as a global vercel install, as it does when installed to /usr/local/lib.

Looks like this was addressed by [cli] fix self-upgrade for pnpm 11 global installs and post-upgrade prompt by jeffsee55 · Pull Request #16903 · vercel/vercel · GitHub .

vercel upgrade no longer classifies the installation as local without positive evidence (a lockfile found above the CLI’s install location). Previously, when the installation layout was not recognized, the upgrade defaulted to running npm i vercel@latest in the current working directory — silently adding vercel to whatever project (or home directory) the user happened to be standing in. Unrecognized layouts now degrade to a global npm upgrade, which runs from a temporary directory and cannot modify the current project.

This change is in vercel@55.0.0 and above.