Skip to main content

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.diff artifacts (or run git merge-file when --merge is set).
  • Works offline – reference local:/path/to/repo@tag entries 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 pullstpl pull grabs any tagged Cookiecutter repo and writes the requested entry file. Supports overrides via --set key=value.
  • Project compositiontpl compose gh:user/repo@tag runs every block defined in tpl.toml, sharing context variables across blocks and supporting nested kind = "project" entries.
  • Local configs – keep tpl.toml inside your repo and run tpl apply --config tpl.toml so 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_ASKPASS so secrets never hit disk.

Quick start (uv)

  1. Install uv and ensure Python 3.12 exists: uv python install 3.12.

  2. Sync dependencies (grab the dev extras for tooling):

    uv sync --extra dev
    
  3. 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 (or GITHUB_TOKEN). tpl authenticates as x-access-token.
  • Bitbucket – set TPL_BITBUCKET_USERNAME and TPL_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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tpl_cli-0.1.0.tar.gz (18.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tpl_cli-0.1.0-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

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

Hashes for tpl_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2a14678668973480a234e021a0767c9a45ed6f6efb44deea79d3042ceb319eeb
MD5 9f36cadc7bcce6a725854be94ab677a9
BLAKE2b-256 4213fcd3a35d4e94aab2d354fb7c9cdc04429c1f1f655de1b2216eca6d714dfc

See more details on using hashes here.

Provenance

The following attestation bundles were made for tpl_cli-0.1.0.tar.gz:

Publisher: release.yml on wdonofrio/tpl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for tpl_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3f5706e2522cabda95e8b7c3c45c99b6d2eedcd32755e7068ec821cdb7996e7b
MD5 8a5d0c8e2572c7b7d8ffab9d53c59c74
BLAKE2b-256 be56c8e51bc79f33bde234692030f7cf1578caca7cd8a9d4fe34b13129edd369

See more details on using hashes here.

Provenance

The following attestation bundles were made for tpl_cli-0.1.0-py3-none-any.whl:

Publisher: release.yml on wdonofrio/tpl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page