crate-ci/typos: a source code spell checker built on a correction list, not a dictionary
Source code spell checker
At a glance
- What is it?
- typos is a Rust CLI that finds misspellings in source trees and rewrites them in place. Its design bets on a curated list of known corrections instead of a general dictionary, which keeps false positives low enough to run on pull requests.
- Who is it for?
- Adopt typos if you want spell checking that can run unattended on pull requests and you are willing to maintain a _typos.toml for names, acronyms and localized files. Do not adopt it if you expect a general-purpose spell checker that catches any English mistake; the README states it keeps a list of known corrections rather than a list of valid words, so unknown typos stay silent.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What crate-ci/typos solves, and who it is written for
Spell checkers built for prose do not survive contact with a source tree. A dictionary-based checker flags every identifier, hash and acronym it does not recognize, and the usual response is to turn it off. typos takes the opposite position. The README describes it as a source code spell checker that is "fast enough to run on monorepos" and has "low false positives so you can run on PRs". Those two claims define the audience: teams with large repositories who want a check in continuous integration that does not require a human to triage a wall of noise.
The trade-off is explicit in the README. typos maintains a list of known typo corrections rather than a list of valid words. A dictionary checker guesses intent by finding the closest-looking word and asks the user to confirm. typos only reports what it already knows to be wrong, which means it will miss typos it has never seen. The README points to the design document for the reasoning behind that choice. For a repository where a missed typo is a minor embarrassment and a false positive is a blocked build, the trade is reasonable. For documentation, marketing copy or anything where full English coverage matters, it is the wrong tool.
The mechanism: identifiers, words, and a correction list
The pipeline has three visible stages, and the README exposes a flag for each. typos walks the files it decides to check, splits their contents into identifiers (groupings of words), and then reduces those identifiers to individual words. The debugging section names the commands that print each stage: typos --files, typos --identifiers and typos --words. When a correction is not applied, the FAQ walks through the same three questions in order: does the file appear in --files, does the identifier appear in --identifiers, does the word appear in --words. That ordering is the diagnostic model the project expects users to follow.
The heuristics sit between the identifier and word stages. The README notes that a word may be skipped because it looks like a hash or because it follows a backslash escape, which the project treats as an unambiguous signal. If a word does survive into the word stage and still is not corrected, the README's answer is that typos simply does not know about it yet. There is no fuzzy matching step to fall back on. Ambiguity is handled by refusing to act: when multiple corrections are possible, the README states that typos reports the ambiguity and moves on rather than choosing.
Installing typos and running it on a real tree
The README lists four installation routes. Prebuilt binaries are published on the releases page and can be installed with gh-install. Rust users can install from crates.io. Homebrew, Conda and Pacman packages also exist. The cargo route pins the lockfile, which is what you want for reproducible CI images:
cargo install typos-cli --lockedThe Homebrew formula is a single command and is the shortest path on macOS:
brew install typos-cliOnce installed, running the binary with no arguments in a repository reports the typos it finds. This is the form the README calls the most common usage:
typosTo apply the corrections rather than just list them, pass --write-changes or its short form -w. The README warns that when a correction is ambiguous, typos reports it to the user and skips it, so a run of -w is not guaranteed to leave zero findings:
typos --write-changesFor a single file, you can pass the path directly and get a diff instead of a rewrite. This is the shape used by custom integrations:
typos dir/file --diffThe Dockerfile in the repository builds the CLI from source with cargo install --path ./crates/typos-cli and sets the entrypoint to typos with --help as the default command, so a container run with no arguments prints usage rather than scanning the working directory.
Suppressing false positives with _typos.toml
The configuration file is named _typos.toml, and the README's examples all use the [default] table. There are three distinct escape hatches, and they operate at different stages of the pipeline. extend-ignore-identifiers-re takes a regular expression and drops matching identifiers before they are split into words. extend-identifiers declares a whole identifier as its own valid spelling. extend-words declares a single word valid, which is how the README handles the surname "Teh".
[default]
extend-ignore-identifiers-re = [
"AttributeID.*Supress.*",
]
[default.extend-identifiers]
AttributeIDSupressMenu = "AttributeIDSupressMenu"
[default.extend-words]
teh = "teh"The value on the right-hand side is the valid spelling, so a word mapped to itself is left alone. Choosing between the three is a precision question: a regex covers a family of identifiers, a single identifier entry is narrower, and a word entry is the broadest because it applies everywhere that word appears. The README's own comments in the example suggest reaching for the regex only when the cost of fixing the underlying code is not worth it.
For localized content, the recommended pattern is to disable content checking per file type while still checking the file name. The example adds a glob to the [type.po] table and sets check-file to false. Running typos --type-list prints the configured file types, which is how you confirm the type name you are extending actually exists. When per-type control is not enough, the [files] table takes an extend-exclude list of globs, and files matching them are dropped entirely.
Where typos gets in the way
The correction-list design has a direct cost: typos cannot catch a misspelling it has no entry for. The README states this plainly in the FAQ, and it means the tool is a regression guard against known errors rather than an editor. A new contributor inventing a novel misspelling will pass the check.
The file-walking layer has its own sharp edges, and the README documents them as open issues rather than solved problems. If a file does not appear in typos --files, the FAQ points at two causes. One is files.extend-exclude, with a link to issue #593 for a known problem in that area. The other is files.ignore-vcs set to true combined with a file that is listed in .gitignore but still tracked by git; the FAQ links issue #909 and suggests explicitly allowing the file instead. Neither is presented as fixed.
There is also a class of ambiguity the tool refuses to resolve. When a misspelling has more than one plausible correction, typos reports it and moves on. That is safer than guessing, but it means --write-changes does not always produce a clean tree, and a CI job that expects zero output after a fix pass will need to handle the residue. Finally, the repository's own Cargo.toml sets rust-version to 1.95 and edition to 2024, so building from source requires a recent toolchain; the prebuilt binaries and package-manager routes avoid that constraint entirely.
How typos differs from a dictionary-based checker
The README links to a comparison document, and the FAQ states the contrast directly: most spell checking UIs people use maintain a known list of valid words and guess intent by proximity, with the user verifying corrections. typos inverts that. It keeps a known list of corrections and stays silent otherwise.
That difference shows up in daily operation. A dictionary checker on a monorepo produces a long list of unfamiliar identifiers and asks you to accept or reject each one; the accepted set becomes project state. typos produces a shorter list of things it is confident about, and the project state you maintain is a set of exceptions in _typos.toml for the cases where the confidence is misplaced, such as names and acronyms. The README's example of suppressing the surname "Teh" is exactly this kind of exception.
The practical consequence is that the two tools fail in opposite directions. A dictionary checker fails loudly and needs tuning to become quiet. typos is quiet by default and needs an explicit correction entry to become louder. If your goal is to catch every English mistake in prose files, a dictionary-based checker is the better fit and typos will disappoint. If your goal is a check that can run on every pull request without a triage queue, the correction-list approach is what makes that possible.
Maintenance, licensing and upgrade cost
The repository is not archived, and the last push was on 2026-09-19. Releases are frequent: v1.50.0 on 2026-08-28, v1.50.1 on 2026-09-01 and v1.50.2 on 2026-09-15. The setup.py file in the repository pins TYPOS_VERSION to 1.50.2, so the Python packaging shim tracks the CLI version. A CHANGELOG.md sits at the repository root, which is where release-level changes should be read before upgrading.
Licensing is dual: MIT or Apache 2.0, matching the workspace license field in Cargo.toml and the LICENSE-MIT and LICENSE-APACHE files at the root. The README states the dual licence at the top. Choosing between the two is a downstream decision, and Apache 2.0 carries an explicit patent grant that MIT does not; this is a description of the terms, not legal advice.
Upgrade risk is concentrated in two places. The dictionary of known corrections changes between releases, so a version bump can introduce new findings in a tree that was previously clean. The config schema is published as config.schema.json at the repository root, which is the file to point an editor at for validation. For pinned CI, the cargo install line with --locked and the version-pinned setup.py both give a reproducible reference point.
Editorial conclusion
Adopt typos if you want spell checking that can run unattended on pull requests and you are willing to maintain a _typos.toml for names, acronyms and localized files. Do not adopt it if you expect a general-purpose spell checker that catches any English mistake; the README states it keeps a list of known corrections rather than a list of valid words, so unknown typos stay silent. Before rolling it out, run typos --files and typos --dump-config - on your repository to confirm which files are walked and which config is actually in effect.
Frequently asked questions
How do I use crate-ci/typos to fix spelling mistakes?
Run typos with no arguments to list findings, or typos --write-changes (short form -w) to apply corrections in place. When a correction is ambiguous, typos reports it and skips it rather than guessing.
How do I install the typos CLI?
The README lists prebuilt binaries from the releases page via gh-install, cargo install typos-cli --locked, brew install typos-cli, conda install typos and sudo pacman -S typos. The repository also contains a Dockerfile that builds the CLI with cargo install --path ./crates/typos-cli.
Why did typos not correct a misspelling in my project?
The FAQ suggests checking three commands in order: typos --files to confirm the file is walked, typos --identifiers and typos --words to confirm the text reaches the word stage. If the word appears there, typos simply does not know about that correction yet.
How do I stop typos from flagging a name or acronym?
Add an entry to _typos.toml. The README shows extend-ignore-identifiers-re for regex patterns, extend-identifiers for a whole identifier, and extend-words for a single word, all under the [default] table.
Can typos check localized files without flagging their contents?
Yes. The README shows adding a glob to a type table such as [type.po] with extend-glob and setting check-file to false, which keeps the file name checked while skipping its contents. Run typos --type-list to see the configured file types.
How do I see which config typos is actually using?
Run typos --dump-config - to print the effective configuration. The FAQ points to this command when a file is not being checked, and it is the first step before investigating the [files] table.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/crate-ci-typos)