Mastering Long Codebases with Cursor, Gemini, and Claude: A Practical Guide

This guide outlines my approach to building software projects using Cursor IDE, leveraging Gemini (gemini-exp-1206, gemini-2.0-flash-exp) and Claude (3.5 sonnet and 3 opus) for effective development and maintaining code integrity.

1. Project Setup: Laying the Foundation for AI Collaboration

Think of your project as a well-organized workshop where you and your AI collaborators (Gemini and Claude) will build something amazing. The first step is to set up the workshop properly.

1.1. Define the Rules of Engagement with .cursorrules

Just like any workshop needs rules, your AI collaborators need guidelines. Create a .cursorrules file at the root of your project. This file acts as a constitution, defining how the AI should interact with your code.

Why: This ensures everyone (you and the AI) is on the same page regarding priorities, coding standards, and how to approach tasks.

Example .cursorrules:

{
    "rules": {
        "context_initialization": {
            "description": "Starting point for each interaction",
            "steps": [
                "ALWAYS read `.notes/project_overview.md` and `.notes/task_list.md`"
            ]
        },
        "operational_protocol": {
            "description": "How to approach tasks",
            "before_action": [
                "Create a MECE task breakdown"
            ],
            "code_changes": [
                "Read relevant code sections before editing",
                "Preserve existing functionality",
                "Maintain type safety"
            ]
        },
        "safety_requirements": [
            "NEVER break type safety",
            "ALWAYS maintain proper error handling",
            "ALWAYS document new code"
        ],
        "priorities": [
            {
                "source": ".notes/",
                "weight": 1.0
            }
        ],
        "modes": {
            "base": {
                "description": "For routine tasks"
            },
            "enhanced": {
                "description": "For complex problems"
            }
        },
        "project_directives": {
            "name": "my_project",
            "ai_first": true
        }
    }
}

1.2. Control File Visibility with .cursorignore

Use .cursorignore to tell your AI helpers what to ignore, similar to how you’d use a .gitignore for version control.

Why: This keeps the AI focused on the essential parts of your project, reducing noise and improving efficiency.

Example .cursorignore:

/node_modules
/build
/temp
.DS_Store

1.3. Establish a Central Hub with .notes

Every project needs a central hub for information. Create a .notes directory to store all project-related documentation, meeting notes, architectural diagrams, and AI interaction logs. Think of it as your project’s “brain” or “knowledge base.”

Why: This ensures that you and your AI collaborators have a shared understanding of the project’s goals, status, and history.

Key Files in .notes:

  • project_overview.md: A high-level description of your project, its goals, and architecture.
  • task_list.md: A detailed list of tasks, their status (e.g., “To Do,” “In Progress,” “Complete”), priorities, and any relevant notes.
  • directory_structure.md: An automatically updated overview of your project’s directory structure. This helps the AI understand where different code components live.
  • meeting_notes.md: A log of your interactions with the AI, including questions asked, answers received, and decisions made.

2. Managing .notes and Shared Context

Imagine you’re working with a team of people. To collaborate effectively, you need to ensure everyone has a shared understanding of the project like scrum/kanban/project plan. This is where using markdown docs as shared notepads comes in.

2.1. Populate project_overview.md

This document is like your project’s “elevator pitch.” It should provide a concise overview of what your project is, its goals, its high-level architecture, and (optionally, but highly recommended) some sample user journeys.

Example:

# Project Overview

## Goal

Build a web application that allows users to create and manage to-do lists.

## Architecture

-   **Frontend:** React application using TypeScript.
-   **Backend:** Serverless API using Node.js and a cloud database.
-   **State Management:** Using a custom state management solution based on React hooks.

## Key Features

-   User authentication
-   Create, edit, and delete to-do lists
-   Mark tasks as complete
-   Real-time synchronization

2.2. Create task_list.md

This file is your project’s “to-do list.” It should track all tasks, their status, priorities, and any relevant notes.

Example:

# Task List

## High Priority

-   [ ] Implement user authentication flow. (**Status:** In Progress, **Assigned To:** Gemini, **Notes:** Currently working on the login component.)
-   [ ] Design database schema. (**Status:** To Do, **Assigned To:** Claude, **Notes:** Need to consider scalability.)

## Medium Priority

