Basilisk
The open-source Python language server.
Complete language server, type checker, debugger, and profiler — strict by default.
VS Code, Cursor & Windsurf (Open VSX) • Zed • Neovim. Built in Rust — single binary, no runtime.
Website •
Install •
Quick Start •
Rules •
Refactoring •
Compare
---
## 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-E0029)
| Code | Triggers when |
|------|---------------|
| `BSK-E0010` | Import cannot be resolved |
| `BSK-E0011` | Explicit `Any` annotation, or a return type mismatch |
| `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. a numeric literal used as a type) |
| `BSK-E0025` | Override method is missing the `@override` decorator |
| `BSK-E0026` | `TypeVar` declared with a single constraint |
| `BSK-E0027` | Duplicate `TypeVar` in a `Generic[...]` base |
| `BSK-E0029` | Method defined inside a `TypedDict` class |
These are the most common rules. Basilisk ships **151 diagnostic codes** in total (146 errors, 5 warnings) — see the [complete diagnostic reference](https://www.basilisk-python.dev/docs/rules/) (generated from the checker source by `scripts/gen_rules_reference.py`).
---
## Refactoring
Basilisk ships a suite of refactoring code actions — available via the lightbulb (code actions) menu in VS Code, Cursor, and Windsurf (via Open VSX), plus Zed and Neovim. No extra extensions required.
| Action | Kind | What it does |
|--------|------|-------------|
| **Extract variable** | `refactor.extract` | Extract expression into a named variable |
| **Extract variable (replace all)** | `refactor.extract` | Replace all identical occurrences |
| **Extract constant** | `refactor.extract` | Extract to module-level `SCREAMING_SNAKE` constant |
| **Extract function** | `refactor.extract` | Extract selected statements into a new function |
| **Inline variable** | `refactor.inline` | Replace variable with its value, delete assignment |
| **Inline function** | `refactor.inline` | Replace call with function body (single-expression) |
| **Move to new file** | `refactor.move` | Move class/function to a new file, leave import behind |
| **Move to existing file** | `refactor.move` | Move class/function to a chosen file via command |
| **Rename symbol** | — | Scope-aware rename with keyword arg, `self.attr`, docstring, and `__all__` updates |
| **Remove parameter** | `refactor.rewrite` | Remove parameter from function + all call sites |
| **Add parameter** | `refactor.rewrite` | Add `new_param=None` to function signature |
| **Sort parameters** | `refactor.rewrite` | Alphabetically sort parameters (keeps `self`/`cls` first) |
| **Implement abstract methods** | `refactor.rewrite` | Generate method stubs for abstract base class |
| **Convert Union/Optional** | `refactor.rewrite` | `Union[X, Y]` ↔ `X \| Y`, `Optional[X]` ↔ `X \| None` |
| **Convert constructs** | `refactor.rewrite` | f-string ↔ `.format()`, `dict()` ↔ `{}`, `list()` ↔ `[]`, ternary ↔ if/else, NamedTuple class ↔ functional |
Extract function detects async functions, methods (`self`/`cls`), and rejects selections containing `yield`, `break`, or `continue`.
---
## 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.
> **Pipeline:** source text → parser → AST → resolver → scopes → checker → diagnostics
>
> **Incremental:** `basilisk-db` caches ASTs and resolved modules by content hash so only changed files re-run the pipeline.
### 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 and use-before-assignment | 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 |
### LSP and infrastructure
| Crate | What it does | Status |
|-------|-------------|--------|
| [basilisk-lsp](crates/basilisk-lsp/) | LSP server — diagnostics, hover, go-to-def, code actions, refactoring, debugging | Working |
| [basilisk-db](crates/basilisk-db/) | Salsa-based incremental computation for <10ms latency | Working |
| [basilisk-config](crates/basilisk-config/) | Configuration parsing (`pyproject.toml`, `basilisk.json`) | Done |
| [basilisk-stubs](crates/basilisk-stubs/) | Bundled type stubs (typeshed) — no internet needed | Working |
| [basilisk-uv](crates/basilisk-uv/) | uv package manager integration for the LSP | Working |
| [basilisk-common](crates/basilisk-common/) | Shared constants and types — zero deps, WASM-compatible | Done |
| [basilisk-test-utils](crates/basilisk-test-utils/) | Shared E2E test helpers | Done |
### Future capabilities
| Crate | What it does | Status |
|-------|-------------|--------|
| [basilisk-mojo](crates/basilisk-mojo/) | Mojo-inspired ownership/immutability analysis (`Borrowed`, `InOut`, `Owned`) | Phase 4 |
| [basilisk-compiler](crates/basilisk-compiler/) | Compiles typed Python to native code | Future |
| [basilisk-plugin](crates/basilisk-plugin/) | WASM plugin host for Django, Pydantic, SQLAlchemy type extensions | Phase 5 |
### Editor extensions
| Extension | Editor | Status |
|-----------|--------|--------|
| [vscode-extension](vscode-extension/) | VS Code | Working |
| [basilisk.nvim](basilisk.nvim/) | Neovim 0.10+ | Working |
| [basilisk-zed](basilisk-zed/) | Zed | Phase 2 |
---
## 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.
Built by [NIMBLESITE PTY LTD](https://www.nimblesite.co).