7 min read

How I Optimized My Development Workflow with Cursor Pro, ChatGPT and GitHub Desktop

For the past few decades, I’ve worked as a Product Lead, primarily focused on defining what teams should build and why, rather than doing the coding myself. With the advent of LLM chat tools and coding assistants, I’ve been coding more frequently and tackling more ambitious side projects than I previously would have considered.

Initially, everything went smoothly—I began with smaller projects and saw quick wins using tools like ChatGPT and Claude. But as I took on more complex challenges, I started hitting roadblocks. After hitting snafus and abandoning some projects prematurely, I realized I needed to revisit my approach.

Stepping back I concluded that my main problem, outside of being a better developer, was inefficient workflows. I had grown far too reliant on copying and pasting between different windows, and I wasn’t more regularly using version control or creating branches. This meant that when things went awry, I had no simple way to backtrack or return to a stable state. I ended up abandoning projects when they went off course and felt like they required too much effort to get back on track.

After a conversation with a friend (thanks, Carl!) who shared his workflow, I decided to step back and reassess my own approach. By incorporating a few best practices, such as regularly versioning my code and adopting tools like GitHub Desktop and Cursor Pro, I’ve already noticed significant improvements. While it’s still early days, this new structure is helping me manage more complex projects with greater ease, and I feel much more confident about taking on bigger challenges without burning out. In this post, I’ll walk through the various changes I’ve adopted over the past week.

Streamlining Development with Branches and Frequent Small Commits in GitHub

One of the first changes I implemented was to stop working directly on the main branch of my projects. Instead, I now create a dev branch where I commit more frequently, keeping changes smaller and more manageable. For specific features, I create dedicated branches, merging into the main branch only when I’m confident everything is in good shape. This approach helps me preserve my progress when things get messy. If I don’t want to merge all the changes from a branch, I squash and merge only the relevant commits.

Switching to using the GitHub Desktop client has also been helpful. It provides me with a much clearer overview of the changes I’m about to commit compared to the built-in source control tools in Cursor or my terminal. While the IDE’s tools are fine for quick commits or branch switching, for larger changes, I prefer the enhanced visibility that GitHub Desktop offers.

Development Planning and Spec Creation with ChatGPT

For more complex tasks, I now start by mapping them out in ChatGPT before diving into coding. This approach ensures that I start coding with a clear sequence of steps and starting direction even if the plan changes. It also helps me offer more focused guidance to the coding assistant I'm using.

After outlining a plan, I either start working directly on the dev branch for smaller changes or, for larger tasks, I create one or more GitHub issues where I add my spec and set up a dedicated branch. This approach lets me switch tasks or step away without losing track of important details. Keeping tasks organized and tied to specific branches makes it much easier to pick up where I left off after a break.

I have found creating specs using o1-preview is particularly effective when engaging in refactoring complex sections of code. When I aim to enhance or expand an MVP with new features and capabilities, having a detailed, step-by-step plan not only streamlines the refactor but also uncovers insights I hadn’t anticipated. Following those steps and committing incremental changes leads to noticeably improved outcomes.

Transitioning from Web Chat Tools to Cursor for Coding

The hardest adjustment for me was shifting to doing all of my coding in an IDE, rather than relying on regularly copy-pasting between the IDE and web-based chat tools. Fortunately, a course on using Cursor by Mckay Wrigley made the transition quick and easy.

To ease into this new approach, I started using web-based chat assistants for strategic planning—figuring out how to approach a problem—and relying on Cursor’s coding assistant for tactical execution. This separation of tasks allows me to use each tool in a more focused manner. While it’s not strictly necessary to work this way, it has been a helpful way for me to transition to spending more of my time in Cursor.

The end result is a more efficient workflow where I can develop a clear, opinionated approach outside the IDE and use that output to guide how I work in Cursor. In turn, Cursor enables me to write higher quality code in an environment that tracks both code changes and chat history that contributed to development.

Why Cursor is a Game Changer for Me

Implementing best practices like using Git, tracking issues, and creating specs has been valuable, but adopting Cursor has been the real game changer for me. Although I enjoyed using Copilot in VS Code, I still found myself regularly leaving the IDE for additional coding assistance. Cursor, on the other hand, provides a range of features that enable me to complete my work without ever needing to leave the editor.

