Tickd.ai
← The Tickd Guide

Comparisons

Claude 3.5 Sonnet vs Gemini 1.5 Pro for Large-Scale Codebase Refactoring: Which Engine Actually Understands Cross-File Dependencies?

We put Claude 3.5 Sonnet and Gemini 1.5 Pro head-to-head on a brutal multi-file refactoring task. Here is which LLM actually understands your dependency graph without losing its mind.

Updated 10/14/2026

The Nightmare of the Multi-File Refactor

We have all been there. You have a legacy codebase that has slowly mutated over three years. It is a tangled web of Express controllers, loosely typed TypeScript interfaces, and database queries that belong in a museum. You want to refactor the entire mess to use Fastify and Zod for runtime schema validation.

In the old days, this meant hours of manual grepping, renaming imports, and praying your test suite caught the downstream breakages. Today, we have LLMs with massive context windows promising to do the heavy lifting for us. But when you throw a codebase with dozens of interconnected files at an AI, the marketing promises of "million-token context windows" quickly clash with the messy reality of software engineering.

We decided to put two of the heavyweights head-to-head on a complex refactoring job: Anthropic's Claude 3.5 Sonnet and Google's Gemini 1.5 Pro. We wanted to see which model actually understands how files talk to each other, and which one merely pretends to.

The Test: Moving from Express/Joi to Fastify/Zod

To make this test realistic, we fed both models a medium-sized TypeScript repository. It consisted of: * 6 controller files. * 4 route definition files. * 10 Joi validation schemas. * A database client file wrapping a Prisma setup. * Associated unit and integration tests.

The task was simple to explain, but brutal to execute: rewrite the entire routing and validation layer to use Fastify and Zod, update all imports across the codebase, ensure error handling matched Fastify's native patterns, and rewrite the tests to match the new HTTP client behaviour.

To do this successfully, an LLM cannot just look at one file in isolation. It has to understand the dependency graph—knowing that changing a schema definition in schemas/user.ts requires updating the validator in controllers/userController.ts and changing how the test payload is structured in tests/user.test.ts.

Round 1: Mapping the Dependency Graph

Before writing code, an LLM has to parse the codebase. This is where we look at how the models conceptualise the relationships between files.

Gemini 1.5 Pro has a massive advantage on paper with its 2-million-token context window. We loaded the entire codebase into its context effortlessly. When asked to explain the dependency graph, Gemini gave an incredibly broad, sweeping overview. It correctly identified every import chain. However, when we asked it to identify which specific controllers would break if we modified a shared utility function, it began to hand-wave, grouping files together and giving generic advice rather than surgical analysis.

Claude 3.5 Sonnet has a smaller context window (200k tokens), but it analysed the dependencies like a seasoned staff engineer. Instead of just listing imports, Sonnet mapped out the exact data-flow path. It pointed out a circular dependency in our legacy code that we had not even mentioned—a classic developer oversight where an interface was importing from a service that imported back from the interface's module.

While Gemini has the space to hold your entire digital life in its head, Sonnet seems to have a far better grasp of what makes the actual code tick. It prioritises logical flow over sheer volume.

Round 2: The Output Limit Bottleneck

Here is the industry's dirty secret: a model can have a 2-million-token input window, but if its output limit is restricted to 8k tokens, it cannot write your refactored code in one go.

This is where Gemini 1.5 Pro faltered. Because it had the entire codebase in context, it tried to generate massive, multi-file code blocks. But halfway through writing the refactored controller files, it hit its output token limit and cut off mid-declaration. When we prompted it to "continue," it lost the formatting, forgot its place in the import pathing, and started generating duplicate exports.

Sonnet, on the other hand, worked within its 8k output limit by being incredibly strategic. Instead of vomiting out thousands of lines of code in one go, it broke the refactoring down into a clear, multi-step execution plan. It outputted the core Zod schemas first, then provided precise diffs for the controllers, and finally gave us the updated routing configurations. If you are struggling with Sonnet getting stuck on long generations, our guide to troubleshooting Anthropic workflows offers practical tips on how to structure your multi-prompt sessions to avoid this exact bottleneck.

Round 3: Code Correctness and Imposter Imports

There is nothing more annoying than an LLM that invents a library function that does not exist. We watched both models closely for hallucinations, especially when migrating Joi's .alphanum() and .required() chain to Zod's equivalent syntax.

Gemini 1.5 Pro made three critical errors in its Zod schema generation: 1. It tried to use .optional().default() in a way that violated Zod's type inference rules for our TypeScript build. 2. It generated a non-existent Fastify plugin for error handling, assuming a package called fastify-custom-errors existed on npm. 3. It failed to update the relative import paths for two of our controllers, leaving broken ../ paths in the route files.

Claude 3.5 Sonnet generated flawless Zod schemas. Its understanding of TypeScript's strict type checker was remarkably precise. It did not invent any npm packages; instead, it wrote a custom Fastify error handler inline, fully typed, matching our existing custom error classes. It also used correct relative paths across every single refactored file. If you are working with complex type definitions, you can reference our glossary for a deep dive on how ASTs (Abstract Syntax Trees) help models parse types, though Sonnet seems to do this natively with terrifying accuracy.

The Verdict: Which Engine Should You Use?

If you are refactoring a complex codebase, the winner is clear: Claude 3.5 Sonnet is the superior engine for actual code output and logical dependency mapping.

  • Use Claude 3.5 Sonnet when you need surgical code correctness, strict TypeScript typing, logical step-by-step refactoring plans, and accurate relative imports across files.
  • Use Gemini 1.5 Pro primarily as a search and discovery engine for massive codebases. It is brilliant for uploading a 100,000-line repository and asking, "Where in this codebase do we handle database retries?" but do not trust it to write the refactored code without hand-holding. If you do run into issues with Gemini's coding logic, check out our Gemini troubleshooting guide to help keep its outputs on track.

For serious developer workflows, context size means nothing if the engine cannot write precise, compile-ready code. Sonnet remains the developer's choice.

codingclaudegeminitypescriptrefactoring

Keep going

Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.

Which AI should I use for this?

Tickd is independent and not affiliated with any AI company.