The single biggest lever for coding well in Windsurf is not the model — it's how you brief Cascade, the agentic pane that plans multi-file edits, runs your terminal, reads the output, and self-corrects until the task is done. A vague message makes Cascade guess; a structured one makes it work like a careful teammate.
This guide teaches one repeatable formula, then hands you nine copy-paste prompts you can adapt. Every example uses real Windsurf mechanics — @-mentions, Write/Chat mode, Rules, Memories, and /workflow commands. For a broad library of ready prompts, keep 40 Best Windsurf AI Prompts open in another tab.
The Cascade prompt formula
A strong Cascade prompt has five parts: goal, context, scope, acceptance criteria, and process. Say what you want in plain language, point Cascade at the right files, fence off what it may touch, define "done", and tell it to plan then verify.
- Goal — the outcome in one or two sentences, plain English.
- Context — @-mentions so Cascade reads the right code:
@codebasewhen unsure,@file/@folderfor known paths,@docsfor a library,@terminalfor a failing run,@gitfor a diff. - Scope — the files it may change and the ones it must not ("only touch
src/auth/, don't modify unrelated files"). - Acceptance criteria — an objective finish line ("done when
npm testpasses and the type check is clean"). - Process — how to work ("plan first and wait for my go-ahead, then implement, run the tests, and fix until green").
Here is the difference in practice. First, a weak prompt that forces Cascade to guess:
Add login to my app.Why it fails: no files, no scope, no definition of done. Cascade may invent a stack, touch a dozen files, and you won't know if it worked. Now the same intent with the formula applied:
GOAL: Add email + password login to the web app using our existing session middleware.
CONTEXT: @folder src/auth @file src/middleware/session.ts @file src/routes/index.ts. We use Express + Prisma; @docs prisma for query syntax.
SCOPE: Only add or edit files under src/auth/ and register one new route in src/routes/index.ts. Do not modify unrelated files, config, or the schema.
ACCEPTANCE: Done when POST /auth/login returns a signed session cookie for valid credentials and 401 for bad ones, and `npm test` passes.
PROCESS: Propose a short plan and the exact file list first, then wait for my OK. After I approve, implement, add a test in src/auth/__tests__/, run `npm test`, and fix until green.Why it works: Cascade knows the outcome, the exact context, the blast radius, the finish line, and the order of operations — so it plans instead of guessing and you can verify the result. If you want fill-in-the-blank versions of this structure, see the Windsurf prompt templates.
Give Cascade the right context
Context quality decides edit quality. The direct answer: use @codebase when you don't know which files matter, and switch to precise mentions the moment you do. Each primitive pulls a different slice of context into the prompt.
@codebase— semantic search over the whole indexed repo. Best when you're unsure where a feature lives.@file/@folder— pull specific files or a directory into context. Best when you know the location and want a tight, scoped edit.@docs— indexed library documentation, so Cascade uses the real API surface instead of guessing. Pair with@webfor live search when docs aren't indexed.@terminal— the recent terminal output, ideal for handing Cascade a stack trace or a failing build verbatim.@git— diffs and commit context, useful for "review what I just changed" or "finish the migration I started".
Start broad when you're exploring:
Use @codebase to find where rate limiting is enforced on our API. In Chat mode only, list the files involved, the current limit, and where I'd change it per-route. Do not edit anything yet.Best for: mapping unfamiliar code before you commit to an edit. Once you know the files, hand Cascade the exact context plus a failure:
@file src/api/rateLimit.ts @terminal — the attached terminal output shows the 429 test failing after my last change. Diagnose the root cause from the trace, fix it in rateLimit.ts only, then re-run `npm test -- rateLimit` and confirm it passes. Don't touch other files.Why it works: the exact file plus the live error gives Cascade everything it needs and nothing it can wander into. For error-focused patterns, see the Windsurf prompts for debugging.
Write vs Chat mode, and planning first
Pick the mode to match your intent: Chat/Ask is read-only for questions and planning, Write is agentic and will edit files and run commands. The safe rhythm is Chat to understand and plan, then Write to execute an approved plan.
Even in Write mode, ask Cascade to plan and pause before it changes code. That one instruction catches wrong assumptions before they become diffs.
In Chat mode, using @folder src/checkout, explain how the current cart total is calculated, including tax and discounts. Then propose a plan to add support for percentage coupon codes: the files you'd change, new functions, and edge cases (stacked coupons, expired codes). Output the plan only — do not write code.Best for: aligning on approach before any edits. When the plan looks right, switch to Write and hold Cascade to it:
Switch to Write mode. Implement the coupon plan you just proposed, step by step. Apply changes one file at a time and pause after each so I can review the diff before you continue. When all files are done, run `npm test` and fix failures until green.Why it works: one-file-at-a-time with review points keeps you in control of an agent that can otherwise move fast across many files.
Stop repeating yourself: Rules, Memories, Workflows
If you re-explain the same conventions every session, move them out of the prompt. Windsurf has three durable layers: Rules (persistent instructions), Memories (project facts that survive sessions), and Workflows (reusable /workflow recipes).
Rules live in a .windsurf/rules/ directory of Markdown files (modern, scoped), a single .windsurfrules at repo root (project-wide), or global_rules.md (every workspace). Each rule file's frontmatter has a trigger with four modes: Always On, Manual, Model Decision (the agent pulls it in when relevant), and Glob (activates for matching file paths). Best practice: a short always-on rule that says "follow the matching glob rules", plus several scoped glob rules — that beats one giant always-on file.
Here is a compact .windsurfrules you can drop at repo root:
# Project rules for Cascade
## Stack
- TypeScript strict mode, React 19, Node 22, Prisma, Vitest.
## Conventions
- Never use `any`; prefer explicit types and `unknown` at boundaries.
- Co-locate tests as `*.test.ts` next to the file under test.
- Use named exports only; no default exports.
## Working style
- Plan multi-file changes before editing and wait for approval.
- Keep edits scoped to the files named in the request.
- After any change, run `npm test` and `npm run typecheck`; report results.Memories are short, workspace-scoped facts that persist across sessions, so you skip the warm-up prompt. Cascade can auto-generate them, or you can ask directly:
Create a memory: This repo deploys via GitHub Actions on merge to main; never edit .github/workflows/deploy.yml without asking. The staging URL is [staging-url] and secrets live in Doppler, not .env.Workflows are Markdown recipes in .windsurf/workflows/, run with a /workflow-name slash command in Cascade — perfect for sequences you'd otherwise retype weekly. Save this as .windsurf/workflows/ship-feature.md, then run /ship-feature:
---
description: Implement, test, and prep a feature branch for PR
---
1. Create a branch `feat/[short-name]` from main.
2. Implement the change described in my message; keep edits scoped.
3. Add or update tests for the new behavior.
4. Run `npm run lint`, `npm run typecheck`, and `npm test`; fix until all pass.
5. Summarize the diff by file and draft a PR title + description.
6. Stop and wait — do not push or open the PR without my confirmation.Remember the precedence order (highest to lowest): Global Rules > .windsurfrules > Memories > your current prompt. Persistent layers set the baseline; a specific prompt guides the task at hand. For more on agent behavior, see the Windsurf Cascade agent prompts.
Keep it on track
Cascade is fast, which means a loose prompt can produce sprawling edits. Keep it tight: name exact paths, forbid unrelated changes, insist on tests, and review the per-file diff before accepting. Pick a stronger model (Claude Opus 4.8 or Sonnet 5, GPT-5.x, Gemini, or fast/auto) for heavy multi-file reasoning, but technique matters more than the model.
Refactor only the functions in @file src/utils/date.ts to remove duplicate parsing logic. Do not change any public function signatures and do not touch callers. Keep behavior identical — prove it by adding characterization tests first, then refactor, then run `npm test -- date` until green. Show me the diff for date.ts before finalizing.Why it works: it pins the file, freezes the API, and demands tests-before-refactor so behavior can't drift. When a change starts touching too much, stop and re-scope:
Stop. That plan touches more files than needed. Redo the plan so it changes only @file src/components/Table.tsx and its test. List any change outside that file as a separate follow-up I can approve later. Then wait for my OK before editing.Best for: reeling in an over-broad edit before it lands. Clean-code work fits the same discipline — see the Windsurf refactoring prompts.
A full worked example
Here is the whole formula in one realistic feature request — goal, context, scope, acceptance criteria, and process together. Paste it into Cascade in Write mode and let it plan first.
GOAL: Add server-side pagination to the users list endpoint and wire it to the admin table so large orgs load fast.
CONTEXT: @codebase to locate the users endpoint and the admin table. Likely files: @file src/api/users.ts @file src/components/admin/UsersTable.tsx. We use Express + Prisma on the API and TanStack Query on the client; @docs prisma for cursor pagination.
SCOPE: Change only the users endpoint, its test, UsersTable.tsx, and the query hook it uses. Do not modify the Prisma schema, other endpoints, shared UI components, or config. Keep the existing response shape backward compatible by adding fields, not renaming.
ACCEPTANCE: Done when GET /api/users accepts `?limit` and `?cursor`, returns { items, nextCursor }, defaults to 25 per page, and the admin table shows a working "Load more" control. `npm test` and `npm run typecheck` must pass, and no existing test may break.
PROCESS:
1. In Chat, propose a plan: exact files, the pagination approach (cursor vs offset), and edge cases (empty page, last page, invalid cursor). Wait for my approval.
2. In Write mode, implement one file at a time and pause after each for diff review.
3. Add a test in src/api/__tests__/users.pagination.test.ts covering first page, next page, and last page.
4. Run `npm test` and `npm run typecheck`; fix until both are green, then summarize the diff by file.
5. Do not commit or push — stop and wait for me.That prompt gives Cascade an unambiguous target, the right context, a fenced blast radius, a testable finish line, and a review-friendly process. Copy it, swap the specifics, and reuse it as your default shape. For a one-page reference of mentions and modifiers, keep the Windsurf prompt cheat sheet handy — and if you also work in a sibling editor, compare with the best Cursor prompts.
Frequently Asked Questions
What is the best structure for a Windsurf prompt?
Use five parts: a plain-language goal, context via @-mentions (@codebase, @file, @docs, @terminal, @git), scope constraints that say what not to touch, acceptance criteria like "done when npm test passes", and a process instruction to plan first, then implement, then run the tests and fix until green.
When should I use @codebase instead of @file?
Use @codebase when you don't know which files matter and want Cascade to semantically search the indexed repo. Use @file or @folder when you already know the exact files or directory the change belongs in, which keeps context tight and edits scoped.
What is the difference between Write and Chat mode in Cascade?
Write mode is agentic — Cascade edits files and runs terminal commands. Chat/Ask mode is read-only — it answers questions and proposes plans but won't change your code. Use Chat to explore and plan, then switch to Write to execute.
How do I stop repeating conventions in every Windsurf prompt?
Move durable conventions into Rules (.windsurf/rules/ files, .windsurfrules at repo root, or global_rules.md), save project facts as Memories, and turn multi-step sequences into /workflow recipes. Cascade loads these automatically so you stop re-explaining them.
What is the precedence order for Windsurf rules?
Highest to lowest: Global Rules, then .windsurfrules, then Memories, then your current prompt. A specific instruction in your prompt can still guide behavior, but persistent rules set the baseline Cascade follows every session.
Does the model I pick in Cascade matter?
Prompting technique matters more than model choice. You can select Claude Opus 4.8 or Sonnet 5, GPT-5.x, Gemini, or a fast/auto option per chat. Reach for a stronger model on multi-file reasoning tasks, but a well-scoped prompt with clear acceptance criteria beats a vague prompt on any model.
How do I keep Cascade from editing unrelated files?
Scope the request explicitly: name the exact files or folder, add "do not modify anything outside these paths", ask for a plan first, and review the per-file diff before accepting. If Cascade drifts, reject the diff and tighten the scope in a follow-up.