Skip to content
Engineering··4 min read

Prompt engineering for Claude Code: 12 practical patterns

Practical prompt patterns for getting better, faster, more reliable code out of Claude Code.

By

Prompt engineering for Claude Code: 12 practical patterns

Most "prompt engineering" content is hype. Real prompt engineering for coding agents is a small set of patterns that, when followed consistently, improve output. Here are 12 of them.

  1. State the constraint before the goal

Bad: "Write a function that fetches user data."

Good: "We use Drizzle ORM, the existing helper is db.users.findMany. Add a function that fetches a single user by id — should match the existing pattern in lib/db/queries.ts."

The model produces better code when you frontload the constraints (what library, what pattern, what file) before stating the goal.

  1. Reference real files, not abstractions

Bad: "Add a similar pattern to our other utilities."

Good: "Add it the same way lib/utils/format-date.ts does — same file structure, same export style, same JSDoc comment shape."

Concrete file references give the model an exact target to mimic. "Similar pattern" gives it nothing.

  1. Ask for a plan before code on multi-file changes

For anything touching 3+ files, prefix your request with: "First, list the files you'll change and what each change is. Don't write any code yet."

This costs you one extra turn, and you catch wrong assumptions before any code is written.

  1. Use TODO comments as scope markers

When you want changes constrained to a region:

ts
// TODO(claude): rewrite this block to use streaming
// ... existing code ...
// TODO(claude): end of scope

Claude treats those markers as boundaries. Without them, it tends to "improve" surrounding code that you didn't ask to change.

  1. Pin the test framework explicitly

State the framework in your first prompt of the session: "We use Jest and @testing-library/react. Use describe/it style." This avoids the painful discovery later that all your tests use the wrong matcher.

  1. Reject unfounded "while I'm here" changes

When Claude returns a 200-line patch and 40 of those lines are "while I'm here" cleanups: reject the patch and reissue with "only change the function I asked about. Don't touch anything else, even if you think it could be improved."

Drift is the silent killer of long sessions. Police it from prompt 1.

  1. Quote error messages literally

Bad: "I'm getting a TypeScript error about union types."

Good: paste the exact error, e.g.:

text
Type 'User | null' is not assignable to type 'User'.
  Type 'null' is not assignable to type 'User'.

Claude is excellent at parsing error messages — but it's much worse at guessing which error you saw. The fix on a paraphrase is often unrelated to the actual issue.

  1. Use "minimum diff" framing for fixes

For bug fixes specifically:

text
Apply the smallest possible change that fixes this bug. No
refactoring. No "while I'm here" cleanups. The diff should
be as small as possible.

This frames the model toward surgical edits and away from rewriting the file.

  1. Bring in skill files for repeat work

If you find yourself repeatedly saying "use Drizzle ORM, the helper is at lib/db, write tests with Jest, follow the conventions in lib/utils" — promote that into a SKILL.md and save it once as .claude/skills/<name>/SKILL.md in the project (commit it so your team gets it too). Claude loads it whenever a request matches its description; you stop re-typing the constraints.

For common patterns, check claudeskil.com/explore — many are already published.

  1. Use placeholders for sensitive data

Bad: "My API key is sk-12345; use it to call X."

Good: "I'll provide an API key as the env var FOO_API_KEY. Generate code that reads from process.env.FOO_API_KEY."

The cleaner pattern is not to put secrets in the conversation at all: reference the env var by name and pass real values at runtime only.

  1. Use diff format for surgical edits

When you want a 3-line change in a 500-line file:

text
Output the change as a unified diff against the current file.
No prose, no full-file rewrite — just the diff.

A diff is much faster to review and apply than a full-file regeneration.

  1. End complex sessions with a "summarise what changed"

Before you commit, ask: "Summarise the changes you've made in this session, file by file. Anything I should know before reviewing?"

This catches subtle drift. Claude often confesses to "while I was at it, I also..." changes that weren't in the original ask. Better to find that before you commit than after.

The meta-pattern

All twelve patterns share a structure: be more specific about constraints, more concrete about references, and more explicit about scope. Models reward specificity disproportionately. The work of prompt engineering is the work of being clearer than feels necessary.

For more patterns specific to your role (frontend, data, SQL, SEO, etc.), the SKILL.md ecosystem at claudeskil.com has skills you can install in 60 seconds.