Welcome back! In the last lesson, we learned how to connect OpenCode to external data sources. Now, we are turning our focus inward to explore how to manage large, multi-file projects. Working with massive codebases presents unique challenges. When you change a single file, you risk breaking dependencies, creating inconsistencies, or causing unintended ripple effects across your entire project. Managing these complex relationships manually can be quite exhausting and prone to errors.
In this lesson, we will learn how to safely navigate and modify complex project structures using advanced OpenCode features. You will revisit @ file references to target specific areas, ! shell commands to interact with your system, and the /undo command to safely recover from mistakes. By the end of this lesson, you will be able to refactor across dozens of files with confidence. Let's dive in!
Before making changes to a large project, you must first understand how its files are organized. Project Structure refers to the directory tree and the architectural patterns that group related code together, such as separating database models from API routes.
This matters because asking OpenCode to make changes without understanding the big picture can lead to messy, disorganized code. To get started, you can simply ask OpenCode to summarize your codebase. OpenCode will automatically read your directory tree and identify the key components for you.
When you run this prompt, OpenCode scans your folders and explains how data flows through your application. It maps out where your tests, services, and models live so that you can understand the layout.
To help OpenCode understand your specific project better, you can create a helper file named AGENTS.md. This file stores custom instructions about your project's unique rules, context, and preferred coding styles. As you may recall, the watcher.ignore field inside your opencode.json file can also hide irrelevant folders, like temporary build files or secret configurations. In the context of large projects, keeping OpenCode focused strictly on your source code becomes especially important so it does not get distracted by generated files.
Once you understand the broad architecture, you will often need to inspect specific components in detail. As a quick recap, File References let you point directly to a specific file or folder using the @ symbol followed by the file path. In the context of large projects, this becomes especially valuable — with hundreds of files, letting an AI scan everything just to answer a small question is slow and wastes computing power. By narrowing your focus, you get faster, more accurate answers.
In this example, we use the @ symbol to directly attach the auth.py file to our prompt. OpenCode instantly reads just that file and explains the authentication logic inside it without searching the rest of the project.
You can also use this syntax to reference entire directories, like @src/models/, if you want OpenCode to analyze a specific group of related files. This focused approach ensures the AI does not get confused by similarly named functions or variables that might exist in other parts of your project.
A common task in large projects is updating names to better reflect your business logic. Coordinated Refactoring is the process of safely changing a variable, function, or class name across every single file where it is defined, imported, or used. This matters because missing even a single import during a rename will crash your application instantly. OpenCode excels at this task by finding and updating all connected pieces simultaneously.
When you issue this command, OpenCode does not just blindly find and replace text like a simple search tool. It first inspects the codebase to deeply understand how the User class is used.
As shown in the output, it updates the core definition in your models folder and then systematically updates the routes, services, and test files that rely on it. Notice how the output confirms exactly which files were modified. This intelligent coordination saves you from manually hunting down broken imports across dozens of directories and ensures your project remains in a working state.
Beyond renaming things, you will often need to apply structural changes across a project. Pattern Fixing involves finding code that violates a project standard and automatically correcting it in bulk. This matters because maintaining high code quality manually across hundreds of files is tedious and easily neglected by developers. You can ask OpenCode to search for missing elements, like missing documentation, or to fix broken import paths after you move a folder.
In this first example, we ask OpenCode to identify a negative pattern (missing docstrings) and fix it. OpenCode will scan the directory, locate every function without a comment, and generate a concise description based on what the underlying code actually does.
Similarly, for the imports example above, OpenCode will track down and rewrite the path statements across the entire project. If you recently renamed a folder from utils to helpers, this command ensures every file points to the new location. This turns a multi-hour chore of standardizing a sprawling codebase into a task that takes just a few seconds.
Similar to fixing broken patterns, you also need to ensure different files behave exactly the same way. Enforcing Consistency means analyzing multiple files that do similar jobs and making sure they follow a unified, standard approach. This matters because inconsistent code, such as returning different JSON structures for errors, creates terrible bugs for the frontend applications that consume your API. OpenCode can compare these files side-by-side, identify the deviations, and rewrite them to match a single standard.
When we give this instruction, OpenCode reviews the current state of our API route files. It compares how users.py, products.py, and orders.py handle their failures.
As shown in the output, it discovers that users.py has a good pattern, but the others handle errors poorly. It then defines a recommended standard pattern using standard HTTP status codes and a consistent shape. Finally, it rewrites the non-compliant files to match the standard. This ensures that no matter which endpoint a user hits, the application responds predictably.
Making massive changes across a codebase is powerful, but it also carries significant risk. Verification and Recovery involve inspecting exactly what the AI modified and safely rolling back those changes if they are incorrect. This matters because AI is not perfect; you must always review multi-file modifications before committing them to your project history to avoid introducing silent bugs.
OpenCode allows you to run shell commands directly in the chat by prefixing them with an exclamation mark (!). By running !git diff, you ask your version control system to print a line-by-line comparison of exactly what OpenCode changed. You can safely review the deleted lines in red and the newly added lines in green to ensure the logic is sound.
If you spot a mistake in the logic or realize the refactor went too far, you can type /undo directly in the chat. This special session recovery command instantly reverts all the file changes OpenCode just made. It acts as an immediate safety net, returning your project to its previous safe state without requiring complex git commands.
Fantastic job! In this lesson, we scaled up our skills to handle large, multi-file projects efficiently. You learned how to use helper files like AGENTS.md and opencode.json and ask OpenCode for architectural summaries to understand your project structure. We revisited using @ file references to narrow OpenCode's focus and save processing time. You also saw how to perform coordinated refactors, fix codebase patterns in bulk, and enforce consistent logic across multiple files.
Most importantly, you learned how to use !git diff to review changes safely and the /undo command to recover from mistakes easily. In the upcoming practice exercises, you will step into the CodeSignal IDE to navigate a complex sample project. You will practice using the @ symbol, refactoring scattered variables, and verifying your updates. Let's get ready to write some clean, consistent code!
