// basilisk — v0.1 alpha

The open-source
Pylance replacement.

Basilisk is a complete Python language server and VS Code extension that replaces Pylance and Pyright. Autocomplete, go-to-definition, hover info, refactoring, diagnostics, integrated debugging — everything you rely on, fully open source. Strict by default. Built in Rust.

Get Started GitHub
Full LSP Built in Rust <10ms incremental No Node.js MIT License
bad.py
def process(data):
    return data.upper()

class User:
    def __init__(self, name, age):
        self.name = name
        self.age  = age

    def greet(self):
        return f"Hello, {self.name}"
error[BSK-E0001]: : Missing parameter type annotation --> bad.py:1:12 | 1 | def process(data): | ^^^^ parameter `data` has no type annotation = help: add type annotation: `data: str` Found 5 errors in 1 file.
good.py
def process(data: str) -> str:
    return data.upper()


class User:
    name: str
    age: int

    def __init__(self, name: str, age: int) -> None:
        self.name = name
        self.age  = age

    def greet(self) -> str:
        return f"Hello, {self.name}"
All checked. No issues found. Checked 1 file — 0 errors, 0 warnings.

The problem

Pylance is proprietary. Pyright is just a type checker. Python deserves a fully open-source language server that does everything.
  • 01 Pylance is closed source. The most-used Python VS Code extension is proprietary. You can’t inspect, modify, or redistribute it. Basilisk is MIT/Apache-2.0 — fully open.
  • 02 Pyright is only a type checker. No autocomplete, no hover, no refactoring — not without Pylance wrapping it. Basilisk is a complete LSP: diagnostics, completions, go-to-definition, inlay hints, and more.
  • 03 Every type checker defaults to permissive. You get type checking only where you add --strict. Basilisk is strict by default — no opt-in required.
  • 04 Node.js is not a Python dependency. Pyright requires Node.js. Basilisk is a single Rust binary — no runtime, no npm, instant startup.

01 — Strict by default

No --strict flag.
No gradual mode.
No opt-in.

Basilisk treats every untyped function as a type error — because that’s what it is. There is no configuration key to make it permissive. The safe path is the only path.

0% escape hatches
<10 milliseconds, incremental

02 — Sub-10ms incremental checks

Keystroke-responsive.
Every edit.

Powered by Salsa — the same incremental computation framework behind rust-analyzer. Basilisk only recomputes what changed. Cold start on 100K LOC in under 5 seconds. Keystroke-responsive on every subsequent edit.

03 — Ownership semantics

Borrow. Mutate.
Move. All enforced.

Add Borrowed, InOut, and Owned annotations to express ownership. Standard Python syntax — no compiler required. Catch mutation of borrowed values and use-after-move before they reach production.

ownership.py
from basilisk import Borrowed

def summarise(
  items: Annotated[
    list[int], Borrowed],
) -> int:
  items.append(99)  # E0030
  return sum(items)
83.4% PEP conformance score

04 — PEP conformance

86 of 145 tests passing.
Target: 100%.

Tested against the official Python typing conformance suite — the same suite used to measure Pyright (~99%), mypy (~58%), and Pyrefly (~86%). Enums, overloads, qualifiers, and directives already at 90–100%. Generics, protocols, and aliases are next.

Basilisk Output
[Basilisk Debug] createDebugAdapterDescriptor
  type=basilisk-debug, request=launch

[Basilisk Debug] Requesting LSP to spawn
  debugpy (python: auto-detect)...

[Basilisk Debug] LSP spawned debugpy →
  connecting DAP client to
  localhost:57356

05 — Integrated debugging

F5 to debug.
Basilisk handles the rest.

Set breakpoints, step through code, inspect variables — all brokered through the Basilisk LSP. The Rust server spawns debugpy on a free TCP port and connects VS Code’s DAP client automatically. No manual configuration. No separate debug extension. Just press F5.

06 — Single binary

Drop it in PATH.
That’s the whole install.

