Find the phrases thatread as machine-written.

Counts, lines and columns for known signs of LLM text. Never a verdict.

Try it on your text

What began as a weekend repair stand has grown into a full-service shop em-dash5:267weak but the heart of it hasn't changed.

Nestledpuffery7:143weak at the foot of the Ridgeline trail system, we've had a front-row seat as Pine Hollow has grown into a vibrantvocabulary7:253moderate cycling destination, and we're proud to have played a part in that story.

Ridgeline isn't just a place to buy a bike — it'snegative-parallelism11:11moderate a gathering place for the local riding community.

Sample written by Claude Fable 5.1 on 2026-09-19 for this corpus; prompt in corpus/MANIFEST.json.

What it gives you

A finding, not a feeling.

Every result is a place in your document and the name of the pattern found there. Nothing is averaged into a score.

…Pine Hollow has grown into a vibrant cycling destination…

vocabularyRuleWhich pattern matched, by name.
7:253Line : columnWhere it is. Go straight to it.
moderateWeightHow much one hit means alone.
3 · 5.6/1kCount and rateFor this rule in this file. Never added up.

Weak

Common in careful human writing, so only the density means anything.

Moderate

A recognisable habit. A handful in a short document is a pattern.

Strong

Leftovers from a chat window, not a writing style. One hit is worth reading. It still shows only that the text went through a chat window, not who wrote it.

Rules overlap. “Vibrant” is counted by both vocabulary and puffery, which is why the counts are never summed into one number.

Try it

Paste a draft. See where it reads as machine-written.

This is the linter itself, running in your browser as you type. Your text goes nowhere.

24findings from 7 rules

Rates are per 1,000 words. Rules overlap, so no total score.

Click a finding to jump to it. No request leaves this page.

The difference

Same text. Only one of these tells you what to fix.

A detector

Nestled at the foot of the Ridgeline trail system, we've had a front-row seat as Pine Hollow has grown into a vibrant cycling destination, and we're proud to have played a part in that story.

Ridgeline isn't just a place to buy a bike — it's a gathering place for the local riding community.

Likely AIone verdict, whole document

It does not say which sentence, or why. (The shape of what a detector hands back, not a real run.)

Tells

Nestled at the foot of the Ridgeline trail system, we've had a front-row seat as Pine Hollow has grown into a vibrant cycling destination, and we're proud to have played a part in that story.

Ridgeline isn't just a place to buy a bike — it's a gathering place for the local riding community.

7:143pufferyweak
7:253pufferyweak
7:253vocabularymoderate
11:11negative-parallelismmoderate
11:44em-dashweak

A verdict is an accusation. A line number is a place to start editing.

Tested on its own corpus

Only one rule clears the gap.

For each rule: the lowest rate in any machine file minus the highest in any human file. Above zero, every machine file outscored every human one.

Observed 2026-09-19 with tells 0.1.0, 14 files. Reproduce: node bin/tells.mjs corpus --date 2026-09-19

The rates below are in-sample. The rules were revised after looking at the first corpus run, and one rule (rule-of-three) was taken out of the default set after a hostile review read this table and a set of eight human passages written for that review. The first run is kept unedited in studies/2026-09-19-corpus/first-run-results.json, and the study README lists every cell that moved, why, and what the demotion was for. No corpus text was changed at any point, and no machine text was edited after the linter first ran on it. The machine texts were also written by an author who had read the rule list. Treat this table as a demonstration of what the rules count, on files they were tuned against. The table runs every rule, including the two that are off by default, because it is the evidence for why they are off.

The machine samples were written by the same model family that built the linter; rates in this table describe these files and are not an accuracy claim about any detector, including this one.

What Tells cannot do.

  1. Tells cannot determine authorship.
  2. No single rule is evidence on its own; the guide this draws on says the same.
  3. Seven detectors flagged an average of 61% of TOEFL essays by non-native English writers as machine-written (Liang et al. 2023); surface features are not origin.
  4. This report does not make text undetectable and does not try to.

The figure is from Liang et al., GPT detectors are biased against non-native English writers, Patterns, 2023, arXiv:2304.02819.

It gives no probability and no score. It does not rewrite anything. A person can write every pattern here, and a model can write none of them.

Use it

One command, nothing to install.

It works like a code linter: named rules, a line and column for every finding, and a failing exit when you ask for one.

# check a file
npx github:CandyFlex/tells draft.md

# fail a build on chat leftovers
npx github:CandyFlex/tells draft.md --fail-on strong

# an annotated page you can read
npx github:CandyFlex/tells render draft.md --out report.html

Not on npm yet: npm view tells returned E404 (not in this registry) on 2026-09-19, so this runs it straight from the repository.

Formats
text, json, md, sarif
In CI
Exits non-zero once --fail-on is met
Requires
Node 20 or newer. No dependencies. MIT.
Rules
Every rule, its sources and its false positives: the rules page