ChatGPT for Coding in 2026: What It Nails, What It Fumbles, What to Stop Asking
Twelve coding tasks sorted by how reliable ChatGPT actually is: six it nails, four that need verification, two to stop asking, plus chat versus agent and current plan pricing.
The question worth asking in 2026 is not whether the model can write code: it is whether the job belongs in a chat window at all, or in an agent that already has your repository checked out and can run your test suite. Those are two different products with two different failure modes, and picking wrong is why a lot of developers conclude that "AI coding" either changed everything or does nothing.
A chat thread is a colleague with an excellent memory of the public internet, no login to your VPN, and no terminal. An agent is that same colleague sitting at your machine with write access. The first is cheap, fast, and safe to be wrong. The second is faster on real work and much more expensive when it is confidently wrong across nine files.
So the useful framing is not a list of ten tricks. It is a reliability ranking. Below, twelve coding tasks sorted into three tiers: six where a chat window is close to always right, four where it is right roughly half the time and you carry the verification cost, and two where you should stop asking and go somewhere else.
Chat window vs coding agent
"ChatGPT" here means the chat interface, the desktop app, or the browser extension: a box you paste code into. It does not read your repository, does not know your branch, and cannot run anything unless you paste the output back in. Every strength and limitation below follows from that one fact.
Here is what OpenAI currently charges, from the pricing page on chat.openai.com:
- Free ($0/month): GPT-5.5 Instant, 27K context window, tight message caps. Fine for a one-off question, not a working session.
- Go ($8/month): more messages, a bigger 54K window, still built for casual chat, not dev workloads.
- Plus ($20/month): GPT-5.6, 256K reasoning context, expanded Codex access, custom GPTs, projects. The tier most developers should buy.
- Pro (from $100/month): 5x to 20x usage, 400K context, maximum Codex tasks. Worth it only if you hit Plus's limits weekly.
- Business (custom, 2-seat minimum): admin console, SSO, data excluded from training by default. Buy it for compliance, not coding power.
The context window is the number that decides whether a chat thread is viable for your task. A 27K window on Free will not hold a real file plus its tests plus a stack trace. Plus's 256K reasoning context will hold several files at once, which is roughly the point where pasting stops feeling like a workaround.
OpenAI's own answer to the missing-repo problem is Codex, a separate agentic tool with a CLI and an IDE extension, bundled into Plus and up. Codex, Claude Code, Cursor's agent mode, and Copilot's agent mode all compete in the same category: they index your repo, edit multiple files, and run build and test commands in a loop. Claude Code ships inside Claude Pro ($20) and Max (from $100). Cursor is $16 Individual, $32 Teams. Copilot is $10 Pro, $39 Pro+.
Pick the chat window when the task fits in a conversation and you want to understand the answer: explain this, write this function, why does this trace look like that, turn this schema into a query. Pick an agent when the task is defined by the repo rather than by the snippet: rename a concept across twelve files, make the failing suite green, migrate a config format everywhere it appears. Most engineers keep both open and switch without thinking about it.
One thing to settle before you paste anything: on a personal account, OpenAI's default is that your conversations can be used to improve its models, and turning that off is a switch you flip yourself under Data Controls. Business and Enterprise workspaces are excluded from training by default. Independently of the tier, strip API keys, credentials, customer identifiers, and anything covered by a client agreement before the code goes in the box. Redacting a variable name costs you five seconds. Explaining a leak costs considerably more.
Six things it gets right almost every time
These are the tasks where the model needs no knowledge of your system, only the text you gave it. Verification is cheap, failure is loud, and the hit rate is high enough that you can work fast.
Explain code you didn't write
The most common use, and the safest. Good for onboarding onto a legacy module, or for reading a dependency's internals before you patch around it.
Explain what this function does, line by line where it's not obvious.
Then tell me: what are the edge cases it handles, what happens if
`items` is empty or None, and is there anything here that looks like
a bug rather than intentional behavior?
def reconcile(items, ledger):
seen = {}
for i in items:
key = (i.account_id, i.posted_at.date())
seen.setdefault(key, []).append(i)
...
Paste the whole function, not a snippet. Half a function with no context is how you get a plausible-sounding explanation of the wrong thing. The follow-up that pays for itself: ask which lines it is least sure about, and why.
Write a function from a tight spec
Give it the exact signature, the types, and one concrete example. A vague description gets a vague function back, and you spend the time you saved rewriting it.
Write a Python function `chunk_by_weight(items: list[dict], max_weight: float) -> list[list[dict]]`
that splits a list of items (each with a "weight" key) into sublists
where no sublist's total weight exceeds max_weight. Preserve original
order. If a single item's weight exceeds max_weight on its own, put it
alone in its own sublist rather than raising. Include a docstring and
one usage example in the docstring.
Name the edge case you actually care about (here, the oversized single item) or you get a naive implementation that breaks on real data. The rule of thumb: whatever you leave unspecified, you are delegating to a guess.
Generate boilerplate
The highest-volume, lowest-risk category. A Dockerfile, a CI workflow, a CRUD router skeleton, a Terraform block: pattern-heavy, well represented in public code, and cheap to verify.
Write a multi-stage Dockerfile for a Node 20 TypeScript app: install
deps and build in a builder stage, copy only the compiled dist and
production node_modules into a slim runtime stage, run as a non-root
user, and expose port 3000. Add a HEALTHCHECK that curls /health.
Boilerplate is where a subscription pays for itself fastest, and where you can accept output nearly as-is: a wrong Dockerfile fails loudly in CI rather than shipping a silent bug. Failure mode matters more than raw accuracy when you decide how much to trust something.
Build a regex you don't want to write by hand
Regex is pure pattern matching. The model needs to know nothing about your system to get it right, which is exactly the condition under which it performs best.
Write a regex that matches valid semantic version strings (e.g. 1.2.3,
2.0.0-beta.1, 1.4.10+build.5) and captures major, minor, patch, and an
optional prerelease/build suffix as named groups. Show the pattern,
name each group, and give me 5 example strings it should match and 3
it should reject.
Always ask for the rejection examples too. A pattern that matches everything you want but also swallows garbage you never tested is the standard way this goes wrong, and the rejection list turns a review into a thirty-second check.
Write SQL from a schema you describe
Paste the schema, not a description of the tables. Guessed column names produce queries that read beautifully and fail against your actual database.
Given this schema, write a PostgreSQL query that returns each customer's
total spend in the last 90 days, only for customers with at least 3
orders in that window, sorted by spend descending.
orders(id, customer_id, total_cents, created_at)
customers(id, email, created_at)
Use created_at for the date filter, total_cents for spend (convert to
dollars in the output), and explain the query plan implications of the
HAVING clause you use.
Run it against staging first, and read the plan yourself on large tables. It does not know which indexes exist, so its performance commentary is generic advice, not analysis of your database. Correctness of the logic is the strong part; cost is your problem.
Learn a new API from docs you paste in
Do not ask it to recall a library's usage from memory. Paste the current README section or docs page and constrain the answer to that text.
Here's the README section for a library I haven't used before. Based
only on what's in this text, show me a minimal working example that
does [specific thing], and tell me if anything I'm asking for isn't
covered by what you can see here.
[paste the README section or docs page]
That last clause is the whole trick. "Tell me if what I'm asking for isn't in here" converts a generator into a reader, and gives it an explicit way to say no instead of filling the gap. "Explain this from what I pasted" beats "explain how this library works" every single time.
Four it gets right about half the time
These tasks depend on things the chat window cannot see: your runtime, your data, your team's history. The output is often useful and occasionally wrong in ways that look fine. Budget verification time, or do not start.
Debug from a stack trace
Paste the full trace, not just the last line. It needs the call chain to reason about where the bug lives versus where it merely surfaced.
I'm getting this error and I don't understand why, since the function
above it checks for None. Walk me through what's likely happening,
and give me two hypotheses ranked by likelihood.
Traceback (most recent call last):
File "worker.py", line 88, in process_batch
result = handler(item)
File "worker.py", line 41, in handler
return item.metadata["source"]["id"]
TypeError: 'NoneType' object is not subscriptable
# handler():
def handler(item):
if item is None:
return None
return item.metadata["source"]["id"]
The trap here is a mismatch it spots well: the guard covers item, not item.metadata["source"]. What it cannot tell you is why source is None in production, because that lives in your data. Asking for two ranked hypotheses rather than one answer is the difference between a lead and a confident dead end, and it costs nothing.
Write tests
Name the framework and the cases that matter. Left unguided, it writes happy-path tests and calls the job done.
Write pytest unit tests for this function. I want cases for: normal
input, an empty list, a single item over max_weight, all items exactly
at max_weight, and negative weights (should raise ValueError). Use
parametrize where it reduces duplication. Don't test implementation
details, test behavior.
def chunk_by_weight(items, max_weight):
...
"Write tests for this" on its own gets you three trivial assertions that miss the case that actually breaks in production. It is also worth remembering that the model cannot run what it wrote: a test that passes in its head may not even import in your project. Half the value here is that enumerating the cases yourself forces you to think about the boundaries.
Refactor without changing behavior
State the constraint explicitly: same inputs, same outputs, different internals. Otherwise you get a rewrite that "improves" behavior something else depended on.
Refactor this function to reduce nesting and improve readability.
Do not change any behavior, including error messages and the order
operations happen in. Explain each change in one line so I can verify
nothing shifted.
def validate_order(order):
if order:
if order.get("items"):
if len(order["items"]) > 0:
for item in order["items"]:
if not item.get("sku"):
return False, "missing sku"
return True, None
Diff the output line by line. A tidy early return can silently change which error message a caller sees first, and that kind of drift passes review easily because the new code looks better than the old code. Asking for a one-line justification per change is what makes the diff reviewable at all.
Second opinion on a diff
Paste the actual diff, not a description of it. Ask for named categories of feedback, or you get a summary of your own change back.
Review this diff as if you were a strict senior engineer. Flag:
1) anything that could break in production but isn't covered by a test,
2) unclear naming, 3) any place error handling swallows a real failure,
4) anything that duplicates logic that probably exists elsewhere in a
codebase like this. Be specific about line numbers, don't just summarize.
[paste the diff]
Treat it as a pre-review pass that catches the obvious things before a human spends attention on them. It cannot know whether the change matches a decision taken in last week's design review, whether the duplicated helper it flagged exists on purpose, or whether the pattern you used is the one your team standardized on last quarter. It also has no accountability for what merges, which is most of what a review actually is.
Two things to stop asking it
Not "be careful with these." Stop. The expected value is negative because both failures are silent.
Current library versions and API surfaces from memory
Every model has a training cutoff, and none of them know about last week's release. Ask for usage of a fast-moving library from memory and you can get a method that never existed, an argument order from two majors ago, or an approach deprecated with a loud warning you will not see until runtime. It is worse for smaller libraries with less public code around them, which are exactly the ones you were most likely to need help with.
There is no prompt that fixes recall. There is only a different question:
I'm pasting the current docs for [library] version [X.Y]. Using only
this text, show me how to do [task]. If the docs I pasted don't cover
it, say so instead of filling in the gap.
Same information need, different mechanism: reading instead of remembering. If the docs are too long to paste, that is a signal to read them yourself, not a reason to trust recall.
A security review of code that ships
A chat window can point out a string-concatenated query or a missing input check, and it will do that reliably enough to be worth a pass on a hobby project. It cannot do a security review, because a review is about your threat model, your trust boundaries, your auth flow, and what an attacker can reach from outside, none of which is in the snippet you pasted.
The specific danger is that generic requests get generic answers. Ask for "a login function" and you get the simple pattern that appears most in public code, not a hardened one: plausible session handling, defaults nobody hardened, error paths that leak which half of the credentials was wrong. It compiles, it passes your tests, and it looks like code a reasonable person wrote. That is precisely why it survives review.
Use it for the cheap pass (ask explicitly for parameterised queries, output encoding, and secure defaults), then send anything touching authentication, payments, permissions, or data deletion to a person, a scanner, and where the stakes justify it, an audit. The costly failure in this whole category is never obviously broken code. It is code that looks correct, compiles, and fails on the case you did not test.
If you want to keep track of which of these tools actually changed month to month, Devshot writes up AI and developer tooling every day.
What these tools actually cost
We price every tool we review, so this is measured rather than estimated. Across 429 tools, 293 publish a price and 33% offer a free tier. Among developer tools, the median entry plan is $24.50 a month, which runs above the $24 median across every category we price.
The spread matters more than the median. Half of the developer tools sit between $10 and $49, and the range runs from $2.49 to $299. A quoted "starting at" price near the bottom of that range usually means per-seat add-ons land on top of it.
| Price point | Developer tools | All tools |
|---|---|---|
| Cheapest paid plan | $2.49 | $1 |
| Lower quartile | $10 | $10 |
| Median | $24.50 | $24 |
| Upper quartile | $49 | $49 |
| Most expensive | $299 | $990 |
| Tools measured | 18 | 293 |
FAQ
Should I be using ChatGPT or a coding agent like Codex, Claude Code, or Cursor?
Both, for different shapes of work. The chat window is for conversation-sized tasks where you want to understand the answer: explain this, draft this function, turn this schema into a query. An agent is for repo-sized tasks where you want the work done: multi-file changes, making a failing suite pass, mechanical migrations. If you find yourself pasting five files into a chat thread to give it context, that is the signal to switch.
Which plan do I actually need as a developer?
Plus at $20/month, for almost everyone. It gets you the current model, a 256K reasoning context that holds real files rather than fragments, and expanded Codex access. Pro at $100 and up only pays off if you hit Plus's limits weekly. Free's 27K window will not survive a real file plus its stack trace, so treat it as a trial rather than a tier.
Why does it invent methods and arguments that don't exist?
Because it is producing the most plausible continuation of your prompt, and for a library it saw rarely during training, a method that should exist looks a lot like one that does. The rate goes up for small, new, or fast-moving packages. The fix is mechanical rather than clever: paste the current docs and constrain the answer to what is in them, and explicitly give it permission to say the docs do not cover your case.
Can I paste proprietary code into it?
Check your workspace policy first, then the account settings. Personal accounts default to allowing conversations to be used for model improvement, and you switch that off yourself under Data Controls; Business and Enterprise are excluded by default. Regardless of tier, strip keys, tokens, customer names, and anything covered by a client agreement before pasting. If the code is under an NDA, that is a question for whoever signed it, not for a settings toggle.
Can it run my test suite?
No. It can execute Python in a sandboxed session for data analysis, but that sandbox has no access to your repository, your dependencies, your database, or your CI. It writes tests you run. That gap is also why "it says this passes" means nothing on its own, and why anything that depends on runtime state (flaky CI, a race condition, a slow query under real load) is a guess dressed up as an answer.
Is a ChatGPT pass enough to skip human code review?
No. It is a good pre-review filter: run it before you request review and you waste less of a colleague's attention on naming, missing tests, and swallowed errors. What it cannot supply is the actual function of review, which is a person with context on your system agreeing to be accountable for what merges. Use it to arrive at review with a tighter diff, not to arrive with none.
Devshot: the daily dev & AI brief
Free daily newsletter, read in 5 minutes.
Subscribe free