-   [ ] Create basic UI for to-do list creation. (**Status:** To Do, **Assigned To:** Gemini, **Notes:** Waiting for authentication to be completed.)

## Low Priority

-   [ ] Add support for task categorization. (**Status:** To Do, **Assigned To:** None, **Notes:** Can be implemented later.)

## Completed

-   [x] Set up project structure.
-   [x] Create basic React components for header and footer.

2.3. Generate directory_structure.md

This file provides a map of your project’s layout. You can create it manually or use a script to generate it automatically.

Example (Manual):

# Directory Structure

-   **components/**: Reusable UI components (e.g., Button, Input, List)
-   **hooks/**: Custom React hooks (e.g., useAuth, useData)
-   **lib/**: Utility functions and API clients
-   **pages/**: Top-level application pages (e.g., Home, Login, Register)
-   **styles/**: Global styles and theme definitions

Example Script (PowerShell):

# Save as update_directory.ps1
$projectRoot = "."
$outputFile = "./.notes/directory_structure.md"

# Generate directory listing
function Get-FormattedDirectory {
    param (
        [string]$path,
        [int]$indent = 0
    )

    $indentString = "    " * $indent
    $content = ""

    foreach ($item in Get-ChildItem -Path $path -Force) {
        if ($item.PSIsContainer) {
            $content += "$indentString- **$($item.Name)/**`n"
            $content += Get-FormattedDirectory -path $item.FullName -indent ($indent + 1)
        } else {
            $content += "$indentString- $($item.Name)`n"
        }
    }
    return $content
}

# Generate content for markdown file
$markdownContent = @"
# Current Directory Structure

## Core Components

```
$(Get-FormattedDirectory -path $projectRoot)
```
"@

# Output to file
$markdownContent | Out-File -FilePath $outputFile -Encoding UTF8

Write-Host "Directory structure updated in $($outputFile)"

3. Prompt Mastery and Focusing Conversations

Now that you setup a digital “workshop” with you, Claude, and Gemini all on the same page through the docs created above, it’s time to start working with Composer in Normal mode with Gemini. This is where the art of prompting comes in.

3.1. Why is Context Crucial?

  • Focus: Like a spotlight, context helps the AI focus on the relevant parts of your codebase, ignoring irrelevant details.
  • Accuracy: A shared understanding of the project’s goals, status, and architecture ensures responses are accurate and aligned with your intentions.
  • Consistency: You can help the AI maintain the architectural integrity of your project, preventing it from making changes that might break existing functionality or introduce inconsistencies.

3.2. Using @ to Focus the AI

The @ symbol is your primary tool for providing context to Gemini and Claude within Cursor. It’s like pointing to a specific document or code section during a conversation.

Examples:

  • @components/Button.tsx: “Hey Gemini, let’s focus on this specific component.”
  • @.notes/task_list.md: “Claude, check out the current task list and priorities.”
  • @.notes/project_overview.md: “Gemini, remember the overall goals and architecture we discussed?”

3.3. Ground AI Answers with Accuracy and Consistency

  • Be Specific: Ask direct, specific questions. Avoid vague or ambiguous language.

    • Instead of: “How can I improve this code?”
    • Try: “Gemini, how can I make the handleSubmit function in @components/LoginForm.tsx more efficient?”
  • Use MECE: MECE (Mutually Exclusive, Collectively Exhaustive) is a powerful problem-solving technique. Break down complex tasks into smaller, non-overlapping subtasks.

    • Example: "Claude, let’s break down the implementation of the user authentication flow using MECE:

      1. User Input: Handle username and password input.
      2. API Call: Send credentials to the authentication API.
      3. Response Handling: Process the API response (success or error).
      4. State Update: Update the application state based on the authentication result.

      What are your thoughts on this breakdown? Any suggestions?"

  • Iterate and Refine: Don’t expect perfect results on the first try. Engage in an iterative dialogue with the AI. Provide feedback on its suggestions, ask clarifying questions, and refine your prompts based on its responses.

    • Example: “Gemini, your suggestion for optimizing the handleSubmit function is good, but it doesn’t address the potential for race conditions. How can we modify it to handle that scenario?”
  • Ask “Why”: Encourage the AI to explain its reasoning. This helps you understand its thought process and identify potential misunderstandings.

    • Example: “Claude, why did you recommend using this particular state management approach instead of the one outlined in @.notes/project_overview.md?”
  • Explore Counterfactuals: Consider alternative approaches and discuss their pros and cons with the AI.

    • Example: “Gemini, what would be the downside of using a different API client library than the one currently used in @lib/api.ts?”
  • “What If” Scenarios: Challenge the AI with hypothetical situations to assess its understanding and problem-solving abilities.

    • Example: “Claude, what if the authentication API is temporarily unavailable? How should the application handle that scenario to provide a good user experience?”
  • Leverage “Remember When” Prompts: Refer back to previous interactions or decisions to maintain continuity and build upon established knowledge.

    • Example: “Gemini, remember when we discussed the need for optimistic updates in the context of the to-do list creation? How can we apply that concept to the task editing functionality in @components/TaskItem.tsx?”

4. Advanced Tips: Taking Your AI Collaboration to the Next Level

  • Maintain a “Consciousness Stream”: Keep detailed logs of your interactions with Gemini and Claude in .notes/meeting_notes.md. Ask Gemini and Claude to keep these updated on a regular basis throughout your conversations.

  • Set up different modes: Utilize the different modes defined in your .cursorrules (e.g., “base” for routine tasks, “enhanced” for more complex problems) to optimize the AI’s performance.

  • Don’t Be Afraid to Start Over: Sometimes, it’s more efficient to start a particular task or conversation from scratch than to try to fix a confused or misaligned AI.

5. Conclusion

By treating your AI collaborators like valuable human contributors, establishing clear rules of engagement, providing focused context, and prompting effectively, you can achieve significant success with large codebases.

I’ve used this approach for over 70 apps/projects in the last 6 months and have had several scenarios without a single hiccup. Remember to use AI to help AI help itself. It’s the magic of Cursor and having the IDE as an extension (ie. digital body) for the AI.

66 Likes

cool man ,would composer really read the files memtion at .cursorrules in every conversation ?

By the way ,in your .cursorrules example , the config format would more readable by AI?

3 Likes

Nice, this was me every day, trying to create context, doc, notes for the AI, but I’m surprised about your detailed structure, I will learn from this :3 Thank mate

1 Like

what a beautiful thing you shared. Thanks!

3 Likes

This was a great post, thank you. For some reason, I did not conclude this on my own. I have added my own .cursorrules to an active project and it has made a significant difference. Thanks again :slight_smile:

4 Likes

You can also use this project it also generates .cursorrules

6 Likes

this is lovely! thank you for sharing

1 Like

which one are you talking about?

I actually started this GitHub - garotm/awesome-cursorrules-dynamic: 📄 A "Phase 2" approach to the list of awesome .cursorrules files if anyone else is interested


1 Like

Regarding this, it’s good to ask super general questions after you finished asking the specific ones. For example, you and claud made an amazing login screen for the user. Once you’re confident everything’s good and you’re out of questions and problems, then you ask “How can I improve this code.” The results are amazing!

2 Likes

Maybe it doesnt matter, but Android is misspelled.

1 Like

what do you use

@wheattoast11 what is the advantage of using this approach (multiple markdown files) compared to using the official notebooks provided? See documentation on notepads here: Features / Beta / Notepads – Cursor

  1. notebooks are not in git, so no history or version control.
  2. Notebooks are not editable by the cursor itself. So, after a composer session, I can say, “We made some decisions in this session regarding our data structure. Please update the SQL portion of the project overview.md,” and it usually does a good job of that.
  3. the advantage of the notebooks like including them with @ mentions works just as well for a couple of files at the root of the project @tech-stack.md, or @todo-items.md etc
  4. I keep forgetting that notebooks are there, too hidden in my normal workflow
2 Likes

Using this project of mine it also automatically generates .cursorrules
https://github.com/RenjiYuusei/CursorFocus

Another excellent approach is to consider everything as “production” and work on your projects as such. You can share the terminal capture with the AI to validate your work, often leading to suggestions for improvements or next steps automatically.

Wouldn’t be interesting to generalize this approach and creating folder/file structure and share it on github, ready to be used and adapted?

1 Like

Why not develop a project for it instead?

:smiling_face: it is so comforting to see that everything is .dotfiles all the way down.

let us know when it’s ready :rocket: