A CLI that composes single-file Cookiecutter templates via Git
Project description
tpl – Template Puller CLI
tpl treats single-file Cookiecutter templates like versioned building blocks. Instead of copy/pasting snippets or maintaining giant boilerplate repos, point tpl at any Git tag (GitHub, Bitbucket, or a local directory), drop the rendered file into your project, and record the provenance in .tpl-lock.toml. When a new tag ships, tpl upgrade tells you exactly what changed and keeps your tweaks safe.
Why tpl?
- Composable building blocks – pull one template at a time or describe an entire starter kit in
tpl.toml. Every block is still a normal Cookiecutter repo, with tags for versioning and hooks for customization. - Deterministic upgrades – tpl stores the source URL, tag, entry file, checksum, and context for every managed file. Upgrades re-render using the same context, detect local edits, and produce
.tpl-new/.tpl.diffartifacts (or rungit merge-filewhen--mergeis set). - Works offline – reference
local:/path/to/repo@tagentries to test unreleased templates or run integration tests without hitting the network. - Zero vendor lock-in – tpl orchestrates Git + Cookiecutter. Templates live wherever you keep them; tpl just fetches, renders, and tracks provenance.
# Pull a single template
uv run tpl pull gh:you/tpl-logging@v0.3.0 --as infra/logging.yaml --set project_slug=my-app
# Compose an entire starter kit
uv run tpl compose gh:you/python-service@v1.2.0 --set project_name=my-app
# Reapply a local tpl.toml (hierarchical blocks + shared context)
uv run tpl apply --config tpl.toml --force
# Detect drift / upgrade safely
uv run tpl status
uv run tpl upgrade --merge
Feature highlights
- Single-file template pulls –
tpl pullgrabs any tagged Cookiecutter repo and writes the requested entry file. Supports overrides via--set key=value. - Project composition –
tpl compose gh:user/repo@tagruns every block defined intpl.toml, sharing context variables across blocks and supporting nestedkind = "project"entries. - Local configs – keep
tpl.tomlinside your repo and runtpl apply --config tpl.tomlso teammates can rehydrate the same files without remembering commands. - Hierarchical layering – include other project templates (Docker layer, CI layer, etc.) to build multi-stage starter kits.
- Upgrade safety – checksum tracking, optional three-way merge (
--merge), and consistent conflict artifacts. - Private repo support – authenticate with GitHub or Bitbucket tokens; tpl passes creds to Git via
GIT_ASKPASSso secrets never hit disk.
Quick start (uv)
-
Install uv and ensure Python 3.12 exists:
uv python install 3.12. -
Sync dependencies (grab the
devextras for tooling):uv sync --extra dev
-
Run commands through uv to pick up the managed
.venv:uv run tpl --help uv run pytest
Daily workflow
Pull a single template
uv run tpl pull gh:you/template-repo@v0.1.0 \
--as src/logging.yaml \
--set project_slug=my_app
tpl clones the tagged repo into ~/.tpl-cache, runs Cookiecutter with no_input=True, writes the configured entry file, and records metadata inside .tpl-lock.toml.
Check managed files
uv run tpl status
Outputs each tracked file plus its checksum status (OK, MODIFIED, MISSING).
Compose a remote project template
Project templates ship a tpl.toml:
name = "python-service"
version = "0.2.0"
[context]
project_name = "my-service"
[[blocks]]
source = "gh:you/logging-block@v0.1.0"
path = "infra/logging.yaml"
[[blocks]]
kind = "project"
source = "gh:you/docker-layer@v0.3.0"
kind = "project" layers another template, letting you stack base scaffolds, Docker bits, CI pipelines, etc.
uv run tpl compose gh:you/python-service@v0.2.0 --set project_name=my-service
Apply a local tpl.toml
Keep the same schema in your own repo to define reusable building blocks:
name = "demo"
version = "0.3.0"
[context]
project_name = "demo"
[[blocks]]
source = "gh:you/logging-block@v0.1.0"
path = "infra/logging.yaml"
[[blocks]]
source = "bb:team/docker-layer@v0.4.0"
path = "infra/docker-compose.yaml"
[[blocks]]
source = "local:../templates/tpl-cache@v0.1.0"
path = "scripts/bootstrap.py"
uv run tpl apply --config tpl.toml --set project_name=my-service
Upgrade everything
uv run tpl upgrade --merge
If a file’s checksum changed, tpl writes <file>.tpl-new and <file>.tpl.diff. With --merge, tpl attempts a Git-style three-way merge before falling back to artifacts. Target a single file with uv run tpl upgrade path/to/file --to v0.3.0.
Authentication
- GitHub – set
TPL_GITHUB_TOKEN(orGITHUB_TOKEN). tpl authenticates asx-access-token. - Bitbucket – set
TPL_BITBUCKET_USERNAMEandTPL_BITBUCKET_APP_PASSWORD(app password).
Credentials feed Git via GIT_ASKPASS, so secrets never appear in lockfiles or logs.
Automation & development
| Command | Description |
|---|---|
just fmt |
Run ruff format. |
just lint / just lint-fix |
Run ruff check (optionally with --fix). |
just typecheck |
Run mypy tpl. |
just test |
Run pytest (unit + integration). |
just check |
Run lint, typecheck, and tests sequentially. |
just precommit |
Run the full pre-commit stack. |
Install hooks once per machine:
uv run pre-commit install
Contributing
See CONTRIBUTING.md for the full workflow (uv setup, testing expectations, release process). CI runs Ruff, mypy, pre-commit, and pytest on every PR, and tagged commits on main auto-publish to PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tpl_cli-0.1.0.tar.gz.
File metadata
- Download URL: tpl_cli-0.1.0.tar.gz
- Upload date:
- Size: 18.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a14678668973480a234e021a0767c9a45ed6f6efb44deea79d3042ceb319eeb
|
|
| MD5 |
9f36cadc7bcce6a725854be94ab677a9
|
|
| BLAKE2b-256 |
4213fcd3a35d4e94aab2d354fb7c9cdc04429c1f1f655de1b2216eca6d714dfc
|
Provenance
The following attestation bundles were made for tpl_cli-0.1.0.tar.gz:
Publisher:
release.yml on wdonofrio/tpl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tpl_cli-0.1.0.tar.gz -
Subject digest:
2a14678668973480a234e021a0767c9a45ed6f6efb44deea79d3042ceb319eeb - Sigstore transparency entry: 709693353
- Sigstore integration time:
-
Permalink:
wdonofrio/tpl@1e70fdd5b971b75c1dd364eac2b4a513fe076cc4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/wdonofrio
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1e70fdd5b971b75c1dd364eac2b4a513fe076cc4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tpl_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tpl_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f5706e2522cabda95e8b7c3c45c99b6d2eedcd32755e7068ec821cdb7996e7b
|
|
| MD5 |
8a5d0c8e2572c7b7d8ffab9d53c59c74
|
|
| BLAKE2b-256 |
be56c8e51bc79f33bde234692030f7cf1578caca7cd8a9d4fe34b13129edd369
|
Provenance
The following attestation bundles were made for tpl_cli-0.1.0-py3-none-any.whl:
Publisher:
release.yml on wdonofrio/tpl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tpl_cli-0.1.0-py3-none-any.whl -
Subject digest:
3f5706e2522cabda95e8b7c3c45c99b6d2eedcd32755e7068ec821cdb7996e7b - Sigstore transparency entry: 709693355
- Sigstore integration time:
-
Permalink:
wdonofrio/tpl@1e70fdd5b971b75c1dd364eac2b4a513fe076cc4 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/wdonofrio
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1e70fdd5b971b75c1dd364eac2b4a513fe076cc4 -
Trigger Event:
push
-
Statement type: