AI speak patterns, part 1
Built from the packs in hooks/lib/patterns. Each section names its own source.
Phrase patterns are case-insensitive. The left column holds the flagged text, the right column the fix the hook prints.
| Category | Label | Pack | Presets | File |
|---|---|---|---|---|
claude-tells | Claude tells | backtick-branches, claude-tells, closing-offer | default, ryan, technical, all | ai-speak-patterns.md |
british-spelling | British spelling | british-spelling | ryan, all | ai-speak-patterns.md |
chatbot | chatbot phrases | chatbot | default, ryan, technical, minimal, all | ai-speak-patterns.md |
closers | closers | closers | default, ryan, technical, all | ai-speak-patterns.md |
contrast | contrast frames | contrast | default, ryan, technical, all | ai-speak-patterns.md |
copula | interpreting verbs | copula | ryan, ste, all | ai-speak-patterns.md |
elegant-variation | elegant variation | elegant-variation | ryan, all | ai-speak-patterns.md |
false-ranges | false ranges | false-ranges | default, ryan, technical, all | ai-speak-patterns.md |
filler | filler | filler | default, ryan, technical, all | ai-speak-patterns.md |
formatting | formatting | formatting | default, ryan, all | ai-speak-patterns.md |
hedging | hedging | hedging | ryan, ste, all | ai-speak-patterns.md |
inflation | significance inflation | inflation | default, ryan, technical, all | ai-speak-patterns-2.md |
lexical-diversity | lexical diversity | lexical-diversity | statistical, all | ai-speak-patterns-2.md |
negative-parallelism | negative parallelism | negative-parallelism | default, ryan, technical, all | ai-speak-patterns-2.md |
outline-conclusion | outline-restating conclusions | outline-conclusion | ryan, all | ai-speak-patterns-2.md |
overgeneralization | overgeneralization | overgeneralization | default, ryan, technical, all | ai-speak-patterns-2.md |
paragraph-coherence | paragraph coherence | paragraph-coherence | ryan, statistical, all | ai-speak-patterns-2.md |
parallel-bullets | parallel bullets | parallel-bullets | ryan, all | ai-speak-patterns-2.md |
passive-voice | passive voice | passive-voice | ryan, statistical, all | ai-speak-patterns-2.md |
promotional | promotional language | promotional | default, ryan, technical, all | ai-speak-patterns-2.md |
punctuation-patterns | punctuation patterns | punctuation-patterns | statistical, all | ai-speak-patterns-2.md |
rare-words | rare word usage | rare-words | statistical, all | ai-speak-patterns-2.md |
readability-grade | readability grade | readability-grade | ryan, statistical, all | ai-speak-patterns-2.md |
rule-of-three | rule of three | rule-of-three | ryan, all | ai-speak-patterns-2.md |
sentence-variation | sentence variation | sentence-variation | ryan, statistical, all | ai-speak-patterns-2.md |
ste | simplified technical english | ste | ste, all | ai-speak-patterns-2.md |
structure | openers and frames | structure | default, ryan, technical, all | ai-speak-patterns-2.md |
superficial-analysis | superficial analysis | superficial-analysis | ryan, all | ai-speak-patterns-2.md |
sycophancy | sycophancy | sycophancy | default, ryan, technical, minimal, all | ai-speak-patterns-3.md |
terminal-punctuation | terminal punctuation uniformity | terminal-punctuation | statistical, all | ai-speak-patterns-3.md |
transition-density | transition density | transition-density | ryan, statistical, all | ai-speak-patterns-3.md |
transitions | transitions | transitions | default, ryan, technical, all | ai-speak-patterns-3.md |
undue-emphasis | undue emphasis | undue-emphasis | ryan, all | ai-speak-patterns-3.md |
vague-attribution | vague attribution | vague-attribution | default, ryan, technical, all | ai-speak-patterns-3.md |
vocabulary | AI frequency words | vocabulary | default, ryan, technical, all | ai-speak-patterns-3.md |
word-frequency | word frequency | word-frequency | statistical, all | ai-speak-patterns-3.md |
wordiness | wordiness | wordiness | ryan, ste, all | ai-speak-patterns-3.md |
ai-attribution | AI attribution trailer | ai-attribution | default, ryan, technical, minimal, git, all | ai-speak-patterns-3.md |
ai-identity | AI author identity | ai-identity | default, ryan, technical, minimal, git, all | ai-speak-patterns-3.md |
ai-tool-mention | AI tool mention | ai-tool-mention | default, ryan, technical, git, all | ai-speak-patterns-4.md |
benefit-tail | benefit tail | benefit-tail | ryan, technical, git, all | ai-speak-patterns-4.md |
canned-review | canned review | canned-review | default, ryan, technical, git, all | ai-speak-patterns-4.md |
file-narration | file narration | file-narration | ryan, technical, git, all | ai-speak-patterns-4.md |
praise-sandwich | praise sandwich | praise-sandwich | ryan, git, all | ai-speak-patterns-4.md |
hidden-characters | hidden characters | hidden-characters | default, ryan, technical, git, all | ai-speak-patterns-4.md |
smart-punctuation | smart punctuation | smart-punctuation | default, ryan, technical, all | ai-speak-patterns-4.md |
unicode-glyphs | unicode glyphs | unicode-glyphs | default, ryan, technical, all | ai-speak-patterns-4.md |
claude-tells
Presets: default, ryan, technical, all. Source: Measured on 1.29M words of Opus 5.5 Claude Code replies against 1.13M words of npm READMEs and 87K words of pre-2023 commits; Anthropic’s Opus 5.5 and Fable 5.1 prompting guides; Anthropic’s Opus 5.5 prompting guide lists “an offer to carry on with something unless the user would prefer otherwise” as a habit to suppress; 1.93 per 10,000 words in Opus 5.5 replies, none in the baselines.
Phrasing that Claude 5.x models write far more often than people do.
| Flagged | Fix |
|---|---|
| Phrasing that Claude 5.x models write far more often than people do. | branches = ["main","master","dev","develop","development","staging","stage","production","prod","release","trunk","next","beta","canary"] |
the doc admits, the code pretends, the test lies | say what the text states: the doc says X |
admits it, concedes as much | say what the text states |
Existing bug, not a regression | cut the not X tail, the label already says it |
the big migration, the huge refactor | cut the size word, or give the size |
covers this path, hits that path | name the branch: the function, condition, or flag |
on purpose | put intentionally before the verb, or give the reason |
, by design., , as intended. | cut the tag, or give the reason |
, with your low call volume note | put the aside in parentheses, or make it a clause |
quietly | cut it, or say what is not logged or reported |
earns its keep, earns its place | say what it does |
Want me to ...? or Do you want me to ...? at the end of the text | cut the offer, or name the step that needs approval |
| Flagged (tier 2) | Fix |
|---|---|
a real bug, the real gap, the real story | cut real |
reads well, reads cleanly | say what works |
Flags a branch name in backticks after from, into, onto, against, or a similar word, or before branch. Prose files stay out of scope: docs often set branch names as code by convention. Set options.branches to match the repo’s branch names.
Every tier-1 row fired at most 0.02 times per 10,000 words in the README and commit baselines. The status-label row needs a verbless fragment at the start of a line or sentence, so This is a known limitation, not a bug stays with the contrast pack. The closing offer lives in closing-offer.json so it can be excluded alone.
Fires only when the offer is the last sentence of the text. A question followed by a reason, such as Do you want me to delete it? It has two unmerged commits., stays unflagged. A setup that asks before every test run can list closing-offer in excludePacks.
british-spelling
Presets: ryan, all. Source: Measured on Claude Code transcripts: Opus 5.5 wrote behaviour in 31% of uses, labelled in 58%, and grey in 77%; npm READMEs used them in 11%, 20%, and 30%.
British spellings in text that otherwise uses American English.
| Flagged | Fix |
|---|---|
behaviour, behaviours, behavioural | behavior |
colour, colours, coloured | color |
favour, honour, neighbour, labour, flavour, humour, rumour, harbour, armour, vapour | drop the u: favor, honor, neighbor |
labelled, modelling, travelled, signalled, levelled, channelled | one l: labeled, modeling |
centre, metre, litre, fibre, theatre | -er: center, meter |
-ise and -isation forms such as normalise, initialised, organisation | -ize, -ization |
analyse, analysed, analysing | -yze: analyze |
grey, greys, greyed, greying | gray |
whilst | while |
amongst | among |
programme, programmes | program |
licence[ds]? | license |
defence, offence | defense, offense |
catalogue[ds]? | catalog |
artefact, artefacts | artifact |
spelt, learnt | spelled, learned |
per cent | percent |
A repo that writes British English lists british-spelling in excludePacks. cancelled, judgement, acknowledgement, towards, and dialogue are left out because American writers use them too. analyses is left out because it is also the plural of analysis. Elixir’s @behaviour attribute sits in code, which the scan skips.
chatbot
Presets: default, ryan, technical, minimal, all. Source: avoid-ai-writing by Conor Bronsdon (MIT) and Ryan Yannelli’s house rules.
Assistant boilerplate that belongs to a chat window.
| Flagged | Fix |
|---|---|
certainly!, absolutely!, of course! (sentence-initial) | cut |
I hope this helps, hope this helps | cut |
great question, excellent question, good question | cut |
feel free to reach out, feel free to ask, feel free to contact, feel free to let me know | cut |
don't hesitate to | cut |
let me know if you, let me know if there, let me know if that, let me know if this, let me know if it | cut |
happy to help | cut |
I'd be happy to, I would be happy to | cut |
as an AI, as an AI language model | cut |
as of my last update, as of my last training, as of my last knowledge, as of my latest update, as of my latest training, as of my latest knowledge, knowledge cutoff | cut |
I don't have access to real-time | cut |
As a language model | cut |
I am an AI | cut |
I'm just an AI | cut |
As an assistant | cut |
I cannot browse | cut, state the limit |
I don't have personal opinions | cut |
I'm unable to browse, verify this, and the like | state what you can do |
please note that | state the fact |
Kindly + verb | imperative without “kindly” |
closers
Presets: default, ryan, technical, all. Source: avoid-ai-writing by Conor Bronsdon (MIT) and Ryan Yannelli’s house rules.
Endings that restate the text instead of stopping.
| Flagged | Fix |
|---|---|
Ultimately (sentence-initial) | cut |
As we move forward, Moving forward (sentence-initial) | cut |
in conclusion, in summary, to summarize, to sum up | cut, end on the last fact |
at the end of the day, only time will tell, stay tuned, exciting times, happy coding, thank me later | cut |
the future looks bright, the future is bright, the possibilities are endless | cut |
one thing is certain, one thing is clear | state it |
worth reading, worth a look, worth a read, worth exploring, worth checking out, worth your time | say why |
the journey begins, the journey continues, the journey is just beginning, the adventure begins, the adventure continues, the adventure is just beginning | cut |
the bottom line, the key takeaway, the takeaway here | state it |
I look forward to, we look forward to | cut, or state the next step and date |
contrast
Presets: default, ryan, technical, all. Source: avoid-ai-writing by Conor Bronsdon (MIT), Ryan Yannelli’s house rules, and Wikipedia:Signs of AI writing.
Frames that define the subject by what it is not.
| Flagged | Fix |
|---|---|
it's not X, it's Y (also it is not, this is not, that's not, with just, only, about, merely, or simply inside) | state the positive claim |
isn't about X, it's about Y | state the positive claim |
not just X but Y (also not only, not merely, not simply) | state Y |
X, not Y as the tail of a sentence, up to 3 words after not | write the claim as “X does Y” |
less about X, more about Y | state the positive claim |
instead of X, it's Y | state the claim directly |
isn't X. It's Y. | combine into one claim |
A bare rather than is not flagged: it is ordinary technical English. The cross-sentence form stops at a second negation, which the negative-parallelism pack owns.
copula
Presets: ryan, ste, all. Source: avoid-ai-writing by Conor Bronsdon (MIT) and Ryan Yannelli’s house rules.
Verbs that interpret the subject instead of naming what it does.
| Flagged | Fix |
|---|---|
serves as, acts as, stands as, functions as | is, or the literal action |
boasts | has |
the source of truth | say what reads it |
the key constraint | name the constraint |
the path forward | the next step, named |
this ensures | say what happens |
plays a key role, plays a vital role, plays a critical role, plays a central role, plays a significant role, plays an important role | say what it does |
designed to help, designed to ensure, designed to provide, designed to enable, designed to make | say what it does |
State the fact instead of interpreting it.
elegant-variation
Presets: ryan, all. Source: Fowler via Wikipedia:Elegant variation and Wikipedia:The problem with elegant variation.
Rotating synonyms for one referent instead of repeating the name.
| Flagged | Fix |
|---|---|
aforementioned | name it again |
the eponymous | name it directly |
self-titled | name it directly |
the titular | name it directly |
of the same name | name it directly, or cut |
| Rotating synonyms for one referent instead of repeating the name. | minWords = 200, minSynonyms = 3 |
The counting half needs 200 words and three synonyms from one cluster, each used once. Repeating a word turns the paragraph off.
false-ranges
Presets: default, ryan, technical, all. Source: tropes.fyi directory and the agent-toolkit signs-of-ai-writing mirror.
A “from X to Y” span whose endpoints share no real scale.
| Flagged | Fix |
|---|---|
everything from X to Y | list the specific items |
anything from X to Y | list the specific items |
runs the gamut from X to Y | name the actual range |
the full spectrum of X from A to B | name the actual range |
from A to B to C | split into a list |
A plain two-point range stays unflagged, so numeric and version ranges pass. The chained form skips a span that holds a digit or a parenthesis, and skips a third to that opens a purpose clause, so from 0 to 1000 to pick a victim and from left to right to reduce the list stay clean. Only the marked forms and chained word spans report.
filler
Presets: default, ryan, technical, all. Source: avoid-ai-writing by Conor Bronsdon (MIT) and Ryan Yannelli’s house rules.
Openers and asides that carry no fact.
| Flagged | Fix |
|---|---|
honestly (sentence-initial) | cut |
genuinely, truly, quite frankly, to be honest, real talk, at its core, here's the thing | cut |
let's be clear, let's be honest | cut |
a genuine improvement, a genuine step, a genuine shift, a genuine change, a genuine concern, a genuine interest | cut |
it's important to note, it's important to remember, it's important to understand, it is important to note, it is important to remember, it is important to understand | state the point |
worth flagging, worth mentioning, worth remembering | state the point |
let's unpack, let's dive in, let's explore, let's take a look, let's break this down, let's break it down, let's examine, let's get started | start with the point |
straightforward | cut, or say what the steps are |
a powerful example | the example |
this highlights, this speaks to | state the fact |
the broader takeaway | state it |
a reminder that, a reminder of, a stark reminder that, a stark reminder of, a powerful reminder that, a powerful reminder of, a timely reminder that, a timely reminder of, an important reminder that, an important reminder of | state the fact |
I recently had the pleasure of | say what happened |
whether you're X or Y | name the audience or cut |
formatting
Presets: default, ryan, all. Source: avoid-ai-writing by Conor Bronsdon (MIT), Ryan Yannelli’s house rules, Pangram signs-of-ai-writing.
Emoji and bold runs used as structure.
| Flagged | Fix |
|---|---|
| an emoji in a heading | remove |
| an emoji ending a line | remove |
| an emoji starting a line | remove |
| an emoji before a colon | remove |
A code check in ai-patterns.mjs reports three or more bold spans in one paragraph or list item; no pattern row covers it. The pack applies one scope to every pattern, so the line-initial emoji rule also runs on commit messages and flags a gitmoji prefix such as a sparkle before feat:. A repo on that convention puts the glyph in allowList.patterns, or ships its own formatting pack with a scope that leaves out commit.
hedging
Presets: ryan, ste, all. Source: avoid-ai-writing by Conor Bronsdon (MIT) and Ryan Yannelli’s house rules.
Qualifiers that leave the claim unowned.
| Flagged | Fix |
|---|---|
Note that (sentence-initial) | cut, state the fact |
perhaps, arguably | cut, or commit |
may eventually, could eventually | say when |
could potentially, may potentially, might potentially, might possibly, could possibly | can, or cut |
to be clear, in general | cut |
keep in mind | cut, state the fact |
generally, typically | cut, or name the exception |
in some cases, in many cases, in most cases | name the case |
somewhat, to some extent | cut, or measure |
it could be argued, it could be said, it may be argued, it may be said, it might be argued, it might be said | state the claim |
potentially (bare) | cut |