ty
5 min read

Extremely fast Python type checker and language server by Astral (creators of uv and Ruff). Written in Rust. 10–80x faster than mypy and Pyright.

Status: Beta (released December 2025, formerly "Red Knot"). Stable 1.0 targeted for 2026. Expect bugs and missing features. Playground: https://play.ty.dev

Install

sh
# Run without installing
uvx ty check

# Project dev dependency (recommended)
uv add --dev ty
uv run ty check

# Global via uv tool
uv tool install ty@latest

# Standalone installer
curl -LsSf https://astral.sh/ty/install.sh | sh

# pip / pipx
pip install ty
pipx install ty

# mise
mise install ty && mise use --global ty

# Docker
COPY --from=ghcr.io/astral-sh/ty:latest /ty /bin/

# Shell completions
ty generate-shell-completion bash|zsh|fish|elvish|powershell

CLI

ty check [PATHS]

Check files or directories for type errors. Defaults to the project root.

sh
ty check src/
ty check --watch # recheck on file changes
ty check --python .venv # use specific virtualenv
ty check --python-version 3.12
ty check --output-format github # CI annotation format
ty check --add-ignore # auto-add ty: ignore to all current diagnostics

FlagDescription
--watch / -WRecheck on file change
--python PATHPython interpreter or venv
--python-versionTarget version (3.7–3.15, default 3.14)
--python-platformwin32 | darwin | linux | android | ios | all
--output-formatfull | concise | gitlab | github | junit
--error RULETreat rule as error (use all for every rule)
--warn RULETreat rule as warning
--ignore RULEDisable rule
--add-ignoreInsert ty: ignore comments for all current diagnostics
--fixApply auto-fixes
--error-on-warningExit 1 on any warning
--exit-zeroAlways exit 0
--extra-search-path PATHExtra module resolution path
--typeshed PATHCustom typeshed directory
--exclude PATTERNGitignore-style exclusion
-c KEY=VALUEOverride a config key inline
--config-file PATHExplicit config file
--project DIRRun within given project directory

Other Commands

sh
ty server # start LSP language server
ty explain [RULE] # explain a rule or list all rules
ty version # show version
ty help # help

Configuration

Config is discovered by walking up from the current directory. ty.toml takes precedence over pyproject.toml when both exist.

User-level config:

• macOS/Linux: ~/.config/ty/ty.toml
• Windows: %APPDATA%\ty\ty.toml

pyproject.toml

toml
[tool.ty.environment]
python-version = "3.12"
python-platform = "linux"
python = ".venv"
extra-paths = ["src/stubs"]
typeshed = "/path/to/custom/typeshed"

[tool.ty.src]
include = ["src", "tests"]
exclude = ["tests/fixtures"]
respect-ignore-files = true

[tool.ty.rules]
division-by-zero = "warn"
unused-ignore-comment = "error"
unresolved-import = "warn"

[tool.ty.analysis]
allowed-unresolved-imports = ["mypy_extensions.*", "some_untyped_lib.*"]
replace-imports-with-any = ["some_dynamic_lib.*"]
respect-type-ignore-comments = true # default true

[tool.ty.terminal]
output-format = "full"
error-on-warning = false

# Per-file overrides
[[tool.ty.overrides]]
include = ["tests/**"]
rules = { invalid-return-type = "ignore" }

[[tool.ty.overrides]]
include = ["src/legacy/**"]
rules = { all = "ignore" }

ty.toml (same keys, no [tool.ty] prefix)

toml
[rules]
division-by-zero = "warn"

[environment]
python-version = "3.12"

[src]
include = ["src"]

Rules

Severity levels: error | warn | ignore. Configure in [tool.ty.rules] or per-file in [[overrides]].

List all rules and their descriptions:

sh
ty explain rule
ty explain rule unresolved-import

Common Rules

