cd /news/ai-tools/stop-prompt-engineering-copilot-writ… · home topics ai-tools article
[ARTICLE · art-127363] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

Stop Prompt-Engineering Copilot. Write Three Rules in a File Instead.

A developer advocates replacing prompt-engineering tactics with a committed `.github/copilot-instructions.md` file that supplies Copilot with codebase-specific facts it cannot infer. The post argues rules should be durable, specific, and checkable, and that non-obvious conventions — such as avoiding `datetime.utcnow()` or pinning GitHub Actions to full commit SHAs — are followed when they name the specific thing to avoid and explain why. The file is committed and reviewed like code, turning individual preferences into team-agreed conventions.

by read4 min views3 publishedSep 12, 2026

Most advice about getting better output from Copilot is advice about phrasing. Be specific. Give it context. Ask it to think step by step.

That plateaus quickly, and it plateaus for a structural reason: better phrasing asks the model to try harder. It does not tell the model anything it did not already know.

The thing that actually moves output is a file. .github/copilot-instructions.md, committed to the repository, read on every request.

.github/copilot-instructions.md

Inside the .github directory, not the repository root. Plain Markdown, no frontmatter required. That is the whole setup.

Compare these two:

- Write clean, maintainable code.
- Use proper error handling.
- Money is `Decimal`, never `float`. Round half-up to two places at the 
  response boundary only, never mid-calculation.
- All datetimes are timezone-aware UTC. `datetime.utcnow()` returns a naive 
  datetime and will compare incorrectly against everything else here.

The first pair costs context on every request and changes nothing — the model already agrees with both, and agreeing is not the same as knowing what you meant.

The second pair changes the output, because it contains information the model did not have: a fact about your codebase that is not inferable from the code it can see.

Three properties, and a rule wants all three:

Durable. True next month. Anything task-shaped belongs in a prompt, not here.

Specific. datetime.utcnow() returns a naive datetime — not "handle timezones correctly".

Checkable. Somebody can look at a diff and say whether the rule was followed.

"Do not use datetime.utcnow(); it returns a naive datetime and this codebase compares against aware ones."

gets followed.

"Use timezone-aware datetimes."

gets agreed with, and then not done.

The difference is that the first one names the specific thing to avoid and says why. Give a reason and the rule survives contact with a situation you did not anticipate.

Eight rules that get followed beat forty that get averaged.

The file is prepended to requests, so a 400-line instruction file is a tax on every interaction and it dilutes the rules that matter among the ones that do not. If you keep only five lines, keep the non-obvious ones.

Delete anything a tool already enforces. If ruff fails the build on import order, do not spend a line on import order. Say it once, in the place that can actually reject the change.

The pattern holds outside application code, and infrastructure is where it pays best because the mistakes are more expensive.

Terraform:

- for_each for collections; count only for on/off conditionals. count is 
  positional, so removing the second of three items destroys the third.
- Every variable has a type, a description, and a validation block where 
  the value is bounded.
- No hardcoded region, account id or ARN.

Kubernetes:

- Every container sets resources.requests and resources.limits.
- Three probes, pointing at different endpoints. A liveness probe that 
  duplicates readiness turns a slow dependency into a restart loop.
- Images pinned by digest. :latest is not deployable here.

GitHub Actions:

- Never interpolate anything under github.event into a run: block. Pass it 
  through env:.
- permissions: contents: read at workflow level, widened per job.
- Third-party actions pinned to a full commit SHA, never a tag.

Each of those is a defect class that is invisible in review because the wrong version looks exactly like the right version.

It is committed and reviewed like code.

That sounds administrative and it is the most useful property of the whole mechanism. Your conventions stop being a thing one person prefers and become a thing the team agreed to, in a file with a history, changed by pull request.

I have watched a fifteen-minute argument about a convention end with "put it in the instructions file" — not because the file settled the argument, but because it turned a preference into a proposal somebody had to approve.

Open the file. Write three rules about your codebase that a competent new joiner would get wrong in their first week. Not style. Not anything the linter catches. The three things that are true of this repository and not obvious from reading it.

That will take ten minutes and outperform every prompt-engineering tip you have read, including this one.

Full lesson — including path-specific instruction files, the precedence order when several apply, and which surfaces read which file — at GitHub Copilot custom instructions. The stack-specific examples above are condensed from longer ones on The Copilot Stack.

── more in #ai-tools 4 stories · sorted by recency
── more on @github 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/stop-prompt-engineer…] indexed:0 read:4min 2026-09-12 ·