Basilisk
Strict-by-default Python type checker. No escape hatches.
Every parameter typed. Every return declared. Any is always explicit.
Built in Rust — ships as a single binary, no runtime required.
Website •
Install •
Quick Start •
Rules •
Spec
---
## Try it
The `examples/` folder has ready-to-go Python files:
```sh
cargo run -- check examples/bad.py # everything flagged
cargo run -- check examples/good.py # clean
cargo run -- check examples/mixed.py # some errors, some clean
cargo run -- check examples/ # all three at once
```
---
## Quick example
| Basilisk rejects this |
Fixed |
|
```python
def greet(name):
return "Hello " + name
```
|
```python
def greet(name: str) -> str:
return "Hello " + name
```
|
```
error[BSK-E0001]: Missing parameter type annotation for `name`
--> greet.py:1:10
|
1 | def greet(name):
| ^^^^
|
= help: Add a type annotation: `name: `
= see: https://www.basilisk-python.dev/errors/BSK-E0001
error[BSK-E0002]: Missing return type annotation
--> greet.py:1:1
|
1 | def greet(name):
| ^^^^^^^^^^^^^^^^
|
= see: https://www.basilisk-python.dev/errors/BSK-E0002
```
---
## Rules
All rules are on by default. There is no way to relax them globally.
### Annotation rules (E0001-E0005)
| Code | Triggers when |
|------|---------------|
| `BSK-E0001` | Function parameter has no type annotation |
| `BSK-E0002` | Function is missing a return type annotation |
| `BSK-E0003` | Variable assignment has no type annotation |
| `BSK-E0004` | `*args` or `**kwargs` has no type annotation |
| `BSK-E0005` | Class attribute has no type annotation |
### Type correctness (E0010-E0025)
| Code | Triggers when |
|------|---------------|
| `BSK-E0010` | Import from a module with no type stubs |
| `BSK-E0011` | Implicit `Any` — type cannot be inferred |
| `BSK-E0012` | Argument type does not match parameter type |
| `BSK-E0013` | Return type does not match declared return type |
| `BSK-E0014` | Assignment type does not match declared variable type |
| `BSK-E0015` | Wrong number of type arguments (e.g. `list[int, str]`) |
| `BSK-E0016` | Method override has incompatible signature |
| `BSK-E0017` | Class variable override has incompatible type |
| `BSK-E0018` | Reference to an undefined name |
| `BSK-E0019` | Variable used before it is assigned |
| `BSK-E0020` | `@overload` group has no non-decorated implementation |
| `BSK-E0021` | Two `@overload` signatures overlap |
| `BSK-E0022` | Dict key type is not hashable |
| `BSK-E0023` | `match` statement is not exhaustive |
| `BSK-E0024` | Type expression is not valid (e.g. `int | 42`) |
| `BSK-E0025` | Override method is missing the `@override` decorator |
---
## Output format
Diagnostics use rustc-style output:
```
error[BSK-E0001]: Missing parameter type annotation for `data`
--> src/utils.py:14:5
|
14 | def process(data):
| ^^^^
|
= help: Add a type annotation: `data: `
= note: In Basilisk, all function parameters require explicit types
= see: https://www.basilisk-python.dev/errors/BSK-E0001
```
| Exit code | Meaning |
|-----------|---------|
| `0` | Clean — no errors |
| `1` | Type errors found |
| `3` | Internal error |
---
## Architecture
Basilisk is a Cargo workspace. Each crate owns one layer of the analysis pipeline.
| Crate | What it does | Status |
|-------|-------------|--------|
| [basilisk-parser](crates/basilisk-parser/) | Wraps `ruff_python_parser` to parse `.py` source into a typed AST | Done |
| [basilisk-resolver](crates/basilisk-resolver/) | Name resolution and scope analysis — catches undefined names (E0018) and use-before-assignment (E0019) | Done |
| [basilisk-checker](crates/basilisk-checker/) | Core type checker — implements all E0001-E0025 rules | Done |
| [basilisk-cli](crates/basilisk-cli/) | The `basilisk` binary — wires the full pipeline together | Done |
| [basilisk-db](crates/basilisk-db/) | Salsa-based incremental computation for <10ms latency | Phase 2 |
| [basilisk-lsp](crates/basilisk-lsp/) | LSP server via tower-lsp — diagnostics, hover, go-to-def | Phase 2 |
| [basilisk-mojo](crates/basilisk-mojo/) | Mojo-inspired ownership/immutability analysis (`Borrowed`, `InOut`, `Owned`) | Phase 4 |
| [basilisk-stubs](crates/basilisk-stubs/) | Bundled type stubs (typeshed + community) — no internet needed | Phase 5 |
| [basilisk-plugin](crates/basilisk-plugin/) | WASM plugin host for Django, Pydantic, SQLAlchemy type extensions | Phase 5 |
> **Pipeline:** source text → parser → AST → resolver → scopes → checker → diagnostics → CLI output
>
> **Incremental (Phase 2+):** `basilisk-db` caches ASTs and resolved modules by content hash so only changed files re-run the pipeline.
---
## Development
```sh
cargo build # build all crates
cargo test # run all tests
cargo clippy # lint (zero warnings policy)
cargo fmt # format
```
Rust 1.87+ required.
---
## License
MIT or Apache-2.0, at your option.
Built by [NIMBLESITE PTY LTD](https://www.nimblesite.co).