# How to Handle Unused Imports After Code Changes Create Orphans

> Learn to handle unused imports in your code. Safely remove only new orphans after changes and avoid touching existing dead code to maintain code quality.

- Repository: [Jiayuan Zhang/andrej-karpathy-skills](https://github.com/forrestchang/andrej-karpathy-skills)
- Tags: how-to-guide
- Published: 2026-04-08

---

**Remove only the imports, variables, or functions that your specific changes made unused, while leaving pre-existing dead code untouched unless explicitly requested.**

When refactoring Python code or adding new features, your modifications may introduce **orphaned imports**—modules that are imported but no longer referenced anywhere in the file. The `forrestchang/andrej-karpathy-skills` repository defines strict cleanup rules within its *Karpathy Guidelines* (documented in [`skills/karpathy-guidelines/SKILL.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/skills/karpathy-guidelines/SKILL.md), [`README.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/README.md), and [`CLAUDE.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/CLAUDE.md)) to ensure developers handle these orphans without disturbing existing legacy code.

## The Core Rule for Orphaned Imports

According to [`skills/karpathy-guidelines/SKILL.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/skills/karpathy-guidelines/SKILL.md) (lines 45-48), the guidelines establish a clear boundary for cleanup responsibility: "When your changes create orphans – remove imports/variables/functions that **YOUR** changes made unused." This rule aligns with the repository's **Surgical Changes** principle summarized in [`README.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/README.md) (lines 64-68), which emphasizes touching only what is necessary to complete your task.

### Clean Up Your Own Mess

When your refactor or feature addition renders an import statement obsolete, you must delete that specific import before submitting your changes. This mandate applies equally to **variables** and **functions** that became unreachable solely due to your modifications.

### Do Not Touch Pre-Existing Dead Code

The same section of [`SKILL.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/SKILL.md) explicitly prohibits cleaning up unrelated technical debt: "Don't remove pre-existing dead code unless asked." If you encounter unused imports that existed before your edit, leave them in place to avoid scope creep and potential merge conflicts.

## Detecting Unused Imports with Linting Tools

While manual code review can spot orphans, automated tooling eliminates guesswork. The repository supports standard Python linters that flag unused imports with the `F401` error code.

Run **ruff**, **flake8**, or **pylint** against your modified files to generate a concrete list of orphaned imports:

```bash
ruff check utils.py

```

This command surfaces warnings such as `"F401 'json' imported but unused"`, giving you precise targets for removal.

## Step-by-Step Workflow to Handle Orphans

1. **Make your intended code changes** and save the file.

2. **Run the linter** to identify any new unused imports introduced by your edit.

3. **Remove only the orphaned imports** that your changes created, verifying each against the linter output.

4. **Execute the test suite** to confirm that your deletions did not break existing functionality.

5. **Stage and commit** the changes, ensuring your cleanup is limited to the scope of your original task.

## Practical Example: Refactoring a Python Module

Consider a scenario where you are refactoring [`utils.py`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/utils.py) and moving JSON serialization logic to a separate module. Before your changes, the file looks like this:

```python

# utils.py

import json          # <-- will become orphaned

import logging

def format_message(msg: str) -> str:
    return f"[INFO] {msg}"

```

After moving the JSON functionality elsewhere, your changes leave the `json` import unused:

```python

# utils.py

import json          # <-- now unused

import logging

def format_message(msg: str) -> str:
    return f"[INFO] {msg}"

def serialize(data):
    """New helper that previously used json, now moved elsewhere."""
    pass

```

Running `ruff check utils.py` highlights the orphan with error `F401`. Following the Karpathy Guidelines, you remove only the `json` import that your refactoring created:

```python

# utils.py

import logging

def format_message(msg: str) -> str:
    return f"[INFO] {msg}"

def serialize(data):
    """New helper that previously used json, now moved elsewhere."""
    pass

```

Finally, verify the cleanup:

```bash
ruff check utils.py           # No F401 warnings remain

pytest -q                     # All tests pass

```

If the project uses pre-commit hooks with `ruff --fix`, the tool can automatically strip these orphans when you stage the file.

## Summary

- **Remove only your orphans**: Delete imports, variables, or functions that became unused specifically because of your changes, as mandated in [`skills/karpathy-guidelines/SKILL.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/skills/karpathy-guidelines/SKILL.md) (lines 45-48).
- **Preserve existing dead code**: Never delete pre-existing unused imports unless explicitly requested.
- **Use automated detection**: Leverage **ruff**, **flake8**, or **pylint** to identify `F401` errors and confirm you are only removing imports you created.
- **Verify with tests**: Always run the test suite after import cleanup to ensure no accidental deletions of necessary dependencies.

## Frequently Asked Questions

### What is the difference between an orphaned import and pre-existing dead code?

An **orphaned import** is an unused import that resulted directly from your current changes, such as when you delete the last function call that referenced a module. **Pre-existing dead code** refers to unused imports or variables that were already present in the codebase before you began your edit. The Karpathy Guidelines (lines 45-48) instruct you to remove only the former while leaving the latter untouched.

### Should I configure automated tools to remove unused imports automatically?

Yes, but with caution. Tools like **ruff** with the `--fix` flag or pre-commit hooks can automatically remove `F401` violations. However, you must review the changes to ensure the tool only stripped imports introduced by your current work and did not affect pre-existing dead code that should be preserved according to the guidelines.

### What happens if I accidentally remove an import that is actually used?

If you delete an import that other code relies on, your tests will fail with `ImportError` or `NameError` during the verification step. The Surgical Changes workflow requires running `pytest` immediately after cleanup to catch these errors. If tests fail, restore the import and investigate why the linter flagged it as unused—sometimes complex dynamic imports or `__all__` declarations confuse static analysis tools.

### Does this rule apply to variables and functions, or only to imports?

The rule applies to all identifiers. [`SKILL.md`](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/SKILL.md) explicitly mentions "imports/variables/functions" collectively, meaning any unreachable code element falls under this policy. If your changes render a local variable or helper function unreachable, you should remove it provided the variable or function became unused solely due to your modifications.