30 Prompts for Cursor: Master AI-Assisted Development in Your IDE

Introduction

Imagine a coding assistant that doesn't just autocomplete your variable names but understands your entire codebase, refactors complex functions, debugs your logic, and even writes tests for you. That’s Cursor—the AI-native IDE that’s reshaping how developers work. Unlike traditional IDEs with bolt-on AI plugins, Cursor integrates large language models (LLMs) directly into the editing experience, offering features like code generation, natural language commands, and context-aware chat.

But here’s the catch: Cursor’s power only shines when you know how to talk to it. The quality of AI output depends heavily on prompt engineering—crafting clear, specific, and structured instructions. This article presents a curated collection of 30 prompts organized into three levels: Basic (everyday productivity), Advanced (complex refactoring and debugging), and Expert (system design and optimization). Each prompt includes a concrete task, the exact prompt to use, and an example result. Whether you’re a seasoned Cursor user or just starting, these prompts will unlock the full potential of AI-assisted development.

Let’s dive in.

Basic Prompts: Everyday Productivity

These prompts are designed for common tasks like writing boilerplate code, fixing syntax errors, and understanding unfamiliar code. They require minimal context and return quick, actionable results.

Task 1: Generate a REST API endpoint

Prompt:

Create a Flask route for /api/users that returns a JSON list of users from a PostgreSQL database. Use SQLAlchemy ORM. Include error handling.

Example Result:

from flask import Blueprint, jsonify
from models import User
from extensions import db

users_bp = Blueprint('users', __name__)

@users_bp.route('/api/users', methods=['GET'])
def get_users():
    try:
        users = User.query.all()
        return jsonify([user.to_dict() for user in users]), 200
    except Exception as e:
        return jsonify({'error': str(e)}), 500

Task 2: Explain a complex regex

Prompt:

Explain this regex: ^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$

Example Result:
The regex enforces strong password requirements:
- ^ and $ anchor the match to the entire string.
- (?=.*[A-Z]) — at least one uppercase letter.
- (?=.*[a-z]) — at least one lowercase letter.
- (?=.*\d) — at least one digit.
- (?=.*[@$!%*?&]) — at least one special character.
- [A-Za-z\d@$!%*?&]{8,} — password must be at least 8 characters long, containing only allowed characters.

Task 3: Add comments to a function

Prompt:

Add inline comments and a docstring to the following JavaScript function:

function calc(a, b, op) {
  if (op === '+') return a + b;
  if (op === '-') return a - b;
  return a * b;
}

Example Result:

/**
 * Performs basic arithmetic operations.
 * @param {number} a - First operand.
 * @param {number} b - Second operand.
 * @param {string} op - Operator: '+', '-', or '*'.
 * @returns {number} Result of the operation.
 */
function calc(a, b, op) {
  if (op === '+') return a + b;  // Addition
  if (op === '-') return a - b;  // Subtraction
  return a * b;                  // Default to multiplication
}

Task 4: Convert a Python script to TypeScript

Prompt:

Convert this Python function to TypeScript with proper types:

def fetch_user(user_id: int) -> dict:
    import requests
    response = requests.get(f'https://api.example.com/users/{user_id}')
    return response.json()

Example Result:

import axios from 'axios';

interface User {
  id: number;
  name: string;
  email: string;
}

async function fetchUser(userId: number): Promise<User> {
  const response = await axios.get<User>(`https://api.example.com/users/${userId}`);
  return response.data;
}

Task 5: Write unit tests for a utility function

Prompt:

Write Jest tests for this function:

export function isPalindrome(str: string): boolean {
  const cleaned = str.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
  return cleaned === cleaned.split('').reverse().join('');
}

Example Result:

import { isPalindrome } from './utils';

describe('isPalindrome', () => {
  it('returns true for simple palindromes', () => {
    expect(isPalindrome('racecar')).toBe(true);
  });
  it('ignores case and non-alphanumeric characters', () => {
    expect(isPalindrome('A man, a plan, a canal: Panama')).toBe(true);
  });
  it('returns false for non-palindromes', () => {
    expect(isPalindrome('hello')).toBe(false);
  });
  it('handles empty string', () => {
    expect(isPalindrome('')).toBe(true);
  });
});

Advanced Prompts: Refactoring and Debugging

These prompts require more context and produce multi-step transformations, such as refactoring large functions, debugging complex logic, and optimizing performance.

Task 6: Split a monolithic function into smaller functions

Prompt:

Refactor this function into smaller, single-responsibility functions. Add type hints and a main orchestrator.

