ty-extended is
Astral's ty with a sandboxed semantic extension system. It keeps
the ty command and language server while allowing libraries to contribute library-aware types
and diagnostics without linking to checker internals.
Extension showcase
django-ty is a live extension for Django ORM
semantics, available now from PyPI. It covers model fields,
relations, managers, querysets, lookups, settings, forms, and requests, with its behavior measured
against django-stubs in a reproducible differential-conformance suite.
What ships
| Distribution | Published at | Purpose |
|---|---|---|
ty-extended |
PyPI | The ty checker and language server with semantic extension loading and WASM execution. |
ty_plugin_sdk |
crates.io · docs.rs | The Rust API used to build an extension: manifest builders, typed hooks, patch helpers, JSON dispatch, and WASM exports. |
ty_plugin_protocol |
crates.io · docs.rs | The stable serialized manifest, request, response, claim, and patch types shared by extensions and the host. |
Most extension authors only need ty_plugin_sdk; it re-exports the protocol crate as
ty_plugin_sdk::protocol. The Rust implementation lives in the ruff submodule, backed
by ruff-extended.
How extensions run
flowchart LR
subgraph host["ty-extended"]
checker["ty semantic checker"] -->|claimed hook| router["Extension router"]
router -->|validated patch| checker
end
project["Python project"] --> checker
config["ty.toml + plugin manifest"] --> router
router -->|JSON request| wasm["WASM extension<br/>inside Wasmtime"]
wasm -->|declarative patch| router
checker --> output["Types + diagnostics"]
The manifest tells ty which symbols and hooks an extension owns. At a matching semantic query, ty serializes a small request, executes the extension inside a Wasmtime sandbox, validates the returned patch, and feeds the result back into type inference. Extensions receive protocol data, not ty's internal types, AST ids, or Salsa database.
Getting started
Run the checker directly with uvx:
uvx --from ty-extended ty check
Or add it to a project:
uv add --dev ty-extended uv run ty check
See installation, type checking, and editor integration for the regular ty workflow.
Configure extensions
An installed extension package can be discovered from the project's Python environment:
# ty.toml [plugins] auto-discover = true
To load a WASM artifact explicitly, configure and trust it for the project:
# ty.toml [plugins] enabled = true [[plugins.plugin]] id = "my-extension" path = ".ty/plugins/my_extension.wasm" runtime = "wasm" manifest-path = ".ty/plugins/my-extension.plugin.json" trusted = true
Use [tool.ty.plugins] and [[tool.ty.plugins.plugin]] for the same settings in
pyproject.toml. See extension runtime for loading, trust, and
sandbox details.
Everything from ty
ty-extended tracks ty's checker and language server. That includes:
- fast incremental type checking;
- rich diagnostics and configurable rule levels;
- gradual typing, advanced narrowing, and intersection types;
- editor support for navigation, completion, code actions, auto-imports, inlay hints, and hover;
- the same
ty check,ty server, configuration, and project discovery behavior.
The upstream ty documentation remains the reference for those shared features.
Documentation
- Build a semantic extension
- Understand the host runtime
- Read the ty-extended FAQ
- Browse the full ty-extended documentation
For information on upstream ty's timeline to a stable release, see its Stable milestone.
FAQ
Is ty-extended a separate checker?
It is a fork of ty that preserves the ty CLI and language server and adds semantic extensions.
Why does it execute extensions as WASM?
WASM gives extensions a stable, serialized boundary and lets the host enforce deterministic fuel, memory, and response-size limits without exposing checker internals or ambient system access.
Where are general ty questions answered?
See ty's upstream typing FAQ. The ty-extended FAQ covers only fork and extension behavior.
Getting help
For ty-extended packaging, extension runtime, SDK, or protocol issues, open an issue. For behavior inherited unchanged from ty, check the upstream documentation first.
Contributing
Most implementation work happens in the ruff submodule, which points at
regularkevvv/ruff-extended. See the
contributing guide for the repository workflow.
Version policy
ty-extended uses SemVer-compatible fork versioning that records the upstream ty base:
- upstream
0.0.58maps to the initialty-extended 0.58.0release; - later fork releases on the same upstream base increment the patch, such as
0.58.1and0.58.2; - upstream
0.0.59maps toty-extended 0.59.0; - later releases on that base increment the patch, such as
ty-extended 0.59.1; - upstream
0.0.60maps toty-extended 0.60.0; - upstream
0.0.61maps toty-extended 0.61.0; - upstream
0.0.62maps toty-extended 0.62.0; - upstream
0.0.63maps toty-extended 0.63.0; - upstream
0.0.64maps toty-extended 0.64.0; - upstream
0.0.65maps toty-extended 0.65.0; - upstream
0.1.50maps toty-extended 0.150.0; - once upstream reaches
1.0.0, ty-extended follows that shape directly as1.0.x.
The protocol and SDK crates are versioned independently. They are pre-1.0, so breaking changes may
occur between any two 0.0.x releases.
License
ty is licensed under the MIT license (LICENSE or https://opensource.org/licenses/MIT).
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in ty by you, as defined in the MIT license, shall be licensed as above, without any additional terms or conditions.