Advanced Code Editing

Master complex code manipulation, refactoring, and editing techniques using Gemini CLI's advanced features.

What Makes Editing 'Advanced'?

Basic editing is asking Gemini CLI to fix a single function or rename a variable. Advanced editing is coordinating changes across multiple files, migrating an entire codebase from one technology to another, or applying a systematic refactoring that would take hours to do manually.

Three capabilities make these large-scale edits practical with Gemini CLI:

  • Multi-file context — Pass several files as arguments and Gemini CLI reasons across all of them simultaneously, keeping cross-file references, imports, and interfaces consistent.
  • Plan Mode — Ask Gemini CLI to describe every change it will make before it makes any of them. Review the plan, modify it if needed, then execute.
  • Shell scripting integration — Combine Gemini CLI with standard Unix tools to apply changes to hundreds of files in parallel, with automatic rollback on failure.

Multi-File Editing

Many edits cannot be made file by file because the changes are interdependent. Renaming an interface, changing a function signature, or restructuring a module all require updating callers, importers, and type definitions simultaneously. Gemini CLI handles this when you pass all affected files as arguments.

Rename a type across multiple files

Before: UserProfile interface defined in types.ts and used in three components.

# Pass all files that reference the type

gemini 'Rename the UserProfile interface to Profile across all these files. Update all import statements and type annotations.' \

src/types.ts src/components/Header.tsx src/components/Sidebar.tsx src/pages/profile.tsx

Before (types.ts)

- export interface UserProfile {

id: string

name: string

- }

After (types.ts)

+ export interface Profile {

id: string

name: string

+ }

Update a function signature and all call sites

Changing a function to accept an options object instead of positional parameters requires updating the definition and every call site simultaneously.

# Refactor to options-object pattern

gemini 'Refactor createUser(name, email, role) to accept a single options object: createUser({ name, email, role }). Update the definition in userService.ts and all call sites.' \

src/services/userService.ts src/controllers/authController.ts src/tests/user.test.ts

Before (call site)

- createUser('Alice', 'a@x.com', 'admin')

After (call site)

+ createUser({

+ name: 'Alice',

+ email: 'a@x.com',

+ role: 'admin'

+ })

Refactoring Operations

Refactoring improves code structure without changing behavior. These examples show before-and-after patterns for the most common refactoring operations.

Extract a function from a long method

Before

function processOrder(order) {

// 20 lines of validation

if (!order.items?.length) throw new Error(...)

if (order.total < 0) throw new Error(...)

// ... more validation

// 30 lines of processing

const tax = order.total * 0.1

// ...

}

After

function validateOrder(order) {

if (!order.items?.length) throw new Error(...)

if (order.total < 0) throw new Error(...)

}

function calculateTax(total) {

return total * 0.1

}

function processOrder(order) {

validateOrder(order)

const tax = calculateTax(order.total)

}

gemini 'Extract the validation logic into a validateOrder() function and the tax calculation into calculateTax(). Keep the processOrder function as the entry point.' < orderService.ts

Convert class components to React hooks

Before (class component)

class Counter extends React.Component {

state = { count: 0 }

increment = () => {

this.setState({ count: this.state.count + 1 })

}

render() {

return <button onClick={this.increment}>

{this.state.count}

</button>

}

}

After (hooks)

function Counter() {

const [count, setCount] = useState(0)

const increment = () => setCount(c => c + 1)

return (

<button onClick={increment}>

{count}

</button>

)

}

# Convert all class components in a directory

