| name | python-project |
| description | Set up a modern Python project with uv, pyproject.toml, and ruff. Use when creating a new Python project, package, or CLI tool. |
Python Project Setup
Modern Python project setup using uv package manager and pyproject.toml.
Creating a New Project
- Create project directory and initialize git:
mkdir myproject && cd myproject
git init
-
Copy pyproject.toml and edit:
- Change
name to your project name
- Update
description
- Add dependencies to
dependencies list
- Update
[project.scripts] for CLI entry point
-
Copy gitignore to .gitignore
-
Copy AGENTS.md to project root (AI agent instructions)
-
Create package structure:
mkdir myproject
touch myproject/__init__.py
- Initialize uv and install:
uv sync
Project Structure
myproject/
├── myproject/
│ ├── __init__.py
│ ├── __main__.py # For `python -m myproject`
│ └── cli.py # CLI entry point
├── pyproject.toml
├── .gitignore
├── AGENTS.md # AI agent instructions
└── uv.lock # Generated by uv
Entry Points
CLI script (installed as command)
[project.scripts]
myproject = "myproject.cli:main"
main.py (for python -m)
from myproject.cli import main
if __name__ == "__main__":
main()
Code Quality
Format and lint with ruff:
ruff format .
ruff check . --fix
Type Annotations
Required for all new code:
def greet(name: str) -> None:
print(f"Hello, {name}")
def add(a: int, b: int) -> int:
return a + b
Use Python 3.11+ built-in generics: list[str], dict[str, int], not List, Dict.
Structured Data
Use TypedDict for dictionary shapes (e.g., JSON, API responses):
from typing import TypedDict
class Ticket(TypedDict):
key: str
summary: str
status: str
assignee: str | None
Use dataclass for objects with behavior or defaults:
from dataclasses import dataclass
@dataclass
class Config:
site: str
email: str
timeout: int = 30
Common Commands
uv sync
uv add requests
uv run pytest
uv build
GitHub Actions: Publish to PyPI
Setup Steps
-
Copy publish.yml to .github/workflows/publish.yml
-
Configure PyPI Trusted Publisher (no API tokens needed):
-
Create GitHub environment:
- Go to repo Settings → Environments
- Create environment named
pypi
-
Release workflow:
- Create a GitHub release with tag like
v0.1.0
- Action automatically extracts version from tag and publishes
Publishing a Release
Create a GitHub release using gh release create:
gh release create v0.1.0 --title "v0.1.0" --notes "Release notes here"
Or use --generate-notes to auto-generate from commits:
gh release create v0.1.0 --generate-notes
GitHub Actions will automatically update the version in pyproject.toml and publish to PyPI.
Do NOT manually edit the version in pyproject.toml - it is managed by GitHub Actions.