Compiled to a standalone Rust binary. No Node.js. No Python interpreter. No pip install. No npm install. Works on macOS, Linux, and Windows from a single download.

terminal
# one-time install
cargo install basilisk

# or download the binary
curl -sSfL https://get.basilisk-python.dev | sh

# then just run it
basilisk check src/

Pylance features.
Open source.

A feature-complete language server that replaces Pylance — with stricter type checking and no proprietary lock-in.

Feature Basilisk Pyright mypy ty Pyrefly
Strict by default opt-in opt-in opt-in opt-in
PEP conformance ¹ 59.3% (86/145) ~99% ~58% full-pass alpha ~86%
Implementation Rust TypeScript Python/C Rust Rust
Runtime required None Node.js Python None None
Incremental speed ² <10ms ~386ms slower 4.7ms <10ms
Ownership analysis
Immutability enforcement
Plugin system WASM Python hooks Planned
Full LSP (completions, hover, goto) Pylance only Basic Basic
Integrated debugger
VS Code extension Open source Proprietary (Pylance) Open source Open source
License MIT MIT MIT MIT MIT

Sub-100ms on every rule.
Fastest in class.

Basilisk outperforms Pyright and mypy on every core type checking rule. Measured on real-world codebases with the official Python typing conformance suite.

Rule basilisk pyright mypy pyrefly ty
E0002 Missing return 255 ms 779 ms 147 ms 113 ms 52 ms ✓
E0016 Incompatible override 107 ms 824 ms 151 ms 119 ms 73 ms ✓
E0022 Unhashable dict key 105 ms 681 ms 148 ms 104 ms 55 ms ✓
E0023 Non-exhaustive match 81 ms 664 ms 151 ms 109 ms 39 ms ✓
E0026 TypeVar constraint 73 ms 869 ms 151 ms 115 ms 60 ms ✓

Basilisk in 30 seconds

Real error codes. Every fix suggested inline. rustc-style output.

api.py
from typing import Any

def fetch_user(user_id):            # BSK-E0001, BSK-E0002
    ...

def save_record(data: Any) -> bool:   # BSK-E0011
    ...
error[BSK-E0001]: Missing parameter type annotation --> api.py:3:16 | 3 | def fetch_user(user_id): | ^^^^^^^ parameter `user_id` has no type annotation = help: add type annotation: `user_id: int` error[BSK-E0011]: Implicit `Any` — explicit annotation required --> api.py:6:20 | 6 | def save_record(data: Any) -> bool: | ^^^ use of `Any` must be justified = help: replace `Any` with a concrete type, or add a suppression comment with reason = see: https://www.basilisk-python.dev/docs/rules/#BSK-E0011
transform.py
from typing import Annotated
from basilisk import Borrowed, Owned

def summarise(
    items: Annotated[list[int], Borrowed],
) -> int:
    items.append(99)  # BSK-E0030: mutation of Borrowed
    return sum(items)
error[BSK-E0030]: Mutation of `Borrowed` parameter --> transform.py:7:5 | 7 | items.append(99) | ^^^^^ cannot mutate `items`: parameter is `Borrowed` (read-only) | = help: change annotation to `Annotated[list[int], InOut]` to allow mutation = note: `Borrowed` parameters are immutable by contract = see: https://www.basilisk-python.dev/docs/mojo-safety/
service.py
from dataclasses import dataclass

@dataclass(frozen=True)
class Config:
    host: str
    port: int
    debug: bool = False

def create_config(
    host: str,
    port: int,
) -> Config:
    return Config(host=host, port=port)
All checked. No issues found. Checked 1 file — 0 errors, 0 warnings in 4ms.

Drop Pylance.
Pick up Basilisk.

Basilisk is in alpha. The type checker, LSP, VS Code extension, and integrated debugger are working. Autocomplete, go-to-definition, hover info, diagnostics, F5 debugging — all shipping today. Open source. No proprietary lock-in. Early adopters shape the roadmap.