gemini 'Convert class components to hooks' components/*.jsx

Apply consistent changes across multiple files and directories.

Code Migration: JavaScript to TypeScript

Migrating a JavaScript codebase to TypeScript is one of the most impactful refactors you can make for long-term maintainability. It is also one of the most tedious to do by hand. Gemini CLI can automate the mechanical parts — adding type annotations, defining interfaces, converting .js to.ts files — so you can focus on the genuinely difficult type decisions.

Step 1: Migrate a single file

Start with a leaf file (one that has no imports from your own codebase) to validate the approach.

Before (utils.js)

function formatCurrency(amount, currency) {

return new Intl.NumberFormat('en-US', {

style: 'currency',

currency,

}).format(amount)

}

module.exports = { formatCurrency }

After (utils.ts)

export function formatCurrency(

amount: number,

currency: string

): string {

return new Intl.NumberFormat('en-US', {

style: 'currency',

currency,

}).format(amount)

}

gemini 'Convert to TypeScript. Use explicit types for all parameters and return values. Replace CommonJS exports with ES modules.' < src/utils.js > src/utils.ts

Step 2: Bulk-migrate the entire project

#!/bin/bash

# migrate-to-ts.sh

find src -name '*.js' | while read jsfile; do

tsfile="${jsfile%.js}.ts"

echo "Migrating $jsfile → $tsfile"

gemini "Convert to TypeScript. Use ES module syntax." < "$jsfile" > "$tsfile"

done

# Verify the build

npx tsc --noEmit

Step 3: Fix remaining type errors

After the bulk migration, tsc will likely report some remaining type errors. Use Gemini CLI to fix them in batches:

# Pipe tsc errors to gemini for analysis

npx tsc --noEmit 2>&1 | gemini 'These are TypeScript compilation errors. Group them by file and suggest fixes for each.'

Using Plan Mode for Complex Edits

Plan Mode is Gemini CLI's most powerful safety feature for large-scale edits. When you add--plan to a command, Gemini CLI describes every change it intends to make in a numbered list — but makes no modifications to any file. You review the plan, request adjustments, and only run without--plan when you are satisfied.

Example: Plan a database migration refactor

# Step 1: Generate the plan (no files are changed)

gemini --plan 'Migrate all Mongoose model definitions to Prisma schema format. Update all service files to use Prisma client instead of Mongoose.' src/models/ src/services/

Gemini CLI outputs a plan like:

Plan (24 changes across 11 files):

1. Create prisma/schema.prisma with User, Post, Comment models

2. Delete src/models/user.model.ts (replaced by Prisma)

3. Delete src/models/post.model.ts

4. Update src/services/userService.ts: replace mongoose.model() with prisma.user

5. Update src/services/postService.ts: replace populate() with Prisma include

... 19 more changes

# Step 2: Execute after review

gemini 'Migrate all Mongoose model definitions to Prisma schema format. Update all service files to use Prisma client instead of Mongoose.' src/models/ src/services/

When to use Plan Mode

  • • Any edit that touches more than 5 files simultaneously
  • • Database or ORM migrations where wrong changes corrupt data
  • • API contract changes that affect multiple services
  • • Dependency upgrades with breaking changes
  • • Security-critical refactors (authentication, authorization flows)

Advanced Techniques

Large-scale Refactoring

gemini 'Refactor this codebase to use TypeScript' --recursive src/

gemini 'Convert class components to hooks' components/*.jsx

Apply consistent changes across multiple files and directories.

Context-aware Editing

gemini 'Update this function to match the new API schema' --context api-schema.json function.js

Use external context files to inform editing decisions.

Performance Optimization

gemini 'Optimize this code for memory usage and speed' --profile performance algorithm.py

Focus editing on specific performance aspects.

Working with Code Patterns

Pattern-based Refactoring

#!/bin/bash

# Apply design patterns across codebase

find src -name '*.js' | while read file; do

gemini 'Apply observer pattern where appropriate' < '$file' > '$file.tmp'

mv '$file.tmp' '$file'

done

Frequently Asked Questions

How do I migrate a JavaScript project to TypeScript using Gemini CLI?

Use a two-pass approach. First run:find src -name '*.js' | xargs gemini 'Convert to TypeScript. Add explicit types to all function signatures, variables, and React props. Do not use 'any'.'This generates .ts files. Then run a second pass to fix type errors reported bytsc --noEmit.

Can Gemini CLI edit multiple files that depend on each other?

Yes. Pass all related files as arguments:gemini 'Rename the UserProfile interface to Profile across all these files. Update all imports.' src/types.ts src/components/Header.tsx src/pages/profile.tsxGemini CLI processes all files together and keeps cross-file references consistent.

What is Plan Mode and when should I use it?

Plan Mode separates the planning step from the execution step. Use it for large refactors where you want to review and approve the full list of changes before any files are modified. Run: gemini --plan 'Migrate all API calls from axios to fetch.'Gemini CLI will output a numbered list of every change it intends to make. Review the plan, then run without --plan to execute.

How do I refactor class components to React hooks without breaking the app?

Convert one component at a time and run tests after each. Use:gemini 'Convert this class component to a functional component with hooks. Preserve all existing behavior including error boundaries if present.' < UserList.jsx > UserList.tsxThen run npm test to confirm nothing broke before moving to the next component.