Stacks

Migrate a deprecated API across every callsite in JavaScript with Atlas (2026)

Updated 9 min read

Migrating a deprecated JavaScript API is the workflow that punishes half-measures, so Atlas front-loads enumeration. The lsp tool's findReferences operation yields the complete caller set from the language server, grep catches the dynamic and string-based usages the language server cannot see, and todowrite turns the list into tracked work so no `require()` site in a Node script or `import` in a browser bundle is silently skipped. Each migration lands as a context-anchored apply_patch, and you run vitest through Atlas's bash tool after every file, marking a todo completed only once it is green.

How do I find every caller of a deprecated JavaScript function?

Enumerate every caller of the deprecated JavaScript symbol with Atlas's lsp tool findReferences operation, which returns the complete reference set from the language server, then cross-check with grep for dynamic or string-based usages. 2 passes, because JavaScript hides callers the type system never sees.

A JavaScript migration fails on the caller you did not know about. Atlas therefore front-loads enumeration rather than starting to edit. The lsp tool's findReferences operation on the deprecated function returns the callers the language server can prove, which covers ordinary `import { legacyFetch } from './lib/http.js'` sites across `src/` and `scripts/`. Then Atlas greps for the same name to catch what the language server cannot: a `require('./lib/http')` accessed by computed property, a method looked up by string on an options object, a name that only appears in a README or a `package.json` script. Atlas's grep runs through ripgrep and takes a real regex plus include and path filters, so you can scope it to `*.js` and `*.mjs` and keep `node_modules` out. The union of the two passes is the true callsite list.

How do I track a multi-file JavaScript migration so nothing gets skipped?

Atlas creates one todowrite entry per callsite, so partial progress is visible and nothing is silently skipped. A migration across 23 JavaScript files becomes 23 tracked items rather than one vague task that a model, or a developer, can quietly declare finished at file 14.

todowrite is the accountability layer of an Atlas migration. Every callsite that findReferences and grep produced becomes its own entry with a status, so at any point you can see which JavaScript modules are migrated, which are in progress, and which are untouched. That structure matters because a deprecated-API migration is only correct at 100 percent: a codebase with 22 of 23 callers migrated still crashes at the twenty-third. The todo list also survives across turns, so a long migration through `src/api/`, `src/utils/`, and `scripts/` does not depend on Atlas remembering what it did. Atlas fans out work to subagents that can run in the foreground or in parallel background sessions, so large caller sets can be worked in parallel while the todowrite list remains the single record of what is actually done.

How does apply_patch migrate a JavaScript callsite without misapplying?

Atlas migrates each JavaScript callsite with apply_patch, which seeks the hunk's context and old_lines and throws Failed to find expected lines rather than guessing. A patch against a drifted src/api/client.js fails loudly instead of landing in the wrong function, which is exactly what you want during a migration that spans 23 files.

apply_patch is context-anchored. Each hunk carries the surrounding JavaScript lines it expects to find, and if the file has changed since Atlas read it, apply_patch throws Failed to find expected lines rather than applying to a best-guess location. During a migration this failure is a feature. A run-of-the-mill replace would happily rewrite the wrong call in a file that another process or another subagent modified underneath it. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so you review each JavaScript callsite change before it lands, and Atlas snapshots file changes as git patches so any patch can be diffed and rolled back. Every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs, which applies to the apply_patch as much as to the bash call after it.

When should I run vitest during a JavaScript API migration?

Run the affected tests with Atlas's bash tool after each JavaScript file, not once at the end, and mark the todowrite entry completed only once vitest passes. A migration that runs the suite once at the end tells you that something broke across 23 files, which is the least useful possible signal.

Per-file verification is what makes a large JavaScript migration recoverable. After apply_patch lands on `src/api/client.js`, run vitest through Atlas's bash tool scoped to the tests that cover that module, and only then mark the corresponding todowrite entry completed. If the tests fail, exactly one file changed since the last green state, so the blast radius of the investigation is one patch. Use pnpm to install anything the replacement API needs, and run prettier over each migrated file so the diff a reviewer sees contains behavior changes rather than formatting noise. Atlas reads git branches, status, and diffs, and can stage and create commits on your behalf, so a clean per-file rhythm of patch, vitest, commit is easy to hold across a long migration.

How do I prove a deprecated JavaScript API has zero remaining callers?

Finish a JavaScript migration by grepping for the deprecated symbol and confirming 0 remaining hits, then delete the old implementation. Deleting the old function is the real proof: if a caller survived anywhere in src/ or scripts/, vitest and the bundler will say so immediately.

A migration is not done when the last todowrite entry is checked. Atlas's documented final step is to grep for the deprecated symbol across the JavaScript codebase and confirm zero remaining hits, which catches the string-based and dynamic usages the language server never reported. Only then delete the old implementation from `src/lib/http.js` or wherever it lived. Removing it converts every missed caller from a silent deprecation warning into a hard failure at the next vitest run, which is the outcome you want. Atlas computes a unified diff for the deletion and surfaces it for approval before writing, and because Atlas snapshots file changes as git patches, the deletion can be rolled back if the grep missed something exotic. Run prettier once more, run vitest across the whole suite, then let Atlas stage and create the commit.