RuleDefaultDescription
unresolved-importerrorFailed import
unresolved-attributeerrorAttribute not found on object
unresolved-referenceerrorReference to undefined name
invalid-argument-typeerrorArgument not assignable to parameter
invalid-return-typeerrorReturn value incompatible with annotation
invalid-assignmenterrorAssignment violating type rules
missing-argumenterrorMissing required argument
too-many-positional-argumentserrorExcess positional arguments
unknown-argumenterrorUnknown keyword argument
call-non-callableerrorCalling a non-callable
not-iterableerrorIterating over non-iterable
not-subscriptableerrorSubscripting non-subscriptable
unsupported-operatorerrorOperator on incompatible types
index-out-of-boundserrorOut-of-bounds index access
possibly-unresolved-referenceerrorPotentially undefined name
invalid-overloaderrorInvalid @overload usage
no-matching-overloaderrorCall matches no overload
invalid-type-argumentserrorInvalid generic type arguments
type-assertion-failureerrorFailed assert_type()
unused-awaitableerrorUnused awaitable
unused-ignore-commenterrorUnnecessary ty: ignore comment
unused-type-ignore-commenterrorUnnecessary type: ignore comment
invalid-raiseerrorInvalid raise statement
invalid-exception-caughterrorHandler catching non-exception
subclass-of-final-classerrorInheriting from @final class
override-of-final-methoderrorOverriding @final method
division-by-zeroignoreLiteral division by zero (opt-in)
deprecatedwarnUse of deprecated items
invalid-ignore-commentwarnMalformed ignore comment
ignore-comment-unknown-rulewarnty: ignore[bad-code]

Suppressing Diagnostics

Inline

python
x = 20 / 0 # ty: ignore[division-by-zero]
x = 20 / 0 # ty: ignore # suppress all on this line

# Standard mypy syntax also works
x = 20 / 0 # type: ignore[ty:division-by-zero]

Unknown rule codes in ty: ignore[...] raise ignore-comment-unknown-rule.

Auto-suppress all current diagnostics

sh
ty check --add-ignore

Config (disable globally or per-file)

toml
[tool.ty.rules]
division-by-zero = "ignore"

[[tool.ty.overrides]]
include = ["tests/**"]
rules = { invalid-return-type = "ignore" }

CLI

sh
ty check --ignore division-by-zero
ty check --warn unresolved-import --error deprecated

Language Server

sh
ty server # starts LSP on stdin/stdout

Features: go to definition, rename, auto-complete, auto-import, semantic highlighting, inlay hints, code actions, fine-grained incremental analysis, Jupyter notebook cross-cell analysis.

Editor Integrations

VS Code

Install the official ty extension (published by Astral). It automatically disables Pylance's type checking.

To keep Pylance for completions but use ty for type checking only:

json
{
"python.languageServer": "Pylance",
"ty.disableLanguageServices": true
}

Neovim

Neovim ≥ 0.11:

lua
vim.lsp.config('ty', { settings = { ty = {} } })
vim.lsp.enable('ty')

Neovim < 0.11 (via nvim-lspconfig):

lua
require('lspconfig').ty.setup({ settings = { ty = {} } })

Zed

Built-in support. Enable in settings.json:

json
{
"languages": {
"Python": {
"language_servers": ["ty", "ruff"]
}
}
}

Override binary path:

json
{
"lsp": {
"ty": {
"binary": { "path": "/home/user/.local/bin/ty", "arguments": ["server"] }
}
}
}

PyCharm

Native support from PyCharm 2025.3+. Settings → Python | Tools | ty → Enable.

Emacs (Eglot)

elisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(python-base-mode . ("ty" "server"))))
(add-hook 'python-base-mode-hook 'eglot-ensure)

Comparison with mypy / Pyright

AspecttymypyPyright
Speed10–80x fasterbaselinebaseline
ImplementationRustPythonTypeScript
Spec conformance~53% (beta)~58%~98%
Checks unannotated bodiesYes (default)No (opt-in)Optional
Plugin systemNo (roadmap)YesNo
Pydantic/DjangoBeta gapsVia pluginsPartial
Language serverBuilt-inVia pylsp-mypyPylance/pyright
Pre-releaseBetaStableStable

Performance examples: home-assistant — ty 2.19s vs mypy 45.66s (20x). PyTorch incremental edit — ty 4.7ms vs Pyright 386ms (80x).

ty checks all code including unannotated function bodies (mypy skips them by default). ty guarantees the "gradual guarantee": adding annotations to passing code never introduces new errors.