/pyrefly-type-coverage
Migrate a file to use stricter Pyrefly type checking with annotations required for all functions, classes, and attributes.
$ npx -y skills add pytorch/pytorch --skill pyrefly-type-coverage --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/pyrefly-type-coverage
Context preview
The summary Claude sees to decide when to auto-load this skill.
Migrate a file to use stricter Pyrefly type checking with annotations required for all functions, classes, and attributes.
SKILL.md
pyrefly-type-coverage.SKILL.mdname: pyrefly-type-coverage
description: Migrate a file to use stricter Pyrefly type checking with annotations required for all functions, classes, and attributes.
Pyrefly Type Coverage Skill
Prerequisites
- The file must live in a project with a `pyrefly.toml`.
- `pyrefly`, `lintrunner`, and the project's test runner must be on PATH. **If any
are missing, stop and ask whether a conda environment needs activating** — don't install or substitute (per repo CLAUDE.md).
Step 1: Remove file-level type-check suppressions
Delete any of these from the top of the file (pyrefly honors `# mypy: ignore-errors` for mypy compat, so that one must go too):
# pyre-ignore-all-errors
# pyre-ignore-all-errors[16,21,53,56]
# @lint-ignore-every PYRELINT
# mypy: ignore-errors
Step 2: Add a sub-config entry to `pyrefly.toml`
[[sub-config]]
matches = "path/to/directory/**"
[sub-config.errors]
implicit-import = false
implicit-any = true
bad-param-name-override = false
unannotated-return = true
unannotated-parameter = true
**IMPORTANT**: Setting any error key in `[sub-config.errors]` overrides only that key relative to the parent — but enabling `unannotated-return` / `unannotated-parameter` / `implicit-any` will resurface errors that were previously hidden file-wide. If you see unrelated errors (e.g., `bad-param-name-override`) flooding the output, mirror the parent config's setting for that key in the sub-config to silence them.
Step 3: Run pyrefly
pyrefly check <FILENAME>
**Goal:** resolve all `unannotated-return`, `unannotated-parameter`, and `implicit-any` errors by adding annotations — see Step 4's ladder. These three target categories are always resolvable; **never** suppress them with `# pyrefly: ignore`. The single exception is `@compatibility(is_backward_compatible=True)` (Step 4).
Other categories (`bad-argument-type`, `missing-attribute`, …) are real type bugs. Handle them by where pyrefly reports them:
- **Reported in another file** (path != target): leave it. Don't widen scope. If
the error is now blocking the target, suppress at the report site with `# pyrefly: ignore[<category>] # TODO`.
- **Reported in the target file but the message names a symbol defined elsewhere**
(e.g., `bad-return` because an imported function's annotation is wrong): suppress locally with the same TODO comment. Don't invent a `cast()` that papers over the upstream gap.
- **Reported in the target file, originates locally**: fix it.
Use `# pyrefly: ignore[...]` only as a last resort, and only on non-target categories.
Step 4: Add annotations
Examine call sites when the right type isn't obvious from the function body.
Annotation conventions
- Use PEP 604 / PEP 585 syntax (`int | None`, `list[str]`) — assume Python >= 3.10.
- Prefer `collections.abc` over `typing` for ABCs (`Callable`, `Sequence`, `Generator`, ...).
- For generic helpers, import from `typing` when available on the project's minimum
Python version, and from `typing_extensions` only when you need a newer feature (e.g., `Self` and `override` if supporting < 3.11/3.12, or PEP 696 `default=` for `TypeVar` / `ParamSpec`). Don't blanket-import from `typing_extensions`.
- Always parameterize `Callable` (never bare `Callable`). Prefer
`Callable[..., object]`; reach for `Callable[..., Any]` only when a caller genuinely consumes the dynamic return — if the result is just passed through (or the callable isn't even invoked), `object` is stricter and equally correct. (See ParamSpec below for the signature-preserving wrapper case.)
- Give any module-local global you **introduce** a leading underscore —
`TypeVar`/`ParamSpec` (matching the string arg: `_T = TypeVar("_T")`, `_P = ParamSpec("_P")`, `_R = TypeVar("_R")`), `TypeAlias`es, helper constants, and sentinels alike. This is the prevailing torch convention for non-public names (`_P` outnumbers `P` ~6:1 in the tree). Exceptions (leave un-underscored): a name imported by other modules, listed in `__all__`, or used as a runtime token (e.g. an annotation-string dispatch marker). Applies only to names you add — do **not** rename pre-existing globals; that's an unrelated refactor outside this skill's scope.
- A boolean predicate — `is_*`/`has_*` name, takes a broad type (often `object`),
returns `bool` — usually wants `TypeGuard[X]` (or `TypeIs[X]`, which also narrows the negative branch). `TypeGuard` is in `typing` (>= 3.10, so import from there); `TypeIs` only entered `typing` in 3.13, so import it from `typing_extensions` (>= 4.10) to stay 3.10-compatible. An `issubclass`-style helper taking `klass: type[_T]` should return `TypeGuard[type[_T]]`. Prefer an explicit `isinstance(x, type)` guard over `try/except TypeError` around `issubclass()` — clearer, and it lets the checker narrow.
- When a return type is *derived from* a parameter — passthroughs/identity
functions, "return one of these args" helpers, decorators, registries keyed by type — reach for a `TypeVar` (or, for a callable arg whose signature flows through, `Callable[_P, _R]` with `ParamSpec`/`TypeVar`) rather than widening to `object`/`Any`. "Output type == some input type" is exactly what a `TypeVar` encodes; `object` in / `object` out discards it. Caveat: if the function *transforms* the value so the output type differs from the input (e.g. converts an array to an int), a single `TypeVar` is wrong — name the actual domain type instead.
- Class attributes assigned in `__init__` should get a class-level annotation so pyrefly can see them.
- Break import cycles with `if TYPE_CHECKING:` — annotation-only imports go inside the
guard, and use `from __future__ import annotations` (or string forward refs) so runtime imports stay lazy:
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from torch.fx import GraphModule
def transform(gm: GraphModule)Read more
name: pyrefly-type-coverage description: Migrate a file to use stricter Pyrefly type checking with annotations required for all functions, classes, and attributes.
Pyrefly Type Coverage Skill
Prerequisites
- The file must live in a project with a `pyrefly.toml`.
- `pyrefly`, `lintrunner`, and the project's test runner must be on PATH. **If any
are missing, stop and ask whether a conda environment needs activating** — don't install or substitute (per repo CLAUDE.md).
Step 1: Remove file-level type-check suppressions
Delete any of these from the top of the file (pyrefly honors `# mypy: ignore-errors` for mypy compat, so that one must go too):
# pyre-ignore-all-errors # pyre-ignore-all-errors[16,21,53,56] # @lint-ignore-every PYRELINT # mypy: ignore-errors
Step 2: Add a sub-config entry to `pyrefly.toml`
[[sub-config]] matches = "path/to/directory/**" [sub-config.errors] implicit-import = false implicit-any = true bad-param-name-override = false unannotated-return = true unannotated-parameter = true
**IMPORTANT**: Setting any error key in `[sub-config.errors]` overrides only that key relative to the parent — but enabling `unannotated-return` / `unannotated-parameter` / `implicit-any` will resurface errors that were previously hidden file-wide. If you see unrelated errors (e.g., `bad-param-name-override`) flooding the output, mirror the parent config's setting for that key in the sub-config to silence them.
Step 3: Run pyrefly
pyrefly check <FILENAME>
**Goal:** resolve all `unannotated-return`, `unannotated-parameter`, and `implicit-any` errors by adding annotations — see Step 4's ladder. These three target categories are always resolvable; **never** suppress them with `# pyrefly: ignore`. The single exception is `@compatibility(is_backward_compatible=True)` (Step 4).
Other categories (`bad-argument-type`, `missing-attribute`, …) are real type bugs. Handle them by where pyrefly reports them:
- **Reported in another file** (path != target): leave it. Don't widen scope. If
the error is now blocking the target, suppress at the report site with `# pyrefly: ignore[<category>] # TODO`.
- **Reported in the target file but the message names a symbol defined elsewhere**
(e.g., `bad-return` because an imported function's annotation is wrong): suppress locally with the same TODO comment. Don't invent a `cast()` that papers over the upstream gap.
- **Reported in the target file, originates locally**: fix it.
Use `# pyrefly: ignore[...]` only as a last resort, and only on non-target categories.
Step 4: Add annotations
Examine call sites when the right type isn't obvious from the function body.
Annotation conventions
- Use PEP 604 / PEP 585 syntax (`int | None`, `list[str]`) — assume Python >= 3.10.
- Prefer `collections.abc` over `typing` for ABCs (`Callable`, `Sequence`, `Generator`, ...).
- For generic helpers, import from `typing` when available on the project's minimum
Python version, and from `typing_extensions` only when you need a newer feature (e.g., `Self` and `override` if supporting < 3.11/3.12, or PEP 696 `default=` for `TypeVar` / `ParamSpec`). Don't blanket-import from `typing_extensions`.
- Always parameterize `Callable` (never bare `Callable`). Prefer
`Callable[..., object]`; reach for `Callable[..., Any]` only when a caller genuinely consumes the dynamic return — if the result is just passed through (or the callable isn't even invoked), `object` is stricter and equally correct. (See ParamSpec below for the signature-preserving wrapper case.)
- Give any module-local global you **introduce** a leading underscore —
`TypeVar`/`ParamSpec` (matching the string arg: `_T = TypeVar("_T")`, `_P = ParamSpec("_P")`, `_R = TypeVar("_R")`), `TypeAlias`es, helper constants, and sentinels alike. This is the prevailing torch convention for non-public names (`_P` outnumbers `P` ~6:1 in the tree). Exceptions (leave un-underscored): a name imported by other modules, listed in `__all__`, or used as a runtime token (e.g. an annotation-string dispatch marker). Applies only to names you add — do **not** rename pre-existing globals; that's an unrelated refactor outside this skill's scope.
- A boolean predicate — `is_*`/`has_*` name, takes a broad type (often `object`),
returns `bool` — usually wants `TypeGuard[X]` (or `TypeIs[X]`, which also narrows the negative branch). `TypeGuard` is in `typing` (>= 3.10, so import from there); `TypeIs` only entered `typing` in 3.13, so import it from `typing_extensions` (>= 4.10) to stay 3.10-compatible. An `issubclass`-style helper taking `klass: type[_T]` should return `TypeGuard[type[_T]]`. Prefer an explicit `isinstance(x, type)` guard over `try/except TypeError` around `issubclass()` — clearer, and it lets the checker narrow.
- When a return type is *derived from* a parameter — passthroughs/identity
functions, "return one of these args" helpers, decorators, registries keyed by type — reach for a `TypeVar` (or, for a callable arg whose signature flows through, `Callable[_P, _R]` with `ParamSpec`/`TypeVar`) rather than widening to `object`/`Any`. "Output type == some input type" is exactly what a `TypeVar` encodes; `object` in / `object` out discards it. Caveat: if the function *transforms* the value so the output type differs from the input (e.g. converts an array to an int), a single `TypeVar` is wrong — name the actual domain type instead.
- Class attributes assigned in `__init__` should get a class-level annotation so pyrefly can see them.
- Break import cycles with `if TYPE_CHECKING:` — annotation-only imports go inside the
guard, and use `from __future__ import annotations` (or string forward refs) so runtime imports stay lazy:
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from torch.fx import GraphModule
def transform(gm: GraphModule)Tensors and Dynamic neural networks in Python with strong GPU acceleration
Other skills on pytorch.
- /add-uint-support
Add unsigned integer (uint) type support to PyTorch operators by updating AT_DISPATCH macros. Use when adding support for uint16, uint32, uint64 types to operators, kernels, or when user mentions enabling unsigned types, barebones unsigned types, or uint support.
Open skill - /aoti-debug
Debug AOTInductor (AOTI) errors and crashes. Use when encountering AOTI segfaults, device mismatch errors, constant loading failures, or runtime errors from aot_compile, aot_load, aoti_compile_and_package, or aoti_load_package.
Open skill - /at-dispatch-v2
Convert PyTorch AT_DISPATCH macros to AT_DISPATCH_V2 format in ATen C++ code. Use when porting AT_DISPATCH_ALL_TYPES_AND*, AT_DISPATCH_FLOATING_TYPES*, or other dispatch macros to the new v2 API. For ATen kernel files, CUDA kernels, and native operator implementations.
Open skill - /ci-metrics
Query PyTorch CI, GitHub Actions, HUD, Grafana, and infrastructure metrics. Use when users ask about CI duration, job failures, queue times, workflow trends, runner health, dashboard data, or PyTorch infrastructure metrics.
Open skill - /cuda-index-width
Choose 32-bit vs 64-bit index math in PyTorch CUDA kernels. Use when fixing large-tensor indexing overflows, deciding whether to use int64_t, canUse32BitIndexMath, CUDA_KERNEL_LOOP_TYPE, or AT_DISPATCH_INDEX_TYPES, and when considering binary-size or performance impact of
Open skill - /distributed-triage
Sub-triages issues in the oncall:distributed queue by assigning distributed module labels, routing to sub-oncalls, and marking triaged. Use when an issue has been routed to oncall:distributed and needs second-level triage.
Open skill