Step by step

  1. 01Enumerate every caller of the deprecated JavaScript symbol with the lsp tool's findReferences operation, which returns the complete reference set from the language server.
  2. 02Cross-check with Atlas's grep for dynamic or string-based usages the language server cannot see, scoping the ripgrep search to *.js and *.mjs so node_modules stays out.
  3. 03Create one todowrite entry per callsite so partial progress is visible and nothing is silently skipped across src/, scripts/, and any bundler config.
  4. 04Migrate each callsite with apply_patch, which seeks the hunk's context and old_lines and throws Failed to find expected lines rather than guessing on a drifted file.
  5. 05Review the unified diff Atlas surfaces for each JavaScript file before it writes, since every file edit is presented for approval.
  6. 06Run the affected tests with vitest through Atlas's bash tool after each file, and install any new dependency with pnpm.
  7. 07Mark the todowrite entry completed only once vitest passes for that file, so the todo list is a record of verified work rather than attempted work.
  8. 08Run prettier over every migrated file so the reviewer sees behavior changes rather than formatting noise.
  9. 09Grep for the deprecated symbol one final time, confirm zero remaining hits, then delete the old implementation and run the full vitest suite.

Frequently asked questions

how to find every callsite of a deprecated function in javascript
Run the lsp tool's findReferences operation on the deprecated symbol to get the language server's complete reference set, then grep for the same name to catch dynamic and string-based usages the language server cannot see.
how do I migrate a deprecated api across many javascript files without missing one
Enumerate callers with findReferences plus grep, create one todowrite entry per callsite, migrate each with apply_patch, run vitest after every file, then grep at the end and confirm zero remaining hits before deleting the old implementation.
what does Failed to find expected lines mean in atlas
apply_patch is context-anchored: it seeks the hunk's context and old_lines. Failed to find expected lines means the JavaScript file drifted since Atlas read it, so the patch refused to guess. Re-read the file and reissue the patch.
why does grep find javascript callers that findReferences misses
The language server only sees usages the type system can resolve. A function accessed by computed property, referenced by string in a config, or named in a package.json script is invisible to findReferences but visible to grep, which is why Atlas runs both.
should I run vitest after every file during a migration
Yes. Run vitest through Atlas's bash tool after each migrated JavaScript file and mark the todowrite entry completed only once it passes. Running the suite once at the end tells you something broke, not which patch broke it.
when should I delete the old javascript implementation
Delete it only after grepping for the deprecated symbol and confirming zero remaining hits. Deleting it turns any surviving caller into a hard vitest or bundler failure instead of a silent deprecation warning, which is the outcome you want.
does atlas apply javascript patches without my approval
No. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, and every tool call is permission-gated against allow, ask, and deny rules before it runs.
can I roll back one bad callsite patch in javascript
Yes. Atlas snapshots file changes as git patches so edits can be diffed and rolled back. Because apply_patch works per file, one bad JavaScript callsite migration can be reverted without disturbing the ones that already pass vitest.

Try Atlas in your terminal

The terminal-native AI coding agent. Free core, single binary.

Install Atlas

Related guides

Migrate a Deprecated API Across Every Callsite with Atlas (2026 Workflow)

How to migrate a deprecated API across every callsite with Atlas in 2026: the lsp tool's findReferences enumerates callers, todowrite tracks them, apply_patch migrates each one.

Atlas for JavaScript in 2026

In 2026, Atlas empowers JavaScript developers with a terminal-native AI coding agent. It indexes code by AST, uses local embeddings, and offers permission-gated tools for safe, efficient development.

Rename a symbol across the repo in JavaScript with Atlas (2026)

Rename a JavaScript function, class, or constant repo-wide in 2026 with Atlas: lsp findReferences for real callsites, grep for strings and docs, edit with replaceAll.

Research a Third-Party API Before Integrating It in JavaScript with Atlas (2026)

Atlas uses websearch and webfetch to pull live API docs into context before you write JavaScript, so your Node or browser integration matches the real endpoints in 2026.

Plan a Multi-File Change Before Editing in JavaScript with Atlas in 2026

Plan a multi-file JavaScript change before editing in 2026. Atlas's plan agent denies edit outside .atlas/plans/*.md, and plan_exit gates the build agent handoff.

Write Unit Tests for Untested JavaScript Code with Atlas (2026)

Atlas enumerates a JavaScript module's exports with the lsp tool, copies your existing vitest conventions, writes the spec file, and runs vitest with the bash tool.

Onboard to an Unfamiliar JavaScript Codebase with Atlas in 2026

Onboard to an unfamiliar JavaScript codebase in 2026. Atlas maps package.json, npm scripts, and bundler config with codebase_search, glob, read, and lsp.

Audit a JavaScript Repo with Parallel Subagents in 2026

In 2026, JavaScript developers use Atlas to sweep entire repositories for code issues. Leverage parallel subagents to audit pnpm projects, vitest configurations, and prettier formatting without blowing your main context

Browse this resource hub