Duplication in JavaScript is a semantic problem, not a textual one, because the copies almost always differ in variable names. That is why Atlas starts with codebase_search rather than grep: ask for the behavior, not the exact code, and the semantic index surfaces near-duplicate implementations that a regex over src/**/*.js would never connect. Atlas then creates the shared module with the write tool, replaces each duplicate with a call using apply_patch, one file per patch so each swap is independently reviewable and revertible, and runs vitest through bash after every swap.
Why does grep fail to find duplicated JavaScript logic?
Because the copies do not match textually. The same currency formatting logic pasted into 4 JavaScript files will use amount in one, value in another, cents in a third, and an arrow function instead of a function declaration in the fourth. grep matches text. Duplication is about meaning.
The JavaScript ecosystem makes this worse than most, because the same logic can be written as a function declaration, a const arrow, a class method, or an inline callback, and any of those may have been ported between a Node script and a browser bundle with the style changed on the way. Atlas's answer is codebase_search: describe the behavior, not the code, and the semantic index returns the candidate implementations. Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, so a description of the behavior gets semantic weight while a distinctive identifier still gets keyword weight, and Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so the hits are real functions.
How do I confirm two JavaScript functions are actually duplicates before merging them?
Read each hit and confirm the copies are genuinely equivalent before collapsing them. Two JavaScript functions that look 90 percent the same are not duplicates if one of them rounds and the other truncates, and collapsing them into 1 helper silently changes behavior in whichever caller was relying on the difference.
The near-miss is the trap. In JavaScript the divergence is usually a default parameter, a null check that one copy grew and the other did not, or a subtle difference in how each handles undefined versus null. Atlas reads each candidate returned by codebase_search rather than trusting the similarity score, and the read is where the divergences show up. If two copies genuinely differ, the honest outcome is either a helper with a parameter that captures the difference, or two helpers. Merging them by pretending the difference is not there is how a refactor turns into a bug report.
Why swap each duplicate with apply_patch one file at a time?
Atlas replaces each duplicate with a call using apply_patch, one file per patch, so each swap is independently reviewable and revertible. Collapsing 4 duplicated JavaScript functions in one giant patch means one bad hunk poisons all four, and a rollback throws away the three swaps that were correct.
One patch per file also matches how JavaScript changes actually get reviewed. Each patch deletes the local copy, adds an import of the shared helper, and updates the callsites in that file, which is a small, self-contained diff a human can read in under a minute. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, and it snapshots file changes as git patches so edits can be diffed and rolled back individually. If the third swap turns out to have relied on a divergent behavior, you revert that one file and keep the rest.
How do I verify the JavaScript extraction did not change behavior?
Run the suite with the bash tool after every swap, then finish by grepping for any surviving copy. In 2026 a JavaScript repo still has no compiler, so pnpm vitest run after each apply_patch is the only thing standing between an extraction and a silent behavior change in a browser bundle.
Per-swap runs give you a free bisect: if the suite is green after swaps 1 and 2 and red after swap 3, you know precisely which file broke and why, which is not true if you swap all four and run vitest once. When every swap has landed, grep for the original logic one last time to catch the copy that codebase_search missed, since a fifth duplicate hiding in a rarely-touched Node script is exactly the sort of thing that survives a refactor. Run prettier so the final diff shows the extraction rather than a formatting churn, and let Atlas stage the commit.
How do I set Atlas up in a JavaScript repo before extracting a helper?
Run atlas where your package.json lives. In 2026 Atlas maps your modules, npm scripts, and bundler config, which is the context that decides where a shared JavaScript helper can live and still be importable by both a Node script and a browser bundle.
Install with pnpm so the test runner and the module resolution behave the way they will in CI. From there, the extraction workflow runs on Atlas's search and patch tools: codebase_search to find the copies by meaning, read to confirm they are genuinely equivalent, write to create the helper, apply_patch per file to swap each copy for a call, bash to run vitest between swaps, and grep to catch survivors. You can also have Atlas modernize callbacks to async/await or add Jest tests, reviewing each diff, and the review path is identical: a unified diff surfaced before anything is written.
Step by step
- 01Run atlas where your package.json lives so Atlas maps your modules, npm scripts, and bundler config, then install with pnpm.
- 02Ask codebase_search for the behavior, not the exact code, to surface near-duplicate JavaScript implementations that grep would miss because the copies use different variable names.
- 03Read each hit and confirm the copies are genuinely equivalent, checking for the divergent default parameter or null check that would make a merge a behavior change.
- 04Create the shared helper with the write tool under src/utils/ or an existing shared module, which shows the full diff in the permission prompt before the file is created.
- 05Replace each duplicate with a call using apply_patch, one file per patch, so each swap is independently reviewable and revertible.
- 06Run the suite with the bash tool using pnpm vitest run after every swap, since JavaScript has no compiler to catch a behavior change.
- 07Grep for any surviving copy of the original logic to catch the duplicate that codebase_search did not surface.
- 08Run prettier so the final diff shows the extraction rather than formatting churn, then let Atlas stage and commit the change.
Frequently asked questions
- how do I find duplicated code in a JavaScript project that grep cannot see
- Use Atlas's codebase_search and ask for the behavior rather than the exact code. The copies usually differ in variable names, so a regex over src/**/*.js will not connect them. Atlas searches with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, and indexes by AST declarations, so the hits are real functions.
- how do I extract a shared helper from copy pasted JavaScript
- Find the copies with codebase_search, read each one to confirm they are genuinely equivalent, create the helper with Atlas's write tool under src/utils/, then replace each duplicate with a call using apply_patch, one file per patch. Run pnpm vitest run after every swap.
- why does Atlas patch one file at a time when removing duplication
- So each swap is independently reviewable and revertible. If four duplicated JavaScript functions are collapsed in one patch, a single bad hunk poisons all four and a rollback throws away the three that were correct. Atlas snapshots each change as a git patch, so a single file can be reverted.
- when should I not merge two similar JavaScript functions
- When they diverge in behavior. A default parameter, a null versus undefined check, or one copy that rounds where the other truncates means the copies are not duplicates. Read each candidate before collapsing it, and either add a parameter that captures the difference or keep two helpers.
- where should a shared JavaScript helper live
- Where your package.json and bundler config already look, typically src/utils/ or an existing shared module, so both Node scripts and browser bundles can import it. Atlas maps your modules, npm scripts, and bundler config when you run atlas where package.json lives.
- how do I know the extraction did not break anything in JavaScript
- Run pnpm vitest run through Atlas's bash tool after every apply_patch swap, not once at the end. Per-swap runs give you a free bisect. JavaScript has no compiler, so the suite is the only check between an extraction and a silent behavior change.
- how do I make sure no copy of the duplicated logic survives
- Grep for the original logic after all the swaps have landed. codebase_search finds duplicates by meaning, but a fifth copy in a rarely touched Node script is exactly the kind of thing that survives a refactor, and a final grep catches it.
Try Atlas in your terminal
The terminal-native AI coding agent. Free core, single binary.
Install AtlasRelated guides
Extract a Shared Helper from Duplicated Code with Atlas (2026 Workflow)
How to extract a shared helper from duplicated code with Atlas in 2026: codebase_search finds the copies by meaning, write creates the module, apply_patch swaps each call.
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.
Debug a Single Failing Test in JavaScript with Atlas (2026)
Debug one failing JavaScript test with Atlas in 2026: run it in isolation with vitest through pnpm, walk the call path with the lsp tool, and fix the code, not the assertion.
Add a Regression Test for a Bug Fix in JavaScript with Atlas (2026)
Atlas writes a failing vitest spec, proves it fails via the bash tool exit code, applies the JavaScript fix with edit, and re-runs the same command to prove it passes.
Refactor a Legacy Module in JavaScript with Atlas (2026)
Refactor a legacy JavaScript module with Atlas in 2026: enumerate callsites with the lsp tool, restructure with apply_patch, and prove behavior with vitest.
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
Run Atlas Headless in CI in a JavaScript Project (2026)
Run Atlas non-interactively in a JavaScript pipeline. `atlas run` sends one prompt, streams events to stdout, supports --format json, and exits when the session goes idle.