Metadata-Version: 2.4
Name: tpl-cli
Version: 0.1.0
Summary: A CLI that composes single-file Cookiecutter templates via Git
Author: tpl Maintainers
License: MIT
Project-URL: Homepage, https://github.com/your-org/tpl
Project-URL: Repository, https://github.com/your-org/tpl
Project-URL: Documentation, https://github.com/your-org/tpl#readme
Project-URL: Issues, https://github.com/your-org/tpl/issues
Keywords: cookiecutter,templates,cli
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: cookiecutter
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: pre-commit; extra == "dev"

# 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 pulls** – `tpl pull` grabs any tagged Cookiecutter repo and writes the requested entry file. Supports overrides via `--set key=value`.
- **Project composition** – `tpl 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](https://github.com/astral-sh/uv) and ensure Python 3.12 exists: `uv python install 3.12`.
2. Sync dependencies (grab the `dev` extras for tooling):

   ```bash
   uv sync --extra dev
   ```

3. Run commands through uv to pick up the managed `.venv`:

   ```bash
   uv run tpl --help
   uv run pytest
   ```

## Daily workflow

### Pull a single template

```bash
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

```bash
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`:

```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.

```bash
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:

```toml
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"
```

```bash
uv run tpl apply --config tpl.toml --set project_name=my-service
```

### Upgrade everything

```bash
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:

```bash
uv run pre-commit install
```

## Contributing

See [CONTRIBUTING.md](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.
