uptide Star on GitHub
Open source · Apache-2.0 · 0.7.1 on npm

Migrations you can merge.

Uptide is an open-source CLI that shows which dependency upgrades matter in your repo, what each one breaks in your code, and opens a verified migration branch or PR. It runs locally on your repo. Nothing to sign up for.

npx uptide list --html --open

No API key. No account. Node 20 or newer.

fixtures/repos/storefrontuptide check
$ npx uptide check zod stripe
uptide check · storefront · pnpm · 8.5s

zod                     3.25.76 → 4.6.5    major · latest on npm      verified   ✗ 28 breaking in 7 files   24 auto-fixable · 4 need the agent (LLM)
stripe (packages/api)   14.25.0 → 23.0.0   9 majors behind · latest on npm   verified   ✗ 4 breaking in 3 files    1 auto-fixable · 3 need the agent (LLM)
Full output below ↓the first lines of the run
01 / The problem

Major upgrades sit for months because nobody knows what they'll break.

Version bots open the PR. The version changes, the build goes red, and the code that breaks is still on you. So the PR waits, and the next major lands on top of it.

What a version bot does
  • Bumps the version and the lockfile.
  • Links the changelog.
What is left, and what Uptide does
  • Decide which upgrades matter first.
  • Find every line the new version breaks.
  • Rewrite those lines and prove the rest still compiles and passes its tests.
02 / How it works

list, check, fix, pr.

list

Every outdated dependency in seconds, grouped into packages that move together and ranked by priority with a reason: known advisories with the smallest fixing version, deprecated versions, unsupported major lines, version drift across workspaces, runtime before dev. In the terminal, or as an HTML report with filters. No LLM, no API key.

npx uptide list --html --open
check <pkg>

Compiles your code against the new version and states the verdict, 28 breaking · compiled against 4.6.5: 28 new type errors, with every call site. No LLM, no API key.

npx uptide check zod --html --open
fix <pkg>

Migrates on a new branch in an isolated clone of your local HEAD, in two passes:

  • Deterministic rules first. When the dependency has a verified pack, it rewrites every site it covers, the same way on every run. No LLM, no key.
  • Then AI, only for what rules can't do. It needs your API key in the environment: ANTHROPIC_API_KEY, OPENAI_API_KEY or GEMINI_API_KEY (experimental). Without one, the rules still run and the remaining sites are listed for you; a dependency with no pack has no rules, so it needs the key.

Then it verifies with your compiler, the related tests, and your linter and formatter. With --pr --yes it pushes the branch and opens a draft PR once verification passes; without them it never pushes.

npx uptide fix zod --pr --yes
pr

For a branch fix left local: opens the pull request with the evidence, summary first. It prints the plan and pushes only when you add --yes.

npx uptide pr --branch uptide/zod-4.6.5
03 / Real output

Real runs. Numbers as printed.

check and fix on fixtures/repos/storefront, a small pnpm workspace in the repository written to exercise Uptide: two packages on zod 3 and stripe 14, with a few tests. Every block below is a run published in the uptide README and docs, and the site build checks it against them.

Before: check. What breaks, where, and who can fix it.
fixtures/repos/storefrontuptide check
$ npx uptide check zod stripe
uptide check · storefront · pnpm · 8.5s

zod                     3.25.76 → 4.6.5    major · latest on npm      verified   ✗ 28 breaking in 7 files   24 auto-fixable · 4 need the agent (LLM)
stripe (packages/api)   14.25.0 → 23.0.0   9 majors behind · latest on npm   verified   ✗ 4 breaking in 3 files    1 auto-fixable · 3 need the agent (LLM)

zod   28 breaking · compiled against 4.6.5: 28 new type errors
  compiled 11 of 11 files in 2 workspaces with the repo's TypeScript 5.9.3
  ✗ New error API (required_error → error)   24 sites          auto-fixable
  ✗ ZodTypeDef removed                       1 fix, 3 errors   needs the agent (LLM)
  ✗ .ip() removed                            monitoring.ts:6   needs the agent (LLM)
  ! 15 deprecated calls (.uuid, .datetime, .email, ...)   8 auto-fixable

stripe   4 breaking · compiled against 23.0.0: 4 new type errors
  compiled 7 of 7 files in 1 workspace with the repo's TypeScript 5.9.3
  ✗ Test fixture casts widened                   renewal.test.ts:7   auto-fixable
  ✗ Subscription billing period moved to items   2 sites             needs the agent (LLM)
  ✗ apiVersion no longer matches the SDK         client.ts:9         needs the agent (LLM)
    1 API change since 2023-10-16 affects your code

Next
  npx uptide fix zod                       migrate on a new branch, verify, no push
  npx uptide fix stripe                    migrate on a new branch, verify, no push
  npx uptide plan --only 'zod,stripe'      the order to upgrade in, with the effort
  npx uptide check zod stripe --details    every site and reason
