| name | modern-python-projects |
| description | Initialize state-of-the-art greenfield Python projects with current stable Python, uv, uv_build, Ruff, ty, pytest, a src layout, locked dependencies, and CI. Use when creating a new Python library, packaged application, CLI, service, worker, or standalone script. |
Modern Python Projects
Create new Python projects with one opinionated, current toolchain and minimal structure.
Standard stack
- Python: current stable release
- Project, Python, environment, dependencies, lockfile, execution, and build:
uv
- Metadata and tool configuration:
pyproject.toml
- Build backend for packages:
uv_build, generated by current uv init
- Package layout:
src/<import_name>/
- Formatting and linting: Ruff
- Type checking:
ty
- Tests: pytest
- CI: locked sync followed by the same Ruff,
ty, pytest, and build commands used locally
Read references/tooling.md for the baseline rationale.
Choose the project shape
| Shape | Use when | Command |
|---|
| Script | One small automation file | uv init --script <file.py> |
| Library | Code imported by other projects | uv init --lib --python <version> <path> |
| Packaged application | CLI, API, service, worker, daemon, or substantial internal app | uv init --app --package --python <version> <path> |
Use a package for all projects larger than one standalone script. Do not create a workspace unless the request explicitly requires multiple independently packaged projects.
Initialization procedure
-
Resolve names and Python
- Determine the distribution name, import name, destination path, and project shape.
- Use the current stable Python release available through
uv.
- Distribution names may contain hyphens. Import names use underscores and must be valid Python identifiers.
- Run
uv init --help before initialization so commands match the installed stable uv.
-
Generate the project
- Run exactly one initialization command from the table above.
- Keep the generated
uv_build configuration.
- Inspect the generated
.python-version, requires-python, source package, entry point, and README.
- Replace all placeholder metadata and README text.
-
Install the development toolchain
uv add --dev ruff ty pytest
Add runtime dependencies only through:
uv add <dependency>
-
Create the minimum source shape
- Keep package code under
src/<import_name>/.
- Put tests under
tests/.
- Add one meaningful public-behavior or interface smoke test immediately.
- For a CLI, declare
[project.scripts] and keep reusable logic separate from argument parsing.
- For a service, expose an importable application or application factory.
- Start with cohesive modules. Do not pre-create architectural layers or generic
utils buckets.
-
Configure quality gates
- Add the Ruff and pytest baseline from references/greenfield.md.
- Let
ty infer the project from pyproject.toml; add configuration only when the project develops a concrete need.
- Keep every gate executable through
uv run.
-
Document the project
- README: purpose, setup, development checks, run/use example, and build command.
- Do not add publishing, deployment, documentation-site, or release machinery unless requested.
-
Add CI
- Use the repository’s CI platform.
- Install current stable
uv through the platform’s maintained integration.
- Sync from the committed lockfile.
- Run the exact local checks below.
-
Verify the complete project
uv lock --check
uv sync --locked
uv run ruff check .
uv run ruff format --check .
uv run ty check
uv run pytest
uv build
Then test the shipped interface:
- script: representative execution
- library: import and call one public API
- CLI: top-level
--help and one representative command
- service: import/create the app and exercise startup or a health path
- worker: process one deterministic sample
Required repository shape
For a library or packaged application:
project/
├── .python-version
├── pyproject.toml
├── README.md
├── uv.lock
├── src/
│ └── import_name/
│ └── __init__.py
└── tests/
└── test_smoke.py
Add py.typed for a typed library. Add files only when the project needs them.
Rules
- Use only
uv; do not add Poetry, PDM, pip-tools, virtualenv wrappers, or handwritten requirements files.
- Use
uv_build; do not replace the generated backend.
- Use Ruff for both formatting and linting; do not stack Black, isort, Flake8, or pyupgrade.
- Use
ty; do not add another type checker.
- Use pytest; do not add test plugins without a concrete test requirement.
- Commit
uv.lock.
- Keep configuration in
pyproject.toml wherever supported.
- Do not add a task runner for commands already expressed clearly with
uv run.
- Do not add hooks, coverage thresholds, architecture tests, security scanners, docs generators, or release automation by default.
- Generated defaults beat copied boilerplate and hardcoded dependency versions.
Report
State:
- selected project shape, names, and Python version
- generated paths
- runtime dependencies
- exact verification and smoke-test results
- anything requested but intentionally not added