Pair programming with Cursor: A modern twist on collaborative coding

Imagine having a coding partner available 24/7—tireless, fast, and, while not flawless, always ready to help. With AI tools like Cursor, this vision of “pair programming” is now closer to reality, offering a fresh approach for solo developers and teams alike.

While AI development tools are becoming increasingly widespread, software developers often remain sceptical: Can an AI really help us write high-quality code? From my experience, using AI-powered tools reminds me of pair programming with a human. If you are reluctant to give them a go, I think approaching these tools from this perspective may help overcome this barrier, and ultimately will help you get the most out of them.

Listen to this post as an AI generated podcast

Why try AI pair programming?

Traditional pair programming has long been praised for its impact on code quality, error reduction, and team culture. Two developers work together at the same workstation, with one acting as the “driver” who writes code and the other as the “observer” who reviews each line. While this approach fosters learning and collaboration, it also requires two people on one task, which can be costly in terms of time and resources.

AI tools offer a practical, low-cost alternative to traditional pair programming. It provides instant feedback, useful suggestions, and a second set of “eyes” on your code—all without needing a human counterpart. While AI isn’t perfect, the back-and-forth interaction can feel surprisingly similar to a human pairing session, and it is beneficial to treat it this way.

How Cursor mimics traditional pair programming

The workflow will feel familiar to anyone who’s done pair programming before. Here’s how it typically unfolds:

  1. Starting the Task: You prompt Cursor to tackle a specific coding problem—perhaps generating a new function, designing a user interface, or drafting test cases.
  2. Iterative Refinement: Cursor generates an initial solution, which you review and adjust. You may request changes, fixes, or refactoring to refine its response.
  3. Moving Towards a Solution: Through this iterative feedback loop, Cursor refines the code until you reach a satisfactory result.

This conversational back-and-forth mimics the dynamic of traditional pair programming.  Approaching development tasks in this way encourages you to think about what you are really trying to achieve, rather than getting sucked into the details of the implementation at the outset.

Using cursor as your code reviewer

One powerful feature of Cursor is its ability to act as a reviewer, in a sense reversing this workflow. Rather than asking Cursor to write code from scratch, you can ask it to review code you’ve written, offering suggestions for improvement or optimization. This can be particularly helpful when tackling coding tasks you are less comfortable with, such as frontend development or infrastructure as code. The AI can often spot potential improvements you might overlook, augmenting your knowledge in these areas.

This reverse workflow can feel like having an unbiased reviewer who you can call on without worrying about taking up their time. Cursor may suggest alternative approaches, flag potential pitfalls, or highlight areas for optimisation if you ask.

An example: Building a search interface for a GraphRAG API

To illustrate how Cursor works in practice, let’s look at a recent project where I used it to build a simple front-end for a GraphRAG search API. The goal was to create an interface that could display the search responses, and pull out references to supporting documents. Here’s a step-by-step breakdown of how I approached the task:

  • Defining the Extraction Task: The tricky part of this task was writing a set of regular expressions to identify and extract references to documents embedded in the API’s text responses. I started by prompting Cursor to parse the response, giving it a concrete example of the data I wanted to isolate. For instance, in a response snippet like:

    “… as a result, Nvidia stocks are set to rise [Data: Reports (328); Entities (2542, 431); Relationships (372, 5709)]”

I explained that I needed to capture the document references—like “Reports (328)” or “Entities (2542, 431)” from the text.

  • Testing with Cursor’s Help: Having  generated an initial implementation, we worked together to write a set of tests. These tests were essential to validate that the references were extracted correctly, capturing different formats that might show up in the API’s responses.
  • Reviewing and Identifying Edge Cases: I reviewed the extraction results on a wider set of data to identify any edge cases that the initial implementation had missed. 
  • Refining the Solution: I added these edge cases as additional test cases, and asked Cursor to amend the code to account for the variations. With each iteration, it refined the parser incrementally to handle the new scenarios.
  • Removing duplication: As the test suite grew, Cursor was able to make suggestions to simplify the tests and remove duplicated code.
  • Finalising the Implementation: Once the solution was passing all tests, I committed the code. With the references reliably extracted, I moved on to the next step: displaying the referenced data in the frontend. “Cursor, please display the references as cards below the search result …”

