Skip to main content
Now there’s another powerful thing you can do with Claude Code: analyze and modify large codebases to find architectural issues, implement fixes, and validate the result with builds.
A presentation slide titled "Understanding Codebases with Claude" with a dark curved panel on the right containing the word "Demo" in large blue text. The slide has a clean, minimalist design and a small copyright notice for KodeKloud.
This demo uses a moderately large repository from my collection called RetroRacer. I suspected it was a JavaScript/Three.js frontend with a Go backend (initially guessed a SQLite-backed API), so I asked Claude Code to analyze the repo and answer targeted questions.
Before allowing tools to read or execute files, review permissions carefully. Executing untrusted code is unsafe; reading files may still surface sensitive data.

Granting access and onboarding

Claude Code asks for permission to read (and optionally execute) files in the workspace. The prompt for this repo looked like:
Do you trust the files in this folder?

/Users/jeremy/Repos/RetroRacer

Claude Code may read files in this folder. Reading untrusted files may lead Claude Code to behave in unexpected ways.

With your permission Claude Code may execute files in this folder. Executing untrusted code is unsafe.

https://docs.anthropic.com/s/claude-code-security

 1. Yes, proceed
 2. No, exit

Enter to confirm · Esc to exit
After granting access, Claude Code shows onboarding tips and lets you initialize a workspace:
* Welcome to Claude Code!

/help for help, /status for your current setup

cwd: /Users/jeremy/Repos/RetroRacer

Tips for getting started:

1. Run /init to create a CLAUDE.md file with instructions for Claude
2. Use Claude to help with file analysis, editing, bash commands and git
3. Be as specific as you would with another engineer for the best results
4. Run /terminal-setup to set up terminal integration

 Tip: Cmd+Escape to launch Claude in your IDE

> Try "refactor <filepath>"

? for shortcuts
I ran the terminal setup so Claude would know my VS Code key bindings:
> /terminal-setup
 Installed VSCode terminal Shift+Enter key binding
  See /Users/jeremy/Library/Application Support/Code/User/keybindings.json

> 
? for shortcuts
Tip: Being specific when asking about code (file paths, function names, or error messages) yields more precise analysis and actionable fixes.

High-level codebase overview

I asked for a high-level overview:
> give me a high level overview of this codebase

 I'll analyze the codebase structure to give you a high-level overview.

● List(.)
└ Listed 47 paths (ctrl+r to expand)

● Read(README.md)
└ Read 3 lines (ctrl+r to expand)

● Read(package.json)
└ Read 32 lines (ctrl+r to expand)

● Read(backend/go.mod)
└ Read 14 lines (ctrl+r to expand)

* Crunching (12s · ↓ 93 tokens · esc to interrupt)
Claude produced an accurate summary:
  • RetroRacer is a multiplayer racing game with a retro aesthetic built with modern web technologies and a Go backend.
  • Architecture:
    • Frontend: JavaScript client using Three.js for 3D graphics
    • Backend: Go server with WebSocket support for real-time multiplayer
    • Build System: Vite for development and bundling
Key frontend and backend files were listed and categorized.

Technology stack (quick reference)

LayerTechnologies / LibrariesNotes
FrontendJavaScript (ES6+), Three.js, ViteClient game logic, rendering and UI
BackendGo, Gorilla WebSocket, UUID libsReal-time server, game loop, networking
TestingJest (frontend), Go testingUnit and integration tests

Key files and structure

