template-python bakes a full Python toolchain into every new library
My template for new Python libraries.
At a glance
- What is it?
- jacebrowning/template-python is a cookiecutter template that generates a Python library with Poetry packaging, a Makefile of common tasks, and preconfigured CI, coverage and analysis services. It suits library authors who want the tooling decisions made for them, and it suits nobody who wants a minimal starting point.
- Who is it for?
- Adopt template-python if you are starting a Python library and would rather inherit a settled toolchain, CI setup and release flow than design one, and if your team accepts asdf, Poetry and the sibling templates as prerequisites. Skip it for a small script, for a project that needs a different packaging model, or for a team that treats black, mypy and pylint as opinions rather than defaults.
- Can I use it commercially?
- Yes. Unlicense is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 25 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The template is one cookiecutter.json and one templated directory
The layout explains how little is hard coded. At the top level of the repository there is a cookiecutter.json file, which holds the questions cookiecutter asks, and a directory whose name is itself a template expression, {{cookiecutter.project_name}}/, holding the files that get copied into your new project. Everything else at the root, the Makefile, pyproject.toml, poetry.lock and the CI configuration under .github/, describes how the template itself is developed and how it renders its own output. The project description calls it a template for new Python libraries, and the README says it is a cookiecutter template for a typical Python library following modern packaging conventions. That word typical is doing real work. This is an opinionated starting point rather than a neutral scaffold, and the opinion is that a library should arrive with formatting, static analysis, type checking, docstring rules, tests and documentation already wired together.
The Makefile maps every task to a named tool
The value of the template is concentrated in its task list. The README enumerates what the Makefile automates: installing dependencies with poetry, automatic formatting with isort and black, static analysis with pylint, type checking with mypy, docstring styling with pydocstyle, running tests with pytest, building documentation with mkdocs, and publishing to PyPI using poetry. Each of those is a Makefile target, so a contributor can run tasks like make format instead of a list of tool invocations to remember. The generated project's own CONTRIBUTING.md is linked as the place where those development tasks are documented, which means the template ships documentation for its own conventions rather than leaving them in the README of the template. The template's own root Makefile also reveals what the generated project will look like, since it drives a cookiecutter run of the template into a directory called TemplateDemo as part of its build target.
Three commands take you from nothing to a generated project
The README gives the usage path in three steps. First you install cookiecutter and generate a project from the GitHub hosted template.
$ pip install cookiecutter
$ cookiecutter gh:jacebrowning/template-python -fCookiecutter then asks for basic information such as your name, the project name and the Python package name, and generates a base Python project. The -f flag in that command line is what the README shows, so it is worth keeping in mind when you script the generation. Once the project exists you move into it and run the formatter, which updates files based on the names you chose.
$ cd <github_repo>
$ make formatThe final step in the README workflow is to commit all files generated by the template. The project then stays current through an update tool that is generated inside each project.
$ bin/updateThat last command is the part that distinguishes this from a one time scaffold. The generated project can pull in later changes to the template instead of drifting.
The template pins Python 3.11 and a fixed toolchain in pyproject.toml
The root pyproject.toml shows the dependency policy the template assumes, and it is narrow. The project name is template-python with version 1.0 and the description A template for new Python libraries, and the only runtime dependency declared is python = "^3.11". Alongside it sit cookiecutter = "^2.6.0", black = "^23.1", sniffer = "*", and MacFSEvents pinned to the darwin platform.
[tool.poetry.dependencies]
python = "^3.11"
cookiecutter = "^2.6.0"
black = "^23.1"
sniffer = "*"
MacFSEvents = { version = "*", platform = "darwin" }Two things stand out. The Python floor is 3.11, so a team still on 3.10 cannot use the template unchanged. And the tool versions are dated rather than floating: black is pinned to the 23 series, which is a specific generation of formatting behaviour that a project will inherit and then have to unpick. The presence of a darwin only dependency means the template itself is developed on a Mac, though the tool version check file .verchew.ini and the .tool-versions file point to a version manager based approach rather than a hard coded interpreter path.
Bootstrap assumes asdf and Poetry are already on the machine
The Makefile exposes the real prerequisites, and they are not trivial. The bootstrap target runs asdf plugin add python or updates it, adds the poetry plugin or updates it, and then runs asdf install. The install target depends on a local .venv directory and configures Poetry with virtualenvs.in-project true, so the virtual environment lives inside the project rather than in a global cache. The dependency install differs depending on environment: with CI defined it runs poetry install --no-root --only=main, and without it runs poetry install --no-root. There is also a doctor target that runs {{cookiecutter.project_name}}/bin/verchew, which is a check that the tool versions on the machine match what the project expects. Taken together, this is a template that assumes a developer workstation already has asdf, Poetry and Python managed, and it will fail early and loudly if they do not.
Rendering the template inside its own build is unusual and fragile
The root Makefile does something most templates avoid: it builds the template by generating a project from itself. The build target depends on the source files listed in SOURCE_FILES, which include the Makefile, cookiecutter.json and the templated directory tree. It then prints the cookiecutter configuration, runs a cookiecutter pass with --no-input and --overwrite-if-exists into the TemplateDemo directory, and locks the result with poetry lock. Outside CI it also creates a .git directory inside the generated project and writes a remote origin pointing at https://github.com/jacebrowning/template-python-demo into that .git/config. In other words, the generated sample is wired to a separate demo repository. This is a reasonable way to keep the template honest, since the CI build fails if the template cannot render, but it also means the template's own test surface is one boolean: does it render without errors. There is no suite that checks the generated project behaves correctly beyond that.
Siblings for applications, and a template that ages with its dependencies
The README is direct about scope. If you are looking for a Python application template rather than a library template, it points to two sibling projects, template-django and template-flask, and links to a post on setup.py versus requirements files. That framing tells you this template is deliberately narrow, and it also tells you the author maintains a family of templates with a common shape. The reference implementations are listed as well: minilog, theovoss/Chess, sprout42/StarStruct, MichiganLabs/flask-gcm and flask-restful are named as sample projects based on the template. On maintenance, the last push was on 2026-09-28 and the repository has no GitHub releases, so there is no version history to inspect and no changelog to read. The declared dependencies, in particular black at ^23.1, mean a project generated from this template starts on a specific point in the formatter's history and will need a deliberate upgrade pass rather than picking up improvements automatically.
Editorial conclusion
Adopt template-python if you are starting a Python library and would rather inherit a settled toolchain, CI setup and release flow than design one, and if your team accepts asdf, Poetry and the sibling templates as prerequisites. Skip it for a small script, for a project that needs a different packaging model, or for a team that treats black, mypy and pylint as opinions rather than defaults. Verify first by running cookiecutter gh:jacebrowning/template-python -f in a scratch directory, reading the generated CONTRIBUTING.md for the task list, and checking pyproject.toml in the template, which pins python to ^3.11, before you commit a generated project to a repository.
Frequently asked questions
How do I generate a new Python library project from template-python?
Install cookiecutter and run cookiecutter gh:jacebrowning/template-python -f, then answer the prompts for your name, project name and Python package name. The README instructs you to run make format afterwards in the generated directory so files are updated based on the names you chose.
Which tools does the generated Makefile wire up?
The README lists installing dependencies with poetry, formatting with isort and black, static analysis with pylint, type checking with mypy, docstring styling with pydocstyle, running tests with pytest, building documentation with mkdocs, and publishing to PyPI using poetry. Each is exposed as a Makefile target.
What does bin/update do in a project made from template-python?
The README describes it as the update tool, which is generated inside each project, and it is run with bin/update. It is the mechanism that lets a generated project pull in later changes to the template rather than drifting from it.
What are the prerequisites for working with template-python?
The Makefile bootstrap target adds the python and poetry plugins to asdf and runs asdf install, and the install target configures Poetry with virtualenvs.in-project true. The doctor target runs bin/verchew to check the expected tool versions, so asdf, Poetry and a managed Python are assumed.
Is template-python suitable for a Python web application?
The README says this template is for a typical Python library, and it points readers looking for an application template to the sibling projects template-django and template-flask instead.
What licence is template-python released under?
The repository is licensed under the Unlicense, with the licence text stored in a file named LICENSE.txt at the top level of the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jacebrowning-template-python)Was this useful?