So i just had to redo an ENTIRE project over 100k lines of code because 10 of the files had like over 4k lines of code each, not only was cursor itself taking forever because of the huge file size, but it was unable to even diagnose errors let alone make changes because the files were so big.
Anyways, to ensure I never had to do something like this again, I came up with a new method
But before implementing that, I forced myself to break out of the AI laziness induced slog and do the basics
keep track of the Agent and make sure it never creates files over 700 lines
Feed data directly back to it with MCPs and debugging
consistently have it reorganize the entire file structure into folders and subfolders (I don’t even look at the organization, but it helps the Agent not get confused)
And after doing all this, I had a clean enough project setup that I was able to make THIS key improvement (cursor should add a feature to do this automatically)
At the end of EVERY chat where either a major feature is added or a ton of errors are fixed, even the beginning setup chat
I ask it to create a text file explaining exactly what it did and exactly which files are involved.
Then when I add a new one I update all the rest to be compatible with it.
This way cursor will run way faster and never get confused. It’s like a version of cursor where it completely forgets all the dumb stuff it did but entirely remembers all the smart stuff it did and builds on it.
I guess he means when adding a new feature he tells the agent to update the documentation.
Actually I find that when working on big projects, you just can’t delegate to the AI you have to get your foundation right and apply the SOLID principals and general software engineering principals your self.
I added in the rules those principals to the AI to follow but most of the times your have to specifically include the right rules that you want the AI to follow with some extra and precise instructions.
For my workflow I find it useful to always start in the chat mode ctrl+L to make sure the AI understands the context of what I want to achieve and include the bits of code we are concerned with, only after that I jump into agent mode to make the changes. There is a feature that should be checked for that to share context between agent and chat, I believe it’s marked as beta but is checked by default.
Vibe coding is great, but I feel that for now it’s only useful for quick prototyping and ideation and not suited for real production or bigger projects.
Also I believe big files in a project isn’t healthy whether you work with AI, with a team or even when working alone.
If someone is on this case even AI will get confused as you described so well.
I would approach this refactoring with cursor with in file edits first (ctrl+K) for chunks of code. If you don’t remember what the code does or simply don’t know maybe ask cursor to add comments for each chunk of code, consolidating and organizing those chunks in file than manually creating new files to group them and ask the AI to add the dependencies precisely on those files without making any other changes, than you can continue refactoring using the agent mode or the chat mode.
Yeah, if I knew more about planning large codebases I would implement this
If you could share whatever you’re using for your code planning and principles documentation that would be awesome
You’re right, this is basically pushing up against the limits of vibe coding, but I’ve been able to make some pretty extensive codebases with this approach
Sure even though I know most AI models are trained to know all the principals and I could just mention them but I find there is a some better performance to include them in the Rules and target them when needed
Best Practices - General
You are generating code that follows general software engineering best practices. Adhere to these guidelines:
WRITE clean, maintainable code:
Follow consistent formatting and naming conventions
Document public APIs and complex logic
Write automated tests for functionality
Handle errors and edge cases appropriately
IMPLEMENTATION guidelines:
Use meaningful names for variables, functions, and classes
Keep functions/methods short and focused
Apply appropriate design patterns for common problems
Follow language-specific idioms and conventions
VALIDATION criteria:
Code passes static analysis checks
Documentation is clear and up-to-date
Tests verify expected behavior
Error handling is comprehensive
EXAMPLE practices:
Consistent error handling strategy
Comprehensive logging for troubleshooting
Clear separation between interface and implementation
Secure coding practices for sensitive operations
KISS (Keep It Simple, Stupid)
You are generating code that follows the KISS principle. Adhere to these guidelines:
IMPLEMENT the simplest solution that satisfies requirements:
Choose straightforward approaches over complex ones
Avoid premature optimization and over-engineering
Use standard libraries and patterns where appropriate
Prioritize readability and maintainability
IMPLEMENTATION guidelines:
Write clear, self-documenting code
Limit method/function complexity
Use descriptive naming over clever abbreviations
Break complex operations into simple steps
VALIDATION criteria:
New developers can understand the code quickly
Solutions directly address the problem at hand
Implementation avoids unnecessary abstractions
Code is concise without being cryptic
EXAMPLE structure:
Direct data validation instead of complex rule engines
Simple conditional logic instead of pattern matching
Straightforward data structures instead of specialized collections
Clear procedural steps instead of complex chains
DRY (Don’t Repeat Yourself)
You are generating code that follows the DRY principle. Adhere to these guidelines:
ELIMINATE duplication by centralizing common functionality:
Maintain a single source of truth for knowledge/logic
Extract repeated code into reusable functions/modules
Centralize configuration and constants
Apply abstraction for similar operations
IMPLEMENTATION guidelines:
Create utility functions for common operations
Use inheritance or mixins for shared behavior
Implement templates/generics for similar data structures
Follow the “Rule of Three” before abstracting (wait until code is duplicated 3+ times)
VALIDATION criteria:
No copy-pasted code across the codebase
Changes can be made in a single location
Common operations use shared implementations
Configuration values are centralized
EXAMPLE structure:
Utility classes for common operations
Shared validation functions across forms
Centralized error handling
Template methods for similar processes
Composition over Inheritance
You are generating code that follows the Composition over Inheritance principle. Adhere to these guidelines:
FAVOR object composition over class inheritance:
Build complex objects by combining simpler components
Use interfaces to define behavior contracts
Prefer “has-a” relationships over “is-a” relationships
Avoid deep inheritance hierarchies (>2-3 levels)
IMPLEMENTATION guidelines:
Inject dependencies rather than extending base classes
Use interface implementation for behavior contracts
Apply decorator pattern for extending functionality
Implement mixins/traits for reusable behaviors
VALIDATION criteria:
Features are added through composition
Components can be reused in different contexts
Behavior can be modified without changing inheritance
System is flexible to requirement changes
EXAMPLE structure:
Vehicle with Engine component instead of Car extends Vehicle
Logger interface with multiple implementations
Authentication service composed of multiple validators
UI component composed of smaller, reusable elements
Separation of Concerns (SoC)
You are generating code that follows the Separation of Concerns principle. Adhere to these guidelines:
DIVIDE functionality into distinct, independent modules:
Each module handles ONE specific aspect of the system
Modules interact through well-defined interfaces
Changes in one module should minimally impact others
Domain boundaries should be clearly established
IMPLEMENTATION guidelines:
Group related functionality within logical boundaries
Hide implementation details through encapsulation
Use interfaces or events for cross-module communication
Maintain independent testability for each component
VALIDATION criteria:
Components can be developed, tested, and maintained independently
Interfaces between modules are clearly defined
System functionality is logically partitioned
Minimal dependencies exist between separate concerns
EXAMPLE structure:
Data layer: Handles data persistence only
Business layer: Implements domain logic only
Presentation layer: Manages user interaction only
Service layer: Coordinates between layers only
Single Responsibility Principle (SRP)
You are generating code that follows the Single Responsibility Principle. Adhere to these guidelines:
ENSURE each component has exactly ONE reason to change:
Classes/modules should focus on a single capability
Functions should perform one logical operation
Avoid “god” classes that handle multiple concerns
Split components with “and” in their purpose description
IMPLEMENTATION guidelines:
Name classes/modules after their single responsibility
Keep components small and focused (<200 lines recommended)
Use dependency injection for required services
Extract unrelated functionality into separate components
VALIDATION criteria:
Component name clearly describes its sole purpose
All methods relate to the primary responsibility
Changes to one feature don’t affect unrelated functionality
There are so many other rules with some trade offs for each approach, so I recommend you research them more in depth and see what approaches and rules suit your project and preferences more.
This does sound like a project beyond what AI coding is currently capable of. I work on large codebases and it does take a different strategy to vibe coding for fun/throwaway apps.
The most important element of it is that you invest a lot of time in planning and reviewing. I’ve just spent about an hour having claude plan out a new feature for me, with me intervening and having discussions as I’m a manager of a junior dev (who happens to have an expansive knowledge but often has weird ideas and has to be coached back to normalcy). I’m letting it run now then I’ll probably spend another hour reviewing and ensuring everything makes sense, following up with fine tuning.
The caveat is that it does take enough experience to be able to guide the AI and pick up mistakes. Without that it tends to turn into a snowball rolling down a hill where it picks up oddities that magnify and become too big to fix.
Yes it does, that’s why you have to be selective and to make the decisions with a clear plan in mind, don’t include every thing at once it will only waste context and confuse the llm.