AreaImportant files
Frontendindex.html, main.js, multiplayer.js, connection-manager.js, SkidMarkSystem.js, ui-helpers.js
Backend (/backend)main.go, server/* (WebSocket & hub), game/* (physics & state), network/, config/
Build & toolingpackage.json, go.mod, Vite config
Links and references:

Backend architecture observations

Claude highlighted backend patterns worth noting:
  • Event-driven hub model (hub.go) using Go channels for non-blocking communication.
  • 60 Hz game tick with delta-time physics simulation.
  • Mutex-protected shared state and goroutines for per-client I/O.
  • JSON message protocol for real-time sync between clients and server.
  • Hub/channel design optimized for low-latency gameplay and limited concurrent players per hub (e.g., ~8).

Confirming persistence assumptions

I had assumed a SQLite-backed API, so I asked Claude to search for database access code:
> find the files that handle database access

 Wrangling… (0s · 0 tokens · esc to interrupt)
Findings:
  • No database dependencies in go.mod (only WebSocket, UUID, and test libraries).
  • No SQL or database-related imports in Go files.
  • No persistence layer found — game state is stored in memory via Go structs.
  • Logging is file-based to retroracer_server.log.

Current data storage (summary)

Data TypeStorage
Game stateIn-memory (game/state.go structs)
Player dataTransient, stored in in-memory hub/client maps
SessionsWebSocket connections maintained in memory
LogsFile-based (retroracer_server.log)
This confirmed that the server is ephemeral and does not persist game state across restarts.

Log analysis and detected issues

I asked Claude to scan recent server logs for errors:
> what are the most recent errors found in retroracer_server.log

+ Computing... (0s · 0 tokens · esc to interrupt)
The log scan did not show many explicit ERROR-level messages, but it surfaced serious synchronization and lifecycle issues. Key problems found:
  1. Player/client map synchronization problem
    • Example log: “[DEBUG] Removing player 1748150421520079300-2524 from players map - no client found” — players are removed immediately after joining, indicating a race between registration and tracking.
  2. Client count discrepancy
    • Broadcasts were dispatched to 0 clients even as players were joining — client tracking is inconsistent.
  3. Phantom heartbeat messages
    • Heartbeats arrive from clients that appear removed from internal maps — the WebSocket remains open while server state shows zero clients.
  4. WebSocket connection errors
    • Lines like “websocket: close 1001 (going away)” and “Error sending ping to client: websocket: close sent” indicate disconnects, but timing makes them look like symptoms of premature cleanup.

Root cause (as computed by Claude)

  • Dual maps (clients + players) combined with concurrent operations produced race conditions where cleanup and synchronization tasks remove players before registration completes. The recommended approach is:
    1. Use a single source of truth (clients map).
    2. Add a registration state flag to the Client struct to avoid treating partially-registered connections as active players.
    3. Perform registration atomically inside the hub event loop using a registration message channel.

Suggested refactor (atomic registration)

Claude suggested introducing an atomic registration message type and channel so registrations are handled inside the hub’s main event loop. Example server types:
// server types to coordinate registration atomically
type registrationMessage struct {
    client *Client
    done   chan bool
}

type Hub struct {
    // ... existing fields
    registerClient chan registrationMessage
}
And in the hub main loop:
// In hub.go Run():
select {
case regMsg := <-h.registerClient:
    h.handleAtomicRegistration(regMsg.client)
    regMsg.done <- true
// other cases...
}
Adopt a single source of truth by removing a duplicate players map and adding a registration flag:
type Client struct {
    // existing fields...
    registrationComplete bool
    registrationMutex    sync.Mutex
    // ...
}
This prevents partially-registered clients from being treated as active players during concurrent operations.

Implementing fixes and validating with build

I asked Claude to implement the changes and run a build. During the edit-and-build cycle the initial compile failed (expected while refactoring):
cd /Users/jeremy/Repos/RetroRacer/backend && go build .
# Build output (errors)
server/hub.go:377:23: h.players undefined (type *Hub has no field or method players)
server/multiplayer.go:97:16: s.defaultHub.players undefined (type *Hub has no field or method players)
server/multiplayer.go:107:33: s.defaultHub.players undefined (type *Hub has no field or method players)
# ... additional lines omitted for brevity
Claude iterated, updating references and helper methods to rely on the clients map and the registrationComplete flag. After the edits, Claude rebuilt the backend:
cd /Users/jeremy/Repos/RetroRacer/backend && go build . && echo "Build successful!"
Build successful!

Final result and rationale

  • Root cause: concurrent synchronization between two maps (clients and players) led to race conditions and premature player removal.
  • Fixes applied:
    1. Single source of truth — removed duplicate players map and used clients map consistently.
    2. registrationComplete flag added to Client to prevent partial registration races.
    3. Atomic registration via registration messages handled in the hub event loop.
  • Outcome: The race condition was resolved, build succeeds, and the log anomalies tied to the race condition were addressed.
This workflow demonstrates how Claude Code can:
  • Analyze a large repository to identify architectural and concurrency issues.
  • Recommend targeted code changes (with concrete examples).
  • Implement refactors and run builds to validate fixes.
References and further reading: Thank you for following this lesson.

Watch Video