Open-source project
beartype/beartype avatar
beartype/beartype

beartype: the documentation moved, and the links did not

Unbearably fast near-real-time pure-Python runtime-static type-checker.

3,503 stars90 forksPythonMIT

At a glance

What is it?
beartype is a pure Python type checker that enforces hints at run time rather than in a separate pass, and its README is written at a volume most type checkers would not dare. Two things are worth reading past the jokes: the documentation was moved to a different host while every link inside the file still points at the old one, and the second code sample, which shows how to check other people's packages, stops halfway through a line.
Who is it for?
beartype fits code that ships type hints and runs in production, where a checker that only reports at development time misses the paths that matter, and the granularity claim is the reason to look at it. Three things to weigh.
Can I use it commercially?
Yes. MIT 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 last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The documentation host changed, and every link in the file predates the change

The most structurally useful sentence in this README is a status announcement.

The file says the documentation officially lives on GitHub Pages, gives the address, and calls it the Bearpedia. The justification offered is characteristically specific: the document you are reading used to be one monolithic file of roughly 316 KB that induced migraines in 22 per cent of the devops population, and for your safety that document no longer exists.

Now read the rest of the file with that in mind. Every link in the introduction, the positioning paragraph and the conclusion points at the readthedocs-hosted documentation: the FAQ, the standards page, the API index, the human-readable synopsis, the complexity discussion. The repository's recorded homepage points there too. Meanwhile the configuration file for the old host is still in the tree.

So the project has moved its documentation and left its own entry points pointing at the previous one. That is a small thing in isolation, and a genuinely annoying one for a reader, because the migration note and the links disagree and only one of them is current.

The practical rule is simple: trust the announcement, not the link bar.

One function call in your package's init module covers every submodule

The quickstart is two steps, and the second one is a single call.

Install it with the package manager:

bash
pip install beartype

Then call its package-level helper from the initialisation module of your own package. The file describes what that one call does: the checker now implicitly type-checks all annotated classes, all annotated callables, and all annotated variable assignments, across all submodules of that package.

That is the design decision worth understanding. Most run-time checkers are opt-in per function through a decorator, which means the coverage you get is the coverage you remembered to annotate. This one inverts it: you enable the package once, and everything annotated inside it is checked, including the parts you did not touch.

The cost of that choice is that the checking cost is no longer visible at the call site. You cannot read a function and know whether its hints are enforced, because the answer is set by a call in a different file. If you are reviewing code rather than writing it, that is the thing to look for.

Violations in your package raise, violations in other packages only warn

The second claim in the file is bigger, and its code sample is the one that stops halfway.

The idea is to reach past your own code. The file's framing is that your application depends on a sprawl of other packages, and asks how riddled with problems that code is. The answer is a pair of calls: one that checks your own package and raises on violations, and one that checks every installed package. In that mode, a violation inside your package raises an exception and a violation inside any other package only emits a warning.

That split is the whole design of the wider mode, and it is a good one, because a third-party package raising inside your application is indistinguishable from your own bug until you read the traceback. A warning keeps the signal and removes the blast radius.

The sample, however, is cut off. It shows the two imports and the first call, then stops on a fragment of two letters at the start of the second call, with no closing line. So the exact order and arguments of the two calls are not readable in the file, and anyone copying that snippet gets a syntax error rather than a hint about what was meant.

A configuration object is imported alongside the two helpers, which suggests the severity split is configurable, but the visible text does not say how.

Manual enforcement is one decorator, and its example stops mid-expression

For the case where you want a specific class or function checked rather than a whole package, the file points at what it calls a plethora of APIs and then demonstrates the narrowest one.

The demonstration starts a Python session, imports the decorator, and applies it to a function definition whose hints are the ordinary builtin generic syntax. That is the entire mechanism: a decorator that reads the hints off the object it wraps and enforces them when it is called.

Then the example stops mid-expression, inside a print statement whose format string and argument list are both unfinished. So the file shows you how to declare the checked function and not how it behaves.

What the surrounding text does say is worth keeping, because it is an admission about when to reach for this mode. The comment above it says to do it only if you want another repetitive stress injury, which is a fair description of decorating every function in a large codebase by hand.

So the two modes divide cleanly along that line: the decorator when you want one thing checked, the package call when you want everything checked. The file's own preference is the second.

