# How to Use pyrefly infer to Generate Python Type Annotations

> Learn how to use pyrefly infer to automatically add type annotations to your Python code. This powerful tool analyzes your code and inserts type hints directly into your source files.

- Repository: [Meta/pyrefly](https://github.com/facebook/pyrefly)
- Tags: how-to-guide
- Published: 2026-05-21

---

**pyrefly infer** is the built-in command that automatically adds type annotations to existing Python code by running the type checker, collecting inferred types, and inserting them directly into source files.

The `pyrefly infer` command in the [facebook/pyrefly](https://github.com/facebook/pyrefly) repository provides an automated way to add static type hints to unannotated Python codebases. This tool analyzes function bodies, determines precise types for parameters and return values, and modifies source files in-place to include the annotations.

## Command-Line Interface and Flags

The `pyrefly infer` command accepts several flags that control which elements receive type annotations. These options are defined in the `InferFlags` struct located in [[`pyrefly/lib/commands/infer.rs`](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs)](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs) (lines 52-87).

**Available flags include:**

- **`--containers`** – Annotate empty containers such as `list` and `dict` with their inferred element types.
- **`--return-types`** – Add return-type hints to function definitions (enabled by default).
- **`--parameter-types`** – Add parameter type hints to function signatures.
- **`--imports`** – Automatically insert required import statements for types defined in other modules.

You can negate boolean flags using the `--no-` prefix. For example, `--no-return-types` disables return-type inference while keeping parameter annotations enabled.

## The Inference Pipeline

The `pyrefly infer` command follows a seven-stage pipeline to transform untyped Python code into fully annotated code. The core logic resides in the `InferArgs::run` method in [[`pyrefly/lib/commands/infer.rs`](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs)](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs).

### Configuration Enforcement

Before type checking begins, the command ensures the type checker runs with inference-specific settings. In lines 82-89 of [`infer.rs`](https://github.com/facebook/pyrefly/blob/main/infer.rs), the code forces two configuration options unless explicitly overridden by the user:

- `check_unannotated_defs` – Ensures the analyzer processes function bodies without existing annotations.
- `infer_return_types` – Enables return-type inference from return statements.

This guarantees that the checker produces the type information necessary for annotation generation.

### Type Checking and Data Collection

The command creates a `State` object and runs a `Forgetter` transaction across all selected files (lines 99-124). The call to `transaction.run(&handles, Require::Everything, None)` executes the full type-checking pipeline in parallel.

After analysis completes, the system extracts inferred types through two primary methods:

- `transaction.inferred_types` – Returns tuples of `(position, Type, AnnotationKind)` for return values and variables (line 126).
- `transaction.infer_parameter_annotations` – Provides inferred parameter hints when the `--parameter-types` flag is enabled (lines 128-131).

### Formatting and Import Resolution

The `format_hints` function (lines 74-126) processes the raw type data by:

1. Filtering out undesirable types such as `Any`, `Unknown`, and `Overload`.
2. Converting each `Type` into a printable string using `hint_to_string`.
3. Recording which modules require imports to support the generated annotations.

This step ensures that generated annotations use valid Python syntax and that all referenced types are importable.

### File Modification

The command writes annotations back to disk using two specialized functions:

- `add_annotations_to_file` (lines 88-103) – Inserts formatted type strings (`: type` for parameters, `-> type` for returns) at the exact byte offsets recorded during analysis.
- `add_imports_to_file` (lines 104-117) – Adds necessary `from <module> import <name>` statements immediately after any `__future__` imports or module docstrings.

After processing all files, the command exits with `CommandExitStatus::Success` (line 85), leaving the modified Python files with inline type hints and required imports.

## Practical Usage Examples

**Basic inference on a single file:**

```bash
pyrefly infer path/to/file.py

```

**Include container type annotations:**

```bash
pyrefly infer --containers path/to/file.py

```

**Disable return-type inference (parameters only):**

```bash
pyrefly infer --no-return-types path/to/file.py

```

**Process an entire directory recursively:**

```bash
pyrefly infer path/to/project/

```

**Combine multiple flags:**

```bash
pyrefly infer --containers --no-imports path/to/project/

```

**Using a configuration file:**

Create a [`pyrefly.toml`](https://github.com/facebook/pyrefly/blob/main/pyrefly.toml) file:

```toml
project_includes = ["src/**/*.py"]
project_excludes = ["src/tests/**/*.py"]
infer-return-types = "checked"

```

Then run:

```bash
pyrefly infer --config pyrefly.toml

```

### Before and After Examples

*Input ([`example.py`](https://github.com/facebook/pyrefly/blob/main/example.py)):*

```python
def add(a, b):
    return a + b

```

*Output after `pyrefly infer`:*

```python
def add(a: int, b: int) -> int:
    return a + b

```

*Handling external imports:*

```python

# Before

def make():
    return Example()

# After (assuming Example is defined in models.py)

from models import Example

def make() -> Example:
    return Example()

```

## Key Implementation Files

The `pyrefly infer` functionality is centralized in [[`pyrefly/lib/commands/infer.rs`](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs)](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs). Critical sections include:

- **Lines 52-87** – Definition of `InferFlags` controlling CLI behavior.
- **Lines 82-89** – Configuration enforcement for unannotated definition checking.
- **Lines 74-126** – The `format_hints` function for type string conversion.
- **Lines 88-103** – `add_annotations_to_file` for source code modification.
- **Lines 104-117** – `add_imports_to_file` for import statement injection.
- **Lines 495-530** – Test suite demonstrating end-to-end inference scenarios.

Additional user-facing documentation is available in [`website/docs/autotype.mdx`](https://github.com/facebook/pyrefly/blob/main/website/docs/autotype.mdx).

## Summary

- **pyrefly infer** automatically adds type annotations by analyzing code with the Pyrefly type checker and inserting hints at the correct source positions.
- The command supports granular control via flags like `--containers`, `--return-types`, `--parameter-types`, and `--imports`.
- Configuration options `check_unannotated_defs` and `infer_return_types` are automatically enabled to ensure comprehensive type discovery.
- The tool modifies files in-place, adding both annotations and necessary import statements while preserving existing code structure.
- Implementation resides primarily in [`pyrefly/lib/commands/infer.rs`](https://github.com/facebook/pyrefly/blob/main/pyrefly/lib/commands/infer.rs), with distinct functions handling formatting, annotation insertion, and import management.

## Frequently Asked Questions

### What is the difference between `pyrefly infer` and `pyrefly check`?

`pyrefly check` analyzes code for type errors and reports diagnostics without modifying files. `pyrefly infer` runs the same type analysis but uses the results to generate and insert type annotations directly into the source code, effectively automating the migration to typed Python.

### Does `pyrefly infer` modify files in-place?

Yes, `pyrefly infer` modifies Python files in-place by inserting type annotations at the byte positions determined during analysis. The command uses `add_annotations_to_file` to write type hints and `add_imports_to_file` to insert necessary import statements, preserving the original formatting and structure of the code.

### How does `pyrefly infer` handle imports for custom types?

When the `--imports` flag is enabled, the inference pipeline tracks which modules define the types used in annotations. The `format_hints` function records these dependencies, and `add_imports_to_file` inserts appropriate `from <module> import <name>` statements after any `__future__` imports or module docstrings, ensuring the annotated code remains valid and executable.

### Can I use `pyrefly infer` with a pyrefly.toml configuration file?

Yes, `pyrefly infer` respects configuration files. You can define project includes, excludes, and default inference settings in [`pyrefly.toml`](https://github.com/facebook/pyrefly/blob/main/pyrefly.toml), then invoke the command with `pyrefly infer --config pyrefly.toml`. Configuration options like `infer-return-types` can be set to `"checked"` to match the command's default behavior.