async def process_order(order_id: int):
    order = await db.fetch_one(...)
    if not order:
        raise ValueError('Order not found')
    if order.status != 'pending':
        raise ValueError('Order already processed')
    await payment_service.charge(order.total, order.user_id)
    await db.update(...)
    await email_service.send_confirmation(order.user_email)

Example Result:

async def validate_order(order_id: int) -> dict:
    order = await db.fetch_one(...)
    if not order:
        raise ValueError('Order not found')
    if order.status != 'pending':
        raise ValueError('Order already processed')
    return order

async def charge_customer(order: dict) -> bool:
    return await payment_service.charge(order.total, order.user_id)

async def update_order_status(order_id: int, status: str) -> None:
    await db.update(...)

async def send_confirmation(order: dict) -> None:
    await email_service.send_confirmation(order.user_email)

async def process_order(order_id: int) -> None:
    order = await validate_order(order_id)
    await charge_customer(order)
    await update_order_status(order_id, 'completed')
    await send_confirmation(order)

Task 7: Debug a memory leak

Prompt:

I have a Python script that reads large CSV files and holds data in a list. Memory usage grows unbounded. Suggest fixes with code examples.

Example Result:
The issue is holding all rows in memory. Use a generator to process rows one by one:

import csv

def read_csv_generator(file_path):
    with open(file_path, 'r') as f:
        reader = csv.DictReader(f)
        for row in reader:
            yield row

# Usage:
for row in read_csv_generator('large.csv'):
    process(row)  # No list accumulation

If you need to accumulate some data, use a memory-efficient structure like SQLite or a streaming approach.

Task 8: Optimize a slow SQL query

Prompt:

Optimize this PostgreSQL query. It takes 30 seconds on 10 million rows:

SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE signup_date > '2025-01-01') AND status = 'active';

Example Result:
The subquery can be slow. Use an explicit JOIN and ensure proper indexes:

CREATE INDEX idx_orders_user_id_status ON orders (user_id, status);
CREATE INDEX idx_users_signup_date ON users (signup_date);

SELECT orders.*
FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.signup_date > '2025-01-01' AND orders.status = 'active';

Consider also using EXISTS for better performance in some cases.

Task 9: Rewrite callback-based code to async/await

Prompt:

Convert this Node.js callback code to async/await with try/catch:

function getUser(id, cb) {
  db.find(id, (err, user) => {
    if (err) return cb(err);
    cb(null, user);
  });
}

Example Result:

import { promisify } from 'util';

const findAsync = promisify(db.find).bind(db);

async function getUser(id: number): Promise<User> {
  try {
    const user = await findAsync(id);
    return user;
  } catch (error) {
    throw new Error(`Failed to fetch user: ${error.message}`);
  }
}

Task 10: Add logging and monitoring

Prompt:

Add structured logging (using the 'logging' module) to this FastAPI endpoint. Include request ID and execution time.

Example Result:

import logging
import time
from contextvars import ContextVar
from uuid import uuid4

request_id_var: ContextVar[str] = ContextVar('request_id', default='')

logger = logging.getLogger(__name__)

@app.get('/api/items/{item_id}')
async def get_item(item_id: int):
    request_id = str(uuid4())
    request_id_var.set(request_id)
    start = time.time()

    logger.info('Request started', extra={'request_id': request_id, 'item_id': item_id})
    try:
        item = await db.fetch_item(item_id)
        elapsed = time.time() - start
        logger.info('Request completed', extra={'request_id': request_id, 'elapsed': elapsed})
        return item
    except Exception as e:
        elapsed = time.time() - start
        logger.error('Request failed', extra={'request_id': request_id, 'elapsed': elapsed, 'error': str(e)})
        raise

Expert Prompts: System Design and Optimization

These prompts are for senior developers and architects. They involve designing entire systems, optimizing for scale, and making architectural decisions.

Task 11: Design a rate limiter

Prompt:

Design a rate limiter for a public API. Support both per-user and per-IP limits. Use Redis. Provide code examples in Python.

Example Result:

import redis
import time

r = redis.Redis()

class RateLimiter:
    def __init__(self, max_requests: int, window_seconds: int):
        self.max_requests = max_requests
        self.window = window_seconds

    def is_allowed(self, key: str) -> bool:
        current = int(time.time())
        window_start = current - self.window

        # Remove old entries
        r.zremrangebyscore(key, 0, window_start)

        # Count requests in current window
        count = r.zcard(key)

        if count < self.max_requests:
            r.zadd(key, {current: current})
            r.expire(key, self.window)
            return True
        return False

# Usage
limiter = RateLimiter(max_requests=100, window_seconds=60)
if limiter.is_allowed(f'user:{user_id}'):
    # process request
    pass

Task 12: Implement a microservice communication pattern

Prompt:

