Skip to content
Back to skills

Mypy Setup

ASecurity

Set up Mypy type checking configuration for a Python project

  • 15 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 27, 2026
developmentpythongobashfastapidjangogitapibackendci/cd

Works with

  • claude code
  • vscode
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned May 27, 2026

npx -y skills add jpoutrin/product-forge --skill mypy-setup --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mypy Setup?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mypy Setup
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jpoutrin-mypy-setup/badge)](https://www.skillsdirectory.com/skills/jpoutrin-mypy-setup)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mypy-setup
description: Set up Mypy type checking configuration for a Python project
argument-hint: [--strict] [--django] [--format=<ini|toml>] [--install]
---

# mypy-setup

**Category**: Python Development

## Usage

```bash
/mypy-setup [--strict] [--django] [--format=<ini|toml>] [--install]
```

## Arguments

| Argument | Required | Description |
|----------|----------|-------------|
| `--strict` | No | Use strict type checking configuration |
| `--django` | No | Add Django-specific configuration and plugin |
| `--format=<ini\|toml>` | No | Config format (default: ini) |
| `--install` | No | Install Mypy and required plugins |

## Purpose

Set up Mypy static type checking in a Python project:

1. **Create Configuration**: Generate mypy.ini or pyproject.toml config
2. **Install Dependencies**: Install Mypy and type stub packages
3. **Configure IDE**: Add Mypy settings for VS Code/PyCharm
4. **Setup CI/CD**: Generate GitHub Actions workflow
5. **Add Pre-commit**: Configure pre-commit hook for Mypy

## Execution Instructions for Claude Code

When this command is run, Claude Code should:

### 1. Parse Arguments

```
STRICT_MODE = true if --strict specified
DJANGO_MODE = true if --django specified
FORMAT = value after --format= (default: "ini")
INSTALL = true if --install specified
```

### 2. Detect Project Type

Scan the project to determine:

```bash
# Check for Django
HAS_DJANGO=false
if [ -f "manage.py" ] || grep -q "django" requirements.txt 2>/dev/null; then
    HAS_DJANGO=true
    echo "✓ Django project detected"
fi

# Check for existing config
HAS_CONFIG=false
if [ -f "mypy.ini" ] || [ -f ".mypy.ini" ] || grep -q "\[tool.mypy\]" pyproject.toml 2>/dev/null; then
    HAS_CONFIG=true
    echo "⚠ Existing Mypy configuration found"
fi

# Check Python version
PYTHON_VERSION=$(python --version | cut -d' ' -f2 | cut -d'.' -f1,2)
echo "Python version: $PYTHON_VERSION"
```

### 3. Install Mypy (if --install)

```bash
if [ "$INSTALL" = true ]; then
    echo "Installing Mypy..."

    # Use uv if available, otherwise pip
    if command -v uv &> /dev/null; then
        PKG_MANAGER="uv pip install"
    else
        PKG_MANAGER="pip install"
    fi

    # Install Mypy
    $PKG_MANAGER mypy

    # Install Django plugin if needed
    if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then
        $PKG_MANAGER django-stubs mypy-django-plugin
    fi

    # Install common type stubs
    $PKG_MANAGER types-requests types-PyYAML types-redis

    echo "✓ Mypy installed successfully"
fi
```

### 4. Generate Configuration File

#### Option A: mypy.ini (default)

```bash
if [ "$FORMAT" = "ini" ]; then
    cat > mypy.ini << 'EOF'
[mypy]
# Python version
python_version = 3.11

# Import discovery
namespace_packages = True
explicit_package_bases = True
ignore_missing_imports = False

# Platform configuration
platform = linux

# Disallow dynamic typing
disallow_any_generics = True
disallow_subclassing_any = True

# Disallow untyped code
disallow_untyped_calls = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
check_untyped_defs = True
disallow_untyped_decorators = True

# None and Optional handling
no_implicit_optional = True
strict_optional = True

# Warnings
warn_redundant_casts = True
warn_unused_ignores = True
warn_no_return = True
warn_return_any = True
warn_unreachable = True

# Strictness flags
strict_equality = True
strict_concatenate = True

# Error messages
show_error_codes = True
show_column_numbers = True
show_error_context = True
pretty = True

# Miscellaneous
warn_unused_configs = True

# Per-module options for gradual typing
[mypy-tests.*]
disallow_untyped_defs = False

[mypy-migrations.*]
ignore_errors = True

EOF

    if [ "$STRICT_MODE" = true ]; then
        # Already strict by default
        echo "✓ Created strict mypy.ini"
    else
        # Relax some settings for gradual adoption
        cat >> mypy.ini << 'EOF'

# Relaxed settings for gradual adoption
# Remove these overrides as you add type hints
[mypy]
disallow_untyped_calls = False
disallow_untyped_defs = False
disallow_incomplete_defs = False

EOF
        echo "✓ Created mypy.ini (gradual mode)"
        echo "  Gradually enable stricter checks as you add type hints"
    fi

    # Add Django configuration
    if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then
        cat >> mypy.ini << 'EOF'

# Django configuration
[mypy]
plugins = mypy_django_plugin.main

[mypy.plugins.django-stubs]
django_settings_module = "config.settings"  # Update with your settings module

EOF
        echo "✓ Added Django plugin configuration"
        echo "  Update django_settings_module in mypy.ini"
    fi
fi
```

#### Option B: pyproject.toml

```bash
if [ "$FORMAT" = "toml" ]; then
    # Check if pyproject.toml exists
    if [ ! -f "pyproject.toml" ]; then
        cat > pyproject.toml << 'EOF'
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

EOF
    fi

    # Add Mypy configuration
    cat >> pyproject.toml << 'EOF'

[tool.mypy]
python_version = "3.11"
namespace_packages = true
explicit_package_bases = true
ignore_missing_imports = false

# Strictness
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true

# None/Optional
no_implicit_optional = true
strict_optional = true

# Warnings
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_return_any = true
warn_unreachable = true

# Output
show_error_codes = true
show_column_numbers = true
show_error_context = true
pretty = true

# Per-module options
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false

[[tool.mypy.overrides]]
module = "migrations.*"
ignore_errors = true

EOF

    if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then
        cat >> pyproject.toml << 'EOF'

[tool.mypy]
plugins = ["mypy_django_plugin.main"]

[tool.django-stubs]
django_settings_module = "config.settings"

EOF
    fi

    echo "✓ Created [tool.mypy] section in pyproject.toml"
fi
```

### 5. Create .mypy.ini in home directory (optional)

For user-specific defaults:

```bash
cat > ~/.mypy.ini << 'EOF'
[mypy]
# User-wide Mypy defaults
warn_unused_ignores = True
show_error_codes = True
pretty = True

EOF
```

### 6. Add to .gitignore

```bash
if [ -f ".gitignore" ]; then
    if ! grep -q ".mypy_cache" .gitignore; then
        echo "" >> .gitignore
        echo "# Mypy cache" >> .gitignore
        echo ".mypy_cache/" >> .gitignore
        echo "✓ Added .mypy_cache to .gitignore"
    fi
fi
```

### 7. Generate VS Code Settings

```bash
mkdir -p .vscode

if [ ! -f ".vscode/settings.json" ]; then
    cat > .vscode/settings.json << 'EOF'
{
  "python.linting.enabled": true,
  "python.linting.mypyEnabled": true,
  "python.linting.mypyArgs": [
    "--show-error-codes",
    "--show-column-numbers"
  ]
}
EOF
    echo "✓ Created .vscode/settings.json for Mypy"
else
    echo "⚠ .vscode/settings.json already exists"
    echo "  Add Mypy configuration manually if needed"
fi
```

### 8. Generate Pre-commit Hook

```bash
if [ -f ".pre-commit-config.yaml" ]; then
    # Check if Mypy already configured
    if ! grep -q "mirrors-mypy" .pre-commit-config.yaml; then
        cat >> .pre-commit-config.yaml << 'EOF'

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.8.0
    hooks:
      - id: mypy
        args: [--show-error-codes]
        additional_dependencies:
          - types-requests
          - types-PyYAML
EOF
        if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then
            cat >> .pre-commit-config.yaml << 'EOF'
          - django-stubs
          - mypy-django-plugin
EOF
        fi
        echo "✓ Added Mypy to .pre-commit-config.yaml"
    else
        echo "⚠ Mypy already in .pre-commit-config.yaml"
    fi
else
    # Create new pre-commit config
    cat > .pre-commit-config.yaml << 'EOF'
repos:
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.8.0
    hooks:
      - id: mypy
        args: [--show-error-codes]
        additional_dependencies:
          - types-requests
          - types-PyYAML
EOF
    if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then
        cat >> .pre-commit-config.yaml << 'EOF'
          - django-stubs
          - mypy-django-plugin
EOF
    fi
    echo "✓ Created .pre-commit-config.yaml with Mypy"
fi
```

### 9. Generate GitHub Actions Workflow

```bash
mkdir -p .github/workflows

cat > .github/workflows/type-check.yml << 'EOF'
name: Type Check

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  mypy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install mypy
EOF

if [ "$DJANGO_MODE" = true ] || [ "$HAS_DJANGO" = true ]; then
    cat >> .github/workflows/type-check.yml << 'EOF'
          pip install django-stubs mypy-django-plugin
EOF
fi

cat >> .github/workflows/type-check.yml << 'EOF'
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

      - name: Type check with Mypy
        run: mypy .

      - name: Upload Mypy report
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: mypy-report
          path: .mypy_cache/
EOF

echo "✓ Created .github/workflows/type-check.yml"
```

### 10. Generate Summary Report

```
Mypy Setup Complete!
====================

Configuration:
  • Config file:     mypy.ini
  • Mode:            Strict
  • Django plugin:   Enabled
  • Python version:  3.11

Files Created:
  ✓ mypy.ini
  ✓ .vscode/settings.json
  ✓ .pre-commit-config.yaml
  ✓ .github/workflows/type-check.yml

Next Steps:
  1. Review and adjust mypy.ini settings
  2. Update Django settings module path (if applicable)
  3. Run: /mypy-check to test configuration
  4. Install pre-commit: pre-commit install
  5. Add type hints to your code gradually

Gradual Adoption Strategy:
  1. Start with new files (keep disallow_untyped_defs = True)
  2. Add type hints to critical paths (services, models)
  3. Enable stricter checks per module:
     [mypy-myapp.services.*]
     disallow_untyped_defs = True
  4. Expand coverage over time

Resources:
  • Mypy docs: https://mypy.readthedocs.io/
  • Cheat sheet: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html
  • Django stubs: https://github.com/typeddjango/django-stubs

Run '/mypy-check' to verify your setup!
```

### 11. Interactive Setup (if no args)

If no arguments provided, ask user questions:

```
Mypy Setup Wizard
=================

1. Configuration format?
   [1] mypy.ini (recommended)
   [2] pyproject.toml

2. Strictness level?
   [1] Strict (recommended for new projects)
   [2] Gradual (for existing projects)

3. Project type?
   [1] Django
   [2] FastAPI
   [3] Generic Python

4. Install Mypy and plugins?
   [Y/n]

5. Setup IDE integration (VS Code)?
   [Y/n]

6. Add pre-commit hook?
   [Y/n]

7. Create GitHub Actions workflow?
   [Y/n]
```

---

## Examples

```bash
# Basic setup (interactive)
/mypy-setup

# Strict mode with mypy.ini
/mypy-setup --strict

# Django project with installation
/mypy-setup --django --install

# Use pyproject.toml format
/mypy-setup --format=toml

# Full setup for Django
/mypy-setup --strict --django --format=toml --install
```

## Configuration Templates

### Minimal (Gradual Adoption)

```ini
[mypy]
python_version = 3.11
warn_return_any = True
warn_unused_configs = True
show_error_codes = True

# Start here, gradually enable more
```

### Balanced (Recommended)

```ini
[mypy]
python_version = 3.11
disallow_untyped_defs = True
warn_return_any = True
warn_unused_configs = True
no_implicit_optional = True
show_error_codes = True

[mypy-tests.*]
disallow_untyped_defs = False
```

### Strict (New Projects)

```ini
[mypy]
python_version = 3.11
strict = True
show_error_codes = True
```

## Related Skills

| Skill | Purpose |
|-------|---------|
| `python-experts:python-mypy` | Mypy type checking patterns |
| `python-experts:python-style` | Python coding standards |

## Related Commands

| Command | Purpose |
|---------|---------|
| `/mypy-check` | Run type checking |
| `/python-experts:review-django-commands` | Review Django commands |

## Troubleshooting

### Django Settings Not Found

```bash
# Update in mypy.ini
[mypy.plugins.django-stubs]
django_settings_module = "your_project.settings"
```

### Import Errors

```bash
# Install missing type stubs
mypy --install-types
```

### Too Many Errors Initially

Start with:
```ini
[mypy]
ignore_missing_imports = True
check_untyped_defs = False
```

Then gradually remove these.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.