RepoPilotOpen in app →

astral-sh/ty

An extremely fast Python type checker and language server, written in Rust.

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit today
  • 17 active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • MIT licensed
  • CI configured
  • No test directory detected

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/astral-sh/ty)](https://repopilot.app/r/astral-sh/ty)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/astral-sh/ty on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: astral-sh/ty

Generated by RepoPilot · 2026-05-07 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/astral-sh/ty shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit today
  • 17 active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • MIT licensed
  • CI configured
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live astral-sh/ty repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/astral-sh/ty.

What it runs against: a local clone of astral-sh/ty — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in astral-sh/ty | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>astral-sh/ty</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of astral-sh/ty. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/astral-sh/ty.git
#   cd ty
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of astral-sh/ty and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "astral-sh/ty(\\.git)?\\b" \\
  && ok "origin remote is astral-sh/ty" \\
  || miss "origin remote is not astral-sh/ty (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "pyproject.toml" \\
  && ok "pyproject.toml" \\
  || miss "missing critical file: pyproject.toml"
test -f "python/ty/__init__.py" \\
  && ok "python/ty/__init__.py" \\
  || miss "missing critical file: python/ty/__init__.py"
test -f "python/ty/__main__.py" \\
  && ok "python/ty/__main__.py" \\
  || miss "missing critical file: python/ty/__main__.py"
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"
test -f ".github/workflows/ci.yaml" \\
  && ok ".github/workflows/ci.yaml" \\
  || miss "missing critical file: .github/workflows/ci.yaml"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/astral-sh/ty"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

ty is an extremely fast Python type checker and language server written in Rust that aims to be 10-100x faster than mypy and Pyright. It performs comprehensive static type analysis on Python code with diagnostics, code navigation, auto-import, and fine-grained incremental analysis suitable for IDE integration. The project supports advanced typing features like intersection types, sophisticated type narrowing, and reachability-based type analysis. Monorepo structure with Rust as the core implementation (mentioned in README), Python wrapper and CLI on top (distribution via PyPI), and docs/ containing MkDocs-based documentation with Material theme. GitHub Actions orchestrate CI, binary builds for multiple platforms, Docker images, and PyPI publishing. The .github/workflows directory shows 10+ specialized build and release pipelines.

👥Who it's for

Python developers and teams who need fast, IDE-integrated type checking during development, particularly those working on large codebases (demonstrated by benchmarks on home-assistant/core). Also for Python package maintainers who want to adopt type safety gradually without mypy/Pyright's performance overhead.

🌱Maturity & risk

Actively developed and backed by Astral (creators of uv and Ruff), but explicitly in beta according to the README. The project has substantial CI/CD infrastructure (.github/workflows/ with 10+ automated jobs), comprehensive documentation in docs/, and Docker support. However, beta status signals API/behavior stability should not be assumed.

Beta maturity is the primary risk—breaking changes are expected per the VERSION_POLICY referenced in README. The Rust implementation creates a barrier for Python-only contributors and potential hiring bottlenecks. Dependencies appear well-maintained (uv ecosystem) but the single-language implementation (Rust) in a Python tool ecosystem may limit community contributions.

Active areas of work

Active development: GitHub workflows for daily property tests, renovate.json5 indicates automated dependency updates, and multiple publish pipelines (publish-pypi.yml, publish-docker.yml, publish-versions.yml) suggest frequent releases. The project is monitoring security (SECURITY.md, zizmor.yml) and maintains a pre-commit config, indicating active community support infrastructure.

🚀Get running

Clone the repository, then use uvx (uv's tool runner) as documented: uvx ty check to type-check a project, or git clone https://github.com/astral-sh/ty && cd ty followed by uv-based setup (see CONTRIBUTING.md for full developer setup, likely uv venv && uv sync based on the Astral ecosystem).

Daily commands: Based on file structure: uv sync to install dependencies (using uv workspace), then ty check <path> to type-check code. For development, refer to CONTRIBUTING.md. The Dockerfile indicates containerized runs: docker build -t ty . && docker run ty check.

🗺️Map of the codebase

  • pyproject.toml — Defines the project's Python packaging, dependencies, and build configuration; essential for understanding how ty is published and installed.
  • python/ty/__init__.py — Python package entry point that bridges the Rust implementation to Python consumers; critical for understanding the public API.
  • python/ty/__main__.py — CLI entry point for the ty type checker; shows how the Rust binary is invoked from Python.
  • README.md — Describes ty's purpose, highlights, and architecture; essential context for any contributor joining the project.
  • .github/workflows/ci.yaml — Defines the continuous integration pipeline including tests, builds, and validation; critical for understanding development workflow.
  • Dockerfile — Containerization definition for ty; important for understanding deployment and distribution strategy.
  • CONTRIBUTING.md — Contribution guidelines and development setup instructions; required reading for all contributors.

🧩Components & responsibilities

  • Python wrapper (python/ty/) (Python 3.8+, ctypes or subprocess for binary inv) — Provides entry points for CLI (python -m ty) and discovers the Rust binary at runtime; bridges Python ecosystem to Rust core.

🛠️How to make changes

Add a new diagnostic rule

  1. Document the rule's error code, message, and examples in the rules reference (docs/reference/rules.md)
  2. Add rule documentation with examples in the feature guides (docs/features/diagnostics.md)
  3. Update the changelog to document the new rule (CHANGELOG.md)

Configure ty for a Python project

  1. Create or modify pyproject.toml with [tool.ty] section referencing configuration schema (pyproject.toml)
  2. Reference the configuration guide and examples (docs/reference/configuration.md)
  3. Customize exclusion patterns if needed (docs/exclusions.md)

Set up ty in an editor

  1. Install ty via PyPI or binary, following installation instructions (docs/installation.md)
  2. Follow editor-specific setup guide for your IDE (docs/editors.md)
  3. Configure editor settings per the reference documentation (docs/reference/editor-settings.md)

Release a new version of ty

  1. Update version information and document changes (CHANGELOG.md)
  2. Run the release script to trigger automated workflows (scripts/release.sh)
  3. CI/CD workflows automatically build binaries, publish to PyPI, and update Docker (.github/workflows/release.yml)

🔧Why these technologies

  • Rust — Enables 10x–100x faster type checking than Python-based checkers (mypy, Pyright) with memory efficiency and zero-cost abstractions; critical for competitive performance benchmarks.
  • Python wrapper (pyproject.toml, python/) — Allows seamless distribution on PyPI and integration with Python ecosystem tools (pip, uv) while keeping core logic in performant Rust.
  • Language Server Protocol (LSP) — Enables IDE integration (VS Code, Neovim, etc.) with real-time diagnostics, code completion, and refactoring without editor-specific implementations.
  • GitHub Actions / CI workflows — Automates cross-platform binary compilation, testing, PyPI publishing, and Docker image builds to ensure reliable releases.
  • Docker — Provides containerized distribution for environments where Python binary wheels may be unavailable or to simplify deployment in containers.
  • MkDocs + Material — Generates professional, searchable documentation website from Markdown, supporting multiple versions and maintainable docs-as-code.

⚖️Trade-offs already made

  • Rust implementation over pure Python

    • Why: Speed is the primary competitive advantage; Rust achieves 10–100x speedup with memory safety guarantees.
    • Consequence: Higher barrier to local Rust development; requires cross-compilation setup and familiarity with Rust toolchain; distribution is more complex (binaries vs. pure wheels).
  • Beta version policy vs. stable 1.0 release

    • Why: Allows rapid iteration and breaking changes while building towards a stable API without committing to backwards compatibility.
    • Consequence: May deter adoption in conservative projects requiring stable, long-term versioning guarantees.
  • Comprehensive rule set over minimal core

    • Why: Aims to replace mypy and Pyright by covering a wide range of type checking scenarios and diagnostics.
    • Consequence: Increased maintenance burden; more rules to test, document, and keep in sync with Python typing specification.
  • Built-in LSP server over external server process

    • Why: Reduces deployment complexity and latency by embedding language server logic in the main binary.
    • Consequence: Tightly couples server logic with type checker; harder to independently evolve server and checker protocols.

🚫Non-goals (don't propose these)

  • Does not support Python 2 or versions older than ~3.8; focuses on modern Python typing.
  • Does not provide automatic code fixes (focus is diagnostics and reporting, not automated refactoring).
  • Does not aim to be a formatter; complementary to formatters like Black but does not replace them.
  • Does not handle authentication or license validation; designed for open-source and commercial use without gating.

🪤Traps & gotchas

Beta status means configuration/CLI may change without deprecation warnings. The Rust implementation is opaque to Python-only developers—understanding type checker behavior requires either reading docs or running it empirically. The project uses uv as its package manager and build tool, not pip/setuptools, so Python developers familiar only with traditional tools need uv setup knowledge. No explicit Makefile visible; build/test commands likely in CONTRIBUTING.md (not provided). Docker builds may require significant disk space for Rust compilation.

🏗️Architecture

💡Concepts to learn

  • Language Server Protocol (LSP) — ty implements LSP to provide IDE features (code completion, navigation, diagnostics) across multiple editors; understanding LSP is essential for extending IDE integration or debugging language server behavior
  • Gradual typing — ty explicitly supports partially typed code and gradual adoption of type annotations (mentioned in README), unlike strict-only type checkers; this is a core design philosophy affecting rule configuration and error reporting
  • Type narrowing — ty advertises 'advanced type narrowing' and 'reachability-based type analysis' as differentiators; understanding control flow-based type refinement is critical for predicting type checker behavior on conditional code
  • Intersection types — ty lists intersection types as a 'first-class' advanced feature in README; this is non-standard for Python type checkers and affects how union/intersection type resolution works versus mypy/Pyright
  • Incremental type checking — ty emphasizes 'fine-grained incremental analysis' for IDE responsiveness; understanding file-level dependency graphs and cache invalidation is essential for LSP performance debugging
  • Python type hints (PEP 484 / PEP 586 / PEP 604) — ty analyzes Python's standard type annotation syntax; contributors need familiarity with typing module conventions, Union vs | syntax, TypeVar, Protocol, and Literal types
  • Redeclarations / type variable scoping — ty explicitly supports 'redeclarations' as an adoption feature (README); understanding how shadowing and re-annotation of variables affects type inference differs from mypy and requires careful semantics design
  • astral-sh/ruff — Sibling project by Astral; Rust-based Python linter with similar philosophy of speed and comprehensive diagnostics, potential code pattern reuse
  • astral-sh/uv — Companion project by Astral; Python package manager used by ty for dependency management and distribution, required for developer setup
  • python/mypy — Direct predecessor and benchmark target; ty's 10-100x speedup claims are measured against mypy's performance
  • microsoft/pyright — Primary alternative type checker; ty competes directly on speed and feature parity while maintaining gradual typing support
  • python/typeshed — Upstream type stubs for standard library; critical dependency for both ty and competitor type checkers to resolve third-party package types

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive CLI integration tests

The repo has extensive CLI workflows (.github/workflows/ci.yaml, .github/workflows/release.yml) and detailed CLI reference docs (docs/reference/cli.md), but there's no visible test suite specifically for CLI argument parsing, configuration loading, and output formatting. This would catch regressions in user-facing behavior and ensure the CLI remains stable as the type checker evolves.

  • [ ] Create tests/cli directory with test modules for argument parsing
  • [ ] Add tests for configuration file loading (pyproject.toml, setup.cfg support)
  • [ ] Add tests verifying output formats (JSON, text, sarif for LSP)
  • [ ] Test error handling for missing files and invalid configurations
  • [ ] Integrate tests into existing CI pipeline in .github/workflows/ci.yaml

Document and add tests for LSP protocol compliance

The repo has a language server feature (docs/features/language-server.md) and editor integration docs (docs/editors.md), but lacks visible test coverage for LSP protocol compliance (hover, diagnostics, code completion, references). Given this is a production type checker, comprehensive LSP tests ensure reliability across all supported editors.

  • [ ] Create tests/lsp directory with LSP specification compliance tests
  • [ ] Add test fixtures for hover, go-to-definition, and find-references scenarios
  • [ ] Test diagnostic publishing across different Python versions
  • [ ] Add tests for code completion accuracy on complex type annotations
  • [ ] Document LSP implementation status in docs/features/language-server.md with a compliance matrix

Add type checking regression tests for Python language features

The repo emphasizes benchmarks (BENCHMARKS.md) and supports multiple Python versions (docs/python-version.md), but there's no visible test suite validating type checking correctness across Python 3.8-3.13 language features (match statements, type unions, overloads, generics). This is critical for a type checker's credibility.

  • [ ] Create tests/type_checking directory with feature-specific test modules
  • [ ] Add test cases for Python 3.10+ match statements and structural pattern matching
  • [ ] Add test cases for PEP 604 union syntax (X | Y) and type parameter syntax (PEP 695)
  • [ ] Add test cases for @override decorators, TypeVar bounds, and Protocol validation
  • [ ] Add parametrized tests to run across all supported Python versions in CI

🌿Good first issues

  1. Add missing editor integration documentation: the docs/editors.md file exists but likely has incomplete Vim/Emacs sections—review against Pyright docs and expand integration guides. 2) Improve diagnostics categorization: docs/features/diagnostics.md likely lists rules but lacks examples—add before/after code snippets for each rule category (type mismatch, unused variables, etc.). 3) Create automated benchmark regression test: BENCHMARKS.md exists but no visible CI job comparing performance across commits—add GitHub Actions workflow that runs benchmarks on PRs and comments with comparison.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 05def00 — Update maturin to v1.13.1 (#3417) (renovate[bot])
  • 569c081 — Update prek dependencies (#3416) (renovate[bot])
  • 608f8ff — Update renovate configuration (#3379) (MichaReiser)
  • 518b61d — Update uraimo/run-on-arch-action action to v3.1.0 (#3405) (renovate[bot])
  • 5542959 — Update pre-commit hook astral-sh/ruff-pre-commit to v0.15.12 (#3404) (renovate[bot])
  • d00448e — Bump version to 0.0.34 (#3392) (charliermarsh)
  • e9e4c90 — docs: Reference correct issue in FAQ regarding strict mode (#3385) (thernstig)
  • 1b70eae — Release: move 'diagnostics' section further down (#3373) (sharkdp)
  • d439e37 — CHANGELOG: Rename to 'Notable changes' (#3372) (sharkdp)
  • c512d84 — Bump version to 0.0.33 (#3368) (sharkdp)

🔒Security observations

The codebase demonstrates good security hygiene overall with a proper security policy and vulnerability reporting process. However, there are several infrastructure and build configuration issues that should be addressed. The Dockerfile has an incomplete RUN command that needs completion, overly permissive package management without version pinning, and relies on piping remote scripts to shell (though with HTTPS). The dependency files lack hash verification for integrity assurance. The project follows best practices with SECURITY.md, uses HTTPS for remote resources, and maintains proper GitOps workflows. Recommendations focus on hardening the build process and implementing stricter dependency verification mechanisms.

  • Medium · Incomplete Dockerfile Build Configuration — Dockerfile (final RUN statement). The Dockerfile has an incomplete RUN command at the end without a command specified. This could cause build failures or unexpected behavior during container image creation. Fix: Complete the final RUN command with the appropriate build instructions, or remove it if not needed. Ensure all RUN statements have valid commands.
  • Low · Overly Permissive APT Installation in Dockerfile — Dockerfile (line: RUN apt update && apt install -y build-essential curl python3-venv). The Dockerfile uses 'apt update && apt install -y' without pinning package versions. This could lead to non-deterministic builds and potential security issues if vulnerable versions are installed. Fix: Pin package versions explicitly (e.g., 'build-essential=12.x curl=7.x') and consider using '--no-install-recommends' to reduce attack surface.
  • Low · Missing Package Integrity Verification — docs/requirements.txt. The documentation dependencies in docs/requirements.txt use pinned versions but lack hash verification mechanisms. This could allow dependency substitution attacks. Fix: Use pip's '--require-hashes' flag or implement hash verification for all dependencies to ensure integrity of downloaded packages.
  • Low · Rust Toolchain Downloaded via Curl Pipe to Shell — Dockerfile (RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s --). The Dockerfile downloads and executes the rustup installer directly from the internet (curl ... | sh). While using --tlsv1.2 and https://, this pattern is inherently risky. Fix: Consider verifying the script signature or checksum before execution, or use a pre-built Rust image as base. At minimum, ensure TLS verification is enabled and inspect the script.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · astral-sh/ty — RepoPilot