Cookiecutter PyPackage

July 28, 2026 ยท View on GitHub

PyPI version PyPI downloads

Cookiecutter template for a Python package with production-ready CI and automated PyPI publishing.

uvx cookiecutter-pypackage

What you get

Tooling

Tool
Package manageruvFast, handles venvs automatically
Task runnerjustjust qa formats, lints, type-checks, and tests
LintingruffFormat + lint in one tool
Type checkingtyAll rules enabled, watch mode with just type-check-watch
TestingpytestPython 3.12, 3.13, 3.14
CLI frameworkTyperEntry point + __main__.py included
DocsZensical + mkdocstringsAuto-deployed to GitHub Pages, API docs from docstrings

CI/CD (GitHub Actions, security-hardened)

WorkflowTriggerWhat happens
CIPush, PRsLint, type check, test across 3 Python versions
Publishv* tagBuild, Sigstore attestation, PyPI via Trusted Publishers (no tokens)
DocsPush to mainBuild and deploy to GitHub Pages
DependabotWeeklyPRs to update SHA-pinned actions

All actions pinned by SHA, minimal permissions, no persisted credentials.

Quickstart

Install uv, then:

uvx cookiecutter-pypackage

You'll be prompted for your package name, GitHub username, and a few other values (full list). Then push to GitHub and follow the tutorial to enable Pages and set up PyPI publishing.

Without uvx
uv venv
source .venv/bin/activate
uv pip install cookiecutter
cookiecutter gh:audreyfeldroy/cookiecutter-pypackage

Override template variables

Pass key=value arguments to prefill the interactive prompts. You can still review or change each value:

uvx cookiecutter-pypackage \
    full_name="Your Name" \
    github_username=yourhandle

For non-interactive automation, add --no-input before the overrides. Variables you don't pass use the defaults in cookiecutter.json:

uvx cookiecutter-pypackage --no-input \
    full_name="Your Name" \
    email="you@example.com"

List the available variables and their configured defaults without generating a project:

uvx cookiecutter-pypackage --list-variables

Quote values that contain spaces so the shell passes each assignment as one argument:

full_name="First Last"  # correct
full_name=First Last    # incorrect

See the template prompts for descriptions of all available variables.

Documentation

audreyfeldroy.github.io/cookiecutter-pypackage

Alternatives

This template is opinionated. If it doesn't fit:

Pull requests welcome if they're small, atomic, and improve the template.


Discord | MIT license