After: fix, one dependency at a time, each on its own verified branch.
fixtures/repos/storefrontuptide fix zod
$ npx uptide fix zod
uptide fix · zod 3.25.76 → 4.6.5 (latest on npm) · verification passed · 36s

  Risk      Medium: request validation in webhooks
  Changes   29 sites in 8 files · 25 auto-fixed · 4 fixed by the agent (LLM)
  Types     ✅ 29 errors after the bump → 1 (1 pre-existing)
  Behavior  ✅ 9 schemas identical · 2 not checked · 21/21 custom-message assertions
  Tests     ✅ 5 tests in 3 files passed
No compiler sees this one: zod 4 words its default messages differently, and a test that asserted the old wording failed after the migration. Uptide updated it and says so in the pull request, so you can check that nothing else reads that text.
packages/shared/src/monitoring.test.tsdiff
-    expect(parsed.error?.issues[0]?.message).toBe('Required');+    expect(parsed.error?.issues[0]?.message).toBe('Invalid input: expected string, received undefined');
fixtures/repos/storefrontuptide fix stripe
$ npx uptide fix stripe
uptide fix · stripe 14.25.0 → 23.0.0 (latest on npm) · verification passed · 41s

  Risk      High: behavior changes
  Changes   6 sites in 3 files · 3 auto-fixed · 3 fixed by the agent (LLM)
  Types     ✅ 5 errors after the bump → 1 (1 pre-existing)
  Behavior  ⚠️ 1 of 570 API changes affects your code · 47 touch resources you use (8 breaking)
  Tests     ✅ 3 tests in 2 files passed · the test script of packages/api
Stripe moved a subscription's billing period from the subscription to its items. Uptide added a subscriptionPeriod helper and migrated the code that read the old fields.
packages/api/src/billing/renewal.tsdiff
-    renewsAt: new Date(subscription.current_period_end * 1000),+    renewsAt: new Date(period.end * 1000),
The one type error left in both runs is the fixture's own, there on purpose: errors a repository already had are subtracted, never blamed on the upgrade.
04 / Honest by design

The compiler decides. The diff explains.

A change in a package's API is a reason to look, not a verdict. A site is breaking when your own compiler, or the new version loaded at runtime, says so.

Verified packs and generic mode

A verified pack holds rules written for that dependency, a guide for the agent, behavior checks, and ground truth from public repositories that made the upgrade, which the pack is scored against. The packs below are verified.

Every other dependency runs in generic mode. A finding is breaking only when your compiler or the runtime probe confirms it, or when it is a require() of an ESM-only package or an import of a removed export. Everything else is listed as unconfirmed under --details. A generic fix uses the agent alone, under the same verification, and its pull request says no pack covers the package.

When it can't verify, it says so

If the compiler could not run, the verdict says why instead of guessing: N breaking · types not verified: <reason>. A package whose analysis fails is named with its reason and never called clean.

A fix that does not verify exits 1 and lists the sites left for you. Unfinished sites stay manual and cannot pass the publish gate. Passing compilation does not prove runtime equivalence, so the report says what was verified, what was not, and what to review.

Risk levels

LowVerified rule-only edits.
MediumAgent edits, sensitive paths, or missing tests.
HighUnverified sites, behavior changes, or manual work left.

Why stripe is High on purpose

Types and tests pass, but a new Stripe API version changes what Stripe sends. Server API changes are never rewritten by rule, and the pull request asks what only you can answer, such as which item's period counts when a subscription has several.

5 verified packs

Precision and recall are for breaking findings on each pack's ground truth, as uptide pack test recorded them in the pack's verification.json. A pack is verified with two or more public repositories and no false positive. This table is built from those files on every deploy, the same way as the uptide README.

PackageRangePrecisionRecallGround-truth repositoriesStatus
ai6.x → 7.x100%36%vercel/chatbot, miurla/morphicverified
react18.x → 19.x100%69%excalidraw/excalidraw, tldraw/tldrawverified
stripe14 and newer100%90%unkeyed/unkey, nextjs/saas-starterverified
vitest4.x → 5.x100%50%votingworks/vxsuite, vitorvasc/opentelemetry-ecosystem-explorerverified
zod3.x → 4.x100%71%ugurkocde/AwesomeIntune, howardyang2009/PATH, band-ai/band-sdk-typescriptverified
05 / Safe to run

