- SOTA Embedding Retrieval: Gemini + pgvector for Production Chat
- A Review of Agentic Design Patterns
- Model Context Protocol (MCP) and MCP Servers in LLM Agent Systems
- Building AI Agents for Automated Multi-Format Content: From News to Podcasts
- ›Rediscovering Cursor
- GraphRAG > Traditional Vector RAG
- Cultural Bias in LLMs
- Mapping out the AI Landscape with Topic Modelling
- Sustainable Cloud Computing: Carbon-Aware AI
- Defensive Technology for the Next Decade of AI
- Situational Awareness: The Decade Ahead
- Mechanistic Interpretability: A Survey
- Why I Left Ubuntu
- Multi-Agent Collaboration
- Embeddings and Vector Databases: Enhancing Retrieval Systems
- Building an Automated Newsletter-to-Summary Pipeline with OpenAI: Zapier AI Actions vs AWS SES & Lambda
- Local AI Image Generation
- MLOps: Deploying a Distributed Ray Python Server with Kubernetes, EKS & KubeRay
- Making the Switch to Linux for Development: A Developer's Experience
- Scaling Options Pricing with Ray
- The Async Worker Pool
- Browser Fingerprinting: Introducing My First NPM Package
- Reading Data from @socket.io/redis-emitter without Using a Socket.io Client
- Socket.io Middleware for Redux Store Integration
- Sharing TypeScript Code Between Microservices: A Guide Using Git Submodules
- Efficient Dataset Storage: Beyond CSVs
- Embracing Next.js 13: Why I switched from Plain React
- Deploy & Scale Socket.io Containers in ECS with Elasticache
- Implementing TOTP Authentication in Python using PyOTP
- Simplifying Lambda Layer ARNs and Creating Custom Layers in AWS
- TimeScaleDB Deployment: Docker Containers and EC2 Setup
- How to SSH into an EC2 Instance Using PuTTY
When Cursor first came out, I gave it a try - but it didn't stick. I found myself going back to VSCode and PyCharm. Recently, though, the noise on X convinced me to try Cursor out one more time, and I'm glad I did because something just clicked.
Now, I'm loving coding with Cursor, and I realize the issue the first time around wasn't the AI itself - it was how I was working with it. Initially, I complained that the Composer changed too much of my code, and I preferred individually reviewing each edit, ChatGPT-style, before deciding what to include. I wanted to actively incorporate changes rather than passively skimming them.
In retrospect, the very power Cursor offers - making large-scale, direct code edits - was what frustrated me. It's like giving an over-eager intern developer complete freedom without proper guardrails. It was my mistake, not Cursor's.
This time, I built a structured workflow to guide Cursor in ways that boost productivity without going rogue.
When to Use Cursor
- Best for experienced developers who are comfortable reviewing code
- Great as a speed-up tool, not a complete code generator
- Ideal for smaller, focused tasks like unit tests or refactoring
- Handy for exploring new languages when you already understand coding fundamentals
- Performs particularly well on certain frameworks like Flutter and Next.js
Key Features
- Autocomplete - Context-aware suggestions using your entire codebase. Hit
Tab
to accept. - AI Chat - Quick Q&A and code edits that apply changes directly to files.
- Composer - Generates or updates multiple files based on a single instruction. Very powerful but needs solid guardrails.
- Agents - Facilitates multi-file edits, terminal commands, and full project context. Can automate big tasks but error-prone if not configured correctly.
- File Tagging - Control exactly where AI should make changes using
@
syntax. .cursorrules
- Configuration file to define consistent coding, naming, and formatting rules.
Context is Everything
Cursor thrives on context. If you don't set up clear boundaries and good documentation, it will hallucinate. Think of it as a junior developer that you haven't properly onboarded. You must define a strong boundary of context around your project. The more you feed Cursor with well-structured docs, the better and more reliable its output becomes.
Effective Prompting
I used to spend a lot of time crafting in-depth prompts for ChatGPT, explaining code bases, constraints, and patterns. When it came to Cursor, I took the fact that it had access to code context for granted, and I started using single-line instructions like "fix this code" - assuming it had enough context just by reading my files.
That's a recipe for frustration. If you don't offer the same level of detail you'd give a human teammate, Cursor might "improve" code in ways that break subtle but critical patterns.
Good prompting practices:
- Discuss requirements - Spell out what you need, including acceptance criteria and constraints
- Provide context - Include relevant code snippets, hidden dependencies, and usage patterns
- Tag documentation - Use
@
to reference docs in the Composer - Review changes incrementally - Don't blindly accept changes; keep commits small and reviewable
- Explain patterns and constraints - Mention custom loggers, design patterns, or architectural decisions
- Avoid one-liner instructions for complex tasks
Practical Usage Tips
- Use LLMs to explain code - Great for learning and documentation. "Explain like I'm a beginner" reveals hidden logic or patterns.
- Add comments to your code - Improves readability and helps AI or teammates understand your intent.
- Duplicate and modify existing functionality - Copy a working code snippet and have Cursor adapt it. This gives Cursor relevant context and patterns of how you like to code.
- Debugging workflow - For each update, open a new Composer, attach files with issues, and paste the errors. Review the diff before applying changes.
- Use Git religiously - Always have your code under version control. Commit frequently so you can revert if something breaks.
- Focus changes with file tagging - Use
@
in the composer window to pinpoint where changes should occur. Avoid too many large-scale edits at once. - Don't rely on Cursor for architecture - It can propose ideas, but architectural decisions need human oversight, especially for database schema design.
- Consult other AI if stuck - Sometimes GPT-o1 or Claude can see solutions Cursor misses. Provide errors and context for the best results.
- Keep generations small and focused - Big requests lead to big confusion. Think incremental.
- Tab completion is underrated - For experienced developers, Cursor's line-by-line suggestions are often more valuable than Chat.
Establishing a Workflow
Start with problem statement and requirements - Achieve clear alignment before any code is written. This prevents Cursor from making assumptions or going off track.
- Brain dump first - Use Claude or another model to turn raw ideas into structured text
- Discuss the problem space - Clarify the issue and define acceptance criteria
- Document key constraints - Outline anything that might trip up the AI (legacy code, unique design patterns)
- Aim for shared understanding - Ensure everyone (including Cursor) knows the end goals
Create design documentation - Build a roadmap that both you and Cursor understand and can reference.
- Refine the PRD - GPT-4 can help with detailed formatting. This becomes your North Star
- Use standard templates - System architecture overview, component interactions, data flow diagrams, API specs, DB schema
- Review and iterate - Ask Cursor to validate technical approaches and document constraints
Leverage existing code templates - Start with boilerplate like Next.js, FastAPI, Auth, DB, payments. Build on what works to save time using proven patterns.
Research packages and documentation - Add official docs to Cursor (Next.js, Supabase, etc.). Models often have outdated info, so explicitly referencing docs helps accuracy. Use @
to tag relevant docs for context.
You can run brew install tree
to get a tree view of your project. For a clean overview, use:
tree -L 2 -I 'node_modules|dist|build|coverage|.git'
Keep a docs/instructions.md
file with code examples, usage patterns, and file structures. Update this as you develop the project.
Cursor Rules and Configuration
Cursor Directory provides tech-specific prompts and rules. Copy the relevant .cursorrules
file to your project root. The instructions in this file are included for features like Cursor Chat and Ctrl/⌘ K
. The more specific your rules, the better Cursor's output becomes.
Implementation phases:
- Define clear scope - Break tasks into manageable chunks aligned with your design doc
- Reference documentation - Keep returning to documented constraints and acceptance criteria
- Make small, focused changes - Reduces risk and makes reviews easier
Continuous testing approach:
- Mixed testing strategy - Combine automated tests (unit/integration) with manual validation
- Document test cases - Ensure everything ties back to requirements
- Validate against requirements - If tests fail, dig deeper rather than relying on Cursor's guesses
Debugging with Cursor
When stuck on a bug, tell Cursor to add debug logs. It will insert systematic logging, track state changes, and suggest next steps. Then paste the new logs or errors back into Cursor to improve its context.
Best Practices
- Enforce a structured workflow - Any consistent process is better than none. Share your workflow with Cursor at the start of each session.
- Communicate before coding - Explicitly say "Do not write code yet. Let's discuss requirements." Use design docs as the conversation anchor.
- Maintain context continuity - Reference previous steps often. Update Cursor about manual edits so it doesn't become "blind" to new changes.
- Break down work - Limit the scope of each interaction. Focus on one component or phase at a time.
- Iterate and document - Don't push forward if confused; revisit requirements. Keep a record of decisions, especially on teams.
- Review code thoroughly - Even small snippets can introduce bugs. Use diff views and
git diff
extensively. - Keep generations small - Quick, incremental tasks prevent "spaghetti" code from creeping in.
- Stay open to other AI - If Cursor is stuck, GPT-4, Claude, or others might offer fresh perspectives. Share context and errors with them too.
Troubleshooting Common Issues
- Step back when things go wrong - If something goes off the rails, revert to your last working commit. Revisit your documentation or reset the conversation.
- Clarify context - Reattach relevant files or constraints. Double-check your design docs.
- Break down further - If a task is too big, subdivide it. Address one function or file at a time.
- Document and learn - Keep a log of failed attempts and resolutions. Update your
.cursorrules
or instructions accordingly.
Conclusion
Cursor can be a brilliant coding companion - if you treat it like a junior developer who needs direction, documentation, and incremental tasks. The key is structured workflow, clear requirements, and thorough code review. With the right guardrails, Cursor speeds up repetitive tasks, offers fresh insights, and helps you ship code faster than ever.
Overall:
- Good prompts and detailed context keep things on track
- Small, focused changes are easier to review
- Documentation matters - spend 80% of your time preparing and guiding, 20% coding