From ty-lsp
Use when reading, navigating, or editing Python (.py/.pyi) in a project where the ty language server is running. Covers when to prefer LSP requests (definition, references, hover, document/workspace symbols, call hierarchy) over grep, how to position requests so they don't silently miss, how to read ty's diagnostics, and which type-system gaps to expect while ty is in beta.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ty-lsp:ty-python-lspThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`ty` is Astral's Python type checker and language server. It is fast and its
ty is Astral's Python type checker and language server. It is fast and its
navigation is semantic, so it resolves through imports, re-exports, aliases, and
into .venv and the stdlib — things a text search cannot do.
ty is in beta. Navigation is solid; the type system still has holes. See
"Beta expectations" below before trusting a type conclusion.
These are operation values on the LSP tool.
| Question | Use |
|---|---|
| Where is this symbol actually defined? | goToDefinition |
| Who calls / uses this? | findReferences |
| What is this expression's type? What are the args? | hover |
| What's in this file, structurally? | documentSymbol |
| Where is a symbol whose file I don't know? | workspaceSymbol |
| What's the call chain into or out of this function? | prepareCallHierarchy, then incomingCalls / outgoingCalls |
| Where is this string literal / TODO / config key? | grep |
| Which files exist, what's the layout? | glob / read |
Run documentSymbol before reading a large file — it's a cheap sitemap and
saves pulling the whole file into context.
Grep is still right for non-semantic text and for symbols that ty cannot resolve (see beta gaps). When LSP returns nothing for something you can see with your own eyes, that is usually a positioning bug on your side, not absence — check the next section before falling back.
Positions are zero-indexed lines, and characters are UTF-16 code units (so astral-plane characters — emoji, some CJK — count as 2).
Point at a character inside the identifier you're asking about, not at the dot, the paren, the whitespace before it, or the line. Off by one and you get an empty result with no error, which reads exactly like "not found."
result = client.fetch_user(uid)
# ^0-based col 9 = `client` -> the variable
# ^col 16 = `fetch_user` -> the method
If a request comes back empty, re-check the column against the actual line text before concluding the symbol doesn't exist.
Warm-up: the server indexes the workspace on start. The very first
workspaceSymbol or cross-file findReferences request against a cold server
can return fewer results than it should. If a result looks suspiciously empty
right after startup, retry once.
Diagnostics are pushed as you open and edit files — you don't poll for them.
After a Write or Edit to a .py file, they surface on their own. Treat a new
diagnostic on a line you just touched as feedback on that edit.
ty is a gradual checker: when it cannot infer a type it yields Unknown
and stays quiet rather than erroring. Unknown in a hover is a signal that
inference bottomed out — often an unannotated function return, a dynamically
assigned attribute, or an untyped third-party call. It is not proof the code is
correct, and it is not itself an error to fix.
For type errors on the whole project (rather than open files), run the checker
directly: ty check.
Claude Code offers a goToImplementation operation, but ty does not implement
it. The request hard-errors (-32601 Unknown request) rather than returning an
empty list — so a tool error there means "ty can't do this," not "no
implementations exist." Reach for findReferences on the base symbol, or grep
for (BaseName), instead.
Also unsupported: code lens, document link, document color, rename-files.
Formatting is out of scope for ty. Use ruff format; ty exposes no
formatting, range-formatting, or on-type-formatting.
Navigation and hover are reliable. The type system has known gaps, tracked in astral-sh/ty#1889 — consult it before reporting a bug or trusting a surprising type. As of this writing the notable ones:
Unknown. Adding a return annotation usually restores inference
downstream.TypeVarTuple / Unpack unsupported (#156),
including Unpack for **kwargs.attrs — are not
modeled, so synthesized __init__s and fields may type as Unknown.functools.partial is only partially modeled (#1536);
simple cases do resolve (partial(add, 1) → partial[(b: int) -> int])..so) and PEP 723 inline script metadata are unresolved.@classmethod/@staticmethod members and type[SomeProtocol] are incomplete.Missing LSP features are tracked separately in astral-sh/ty#3588.
When ty's answer contradicts what the code plainly does, suspect one of the gaps above rather than rewriting working code to satisfy the checker.
Guides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.
Creates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.
Implements work from a spec or tickets using TDD at agreed seams, with regular typechecking and test runs, followed by code review.
npx claudepluginhub jsperger/claude-ty-lsp --plugin ty-lsp