Design an event-driven microservice architecture using RabbitMQ. Show a producer (order service) and consumer (inventory service) in Python with pika.

Example Result:
Producer (order_service.py):

import pika
import json

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='orders', exchange_type='topic')

order = {'order_id': 123, 'product_id': 456, 'quantity': 2}
channel.basic_publish(exchange='orders', routing_key='order.created', body=json.dumps(order))
print('Order event published')
connection.close()

Consumer (inventory_service.py):

import pika
import json

def callback(ch, method, properties, body):
    order = json.loads(body)
    print(f'Reserving inventory for order {order["order_id"]}')
    # Update inventory logic
    ch.basic_ack(delivery_tag=method.delivery_tag)

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='orders', exchange_type='topic')
queue = channel.queue_declare(queue='inventory_queue', durable=True)
channel.queue_bind(exchange='orders', queue='inventory_queue', routing_key='order.created')
channel.basic_consume(queue='inventory_queue', on_message_callback=callback)
channel.start_consuming()

Task 13: Write a complex data pipeline

Prompt:

Create an ETL pipeline in Python that extracts data from a PostgreSQL database, transforms it (aggregates sales by region), and loads into a Redshift table. Use pandas and SQLAlchemy.

Example Result:

import pandas as pd
from sqlalchemy import create_engine

# Extract
pg_engine = create_engine('postgresql://user:pass@localhost/sales')
query = 'SELECT region, amount, date FROM orders WHERE date >= CURRENT_DATE - INTERVAL \'1 day\''
df = pd.read_sql(query, pg_engine)

# Transform
df['date'] = pd.to_datetime(df['date'])
df_agg = df.groupby(['region', df['date'].dt.date]).agg(total_sales=('amount', 'sum')).reset_index()

# Load
rs_engine = create_engine('redshift://user:pass@redshift-cluster.amazonaws.com:5439/dwh')
df_agg.to_sql('daily_sales_by_region', rs_engine, if_exists='append', index=False)

Task 14: Refactor a monolith into a modular monolith

Prompt:

I have a Django monolith with models, views, and services all in one app. Propose a modular structure with bounded contexts. Provide folder structure and code examples.

Example Result:

project/
├── orders/
│   ├── models.py
│   ├── services.py
│   ├── views.py
│   └── urls.py
├── inventory/
│   ├── models.py
│   ├── services.py
│   ├── views.py
│   └── urls.py
├── users/
│   ├── models.py
│   ├── services.py
│   ├── views.py
│   └── urls.py
└── common/
    ├── base_models.py
    └── utils.py

Each module has its own models and business logic, communicating via events or service calls. For example, orders/services.py calls inventory/services.py via a shared interface:

# orders/services.py
from inventory.services import reserve_inventory

def place_order(order_data):
    reserve_inventory(order_data['product_id'], order_data['quantity'])
    # ... create order

Task 15: Write a CI/CD pipeline configuration

Prompt:

Write a GitHub Actions workflow for a Python FastAPI project. Include linting, testing, building a Docker image, and deploying to AWS ECS.

Example Result:

name: CI/CD Pipeline

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.12'
      - name: Install dependencies
        run: pip install -r requirements.txt
      - name: Lint
        run: flake8 .
      - name: Test
        run: pytest

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      - name: Build and push Docker image
        run: |
          docker build -t myrepo/myapp:latest .
          docker push myrepo/myapp:latest
      - name: Deploy to ECS
        run: |
          aws ecs update-service --cluster my-cluster --service my-service --force-new-deployment

Practical Tips for Prompting Cursor

  1. Be specific: Instead of “fix this code”, say “fix the off-by-one error in the loop on line 15”.
  2. Provide context: Include error messages, expected output, and constraints.
  3. Use system messages: In Cursor’s chat, you can set a system message like “You are a senior Python developer specializing in Django. Always follow PEP 8.”
  4. Iterate: Don’t expect perfect results on the first try. Refine your prompt based on the output.
  5. Combine modes: Use autocomplete for small code snippets, chat for complex explanations, and command mode for file-wide refactoring.

Conclusion

Cursor is more than an IDE—it’s an AI pair programmer. But like any tool, its value depends on how you use it. By mastering prompt engineering, you can transform Cursor from a simple autocomplete engine into a full-fledged development partner that writes, debugs, refactors, and designs code at an expert level.

The 30 prompts in this article cover the spectrum from basic daily tasks to complex system design. Use them as templates, adapt them to your projects, and experiment with different phrasings. The more you practice, the more intuitive it becomes. Start with a simple task today—maybe generate a REST endpoint or add tests—and watch your productivity soar.

Happy coding with Cursor!

← All posts

Comments