Cursor’s built-in chat assistant supports multiple models, allowing me to switch between the best-suited ones for different tasks. I can also integrate third-party API keys for added flexibility. By indexing my entire codebase, Cursor makes it much easier to integrate new features or libraries and apply suggested changes efficiently. Additionally, with the ability to @mention files, folders, web resources, or even my entire codebase, I can quickly reference the latest documentation for APIs, SDKs, or languages. Cursor is bundled with shortcuts to success.

Key Features

Cursor offers several features that significantly enhance the coding experience.

Codebase Indexing

Codebase indexing generates embeddings for each file in my codebase, improving the accuracy of code suggestions. The index stays in sync with my latest changes, ensuring responses are always up-to-date and relevant.

Long-Context Chat

Codebase indexing shines when combined with long-context chat. Models with support for larger context windows allow me to include entire folders in conversations, enabling Cursor to offer comprehensive feedback based on broader sections of my codebase.

@Mentions and Chat History

What convinced me to switch to Cursor was the ability to reference specific files, folders, and code directly in chats. By @mentioning them within the IDE, I stay in the flow without unnecessary interruptions. No more copying and pasting between windows. Plus, the chat history is stored in the IDE, providing a central place to track past discussions and changes.

Adding Docs

One major advantage of using AI coding assistants is no longer needing to search through third-party docs when integrating new tools. Cursor has many third-party libraries indexed, accessible via mentioning them in chat with @Docs. For documentation that hasn’t been indexed yet, I can easily add it by pasting a URL to the support materials, and Cursor will index it for use in prompts.

Apply Feature

The apply feature is another favorite of mine, allowing me to quickly integrate code suggestions from the chat. After applying, I can review the diffs and choose to accept or reject the changes.

Occasionally, I notice that this feature suggests applying the correct changes to the wrong file. Thankfully, it’s easy to spot when this happens, and I can either manually fix it by copying and pasting the code into the right file or ask the assistant to correct it.

Numerous features in Cursor require hands-on use to get a proper feel for them. Sometimes this is due to their non-deterministic behavior, while other times it's because they are a bit buggy or just slow. For example, I initially thought the apply feature wasn’t working because it takes a few moments to generate changes in local files, but I was simply being impatient with it. I’ve learned to give certain features in Cursor more than one try to work correctly.

Cursor Tab

Cursor Tab is a powerful autocomplete tool that goes beyond simple suggestions. It predicts entire edits based on your recent changes and codebase knowledge, suggesting edits across multiple lines and even fixing your mistakes.

AI Rules

A handy feature is the ability to add custom AI rules, tailoring the assistant’s responses to fit my specific workflow. This ensures it focuses on the most helpful actions and avoids less useful suggestions. Apparently, there's a third party directory of suggestions but I currently use this one.

Markdown Files

Since large language models (LLMs) are trained on extensive markdown (.MD) content and have well-structured knowledge, MD files work great with assistants in Cursor to provide actionable, step-by-step instructions. Coding chat assistants can generate relevant context that can be easily acted upon. For example, whenever you save changes to a note in Cursor, you can reference them in Chat. Here's how:

  • Create a markdown file in cursor reference it in the chat.
  • By mentioning the markdown file in the chat assistant it can use that as context and even act upon it.

For instance, Imran realized you could make a markdown file that requests a visual component, uses the assistant to generate a suitable prompt, sends that prompt to v0.dev, and returns a link to view the visual component. If that's unclear what an example of it in action here.

This method also works for managing projects in Composer and directing chats to update project status once things are implemented. You can watch how markdown works in Composer.

Composer

Composer is a feature that lets you use natural language prompts to create new projects from scratch, enhance existing ones, or generate code snippets. With Composer Projects, it takes the functionality even further, offering a huge time-saving advantage when starting a project. You can see Composer in action here.

Final Thoughts

Although I still have plenty of room to grow as a developer, the changes I’ve adopted this past week have already improved my productivity. Compared to my previous workflow, taking on ambitious projects now feels both simpler and more enjoyable, and I believe it will enable me to see more projects through to completion.