No runtime dependencies, one test dependency, one documentation dependency

The dependency claims are specific enough to check, and they are the reason a checker like this is viable in a library.

The file states there are no runtime dependencies at all, one test-time dependency, and one documentation-time dependency. For a run-time checker, that matters more than it would for most libraries, because a type checker is something you put inside the import path of an application that already has an opinion about its dependency tree.

The documentation-time dependency is the interesting one, since the file links it to a separate documentation generator rather than to a Python package. That is consistent with the GitHub Pages migration described earlier, and it is a second piece of evidence for the same transition.

On compatibility, the claims are broad: portably implemented in Python 3, supporting all actively developed Python versions, all Python package managers, and multiple platform-specific package managers.

The performance claim is the one to treat as a promise rather than a measurement. The file says enforcement happens at the granularity of functions and methods in O of 1 non-amortized worst-case time with negligible constant factors, and it immediately acknowledges that if that sentence was unreadable jargon, there is a friendly FAQ for a human synopsis.

Three documentation directories and three checker configurations at the root

The tree is where the transition shows, because the artefacts of both tools are present at once.

There are two directories named for documentation, plus a third directory for a documentation generator, plus a README in the reStructuredText format alongside the Markdown one, plus a configuration file for the hosted documentation service and a configuration file for the new generator. So a reader looking for the docs will find at least four places that claim to be one of them.

The static analysis side is the same story. The root carries configuration files for two type checkers, a test framework and a multi-environment test runner, and it also carries directories named after the same four tools. Those directories are not duplicates of the libraries; they are where per-project integration lives, and having them beside the configuration files is the conventional layout. But it does mean the root lists eight entries where a newcomer expects four.

Two other entries are unusual enough to mention: an overrides directory at the root, and a coverage configuration in the file's older format alongside a codecov configuration in the modern one.

Three release candidates in seven weeks, each with a subtitle

The release history is the least technical thing in this repository and the most revealing about how the project works.

The three most recent releases are all candidates for the same version: the first candidate in early August 2026, the second in mid September, the third in late September. No final release appears among them, so the project has been sitting on a candidate line for about seven weeks.

Every one of those three has a subtitle in its release title, and the subtitles are jokes in the same register as the README. One promises that the bear will catch your codebase if it falls, one refers to a flying space turtle, and one is a declaration about glory. None of them tells you what changed, which means the changelog is where a reader has to go to evaluate a candidate.

That combination, candidate-only releases with decorative titles, is consistent with everything else in this repository: the tone is a deliberate part of the project, and the technical claims are made in the body text while the release notes carry the voice.

For anyone pinning a dependency, the practical point is the same as for most projects in this position: pin the candidate you tested, not the newest one.

Editorial conclusion

beartype fits code that ships type hints and runs in production, where a checker that only reports at development time misses the paths that matter, and the granularity claim is the reason to look at it. Three things to weigh. The guarantee is a complexity claim from the project, not a benchmark you can read here, so measure it on your own code before adopting it broadly. Enabling it across third-party packages means turning on checking for code you do not maintain, which changes failure behaviour for other people's bugs, so decide deliberately whether violations there raise or warn. And if you are new to the documentation, ignore the links in the README and go straight to the GitHub Pages site the file itself nominates as official.

Frequently asked questions

What does beartype do?

It enforces type hints at run time, at the granularity of functions and methods, against hints that follow the Python community's standards. The project describes this as happening in O of 1 non-amortized worst-case time with negligible constant factors.

How do I type-check a whole package with beartype?

Call its claw helper for your package from that package's initialisation module. The file says this one call type-checks all annotated classes, callables and variable assignments across all submodules of the package.

What happens when another package violates a type hint under beartype?

It emits a warning rather than raising, while violations inside your own package raise exceptions. The wider mode is reached by calling the package checker and the all-packages checker together, alongside a configuration object.

Does beartype have any dependencies?

The file states it has no runtime dependencies, only one test-time dependency, and only one documentation-time dependency.

Where is the beartype documentation?

The README says the documentation officially lives on GitHub Pages and names it the Bearpedia, while the repository homepage and the links inside the README still point at the readthedocs-hosted documentation.

Official sources

  1. beartype/beartype on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/beartype-beartype.svg)](https://hysenlabs.com/projects/beartype-beartype)