Skip to content

fix(web): copy an update command that matches how the server is installed - #9489

Open
ylcn91 wants to merge 3 commits into
pingdotgg:mainfrom
ylcn91:fix/install-aware-update-command
Open

fix(web): copy an update command that matches how the server is installed#9489
ylcn91 wants to merge 3 commits into
pingdotgg:mainfrom
ylcn91:fix/install-aware-update-command

Conversation

@ylcn91

@ylcn91 ylcn91 commented Sep 3, 2026

Copy link
Copy Markdown

What Changed

packages/contracts/src/environment.ts: a new optional capability, serverInstall, says how the server's CLI is installed: run out of a package runner's cache (npx, pnpm-dlx, bunx) or installed globally by a package manager (npm-global, pnpm-global, bun-global). It is declared with ForwardCompatibleOptional, like platform.machine, so a kind an older client does not know decodes as absent instead of failing the descriptor.

apps/server/src/cli/invocation.ts: detectServerInstall builds on the existing detectCliRunner entry-path check and recognises global installs by each package manager's own layout: npm's <prefix>/lib/node_modules/ (system node, nvm, fnm, volta, Homebrew) or %APPDATA%/npm/node_modules/ on Windows, pnpm's /pnpm/global/, bun's /.bun/install/global/. Repo checkouts, project-local installs, and the pinned service runtime return null, since no global command would update the executable that gets restarted.

apps/server/src/environment/ServerEnvironment.ts: the descriptor carries serverInstall only when serverSelfUpdate is absent, since that is the only server whose clients hand out a command. The entry path is resolved first because a global install's bin is a symlink into the package.

apps/web/src/versionSkew.ts: manualServerUpdateCommand picks the command from it: npm i -g / pnpm add -g / bun add -g t3@<version> for a global install, npx / pnpm dlx / bunx t3@<version> for a package runner, and the unchanged npx t3@<version> when the server does not say (older servers, dev checkouts). ServerUpdateAction takes the install as a prop; its three call sites (chat banner, Connections row, Connections primary card) pass it.

docs/user/updating.md: the Copy update command description now matches.

Tests: detectServerInstall per layout, the descriptor advertising serverInstall only for a server that cannot update itself (through a real bin symlink), and the command per install kind.

Why

Fixes #9370.

Copy update command always produced npx t3@<version>. For a server started with npx that relaunches it at the right version, but for a server installed with npm i -g it runs a throwaway copy out of the npx cache and never touches the installed CLI. The next t3 start, systemd unit, or shell alias comes back on the old version and the banner reappears, even though the user did exactly what the toast asked.

The server already knows how it was launched (detectCliRunner powers the npx t3 serve suggestions), so this reports that over the existing capabilities channel and lets the client format the command that will actually land. Nothing changes for servers that self-update, and older servers keep the current behaviour because the field is optional.

Model and harness: Claude Fable 5.1 in Claude Code.

Note

Show update command matching server install type instead of npx fallback

  • Adds ServerInstallKind and an optional serverInstall capability to environment.ts so the server can report whether it runs via npx, pnpm dlx, bunx, or npm/pnpm/bun global.
  • invocation.ts detects the install kind from the entry script path; ServerEnvironment.ts advertises serverInstall only for manually-updateable installs.
  • versionSkew.ts builds global upgrade commands for global installs, relaunch commands for package-runner installs, and keeps the npx fallback when no kind is reported.
  • Wires the install kind through ServerUpdateAction.tsx, ChatView.tsx, and ConnectionsSettings.tsx; updates updating.md.
  • Risk: older or unrecognized servers omit serverInstall, so the web client falls back to the npx command — this is intentional but may not match the actual install.

Macroscope summarized 290522b.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 3, 2026
Comment thread docs/user/updating.md Outdated
Comment thread apps/server/src/cli/invocation.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 33ca5dd. Configure here.

Comment thread packages/contracts/src/environment.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 290522b

Macroscope's review found this PR approvable — This is a focused fix to an existing version-mismatch action: it reports the server’s install type and copies the matching package-manager command while preserving older-server fallbacks and self-update paths. The additive descriptor is forward-compatible and the detection, wiring, and command selection are covered by targeted tests.

You can add or adjust custom eligibility rules. Learn more.

Comment thread docs/user/updating.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copy update command always emits npx t3@<version>, which never updates a globally installed server

1 participant