Starting a Python library is easy. Setting up everything around it--testing, documentation, CI, security checks, packaging, releases, and containers--often takes longer than writing the first version of the library itself.
Python Project Foundry generates an opinionated, production-ready repository for a Python package or library from an interactive questionnaire.
uvx python-project-foundry ./my/new/project
What Foundry generates
Foundry starts with a package skeleton and builds the rest of the repository around it:
Questionnaire
│
▼
Python package repository
├── Typed src/ package
├── Tests and examples
├── Documentation site
├── Development environment
├── Quality and security checks
├── GitHub Actions workflows
├── Container images
└── Release automation
The generated repository exposes the same commands to developers and CI.
Quickstart
The one-line invocation requires uv, Git, Make, Node.js, and npm.
Generate a repository:
uvx python-project-foundry ./orbit-tools
Foundry prompts for values such as:
- Project and package names
- Description and initial version
- Supported Python versions
- License
- GitHub owner and repository
- Documentation URL
- Maintainer name and email
- Coverage threshold
After generation:
cd orbit-tools
make check
On Linux and macOS, Foundry can also initialize Git, install dependencies, create the initial commit, and install Git hooks.
Without uv, use the bootstrap script:
curl -LsSf https://raw.githubusercontent.com/ryancswallace/python-project-foundry/main/ppf |
sh -s -- ./orbit-tools
Modern Python packaging defaults
Generated repositories use a src/ layout:
src/
└── orbit_tools/
├── __init__.py
├── _core.py
├── exceptions.py
└── py.typed
Each project includes:
- PEP 621 package metadata
- Hatchling builds
- A
py.typedmarker - Explicit Python version bounds
- Locked dependencies through uv
- Wheel and source-distribution builds
- Installation smoke tests
- Twine metadata validation
One interface for development
The generated Makefile provides a discoverable command surface:
make help
Common commands include:
| Goal | Command |
|---|---|
| Install dependencies | make install |
| Run tests | make test |
| Check formatting and lint | make lint |
| Check types | make typecheck |
| Build documentation | make docs |
| Run the standard suite | make check |
| Build distributions | make build |
| Test containers | make docker-check |
Local development and CI use the same commands, so contributors do not have to remember each underlying tool invocation.
Testing and quality controls
Each generated project wires together:
| Concern | Tools |
|---|---|
| Tests | Pytest, Hypothesis, pytest-cov |
| Linting and formatting | Ruff |
| Type checking | BasedPyright |
| Dependency declarations | deptry |
| Markdown | markdownlint |
| Spelling | CSpell |
| Workflows | actionlint, Zizmor |
| Automation matrix | Nox |
Test coverage enforcement is configurable during generation.
The Linux CI matrix tests every selected Python version from the minimum through the default. macOS and Windows test the default version.
Documentation included
Every repository includes a MkDocs Material site with:
- A project overview
- Development instructions
- Explanations and how-to pages
- Release runbooks
- Generated API reference
- Strict documentation builds
- Link checking
- A GitHub Pages deployment workflow
Preview it locally:
make serve-docs
The docs configuration uses the repository and package metadata supplied during generation.
Security and supply-chain checks
Security checks are present from the first commit:
- Bandit source scanning
- pip-audit dependency auditing
- detect-secrets
- GitHub dependency review
- CodeQL
- OpenSSF Scorecard
- Zizmor workflow analysis
- Trivy container scanning
- CycloneDX SBOM generation
- Artifact attestations
The defaults are intentionally broad. A new repository starts with source, dependency, workflow, container, and release-artifact checks already wired into CI.
Container support
Generated repositories include a multi-stage Dockerfile with separate runtime and test targets.
Base image
├── Runtime image
└── Test image
The generated workflows can:
- Build the runtime image
- Run package tests inside an image
- Smoke-test the runtime image
- Scan both images for critical vulnerabilities
- Publish images to GitHub Container Registry
- Generate build attestations
Run the complete local container suite with:
make docker-check
Open-source and proprietary licensing
Foundry can generate:
| Choice | Identifier |
|---|---|
| MIT License | MIT |
| BSD 3-Clause License | BSD-3-Clause |
| Apache License 2.0 | Apache-2.0 |
| Mozilla Public License 2.0 | MPL-2.0 |
| GNU GPL version 3 | GPL-3.0-only |
| Proprietary notice | LicenseRef-Proprietary |
The selected value is used consistently in the license file, package metadata, citation metadata, README, and container labels.
The proprietary option provides a general all-rights-reserved notice.
GitHub publishing
Generating files does not automatically create external resources.
When the repository is ready, preview publishing:
uvx python-project-foundry publish \
--visibility private \
--dry-run
Then publish it:
uvx python-project-foundry publish \
--visibility private
The publish command:
- Reads the configured GitHub destination
- Validates the local Git repository
- Creates the remote repository
- Pushes
main - Configures GitHub Pages
Visibility must be selected explicitly:
privatepublicinternal
Template updates
Generated repositories record their original Foundry template version and questionnaire answers.
Preview an update:
uvx --refresh python-project-foundry update --pretend
Apply it:
uvx --refresh python-project-foundry update
Foundry uses Copier’s update support to preserve project changes where possible. If the same content changed in both the project and template, conflicts are left for review.
After updating:
git diff
make check
Updates are pinned to the installed Foundry release rather than selecting the latest template version.
Automation-friendly generation
For unattended generation, skip the questionnaire:
uvx python-project-foundry ./orbit-tools --defaults
Useful options include:
| Option | Effect |
|---|---|
--defaults | Accept questionnaire defaults |
--pretend | Preview without writing |
--skip-tasks | Render files without setup tasks |
--overwrite | Replace existing destination files |
When to use Foundry
Python Project Foundry is useful when you want a package repository with mature engineering practices from its first commit.
Each generated repository includes:
- Consistent local and CI commands
- Typed Python packaging
- Cross-platform testing
- Documentation and Pages deployment
- Security and supply-chain checks
- Container workflows
- Release automation
- Explicit GitHub publishing
- Template updates
Foundry quickly creates strong repo scaffolding so you can focus on developing your Python application itself.