Container Unit Templates in Python — a deterministic framework for building container workloads
Project description
CUTIP
Container Unit Templates in Python — a deterministic framework for defining, validating, and orchestrating container environments using structured YAML artifacts and Python workflows.
CUTIP is not a replacement for docker-compose. It is designed for a different use case: environments where the startup sequence is imperative, not declarative.
| docker-compose | CUTIP | |
|---|---|---|
| Startup ordering | depends_on with condition polling |
Python loop — exec into container, branch on result |
| Post-start hooks | None native | startup(ctx) per unit — full container API |
| Pre-build file staging | None | pre_build(ctx) — generate config, copy deps before build |
| Config variables | .env flat substitution |
paths.yaml + secrets.yaml with required/generated sections + fail-fast validation |
| Validation | Runtime only | Static graph validation — no backend required |
| Orchestration logic | Shell scripts outside compose | First-class Python in workflow.py |
| Migration from compose | — | cutip from-compose — convert any compose file to a CUTIP workspace |
The Model
Container infrastructure is organized into four composable layers:
ImageCard ─┐
NetworkCard ─┘──▶ ContainerCard ──▶ Unit ──▶ Group ──▶ workflow.py
| Layer | What it represents |
|---|---|
| Card | One atomic container resource (image, network, or container configuration) |
| Unit | One running container instance — a ContainerCard reference |
| Group | A collection of Units + a Python workflow.py — the executable artifact |
| Workflow | A plain Python function main(ctx: CutipContext) — full control, no magic |
Every artifact is a versioned YAML file. Every ref is validated before any backend is contacted.
Install
pip install cutip
cutip --help
Contributing? Clone the repo and use
uv pip install -e .for an editable install — see the installation guide.
[!NOTE]
cutip init,cutip from-compose,cutip tree,cutip validate,cutip show, andcutip planrun without any container runtime installed. Onlycutip runrequires a container backend (Podman or Docker).
Quick Look
# cutip/cards/images/app.yaml
apiVersion: cutip/v1
kind: ImageCard
metadata:
name: app
spec:
source: build
context: resources/buildtime
dockerfile: resources/dockerfiles/app.dockerfile
tag: latest
# cutip/cards/containers/app.yaml
apiVersion: cutip/v1
kind: ContainerCard
metadata:
name: app
spec:
imageRef:
ref: images/app
networkRef:
ref: networks/dev
environment:
ENV: production
workdir: /app
# cutip/groups/dev/workflow.py
def main(ctx):
ctx.container("app").start()
cutip validate
cutip plan dev
cutip run dev
CLI
Workflow
| Command | Description |
|---|---|
cutip init [--path] |
Scaffold workspace directories and cutip.yaml |
cutip from-compose <file> [--output-dir] |
Convert a docker-compose.yaml into a CUTIP workspace |
cutip plan <group> [--path] |
Dry-run: print execution table, start nothing |
cutip run <group> [-b backend] [--local] [--path] |
Validate → connect → execute workflow |
Inspect
| Command | Description |
|---|---|
cutip tree [--path] |
Print discovered cards, units, and groups |
cutip validate [--path] |
Full schema + graph validation (no backend required) |
cutip show card <ref> |
Dump a resolved card as YAML |
cutip show unit <name> |
Show a unit's resolved card graph |
cutip show group <name> |
Show a group's units and workflow status |
cutip group ls / cutip unit ls / cutip card ls |
List workspace artifacts |
Configuration
| Command | Description |
|---|---|
cutip secrets set <key> <value> |
Set a secret in cutip/secrets.yaml |
cutip secrets list |
List secret keys (values masked) |
cutip secrets check |
Validate all {{ secrets.key }} refs are defined and non-empty |
cutip upgrade [--apply] |
Detect and apply workspace migrations for newer CUTIP versions |
AI & Issues
| Command | Description |
|---|---|
cutip issue create -t "title" |
Create a local issue YAML from template |
cutip issue list |
List local issues with status |
cutip issue push <slug> |
Push issue to GitHub via gh CLI |
cutip issue diagnose <slug> |
Run Claude diagnosis locally (requires ANTHROPIC_API_KEY) |
cutip issue fix <slug> |
Generate fix locally (requires ANTHROPIC_API_KEY) |
[!NOTE] AI commands require the optional
anthropicdependency:pip install cutip[ai]SetANTHROPIC_API_KEYin your environment. Forcutip issue push, rungh auth loginfirst.
cutip run uses Docker by default. Pass --backend podman (or set CUTIP_BACKEND=podman) to use Podman instead. Set project.backend in cutip.yaml to persist the choice. Pass --local for direct socket connection (CI / rootless setups).
paths.yaml + secrets.yaml
Workspace configuration is split into two files:
cutip/paths.yaml — filesystem paths (safe to sync):
required:
my_repo: "" # must be filled in — cutip fails fast if empty
generated:
data_dir: ".my-data" # cutip creates this directory automatically
cutip/secrets.yaml — sensitive values (never synced, always gitignored):
required:
ssh_private_key: "" # passwords, tokens, keys
db_password: ""
CUTIP validates all {{ paths.key }} and {{ secrets.key }} references in cards before any container backend is contacted — missing or empty required values surface as a clear error, not a runtime failure.
Documentation
Full documentation at joshuajerome.github.io/cutip
| Section | Contents |
|---|---|
| Getting Started | Installation, quickstart, workspace layout |
| Concepts | The 4-layer model, cards, units, groups, graph resolution |
| Reference | CLI flags, card schemas, workflow contract, exceptions |
| Guides | Podman/Docker setup, writing workflows, CI/CD |
License
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 cutip-0.1.13.tar.gz.
File metadata
- Download URL: cutip-0.1.13.tar.gz
- Upload date:
- Size: 224.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9973e929f9ee17334e61af07b3acb0b3adc786f6a2d0e68c98365330fa232352
|
|
| MD5 |
443a1b27a43b33a7671178014a77fb33
|
|
| BLAKE2b-256 |
64e4c246285ffa87d09391bebdff073df0869affac4380c26a9f5bd2bbe1d49d
|
File details
Details for the file cutip-0.1.13-py3-none-any.whl.
File metadata
- Download URL: cutip-0.1.13-py3-none-any.whl
- Upload date:
- Size: 91.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2faf3f185c4a91bece0b9094a01515099b43de8afcbc92d594aa45e44f77397a
|
|
| MD5 |
919d11049c7a86091be8082f1c5ced52
|
|
| BLAKE2b-256 |
bfb3ef0ae3785d24a720d7c4bfcaa32def8d297156c0ca588bf15a175b7eb85b
|