Built to run on code it didn't write.

  • list and check execute nothing from your repository. Configs are read as data; check compiles against the target in memory.
  • fix works in an isolated clone of the commit you have checked out, never in your checkout and never from the remote. Uncommitted changes are left out and listed. Your branch, files, git hooks and git config are compared before and after and must be identical.
  • Lifecycle scripts are disabled for every install, and git hooks are disabled for every git command it runs.
  • Lockfile check: a lockfile change outside the upgraded dependency's subtree is rejected.
  • Services are opt-in. Tests that need a database, cache or queue run only with --with-services --yes, after it prints what they connect to.
  • No PR from a dirty or diverged tree. With --pr it stops before any work when the working tree has uncommitted changes or the base branch on origin does not contain your commit. uptide pr checks the branch is still at the verified commit.
  • No push without you. The branch stays local until you run uptide pr --yes or pass fix --pr --yes.
  • Secrets stay out of child processes. Install and test commands do not receive your LLM API key or GitHub token.

Not a sandbox for your own code. fix runs your repository's tests with your user's permissions, the way you would. Run it on code you would run yourself. The full model is in SECURITY.md.

06 / Your code, your key

The agent runs on your key, only when rules run out.

list, check

Never call an LLM.

fix

Rules first. Only sites no rule covers go to the agent, one at a time, and a patch is kept only if it removes its compiler error and introduces none.

Providers

Anthropic by default (claude-sonnet-5-5), OpenAI (gpt-6.1-sol) or Gemini, experimental (gemini-3.8-flash), with your own key from ANTHROPIC_API_KEY, OPENAI_API_KEY or GEMINI_API_KEY. Keys are read only from the environment. Pick with --provider and --model.

Cost cap

--max-cost defaults to $1 per package. Uptide reserves the worst-case cost before every call, and a call that would exceed the budget is never sent.

Fully local

--no-llm turns the agent off. Rules still apply, and the remaining sites are listed for you.

07 / Privacy

What leaves your machine, exactly.

The same statement the CLI prints in uptide --help:

uptide --helpprivacy
Privacy:
  Analysis runs locally. Code snippets go to your chosen LLM provider (Anthropic, OpenAI or Gemini), only
  for assisted fixes in `uptide fix`, and only with your own API key from ANTHROPIC_API_KEY,
  OPENAI_API_KEY or GEMINI_API_KEY: for each
  site the rules cannot migrate, the finding, the enclosing function and the compiler
  error. `uptide fix --no-llm` turns assisted fixes off. No account.
  `check` and `verify` load the `typescript` package your repository installs (resolved from its
  node_modules) to compile with, and never run your repository's scripts or other code outside
  `fix`'s verification step.
  Anonymous telemetry is off by default and asks for consent in an interactive terminal.
  Set UPTIDE_TELEMETRY=0 to disable it. No IP, code, paths or repo names are collected.
  Other network use: your npm registry for package metadata and tarballs, npm's advisory
  endpoint from `list` (public package names and installed versions; `--no-advisories` turns
  it off), PostHog EU only
  after telemetry opt-in, and GitHub when you pass `fix --pr` or run `pr` / `pr-body`.
CommandWhat leaves your machine (telemetry off, the default)
listPackage names and versions requested from your npm registry, and the names and installed versions of public packages sent to npm's advisory endpoint. Off with --no-advisories.
checkNothing of yours. It downloads package tarballs from your npm registry.
fixNothing of yours for rules and verification. For each site no rule covers: the finding, the enclosing function or declaration, and the compiler error, to the provider you chose, with your key.
prThe branch and the pull request, to GitHub through your own gh, when you say so.

Telemetry is anonymous, off by default and opt-in: the first interactive run asks once, and Enter means no. CI never sends without UPTIDE_TELEMETRY=1. The exact fields are in docs/telemetry.md.

08 / Supported today

What works now.

Package managers

npm, pnpm and Yarn with the node-modules linker. Not Yarn Plug'n'Play.

Monorepos

Workspaces and pnpm catalogs. One row per package across workspaces, with version drift called out.

Languages

TypeScript, and JavaScript in the project (allowJs). In JavaScript the compiler type-checks (checkJs or // @ts-check) the compiler decides; elsewhere a site is breaking only when the runtime confirms it.

Verified packs

ai 6.x → 7.x, react 18.x → 19.x, stripe 14 and newer, vitest 4.x → 5.x and zod 3.x → 4.x.

Generic mode

Every other dependency: list, check, and fix with the agent.

GitHub Action

For version-bot pull requests: detects zod and stripe upgrades and keeps one findings comment. With fix enabled, it pushes one verified commit to the bot's branch. Setup.

Runtime

Node 20 or newer.

09 / Contribute

Packs are how Uptide learns a library.

A pack holds what Uptide knows about one dependency: deterministic rules applied only at sites check reported, a guide and validator for the agent, findings the compiler cannot see, and review material for the pull request. Every rule ships with a before-and-after test and a case it must leave alone, and every claim is backed by ground truth from a real upgrade.