# Extract a Shared Helper from Duplicated Swift Code with Atlas (2026)

> In Swift, Atlas finds copy-pasted logic with codebase_search rather than grep, because the copies differ in variable names but not in meaning.

Atlas extracts a shared helper from duplicated Swift code by treating duplication as a semantic problem rather than a textual one. Copy-pasted logic in Swift almost never matches character for character, because the copies drift: one names the variable response, another names it payload, a third wraps the same work in async/await. Grep cannot see that. codebase_search can, because Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion. Atlas then creates the new helper in a Sources/ target with the write tool, swaps each copy for a call with apply_patch, one file per patch, and proves nothing broke by running XCTest via swift test.

## Key takeaways

- Swift duplication is semantic, not textual: codebase_search finds copies that differ in variable names, where grep finds nothing.
- Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, and indexes by AST declarations using tree-sitter.
- The write tool shows the full diff in the permission prompt before the new Swift helper file is created.
- apply_patch performs each swap as one file per patch, so every Sources/ change is independently reviewable and revertible.
- XCTest via swift test runs after every swap, and a final grep confirms zero surviving copies of the old logic.

## How do I find duplicated Swift code that grep cannot match?

Ask codebase_search for the behavior, not the exact code. Duplication in a Swift package is a semantic problem: the copies in Sources/Networking and Sources/Auth usually differ in variable names, so a grep for one spelling misses the other. Atlas fuses semantic and keyword retrieval with reciprocal rank fusion in 2026.

Describe what the duplicated Swift logic does, for example decoding a JSON response and mapping a URLError into a domain error, and codebase_search returns the near-duplicate implementations across your Swift Package Manager targets. Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so the hits come back as whole Swift functions and extensions rather than arbitrary line ranges. That is what lets you compare two candidate copies side by side and judge whether they really are the same thing.

## How do I confirm two Swift functions are genuinely the same before merging them?

Read each hit with the read tool and confirm the copies are genuinely equivalent before collapsing them. In Swift the trap is subtle: two functions that look identical can differ in optional handling, in throws, or in actor isolation, and merging them in 2026 would change behavior at one of the callsites.

Confirmation is a human judgment Atlas supports with evidence. Atlas reads each candidate in full, so you can see whether one copy force-unwraps where the other uses guard let, whether one is marked async and the other is not, and whether the error types they throw actually unify. Only when the copies are genuinely equivalent should they collapse into one helper. A false merge in a Swift package is worse than the duplication it replaces, because it introduces a behavior change disguised as a refactor.

## Where should the new shared Swift helper live?

Put the new Swift helper where every duplicate site can import it, typically a shared target in Package.swift under Sources/. Atlas creates it with the write tool, which shows the full diff in the permission prompt before the file is created, so in 2026 the new file is reviewed before it exists.

Swift Package Manager makes the placement decision explicit: a helper used by two targets must live in a target both depend on, and Package.swift must list that dependency. Atlas reads your Package.swift to see the existing target graph before choosing. The helper itself is written as a plain function, a protocol extension, or a generic, whichever matches the idiom already used in your Sources/ tree. Running swift-format on the new file keeps it consistent with the rest of the package.

## Why does Atlas use apply_patch, one file per patch, for the swaps?

Atlas replaces each duplicate with a call using apply_patch, one file per patch, so each swap is independently reviewable and revertible. Removing a copied Swift function from Sources/Auth and one from Sources/Networking in 2026 becomes two separate patches, not one large uninspectable change.

One patch per Swift file is the discipline that keeps a deduplication reversible. If the swap in Sources/Networking/APIClient.swift turns out to change behavior, that single patch is reverted without touching the swap in Sources/Auth/TokenStore.swift. Atlas snapshots file changes as git patches, so every swap can be diffed and rolled back individually. Atlas also computes a unified diff for every file edit and surfaces it for approval before writing, so you approve each Swift file's swap on its own merits.

## How do I prove the Swift refactor did not change behavior?

Run XCTest via swift test with the bash tool after every swap, not once at the end. A Swift package with several targets can compile fine and still fail a test, so in 2026 the suite runs after each apply_patch lands and the process exit code is the verdict.

Running the suite after each swap localizes any failure to the one Swift file you just changed. The bash tool records the process exit code in its metadata alongside the output, so a green XCTest via swift test run is proven rather than assumed. When every swap is done, grep for any surviving copy of the old logic, because a copy in a target codebase_search ranked low is exactly the one that will rot. Finish by running swift-format so the final diff shows the refactor and not indentation.

## Steps

1. Run atlas in your Swift package, the one with a Package.swift, and let Atlas read your targets, protocols, and dependencies.
2. Ask codebase_search for the behavior (not the exact code) to surface near-duplicate Swift implementations across Sources/ that grep would miss.
3. Read each hit with the read tool and confirm the copies are genuinely equivalent, checking optional handling, throws, and async/await, before collapsing them.
4. Create the shared helper with the write tool in a target both callers can import; write shows the full diff in the permission prompt before the file is created, and Package.swift must list the dependency.
5. Replace each duplicate with a call using apply_patch, one file per patch, so each swap is independently reviewable and revertible.
6. Run XCTest via swift test with the bash tool after every swap, not once at the end.
7. Finish by grepping for any surviving copy of the old Swift logic and confirming zero hits.
8. Run swift-format so the final diff carries the refactor rather than formatting churn.

## FAQ

### how to find duplicated code in a swift package with an ai agent

Ask Atlas's codebase_search for the behavior rather than the exact code. Swift copies usually differ in variable names, so grep misses them. Atlas fuses semantic and keyword retrieval with reciprocal rank fusion and returns whole declarations.

### why does grep miss copy pasted swift code

Because the copies are not textually identical. One function names the variable response and another names it payload, one is async and one is not. Duplication is a semantic problem, which is why Atlas uses codebase_search instead of grep to find it.

### where should a shared helper go in a swift package manager project

In a target that every duplicate site can import, with the dependency declared in Package.swift. Atlas reads your existing target graph before choosing, then creates the file with the write tool, which shows the full diff in the permission prompt first.

### atlas apply_patch one file per patch why

So each swap is independently reviewable and revertible. If replacing the duplicate in Sources/Networking turns out to change behavior, that single patch is reverted without touching the swap in Sources/Auth. Atlas snapshots file changes as git patches.

### how do i verify a swift refactor did not break anything

Run XCTest via swift test with the bash tool after every swap, not once at the end. The bash tool records the process exit code in its metadata, so a green run is proven. Finish by grepping for any surviving copy of the old logic.

### can atlas adopt async await while extracting a swift helper

Only if the copies genuinely agree. Read each hit first and confirm they are equivalent: two Swift functions that differ in actor isolation or throws are not the same function, and merging them would change behavior at a callsite.

### does atlas run swift-format after a refactor

You can have it run swift-format through the bash tool as the last step, so the final diff carries the deduplication rather than indentation churn. Every tool call is permission-gated against allow, ask, and deny rules before it runs.

---

Canonical HTML: https://runatlas.sh/resources/stacks/extract-a-shared-helper-from-duplicated-code-in-swift
Source of truth: aeo_pages row `/resources/stacks/extract-a-shared-helper-from-duplicated-code-in-swift` (segment: Stacks) (this file is generated from it, never hand-edited).
Licence: Atlas is proprietary with a free core. It is not open source and there is no public source repository.
