Basilisk

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).