Justin McKelvey
Fractional CTO · 15 years, 50+ products shipped
How to Tell If Code Was Written by AI (and What to Do About It)
Quick Answer
You can tell if code was written by AI — but not with detector tools, which fail on code. You read for tells: uniform comments explaining the obvious, the same problem solved five ways in one repo, dependencies imported and never used, generic names like data2 and result_final, tests that assert nothing, TODO blocks in production, and a git history of giant single commits. One tell is a hunch. Four or five together is a diagnosis — and the fix starts with security, not bugs.
Reviewed July 2026 · Author: Justin McKelvey, fractional CTO — 50+ products shipped, AI-codebase rescues for a living
TL;DR: Detecting AI-Written Code in 2026
The question usually isn't academic. When someone asks me "was this code written by AI?", what they actually mean is: my freelancer delivered this, my last developer left this behind, my co-founder built this over a weekend — and something feels off. As of 2026, the honest answer is that a lot of it was AI-written, and that's not the problem. The problem is whether anyone understood it before it went to production.
I review AI-built codebases for a living — fixed-price rescues of apps built with Lovable, Cursor, Replit Agent, Bolt, and friends. Below are the tells I actually use, why the automated detectors don't work on code, and the exact order to fix things in once you know what you're holding.
Can You Tell If Code Was Written by AI?
Yes — with pattern reading, not software. Here's the core insight from a couple dozen rescues: humans are inconsistent in small ways but consistent in approach. AI is the exact opposite. AI code is eerily uniform line by line — every comment formatted the same, every function documented identically — and wildly inconsistent in architecture, because every prompt session reinvented the approach from scratch.
That inversion is the fingerprint. You're not looking for bad code. You're looking for code that's locally perfect and globally incoherent.
How to Detect AI-Generated Code: 9 Tells From Real Rescues
-
Comments that explain the obvious, uniformly.
# increment the counterabovecounter += 1. A human writes that comment zero times. An AI writes it forty times, in identical style, on every file. - The same problem solved five different ways. Three HTTP clients. Two date libraries. Four patterns for form validation. Each prompt session picked its own favorite, and nobody was watching the whole.
- Dependency bloat. Packages imported and never called. Libraries pinned in the manifest that nothing uses. Three tools doing one job. AI reaches for a library the way a nervous cook reaches for another pan.
-
Generic naming.
data2,result_final,handleClick2,newFunction. Names carry intent; AI-in-a-hurry code carries numbering. -
Tests that don't test. Either no tests at all, or test files that assert
true == truein various costumes. Looks like coverage in the file tree; proves nothing. -
TODO and placeholder blocks in production.
// TODO: add real authentication here— live, on the internet, taking user data. I've seen this more times than I want to type. - Git history made of boulders. An "initial commit" with 40,000 lines, then five commits called "fixes" and "updates" at 3,000 lines each. Real development leaves a trail of small decisions; prompt sessions leave craters. This is my single most reliable check, because history can't be faked after the fact without real effort.
- Dead code that looks load-bearing. Whole components, routes, and helpers that nothing calls — fully built, nicely formatted, wired to nothing. The AI built what was asked for, and also what it guessed might be asked for.
- Error handling that swallows everything. Beautiful try/catch blocks on every function… that catch every exception and do nothing. It looks defensive. It's actually a blindfold — the app can't crash, so you never learn it's broken.
Scoring: any single tell shows up in tired-human code too. Four or more, uniformly across the repo, is a diagnosis.
How Can I Tell If My Python Code Was Generated by AI?
Python deserves its own list because the tells are so specific, as of 2026:
- Docstrings in identical format on every function — including three-line utilities that need none.
- Type hints everywhere or nowhere. Humans drift; AI commits to a policy per session.
- A
requirements.txtfull of pinned packages the code never imports. -
except Exception: pass— the Python edition of the blindfold from tell #9. -
if __name__ == "__main__":boilerplate on modules that nothing ever runs directly.
Do AI Code Detectors Work?
Short version: no, and code is the worst possible input for them. Detector tools were built for prose, where word-choice statistics carry signal. Code passes through linters and formatters that normalize style, follows community conventions on purpose, and legitimately repeats common patterns. That erases exactly the signal detectors depend on — so they false-positive on clean human code and false-negative on lightly-edited AI code.
The heuristics above plus twenty minutes of git archaeology outperform every automated detector I've tried. I don't run a detector on rescue audits. I read the log.
Does It Matter Who Wrote It?
Here's the honest part: no. I use AI to write code every single day. Reviewed, tested, understood AI code is just… code. The thing the tells above actually detect isn't authorship — it's the absence of a human who understood the system before it shipped.
That absence has a name: Vibe Debt — the silent cost of running software nobody on the team can explain. It comes in three flavors: comprehension debt (nobody can explain it), drift debt (five patterns for one job), and dependency debt (the bloat from tell #3). The "was it AI?" question is really the "does anyone understand this?" question wearing a trench coat.
What Steps Should I Follow to Fix Bugs in AI-Generated Code?
The most common mistake I see: opening the bug list and starting at the top. In an AI-built codebase, that means fixing symptoms inside a structure you don't understand yet — you'll fix some of them twice. The order that works (the same triage I run on paid rescues — full framework at The Crash Cart):
- Security first, always. Exposed API keys, missing auth on endpoints, client-side "validation" as the only validation. AI-built apps ship these disproportionately, and they're the bugs that end companies. Run the free 20-point security checklist before touching anything else — it takes an evening.
- Stabilize. Get the app running reproducibly, under version control, with a way to deploy that isn't "it worked on the builder's laptop."
- Survey. Map what actually executes versus what's dead weight (tell #8). You can't reason about a system you haven't bounded.
- Strip. Delete the dead code. It's not an asset; it's fog.
- Then fix bugs — writing a failing test before each fix, so the fix stays fixed and the test suite stops being decorative.
If you'd rather have a professional read before deciding anything: I do a free 20-minute repo audit — a recorded walkthrough of what's actually in your codebase and a written summary, no strings. Owners usually walk away knowing whether they need a cleanup weekend or a real rebuild ($25K–$50K fixed, if it comes to that — you'll know before you spend a dollar).
Related guides: what is vibe coding, vibe coding examples, Vibe Debt, The Crash Cart triage framework, the 20-point security checklist.
Ship AI-built code without the 2am surprise
The free 20-point security checklist I run on every AI-built codebase before it touches real users.
Frequently Asked Questions
- Can you tell if code was written by AI?
- Yes — but not with detector tools. Code is too structured for the statistical tricks that flag AI prose. What works is pattern reading: AI-written codebases have recognizable tells like uniform comments that explain the obvious, the same problem solved five different ways in one repo, dependencies that are imported but never used, generic variable names (data2, result_final), tests that assert nothing, and git histories made of a few giant commits. One tell is a hunch; four or five together is a diagnosis.
- How do you detect AI-generated code?
- Read for consistency failures, not style. Humans are inconsistent in small ways but consistent in approach; AI is the opposite — perfectly uniform line by line, wildly inconsistent in architecture. Check: comment style (uniform and obvious), pattern reinvention (three different HTTP clients in one app), dependency bloat, naming quality, test quality, placeholder TODO blocks in production, and the git log. Git archaeology is the most reliable single check: a 40,000-line 'initial commit' followed by giant amorphous 'fixes' commits is prompt-session fingerprints.
- How can I tell if my Python code was generated by AI?
- Python-specific tells, as of 2026: identical-format docstrings on every function (including trivial ones), type hints applied everywhere or nowhere with no middle ground, a requirements.txt full of pinned packages the code never imports, try/except blocks that catch Exception and pass, and if __name__ == '__main__' boilerplate on modules nothing ever runs directly. Any one of these appears in human code too — the tell is all of them at once, uniformly.
- What steps should I follow to fix bugs in AI-generated code?
- Don't fix bugs one at a time first — that's the most common mistake. Order matters: (1) Security first — check for exposed API keys, open endpoints, and missing auth before anything else, because AI-built apps ship those bugs disproportionately. (2) Stabilize — get the app running reproducibly under version control. (3) Survey — map which code actually executes versus dead weight. (4) Strip the dead code. (5) Then fix bugs, writing a failing test before each fix so it stays fixed. Fixing bugs before understanding structure means fixing some of them twice.
- Do AI code detectors work?
- Not reliably, and code is the worst case for them. Detectors were built for prose, where word-choice statistics carry signal. Code gets formatted by linters, follows shared conventions, and legitimately reuses common patterns — which normalizes away the signal detectors depend on. False positives and false negatives are both common. Human heuristics plus git history beat any automated detector for code, and the git log can't be faked retroactively without real effort.
- Does it matter if code was written by AI?
- Honestly: no. What matters is whether anyone on your team understands it. AI-written code that a developer reviewed, tested, and can explain is fine — I ship code like that every week. The dangerous thing is comprehension debt: a production system nobody can explain, regardless of who or what wrote it. The 'was it AI?' question is really a proxy for 'did anyone understand this before it shipped?' — and the tells in this post mostly detect the absence of that understanding, which is exactly why they predict trouble.
- Is AI-generated code bad?
- No — unreviewed AI-generated code is bad. The same tools that produce unmaintainable messes in untrained hands produce solid, shippable software when someone who understands the output stays in the loop. The quality difference isn't the AI, it's the review step. That's also why 'my app was built with AI' isn't embarrassing; 'nobody has read the code my app runs on' is.
More on Vibe Code Rescue
Claude Code Setup Guide 2026: Install to First Shipped Feature in 30 Minutes
The Claude Code setup that actually matters: install, login, a CLAUDE.md that stops the agent improvising, MCP servers, and a first-project workflow — from someone who uses it on client work daily.
Vibe Coding Flutter Apps in 2026: Tools, Workflow, and What Breaks
Yes, you can vibe code a Flutter app in 2026 — FlutterFlow, Claude Code, and Cursor with the Dart MCP server all work. Here's the honest tool comparison and where mobile vibe coding falls apart.
7 Best Lovable Alternatives in 2026 (From a CTO Who Fixes These Apps)
Lovable's credit limits and React-only opinions push a lot of builders to shop around. I ranked 7 Lovable alternatives by what actually ships — with real pricing and honest trade-offs.
7 Best Replit Alternatives in 2026 (Ranked by What Actually Ships)
Replit's credit-based Agent pricing surprises a lot of founders. I ranked 7 Replit alternatives by production readiness and real monthly cost — here's which one fits your situation.
Written by
Justin McKelvey
Fractional CTO & AI consultant in Austin, TX. 15 years building software, 50+ products shipped, $53M+ in client revenue generated. I help $1M–$50M founders ship production software and automate operations with AI — without hiring a full-time executive team.
Work with me