You can see in this example the natural back-and-forth process with Cursor, similar to pair programming with a human partner. By iteratively refining the regular expressions, testing thoroughly, and addressing edge cases, my AI partner helped turn a tricky data extraction task into a manageable and enjoyable workflow.

Benefits of AI pair programming

AI pair programming offers many of the same benefits as a human partner in pair programming. For example:

  • Conversational Flow: Just as you’d ask a human partner for feedback, you interact through questions, prompts, and iterative requests, creating a “conversation” with your AI partner.
  • AI as the Driver: The AI partner  generates solutions based on your prompts, while you guide it toward the right path.
  • Expecting Mistakes: Like a human partner, the AI will make mistakes. Together, you can refine and improve the code, iterating to align its output with your vision.
  • Incremental Development: Working with AI encourages an incremental approach. You can request small sections of code, review each piece, and adjust as needed—fostering a step-by-step workflow that ensures quality.
  • Broader Perspective: With the AI handling the details, you’re free to step back and consider larger concerns, like UX, accessibility, and project-specific requirements.

Key Differences from Human Pair Programming

While developing with an AI tool shares many of the benefits of traditional pair programming, there are also significant differences:

  • Infinite Patience and Subservience: Unlike a human partner, the AI is endlessly patient and will take a backseat. You can ignore its suggestions without worrying about offence, conflict or having to take a long walk.
  • Freedom from Judgment: There’s no fear of embarrassment when asking a question that might seem “basic.” The assistance is provided without judgement, creating a comfortable environment to explore, learn, and iterate.
  • Knowledge Sharing and Mentorship: AI tools won’t spontaneously take you on a deep dive into the codebase, and lack the mentorship qualities that a human partner might offer. The explanations are often only as detailed as your requests.
  • Code Ownership and Accountability: When pairing with a human, ownership of the code is shared. With an AI partner, the responsibility for quality and accuracy ultimately remains with you. It’s important that these tools are used within a robust development process, with peer code review and testing in a CI pipeline.
  • Emotional Support and Empathy: A human partner can recognize signs of frustration, offer encouragement, or provide a sense of camaraderie that reduces burnout. An AI, whilst supportive in its own way, doesn’t provide emotional support 🙂.

Tips for effective AI pair programming with Cursor

Here are some best practices to help you get the most out of Cursor as your AI pair programming partner:

  • Use Precise Prompts: The clearer your requests, the more accurate Cursor’s responses. Providing relevant context from your codebase use the files and folders commands helps Cursor generate output aligned with your goals.
  • Handle Mistakes as Learning Moments: Cursor will make mistakes or miss the mark. Treat these errors as opportunities to refine your prompts and learn how best to interact with the AI.
  • Experiment with the Reverse Workflow: If you’re unsure about a piece of code, ask Cursor to review it. Its suggestions can help you catch issues early and improve overall code quality.
  • Know When Not to Use Cursor: Cursor may not be ideal for highly creative problem-solving or tasks that require complex decision-making. Use it as a support tool, but don’t rely on it for aspects that benefit from nuanced human judgement.

Final thoughts: Embracing AI as a pair programming partner

If you’re hesitant about using an AI-powered developer tool, thinking of it as a virtual pair programming partner may just be what you need to get started. Remember, these tools are in their infancy, and are continually improving—just like all good developers. Embrace the imperfections and cut them some slack; after all, you would not expect perfection of your partner, or yourself. Like it or not AI is here to stay and is a tool every professional developer needs to master.

AI assisted 3D printing

