Paste a git diff. Only the added lines are read, the strings people will see are pulled out, and each one is checked against your copy rules and your own regex rules.
A UI copy linter reads only the lines a diff adds, pulls out the strings people will see, and flags dashes, exclamation marks, Title Case, banned words and quote mix-ups in them. Removed lines and unchanged context lines are never reported, so an old problem in a file you touched does not block your change. The strings it takes are JavaScript and TypeScript string literals and template literals, JSX text between tags, and the values of title, alt, aria-label, placeholder, label and a few other copy attributes. It skips import paths, class names, test ids, URLs, file names, selectors, object keys and words that look like identifiers (a lower case word such as save, or camelCase). A single capitalised word such as Save or Cancel is kept. For a template literal, each ${...} is replaced with {} before checking.
The house style follows the Yolo Picker copy guide: no em or en dash in prose (a number range written with an en dash, as in pages 10 to 20, is left alone), no exclamation mark, no Title Case in a sentence, and the banned phrases of the build (the nine listed in the copy guide), plus filler like leverage, powerful and robust. Plain keeps only the common checks: two or more spaces between words, a trailing space, and quote consistency. Quotes are judged across the whole diff: curly quotes and straight quotes in the same string are flagged, and when strings use both styles, the less used style is flagged. You can edit the list of extra banned words or brands and the list of gendered terms (guys, chairman, he or she and others), and the names that Title Case should keep, such as Yolo Picker. A term matches whole words in any case, and an ending such as s, ed or ing still counts. Each finding gives the file, the line in the new file, the string, the rule and, where it can, a rewritten string.
The sample diff adds 6 user-facing strings to one file and also adds an import path and a className, which are skipped. The Title Case string Pay Now With Saved Card is suggested as Pay now with saved card. The string that begins Payment received has an em dash and an exclamation mark, so it gets 2 findings. The string that begins Charging has a double space. The string that begins We couldn't take the payment mixes a curly and a straight apostrophe. The JSX text Leverage your saved card, guys hits a banned word and a gendered term, and the title attribute Powerful one-click checkout hits a banned word. That is 8 findings from the rules, and 9 with the sample custom rule that matches the word checkout. Custom rules are lines of the form name = pattern, optionally followed by => and a suggestion. A pattern is a JavaScript regular expression, case-insensitive unless you write it as /pattern/flags. They run in a background worker that is stopped after 1.5 seconds, patterns that repeat a repeat are refused (this includes a repeated group with a choice inside, such as (cat|dog)+, even when it is safe: write cat|dog instead), and at most 10 rules of 200 characters are used.
This is a scanner, not a parser. It reads each hunk on its own, so a string or JSX block that opens above the first line of a hunk can be misread, and JSX is only recognised in JavaScript and TypeScript files. Other C-style languages (Java, Kotlin, Swift, Go, Rust, C#, PHP) and Python and Ruby are read for string literals only. Markdown, JSON, CSS, HTML and other files in a diff are skipped. If you paste code that is not a diff, every line counts as added. Input is limited to 1,000,000 characters, 5,000 strings and 2,000 findings. An AI agent can open this page with a diff already in the first box using #input= followed by the URL-encoded diff. The text is processed in your browser and not uploaded; only your option choices are saved.
Run git diff main...HEAD (or copy the diff from the pull request) and paste it. Only lines that start with + are read, so a 40-line change in a 900-line file reports on those 40 lines. Unchanged lines around them are used only to keep the scanner in step.
It was probably skipped as code: an import path, a className, a data-testid, a URL, an object key such as "id" or a lower case word like save. Strings with a space, a capital first letter or ending punctuation are kept, and so are title, alt, aria-label, placeholder and label values. A file type such as .md or .json is skipped as a whole.
No. An en dash between two digits, as in a page range, is left alone. An en dash or an em dash anywhere else in a string is flagged in the house style, with a comma suggested in its place.
For a plain word, add it to Extra banned words, for example Acme Cloud, leverage => use. For a pattern, write a custom rule line such as no-ellipsis = \.{3} => use … instead. A line starting with # is ignored, and a rule that is invalid or unsafe is dropped with a notice.
Yes. Paste code with no @@ hunk headers and every line counts as added, with line numbers from 1. That works for one JSX component or a list of strings, but a long file is better checked as a diff of what changed.
No. The text is processed in your browser, in this tab, and no server receives it. Your option choices are saved in this browser, the diff and your custom rules are not. Findings quote the strings, so check them before you paste them into a public issue.