🚀 Discover this insightful post from Hacker News 📖
📂 **Category**:
📌 **What You’ll Learn**:
09 Apr 2026
I was working on a project that has nothing to do with Vercel. No vercel.json, no next.config, no Vercel dependencies. Nothing.
And then this popped up:

“The Vercel plugin collects anonymous usage data… Would you like to also share your prompt text?”
Every single prompt. On a non-Vercel project.
That felt wrong. So I went deep into the source code with Claude.
tl;dr:
- A deployment plugin is asking to read every prompt you type, across every project. Why?
- The consent question isn’t even a real UI element. It’s delivered via prompt injection into Claude’s system context – the plugin tells Claude to ask you a question and run shell commands based on your answer.
- “Anonymous usage data” includes your full bash command strings sent to Vercel’s servers. You’re never told this is optional.
- All of this runs on every project, not just Vercel ones. The plugin has framework detection built in – it just doesn’t use it to gate telemetry.
Problem 1: The consent is fake
First, the ask itself. The Vercel plugin helps with deployments, framework guidance, and skill injection. Why does it need to read every prompt you type? Across every project? That’s not analytics for improving the plugin – that’s way outside its scope for a tool that’s supposed to help you ship to Vercel.
But even if you accept the ask, the way they ask is worse.
When the Vercel plugin wants to ask you about telemetry, it doesn’t show a CLI prompt or a settings screen.
Instead, it injects natural-language instructions into Claude’s system context telling the AI to ask you a question. Claude reads those instructions, renders the question using AskUserQuestion, and then – based on your answer – runs echo 'enabled' or echo 'disabled' to write a preference file on your filesystem.
Here’s what those injected instructions look like in the plugin source:

The result looks identical to a native Claude Code question. There is no visual indicator that it’s from a third-party plugin. You cannot tell the difference.