I’d like to share an anecdote which highlights why I find generative AI useful as a way of quickly being able to validate an idea or an approach.  I’ve recently been looking into replacing some small glass lampshades which I may have accidentally broken, and then broken some more whilst trying to glue them back together.  When they are not shattered and clumsily reassembled, this is what they look like:

Pristine lampshade, prior to impact with ground

Employing my usual strategy of scouring Ebay and Etsy for suitable replacements didn’t turn up anything useful.  I was able to determine that these glass lampshades were cut from a long tube of borosilicate glass, and based on this information I was able to find a supplier, who could provide the glass and even cut it to the required length – which would avoid me injuring myself, but would cost £100.

Having recently been exposed to a series of Tiktoks by Scott Hanselman expounding the value of owning a 3D printer, I wondered if it would be possible to 3D print some replacements.  I don’t have a 3D printer (yet), and I don’t know much about 3D printing, other than Scott thinks it is cool, and it does look pretty cool.  I thought it should be possible, but I didn’t really know how well it would turn out, and there were some non-functional requirements around thermal stability (i.e. is it going to melt) that I was interested in bottoming out.

I found a number of companies online who will print STL files in a range of materials, so now all I needed to do was generate the STL file.  A brief search on Reddit  suggested that for this type of model, a parametric design tool would be most appropriate – So I downloaded OpenScad and set to work.  I could have spent the next couple of hours learning the language and writing my scad file, but as I just wanted to see if it could be done as quickly as possible, I asked ChatGPT:

“Please can you help me create an openscad file for the following object: A hollow cylinder, with 20 circular cutouts around the inner edge. The cutouts should run the entire height of the cylinder.”

The response was encouraging:

// Parameters
$fn=100;                   // Setting high facet count for smooth curves
outer_radius = 40;         // Outer radius of the base circle
inner_radius = 35;         // Inner radius of the base circle
height = 100;              // Height of the extrusion
cutout_radius = 2;         // Radius of the circular cutouts
num_cutouts = 20;          // Number of cutouts

module cutout_pattern() {
    difference() {
        // Outer circle
        circle(r = outer_radius);
        
        // Inner circle to create hollow space
        circle(r = inner_radius);
        
        // Cutouts placed around the inner circle
        for (i = [0:num_cutouts-1]) {
            rotate([0, 0, i * 360 / num_cutouts]) {
                translate([inner_radius, 0, 0]) {
                    circle(r = cutout_radius);
                }
            }
        }
    }
}

// Extrude the 2D pattern to create a 3D object
linear_extrude(height = height, center = true) {
    cutout_pattern();
}

Tweaking the parameters so it was the correct size, and rendering it gave me:

Openscad rendering of AI designed lampshade

Not bad! I uploaded this to www.surfacescan.co.uk, and a couple of days later this arrived in the post:

3D printed lampshade in situ – it is the one on the right, I will probably replace them all

It cost about £3 to print, shipping was extra.  It looks pretty good in the lamp, and doesn’t melt with the 1.5W LED bulbs, so that’s my MVP! 

I did a fair amount of experimentation afterwards, trying my own designs, initially with ChatGPT, then increasingly more without it, as I became more confident in the tooling and the benefit of using Generative AI over coding it myself began to diminish.  I learnt why I should use $fa and $fs over globally setting $fn, I watched a series of introductory videos on Autodesk Fusion because I wanted to experiment interactively when modelling – all safe in the knowledge that I was spending my time on something I knew worked end to end. 

Honeycomb inside FTW, because Hexagons are the Bestigons

This is why Generative AI is so useful – I could definitely have written the Openscad file myself but not knowing how to was a barrier.  Being able to get from a textual description of a model, to a visualisation in a matter of minutes, to an actual object in days allowed me to validate the approach really quickly, without having to learn much at all. I think this is similar to product development – Generative AI may or may not be part of the solution, but it can certainly help you get there quicker.