Skip to main content

Prompt Engineering for Code

How you phrase a prompt directly affects the quality of the output. This page covers practical techniques for code-related tasks, plus the workspace instruction files that let you front-load context once for the whole repo.

Principles of Effective Prompts

  • Be specific and concrete. Include the language, framework, relevant types/interfaces, and surrounding context — not just "write me a function."
  • State constraints explicitly. "Don't change the public API" or "keep the existing test structure" are things the AI won't infer on its own.
  • Specify the output format. Do you want code only, code with explanation, code with tests, or a refactored diff? Say so.
  • Use few-shot examples. Paste a snippet of your codebase's style and the model will match it far better than it would from style descriptions alone.
  • Ask for reasoning on complex tasks. "Explain your approach before writing the code" produces more careful output and lets you catch a wrong direction early.

Prompt Patterns for Common Tasks

Generating New Code

Include: the language and framework, any relevant types or interfaces, what module or file this belongs in, and what you've already got. The richer the context, the less the model invents.

Example prompt structure:

Prompt: generating a new hook
I'm working in a React 18 + TypeScript project using React Query and Zod.

I need a custom hook called `useUserProfile` that:
- Fetches `/api/users/:id` using React Query
- Validates the response with this Zod schema: [paste schema]
- Returns `{ data, isLoading, error }` — typed strictly, no `any`

Don't add error boundary logic; we handle that at the page level.
Here's how another similar hook looks in this codebase: [paste example]

Refactoring

  • Include the full function or module to be changed.
  • State what to change and what to leave alone.
  • Specify invariants: "preserve the return type," "don't add new dependencies," "keep the existing tests passing."

Debugging

  • Include the full error message and stack trace.
  • Paste the relevant code.
  • Describe what you've already tried.
  • Ask for step-by-step reasoning before the fix: this catches cases where the model would jump to the wrong conclusion.

Code Review and Explanation

  • Ask for specific feedback dimensions: correctness, performance, security, readability.
  • "What edge cases is this missing?" is a more productive prompt than "review this."
  • "Explain this code as if I'm new to this codebase" works better than "what does this do?"

Workspace Instruction Files

note

These files give the AI persistent context about your project without pasting it into every prompt. Set them up once per repo, and every prompt benefits.

GitHub Copilot — .github/copilot-instructions.md

Copilot reads this file and incorporates it as system-level context for all Copilot Chat interactions in the workspace.

What to include: tech stack and versions, coding conventions, folder structure, preferred patterns, patterns to avoid.

.github/copilot-instructions.md
# Copilot Instructions

## Stack
- React 18, TypeScript 5, Vite
- React Query for data fetching, Zod for validation
- Tailwind CSS + shadcn/ui for styling

## Conventions
- All components use named exports (no default exports)
- Use React Query for all server state; avoid `useState` for async data
- Validate all API responses with Zod schemas before use
- Prefer `const` arrow functions for components

## Do Not
- Add `any` types — use `unknown` and narrow instead
- Install new dependencies without discussing in a PR
- Use `useEffect` for data fetching — use React Query instead

Reference: GitHub Copilot custom instructions

Cursor — .cursorrules

Cursor reads .cursorrules at the repo root as a standing system prompt for all Cursor Chat and Composer interactions.

.cursorrules
You are an expert TypeScript and React developer.

This project uses React 18, TypeScript 5, React Query, Zod, Tailwind CSS, and shadcn/ui.

Always:
- Use named exports for components
- Type everything strictly — no `any`
- Use React Query for server state
- Validate API responses with Zod

Never:
- Add new npm packages without noting it
- Use useEffect for data fetching
- Generate default exports for components

Cursor is also moving toward a .cursor/rules/ folder for modular, file-glob-scoped rules. See the Cursor documentation for the latest on this.

Claude Code — CLAUDE.md

Claude Code reads CLAUDE.md at the project root when starting a session. It's the most important context file for agentic Claude workflows.

Recommended content: project description, tech stack, key architecture decisions, how to run the dev server and tests, common commands.

CLAUDE.md
# Project: My App

A React + Node.js web application for [brief description].

## Stack
- Frontend: React 18, TypeScript 5, Vite, React Query, Tailwind CSS, shadcn/ui
- Backend: Node.js 20, Express, Prisma, PostgreSQL
- Testing: Vitest (unit), Playwright (E2E)

## Running the project
- `npm run dev` — start the dev server (frontend on :5173, backend on :3000)
- `npm test` — run unit tests
- `npm run test:e2e` — run Playwright tests

## Key conventions
- Named exports everywhere
- All API responses validated with Zod
- No `any` types
- Feature folders: `src/features/<name>/{components,hooks,api,types}.ts`

Reference: Claude Code memory docs

VS Code Copilot Techniques

  • @workspace — semantic search across all open workspace files. Use it to ask questions about your codebase: @workspace how is authentication handled?
  • @terminal — include terminal output (errors, build failures) as context for a fix.
  • #file / #selection — explicitly scope context to a specific file or highlighted code block.
  • Slash commands:
    • /explain — explain a piece of code in plain language
    • /fix — fix a bug or error in selected code
    • /tests — generate unit tests for selected code
    • /doc — generate a documentation comment for selected code
tip

@workspace /explain on an unfamiliar module is one of the highest-value quick wins when onboarding to a new codebase.

Cursor-Specific Techniques

  • @codebase — full semantic search across the entire indexed repo; more powerful than @workspace for large codebases.
  • Composer — multi-file editing mode. Describe a cross-cutting change and Cursor drafts diffs across all affected files simultaneously.
  • .cursorrules — see Workspace Instruction Files above.

Resources