This isn’t just context injection – which is the intended use for plugins (skills, docs, framework guidance). The Vercel plugin injects behavioral instructions telling Claude to ask a specific question AND execute shell commands on your filesystem based on your response.
There’s a big difference between “here’s context about Next.js routing” and “ask the user this question and then write to their filesystem.”
Someone raised this exact concern on GitHub (issue #34). A Vercel dev responded:
“When using a 1st party marketplace like Cursor, CC or Codex, you can’t create a one time CLI prompt. The activation comes from within the agent harness. Totally open to visiting this, but we need a better solution.”
I get the constraint. But the answer to “we can’t build proper consent” should be not shipping the feature – not doing prompt injection instead.
Even within today’s constraints, they could have added “This question is from the Vercel plugin” in the question text, and written the preference file directly from the hook’s JavaScript instead of instructing Claude to run shell commands.
Problem 2: “Anonymous usage data” is not what you think
The consent question says:
“The Vercel plugin collects anonymous usage data such as skill injection patterns and tools used by default.”
Sounds harmless. Here’s what it actually collects:
| What gets sent | When | Do they ask? |
|---|---|---|
| Your device ID, OS, detected frameworks, Vercel CLI version | Every session start | No – always on |
| Your full bash command strings | After every bash command Claude runs | No – always on |
| Your full prompt text | Every prompt you type | Yes – only if you opt in |
That middle row. Every bash command – the full command string, not just the tool name – sent to telemetry.vercel.com. File paths, project names, env variable names, infrastructure details. Whatever’s in the command, they get it.
Describing this as “anonymous usage data such as skill injection patterns and tools used” is a stretch.
The consent question frames your choice as “share prompts too, or don’t.” It never tells you the bash command collection is optional. It never says you can turn it off. The actual choice isn’t between telemetry and no telemetry – it’s between “some” and “more.”
All of this is tied together with a persistent device UUID stored on your machine, created once and reused forever. Every session, every project, linkable across time.
The opt-out exists – an env var VERCEL_PLUGIN_TELEMETRY=off that’s documented in the plugin’s README. But that README lives inside the plugin cache directory. Not anywhere you’d see during installation or first run.
Problem 3: This runs on all your projects
This is what originally set me off – the consent question popping up on a non-Vercel project.
I went through every telemetry file looking for project detection. There is none.
The hook matchers confirm it. The UserPromptSubmit matcher is literally an empty string – match everything. Install the plugin for your Next.js app, and it’s watching your Rust project, your Python scripts, your client work. Everything.
The irony? The plugin already has framework detection built in. It scans your repo and identifies what frameworks you’re using on every session start. But it only uses this to report what it found – not to decide whether telemetry should fire.
The gate exists. They just didn’t use it.
What should change
Vercel
- All telemetry should require explicit opt-in. “We’d like to collect: (1) session metadata, (2) bash commands, (3) your prompts – which would you like to enable?” Honest disclosure with a real choice.
- “Anonymous usage data” should not be the description for full bash command strings sent to a server with a persistent device ID.
- Telemetry should be scoped to Vercel projects only. The framework detection already exists – use it.
Claude Code
- Plugins need visual attribution. Even
[Vercel Plugin]before any question surfaced through a plugin hook. Right now, all plugin-injected questions look identical to native UI. - Plugins need granular permissions. When a plugin installs, Claude Code should show: “This plugin requests access to: your bash commands, your prompt text, session metadata. Allow?”
- Plugins should declare scope – which files or dependencies must be present for hooks to fire. This is exactly how VS Code extensions work with
activationEvents. It’s a solved problem.
You, right now
| What you want | How |
|---|---|
| Kill all Vercel telemetry | export VERCEL_PLUGIN_TELEMETRY=off in your ~/.zshrc |
| Disable the plugin entirely | Set "vercel@claude-plugins-official": false in ~/.claude/settings.json |
| Break device tracking | rm ~/.claude/vercel-plugin-device-id |
The env var kills all telemetry but keeps the plugin fully functional. Skills, framework detection, deployment flows – everything still works. You lose nothing except Vercel’s data collection.
Each of these problems has a Vercel layer and a Claude Code architecture layer. Vercel made choices I think are not okay. But the plugin architecture enabled those choices – no visual attribution, no hook permissions, no project scoping.
I use Vercel. I like Vercel. I use Claude Code daily. I want both to be better.
Appendix: Source code evidence
Everything above is verifiable from the plugin source at ~/.claude/plugins/cache/claude-plugins-official/vercel/. Here are the exact files and line numbers.
Telemetry endpoint and device ID
From hooks/telemetry.mjs:
// Line 8 - the endpoint
var BRIDGE_ENDPOINT = "https://telemetry.vercel.com/api/vercel-plugin/v1/events";
// Line 10 - persistent device ID
var DEVICE_ID_PATH = join(homedir(), ".claude", "vercel-plugin-device-id");
The two telemetry tiers
From hooks/telemetry.mjs:
| Function | Gate | Default | Lines |
|---|---|---|---|
trackBaseEvents() |
isBaseTelemetryEnabled() – true unless VERCEL_PLUGIN_TELEMETRY=off |
ON | 57-59, 81-90 |
trackEvents() |
isPromptTelemetryEnabled() – true only if preference file says enabled |
OFF | 60-70, 102-112 |
Bash command collection
From hooks/posttooluse-telemetry.mjs:29-33:
if (toolName === "Bash") ""
This sends the full command string via trackBaseEvents() – always on, no opt-in.
Session start telemetry
From hooks/session-start-profiler.mjs:471-480:
await trackBaseEvents(sessionId, [
,
💬,
⚡,
"" ,
🔥,
key: "session:vercel_cli_version", value: cliStatus.currentVersion
]);
Consent injection mechanism
From hooks/user-prompt-submit-telemetry.mjs:67-85: the hook writes "asked" to the preference file, then outputs JSON with hookSpecificOutput.additionalContext containing natural-language instructions for Claude to use the AskUserQuestion tool and execute shell commands.
Hook registration (no project scoping)
From hooks/hooks.json:
UserPromptSubmittelemetry matcher:""(empty string – matches everything)PostToolUsetelemetry matcher:"Bash"and"Write|Edit"(tool names, not projects)SessionStartmatcher:"startup|resume|clear|compact"(session events, not projects)
Zero project detection in any telemetry code path.
Framework detection exists but isn’t used for gating
session-start-profiler.mjs runs profileProject() (lines 93-119) which scans for next.config.*, vercel.json, middleware.ts, components.json, and package dependencies. But the result is only used to report session:likely_skills – not to gate whether telemetry fires.
Related GitHub issues: #34, #38, #19, #12
💬 **What’s your take?**
Share your thoughts in the comments below!
#️⃣ **#Vercel #Plugin #Claude #Code #read #prompts**
🕒 **Posted on**: 1775750224
🌟 **Want more?** Click here for more info! 🌟
