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
- Be specific: Instead of “fix this code”, say “fix the off-by-one error in the loop on line 15”.
- Provide context: Include error messages, expected output, and constraints.
- 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.”
- Iterate: Don’t expect perfect results on the first try. Refine your prompt based on the output.
- 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!
Comments