Skip to content

feat(cli): make first-run hints runnable and announce newer versions - #187

Merged
aikins01 merged 3 commits into
mainfrom
feat/cli/first-run-ux
Nov 3, 2026
Merged

aikins01 merged 3 commits into
mainfrom
feat/cli/first-run-ux

Conversation

@aikins01

@aikins01 aikins01 commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Run through npx, the CLI ended sign-in with "Try telemetry traces", but npx leaves no telemetry on PATH, so the suggested command failed with command not found. Every printed command, usage line, and JSON hint now starts with the command that started the CLI: npx @telemetry-dev/cli, pnpm dlx @telemetry-dev/cli, yarn dlx @telemetry-dev/cli, or bunx @telemetry-dev/cli, and telemetry otherwise. The runner is detected from the folder it unpacked the package into, including a pnpm cache directory that was moved. A runner start also prints one line on how to install the CLI. No hint prints npx telemetry, because that name runs an unrelated npm package.

The CLI had no way to tell people about new versions. On a terminal, it now asks npm's dist-tags for the latest version at most once a day. The request runs alongside the command and is dropped if the command finishes first, so no command waits for it. A newer stable version gets one stderr line with the update command for how the CLI was installed: npm's global folder under any prefix (recognized by lib/node_modules, or by the telemetry.cmd npm writes on Windows), pnpm, bun, Yarn classic, or Volta. Any other node_modules is a project's dependency, including Yarn Plug'n'Play's cache, and gets no check. The CLI never installs anything itself. There is no check in CI, with --json, or when TELEMETRY_DEV_NO_UPDATE_CHECK or NO_UPDATE_NOTIFIER is set. status --json and login --json report cli_version and the cached latest_cli_version.

On the server side, @telemetry-dev/mcp now records mcp.client.name and mcp.client.version from the client's clientInfo on each request span, cut to 128 characters. telemetry.dev records them after this package is released and apps/web moves to that version.

Other first-run and everyday fixes:

  • A new sign-in keeps the default project when the workspace still has it. Before, a re-login after an expired sign-in dropped it, so the next command asked for a project.
  • status checks the saved sign-in with one list_projects call. A refused sign-in exits 4 with signed_in: false. When the check can't run, for example offline or while the token endpoint fails, it keeps the saved sign-in, says so on stderr, and sets sign_in_verified: false. A refresh that gets no answer is now a retryable server_error, not sign_in_expired.
  • An empty unfiltered traces points to the quickstart, and says that experiment runs need --env experiment. With no default project set, the home screen says how to set one.
  • Network errors name the configured server. When HTTPS_PROXY is set but Node.js ignores it, the error says which setting or Node.js version would use it.
  • login also accepts the pasted callback address while it waits for the browser, for a browser on another device or one that never opened.
  • On Windows, printed commands use double quotes. A command that no quoting keeps as typed in both cmd.exe and PowerShell isn't printed.
  • Options before the command get the reordered command as the hint. Messages no longer put commands in backticks, which a shell runs when pasted. An empty sessions search suggests only wider ranges. Failed spans in trace show the span id that payload takes. -v prints the version.

Not covered yet: bun and Yarn classic global folders moved to a custom location are taken for project dependencies, so they get no update notice.

Tests run: vp test run in packages/cli (46 passed) and packages/mcp (33 passed), and vp check. Each new assertion fails when the code it covers is removed.

Server spans said which MCP method ran but not which client called it, so
a deployment couldn't tell which CLI or editor versions are still in use.
Each request span now carries mcp.client.name and mcp.client.version from
the client's clientInfo: from the request's _meta on protocol 2026-07-28,
or, on older protocols, from initialize, kept for the rest of the
transport's requests. The client reports these values itself, so each is
cut to 128 characters, and a missing or empty value adds no attribute.
Run through npx, the CLI ended sign-in with "Try telemetry traces", a
command that isn't on PATH after npx exits. Every printed command, usage
line, and JSON hint now starts with the command that started the CLI:
npx, pnpm dlx, or bunx @telemetry-dev/cli, detected from the script's
path, or telemetry otherwise. A runner start also gets one line saying
how to install the CLI. Hints never print npx telemetry, which runs an
unrelated npm package.

On a terminal, the CLI asks npm's dist-tags for the latest version at
most once a day, alongside the command, and drops the request when the
command finishes first, so no command waits for it. A newer stable
version gets one line on stderr with the update command for how the CLI
was installed. It never installs anything. A project's dependency, CI,
--json, and TELEMETRY_DEV_NO_UPDATE_CHECK or NO_UPDATE_NOTIFIER skip the
check. status --json and login --json report cli_version and the cached
latest_cli_version.

Other fixes to first-run and everyday use:

- A new sign-in keeps the default project when the workspace still has
  it. Before, every re-login dropped it, so the next command asked for a
  project.
- status checks the saved sign-in with one call. A refused sign-in exits
  4 with signed_in false. A check that can't run, such as offline or a
  token endpoint that fails, keeps the saved sign-in, says so on stderr,
  and sets sign_in_verified false. A refresh that gets no answer is now
  a retryable server_error rather than an expired sign-in.
- An empty unfiltered traces search points to the quickstart, and says
  experiment runs need --env experiment. The home screen leads with
  setting a default project when none is set.
- Network errors name the configured server, and a proxy that Node.js
  ignores is named with the setting or version that would use it.
- login also takes the pasted callback address while it waits for the
  browser. Ctrl-D stops only the prompt, or cancels without a browser.
- On Windows, printed commands use double quotes, and a command that no
  quoting keeps as typed isn't printed.
- Options before the command get the reordered command as the hint.
  Messages don't wrap commands in backticks, which a shell would run.
  An empty sessions search suggests only wider ranges. Failed spans in
  trace show their id for payload. -v prints the version.
@aikins01 aikins01 self-assigned this Nov 3, 2026
…any prefix

Hints said telemetry under yarn dlx and under pnpm dlx with a moved
cache directory, where nothing puts telemetry on PATH. Both are now
recognized from where they unpack the package. bunx is recognized only
from its bunx-<uid>- cache folder, so a project folder named bunx-demo
is no longer taken for it.

npm's global folder was recognized only by its usual names, so a global
install under a custom prefix, nvm-windows, fnm, or Scoop got no update
notice. It is now recognized by npm's layout: lib/node_modules on macOS
and Linux, or the telemetry.cmd shim npm writes on Windows. Any other
node_modules stays a project's dependency, which covers Yarn
Plug'n'Play's global cache, pnpm's global virtual store, and Deno.
Windows' Yarn and Volta folders and pnpm globals under any PNPM_HOME get
their own update command.
@aikins01
aikins01 merged commit 0f314b7 into main Nov 3, 2026
10 checks passed
@aikins01
aikins01 deleted the feat/cli/first-run-ux branch November 3, 2026 21:20
@aikins01 aikins01 mentioned this pull request Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant